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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions