summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@fairlite.demon.co.uk>2005-05-28 00:00:08 +0000
committerAlan Hourihane <alanh@fairlite.demon.co.uk>2005-05-28 00:00:08 +0000
commit45f1db8db9d1280dff51cdfb680bff2754195483 (patch)
treea8ed0391f5efad8ddb8c057f23fc2cd79fa8f7ce /shared-core
parent4a84416c458027462ee6112a5fa442415597f6c2 (diff)
Re-implement the power management.
There's two choices when fb is or isn't loaded as we treat ourselves as a PCI driver in the latter case. If we are a PCI driver, then register the suspend/resume functions directly. If not, then we register as a sysdev and pick up the suspend/resume actions and pump them down into a generic *power function. It'll be nice when this little mess is sorted out with regard to being a real PCI driver ;-/
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/i915_drv.h5
-rw-r--r--shared-core/i915_pm.c140
2 files changed, 145 insertions, 0 deletions
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 75480c16..8024d829 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -91,6 +91,11 @@ extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
extern void i915_driver_irq_uninstall(drm_device_t * dev);
+/* i915_pm.c */
+extern int i915_suspend(struct pci_dev *pdev, u32 state);
+extern int i915_resume(struct pci_dev *pdev);
+extern int i915_power(drm_device_t *dev, unsigned int state);
+
/* i915_mem.c */
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
extern int i915_mem_free(DRM_IOCTL_ARGS);
diff --git a/shared-core/i915_pm.c b/shared-core/i915_pm.c
new file mode 100644
index 00000000..17451319
--- /dev/null
+++ b/shared-core/i915_pm.c
@@ -0,0 +1,140 @@
+/* i915_pm.c -- Power management support for the i915 -*- linux-c -*-
+ */
+/**************************************************************************
+ *
+ * Copyright 2004 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ **************************************************************************/
+
+#define __NO_VERSION__
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+
+/**
+ * Set DPMS mode.
+ */
+static int i915_set_dpms(drm_device_t *dev, int mode)
+{
+ drm_i915_private_t *dev_priv =
+ (drm_i915_private_t *)dev->dev_private;
+ unsigned sr01, adpa, ppcr, dvob, dvoc, lvds;
+
+ DRM_DEBUG("%s mode=%d\n", __FUNCTION__, mode);
+
+ I915_WRITE( SRX_INDEX, SR01 );
+ sr01 = I915_READ( SRX_DATA );
+
+ adpa = I915_READ( ADPA );
+ ppcr = I915_READ( PPCR );
+ dvoc = I915_READ( DVOC );
+ dvob = I915_READ( DVOB );
+ lvds = I915_READ( LVDS );
+
+ switch(mode) {
+ case 0:
+ /* On */
+ sr01 &= ~SR01_SCREEN_OFF;
+ adpa = (adpa & ADPA_DPMS_MASK) | ADPA_DPMS_ON;
+#if 0
+ I915_WRITE( LVDS, lvds | LVDS_ON ); /* Power on LVDS */
+#endif
+ I915_WRITE( PPCR, dev_priv->ppcr ); /* Power up panel */
+ I915_WRITE( DVOC, dev_priv->dvoc );
+ I915_WRITE( DVOB, dev_priv->dvob );
+ break;
+
+ case 1:
+ /* Standby */
+ sr01 |= SR01_SCREEN_OFF;
+ adpa = (adpa & ADPA_DPMS_MASK) | ADPA_DPMS_STANDBY;
+ I915_WRITE( PPCR, ppcr & ~PPCR_ON ); /* Power off panel*/
+#if 0
+ I915_WRITE( LVDS, lvds & ~LVDS_ON ); /* Power off LVDS */
+#endif
+ I915_WRITE( DVOC, dvoc & ~DVOC_ON );
+ I915_WRITE( DVOB, dvob & ~DVOB_ON );
+ break;
+
+ case 2:
+ /* Suspend */
+ sr01 |= SR01_SCREEN_OFF;
+ adpa = (adpa & ADPA_DPMS_MASK) | ADPA_DPMS_SUSPEND;
+ I915_WRITE( PPCR, ppcr & ~PPCR_ON ); /* Power off panel*/
+#if 0
+ I915_WRITE( LVDS, lvds & ~LVDS_ON ); /* Power off LVDS */
+#endif
+ I915_WRITE( DVOC, dvoc & ~DVOC_ON );
+ I915_WRITE( DVOB, dvob & ~DVOB_ON );
+ break;
+
+ case 3:
+ /* Off */
+ sr01 |= SR01_SCREEN_OFF;
+ adpa = (adpa & ADPA_DPMS_MASK) | ADPA_DPMS_OFF;
+ I915_WRITE( PPCR, ppcr & ~PPCR_ON ); /* Power off panel*/
+#if 0
+ I915_WRITE( LVDS, lvds & ~LVDS_ON ); /* Power off LVDS */
+#endif
+ I915_WRITE( DVOC, dvoc & ~DVOC_ON );
+ I915_WRITE( DVOB, dvob & ~DVOB_ON );
+ break;
+ }
+
+ I915_WRITE( SRX_DATA, sr01 );
+
+ I915_WRITE( ADPA, adpa );
+
+ return 0;
+}
+
+int i915_suspend( struct pci_dev *pdev, unsigned state )
+{
+ drm_device_t *dev = (drm_device_t *)pci_get_drvdata(pdev);
+
+ DRM_DEBUG("%s state=%d\n", __FUNCTION__, state);
+
+ switch(state) {
+ case 0:
+ /* D0: set DPMS mode on */
+ i915_set_dpms(dev, 0);
+ break;
+ case 1:
+ /* D1: set DPMS mode standby */
+ i915_set_dpms(dev, 1);
+ break;
+ case 2:
+ /* D2: set DPMS mode suspend */
+ i915_set_dpms(dev, 2);
+ break;
+ case 3:
+ /* D3: set DPMS mode off */
+ i915_set_dpms(dev, 3);
+ break;
+ }
+
+ return 0;
+}
+
+int i915_resume( struct pci_dev *pdev )
+{
+ drm_device_t *dev = (drm_device_t *)pci_get_drvdata(pdev);
+
+ /* D0: set DPMS mode on */
+ i915_set_dpms(dev, 0);
+
+ return 0;
+}
+
+int i915_power( drm_device_t *dev, unsigned int state )
+{
+ DRM_DEBUG("%s state=%d\n", __FUNCTION__, state);
+
+ /* D0: set DPMS mode on */
+ i915_set_dpms(dev, state);
+
+ return 0;
+}