Preserve U-Boot splash through to kernel boot with Colibri-iMX8X

Further to my previous post I’m trying to keep the U-Boot splash on screen until the user space application starts.

Initially U-Boot clears the screen before it jumps to the kernel. I prevent this by commenting the call to video_link_shutdown().

Next when the kernel starts I see random artifacts on screen. I believe this is because the memory previously used for U-Boot framebuffer is re-used by the kernel. Added a reserved-memory node in the Linux device tree to reserve the U-Boot framebuffer memory, which prevents this.

Now I see the screen flicker when the mxsfb-drm driver starts. I have tried quite a few things from this point, but ultimately can’t resolve the flicker:

  • Define a simple-framebuffer node to run before mxsfb-drm starts (and set CONFIG_FB_SIMPLE=y)
    • Doesn’t seem to make much difference, I think the flicker still happens when mxsfb-drm driver starts
  • Patch the simple-framebuffer driver to add a BGR666 format to match my U-Boot (and LCD) behaviour
    • Some unexpected colour changes, so I might have got this wrong, but certainly still flickering
  • Set CONFIG_DRM_FBDEV_EMULATION=n to delay most initialization until the application prompts a plane update
    • Doesn’t make much difference on its own
  • Conditionally skip the clock disable in the first call to mxsfb_irq_disable()
    • Alongside disabling FBDEV_EMULATION this delays the flicker until the application starts
  • Conditionally skip the first mxsfb_crtc_atomic_enable()
    • This ‘works’ in that it prevents the flicker but seems very fragile. If I restart the application then the output is often misaligned.

I have seen related posts on the forum such as this one and have tried suggestions like setting bootargs

Here are my Linux and U-Boot device trees, which I think are compatible. Particularly the lcdif and panel definitions.
linux.dts (144.7 KB)
u-boot.dts (117.2 KB)

Does anyone have any suggestions to resolve this, either from my attempts or their own experience?

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello! Thank you for your detailed description and the steps you have already taken. Seamlessly preserving the U-Boot splash screen until your user-space application takes over—especially on i.MX8X with the mxsfb-drm driver and a parallel LCD—can be tricky. You’ve already investigated most of the best-practice options. Let me summarize and add a couple of further suggestions based on the available Toradex documentation and general practices:

Key Steps and Considerations

1. U-Boot Splash Persistence

You’ve already kept the framebuffer content alive by preventing U-Boot from clearing the display buffer (reference), and you’ve also reserved the memory region in the device tree to prevent overwrite by the kernel—this is correct.

2. ** simple-framebuffer Handoff**

Adding a simple-framebuffer node in your Linux device tree is the standard method to pass the splash image from U-Boot to the kernel. Ensure these parameters all match exactly:

  • Address
  • Format (pixel order, depth)
  • Resolution, stride

Any mismatch—especially with BGR666 or custom formats—could cause color or flickering issues. If you had to patch simple-framebuffer for BGR666 support, this increases the risk of format mismatch and flicker.

Tip:

Check that U-Boot and Linux both write and read the framebuffer in precisely the same format and memory alignment. Otherwise, the start of the mxsfb-drm driver may flush or reinitialize the controller, showing artifacts.

3. Disabling Kernel Console Output

Make sure that kernel messages are not being printed to the screen, as these can cause early framebuffers to be invalidated or redrawn (reference). In your U-Boot environment, remove any console=tty1 or similar assignments in your kernel command line:

setenv defargs
saveenv

Or specifically omit framebuffer consoles.

4. DRM/FBDEV Interplay

DRM subsystem initialization often resets the display hardware when starting, which can cause the flicker you see. Setting CONFIG_DRM_FBDEV_EMULATION=n may help, but, as you’ve observed, the flicker comes back when DRM first takes over.

5. Panel Power/Reset Sequence

While direct hardware modification is not advised, review your device tree to ensure:

  • Any panel reset-gpios or enable-gpios are not explicitly toggled by Linux.
  • The Linux panel driver does not trigger unnecessary resets unless strictly required.

6. Try a “Dummy” Panel Until App Launch

If the above does not work, consider keeping the simple-framebuffer node active until your application is ready, and only then load/enable the mxsfb-drm and panel drivers. This could be done by delaying the DRM-related modules from loading until your application startup (e.g., disabling the relevant device tree node via status = "disabled"; and re-enabling via overlays or device-tree fragment load at runtime—but this is advanced and not always practical on i.MX8X mainline).

7. Avoid Multiple Initializations

The instability you see when “skipping clock disable” or “CRTC atomic enable” likely results from the state getting out of sync if the hardware/driver expects clean resets. That approach may create new, subtle issues down the line.


Summary of Best Practices

  • Perfectly match framebuffer formats and addresses between U-Boot and Linux.
  • Use a simple-framebuffer node and keep mxsfb-drm idle until your app is ready—if possible.
  • Prevent the kernel from writing to framebuffer before your app starts (disable console output).
  • Do NOT patch DRM/mxsfb/workflow with conditional disables—this usually leads to fragility.

If you’ve done all the above and still see artifacts, it may be an inherent limitation in how the mxsfb-drm driver resets hardware or sequences clocking. For some hardware generations, completely seamless transition is not possible until the in-kernel driver handoff becomes more “handoff aware.”

You might find these resources helpful for additional context and configuration examples:

If you are able to share the relevant sections of your device trees here (panel/lcdif/simple-framebuffer nodes), I can check for format or configuration mismatches that could be tweaked for stability.

Best regards,
Toradex AI Assistant.

There are no enable-gpios or reset-gpios defined.
I have CONFIG_FRAMEBUFFER_CONSOLE disabled to prevent kernel console output.

I have attempted to match framebuffer formats and addresses between U-Boot and Linux, both with and without the bgr666 modifications, but would appreciate if anyone can sanity-check that in my dts files.

Narrowing things down a bit further, I did find a difference between the simple-framebuffer and mxsfb. Even with format=“bgr666” the mxsfb framebuffer is still 32bpp, so my simple-framebuffer stride was wrong.

Unfortunately fixing that didn’t change the behaviour.
The output of fbset -fb /dev/fbX is identical for simplefb and mxsfb.

Inspecting registers manually before and after mxsfb loads (by blacklisting it in bootargs, then later calling modprobe directly) I see a few changes to LCDIF_CTRL1 and LCDIF_CTRL2.
I’m not completely sure this is relevant and its leading me back into making changes to the MXSFB driver, so I’m open to any other suggestions.

I eventually got this working.

First I believe there is a bug in the U-Boot MXSFB driver.
It is interpreting the pixelclk-active property incorrectly and inverting LCDIF_VDCTRL0.DOTCLK_POL

After resolving the differences between simple-framebuffer and mxsfb-drm (fbset and devmem2 were particularly useful here) I did end up patching the mxsfb-drm driver to check whether register writes are necessary or if U-Boot had already set them correctly.
I also skipped a few parts of the initialisation that had already been done, particularly the initial software reset and the first plane_update.

A useful set of bootargs if anyone else is doing similar debugging:
modprobe.blacklist=mxsfb drm.debug=0x1ff log_buf_len=1M
Turns on some verbose logging from the DRM subsystem and delays loading the mxsfb driver until an explicit modprobe mxsfb command.

I won’t post my exact patches because they’re quite specific to the LCD I’m using.

1 Like