aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/exynos/exynos_hdmi.c
diff options
context:
space:
mode:
authorSean Paul <seanpaul@chromium.org>2014-05-09 02:05:10 -0400
committerInki Dae <daeinki@gmail.com>2014-06-01 13:07:06 -0400
commit724fd140d568f472120b550ec10343ee022a307f (patch)
treeacf405f66809dba62243697f3bad1cdd2d5fe2e8 /drivers/gpu/drm/exynos/exynos_hdmi.c
parent35b95ac5c3fbf93c8d42187d5688db3e89a12f61 (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.c23
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
1906static irqreturn_t hdmi_irq_thread(int irq, void *arg) 1911static 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
1925static 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