[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