EDID override
Понадобилось использовать кабель подлиннее для монитора, но внезапно оказалось что через него не пролезает i2c, хотя с картинкой всё ок. Сначала я хотел просто написать modeline в конфиг xorg, но консоль в разрешении 640х480 выглядит не очень. Проблема решается оверрайдом EDID.
Идея в конечном итоге довольно простая: подключить монитор нормальным кабелем, сдампить EDID, подсунуть его ядру. Технически можно было бы написать EDID руками, но зачем.
Итак, ядро делает бинарники доступными по пути /sys/class/drm/*/edid
.
Конкретно в моём случае /sys/class/drm/card0-DP-1/edid
. Порт можно выяснить
глянув на вывод xrandr
(но соответствие не один к одному, скажем в xrandr
у
меня этот порт называется DP1
).
Сохраним сразу в /lib/firmware/edid/
(потому что, забегая вперёд, ядро его
будет там искать):
$ cat /sys/class/drm/card0-DP-1/edid > /lib/firmware/edid/my-monitor-edid.bin
название файла произвольное.
Неплохо ещё проверить что сдампили что-то вменяемое: для этого можно воспользоваться утилитой parse-edid
:
$ parse-edid < /lib/firmware/edid/my-monitor-edid.bin
Checksum Correct
Section "Monitor"
...
EndSection
Обращаю внимание, что parse-edid
читает только с stdin, передать имя файла
аргументом не получится.
Теперь можно скормить этот файл ядру. Для этого у нас есть два варианта:
После загрузки можно записать его в
/sys/kernel/debug/dri/<card>/<port>/edid_override
, где<card>
номер карты (у меня0
), а<port>
название порта в ядре (у меняDP-1
). Это, естественно, будет работать до первой перезагрузки, но для быстрого теста вполне вариант.При загрузке указать парамер ядра
drm.edid_firmware=<port>:edid/my-monitor-edid.bin
, где<port>
это название порта в ядре (у меняDP-1
). Чтобы это работало нужно соблюсти два условия. Во-первых, файл должен существовать и находиться в/lib/firmware
, а если используется initrd, то файл должен быть в нём. Во-вторых, ядро должно быть собрано с параметромCONFIG_DRM_LOAD_EDID_FIRMWARE=y
. Параметр этот, надо отметить, у меня по умолчанию установлен не был.
У меня загрузчик grub, поэтому я дописываю
drm.edid_firmware=DP-1:edid/my-monitor-edid.bin
в конец
GRUB_CMDLINE_LINUX_DEFAULT
(или GRUB_CMDLINE_LINUX
) в /etc/defaults/grub
,
делаю обычный ритуал с grub-mkconfig
и собственно всё, остаётся
перезагрузиться.
Initrd у меня собирается dracut-ом, который автоматом включает содержимое
/lib/firmware
. Как дела обстоят с другими системами не берусь утверждать, но
подозреваю что аналогично. Поскольку мне всё равно пришлось пересобирать ядро чтобы включить CONFIG_DRM_LOAD_EDID_FIRMWARE
, задоно и initrd пересобрал.
Заметка больше для себя, но вдруг кому пригодится.
P.S. Если “хорошего” EDID взять негде, придётся собирать руками. Для этого есть
https://sourceforge.net/projects/wxedid/, или, как вариант, более старый
https://github.com/akatrevorjay/edid-generator. Последний по идее генерирует
edid из modeline, который в свою очередь можно сгенерировать используя cvt
.