Подключение внешнего монитора к ноутбуку с двумя видеокартами в Linux

Недавно сделал загрузочную флешку с ArchLinux. Система очень понравилась: компактная, занимает мало памяти, быстро загружается (12 секунд до консоли с флешки и 15 до GUI), определяет почти все "железо" без дополнительных действий. Решил использовать на ноутбуке, но тут возникла сложность: большую часть времени он у меня находится под столом, а изображение выводится на внешний монитор. Linux же выдавал изображение только на панель самого ноутбука. Кроме того, на аккумуляторах компьютер работал гораздо меньше, чем обычно. Я стал разбираться, что с этим делать.


Ноутбук у меня с технологией Optimus и содержит две видеокарты: встроенную в чипсет Intel и более мощную NVidia. Также есть индикатор, который показывал, что используется карта NVidia, что и было основной причиной ускоренного расхода батареи. Начал искать, как переключиться на встроенную. Поискав в Интернете, выяснил, что переключение видеокарт происходит через файл sys/kernel/debug/vgaswitcheroo/switcher (и работает только при использовании драйвера nouveau, а не пропиертарного от nvidia). Этот файл находится в debugfs, которую сначала надо смонтировать, после чего можно будет узнать текущее состояние видеокарт:

mount -t debugfs none /sys/kernel/debug cat /sys/kernel/debug/vgaswitcheroo/switcher

Вывод будет примерно следующим:


0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0

IGD — это встроенная видеокарта, а DIS — дискретная (т.е. карта NVidia с отдельной видеопамятью). Активная карта помечена знаком +, а Pwr означает, что карта включена. В данном случае использовалась встроенная карточка, но включены были обе.
Для выключения неиспользуемой в данный момент карты в этот файл нужно было записать команду OFF, а для переключения на другую карточку — ее идентификатор (т.е. DIS — переключение на дискретную, IGD — на встроенную). Самый простой вариант это сделать — с помощью команды cat:


cat OFF > /sys/kernel/debug/vgaswitcheroo/switcher # отключаем видеокарту NVidia cat DIS > /sys/kernel/debug/vgaswitcheroo/switcher # включаем карту NVidia и делаем ее активной

Примечание: через sudo эта команда не сработает, так как перенаправление вывода выполнится от имени текущего пользователя, а не root, нужно входить под логином root или пользоваться su.

К моему большому удивлению, когда я сделал активной дискретную видеокарту, вывод сразу же переключился на внешний монитор, подключенный через HDMI. Обрадованный этим обстоятельством, переключился обратно, вынул HDMI-кабель и попытался переключиться еще раз, ожидая, что теперь дискретная видеокарта, не обнаружив кабеля, выведет изображение на встроенную панель. Но это оказалось не так: панель отключилась. Стал разбираться в чем дело и с помощью утилиты xrandr выяснил, что внешняя видеокарта встроенную панель попросту не видит, а обнаруживает только HDMI и VGA-порты. А внутренняя наоборот, не видит HDMI, но видит VGA и панель.

В целом меня такая ситуация устраивала. Оставалось только автоматизировать процесс переключения, а для этого нужно было выяснить, как программно определять, подключено ли что-то к HDMI-порту. После долгих поисков выяснилось, что информацию обо всех имеющиеся видеовыходах можно получить через /sys/class/drm. В частности, в файле /sys/class/drm/card1-HDMI-A-1/status можно было узнать, подключено ли что-то к этому выходу или нет.

Дальше оставалось только написать достаточно простой скрипт, который проверял наличие двух видеокарт (по все тому же /sys/class/drm), проверял содержимое /sys/class/drm/card1-HDMI-A-1/status, и в случае, если оно равно connected, делал бы переключение на дискретную видеокарту и выключал встроенную панель с помощью vbetool (не самый лучший вариант, но других я, увы, не нашел), а в противном случае — отключал дискретную карту в целях энергосбережения. При тестировании выявилось, что иногда встроенная карта определяется как card0, а иногда как card1, поэтому пришлось добавить дополнительную проверку для обеих ситуаций. Этот скрипт я поместил в /etc/rc.d/hdmi и прописал в DAEMONS в /etc/rc.conf. Далее оставалось только вернуть ноутбук под стол и смотреть, как сам собой включается внешний экран при загрузке!

Полную версию скрипта прикладываю на случай, если у кого окажется аналогичная ситуация.

Прикрепленные файлы: