Gfx-Display: forbid runtime suspend for 2 seconds in HDMI hotplug workqueue
authorLei Zhang <lei.zhang@intel.com>
Mon, 21 May 2012 03:10:11 +0000 (11:10 +0800)
committerbuildbot <buildbot@intel.com>
Mon, 28 May 2012 15:46:00 +0000 (08:46 -0700)
BZ: 26745

This patch forbids runtime suspend in HDMI hotplug workqueue for 2 seconds.
This is used to prevent display driver goes to suspend status during hotplug
detect, and allow enough time for HDMI audio to be routed from IHF.

Change-Id: If67e3bb54c8d0d941f5d24a5abdaccaf01eb5682
Signed-off-by: Lei Zhang <lei.zhang@intel.com>
Signed-off-by: Tong, Bo <box.tong@intel.com>
Reviewed-on: http://android.intel.com:8080/49474
Reviewed-by: Xu, Randy <randy.xu@intel.com>
Tested-by: Xu, Randy <randy.xu@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_drv.h
drivers/staging/mrst/drv/psb_intel_hdmi.c
drivers/staging/mrst/drv/psb_powermgmt.c

index 755900e..b0b4242 100644 (file)
@@ -1317,6 +1317,45 @@ bool mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 }
 
 #ifdef CONFIG_MDFD_HDMI
+#define HDMI_HOTPLUG_DELAY (2*HZ)
+static void hdmi_hotplug_timer_func(unsigned long data)
+{
+       struct drm_device *dev = (struct drm_device *)data;
+
+       PSB_DEBUG_ENTRY("\n");
+       ospm_runtime_pm_allow(dev);
+}
+
+static int hdmi_hotplug_timer_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct timer_list *hdmi_timer = &dev_priv->hdmi_timer;
+
+       PSB_DEBUG_ENTRY("\n");
+
+       init_timer(hdmi_timer);
+
+       hdmi_timer->data = (unsigned long)dev;
+       hdmi_timer->function = hdmi_hotplug_timer_func;
+       hdmi_timer->expires = jiffies + HDMI_HOTPLUG_DELAY;
+
+       PSB_DEBUG_ENTRY("successfully\n");
+
+       return 0;
+}
+
+void hdmi_hotplug_timer_start(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct timer_list *hdmi_timer = &dev_priv->hdmi_timer;
+
+       PSB_DEBUG_ENTRY("\n");
+       if (!timer_pending(hdmi_timer)) {
+               hdmi_timer->expires = jiffies + HDMI_HOTPLUG_DELAY;
+               add_timer(hdmi_timer);
+       }
+}
+
 void hdmi_do_hotplug_wq(struct work_struct *work)
 {
        u8 data = 0;
@@ -1387,6 +1426,9 @@ void hdmi_do_hotplug_wq(struct work_struct *work)
                hdmi_state = 1;
                uevent_string = "HOTPLUG_IN=1";
                psb_sysfs_uevent(dev_priv->dev, uevent_string);
+
+               ospm_runtime_pm_forbid(dev);
+               hdmi_hotplug_timer_start(dev);
        } else {
                DRM_INFO("%s: HDMI unplugged\n", __func__);
                hdmi_state = 0;
@@ -2065,6 +2107,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
        /*enable runtime pm at last*/
        pm_runtime_put_noidle(&dev->pdev->dev);
 #endif
+
+#ifdef CONFIG_MDFD_HDMI
+       hdmi_hotplug_timer_init(dev);
+#endif
+
        // GL3
 #ifdef CONFIG_MDFD_GL3
        if (drm_psb_gl3_enable)
index 44268b8..06546f2 100644 (file)
@@ -573,6 +573,7 @@ struct drm_psb_private {
        */
        spinlock_t ospm_lock;
        uint8_t panel_desc;
+       bool early_suspended;
 
        /*
         * Sizes info
@@ -1094,6 +1095,7 @@ struct drm_psb_private {
        struct workqueue_struct *hpd_detect;
        pfn_screen_event_handler pvr_screen_event_handler;
        struct mutex dpms_mutex;
+       struct timer_list hdmi_timer;
 
        /* fix Lock screen flip in resume issue */
        unsigned long init_screen_start;
index e4f156d..26ea0d6 100644 (file)
@@ -784,8 +784,11 @@ static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode)
                (struct drm_psb_private *)dev->dev_private;
        struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
        struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+       int dspcntr_reg = DSPBCNTR;
+       int dspbase_reg = MRST_DSPBBASE;
        u32 hdmip_enabled = 0;
        u32 hdmib, hdmi_phy_misc;
+       u32 temp;
 
        PSB_DEBUG_ENTRY("%s\n", mode == DRM_MODE_DPMS_ON ?
                "on" : "off");
@@ -807,6 +810,19 @@ static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode)
        hdmip_enabled = REG_READ(hdmi_priv->hdmib_reg) & HDMIB_PORT_EN;
        PSB_DEBUG_ENTRY("hdmip_enabled is %x\n", hdmip_enabled);
 
+       if (dev_priv->early_suspended == true) {
+               /*Use Disable pipeB plane to turn off HDMI screen
+                 in early_suspend  */
+               temp = REG_READ(dspcntr_reg);
+               if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+                       REG_WRITE(dspcntr_reg,
+                                       temp & ~DISPLAY_PLANE_ENABLE);
+                       /* Flush the plane changes */
+                       REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+
+               }
+       }
+
        if (mode != DRM_MODE_DPMS_ON) {
                if (dev_priv->mdfld_had_event_callbacks
                        && !dev_priv->bDVIport
index e6a278a..e74facc 100644 (file)
@@ -1932,6 +1932,7 @@ static void gfx_early_suspend(struct early_suspend *h)
 
        gbdispstatus = false;
 
+       dev_priv->early_suspended = true;
 #ifdef CONFIG_GFX_RTPM
 #ifdef OSPM_GFX_DPK
        printk(KERN_ALERT " allow GFX runtime_pm\n");
@@ -2022,6 +2023,7 @@ static void gfx_late_resume(struct early_suspend *h)
        printk(KERN_ALERT "\ngfx_late_resume\n");
 #endif
 
+       dev_priv->early_suspended = false;
        if (IS_MDFLD(gpDrmDevice)) {
 #ifdef CONFIG_GFX_RTPM
                resume_data_back();