From: Sean Paul <seanp...@chromium.org>

This patch debounces hotplug interrupts generated by the HDMI hotplug
gpio. The reason this is needed is that we get multiple (5) interrupts
every time a monitor is inserted which causes us to needlessly enable
and disable the IP block.

Signed-off-by: Sean Paul <seanpaul at chromium.org>
Signed-off-by: Rahul Sharma <Rahul.Sharma at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_hdmi.c |   23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c 
b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 79f98ac..f6d4435 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -51,6 +51,8 @@
 #define get_hdmi_display(dev)  platform_get_drvdata(to_platform_device(dev))
 #define ctx_from_connector(c)  container_of(c, struct hdmi_context, connector)

+#define HOTPLUG_DEBOUNCE_MS            1100
+
 /* AVI header and aspect ratio */
 #define HDMI_AVI_VERSION               0x02
 #define HDMI_AVI_LENGTH                0x0D
@@ -189,6 +191,7 @@ struct hdmi_context {

        void __iomem                    *regs;
        int                             irq;
+       struct delayed_work             hotplug_work;

        struct i2c_adapter              *ddc_adpt;
        struct i2c_client               *hdmiphy_port;
@@ -2058,6 +2061,8 @@ static void hdmi_poweroff(struct exynos_drm_display 
*display)

        hdmiphy_poweroff(hdata);

+       cancel_delayed_work(&hdata->hotplug_work);
+
        clk_disable_unprepare(res->sclk_hdmi);
        clk_disable_unprepare(res->hdmi);
        /* reset pmu hdmiphy control bit to disable hdmiphy */
@@ -2108,9 +2113,11 @@ static struct exynos_drm_display hdmi_display = {
        .ops = &hdmi_display_ops,
 };

-static irqreturn_t hdmi_irq_thread(int irq, void *arg)
+static void hdmi_hotplug_work_func(struct work_struct *work)
 {
-       struct hdmi_context *hdata = arg;
+       struct hdmi_context *hdata;
+
+       hdata = container_of(work, struct hdmi_context, hotplug_work.work);

        mutex_lock(&hdata->hdmi_mutex);
        hdata->hpd = 1;//gpio_get_value(hdata->hpd_gpio);
@@ -2118,6 +2125,14 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)

        if (hdata->drm_dev)
                drm_helper_hpd_irq_event(hdata->drm_dev);
+}
+
+static irqreturn_t hdmi_irq_thread(int irq, void *arg)
+{
+       struct hdmi_context *hdata = arg;
+
+       mod_delayed_work(system_wq, &hdata->hotplug_work,
+                       msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));

        return IRQ_HANDLED;
 }
@@ -2315,6 +2330,8 @@ static int hdmi_probe(struct platform_device *pdev)

        hdata->hpd = 1;//gpio_get_value(hdata->hpd_gpio);

+       INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func);
+
        ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
                        hdmi_irq_thread, IRQF_TRIGGER_RISING |
                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
@@ -2351,6 +2368,8 @@ static int hdmi_remove(struct platform_device *pdev)
        struct exynos_drm_display *display = get_hdmi_display(dev);
        struct hdmi_context *hdata = display->ctx;

+       cancel_delayed_work_sync(&hdata->hotplug_work);
+
        put_device(&hdata->hdmiphy_port->dev);
        put_device(&hdata->ddc_adpt->dev);
        pm_runtime_disable(&pdev->dev);
-- 
1.7.9.5

Reply via email to