Soon after I set up my Rockpro64 board, Peter Robinson told me about an annoying bug that happened on machines with a Rockchip SoC.
The problem was that the framebuffer console just went away after GRUB booted the Linux kernel. We started looking at this and Peter mentioned the following data points:
- Enabling early console output on the framebuffer registered by the
efifb
driver (earlycon=efifb efi=debug
) would get some output but at some point everything would just go blank. - The display worked when passing
fbcon=map:1
and people were using that as a workaround. - Preventing the
efifb
driver to be loaded (modprobe.blacklist=efifb
) would also make things to work.
So the issue seemed to be related to the efifb
driver somehow but wasn’t clear what was happening.
What this driver does is to register a framebuffer device that relies on the video output configured by the firmware/bootloader (using the EFI Graphics Output Protocol) until a real driver takes over an re-initializes the display controller and other IP blocks needed for video output.
I read The Framebuffer device and The Framebuffer Console sections in the Linux documentation to get more familiar about how this is supposed to work.
What happens is that the framebuffer console is bound by default to the first framebuffer registered, which is the one registered by the efifb
driver.
Later, the rockchipdrm
driver is probed and a second framebuffer registered by the DRM fbdev emulation layer but the frame buffer console is still bound to the first frame buffer, that’s using the EFI GOP but this gets destroyed when the kernel re-initializes the display controller and related IP blocks (IOMMU, clocks, power domains, etc).
So why are users left with a blank framebuffer? It’s because the framebuffer is registered but it’s not attached to the console.
Once the problem was understood, it was easy to solve it. The DRM subsystem provides a drm_aperture_remove_framebuffers()
helper function to remove any existing drivers that may own the framebuffer memory, but the rockchipdrm
driver was not using this helper.
The proposed fix (that landed in v5.14-rc1) then is for the rockchipdrm
driver to call the helper to detach any existing early framebuffer before registering its own.
After doing that, the early framebuffer is unbound from the framebuffer console and the one registered by the rockchipdrm
driver takes over:
[ 40.752420] fb0: switching to rockchip-drm-fb from EFI VGA