]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
OMAPDSS: encoder-tpd12s015: Fix race issue with LS_OE
authorTomi Valkeinen <tomi.valkeinen@ti.com>
Fri, 19 Sep 2014 16:58:57 +0000 (16:58 +0000)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Wed, 4 Feb 2015 10:32:04 +0000 (12:32 +0200)
A race issue has been observed with the encoder-tpd12s015 driver, which
leads to errors when trying to read EDID. This has only now been
observed, as OMAP4 and OMAP5 boards used SoC's GPIOs for LS_OE GPIO. On
dra7-evm boards, the LS_OE is behind a i2c controlled GPIO expander,
which increases the time to set the LS_OE.

This patch simplifies the handling of the LS_OE gpio in the driver by
removing the interrupt handling totally. The only time we actually need
to enable LS_OE is when we are reading the EDID, and thus we can just
set and clear the LS_OE gpio inside the read_edid() function.

This also has the additional benefit of very slightly decreasing the
power consumption.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c

index 7f3e11b16c864d3c2ae2ce8c81487b1e9ed0e25f..990af6baeb0fe9b9ecb8b9e8867eae16489d0fa3 100644 (file)
@@ -29,33 +29,10 @@ struct panel_drv_data {
        int hpd_gpio;
 
        struct omap_video_timings timings;
-
-       struct completion hpd_completion;
 };
 
 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
 
-static irqreturn_t tpd_hpd_irq_handler(int irq, void *data)
-{
-       struct panel_drv_data *ddata = data;
-       bool hpd;
-
-       hpd = gpio_get_value_cansleep(ddata->hpd_gpio);
-
-       dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd);
-
-       if (gpio_is_valid(ddata->ls_oe_gpio)) {
-               if (hpd)
-                       gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
-               else
-                       gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
-       }
-
-       complete_all(&ddata->hpd_completion);
-
-       return IRQ_HANDLED;
-}
-
 static int tpd_connect(struct omap_dss_device *dssdev,
                struct omap_dss_device *dst)
 {
@@ -70,23 +47,10 @@ static int tpd_connect(struct omap_dss_device *dssdev,
        dst->src = dssdev;
        dssdev->dst = dst;
 
-       reinit_completion(&ddata->hpd_completion);
-
        gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1);
        /* DC-DC converter needs at max 300us to get to 90% of 5V */
        udelay(300);
 
-       /*
-        * If there's a cable connected, wait for the hpd irq to trigger,
-        * which turns on the level shifters.
-        */
-       if (gpio_get_value_cansleep(ddata->hpd_gpio)) {
-               unsigned long to;
-               to = wait_for_completion_timeout(&ddata->hpd_completion,
-                               msecs_to_jiffies(250));
-               WARN_ON_ONCE(to == 0);
-       }
-
        return 0;
 }
 
@@ -179,11 +143,20 @@ static int tpd_read_edid(struct omap_dss_device *dssdev,
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
        struct omap_dss_device *in = ddata->in;
+       int r;
 
        if (!gpio_get_value_cansleep(ddata->hpd_gpio))
                return -ENODEV;
 
-       return in->ops.hdmi->read_edid(in, edid, len);
+       if (gpio_is_valid(ddata->ls_oe_gpio))
+               gpio_set_value_cansleep(ddata->ls_oe_gpio, 1);
+
+       r = in->ops.hdmi->read_edid(in, edid, len);
+
+       if (gpio_is_valid(ddata->ls_oe_gpio))
+               gpio_set_value_cansleep(ddata->ls_oe_gpio, 0);
+
+       return r;
 }
 
 static bool tpd_detect(struct omap_dss_device *dssdev)
@@ -309,8 +282,6 @@ static int tpd_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ddata);
 
-       init_completion(&ddata->hpd_completion);
-
        if (dev_get_platdata(&pdev->dev)) {
                r = tpd_probe_pdata(pdev);
                if (r)
@@ -340,13 +311,6 @@ static int tpd_probe(struct platform_device *pdev)
        if (r)
                goto err_gpio;
 
-       r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio),
-                                NULL, tpd_hpd_irq_handler,
-                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-                                IRQF_ONESHOT, "hpd", ddata);
-       if (r)
-               goto err_irq;
-
        dssdev = &ddata->dssdev;
        dssdev->ops.hdmi = &tpd_hdmi_ops;
        dssdev->dev = &pdev->dev;
@@ -365,7 +329,6 @@ static int tpd_probe(struct platform_device *pdev)
 
        return 0;
 err_reg:
-err_irq:
 err_gpio:
        omap_dss_put_device(ddata->in);
        return r;