Sample Header Ad - 728x90

DRM: Artificially simulating a monitor Disconnect+Reconnect event, or a HOTPLUG uevent

2 votes
0 answers
154 views
Is there a way to simulate a physical HDMI cable unplugging and replugging on a Linux system running Xorg with AMDGPU driver? In my Xfce system on X11, I have trouble with monitor output/connector detection. In particular, when the system transitions from the Rescueshell/GRUB to the distro login manager (lightdm), the monitor turns blackish grey, and the only fix I've found so far is by unplugging the monitor's HDMI and replugging, or by changing the monitor's own FreeSync setting (Options: Standard Engine, Ultimate Engine, Off) in that black screen state and doing Ctrl+Alt+F2, which I think effectively "resets" the HDMI connection. Using drm.edid= as a kernel boot option can help with the issue, but having a valid Xorg.conf in /usr/share/X11/xorg.conf.d/ basically makes it useless and recreates the blackscreen, as I think Xorg/AMDGPU (my graphics driver) takes over control of the graphical output and uses the edid or modeline in the Xorg.conf, once it gets to the initial pre-login/post-login stage in lightdm. This switchup probably confuses my monitor. But I want to have a Xorg.conf for proper functionality. The blackscreen isn't completely black, as in a no signal, but it's somewhat grey. If I switch TTYs, the screen will flicker and go grey again, but there'll be no display at this stage. It's like the monitor is detected, but there the signal isn't interpreted right. I want to know if there is any way to make the KMS/DRM driver think that the monitor has been disconnected and reconnected, without a real physical disconnect, so the driver refreshes all "connectors" and hopefully gives output to the monitor, possibly using a udev HOTPLUG event. According to the answers in this question: , it is possible to use udevadm trigger to masquerade udev events to specific devices in /sys subsystems. Or by directly using echo ACTION > /sys/class/SUBSYTEM/DEVICE/uevent From udevadm trigger --verbose --action=help /sys/class/drm/card0-HDMI-A-1 I get a list of all possible 'trigger' options:
add
remove
change
move
online
offline
bind
unbind
I've tried using all of them, but they don't do anything equivalent to a full replugging. The screen stays on the whole time. However 'change' using udevadm trigger --verbose --action=change /sys/class/drm/card0-HDMI-A-1 forces a rescan for the device EDID in dmesg:
[34870.335496] Registering platform device 'HDMI-A-1'. Parent at platform
[34870.335523] device: 'HDMI-A-1': device_add
[34870.335545] platform HDMI-A-1: No ACPI support
[34870.335553] bus: 'platform': add device HDMI-A-1
[34870.335720] bus: 'platform': remove device HDMI-A-1
[34870.335746] [drm] Got external EDID base block and 0 extensions from "edid/1920x1080.bin" for connector "HDMI-A-1"
This does not turn off the screen though, and so doesn't help with the problem. Is there any way to mention a specific key / ENV{ATTRIBUTE} when triggering a udev event? For example someone else's udev logs during a monitor unplug and replug cycle:
udevadm monitor --environment --udev 
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV  [1370.249130] change   /devices/pci0000:00/0000:00:02.0/drm/card0 (drm)
ACTION=change
DEVNAME=/dev/dri/card0
DEVPATH=/devices/pci0000:00/0000:00:02.0/drm/card0
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_00_02_0
ID_PATH=pci-0000:00:02.0
ID_PATH_TAG=pci-0000_00_02_0
MAJOR=226
MINOR=0
SEQNUM=1884
SUBSYSTEM=drm
TAGS=:seat:uaccess:
USEC_INITIALIZED=715
Here the main ACTION is "change", but is there a way *I* can specify that HOTPLUG=1 parameter? It's noteworthy that when *I* use udevadm monitor and do an unplug cycle, nothing shows up in output. But when switching TTYs to F2 then F7 (my GUI) using Ctrl+Alt+..., then I get this:
udevadm monitor --environment --udev
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV  [4315.550505] add      /devices/platform/HDMI-A-1 (platform)
ACTION=add
DEVPATH=/devices/platform/HDMI-A-1
SUBSYSTEM=platform
MODALIAS=platform:HDMI-A-1
SEQNUM=3714
USEC_INITIALIZED=4315229577
ID_PATH=platform-HDMI-A-1
ID_PATH_TAG=platform-HDMI-A-1

UDEV  [4315.551278] remove   /devices/platform/HDMI-A-1 (platform)
ACTION=remove
DEVPATH=/devices/platform/HDMI-A-1
SUBSYSTEM=platform
MODALIAS=platform:HDMI-A-1
SEQNUM=3715
USEC_INITIALIZED=4315229577
ID_PATH=platform-HDMI-A-1
ID_PATH_TAG=platform-HDMI-A-1
which could indicate that hotplugging is not supported or triggered properly in my system, leading to my issues. I found a Gentoo forum post: which had my same question regarding unplug and replug, but there was not a solution there. I have tried echo off > /sys/class/drm/card0-HDMI-A-1/status and echo on > /sys/class/drm/card0-HDMI-A-1/status but it doesn't cause the monitor to turn off, only an EDID rescan in dmesg. The same thing as a udevadm trigger --action=change. echoing to enabled or dpms in that same directory doesn't seem to be allowed. I have tried xset -display :0 dpms force off (or -display :0.0) from a TTY/shell script, but it doesn't turn off the monitor. Though it works in a GUI of course, after I've already unplugged the monitor once. I tried
sudo mount -o remount,exec /dev
sudo vbetool dpms off
sudo mount -o remount,noexec /dev
from [this](https://old.reddit.com/r/linux4noobs/comments/vo7u7l/how_can_i_turn_the_display_off_in_a_tty/) and [this](https://askubuntu.com/questions/1384221/real-mode-call-failed-on-macbook-pro-when-trying-to-turn-screen-off-ubuntu-serve) , but it outputs Real mode call failed. So now I tried setterm --blank 1 from and consoleblank=200 (approximate bootup time for my device in seconds) as a kernel commandline parameter, and they also don't work as I want them to. They can turn off the screen, but it's not a hard enough reset that makes the monitor redetected like in a physical replugging. I've tried a systemd service like this ExecStart=/bin/sh -c 'while [ -n "$(pidof lightdm)" ] || [ -n "$(pidof X)" ] || [ -n "$(pidof Xorg)" ]; do sleep 10; done; sleep 15; echo '' > /sys/module/drm/parameters/edid_firmware && pkill X' to restart X at the login prompt, but it doesn't help either. I came across this guide , which mentioned > void (*output_poll_changed)(struct drm_device *dev); > >This operation notifies the driver that the status of one or more connectors has changed. Drivers that use the fb helper can just call the drm_fb_helper_hotplug_event function to handle this operation. Is there a way I can compile a binary and call this function manually at X startup, to achieve what I'm looking for? Or is there any other solution to address this? I am having this issue on a PS4 system running Arch Linux, and I think the monitor might have trouble with EDID communication. So the hardware situation is a bit flaky, but most of the underlying mechanics are still the same.
Asked by feearent (61 rep)
Jun 17, 2025, 08:00 PM
Last activity: Jun 18, 2025, 10:39 AM