firmware icon indicating copy to clipboard operation
firmware copied to clipboard

can't change current resolution of the framebuffer on pi4, /sys/class/display missing?

Open alanbork opened this issue 4 years ago • 21 comments

Using a Pi4 with FKMS I'm trying to change the resolution of the console while not running X, as we used to be able to do with tvservice on the Pi3 and earlier. tvservice actually still works, sort of, but messes up the state of the fkms/drm drivers - at the very least fkms still thinks the previous resolution is the one that's active, but I've also encountered numerous graphical glitches as well after using tvservice.

In (my) ideal world tvservice would be upgraded to work with fkms and we'd be back to having a consistent way to adjust the current resolution at the command line rather than having to reboot every single time, and your current documentation for pi0-3 could match the pi4 rather than having to be split in half.

But: since there's a focus on doing things the kms/upstream way, how about properly supporting an interface that already has been defined for this purpose? Supposedly this should work:

echo 1080p60hz > /sys/class/display/mode

(see https://forum.odroid.com/viewtopic.php?t=35280)

however this path doesn't exist in the current release. But maybe it's located under a different name/path?

/sys/class/graphics/fb0/device/drm/card1/card1-HDMI-A-1 has the list of modes supported by the screen (although it's missing the refresh rate) but no place to change the current mode (I would expect /sys/class/graphics/fb0/device/drm/card1/card1-HDMI-A-1/mode). FYI There's a maze of symbolic links under /sys/class/graphics so that might not be the canonical path.

another source (https://wiki.radxa.com/Rock/display) led me to /sys/class/graphics/fb0 and this has both a list of modes a place to send the new mode to (/sys/class/graphics/fb0/mode). But the list of modes is basically empty: just the current mode. And if I add a new one (using fbset) and then send it to /sys/class/graphics/fb0/mode it changes nothing. it does seem to be backed by something active: if I send it a non-existent resolution it gives an error message.

I'm running a fairly recent version of the os provided by rpi-update:

Linux raspberrypi 5.4.61-v7l+ #1339 SMP Tue Sep 1 18:51:27 BST 2020 armv7l GNU/Linux

and dtoverlay=vc4-fkms-v3d

it seems like a real shame the pi4 has lost the functionality of changing the console resolution after bootup. even your own docs suggest that it's preferable to do that at least for testing purposes before setting /boot/config.txt.

alanbork avatar Sep 16 '20 22:09 alanbork

Does this help?

https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md

JamesH65 avatar Sep 17 '20 08:09 JamesH65

I don't see how that can be used to change the resolution after bootup, ala TVservice. Am I missing something?

On Thu, Sep 17, 2020, 1:19 AM James Hughes [email protected] wrote:

Does this help?

https://www.raspberrypi.org/documentation/configuration/cmdline-txt.md

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/raspberrypi/firmware/issues/1470#issuecomment-694077089, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANPGZ5N63S3QE6WJO3IMN3LSGHBCPANCNFSM4RPQSZTQ .

alanbork avatar Sep 17 '20 13:09 alanbork

Your comment "it seems like a real shame the pi4 has lost the functionality of changing the console resolution at boot time. " implies you wanted to set it at boot time, not after boot.

I think there is a cmd line tool to set stuf via KMS/DRM, but I cannot remember what it is off hand. @6by9 ?

JamesH65 avatar Sep 17 '20 13:09 JamesH65

@JamesH65 ah yes that is confusing, sorry. edited for future clarity. NB: fbset is often mentioned as the tool for this, but several raised issues on this very github show that nobody can get it to work, and the ofifcal response is that fbset is no longer expected to work in a kms/drm world.

alanbork avatar Sep 17 '20 14:09 alanbork

If you use the existing hdmi_group / hdmi_mode parameters in config.txt then the firmware will propagate them forward through the kernel command line (see the link JamesH65 provided for syntax), and should be applied for the console framebuffer.

Regarding changing resolution after boot, I've checked with one of the mainline DRM developers:

You're right (unfortunately), the fbdev emulation doesn't support changing the FB resolution, and the proper fix would be to switch to the KMS API.

Every time that has been brought up, the message was pretty much that they wouldn't support it either, so I guess there's not much we can do (except carrying an out-of-tree patch to do this maybe?)

So the situation is exactly the same on any x86 or any other system, and unlikely to change in mainline. I believe one of the main drivers is that the fbdev APIs don't really support multiple displays, so how should it set things up in that case. The current behaviour is that the emulated framebuffer is the size of the smallest screen, and that will be displayed at 1:1 in the top left on all displays.

The correct approach to this is that your application should use the DRM/KMS APIs (use libdrm to make life easier) to take control of the screen composition. You then get to choose what resolution to use on any connected display, and place your own planes on those screens with the scaling and locations required. This is what things like Kodi do.

The mode chosen via the kernel command line is stored within the driver structures for when needed, so it would be possible to modify that via some userspace hook and I believe it should be persistent. fbset sort of feels possible, but as above it has the issue of how it applies to multiple displays. Some hook off the DRM/KMS API would probably be better, but it would need a bit of thought as to what an how.

6by9 avatar Sep 17 '20 14:09 6by9

NB this is about setting the resolution for the console not applications. I've been messing around with a lot of different TVs and they aren't as straightforward as computer monitors: each resolution gets handled differently in terms of overscan and aliasing, and sometimes they don't even support some of the advertised modes in the edid. It's really nice to be able to interactively try the different modes at the command line and find the one that looks best.

the links I provided do suggest a possible interface, and one of them mentions support in ubuntu - but it does look on closer inspection that both are for non x86 hardware. Not that that should matter, but perhaps that means that the code base they offer is not mainline DRM, which is an obvious issue.

one of the paths in particular that I found on the pi4 does seem to have the display number enumerated (quoting from above):

sys/class/graphics/fb0/device/drm/card1/card1-HDMI-A-1 has the list of modes supported by the screen (although it's missing the refresh rate) but no place to change the current mode (I would expect /sys/class/graphics/fb0/device/drm/card1/card1-HDMI-A-1/mode). FYI There's a maze of symbolic links under /sys/class/graphics so that might not be the canonical path.

in any case some userspace hook would be great.

alanbork avatar Sep 17 '20 14:09 alanbork

The console writes to the emulated framebuffer in whatever mode the kernel command line has set that up. https://elixir.bootlin.com/linux/v5.8.9/source/include/drm/drm_connector.h#L997 is the struct that is populated from the command line, and each drm_connector stores one of them https://elixir.bootlin.com/linux/v5.8.9/source/include/drm/drm_connector.h#L1327

All sorts of hacks have been done by SBC vendors over the years to set up resolutions, including by Raspberry Pi. DRM/KMS is the mainline API for display composition, and we're trying to move towards standard APIs instead of homebrew things. Some of this will be less straightforward than others. Both the links you provided are for other SBC proprietary changes (O-Droid and Rockchip).

/sys/class/graphics/fb0 -> ../../devices/platform/gpu/graphics/fb0, or /sys/class/devices/platform/gpu/graphics/fb0 /sys/class/graphics/fb0/device -> /sys/class/graphics/fb0/../../devices/platform/gpu/graphics/fb0../../../gpu, or /sys/devices/platform/gpu

TBH I tend to use /sys/class/drm which has symlinks for all the DRM devices. AFAIK Everything under those /sys/class/drm nodes is read-only. There are no ways of adjusting settings via them.

6by9 avatar Sep 17 '20 15:09 6by9

It's not hugely surprising that mainline doesn't consider this a priority - developers are probably all under x11, and if they do use the console it's probably not with TVs where things are much more hairy and just choosing the highest resolution or so-called preferred resolution isn't always a good choice. Since there's more than one SBC solution that does there's definitely demand for this, but unfortunately no consistency on how. At least their codebase might be useful for figuring out how to poke the right values into the drm_connector post-boot and get it to work?

meanwhile in terms of the lines of new userspace code required, the tvservice command actually already works to push values into the firmware, it just doesn't update kms/drm, correct? Admittedly, without knowing the issues at all, it seems like it might be easiest to just figure out how to get those changes from tvservice propagated into the kernel. Upside of that vs fbset or /sys/class/drm/ is that tvservice already knows how to query what cea and dmt modes are supported by the TV plus already knows all the possible modes in case you want to go hunting outside what the edid reports, handles NTSC frame rates, etc,, etc.

alanbork avatar Sep 17 '20 17:09 alanbork

Why do you need to change the resolution after boot?

As 6by9 said, we would really rather not move away from standard DRM. Much of our work is trying to make things MORE standard, not less so.

In FULL KMS tvservice will stop working almost completely - the firmware will be taking no part in choosing resolutions, and Full KMS is the direction we are heading.

JamesH65 avatar Sep 17 '20 18:09 JamesH65

@JamesH65

I've been messing around with a lot of different TVs and they aren't as straightforward as computer monitors: each resolution gets handled differently in terms of overscan and aliasing, and sometimes they don't even support some of the advertised modes in the edid. It's really nice to be able to interactively try the different modes at the command line and find the one that looks best. even your own docs suggest that it's preferable to do that at least for testing purposes before setting /boot/config.txt.

alanbork avatar Sep 17 '20 18:09 alanbork

Indeed. Can you run X, try the resolutions in the screen config utility, then use those to set the kernel command line?

JamesH65 avatar Sep 17 '20 20:09 JamesH65

well yes, but the mapping isn't very good there - the config.txt command wants hdmi modes and xrandr doesn't give those. plus you have to run X which is a pain in a non-mouse setup but certainly possible. and you can type tvservice blind in the case that you get yourself into a big enough mess, which has happened when I switched tvs without remembering to set the defaults to a supported resolution.

tvservice was a very helpful tool is all I'm saying, it's a significant loss, at least to me, that the pi4 doesn't have a fully supported equivalent for command line users. Obviously firmware code maintainability and limited resources means that not everything that would be nice to have is going to be implemented. But the suggested workarounds are certainly a regression over what was possible before the Pi4. If they were sufficient, why did anybody bother to write tvservice in the first place? Because I switch between TVs frequently I use tvservice pretty much every time I turn on my pi, often instead of changing the /boot/config.txt options (one of the things I use the pi for is testing displays). I've basically quit using my pi4 because of its non-functionality in this regard, at the loss of the higher resolutions and refresh rates it offers.

On Thu, Sep 17, 2020 at 1:35 PM James Hughes [email protected] wrote:

Indeed. Can you run X, try the resolutions in the screen config utility, then use those to set the kernel command line?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/raspberrypi/firmware/issues/1470#issuecomment-694485298, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANPGZ5OYOOOFZ43LWJZVGMLSGJXIBANCNFSM4RPQSZTQ .

alanbork avatar Sep 17 '20 21:09 alanbork

If you're that stuck on Pi4, then remove the dtoverlay=vc4-fkms-v3d line from config.txt.

You lose all OpenGL 3D acceleration, and get /dev/fb0 and /dev/fb1 as totally independent framebuffer devices (no easy extended desktops in X). tvservice will work there, although you still have to jump through the hoops of fbset to reinitialise the framebuffer after any mode change (which is a good demonstration of how this isn't a good solution in the first place as any integrated solution would update everything together, but the fb driver has no knowledge of what you do via tvservice).

It's not a route we really recommend, but it's an option.

6by9 avatar Sep 18 '20 07:09 6by9

well yes, but the mapping isn't very good there - the config.txt command wants hdmi modes and xrandr doesn't give those. plus you have to run X which is a pain in a non-mouse setup but certainly possible. and you can type tvservice blind in the case that you get yourself into a big enough mess, which has happened when I switched tvs without remembering to set the defaults to a supported resolution. tvservice was a very helpful tool is all I'm saying, it's a significant loss, at least to me, that the pi4 doesn't have a fully supported equivalent for command line users. Obviously firmware code maintainability and limited resources means that not everything that would be nice to have is going to be implemented. But the suggested workarounds are certainly a regression over what was possible before the Pi4. If they were sufficient, why did anybody bother to write tvservice in the first place? Because I switch between TVs frequently I use tvservice pretty much every time I turn on my pi, often instead of changing the /boot/config.txt options (one of the things I use the pi for is testing displays). I've basically quit using my pi4 because of its non-functionality in this regard, at the loss of the higher resolutions and refresh rates it offers.

You don't necessarily have to run X on the same Pi. If you have a spare you can use one to set the screen up, then the headless box can be put in place. Bear in mind the Pi 4 is different to the other models of Pi in terms of the HDMI hardware, so if you're using a Pi 4 it needs to be a Pi 4 you are setting things up with as well.

ghost avatar Sep 18 '20 16:09 ghost

If you're that stuck on Pi4, then remove the dtoverlay=vc4-fkms-v3d line from config.txt.

You lose all OpenGL 3D acceleration, and get /dev/fb0 and /dev/fb1 as totally independent framebuffer devices (no easy extended desktops in X). tvservice will work there, although you still have to jump through the hoops of fbset to reinitialise the framebuffer after any mode change (which is a good demonstration of how this isn't a good solution in the first place as any integrated solution would update everything together, but the fb driver has no knowledge of what you do via tvservice).

that would be fine if you could load fkms on demand. I'm guessing that's not an option though?

alanbork avatar Sep 18 '20 21:09 alanbork

that would be fine if you could load fkms on demand. I'm guessing that's not an option though?

No

popcornmix avatar Sep 19 '20 11:09 popcornmix

I discovered modetest as potential way to play around with modes at the command line, and it seems like it might actually do what I want:

according to https://wiki.st.com/stm32mpu/wiki/DRM_KMS_overview#Set_a_particular_video_mode

By using the modetest option -d (drop master after mode set) in the above command, the next DRM-based application that will start will detect the current video mode and use it directly. For instance, with Weston https://wiki.st.com/stm32mpu/wiki/Wayland_Weston_overview, use "mode=current" in the weston.ini file to set preferred DRM video mode with the above command and restart weston to use it.

this does not however seem to work; after modetest quits the display returns to the console running at it previous resolution. the idea is reasonable, however: if there was a way to prevent the drivers from resetting the display back to the previous resolution and it were possible to restart the frame buffer with the right configuration (manually, as was required with tvservice would be fine) then the pre pi4 functionality could be restored.

On Sat, Sep 19, 2020 at 4:18 AM popcornmix [email protected] wrote:

that would be fine if you could load fkms on demand. I'm guessing that's not an option though?

No

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/raspberrypi/firmware/issues/1470#issuecomment-695200739, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANPGZ5OJT4E2EPOA7VOPVZLSGSHPDANCNFSM4RPQSZTQ .

alanbork avatar Sep 20 '20 04:09 alanbork

this does not however seem to work; after modetest quits the display returns to the console running at it previous resolution.

Correct. After any application that uses DRM quits, all settings and planes that it had added to the display will be removed, and the frame buffer emulation will be reinstated. Otherwise you'd be leaking resources allocated by now dead applications.

If you start another application whilst that modetest -d command is running in the background, then the new mode should be detected.

6by9 avatar Sep 20 '20 08:09 6by9

Is this a change in the standard? modetest.c seems to imply that it's the app's job to restore the mode:

/ * Before calling drmModeSetCrtc() we also save the current CRTC configuration.

  • This is used in modeset_cleanup() to restore the CRTC to the same mode as was
  • before we changed it.
  • If we don't do this, the screen will stay blank after we exit until another
  • application performs modesetting itself. */

On Sun, Sep 20, 2020 at 1:12 AM 6by9 [email protected] wrote:

this does not however seem to work; after modetest quits the display returns to the console running at it previous resolution.

Correct. After any application that uses DRM quits, all settings and planes that it had added to the display will be removed, and the frame buffer emulation will be reinstated. Otherwise you'd be leaking resources allocated by now dead applications.

If you start another application whilst that modetest -d command is running in the background, then the new mode should be detected.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/raspberrypi/firmware/issues/1470#issuecomment-695758957, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANPGZ5PFF6YYJOO2KEZZT23SGW2OPANCNFSM4RPQSZTQ .

alanbork avatar Sep 20 '20 17:09 alanbork

Is this a change in the standard? modetest.c seems to imply that it's the app's job to restore the mode:

I've not tested it, but it was my understanding. I may be wrong.

6by9 avatar Sep 21 '20 08:09 6by9

Why do you need to change the resolution after boot?

Because I use my Pi as a retro game emulation machine via RetroPie, and it (emulationstation / runcommand) needs the ability to change video modes on-the-fly before launching an emulator (retroarch) to set up the display correctly for the game the user is trying to play. PAL games need a 50Hz mode to be playable without motion judder, whereas NTSC games need a 60Hz mode, and the mode switching must be done (given the entire architecture of RetroPie) by the "runcommand" shell script layer that sits between the "emulationstation" front end and the emulator it's trying to launch. Losing the ability to switch between 50Hz/60Hz video modes on-the-fly from a shell script is thus a complete deal-breaker.

I understand the desire to march forward to a better API and way of doing things, but that march of progress is not being handled well at all. It's like a bull in a china shop, exhibiting zero concern for all the widely-used-and-heavily-relied-upon applications and usage scenarios that already exist out in the wild.

It's already bad enough that the (F)KMS video driver doesn't support 90-degree or 270-degree screen rotation (which used to work on the legacy driver), which completely breaks the ability for people to use 90-degree-rotated displays in situations that require it (such as mounting one of these new LG DualUp 16:18 displays sideways inside an arcade cabinet to get a nice big nearly-4:3 proper LCD display). It just seems like the core Raspbian / Pi developers don't have any clue how critical these features and functionality are for the retro gaming crowd or anyone else with specific video needs. And resorting to using X11 is not an option when the software stack needs to remain as fast and lean as possible to keep precious resources free for the perf-hungry needs of game emulation.

We retro gamers desperately need these fundamental basic capabilities (arbitrary screen rotation, switch video modes freely on the fly, etc) to keep working, without having to fire up X-windows. Please stop breaking things we need.

c0d3h4x0r avatar Aug 06 '22 03:08 c0d3h4x0r