[GUIDE] Waveshare 11.9"/7.9" DSI LCD Display Configuration for Volumio 4

Hi @nerd, @aluisperezh

I contacted Waveshare support today and explained the situation. I sent them the log files and all additional information. I will provide an update here when I receive a response.

I ran some more tests today. When the system is “cold,” it takes a few tries before the display starts up. This assumes a separate power supply. When the system is “warm,” the display starts up immediately after a restart or a brief power-down. I can work with this for now until Waveshare (hopefully) revises the driver.

Best regards

I wrote WaveShare yesterday too explaining all this. No answer by now.

Regards.

Angel

Hi there,

Waveshare support replied to me today. I should try the booting version with independent power supply for the display and the RPI.

I answered that this booting option works, but it’s not possible to mount the RPI directly to the display. In this case the power supply for the display and the RPI are the same.

I wrote them, that an init delay or retry logic would solve the problem, like @nerd explained a few posts earlier.

I will provide an update here when I receive a response.

Best regards

As I feared, I’ve had no answer from WaveShare.

Regards.

Angel

Hi @nerd @aluisperezh

Waveshare replied today. Here’s what they suggest to do:

You could try the following software-side approaches :

Add a startup delay: Delay loading the touchscreen driver or initializing the screen by a few hundred milliseconds during boot. This allows the panel controller to fully power up before the driver accesses it.
Adjust boot sequence: If possible, configure your system to load the touchscreen driver after other initialization steps, giving the display a bit more time to become ready.

@nerd What do you think about it?

Kind regards

Hey @Mustang65,

Waveshare’s response confirms the diagnosis - they acknowledge it is a timing issue where the panel controller is not ready when the driver initializes. However, their suggestion pushes the fix onto end users rather than correcting the driver.

The proper fix belongs in the ws_touchscreen driver source code. Adding msleep(100) before the first I2C write attempt, or implementing retry logic on failure, would resolve this for all users permanently. This is a trivial modification - perhaps 3-5 lines of code in the driver initialization function.

Their suggestions require users to:

  1. Modify boot sequences
  2. Blacklist kernel modules
  3. Create custom systemd services with delayed module loading
  4. Potentially rebuild initramfs

These workarounds are fragile, may not survive OS updates, and require technical knowledge beyond typical end users. More importantly, every customer with this hardware combination would need to implement the same workaround individually.

Furthermore: A user-side workaround involving delayed driver loading is not viable on Volumio. The display must initialize during early boot to support Volumio’s custom Plymouth splash - this is core branding that displays from initramfs through to user session. Delaying ws_touchscreen would result in a dark screen during the entire boot sequence, defeating the purpose of having a display.

This leaves no practical user-side solution. The fix must come from Waveshare in the driver itself.

My recommendation: Reply to Waveshare emphasizing that the fix should be in the driver, not pushed to each customer. The driver already emits the error message I2C write failed: -5 - adding retry logic at that exact point would resolve the issue upstream. They maintain the overlay and driver in the Raspberry Pi kernel tree; a pull request with this fix would benefit everyone.

Kind Regards,

Hello @nerd and @Mustang65.

I am an end user, yes. My first Linux installation was with 22 diskettes in 1992. I was the first to deployed a Linux server in a Spanish Government departament. And I don’t know how to “add a startup delay” to a driver. I’m sure I could find it if I look around, but it seems to me an incredible answer. Instead of changing a few lines of code (as @nerd has already explained), they leave to us end users the responsability of making THEIR display work, when it should almost be plug-and-play.

I hope there are other display providers we can choose.

Regards.

Angel

Ps. By the way, they didn’t answer a single word to me
Ps2. I had written that my first Linux was in 1989. It was in 1992.

Hi guys,

I will reply to WaveShare support again and make it clear to them that this is not an end-user problem, but a driver problem with their product. I will pass it on as explained by @nerd and then hope for another reply from support.

I will keep you posted.

Kind regards

Hey @Mustang65, @aluisperezh,

A user-side workaround involving delayed driver loading is not viable on Volumio. The display must initialize during early boot to support Volumio’s custom Plymouth splash - this is core branding that displays from initramfs through to user session. Delaying ws_touchscreen would result in a dark screen during the entire boot sequence, defeating the purpose of having a display. This leaves no practical user-side solution. The fix must come from Waveshare in the driver itself.

I examined the actual driver source code. The file is panel-waveshare-dsi.c in the Raspberry Pi kernel tree.

The probe function (line 390) does this immediately after obtaining the I2C handle:

ts->i2c = i2c;

ws_panel_i2c_write(ts, 0xc0, 0x01);
ws_panel_i2c_write(ts, 0xc2, 0x01);
ws_panel_i2c_write(ts, 0xac, 0x01);

Three I2C writes fire instantly with no stabilization delay. The write function itself (line 309):

static void ws_panel_i2c_write(struct ws_panel *ts, u8 reg, u8 val)
{
    int ret;

    ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
    if (ret)
        dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
}

Single attempt. Error logged. No retry. No recovery. Panel stays uninitialized.


How production-quality DSI drivers handle this

For comparison, here is initialization code from a Volumio proprietary DSI panel driver (OEM series, ILITEK-based controller). This demonstrates defensive initialization patterns expected in embedded display drivers.

Retry parameters defined upfront:

#define RETRY_CMD    3      // Retry attempts before failure
#define RETRY_DELAY  120    // Retry wait time in ms

