aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2014-11-29 02:57:15 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-12-01 05:49:28 -0500
commit6833d26ef823b20acbf9d4afcfd7077e623b302c (patch)
tree748928ded0c600bed45b5567437444f23c255fde
parented9a84262a83ab0260325c2f5eae39e441003d55 (diff)
drm: tda998x: Fix EDID read timeout on HDMI connect
When the HDMI cable is disconnected and reconnected, EDID reading is called too early raising a EDID read timeout. This patch uses the system work queue to delay the notification of the HDMI connect/disconnect event. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 6795f094f737..98f3c4dd7375 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -33,6 +33,7 @@ struct tda998x_priv {
33 struct i2c_client *cec; 33 struct i2c_client *cec;
34 struct i2c_client *hdmi; 34 struct i2c_client *hdmi;
35 struct mutex mutex; 35 struct mutex mutex;
36 struct delayed_work dwork;
36 uint16_t rev; 37 uint16_t rev;
37 uint8_t current_page; 38 uint8_t current_page;
38 int dpms; 39 int dpms;
@@ -549,6 +550,17 @@ tda998x_reset(struct tda998x_priv *priv)
549 reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24); 550 reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
550} 551}
551 552
553/* handle HDMI connect/disconnect */
554static void tda998x_hpd(struct work_struct *work)
555{
556 struct delayed_work *dwork = to_delayed_work(work);
557 struct tda998x_priv *priv =
558 container_of(dwork, struct tda998x_priv, dwork);
559
560 if (priv->encoder && priv->encoder->dev)
561 drm_kms_helper_hotplug_event(priv->encoder->dev);
562}
563
552/* 564/*
553 * only 2 interrupts may occur: screen plug/unplug and EDID read 565 * only 2 interrupts may occur: screen plug/unplug and EDID read
554 */ 566 */
@@ -572,8 +584,7 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data)
572 priv->wq_edid_wait = 0; 584 priv->wq_edid_wait = 0;
573 wake_up(&priv->wq_edid); 585 wake_up(&priv->wq_edid);
574 } else if (cec != 0) { /* HPD change */ 586 } else if (cec != 0) { /* HPD change */
575 if (priv->encoder && priv->encoder->dev) 587 schedule_delayed_work(&priv->dwork, HZ/10);
576 drm_helper_hpd_irq_event(priv->encoder->dev);
577 } 588 }
578 return IRQ_HANDLED; 589 return IRQ_HANDLED;
579} 590}
@@ -1183,8 +1194,10 @@ static void tda998x_destroy(struct tda998x_priv *priv)
1183 /* disable all IRQs and free the IRQ handler */ 1194 /* disable all IRQs and free the IRQ handler */
1184 cec_write(priv, REG_CEC_RXSHPDINTENA, 0); 1195 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1185 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 1196 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1186 if (priv->hdmi->irq) 1197 if (priv->hdmi->irq) {
1187 free_irq(priv->hdmi->irq, priv); 1198 free_irq(priv->hdmi->irq, priv);
1199 cancel_delayed_work_sync(&priv->dwork);
1200 }
1188 1201
1189 i2c_unregister_device(priv->cec); 1202 i2c_unregister_device(priv->cec);
1190} 1203}
@@ -1338,8 +1351,9 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv)
1338 if (client->irq) { 1351 if (client->irq) {
1339 int irqf_trigger; 1352 int irqf_trigger;
1340 1353
1341 /* init read EDID waitqueue */ 1354 /* init read EDID waitqueue and HDP work */
1342 init_waitqueue_head(&priv->wq_edid); 1355 init_waitqueue_head(&priv->wq_edid);
1356 INIT_DELAYED_WORK(&priv->dwork, tda998x_hpd);
1343 1357
1344 /* clear pending interrupts */ 1358 /* clear pending interrupts */
1345 reg_read(priv, REG_INT_FLAGS_0); 1359 reg_read(priv, REG_INT_FLAGS_0);