diff options
author | Sean Paul <seanpaul@chromium.org> | 2014-05-09 02:05:10 -0400 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-06-01 13:07:06 -0400 |
commit | 724fd140d568f472120b550ec10343ee022a307f (patch) | |
tree | acf405f66809dba62243697f3bad1cdd2d5fe2e8 /drivers/gpu/drm/exynos/exynos_hdmi.c | |
parent | 35b95ac5c3fbf93c8d42187d5688db3e89a12f61 (diff) |
drm/exynos: Debounce HDMI hotplug interrupts
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@chromium.org>
Signed-off-by: Rahul Sharma <Rahul.Sharma@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index c7329d97413a..73a7acb1283c 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev)) | 50 | #define get_hdmi_display(dev) platform_get_drvdata(to_platform_device(dev)) |
51 | #define ctx_from_connector(c) container_of(c, struct hdmi_context, connector) | 51 | #define ctx_from_connector(c) container_of(c, struct hdmi_context, connector) |
52 | 52 | ||
53 | #define HOTPLUG_DEBOUNCE_MS 1100 | ||
54 | |||
53 | /* AVI header and aspect ratio */ | 55 | /* AVI header and aspect ratio */ |
54 | #define HDMI_AVI_VERSION 0x02 | 56 | #define HDMI_AVI_VERSION 0x02 |
55 | #define HDMI_AVI_LENGTH 0x0D | 57 | #define HDMI_AVI_LENGTH 0x0D |
@@ -187,6 +189,7 @@ struct hdmi_context { | |||
187 | 189 | ||
188 | void __iomem *regs; | 190 | void __iomem *regs; |
189 | int irq; | 191 | int irq; |
192 | struct delayed_work hotplug_work; | ||
190 | 193 | ||
191 | struct i2c_adapter *ddc_adpt; | 194 | struct i2c_adapter *ddc_adpt; |
192 | struct i2c_client *hdmiphy_port; | 195 | struct i2c_client *hdmiphy_port; |
@@ -1857,6 +1860,8 @@ static void hdmi_poweroff(struct exynos_drm_display *display) | |||
1857 | 1860 | ||
1858 | hdmiphy_poweroff(hdata); | 1861 | hdmiphy_poweroff(hdata); |
1859 | 1862 | ||
1863 | cancel_delayed_work(&hdata->hotplug_work); | ||
1864 | |||
1860 | clk_disable_unprepare(res->sclk_hdmi); | 1865 | clk_disable_unprepare(res->sclk_hdmi); |
1861 | clk_disable_unprepare(res->hdmi); | 1866 | clk_disable_unprepare(res->hdmi); |
1862 | clk_disable_unprepare(res->hdmiphy); | 1867 | clk_disable_unprepare(res->hdmiphy); |
@@ -1903,9 +1908,11 @@ static struct exynos_drm_display hdmi_display = { | |||
1903 | .ops = &hdmi_display_ops, | 1908 | .ops = &hdmi_display_ops, |
1904 | }; | 1909 | }; |
1905 | 1910 | ||
1906 | static irqreturn_t hdmi_irq_thread(int irq, void *arg) | 1911 | static void hdmi_hotplug_work_func(struct work_struct *work) |
1907 | { | 1912 | { |
1908 | struct hdmi_context *hdata = arg; | 1913 | struct hdmi_context *hdata; |
1914 | |||
1915 | hdata = container_of(work, struct hdmi_context, hotplug_work.work); | ||
1909 | 1916 | ||
1910 | mutex_lock(&hdata->hdmi_mutex); | 1917 | mutex_lock(&hdata->hdmi_mutex); |
1911 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 1918 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
@@ -1913,6 +1920,14 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg) | |||
1913 | 1920 | ||
1914 | if (hdata->drm_dev) | 1921 | if (hdata->drm_dev) |
1915 | drm_helper_hpd_irq_event(hdata->drm_dev); | 1922 | drm_helper_hpd_irq_event(hdata->drm_dev); |
1923 | } | ||
1924 | |||
1925 | static irqreturn_t hdmi_irq_thread(int irq, void *arg) | ||
1926 | { | ||
1927 | struct hdmi_context *hdata = arg; | ||
1928 | |||
1929 | mod_delayed_work(system_wq, &hdata->hotplug_work, | ||
1930 | msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); | ||
1916 | 1931 | ||
1917 | return IRQ_HANDLED; | 1932 | return IRQ_HANDLED; |
1918 | } | 1933 | } |
@@ -2142,6 +2157,8 @@ static int hdmi_probe(struct platform_device *pdev) | |||
2142 | 2157 | ||
2143 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 2158 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
2144 | 2159 | ||
2160 | INIT_DELAYED_WORK(&hdata->hotplug_work, hdmi_hotplug_work_func); | ||
2161 | |||
2145 | ret = devm_request_threaded_irq(dev, hdata->irq, NULL, | 2162 | ret = devm_request_threaded_irq(dev, hdata->irq, NULL, |
2146 | hdmi_irq_thread, IRQF_TRIGGER_RISING | | 2163 | hdmi_irq_thread, IRQF_TRIGGER_RISING | |
2147 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 2164 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
@@ -2167,6 +2184,8 @@ static int hdmi_remove(struct platform_device *pdev) | |||
2167 | { | 2184 | { |
2168 | struct hdmi_context *hdata = hdmi_display.ctx; | 2185 | struct hdmi_context *hdata = hdmi_display.ctx; |
2169 | 2186 | ||
2187 | cancel_delayed_work_sync(&hdata->hotplug_work); | ||
2188 | |||
2170 | put_device(&hdata->hdmiphy_port->dev); | 2189 | put_device(&hdata->hdmiphy_port->dev); |
2171 | put_device(&hdata->ddc_adpt->dev); | 2190 | put_device(&hdata->ddc_adpt->dev); |
2172 | 2191 | ||