aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i2c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2014-01-25 12:14:38 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-02-13 14:43:37 -0500
commit12473b7d8e6074c7d4c2816afa6027354ce9a502 (patch)
tree917e727939026122adb26c6001f8ab184696331b /drivers/gpu/drm/i2c
parente47826274e8871bc6b35f82d35aea53db0f4ae31 (diff)
drm/i2c: tda998x: use irq for connection status and EDID read
This patch adds the optional treatment of the tda998x IRQ. The interrupt function is used to know the display connection status without polling and to speedup reading the EDID. The IRQ number and trigger type are defined in the i2c client either by platform data or in the DT. Tested-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/i2c')
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c114
1 files changed, 105 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index fddac4c84c28..c9882246d81f 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/hdmi.h> 20#include <linux/hdmi.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/irq.h>
22#include <sound/asoundef.h> 23#include <sound/asoundef.h>
23 24
24#include <drm/drmP.h> 25#include <drm/drmP.h>
@@ -40,6 +41,10 @@ struct tda998x_priv {
40 u8 vip_cntrl_1; 41 u8 vip_cntrl_1;
41 u8 vip_cntrl_2; 42 u8 vip_cntrl_2;
42 struct tda998x_encoder_params params; 43 struct tda998x_encoder_params params;
44
45 wait_queue_head_t wq_edid;
46 volatile int wq_edid_wait;
47 struct drm_encoder *encoder;
43}; 48};
44 49
45#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) 50#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
@@ -306,11 +311,16 @@ struct tda998x_priv {
306 311
307/* CEC registers: (not paged) 312/* CEC registers: (not paged)
308 */ 313 */
314#define REG_CEC_INTSTATUS 0xee /* read */
315# define CEC_INTSTATUS_CEC (1 << 0)
316# define CEC_INTSTATUS_HDMI (1 << 1)
309#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ 317#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */
310# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) 318# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
311# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) 319# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6)
312# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) 320# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
313# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) 321# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
322#define REG_CEC_RXSHPDINTENA 0xfc /* read/write */
323#define REG_CEC_RXSHPDINT 0xfd /* read */
314#define REG_CEC_RXSHPDLEV 0xfe /* read */ 324#define REG_CEC_RXSHPDLEV 0xfe /* read */
315# define CEC_RXSHPDLEV_RXSENS (1 << 0) 325# define CEC_RXSHPDLEV_RXSENS (1 << 0)
316# define CEC_RXSHPDLEV_HPD (1 << 1) 326# define CEC_RXSHPDLEV_HPD (1 << 1)
@@ -524,6 +534,35 @@ tda998x_reset(struct tda998x_priv *priv)
524 reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24); 534 reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
525} 535}
526 536
537/*
538 * only 2 interrupts may occur: screen plug/unplug and EDID read
539 */
540static irqreturn_t tda998x_irq_thread(int irq, void *data)
541{
542 struct tda998x_priv *priv = data;
543 u8 sta, cec, lvl, flag0, flag1, flag2;
544
545 if (!priv)
546 return IRQ_HANDLED;
547 sta = cec_read(priv, REG_CEC_INTSTATUS);
548 cec = cec_read(priv, REG_CEC_RXSHPDINT);
549 lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
550 flag0 = reg_read(priv, REG_INT_FLAGS_0);
551 flag1 = reg_read(priv, REG_INT_FLAGS_1);
552 flag2 = reg_read(priv, REG_INT_FLAGS_2);
553 DRM_DEBUG_DRIVER(
554 "tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
555 sta, cec, lvl, flag0, flag1, flag2);
556 if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
557 priv->wq_edid_wait = 0;
558 wake_up(&priv->wq_edid);
559 } else if (cec != 0) { /* HPD change */
560 if (priv->encoder && priv->encoder->dev)
561 drm_helper_hpd_irq_event(priv->encoder->dev);
562 }
563 return IRQ_HANDLED;
564}
565
527static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes) 566static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
528{ 567{
529 uint8_t sum = 0; 568 uint8_t sum = 0;
@@ -994,23 +1033,36 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
994 reg_write(priv, REG_DDC_SEGM, segptr); 1033 reg_write(priv, REG_DDC_SEGM, segptr);
995 1034
996 /* enable reading EDID: */ 1035 /* enable reading EDID: */
1036 priv->wq_edid_wait = 1;
997 reg_write(priv, REG_EDID_CTRL, 0x1); 1037 reg_write(priv, REG_EDID_CTRL, 0x1);
998 1038
999 /* flag must be cleared by sw: */ 1039 /* flag must be cleared by sw: */
1000 reg_write(priv, REG_EDID_CTRL, 0x0); 1040 reg_write(priv, REG_EDID_CTRL, 0x0);
1001 1041
1002 /* wait for block read to complete: */ 1042 /* wait for block read to complete: */
1003 for (i = 100; i > 0; i--) { 1043 if (priv->hdmi->irq) {
1004 ret = reg_read(priv, REG_INT_FLAGS_2); 1044 i = wait_event_timeout(priv->wq_edid,
1005 if (ret < 0) 1045 !priv->wq_edid_wait,
1006 return ret; 1046 msecs_to_jiffies(100));
1007 if (ret & INT_FLAGS_2_EDID_BLK_RD) 1047 if (i < 0) {
1008 break; 1048 dev_err(encoder->dev->dev, "read edid wait err %d\n", i);
1009 msleep(1); 1049 return i;
1050 }
1051 } else {
1052 for (i = 10; i > 0; i--) {
1053 msleep(10);
1054 ret = reg_read(priv, REG_INT_FLAGS_2);
1055 if (ret < 0)
1056 return ret;
1057 if (ret & INT_FLAGS_2_EDID_BLK_RD)
1058 break;
1059 }
1010 } 1060 }
1011 1061
1012 if (i == 0) 1062 if (i == 0) {
1063 dev_err(encoder->dev->dev, "read edid timeout\n");
1013 return -ETIMEDOUT; 1064 return -ETIMEDOUT;
1065 }
1014 1066
1015 ret = reg_read_range(priv, REG_EDID_DATA_0, buf, EDID_LENGTH); 1067 ret = reg_read_range(priv, REG_EDID_DATA_0, buf, EDID_LENGTH);
1016 if (ret != EDID_LENGTH) { 1068 if (ret != EDID_LENGTH) {
@@ -1108,7 +1160,13 @@ static int
1108tda998x_encoder_create_resources(struct drm_encoder *encoder, 1160tda998x_encoder_create_resources(struct drm_encoder *encoder,
1109 struct drm_connector *connector) 1161 struct drm_connector *connector)
1110{ 1162{
1111 DBG(""); 1163 struct tda998x_priv *priv = to_tda998x_priv(encoder);
1164
1165 if (priv->hdmi->irq)
1166 connector->polled = DRM_CONNECTOR_POLL_HPD;
1167 else
1168 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
1169 DRM_CONNECTOR_POLL_DISCONNECT;
1112 return 0; 1170 return 0;
1113} 1171}
1114 1172
@@ -1127,6 +1185,13 @@ tda998x_encoder_destroy(struct drm_encoder *encoder)
1127{ 1185{
1128 struct tda998x_priv *priv = to_tda998x_priv(encoder); 1186 struct tda998x_priv *priv = to_tda998x_priv(encoder);
1129 drm_i2c_encoder_destroy(encoder); 1187 drm_i2c_encoder_destroy(encoder);
1188
1189 /* disable all IRQs and free the IRQ handler */
1190 cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1191 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1192 if (priv->hdmi->irq)
1193 free_irq(priv->hdmi->irq, priv);
1194
1130 if (priv->cec) 1195 if (priv->cec)
1131 i2c_unregister_device(priv->cec); 1196 i2c_unregister_device(priv->cec);
1132 kfree(priv); 1197 kfree(priv);
@@ -1186,6 +1251,8 @@ tda998x_encoder_init(struct i2c_client *client,
1186 kfree(priv); 1251 kfree(priv);
1187 return -ENODEV; 1252 return -ENODEV;
1188 } 1253 }
1254
1255 priv->encoder = &encoder_slave->base;
1189 priv->dpms = DRM_MODE_DPMS_OFF; 1256 priv->dpms = DRM_MODE_DPMS_OFF;
1190 1257
1191 encoder_slave->slave_priv = priv; 1258 encoder_slave->slave_priv = priv;
@@ -1242,6 +1309,35 @@ tda998x_encoder_init(struct i2c_client *client,
1242 cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL, 1309 cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
1243 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); 1310 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
1244 1311
1312 /* initialize the optional IRQ */
1313 if (client->irq) {
1314 int irqf_trigger;
1315
1316 /* init read EDID waitqueue */
1317 init_waitqueue_head(&priv->wq_edid);
1318
1319 /* clear pending interrupts */
1320 reg_read(priv, REG_INT_FLAGS_0);
1321 reg_read(priv, REG_INT_FLAGS_1);
1322 reg_read(priv, REG_INT_FLAGS_2);
1323
1324 irqf_trigger =
1325 irqd_get_trigger_type(irq_get_irq_data(client->irq));
1326 ret = request_threaded_irq(client->irq, NULL,
1327 tda998x_irq_thread,
1328 irqf_trigger | IRQF_ONESHOT,
1329 "tda998x", priv);
1330 if (ret) {
1331 dev_err(&client->dev,
1332 "failed to request IRQ#%u: %d\n",
1333 client->irq, ret);
1334 goto fail;
1335 }
1336
1337 /* enable HPD irq */
1338 cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
1339 }
1340
1245 /* enable EDID read irq: */ 1341 /* enable EDID read irq: */
1246 reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); 1342 reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1247 1343