Skip to content

Commit 0082b85

Browse files
committed
Add dual GPU w/ KDE post
1 parent 73a0d0a commit 0082b85

1 file changed

Lines changed: 212 additions & 0 deletions

File tree

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
---
2+
title: Dealing with dual-GPU display issues on KDE Plasma
3+
---
4+
5+
A few months ago I wrote about [[04-jetkvm-tailscale|Getting Tailscale to work on my JetKVM]]. I had been using it as a remote desktop solution by connecting it to the HDMI port on my NVIDIA GPU. It worked fine, but when I started working on [[07-gpu-passthrough-journey|GPU passthrough]], I realized I'd lose all graphics when passing the NVIDIA GPU to a VM.
6+
7+
The solution was to enable the integrated graphics in my BIOS and move the JetKVM to the motherboard's HDMI port. This way I could still access the system remotely (and reach BIOS) even when the NVIDIA GPU was assigned to a VM.
8+
9+
What I didn't anticipate was that having displays connected to both GPUs would cause some strange issues with KDE Plasma.
10+
11+
## My setup
12+
13+
- Fedora Kinoite (Wayland + Plasma 6)
14+
- NVIDIA RTX 4070 Ti SUPER (discrete GPU)
15+
- Intel UHD Graphics 770 (integrated GPU)
16+
- Samsung Odyssey G70NC (4K @ 144 Hz) connected to NVIDIA DisplayPort
17+
- JetKVM connected to motherboard's HDMI port (Intel iGPU)
18+
19+
The JetKVM lets you choose from a selection of different EDID options. I'm using "DELL D2721H, 1920x1080" which has worked well for my setup.
20+
21+
## The problems
22+
23+
After moving the JetKVM to the Intel iGPU's HDMI port, I started running into two separate issues.
24+
25+
### Problem 1: DisplayPort won't wake up
26+
27+
My primary monitor started having issues after waking from sleep:
28+
29+
- Turn on briefly, then go black and repeat this cycle indefinitely
30+
- Wake up stuck at 640×480 resolution
31+
- Lose all refresh rate options above 60 Hz
32+
33+
This was frustrating because nothing about the monitor, cable, or GPU had changed. The first few times it happened I rebooted and everything went back to normal, but I knew something was wrong with the display detection.
34+
35+
#### Troubleshooting
36+
37+
The first thing I checked was whether this was a hardware issue. I looked at `/sys/class/drm/card0-HDMI-A-2/modes` to see what display modes the kernel was detecting:
38+
39+
```
40+
3840x2160
41+
2560x1440
42+
1920x1080
43+
...
44+
640x480
45+
```
46+
47+
When things were working correctly, this file would have entries like `3840x2160@144` and other high refresh rate modes. When broken, all the high refresh modes were just... gone.
48+
49+
This told me the EDID wasn't being read correctly - the driver was falling back to some safe default mode list.
50+
51+
I tried a bunch of things that didn't work:
52+
- Switching between different resolution/refresh rate combinations in Plasma's settings
53+
- Unplugging and replugging the monitor
54+
- Disabling and re-enabling displays in `kscreen-doctor`
55+
56+
Sometimes switching from 4K@60 to 4K@120 would "kick" things back into working, but it was unreliable.
57+
58+
After digging through forums and bug reports, I realized this was a DisplayPort link training issue. When waking from sleep, the DisplayPort connection wasn't renegotiating properly - the EDID read would fail and the driver would fall back to safe modes like 640×480.
59+
60+
I found that forcing a known stable mode would reset the stuck state:
61+
62+
```bash
63+
kscreen-doctor output.2.mode.3840x2160@60
64+
sleep 2
65+
kscreen-doctor output.2.mode.3840x2160@143.99
66+
```
67+
68+
This worked as a workaround, but I shouldn't have to run commands manually every time the monitor wakes up.
69+
70+
Eventually I just switched to an HDMI 2.1 cable and the wake issues disappeared entirely. HDMI 2.1 handles the link negotiation much more reliably than DisplayPort on my setup.
71+
72+
### Problem 2: DPI scaling issues
73+
74+
After switching to HDMI, I noticed something else: my Samsung display looked... off. Text seemed larger than it should be, and when I checked the display settings, I realized KDE was scaling everything to match the DPI across both displays.
75+
76+
The JetKVM at 1080p has a much lower DPI than my 4K Samsung. KDE was using the lower DPI as the baseline, which made everything on my Samsung look less sharp than it should.
77+
78+
## The solution
79+
80+
I didn't need both displays active all the time. The JetKVM is only useful when I need remote access to the system or BIOS. The rest of the time, I want just my Samsung display running at full quality.
81+
82+
What I needed was a way to easily toggle the JetKVM display on and off from SSH.
83+
84+
## The script
85+
86+
I put together a script that auto-detects the JetKVM by reading EDID data from `/sys/class/drm/` and uses `kscreen-doctor` to toggle it.
87+
88+
The tricky part is that `kscreen-doctor` needs access to the Wayland session, which isn't normally available over SSH or a TTY. The script handles this by setting up the necessary environment variables to communicate with the running Plasma session.
89+
90+
```bash
91+
#!/usr/bin/env bash
92+
93+
# jetkvm-display: enable/disable the JetKVM HDMI output in a KDE Wayland session.
94+
# Usage: jetkvm-display enable
95+
# jetkvm-display disable
96+
97+
set -euo pipefail
98+
99+
# Unique EDID substring for the JetKVM monitor
100+
JETKVM_EDID_TAG="DELL D2721H"
101+
102+
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
103+
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
104+
105+
# Make sure sudo can prompt once if needed (for reading EDID)
106+
sudo -v >/dev/null 2>&1 || true
107+
108+
# Run kscreen-doctor inside the active KDE Wayland session
109+
ks_doctor() {
110+
kscreen-doctor "$@"
111+
}
112+
113+
# Find the HDMI connector whose EDID contains the JetKVM tag
114+
find_jetkvm_connector() {
115+
local f basename connector
116+
for f in /sys/class/drm/*HDMI-A-*/edid; do
117+
[ -r "$f" ] || continue
118+
if sudo strings "$f" 2>/dev/null | grep -q "${JETKVM_EDID_TAG}"; then
119+
basename="$(basename "$(dirname "$f")")" # e.g. card0-HDMI-A-1
120+
connector="${basename#*-}" # strip "card0-" -> HDMI-A-1
121+
echo "${connector}"
122+
return 0
123+
fi
124+
done
125+
return 1
126+
}
127+
128+
# Verify that kscreen-doctor knows about this connector name
129+
detect_jetkvm_output_name() {
130+
local connector="$(
131+
find_jetkvm_connector || {
132+
echo "jetkvm-display: EDID tag '${JETKVM_EDID_TAG}' not found on any HDMI connector" >&2
133+
return 1
134+
}
135+
)"
136+
137+
# Check that kscreen-doctor -o lists an Output with that name
138+
if ! ks_doctor -o | awk -v conn="$connector" '
139+
/Output:/ {
140+
# "Output: 2 HDMI-A-1 <uuid>"
141+
name = $3
142+
if (name == conn) {
143+
found = 1
144+
}
145+
}
146+
END { exit (!found) }
147+
'; then
148+
echo "jetkvm-display: found connector '${connector}' for JetKVM, but no matching Output name in kscreen-doctor -o" >&2
149+
echo "jetkvm-display: Outputs seen:" >&2
150+
ks_doctor -o | grep 'Output:' >&2 || true
151+
return 1
152+
fi
153+
154+
echo "jetkvm-display: JetKVM detected on connector '${connector}'" >&2
155+
echo "${connector}"
156+
}
157+
158+
JET_OUTPUT_NAME="$(detect_jetkvm_output_name || true)"
159+
160+
if [ -z "${JET_OUTPUT_NAME}" ]; then
161+
echo "jetkvm-display: could not auto-detect JetKVM" >&2
162+
exit 1
163+
fi
164+
165+
do_enable() {
166+
ks_doctor "output.${JET_OUTPUT_NAME}.enable"
167+
}
168+
169+
do_disable() {
170+
ks_doctor "output.${JET_OUTPUT_NAME}.disable"
171+
}
172+
173+
case "${1:-}" in
174+
enable)
175+
do_enable
176+
;;
177+
disable)
178+
do_disable
179+
;;
180+
*)
181+
echo "Usage: $0 {enable|disable}" >&2
182+
exit 1
183+
;;
184+
esac
185+
```
186+
187+
I saved this to `~/.local/bin/jetkvm-display` and made it executable.
188+
189+
Now when I need remote access:
190+
191+
```bash
192+
ssh desktop
193+
jetkvm-display enable
194+
# Access the system through JetKVM
195+
jetkvm-display disable
196+
```
197+
198+
The key things this script does:
199+
- Reads EDID data from `/sys/class/drm/` to find which HDMI connector has the JetKVM (searches for "DELL D2721H")
200+
- Verifies that `kscreen-doctor` knows about that connector
201+
- Sets up the necessary environment variables (`XDG_RUNTIME_DIR`, `WAYLAND_DISPLAY`, `DBUS_SESSION_BUS_ADDRESS`) to talk to the Wayland session from SSH
202+
- Uses `kscreen-doctor` to cleanly enable/disable the display
203+
204+
## Results
205+
206+
With the JetKVM display disabled by default:
207+
- No wake issues (after switching to HDMI 2.1)
208+
- No DPI scaling problems
209+
- Samsung runs at full 4K @ 143.99 Hz
210+
- I can still enable the JetKVM whenever I need remote access
211+
212+
Switching from DisplayPort to HDMI 2.1 completely resolved the wake issues. Combined with keeping the JetKVM display disabled when not in use, everything has been stable since.

0 commit comments

Comments
 (0)