diff options
author | Alan Hourihane <alanh@fairlite.demon.co.uk> | 2005-05-28 00:00:08 +0000 |
---|---|---|
committer | Alan Hourihane <alanh@fairlite.demon.co.uk> | 2005-05-28 00:00:08 +0000 |
commit | 45f1db8db9d1280dff51cdfb680bff2754195483 (patch) | |
tree | a8ed0391f5efad8ddb8c057f23fc2cd79fa8f7ce /shared-core | |
parent | 4a84416c458027462ee6112a5fa442415597f6c2 (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.h | 5 | ||||
-rw-r--r-- | shared-core/i915_pm.c | 140 |
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; +} |