Skip to content

panel-waveshare-dsi: Reliable initialization failure on cold boot due to missing stabilization delays and retry logic #7240

@m0g13r

Description

@m0g13r

Describe the bug

The current implementation of the panel-waveshare-dsi driver (specifically for DSI-based Waveshare panels using the Goodix/Ilitek controllers) frequently fails to initialize during cold boots. This results in a dark screen or failed touch/panel probe, as the I2C communication is attempted before the panel's internal controller has stabilized.

The driver lacks standard defensive programming patterns required for embedded display hardware, such as power-up delays or retry loops for critical I2C initialization commands.

Steps to reproduce the behaviour

make cold boot :)

Device (s)

Raspberry Pi 5

System

volumio

Logs

No response

Additional context

In drivers/gpu/drm/panel/panel-waveshare-dsi.c, the ws_panel_probe function (line 390) executes several I2C writes immediately after obtaining the handle:
C

ts->i2c = i2c;

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

The ws_panel_i2c_write function (line 309) is a "single-shot" attempt:
C

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);
}

If the panel is still in its power-up cycle, these writes fail, the error is logged, and the panel remains uninitialized. Unlike other production-grade DSI drivers (e.g., those using ILITEK controllers), there is no msleep() to allow for stabilization and no retry logic.
Suggested Fix

A minimum viable fix involves adding a delay before the first I2C write and implementing a retry mechanism in the write function.

  1. Add stabilization delay in probe:
    C

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

  1. Improve ws_panel_i2c_write with retries:
    C

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

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 multiple retries: %d\n", ret);
return ret;

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions