External display via HDMI is not detected on HP laptops with AMD Lucienne (Ryzen 4xxx/5xxx APUs) and possibly other AMD-based laptops. The TV may show “signal detected” (due to +5V on the HDMI power pin) but the system never sees the display — the kernel reports the HDMI-A-1 connector as disconnected with 0 bytes of EDID.
When the connector is force-enabled, the display may work but shows severe artifacts and constant blinking because amdgpu negotiates 16 bpc (48-bit) deep color over the HDMI link, exceeding cable bandwidth.
Cause
Two separate issues:
1. HPD (Hot-Plug Detect) GPIO failure — On certain laptop implementations (commonly HP with AMD Lucienne/DCN 2.1), the amdgpu driver never receives the HPD signal. The HDMI +5V pin is always active (so the TV thinks something is connected), but the HPD line is never asserted or read by the driver. Without an HPD event, amdgpu never probes DDC, never reads the EDID, and never marks the connector as connected.
2. Deep color overload — The TV’s EDID advertises 36/48-bit deep color capability. When amdgpu honors this, it drives 48-bit color at 1080p60, which exceeds what the HDMI cable/port can carry → sparkle artifacts and blinking.
Workaround (proven fix)
Step 1 — Capture TV’s EDID from the DDC bus
sudo dnf install -y i2c-tools
Find the HDMI DDC bus:
ls -la /sys/class/drm/card1-HDMI-A-1/ddc/
# → /sys/devices/.../i2c-3 (yours may differ)
Capture the full EDID (256 bytes):
sudo python3 -c "
import os, fcntl, time
f = os.open('/dev/i2c-3', os.O_RDWR)
fcntl.ioctl(f, 0x0703, 0x50) # I2C_SLAVE
os.write(f, bytes([0x00]))
time.sleep(0.02)
block0 = os.read(f, 128)
os.write(f, bytes([128])) if block0[126] else None
time.sleep(0.02)
block1 = os.read(f, 128) if block0[126] else b''
os.close(f)
with open('/tmp/tv-edid.bin', 'wb') as out:
out.write(block0 + block1)
print(f'Captured {len(block0 + block1)} bytes')
"
Step 2 — Optionally remove deep color (to prevent artifacts)
python3 -c "
with open('/tmp/tv-edid.bin', 'rb') as f:
edid = bytearray(f.read())
if edid[173] & 0xF0:
edid[173] &= 0x0F
edid[255] = (256 - (sum(edid[128:255]) % 256)) % 256
with open('/tmp/tv-edid.bin', 'wb') as f:
f.write(edid)
print('Deep color flags removed from EDID')
"
Step 3 — Deploy to initramfs and kernel cmdline
sudo mkdir -p /lib/firmware/edid
sudo cp /tmp/tv-edid.bin /lib/firmware/edid/tv-edid.bin
sudo chmod 644 /lib/firmware/edid/tv-edid.bin
echo 'install_items+=" /lib/firmware/edid/tv-edid.bin "' | sudo tee /etc/dracut.conf.d/edid.conf
sudo dracut --regenerate-all --force
sudo grubby --update-kernel=ALL --args="drm.edid_firmware=HDMI-A-1:edid/tv-edid.bin video=HDMI-A-1:e"
sudo sed -i 's/^GRUB_CMDLINE_LINUX="/GRUB_CMDLINE_LINUX="drm.edid_firmware=HDMI-A-1:edid\/tv-edid.bin video=HDMI-A-1:e /' /etc/default/grub
sudo reboot
Step 4 — Verify
cat /sys/class/drm/card1-HDMI-A-1/status # should say "connected"
dmesg | grep -i 'tv-edid' # should show no errors
How it works
drm.edid_firmware=HDMI-A-1:edid/tv-edid.bin— feeds the captured EDID at boot, bypassing the broken HPD. Forces the connector toconnectedwith correct display capabilities.video=HDMI-A-1:e— extra insurance that the connector is force-enabled.- EDID in initramfs — required because firmware loading happens before
/lib/firmwareis available from the root filesystem. - Patched EDID — removing
DC_36bit/DC_30bit/DC_Y444flags prevents deep color negotiation entirely.