[Meego-kernel] [PATCH 04/26] GFX: Fix for HSD Issue 3470628 (Can't resume after DPMS off)

hitesh.k.patel at intel.com hitesh.k.patel at intel.com
Wed Nov 24 19:59:18 PST 2010


From: Hitesh K. Patel <hitesh.k.patel at intel.com>

Fixed the issue that Display could not be resumed after
DPMS off (hsd# 3470628) When runtime PM is enabled,
it failed to resume after "xset dpms force off" in
both Moorestown/MIPI and Medfield.

The patch is to disable the runtime PM in the interim of
setting a new config from userspace or dpms on/off.
And this will make sure the save/restore display
registers correct.

Signed-off-by: Jackie Li <yaodong.li at intel.com>
Signed-off-by: Austin Hu <austin.hu at intel.com>
Signed-off-by: Justin Dou <Justin.Dou at intel.com>
Signed-off-by: Hitesh K. Patel <hitesh.k.patel at intel.com>
---
 drivers/staging/mrst/drv/mdfld_dsi_dbi.c     |    4 +++-
 drivers/staging/mrst/drv/psb_drv.c           |    6 +++++-
 drivers/staging/mrst/drv/psb_drv.h           |    3 +++
 drivers/staging/mrst/drv/psb_intel_display.c |   21 ++++++++++++++++++++-
 drivers/staging/mrst/drv/psb_intel_drv.h     |    1 +
 drivers/staging/mrst/drv/psb_intel_dsi.c     |   19 +++++++++++++++++--
 drivers/staging/mrst/drv/psb_powermgmt.c     |   21 +++++++++++++++++----
 7 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/mrst/drv/mdfld_dsi_dbi.c b/drivers/staging/mrst/drv/mdfld_dsi_dbi.c
index d1fc581..691e166 100644
--- a/drivers/staging/mrst/drv/mdfld_dsi_dbi.c
+++ b/drivers/staging/mrst/drv/mdfld_dsi_dbi.c
@@ -495,13 +495,15 @@ void mdfld_dsi_dbi_exit_dsr (struct drm_device *dev, u32 update_src)
 	int i;
 	
 	PSB_DEBUG_ENTRY("\n");
-	
+
+	/*
 	if(!allow_runtime_pm){
 	        printk(KERN_ALERT "Enable runtime_pm \n");
 
 		allow_runtime_pm = 1;
 	        pm_runtime_allow(&gpDrmDevice->pdev->dev);
 	}
+	*/
 
 	dbi_output = dsr_info->dbi_outputs;
 	/*for each output, exit dsr*/
diff --git a/drivers/staging/mrst/drv/psb_drv.c b/drivers/staging/mrst/drv/psb_drv.c
index fceb26f..8d91ae0 100644
--- a/drivers/staging/mrst/drv/psb_drv.c
+++ b/drivers/staging/mrst/drv/psb_drv.c
@@ -2498,22 +2498,26 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
 {
 	struct drm_file *file_priv = filp->private_data;
 	struct drm_device *dev = file_priv->minor->dev;
+	/*
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	static unsigned int runtime_allowed = 0;
+	*/
 	unsigned int nr = DRM_IOCTL_NR(cmd);
 	long ret;
 
 	DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
 	/*Simple (work around)Ugly hack to make runtime pm start only after X is initialized*/
 	/*This doesn't work with Medfield RT PM.*/
-
+	/*
 	if(!runtime_allowed && !(dev_priv->is_lvds_on || dev_priv->is_mipi_on)) {
 		runtime_allowed ++;
 	}
 	if((runtime_allowed == 1) && (dev_priv->is_lvds_on || dev_priv->is_mipi_on)) {
 		runtime_allowed ++;
 		pm_runtime_allow(&dev->pdev->dev);
+		dev_priv->rpm_enabled = 1;
 	}
+	*/
 
 	/*
 	 * The driver private ioctls and TTM ioctls should be
diff --git a/drivers/staging/mrst/drv/psb_drv.h b/drivers/staging/mrst/drv/psb_drv.h
index 44d2cee..3a9280d 100644
--- a/drivers/staging/mrst/drv/psb_drv.h
+++ b/drivers/staging/mrst/drv/psb_drv.h
@@ -639,6 +639,9 @@ struct drm_psb_private {
 	struct mdfld_dsi_dbi_output * dbi_output2;
 /* MDFLD_DSI private date end */
 
+	/*runtime PM state*/
+	int rpm_enabled;
+
 	/*
 	 *Register state
 	 */
diff --git a/drivers/staging/mrst/drv/psb_intel_display.c b/drivers/staging/mrst/drv/psb_intel_display.c
index 7b99631..004be27 100644
--- a/drivers/staging/mrst/drv/psb_intel_display.c
+++ b/drivers/staging/mrst/drv/psb_intel_display.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
 #include "psb_fb.h"
@@ -1301,6 +1302,24 @@ static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
 	psb_intel_crtc_load_lut(crtc);
 }
 
+static int mrst_crtc_set_config(struct drm_mode_set *set)
+{
+	int ret = 0;
+	struct drm_device * dev = set->crtc->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+
+	if(!dev_priv->rpm_enabled)
+		return drm_crtc_helper_set_config(set);
+
+	pm_runtime_forbid(&dev->pdev->dev);
+
+	ret = drm_crtc_helper_set_config(set);
+
+	pm_runtime_allow(&dev->pdev->dev);
+
+	return ret;
+}
+
 /* Returns the clock of the currently programmed mode of the given pipe. */
 static int psb_intel_crtc_clock_get(struct drm_device *dev,
 				struct drm_crtc *crtc)
@@ -1463,7 +1482,7 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
 	.cursor_set = psb_intel_crtc_cursor_set,
 	.cursor_move = psb_intel_crtc_cursor_move,
 	.gamma_set = psb_intel_crtc_gamma_set,
-	.set_config = drm_crtc_helper_set_config,
+	.set_config = mrst_crtc_set_config,
 	.destroy = psb_intel_crtc_destroy,
 };
 
diff --git a/drivers/staging/mrst/drv/psb_intel_drv.h b/drivers/staging/mrst/drv/psb_intel_drv.h
index 3a3bf2a..92fe1e0 100644
--- a/drivers/staging/mrst/drv/psb_intel_drv.h
+++ b/drivers/staging/mrst/drv/psb_intel_drv.h
@@ -258,6 +258,7 @@ extern void psb_intel_lvds_init(struct drm_device *dev,
 extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
 extern void mrst_lvds_init(struct drm_device *dev,
 			   struct psb_intel_mode_device *mode_dev);
+extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev);
 extern void mrst_dsi_init(struct drm_device *dev,
 			   struct psb_intel_mode_device *mode_dev);
 extern void mid_dsi_init(struct drm_device *dev,
diff --git a/drivers/staging/mrst/drv/psb_intel_dsi.c b/drivers/staging/mrst/drv/psb_intel_dsi.c
index 5f5f37b..cf8ecd8 100644
--- a/drivers/staging/mrst/drv/psb_intel_dsi.c
+++ b/drivers/staging/mrst/drv/psb_intel_dsi.c
@@ -116,6 +116,21 @@ static void mrst_dsi_dpms(struct drm_encoder *encoder, int mode)
 		mrst_dsi_set_power(dev, output, false);
 }
 
+static void mrst_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+	struct drm_device * dev = connector->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+
+	if(!dev_priv->rpm_enabled) {
+		drm_helper_connector_dpms(connector, mode);
+		return;
+	}
+
+	pm_runtime_forbid(&dev->pdev->dev);
+	drm_helper_connector_dpms(connector, mode);
+	pm_runtime_allow(&dev->pdev->dev);
+}
+
 static void mrst_dsi_save(struct drm_connector *connector)
 {
 	PSB_DEBUG_ENTRY("\n");
@@ -982,7 +997,7 @@ static void	mrst_init_HIMAX_MIPI_bridge(struct drm_device *dev)
 }
 #endif
 
