> Martin Polden

Raspberry Pi and no video signal

Over the past week I've been setting up a second home office. This required another monitor, so I decided to re-use the one I had been using for my home dashboard. However, as I have grown very used to the information displayed by jarvis, I had to find another monitor for that purpose.

Like most geeks I have piles of unused computer parts and accessories (my SO never misses a chance to make fun of my ever-growing pile of cables), and among it I found a 20" monitor - an ancient Dell 2007WFP.

My dashboard runs on a Raspberry Pi 3B. I've used this monitor for the same purpose in the past, but this time I encountered a strange display issue. I connected the monitor using a HDMI-DVI cable and then booted the Raspberry Pi. The monitor turned on and the kernel boot log was printed, as expected.

However, immediately after booting completed, the monitor went to sleep. After fiddling with a couple of xset commands to disable blanking, I still couldn't make the monitor turn on after the X server was started.

Initial debugging

Searching the web for "raspberry pi no hdmi signal" yielded many similar problems, but most of them revolved around having no video signal at all. In my case I had a video signal until the kernel completed its boot process. The Raspberry Pi has countless options for configuring video output, so I tried a bunch of those, including hdmi_force_hotplug=1, hdmi_safe=1 and config_hdmi_boost=6, but none of them helped.

Then I discovered that Raspbian now has two different video drivers, vc4-fkms-v3d - a legacy driver, and its replacement: vc4-kms-v3d. I'm running standard Debian on my Raspberry Pi, but I still have to use the same non-free firmware as the Raspberry Pi OS. I couldn't find too much details on the difference between these two drivers, but fkms stands for "fake KMS". Basically vc4-fkms-v3d manages more of the video output pipeline internally, while the new vc4-kms-v3d driver delegates this work to the kernel.

From what I could gather, vc4-kms-v3d is the default since Bullseye, so I tried reverting to the legacy driver by setting dtoverlay=vc4-fkms-v3d in /boot/firmware/config.txt (this is the path on standard Debian, on Raspberry Pi OS it's located in /boot). However, changing the driver had no effect. The monitor still went to sleep immediately after booting.

Solution

While searching for more solutions, I found a suggestion to boot with drm.debug=0x14, by adding it to /boot/firmware/cmdline.txt. This causes the kernel to print debug information related to drm - the subsystem responsible for interfacing with the GPU.

Once I did that, I found the following message in the boot log:

$ dmesg -T | grep drm | grep disconnected
[Sat Feb  5 19:13:35 2022] [drm:drm_helper_probe_single_connector_modes [drm_kms_helper]] [CONNECTOR:32:HDMI-A-1] status updated from unknown to disconnected

So the kernel believes that the monitor is disconnected? Let's double-check.

$ cat /sys/class/drm/card0-HDMI-A-1/status
disconnected

Yes, it was indeed showing up as disconnected. But isn't hdmi_force_hotplug=1 supposed work around exactly this problem? From the config.txt documentation:

Setting hdmi_force_hotplug to 1 pretends that the HDMI hotplug signal is asserted, so it appears that a HDMI display is attached. In other words, HDMI output mode will be used, even if no HDMI monitor is detected.

This option changed nothing when using either vc4-fkms-v3d or the vc4-kms-v3d driver. However, if the new driver delegates more of its responsibility to the kernel, the kernel itself must surely have a way of forcing video output?

Some further analysis led me to the excellent Arch wiki:

video=<conn>:<xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
...
D: digital output forced to on (e.g. DVI-I connector)

Adding video=HDMI-A-1:D to /boot/firmware/cmdline.txt and rebooting did the trick! No more loss of video signal.

Update 2022-06-07: video=HDMI-A-1:D should be added to /etc/default/raspi-extra-cmdline instead so that the configuration is preserved when update-initramfs runs, e.g. when the kernel is upgraded.

I have no idea why this workaround is needed though, I suppose it could be a bug in EDID information sent by the monitor, a bug in the kernel or some incompatibility due to using a HDMI-to-DVI adapter.