raspberrypi / firmware

This repository contains pre-compiled binaries of the current Raspberry Pi kernel and modules, userspace libraries, and bootloader/GPU firmware.
5.18k stars 1.68k forks source link

hdmi hotplug, xrandr and 4k resolutions #1449

Open RomanValov opened 4 years ago

RomanValov commented 4 years ago

Describe the bug Cannot use 4k@30hz+ resolutions with xrandr if using hdmi hotplug mode

To reproduce

  1. Disconnect HDMI devices from the board
  2. Add following lines to /boot/config.txt:
    hdmi_force_hotplug=1
    hdmi_group=1
    hdmi_mode=95
    hdmi_drive=2
  1. Reboot the system
  2. Run following command in console:
    xrandr --output HDMI-1 --primary --mode 3840x2160 --rate 30Hz --pos 0x0 --rotate normal
  1. Connect HDMI device

Expected behaviour xrandr sets desired resolution, HDMI device correctly renders picture (as it works with non-4k resolutions)

Actual behaviour xrandr exits with error: xrandr: cannot find mode 3840x2160

System https://pastebin.com/a8jWCHE9

Logs non applicable

Additional context The only 4k resolution I was able to set without additional tweaks is hdmi_mode=98 -- 4096x2160@24Hz Putting the line hdmi_enable_4kp60=1 into /boot/config.txt makes xrandr correctly handle hdmi_mode=95 and hdmi_mode=100 -- 4k 30Hz resolutions (at least xrandr doesn't complain), but 4k 60Hz resolution still fails to be set.

6by9 commented 4 years ago

You have no EDID therefore the only information passed across is via the kernel command line, eg

pi@raspberrypi:~ $ cat /proc/cmdline 
coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_compat_alsa=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_headphones=1 video=HDMI-A-1:3840x2160M@30 smsc95xx.macaddr=B8:27:EB:20:FD:5F vc_mem.mem_base=0x3dc00000 vc_mem.mem_size=0x3f000000  drm.debug=0x14 console=ttyS0,115200 console=tty1 root=PARTUUID=fa9db42e-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait plymouth.ignore-serial-consoles

The kernel command line takes the resolution and frame rate and creates a CVT mode based on that. 3840x2160@30M (reduced margins) becomes

[   30.804292] [drm:drm_mode_debug_printmodeline [drm]] Modeline "3840x2160": 0 338875 3840 4080 4488 5136 2160 2163 2168 2200 0x20 0x6

This compares against mode 95 which has timings

 "3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016, 4104, 4400, 0, 2160, 2168, 2178, 2250, 0,

Without hdmi_enable_4kp60=1 the max pixel clock is 297MHz. This 338.875MHz exceeds that, therefore the mode is not created.

Hot plug isn't supported with FKMS (I looked into it but it became pretty ugly). If you want to add that mode then you need to create it explicitly via xrandr using something along the lines of

xrandr --newmode "3840x2160" 297.000 3840 4016 4104 4400 2160 2168 2178 2250
xrandr --addmode HDMI-1 3840x2160

Either that or grab the EDID from your monitor via tvservice -d edid.dat, copy edid.dat to /boot, and add hdmi_edid_file=1 to config.txt. Then the Pi thinks it has that monitor attached at all times, and the kernel doesn't have to try and second guess which flavour of 3840x2160 @ 30 you meant.

RomanValov commented 4 years ago

@6by9 thanks for your reply. I'm actually trying to make my box correctly working in the scenario of initially unattached hdmi port.

It seems that video parameter of kernel command line is configured based on the mode set by hdmi_mode in /boot/config.txt. So at least in case of RPi it seems we could be sure that video=HDMI-A-1:3840x2160M@30 assumes mode 95. However I'm not sure what is the component that generates 338.875 modeline. I'm not familiar with drm codebase but it seems it could be driver-specific or generic code.

So in my opinion it make sense to patch the kernel/modules to use 297.000 modeline for the video mode specified.

As of hotplug in FKMS I'm sure if you were talking about kind of dynamic hotplug without pseudo-monitor attached. But at least supporting the same scenario with pseudo-monitor as with up to 1080p resolutions would be nice.

6by9 commented 4 years ago

If mode 95 was listed in an EDID from your display, then the video=HDMI-A-1:3840x2160M@30 line would select it.

Without an EDID the kernel uses the industry standard Coordinated Video Timings (CVT) algorithm which gives a different answer to mode 95.

It's generic code in the kernel, not driver specific. It won't be patched.

If you want to boot as if a specific monitor were attached, then capture the EDID and pass it in via hdmi_edid_file=1 and hdmi_edid_filename=edid.dat (as I'd already suggested).