aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i2c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2014-01-25 12:14:45 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-02-13 14:41:36 -0500
commit7d2eadc9b9d4eacc6aa8cc0cb33e05b5a6d30256 (patch)
tree65ad4af48a97e8ed4314ee19934a56173a98c24b /drivers/gpu/drm/i2c
parent2f7f730a4f0fd3376dda9266203f29ceccd0a67f (diff)
drm/i2c: tda998x: check more I/O errors
This patch adds more error checking inn I2C I/O functions. In case of I/O error, this permits to avoid writing in bad controller pages, a bad chipset detection or looping when getting the EDID. 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.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 7df73baf3f9b..9bd336cdb734 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -363,7 +363,7 @@ fail:
363 return 0; 363 return 0;
364} 364}
365 365
366static void 366static int
367set_page(struct tda998x_priv *priv, uint16_t reg) 367set_page(struct tda998x_priv *priv, uint16_t reg)
368{ 368{
369 if (REG2PAGE(reg) != priv->current_page) { 369 if (REG2PAGE(reg) != priv->current_page) {
@@ -372,11 +372,14 @@ set_page(struct tda998x_priv *priv, uint16_t reg)
372 REG_CURPAGE, REG2PAGE(reg) 372 REG_CURPAGE, REG2PAGE(reg)
373 }; 373 };
374 int ret = i2c_master_send(client, buf, sizeof(buf)); 374 int ret = i2c_master_send(client, buf, sizeof(buf));
375 if (ret < 0) 375 if (ret < 0) {
376 dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret); 376 dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret);
377 return ret;
378 }
377 379
378 priv->current_page = REG2PAGE(reg); 380 priv->current_page = REG2PAGE(reg);
379 } 381 }
382 return 0;
380} 383}
381 384
382static int 385static int
@@ -386,7 +389,9 @@ reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt)
386 uint8_t addr = REG2ADDR(reg); 389 uint8_t addr = REG2ADDR(reg);
387 int ret; 390 int ret;
388 391
389 set_page(priv, reg); 392 ret = set_page(priv, reg);
393 if (ret < 0)
394 return ret;
390 395
391 ret = i2c_master_send(client, &addr, sizeof(addr)); 396 ret = i2c_master_send(client, &addr, sizeof(addr));
392 if (ret < 0) 397 if (ret < 0)
@@ -413,18 +418,24 @@ reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt)
413 buf[0] = REG2ADDR(reg); 418 buf[0] = REG2ADDR(reg);
414 memcpy(&buf[1], p, cnt); 419 memcpy(&buf[1], p, cnt);
415 420
416 set_page(priv, reg); 421 ret = set_page(priv, reg);
422 if (ret < 0)
423 return;
417 424
418 ret = i2c_master_send(client, buf, cnt + 1); 425 ret = i2c_master_send(client, buf, cnt + 1);
419 if (ret < 0) 426 if (ret < 0)
420 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); 427 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
421} 428}
422 429
423static uint8_t 430static int
424reg_read(struct tda998x_priv *priv, uint16_t reg) 431reg_read(struct tda998x_priv *priv, uint16_t reg)
425{ 432{
426 uint8_t val = 0; 433 uint8_t val = 0;
427 reg_read_range(priv, reg, &val, sizeof(val)); 434 int ret;
435
436 ret = reg_read_range(priv, reg, &val, sizeof(val));
437 if (ret < 0)
438 return ret;
428 return val; 439 return val;
429} 440}
430 441
@@ -435,7 +446,9 @@ reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
435 uint8_t buf[] = {REG2ADDR(reg), val}; 446 uint8_t buf[] = {REG2ADDR(reg), val};
436 int ret; 447 int ret;
437 448
438 set_page(priv, reg); 449 ret = set_page(priv, reg);
450 if (ret < 0)
451 return;
439 452
440 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); 453 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
441 if (ret < 0) 454 if (ret < 0)
@@ -449,7 +462,9 @@ reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val)
449 uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; 462 uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
450 int ret; 463 int ret;
451 464
452 set_page(priv, reg); 465 ret = set_page(priv, reg);
466 if (ret < 0)
467 return;
453 468
454 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); 469 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
455 if (ret < 0) 470 if (ret < 0)
@@ -459,13 +474,21 @@ reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val)
459static void 474static void
460reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val) 475reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
461{ 476{
462 reg_write(priv, reg, reg_read(priv, reg) | val); 477 int old_val;
478
479 old_val = reg_read(priv, reg);
480 if (old_val >= 0)
481 reg_write(priv, reg, old_val | val);
463} 482}
464 483
465static void 484static void
466reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val) 485reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
467{ 486{
468 reg_write(priv, reg, reg_read(priv, reg) & ~val); 487 int old_val;
488
489 old_val = reg_read(priv, reg);
490 if (old_val >= 0)
491 reg_write(priv, reg, old_val & ~val);
469} 492}
470 493
471static void 494static void
@@ -978,8 +1001,10 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
978 1001
979 /* wait for block read to complete: */ 1002 /* wait for block read to complete: */
980 for (i = 100; i > 0; i--) { 1003 for (i = 100; i > 0; i--) {
981 uint8_t val = reg_read(priv, REG_INT_FLAGS_2); 1004 ret = reg_read(priv, REG_INT_FLAGS_2);
982 if (val & INT_FLAGS_2_EDID_BLK_RD) 1005 if (ret < 0)
1006 return ret;
1007 if (ret & INT_FLAGS_2_EDID_BLK_RD)
983 break; 1008 break;
984 msleep(1); 1009 msleep(1);
985 } 1010 }
@@ -1144,6 +1169,7 @@ tda998x_encoder_init(struct i2c_client *client,
1144 struct drm_encoder_slave *encoder_slave) 1169 struct drm_encoder_slave *encoder_slave)
1145{ 1170{
1146 struct tda998x_priv *priv; 1171 struct tda998x_priv *priv;
1172 int ret;
1147 1173
1148 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 1174 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1149 if (!priv) 1175 if (!priv)
@@ -1172,8 +1198,11 @@ tda998x_encoder_init(struct i2c_client *client,
1172 tda998x_reset(priv); 1198 tda998x_reset(priv);
1173 1199
1174 /* read version: */ 1200 /* read version: */
1175 priv->rev = reg_read(priv, REG_VERSION_LSB) | 1201 ret = reg_read(priv, REG_VERSION_LSB) |
1176 reg_read(priv, REG_VERSION_MSB) << 8; 1202 (reg_read(priv, REG_VERSION_MSB) << 8);
1203 if (ret < 0)
1204 goto fail;
1205 priv->rev = ret;
1177 1206
1178 /* mask off feature bits: */ 1207 /* mask off feature bits: */
1179 priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */ 1208 priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */