Implement a way to determine when the panel is connected. This is done by reading REG_ID through I2C. We consider the panel as disconnect until we retrieve a valid ID. Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxx> --- .../gpu/drm/panel/panel-raspberrypi-touchscreen.c | 62 ++++++++++++++++++---- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c index d964d454e4ae..e65caec590d4 100644 --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -196,6 +196,7 @@ struct rpi_touchscreen { struct drm_panel base; struct mipi_dsi_device *dsi; struct i2c_client *i2c; + bool connected; }; static const struct drm_display_mode rpi_touchscreen_modes[] = { @@ -255,6 +256,9 @@ static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) mipi_dsi_dcs_write_buffer(ts->dsi, msg, sizeof(msg)); #else + if (!ts->connected) + return 0; + rpi_touchscreen_i2c_write(ts, REG_WR_ADDRH, reg >> 8); rpi_touchscreen_i2c_write(ts, REG_WR_ADDRL, reg); rpi_touchscreen_i2c_write(ts, REG_WRITEH, val >> 8); @@ -268,6 +272,9 @@ static int rpi_touchscreen_disable(struct drm_panel *panel) { struct rpi_touchscreen *ts = panel_to_ts(panel); + if (!ts->connected) + return 0; + rpi_touchscreen_i2c_write(ts, REG_PWM, 0); rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); @@ -286,6 +293,9 @@ static int rpi_touchscreen_enable(struct drm_panel *panel) struct rpi_touchscreen *ts = panel_to_ts(panel); int i; + if (!ts->connected) + return 0; + rpi_touchscreen_i2c_write(ts, REG_POWERON, 1); /* Wait for nPWRDWN to go low to indicate poweron is done. */ for (i = 0; i < 100; i++) { @@ -330,6 +340,10 @@ static int rpi_touchscreen_get_modes(struct drm_panel *panel) struct drm_device *drm = panel->drm; unsigned int i, num = 0; static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; + struct rpi_touchscreen *ts = panel_to_ts(panel); + + if (!ts->connected) + return 0; for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) { const struct drm_display_mode *m = &rpi_touchscreen_modes[i]; @@ -362,7 +376,34 @@ static int rpi_touchscreen_get_modes(struct drm_panel *panel) return num; } +static int rpi_touchscreen_detect(struct drm_panel *panel) +{ + struct rpi_touchscreen *ts = panel_to_ts(panel); + int ver; + + if (ts->connected) + return connector_status_connected; + + ver = rpi_touchscreen_i2c_read(ts, REG_ID); + switch (ver) { + case 0xde: /* ver 1 */ + case 0xc3: /* ver 2 */ + ts->connected = true; + + /* Turn off at boot, so we can cleanly sequence powering on. */ + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); + + return connector_status_connected; + + default: + break; + } + + return connector_status_disconnected; +} + static const struct drm_panel_funcs rpi_touchscreen_funcs = { + .detect = rpi_touchscreen_detect, .disable = rpi_touchscreen_disable, .unprepare = rpi_touchscreen_noop, .prepare = rpi_touchscreen_noop, @@ -393,22 +434,24 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, ts->i2c = i2c; ver = rpi_touchscreen_i2c_read(ts, REG_ID); - if (ver < 0) { - dev_err(dev, "Atmel I2C read failed: %d\n", ver); - return -ENODEV; - } - switch (ver) { case 0xde: /* ver 1 */ case 0xc3: /* ver 2 */ + ts->connected = true; + + /* Turn off at boot, so we can cleanly sequence powering on. */ + rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); break; default: - dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver); - return -ENODEV; + if (ver < 0) + dev_err(dev, "Atmel I2C read failed: %d\n", ver); + else + dev_err(dev, + "Unknown Atmel firmware revision: 0x%02x\n", + ver); + break; } - /* Turn off at boot, so we can cleanly sequence powering on. */ - rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); /* Look up the DSI host. It needs to probe before we do. */ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); @@ -432,6 +475,7 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, ts->base.dev = dev; ts->base.funcs = &rpi_touchscreen_funcs; + ts->base.polled = DRM_CONNECTOR_POLL_CONNECT; /* This appears last, as it's what will unblock the DSI host * driver's component bind function. -- 2.14.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel