raspberrypi / linux

Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/
Other
10.87k stars 4.89k forks source link

Raspberry Pi 4 missing "720x480 (scaled)" composite mode on 6.6.33 #6242

Open synthic opened 1 week ago

synthic commented 1 week ago

Describe the bug

For a long time it was recommended to enable 240p output over composite video by adding video=Composite-1:720x480@60e to cmdline.txt. On previous kernel verions 5.10 and earlier, this resulted in the following output from modetest -M vc4:

Connectors:
55  54  connected   composite-1     0x0     3   54
  modes:
    index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 720x480 (scaled) 60.05 720 734 798 858 480 486 492 524 27000 flags: ; type: preferred, driver
  #1 720x480i 29.97 720 734 798 858 480 487 493 525 13500 flags: interlace; type: userdef, driver
  #2 720x240 60.05 720 734 798 858 240 243 246 262 13500 flags: ; type: driver

This worked perfectly as the device was outputting a progressive 240p signal as expected, but according to KMS/DRM the system was running at 720x480. From what I have gathered, this is achieved by vertically scaling the image to double it's height, but since it's still outputting at 240p it's technically a "fake" resolution. However, this is perfect because GUI apps can display properly in 4:3 while still maintaining a sharp progressive output.

When adding the same option to the cmdline on 6.6, the result is quite different:

Connectors:
id  encoder status      name        size (mm)   modes   encoders
45  44  connected   Composite-1     0x0     4   44
  modes:
    index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot
  #0 720x480i 59.94 720 736 800 858 480 486 492 525 13500 flags: nhsync, nvsync, interlace; type: preferred, userdef, driver
  #1 720x576i 50.00 720 732 796 864 576 581 587 625 13500 flags: nhsync, nvsync, interlace; type: driver
  #2 720x288 50.08 720 740 804 864 288 290 293 312 13500 flags: ; type: driver
  #3 720x240 60.05 720 734 798 858 240 243 246 262 13500 flags: ; type: driver

Only 480i and 240p modes are present and when switching mode to 720x240 and starting an application, the video is stretched or fails to scale properly due to the unusual aspect ratio.

Steps to reproduce the behaviour

Boot up Raspberry Pi 4 with latest kernel after adding video=Composite-1:720x480@60e to cmdline.txt and connect to a CRT display.

Device (s)

Raspberry Pi 4 Mod. B

System

May 24 2024 15:30:43 
Copyright (c) 2012 Broadcom
version 4942b7633c0ff1af1ee95a51a33b56a9dae47529 (clean) (release) (start_x)
Linux Lakka 6.6.33 #1 SMP Wed Jun 26 07:50:27 CEST 2024 aarch64 GNU/Linux

Logs

No response

Additional context

I realize that the composite output and vc4 driver code have been improved recently to better adhere to broadcast standards. At the same time, this pull request was merged giving the RP1 on the Raspberry Pi 5 much more flexibility with a new custom mode option. #6105

In the case of Lakka there is now a build for dedicated composite output thanks to this very helpful custom mode option. A custom mode that matches the missing one can now easily be defined on the RPi 5. However, for the RPi 3/4 the 6.6 kernel could not be used due to this issue so they are forced to stay with 5.10, which means a unified build is not possible. Similar distros focused around gaming on CRT TVs have had to take steps to fix this issue in other ways as well. It doesn't make sense that the RPi 5 can output in this mode while the previous models used to be able to and are now unable.

That being said, having a complete custom mode option for RPi 3/4 doesn't make sense as the encoder is too strict to allow for just anything. However, the aforementioned "720x480 (scaled)" mode has been present and functional for years it seems. Ultimately, I was wondering if this functionality could be introduced back into the kernel somehow. My proposition is to add a new option for the vc4 driver such as vc4.vdouble that could be added to the cmdline to recreate the scaled mode how it was previously and enable it. If it is possible to restore this functionality it would help many users get the most out of their CRT displays without being relegated to an older kernel version.

popcornmix commented 1 week ago

@njhollinghurst may be able to describe what the options are.

6by9 commented 1 week ago

What's the full 5.10 version you had that mode with?

The mode name is normally generated by the DRM core code through drm_mode_set_name - https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_modes.c#L1268. That will never add "(scaled)" to the end of the name. I can't immediately see a version of vc4_vec.c that would manually create a mode with that name, so where has it come from?

The command-line mode will have added #1 720x480i in each case, hence the userdef flag on the end of it, not the scaled one.

AIUI vc4's VEC is far more prescriptive over the timings that can be accepted, so we can't alter the pixel clock in the way that is possible with RP1's composite encoder. The only options would be to adjust the porches to redefine which are the active lines reported to DRM.

synthic commented 1 week ago

I am not using Raspberry Pi OS as I'm not sure which older version would have that kernel, but the recent build of Lakka that I mentioned. uname -a reports:

Linux Lakka 5.10.110 #1 SMP Tue May 14 08:52:22 CEST 2024 aarch64 GNU/Linux

Thanks for the information. I didn't realize that mode name was atypical! Searching through the main Lakka repo for "scaled" I found a patch that seems to be the culprit, and apparently it was taken from an open pull request here. But it looks like it only applies to the 5.10 branch. #4636

So I guess this PR is exactly what I was looking for, but it still needs to be merged and hopefully can be adapted and applied to the 6.6 branch as well.

6by9 commented 1 week ago

I'd missed that PR, or decided it needed further review and never came back to it.

It's not the right answer though - if you want a 720x480 framebuffer on the display stretched to 720x240p then create such a buffer and tell DRM to do the stretch. I'm guessing Lakka is trying to do the simple thing and still uses the framebuffer emulation rather than using DRM fully. Fiddling the DRM mode allows some level of configuration over that buffer geometry.

What might be reasonably contained would be having a route to influence the framebuffer resolution choice.

The standard code takes the minimum width and minimum height of all connected displays on the DRM device. It then displays that buffer at 1:1 in the top left of all displays. Using 1:1 scaling makes sense in the generic case as not all hardware can scale, and it also avoids weird situations where you could have a 800x1280 display and a 1280x720 display connected (the resulting 800x720 buffer would look weird stretched on both displays).

If you could override that buffer size, then whilst you could configure it to be larger than the screen and some of the buffer won't be visible, you could also configure scaling on some outputs. I've not thought it fully through (and being core code this is important), but something like drm_kms_helper.fbdev_geometry=720x480,HDMI-A-1:720x480,Composite-1:720x240 to force a 720x480 fb to be 1:1 on HDMI-1 but stretched on Composite. (Potentially you could extend set an x,y offset in there too which could be useful to centre a 1080p fb on a 4k display)

This is unlikely to be acceptable to mainline as I suspect they'd like to totally drop fbdev, and it depends on how significant the changes are as to whether we'd be prepared to handle them downstream.