diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-09-19 16:58:57 +0000 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-02-04 12:32:04 +0200 |
commit | a87a6d6b09de3118e5679c2057b99b7791b7673b (patch) | |
tree | 669887b685004b13504cde0e768be5f8844330fd | |
parent | fa0c52ab232656d5a730eba73b5e37c70acb78db (diff) | |
download | linux-a87a6d6b09de3118e5679c2057b99b7791b7673b.tar.bz2 |
OMAPDSS: encoder-tpd12s015: Fix race issue with LS_OE
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>
-rw-r--r-- | drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c | 57 |
1 files changed, 10 insertions, 47 deletions
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c index 7f3e11b16c86..990af6baeb0f 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c @@ -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; |