From fa6b527bedca77a6fbff01f53fc851a76d665bc6 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 26 Oct 2012 17:54:01 -0700 Subject: [PATCH] CHROMIUM: drm: exynos: optional DP hotplug on a GPIO MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Allow to setup the Display Port hotplug detection on a vanilla GPIO instead of the dedicated DP_HPD pin. Signed-off-by: Vincent Palatin BUG=chrome-os-partner:14491 TEST=boot on Spring, see the display coming up automatically. Change-Id: I8eaba89bff0fcdc56d05abf769d7097df05807e1 Reviewed-on: https://gerrit.chromium.org/gerrit/36825 Reviewed-by: Stéphane Marchesin Commit-Ready: Vincent Palatin Tested-by: Vincent Palatin --- drivers/gpu/drm/exynos/exynos_dp_core.c | 30 ++++++++++++++++++++----- drivers/gpu/drm/exynos/exynos_dp_core.h | 1 + drivers/gpu/drm/exynos/exynos_dp_reg.c | 15 +++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index c108b17ddcfc..2b58af154d04 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -981,6 +982,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) struct exynos_dp_platdata *pdata; int ret = 0; + int irqflags; pdata = pdev->dev.platform_data; if (!pdata) { @@ -1029,11 +1031,23 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) goto err_req_region; } - dp->irq = platform_get_irq(pdev, 0); - if (dp->irq == -ENXIO) { + if (gpio_is_valid(pdata->hpd_gpio)) { + dp->hpd_gpio = pdata->hpd_gpio; + ret = gpio_request_one(dp->hpd_gpio, GPIOF_IN, "dp_hpd"); + if (ret) + goto err_ioremap; + dp->irq = gpio_to_irq(dp->hpd_gpio); + irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + } else { + dp->hpd_gpio = -ENODEV; + dp->irq = platform_get_irq(pdev, 0); + irqflags = 0; + } + + if (dp->irq < 0) { dev_err(&pdev->dev, "failed to get irq\n"); ret = -ENODEV; - goto err_ioremap; + goto err_gpio; } dp->training_type = pdata->training_type; @@ -1043,11 +1057,11 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); - ret = request_irq(dp->irq, exynos_dp_irq_handler, 0, + ret = request_irq(dp->irq, exynos_dp_irq_handler, irqflags, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); - goto err_ioremap; + goto err_gpio; } disable_irq(dp->irq); @@ -1058,6 +1072,9 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev) return 0; +err_gpio: + if (gpio_is_valid(dp->hpd_gpio)) + gpio_free(dp->hpd_gpio); err_ioremap: iounmap(dp->reg_base); err_req_region: @@ -1081,6 +1098,9 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev) if (pdata && pdata->phy_exit) pdata->phy_exit(); + if (gpio_is_valid(dp->hpd_gpio)) + gpio_free(dp->hpd_gpio); + free_irq(dp->irq, dp); iounmap(dp->reg_base); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index 23c8448e7179..61a170a3e739 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h @@ -39,6 +39,7 @@ struct exynos_dp_device { struct clk *clock; unsigned int irq; void __iomem *reg_base; + int hpd_gpio; struct video_info *video_info; enum link_training_type training_type; diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c index 5467d7c199ab..c8b423bd7b1b 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_reg.c +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -293,6 +294,9 @@ void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp) { u32 reg; + if (gpio_is_valid(dp->hpd_gpio)) + return; + reg = HOTPLUG_CHG | HPD_LOST | PLUG; writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); @@ -304,6 +308,9 @@ void exynos_dp_init_hpd(struct exynos_dp_device *dp) { u32 reg; + if (gpio_is_valid(dp->hpd_gpio)) + return; + exynos_dp_clear_hotplug_interrupts(dp); reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); @@ -322,6 +329,14 @@ enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp) { u32 reg; + if (gpio_is_valid(dp->hpd_gpio)) { + reg = gpio_get_value(dp->hpd_gpio); + if (reg) + return DP_IRQ_TYPE_HP_CABLE_IN; + else + return DP_IRQ_TYPE_HP_CABLE_OUT; + } + /* Parse hotplug interrupt status register */ reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); -- 2.20.1