gfx: enable runtime pm support at DPMS
authorLi Peng <peng.li@intel.com>
Fri, 27 Jul 2012 03:00:26 +0000 (11:00 +0800)
committerLi Peng <peng.li@intel.com>
Fri, 27 Jul 2012 03:01:26 +0000 (11:01 +0800)
before we just turn off/on screen at DPMS off/on, now we do further
to let gfx h/w enter and exit D0i3 if userspace control screen off/on
through DPMS interface, it could save more power

Signed-off-by: Li Peng <peng.li@intel.com>
drivers/staging/mrst.mcg/drv/mdfld_dsi_output.c
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_drv.h
drivers/staging/mrst/drv/psb_powermgmt.c
drivers/staging/mrst/drv/psb_powermgmt.h

index 58287e6..0600684 100755 (executable)
@@ -568,10 +568,41 @@ EXPORT_SYMBOL(screen_notifier_call_chain);
 
 static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
 {
+       struct drm_device *dev = connector->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       int old_dpms;
+
        screen_notifier_call_chain((unsigned int)mode, connector);
 
+#ifdef CONFIG_EARLYSUSPEND
        if (early_suspend)
                return;
+#endif
+
+       if (dev_priv->rpm_enabled) {
+               old_dpms = connector->dpms;
+
+               if (mode == old_dpms)
+                       return;
+
+               if ((mode < old_dpms) && (mode == DRM_MODE_DPMS_ON)) {
+                       connector->dpms = mode;
+                       gfx_runtime_resume(&dev->pdev->dev);
+               }
+               
+               if ((mode > old_dpms) && (old_dpms == DRM_MODE_DPMS_ON)) {
+                       connector->dpms = mode;
+                       gfx_runtime_suspend(&dev->pdev->dev);
+               }
+
+               connector->dpms = mode;
+               return;
+       }
+
+       if (!(dev_priv->rpm_enabled)) {
+               if (mode == DRM_MODE_DPMS_ON)
+                       dev_priv->rpm_enabled = 1;
+       }
 
        drm_helper_connector_dpms(connector, mode);
 }
index 045836b..0824469 100644 (file)
@@ -1291,6 +1291,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
        dev_priv->psb_hotplug_state = psb_hotplug_init(kobj);
 
+       mutex_init(&dev_priv->rpm_mutex);
+       dev_priv->rpm_enabled = 0;
+
        // GL3
 #ifdef CONFIG_MDFD_GL3
        gl3_enable();
index b109d22..3e5b3d8 100644 (file)
@@ -379,6 +379,9 @@ struct drm_psb_private {
        struct work_struct te_work;
        int te_pipe;
 
+       struct mutex rpm_mutex;
+       int rpm_enabled;
+
        /*
         *TTM Glue.
         */
index 2cfc3f3..ded877d 100644 (file)
@@ -1320,6 +1320,51 @@ int psb_runtime_idle(struct device *dev)
        return 0;
 }
 
+void gfx_runtime_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_psb_private *dev_priv = drm_dev->dev_private;
+       struct drm_encoder *encoder;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT  "%s\n", __func__);
+#endif
+
+       mutex_lock(&dev_priv->rpm_mutex);
+       list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, head) {
+               struct drm_encoder_helper_funcs *ehf = encoder->helper_private;
+               if (drm_helper_encoder_in_use(encoder) && ehf && ehf->save)
+                       ehf->save(encoder);
+       }
+       mutex_unlock(&dev_priv->rpm_mutex);
+
+       pm_runtime_put(dev);
+}
+
+void gfx_runtime_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct drm_device *drm_dev = pci_get_drvdata(pdev);
+       struct drm_psb_private *dev_priv = drm_dev->dev_private;
+       struct drm_encoder *encoder;
+
+#ifdef OSPM_GFX_DPK
+       printk(KERN_ALERT  "%s\n", __func__);
+#endif
+       pm_runtime_get_sync(dev);
+
+       mutex_lock(&dev_priv->rpm_mutex);
+       list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, head) {
+               struct drm_encoder_helper_funcs *ehf = encoder->helper_private;
+
+               if (drm_helper_encoder_in_use(encoder) && ehf && ehf->restore) {
+                       ehf->restore(encoder);
+               }
+       }
+       mutex_unlock(&dev_priv->rpm_mutex);
+}
+
 int psb_runtime_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -1344,6 +1389,10 @@ int psb_runtime_resume(struct device *dev)
        struct pci_dev *pdev = to_pci_dev(dev);
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
 
+#ifdef OSPM_GFX_DPK
+       dev_dbg(&drm_dev->pdev->dev, "%s\n", __func__);
+#endif
+
        ospm_power_resume(dev);
        psb_runtime_hdmi_audio_resume(drm_dev);
 
index bd67523..90a3422 100644 (file)
@@ -103,6 +103,8 @@ int psb_runtime_suspend(struct device *dev);
 int psb_runtime_resume(struct device *dev);
 int psb_runtime_idle(struct device *dev);
 
+void gfx_runtime_suspend(struct device *dev);
+void gfx_runtime_resume(struct device *dev);
 int gfx_suspend(struct device *dev);
 int gfx_resume(struct device *dev);