Initialization sequence begins with stabilization delay:

static const struct panel_init_cmd mt1280800a_init_cmd[] = {
    _INIT_DELAY_CMD(5),    // Allow controller to stabilize
    ...

Every critical operation uses retry logic:

retry = 0;
do {
    ret = mipi_dsi_dcs_nop(ctx->dsi);
    if (ret) msleep(RETRY_DELAY);
    ++retry;
}
while (ret && retry < RETRY_CMD);
if (ret < 0) {
    dev_err(panel->dev, "DSI: Failed to return to LP11 state: %d\n", ret);
}

Panel prepare sequence with proper reset timing:

static int mtdsi_prepare(struct drm_panel *panel)
{
    // ... power enable ...
    usleep_range(1000, 2000);

    // Warmup with retry
    retry = 0;
    do {
        ret = mipi_dsi_dcs_nop(ctx->dsi);
        if (ret) msleep(RETRY_DELAY);
        ++retry;
    }
    while (ret && retry < RETRY_CMD);

    usleep_range(1000, 2000);

    // Reset sequence with proper timing
    gpiod_set_value_cansleep(ctx->reset, 0);
    msleep(50);
    gpiod_set_value_cansleep(ctx->reset, 1);
    usleep_range(6000, 10000);

    ret = mtdsi_init_dcs_cmd(ctx);
    // ... error handling with poweroff path ...
}

Error state tracking for recovery:

static atomic_t errorFlag = ATOMIC_INIT(0);

// Set on failure
atomic_set(&errorFlag, 1);

// Clear on success
atomic_set(&errorFlag, 0);

Direct comparison

Aspect Waveshare OEM (Volumio)
Initial delay before I2C None 5ms minimum
Retry attempts 1 (fire and forget) 3 with delay
Retry delay N/A 120ms between attempts
Reset timing None 50ms low, 6-10ms settle
Stabilization delays None Multiple usleep_range/msleep
Error recovery Log and continue broken Track state, proper error path
Error state tracking None Atomic flag for recovery

The Waveshare driver lacks every defensive pattern that production embedded code requires. This is not an edge case - cold boot timing variability is fundamental to embedded systems. Every display driver I have written or reviewed handles this. Waveshare’s code does not.


The fix

Minimum viable fix - one line at line 393:

ts->i2c = i2c;

msleep(100);  /* Allow panel controller to stabilize after power-up */

ws_panel_i2c_write(ts, 0xc0, 0x01);

Proper fix - retry logic in the write function:

static int ws_panel_i2c_write(struct ws_panel *ts, u8 reg, u8 val)
{
    int ret, retries = 3;

    while (retries--) {
        ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
        if (!ret)
            return 0;
        msleep(50);
    }
    dev_err(&ts->i2c->dev, "I2C write failed after retries: %d\n", ret);
    return ret;
}

The required header #include <linux/delay.h> is already present at line 8. Either fix takes under 5 minutes to implement.


Summary

Waveshare told you to implement a delay. The delay needs to go in their driver at line 393, not in customer boot configurations. They have the source code. They maintain the driver. The fix is trivial. Asking customers to work around defective initialization code - when the fix is literally adding msleep(100); - is unacceptable.

The driver is maintained in the Raspberry Pi kernel tree. If Waveshare continues to refuse action, an issue can be raised at GitHub · Where software is built referencing this analysis.

Kind Regards,

Hi @nerd

i just replied to waveshare support. I told them again what you told us. I will keep you posted.

Kind regards

Hey @Mustang65, @aluisperezh,

Build 4.081 has OOKT (Out of kernel tree) module for these displays.

Update and share logs please.

Kind Regards,

Where can we find it? Volumio says it’s up to date and in the OS download page only 4.073 is offered.

Regards.

Angel

Thank you. I forgot it could be a beta…

Regards.

Angel

Ok, installed a fresh 4.073 Volumio, with no addins or configuration. Only changed cmdline.txt and userconfig.txt as per “Scenario 1”. Display working on boot, but no Plymouth.

Updated to 4.081. Plymouth working fine on startup (updating and restarting the system). login with QR Code on screen.

Log for this first boot: http://logs.volumio.org/volumio/APRagtZ.html

Thank you very much, it seems it’s working!!!

Best regards.

Angel.

Ps. I’m turning the system off now. I will test it tomorrow in a cold boot and report back. If there is any other test you want me to do, please tell me.

Hey @aluisperezh,

The log from cold boot will be ideal. This is where defensive init would show its workings.

Kind Regards,

Ok, tomorrow I’ll send it.

Best regards.

Angel

Hi @nerd

I have also updated to 4.081 and will power down until tomorrow morning. Then I will report back here with the log.

Best regards

Hi @nerd

my device was power down over night and I did a cold boot without any problems. The Display started as expected. Here’s my log for the cold start:

http://logs.volumio.org/volumio/sBxNHsO.html

Looks like you did great work!

Thanks and best regards

Hey @Mustang65,

Good news. Clean cold boot, no I2C errors - the panel initialized successfully.

Build 4.081 contains the patched driver with defensive initialization. The stabilization delay and retry logic are working as designed. This is exactly the behavior we expected once the fix was deployed.

Continue monitoring over additional cold boots to build confidence, but this is a strong validation result. The timing bug that caused intermittent dark screens should now be handled gracefully by the driver itself.

Thank you for the overnight cold boot test - this is precisely the scenario where the original driver would fail.

Kind Regards,