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
