]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
drm/i2c: adv7511: Add HPD support
authorArchit Taneja <architt@codeaurora.org>
Tue, 16 Feb 2016 05:10:56 +0000 (10:40 +0530)
committerKhalid Elmously <khalid.elmously@canonical.com>
Wed, 14 Mar 2018 02:42:09 +0000 (02:42 +0000)
Add Hot Plug detect support for ADV7533. This involves:

1) Enabling the correct HPD interrupt enable registers in
   adv7511_power_on, adv7511_get_modes and adv7533_bridge_attach.
2) Flushing the irq stat registers in adv7511_irq_process only after
   we have called drm_helper_hpd_irq_event.
3) Getting rid of the HPD_ENABLE macro instances.
4) Add a 200 ms sleep in adv7511_get_modes after powering on the
   chip. This seems to be needed when we rely on EDID_READY
   interrupt to start reading EDID.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
drivers/gpu/drm/i2c/adv7511.c

index f123dbf28be45f07a549ab3348792994cdce383f..efb539d60c2c3f1aed9325195032c5841949b199 100644 (file)
@@ -29,8 +29,6 @@ static const int edid_i2c_addr = 0x7e;
 static const int packet_i2c_addr = 0x70;
 static const int cec_i2c_addr = 0x78;
 
-#define HPD_ENABLE     0
-
 static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
 {
        return to_encoder_slave(encoder)->slave_priv;
@@ -448,7 +446,7 @@ static void adv7511_power_on(struct adv7511 *adv7511)
                 * Still, let's be safe and stick to the documentation.
                 */
                regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
-                            ADV7511_INT0_EDID_READY);
+                            ADV7511_INT0_EDID_READY | ADV7511_INT0_HDP);
                regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
                             ADV7511_INT1_DDC_ERROR);
        }
@@ -496,7 +494,6 @@ static void adv7511_power_off(struct adv7511 *adv7511)
  * Interrupt and hotplug detection
  */
 
-#if HPD_ENABLE
 static bool adv7511_hpd(struct adv7511 *adv7511)
 {
        unsigned int irq0;
@@ -514,7 +511,6 @@ static bool adv7511_hpd(struct adv7511 *adv7511)
 
        return false;
 }
-#endif
 
 static void adv7511_hpd_work(struct work_struct *work)
 {
@@ -549,12 +545,12 @@ static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
        if (ret < 0)
                return ret;
 
-       regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
-       regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
-
        if (process_hpd && irq0 & ADV7511_INT0_HDP && adv7511->encoder)
                schedule_work(&adv7511->hpd_work);
 
+       regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+       regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+
        if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
                adv7511->edid_read = true;
 
@@ -686,7 +682,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511,
                                   ADV7511_POWER_POWER_DOWN, 0);
                if (adv7511->i2c_main->irq) {
                        regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
-                                    ADV7511_INT0_EDID_READY);
+                                    ADV7511_INT0_EDID_READY | ADV7511_INT0_HDP);
                        regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
                                     ADV7511_INT1_DDC_ERROR);
                }
@@ -694,6 +690,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511,
                /* Reset the EDID_I2C_ADDR register as it might be cleared */
                regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
                                edid_i2c_addr);
+               msleep(200);
        }
 
        edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
@@ -722,9 +719,7 @@ adv7511_detect(struct adv7511 *adv7511,
 {
        enum drm_connector_status status;
        unsigned int val;
-#if HPD_ENABLE
        bool hpd;
-#endif
        int ret;
 
        ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
@@ -736,7 +731,6 @@ adv7511_detect(struct adv7511 *adv7511,
        else
                status = connector_status_disconnected;
 
-#if HPD_ENABLE
        hpd = adv7511_hpd(adv7511);
 
        /* The chip resets itself when the cable is disconnected, so in case
@@ -755,7 +749,6 @@ adv7511_detect(struct adv7511 *adv7511,
                                   ADV7511_REG_POWER2_HDP_SRC_MASK,
                                   ADV7511_REG_POWER2_HDP_SRC_BOTH);
        }
-#endif
 
        adv7511->status = status;
        return status;
@@ -1017,11 +1010,6 @@ static void adv7533_bridge_post_disable(struct drm_bridge *bridge)
 {
        struct adv7511 *adv = bridge_to_adv7511(bridge);
 
-#if HPD_ENABLE
-       if (!adv7511->powered)
-               return;
-#endif
-
        adv7511_power_off(adv);
 }
 
@@ -1096,9 +1084,7 @@ static int adv7533_bridge_attach(struct drm_bridge *bridge)
                return -ENODEV;
        }
 
-#if HPD_ENABLE
        adv->connector.polled = DRM_CONNECTOR_POLL_HPD;
-#endif
 
        ret = drm_connector_init(bridge->dev, &adv->connector,
                        &adv7533_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
@@ -1111,12 +1097,14 @@ static int adv7533_bridge_attach(struct drm_bridge *bridge)
        drm_connector_register(&adv->connector);
        drm_mode_connector_attach_encoder(&adv->connector, adv->encoder);
 
-#if HPD_ENABLE
        drm_helper_hpd_irq_event(adv->connector.dev);
-#endif
 
        adv7533_attach_dsi(adv);
 
+       /* enable HPD */
+       if (adv->i2c_main->irq)
+               regmap_write(adv->regmap, ADV7511_REG_INT_ENABLE(0),
+                            ADV7511_INT0_HDP);
        return ret;
 }