From: Hitesh K. Patel <[email protected]>

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 <[email protected]>
Signed-off-by: Austin Hu <[email protected]>
Signed-off-by: Justin Dou <[email protected]>
Signed-off-by: Hitesh K. Patel <[email protected]>
---
 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

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to