Skip to content

Commit 7ba76a9

Browse files
committed
drm/panel: waveshare-dsi: Add I2C retry logic for cold boot reliability
The Waveshare DSI panel driver can fail to initialize on cold boot with "I2C write failed: -5" (EIO) errors. This occurs because the panel controller requires time to stabilize after power-up, but the driver attempts I2C communication immediately after obtaining the handle. Warm boots succeed because residual controller state keeps it responsive. Cold boots after extended power-off periods fail intermittently depending on timing conditions (ambient temperature, power supply characteristics). Add defensive initialization: - 100ms stabilization delay before first I2C write in probe - Retry logic (3 attempts, 50ms between retries) for I2C writes - Return value propagation from ws_panel_i2c_write These patterns follow established practice in production embedded panel drivers and resolve the cold boot initialization race. Signed-off-by: Andrew Seredyn <[email protected]>
1 parent a107374 commit 7ba76a9

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

drivers/gpu/drm/panel/panel-waveshare-dsi.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
#define WS_DSI_DRIVER_NAME "ws-ts-dsi"
2626

27+
#define WS_I2C_RETRIES 3 /* Number of retry attempts for I2C operations */
28+
#define WS_I2C_RETRY_DELAY_MS 50 /* Delay between retries in milliseconds */
29+
#define WS_INIT_DELAY_MS 100 /* Initial stabilization delay for panel controller */
30+
2731
struct ws_panel {
2832
struct drm_panel base;
2933
struct mipi_dsi_device *dsi;
@@ -329,13 +333,19 @@ static struct ws_panel *panel_to_ts(struct drm_panel *panel)
329333
return container_of(panel, struct ws_panel, base);
330334
}
331335

332-
static void ws_panel_i2c_write(struct ws_panel *ts, u8 reg, u8 val)
336+
static int ws_panel_i2c_write(struct ws_panel *ts, u8 reg, u8 val)
333337
{
334-
int ret;
338+
int ret, retries = WS_I2C_RETRIES;
335339

336-
ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
337-
if (ret)
338-
dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
340+
while (retries--) {
341+
ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
342+
if (!ret)
343+
return 0;
344+
msleep(WS_I2C_RETRY_DELAY_MS);
345+
}
346+
dev_err(&ts->i2c->dev, "I2C write failed after %d retries: %d\n",
347+
WS_I2C_RETRIES, ret);
348+
return ret;
339349
}
340350

341351
static int ws_panel_disable(struct drm_panel *panel)
@@ -479,6 +489,9 @@ static int ws_panel_probe(struct i2c_client *i2c)
479489

480490
ts->i2c = i2c;
481491

492+
/* Allow panel controller to stabilize after power-up */
493+
msleep(WS_INIT_DELAY_MS);
494+
482495
ws_panel_i2c_write(ts, 0xc0, 0x01);
483496
ws_panel_i2c_write(ts, 0xc2, 0x01);
484497
ws_panel_i2c_write(ts, 0xac, 0x01);

0 commit comments

Comments
 (0)