video: tegra: dc: Move hpd GPIO request to hdmi driver
Chaitanya Bandi [Thu, 31 Jan 2013 08:16:16 +0000 (13:16 +0530)]
Made these changes:
1. Moved hpd GPIO request to hdmi driver
2. Use Threaded irq to support PMIC gpio for hpd
3. Use rt_mutex instead of spinlock to allow sleepable calls
 while determining GPIO value through I2C PMIC.

Bug 1221130
Bug 1180971

Change-Id: I6eae4da484a34bcae873eabc2455389d46cc6c60
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/195900
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>

drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/hdmi.c

index 8fab252..002c70a 100644 (file)
@@ -744,7 +744,7 @@ bool tegra_dc_hpd(struct tegra_dc *dc)
        int sense;
        int level;
 
-       level = gpio_get_value(dc->out->hotplug_gpio);
+       level = gpio_get_value_cansleep(dc->out->hotplug_gpio);
 
        sense = dc->out->flags & TEGRA_DC_OUT_HOTPLUG_MASK;
 
index d7fa588..440db19 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #ifdef CONFIG_SWITCH
 #include <linux/switch.h>
 #endif
@@ -95,7 +95,7 @@ struct tegra_dc_hdmi_data {
 #endif
        struct tegra_hdmi_out           info;
 
-       spinlock_t                      suspend_lock;
+       struct rt_mutex                 suspend_lock;
        bool                            suspended;
        bool                            eld_retrieved;
        bool                            clk_enabled;
@@ -897,9 +897,9 @@ static irqreturn_t tegra_dc_hdmi_irq(int irq, void *ptr)
 {
        struct tegra_dc *dc = ptr;
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
-       unsigned long flags;
 
-       spin_lock_irqsave(&hdmi->suspend_lock, flags);
+       rt_mutex_lock(&hdmi->suspend_lock);
+
        if (!hdmi->suspended) {
                cancel_delayed_work(&hdmi->work);
                if (tegra_dc_hdmi_hpd(dc))
@@ -909,28 +909,27 @@ static irqreturn_t tegra_dc_hdmi_irq(int irq, void *ptr)
                        queue_delayed_work(system_nrt_wq, &hdmi->work,
                                           msecs_to_jiffies(30));
        }
-       spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
 
+       rt_mutex_unlock(&hdmi->suspend_lock);
        return IRQ_HANDLED;
 }
 
 static void tegra_dc_hdmi_suspend(struct tegra_dc *dc)
 {
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
-       unsigned long flags;
 
        tegra_nvhdcp_suspend(hdmi->nvhdcp);
-       spin_lock_irqsave(&hdmi->suspend_lock, flags);
+       rt_mutex_lock(&hdmi->suspend_lock);
        hdmi->suspended = true;
-       spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
+       rt_mutex_unlock(&hdmi->suspend_lock);
+
 }
 
 static void tegra_dc_hdmi_resume(struct tegra_dc *dc)
 {
        struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
-       unsigned long flags;
 
-       spin_lock_irqsave(&hdmi->suspend_lock, flags);
+       rt_mutex_lock(&hdmi->suspend_lock);
        hdmi->suspended = false;
 
        if (tegra_dc_hdmi_hpd(dc))
@@ -940,7 +939,8 @@ static void tegra_dc_hdmi_resume(struct tegra_dc *dc)
                queue_delayed_work(system_nrt_wq, &hdmi->work,
                                   msecs_to_jiffies(30));
 
-       spin_unlock_irqrestore(&hdmi->suspend_lock, flags);
+       rt_mutex_unlock(&hdmi->suspend_lock);
+
        tegra_nvhdcp_resume(hdmi->nvhdcp);
 }
 
@@ -1083,7 +1083,7 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
        hdmi->clk_enabled = false;
        hdmi->audio_freq = 44100;
        hdmi->audio_source = AUTO;
-       spin_lock_init(&hdmi->suspend_lock);
+       rt_mutex_init(&hdmi->suspend_lock);
 
 #ifdef CONFIG_SWITCH
        hdmi->hpd_switch.name = "hdmi";
@@ -1110,18 +1110,32 @@ static int tegra_dc_hdmi_init(struct tegra_dc *dc)
 
        tegra_dc_hdmi_debug_create(hdmi);
 
+       err = gpio_is_valid(dc->out->hotplug_gpio);
+       if (!err) {
+               dev_err(&dc->ndev->dev, "hdmi: hpd gpio_request failed");
+               goto err_nvhdcp_destroy;
+       }
+
+       gpio_request(dc->out->hotplug_gpio, "hdmi_hpd");
+       gpio_direction_input(dc->out->hotplug_gpio);
+
        /* TODO: support non-hotplug */
-       if (request_irq(gpio_to_irq(dc->out->hotplug_gpio), tegra_dc_hdmi_irq,
+       ret = request_threaded_irq(gpio_to_irq(dc->out->hotplug_gpio),
+               NULL, tegra_dc_hdmi_irq,
                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-               dev_name(&dc->ndev->dev), dc)) {
-               dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed\n",
-                       gpio_to_irq(dc->out->hotplug_gpio));
+               dev_name(&dc->ndev->dev), dc);
+
+       if (ret) {
+               dev_err(&dc->ndev->dev, "hdmi: request_irq %d failed - %d\n",
+                       gpio_to_irq(dc->out->hotplug_gpio), ret);
                err = -EBUSY;
-               goto err_nvhdcp_destroy;
+               goto err_gpio_free;
        }
 
        return 0;
 
+err_gpio_free:
+       gpio_free(dc->out->hotplug_gpio);
 err_nvhdcp_destroy:
        if (hdmi->nvhdcp)
                tegra_nvhdcp_destroy(hdmi->nvhdcp);