-static void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev)
+void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev)
 {
 	int timeout = 0;
 	udelay(500);
@@ -1944,7 +1959,7 @@ static const struct drm_connector_helper_funcs
 };
 
 static const struct drm_connector_funcs mrst_dsi_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = mrst_dsi_connector_dpms,
 	.save = mrst_dsi_save,
 	.restore = mrst_dsi_restore,
 	.detect = mrst_dsi_detect,
diff --git a/drivers/staging/mrst/drv/psb_powermgmt.c b/drivers/staging/mrst/drv/psb_powermgmt.c
index 7db1fdb..aa9bd76 100644
--- a/drivers/staging/mrst/drv/psb_powermgmt.c
+++ b/drivers/staging/mrst/drv/psb_powermgmt.c
@@ -668,12 +668,25 @@ static int restore_display_registers(struct drm_device *dev)
 		} else {
                         PSB_WVDC32(MIPI_PORT_EN | MIPI_BORDER_EN, MIPI); /*force on port*/
                         PSB_WVDC32(1, DEVICE_READY_REG);/* force on to re-program */
+
+                        if (dev_priv->saveDEVICE_READY_REG) {
+                                if ((REG_READ(INTR_STAT_REG) & SPL_PKT_SENT)) {
+                                        REG_WRITE(INTR_STAT_REG, SPL_PKT_SENT);
+                                }
+
+                                /*send turn on packet*/
+                                PSB_WVDC32(DPI_TURN_ON, DPI_CONTROL_REG);
+
+                                /*wait for special packet sent interrupt*/
+                                mrst_wait_for_INTR_PKT_SENT(dev);
+
+                                msleep(100);
+                        }
+
                         if(dev_priv->init_drvIC)
                                 dev_priv->init_drvIC(dev);
                         PSB_WVDC32(dev_priv->saveMIPI, MIPI); /*port 61190h*/
                         PSB_WVDC32(dev_priv->saveDEVICE_READY_REG, DEVICE_READY_REG);
-                        if (dev_priv->saveDEVICE_READY_REG)
-                                PSB_WVDC32(DPI_TURN_ON, DPI_CONTROL_REG);
                         PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
                         PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
                         PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
@@ -1390,9 +1403,9 @@ void ospm_suspend_display(struct drm_device *dev)
 #endif 
 
 	} else {
-		if (dev_priv->iLVDS_enable) {
-			save_display_registers(dev);
+		save_display_registers(dev);
 		
+		if (dev_priv->iLVDS_enable) {
 			/*shutdown the panel*/
 			PSB_WVDC32(0, PP_CONTROL);
 
-- 
1.7.1



More information about the MeeGo-kernel mailing list