Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i2c: tda998x: add CEC support

The TDA998x is a HDMI transmitter with a TDA9950 CEC engine integrated
onto the same die. Add support for the TDA9950 CEC engine to the
TDA998x driver.

Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

+187 -9
+1
drivers/gpu/drm/i2c/Kconfig
··· 22 22 config DRM_I2C_NXP_TDA998X 23 23 tristate "NXP Semiconductors TDA998X HDMI encoder" 24 24 default m if DRM_TILCDC 25 + select CEC_CORE if CEC_NOTIFIER 25 26 select SND_SOC_HDMI_CODEC if SND_SOC 26 27 help 27 28 Support for NXP Semiconductors TDA998X HDMI encoders.
+186 -9
drivers/gpu/drm/i2c/tda998x_drv.c
··· 16 16 */ 17 17 18 18 #include <linux/component.h> 19 + #include <linux/gpio/consumer.h> 19 20 #include <linux/hdmi.h> 20 21 #include <linux/module.h> 22 + #include <linux/platform_data/tda9950.h> 21 23 #include <linux/irq.h> 22 24 #include <sound/asoundef.h> 23 25 #include <sound/hdmi-codec.h> ··· 30 28 #include <drm/drm_edid.h> 31 29 #include <drm/drm_of.h> 32 30 #include <drm/i2c/tda998x.h> 31 + 32 + #include <media/cec-notifier.h> 33 33 34 34 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 35 35 ··· 59 55 struct platform_device *audio_pdev; 60 56 struct mutex audio_mutex; 61 57 58 + struct mutex edid_mutex; 62 59 wait_queue_head_t wq_edid; 63 60 volatile int wq_edid_wait; 64 61 ··· 72 67 struct drm_connector connector; 73 68 74 69 struct tda998x_audio_port audio_port[2]; 70 + struct tda9950_glue cec_glue; 71 + struct gpio_desc *calib; 72 + struct cec_notifier *cec_notify; 75 73 }; 76 74 77 75 #define conn_to_tda998x_priv(x) \ ··· 353 345 #define REG_CEC_INTSTATUS 0xee /* read */ 354 346 # define CEC_INTSTATUS_CEC (1 << 0) 355 347 # define CEC_INTSTATUS_HDMI (1 << 1) 348 + #define REG_CEC_CAL_XOSC_CTRL1 0xf2 349 + # define CEC_CAL_XOSC_CTRL1_ENA_CAL BIT(0) 350 + #define REG_CEC_DES_FREQ2 0xf5 351 + # define CEC_DES_FREQ2_DIS_AUTOCAL BIT(7) 352 + #define REG_CEC_CLK 0xf6 353 + # define CEC_CLK_FRO 0x11 356 354 #define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ 357 355 # define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) 358 356 # define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) ··· 373 359 # define CEC_RXSHPDLEV_HPD (1 << 1) 374 360 375 361 #define REG_CEC_ENAMODS 0xff /* read/write */ 362 + # define CEC_ENAMODS_EN_CEC_CLK (1 << 7) 376 363 # define CEC_ENAMODS_DIS_FRO (1 << 6) 377 364 # define CEC_ENAMODS_DIS_CCLK (1 << 5) 378 365 # define CEC_ENAMODS_EN_RXSENS (1 << 2) ··· 430 415 } 431 416 432 417 return val; 418 + } 419 + 420 + static void cec_enamods(struct tda998x_priv *priv, u8 mods, bool enable) 421 + { 422 + int val = cec_read(priv, REG_CEC_ENAMODS); 423 + 424 + if (val < 0) 425 + return; 426 + 427 + if (enable) 428 + val |= mods; 429 + else 430 + val &= ~mods; 431 + 432 + cec_write(priv, REG_CEC_ENAMODS, val); 433 + } 434 + 435 + static void tda998x_cec_set_calibration(struct tda998x_priv *priv, bool enable) 436 + { 437 + if (enable) { 438 + u8 val; 439 + 440 + cec_write(priv, 0xf3, 0xc0); 441 + cec_write(priv, 0xf4, 0xd4); 442 + 443 + /* Enable automatic calibration mode */ 444 + val = cec_read(priv, REG_CEC_DES_FREQ2); 445 + val &= ~CEC_DES_FREQ2_DIS_AUTOCAL; 446 + cec_write(priv, REG_CEC_DES_FREQ2, val); 447 + 448 + /* Enable free running oscillator */ 449 + cec_write(priv, REG_CEC_CLK, CEC_CLK_FRO); 450 + cec_enamods(priv, CEC_ENAMODS_DIS_FRO, false); 451 + 452 + cec_write(priv, REG_CEC_CAL_XOSC_CTRL1, 453 + CEC_CAL_XOSC_CTRL1_ENA_CAL); 454 + } else { 455 + cec_write(priv, REG_CEC_CAL_XOSC_CTRL1, 0); 456 + } 457 + } 458 + 459 + /* 460 + * Calibration for the internal oscillator: we need to set calibration mode, 461 + * and then pulse the IRQ line low for a 10ms ± 1% period. 462 + */ 463 + static void tda998x_cec_calibration(struct tda998x_priv *priv) 464 + { 465 + struct gpio_desc *calib = priv->calib; 466 + 467 + mutex_lock(&priv->edid_mutex); 468 + if (priv->hdmi->irq > 0) 469 + disable_irq(priv->hdmi->irq); 470 + gpiod_direction_output(calib, 1); 471 + tda998x_cec_set_calibration(priv, true); 472 + 473 + local_irq_disable(); 474 + gpiod_set_value(calib, 0); 475 + mdelay(10); 476 + gpiod_set_value(calib, 1); 477 + local_irq_enable(); 478 + 479 + tda998x_cec_set_calibration(priv, false); 480 + gpiod_direction_input(calib); 481 + if (priv->hdmi->irq > 0) 482 + enable_irq(priv->hdmi->irq); 483 + mutex_unlock(&priv->edid_mutex); 484 + } 485 + 486 + static int tda998x_cec_hook_init(void *data) 487 + { 488 + struct tda998x_priv *priv = data; 489 + struct gpio_desc *calib; 490 + 491 + calib = gpiod_get(&priv->hdmi->dev, "nxp,calib", GPIOD_ASIS); 492 + if (IS_ERR(calib)) { 493 + dev_warn(&priv->hdmi->dev, "failed to get calibration gpio: %ld\n", 494 + PTR_ERR(calib)); 495 + return PTR_ERR(calib); 496 + } 497 + 498 + priv->calib = calib; 499 + 500 + return 0; 501 + } 502 + 503 + static void tda998x_cec_hook_exit(void *data) 504 + { 505 + struct tda998x_priv *priv = data; 506 + 507 + gpiod_put(priv->calib); 508 + priv->calib = NULL; 509 + } 510 + 511 + static int tda998x_cec_hook_open(void *data) 512 + { 513 + struct tda998x_priv *priv = data; 514 + 515 + cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, true); 516 + tda998x_cec_calibration(priv); 517 + 518 + return 0; 519 + } 520 + 521 + static void tda998x_cec_hook_release(void *data) 522 + { 523 + struct tda998x_priv *priv = data; 524 + 525 + cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, false); 433 526 } 434 527 435 528 static int ··· 780 657 sta, cec, lvl, flag0, flag1, flag2); 781 658 782 659 if (cec & CEC_RXSHPDINT_HPD) { 783 - if (lvl & CEC_RXSHPDLEV_HPD) 660 + if (lvl & CEC_RXSHPDLEV_HPD) { 784 661 tda998x_edid_delay_start(priv); 785 - else 662 + } else { 786 663 schedule_work(&priv->detect_work); 664 + cec_notifier_set_phys_addr(priv->cec_notify, 665 + CEC_PHYS_ADDR_INVALID); 666 + } 787 667 788 668 handled = true; 789 669 } ··· 1107 981 if (connector->edid_blob_ptr) { 1108 982 struct edid *edid = (void *)connector->edid_blob_ptr->data; 1109 983 984 + cec_notifier_set_phys_addr_from_edid(priv->cec_notify, edid); 985 + 1110 986 priv->sink_has_audio = drm_detect_monitor_audio(edid); 1111 987 } else { 1112 988 priv->sink_has_audio = false; ··· 1152 1024 offset = (blk & 1) ? 128 : 0; 1153 1025 segptr = blk / 2; 1154 1026 1027 + mutex_lock(&priv->edid_mutex); 1028 + 1155 1029 reg_write(priv, REG_DDC_ADDR, 0xa0); 1156 1030 reg_write(priv, REG_DDC_OFFS, offset); 1157 1031 reg_write(priv, REG_DDC_SEGM_ADDR, 0x60); ··· 1173 1043 msecs_to_jiffies(100)); 1174 1044 if (i < 0) { 1175 1045 dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i); 1176 - return i; 1046 + ret = i; 1047 + goto failed; 1177 1048 } 1178 1049 } else { 1179 1050 for (i = 100; i > 0; i--) { 1180 1051 msleep(1); 1181 1052 ret = reg_read(priv, REG_INT_FLAGS_2); 1182 1053 if (ret < 0) 1183 - return ret; 1054 + goto failed; 1184 1055 if (ret & INT_FLAGS_2_EDID_BLK_RD) 1185 1056 break; 1186 1057 } ··· 1189 1058 1190 1059 if (i == 0) { 1191 1060 dev_err(&priv->hdmi->dev, "read edid timeout\n"); 1192 - return -ETIMEDOUT; 1061 + ret = -ETIMEDOUT; 1062 + goto failed; 1193 1063 } 1194 1064 1195 1065 ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length); 1196 1066 if (ret != length) { 1197 1067 dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n", 1198 1068 blk, ret); 1199 - return ret; 1069 + goto failed; 1200 1070 } 1201 1071 1202 - return 0; 1072 + ret = 0; 1073 + 1074 + failed: 1075 + mutex_unlock(&priv->edid_mutex); 1076 + return ret; 1203 1077 } 1204 1078 1205 1079 static int tda998x_connector_get_modes(struct drm_connector *connector) ··· 1559 1423 cancel_work_sync(&priv->detect_work); 1560 1424 1561 1425 i2c_unregister_device(priv->cec); 1426 + 1427 + if (priv->cec_notify) 1428 + cec_notifier_put(priv->cec_notify); 1562 1429 } 1563 1430 1564 1431 /* I2C driver functions */ ··· 1611 1472 static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) 1612 1473 { 1613 1474 struct device_node *np = client->dev.of_node; 1475 + struct i2c_board_info cec_info; 1614 1476 u32 video; 1615 1477 int rev_lo, rev_hi, ret; 1616 1478 1617 1479 mutex_init(&priv->mutex); /* protect the page access */ 1618 1480 mutex_init(&priv->audio_mutex); /* protect access from audio thread */ 1481 + mutex_init(&priv->edid_mutex); 1619 1482 init_waitqueue_head(&priv->edid_delay_waitq); 1620 1483 timer_setup(&priv->edid_delay_timer, tda998x_edid_delay_done, 0); 1621 1484 INIT_WORK(&priv->detect_work, tda998x_detect_work); ··· 1705 1564 1706 1565 irq_flags = 1707 1566 irqd_get_trigger_type(irq_get_irq_data(client->irq)); 1567 + 1568 + priv->cec_glue.irq_flags = irq_flags; 1569 + 1708 1570 irq_flags |= IRQF_SHARED | IRQF_ONESHOT; 1709 1571 ret = request_threaded_irq(client->irq, NULL, 1710 1572 tda998x_irq_thread, irq_flags, ··· 1723 1579 cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD); 1724 1580 } 1725 1581 1726 - priv->cec = i2c_new_dummy(client->adapter, priv->cec_addr); 1582 + priv->cec_notify = cec_notifier_get(&client->dev); 1583 + if (!priv->cec_notify) { 1584 + ret = -ENOMEM; 1585 + goto fail; 1586 + } 1587 + 1588 + priv->cec_glue.parent = &client->dev; 1589 + priv->cec_glue.data = priv; 1590 + priv->cec_glue.init = tda998x_cec_hook_init; 1591 + priv->cec_glue.exit = tda998x_cec_hook_exit; 1592 + priv->cec_glue.open = tda998x_cec_hook_open; 1593 + priv->cec_glue.release = tda998x_cec_hook_release; 1594 + 1595 + /* 1596 + * Some TDA998x are actually two I2C devices merged onto one piece 1597 + * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter 1598 + * with a slightly modified TDA9950 CEC device. The CEC device 1599 + * is at the TDA9950 address, with the address pins strapped across 1600 + * to the TDA998x address pins. Hence, it always has the same 1601 + * offset. 1602 + */ 1603 + memset(&cec_info, 0, sizeof(cec_info)); 1604 + strlcpy(cec_info.type, "tda9950", sizeof(cec_info.type)); 1605 + cec_info.addr = priv->cec_addr; 1606 + cec_info.platform_data = &priv->cec_glue; 1607 + cec_info.irq = client->irq; 1608 + 1609 + priv->cec = i2c_new_device(client->adapter, &cec_info); 1727 1610 if (!priv->cec) { 1728 1611 ret = -ENODEV; 1729 1612 goto fail; ··· 1780 1609 return 0; 1781 1610 1782 1611 fail: 1612 + /* if encoder_init fails, the encoder slave is never registered, 1613 + * so cleanup here: 1614 + */ 1615 + if (priv->cec) 1616 + i2c_unregister_device(priv->cec); 1617 + if (priv->cec_notify) 1618 + cec_notifier_put(priv->cec_notify); 1783 1619 if (client->irq) 1784 1620 free_irq(client->irq, priv); 1785 1621 err_irq: 1786 - i2c_unregister_device(priv->cec); 1787 1622 return ret; 1788 1623 } 1789 1624