diff options
| author | Jean-Francois Moine <moinejf@free.fr> | 2014-11-29 02:57:15 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-12-01 05:49:28 -0500 |
| commit | 6833d26ef823b20acbf9d4afcfd7077e623b302c (patch) | |
| tree | 748928ded0c600bed45b5567437444f23c255fde | |
| parent | ed9a84262a83ab0260325c2f5eae39e441003d55 (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.c | 22 |
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 */ | ||
| 554 | static 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); |
