Suspend/resume support (incomplete).
parent
e918d2b781
commit
462d5a0dfc
|
@ -70,6 +70,235 @@ static drm_bo_driver_t i915_bo_driver = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static int i915_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_output *output;
|
||||
int i;
|
||||
|
||||
pci_save_state(pdev);
|
||||
|
||||
/* Save video mode information for native mode-setting. */
|
||||
dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
|
||||
dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
|
||||
dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
|
||||
dev_priv->saveFPA0 = I915_READ(FPA0);
|
||||
dev_priv->saveFPA1 = I915_READ(FPA1);
|
||||
dev_priv->saveDPLL_A = I915_READ(DPLL_A);
|
||||
if (IS_I965G(dev))
|
||||
dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
|
||||
dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
|
||||
dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
|
||||
dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
|
||||
dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
|
||||
dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
|
||||
dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
|
||||
dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
|
||||
dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
|
||||
dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
|
||||
dev_priv->saveDSPABASE = I915_READ(DSPABASE);
|
||||
|
||||
for(i= 0; i < 256; i++)
|
||||
dev_priv->savePaletteA[i] = I915_READ(PALETTE_A + (i << 2));
|
||||
|
||||
if(dev->mode_config.num_crtc == 2) {
|
||||
dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
|
||||
dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
|
||||
dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
|
||||
dev_priv->saveFPB0 = I915_READ(FPB0);
|
||||
dev_priv->saveFPB1 = I915_READ(FPB1);
|
||||
dev_priv->saveDPLL_B = I915_READ(DPLL_B);
|
||||
if (IS_I965G(dev))
|
||||
dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
|
||||
dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
|
||||
dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
|
||||
dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
|
||||
dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
|
||||
dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
|
||||
dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
|
||||
dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
|
||||
dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
|
||||
dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
|
||||
dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
|
||||
for(i= 0; i < 256; i++)
|
||||
dev_priv->savePaletteB[i] =
|
||||
I915_READ(PALETTE_B + (i << 2));
|
||||
}
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
dev_priv->saveDSPASURF = I915_READ(DSPASURF);
|
||||
dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
|
||||
}
|
||||
|
||||
dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
|
||||
dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
|
||||
dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
|
||||
dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
|
||||
|
||||
for(i = 0; i < 7; i++) {
|
||||
dev_priv->saveSWF[i] = I915_READ(SWF0 + (i << 2));
|
||||
dev_priv->saveSWF[i+7] = I915_READ(SWF00 + (i << 2));
|
||||
}
|
||||
dev_priv->saveSWF[14] = I915_READ(SWF30);
|
||||
dev_priv->saveSWF[15] = I915_READ(SWF31);
|
||||
dev_priv->saveSWF[16] = I915_READ(SWF32);
|
||||
|
||||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
dev_priv->saveLVDS = I915_READ(LVDS);
|
||||
dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
|
||||
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head)
|
||||
if (output->funcs->save)
|
||||
(*output->funcs->save) (output);
|
||||
|
||||
#if 0 /* FIXME: save VGA bits */
|
||||
vgaHWUnlock(hwp);
|
||||
vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS);
|
||||
#endif
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_resume(struct pci_dev *pdev)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_output *output;
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
pci_enable_device(pdev);
|
||||
|
||||
/* Disable outputs */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head)
|
||||
output->funcs->dpms(output, DPMSModeOff);
|
||||
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
|
||||
/* Disable pipes */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
crtc->funcs->dpms(crtc, DPMSModeOff);
|
||||
|
||||
/* FIXME: wait for vblank on each pipe? */
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
|
||||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
I915_WRITE(LVDS, dev_priv->saveLVDS);
|
||||
|
||||
if (!IS_I830(dev) && !IS_845G(dev))
|
||||
I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
|
||||
|
||||
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
|
||||
I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE);
|
||||
udelay(150);
|
||||
}
|
||||
I915_WRITE(FPA0, dev_priv->saveFPA0);
|
||||
I915_WRITE(FPA1, dev_priv->saveFPA1);
|
||||
I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
|
||||
udelay(150);
|
||||
if (IS_I965G(dev))
|
||||
I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
|
||||
else
|
||||
I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
|
||||
udelay(150);
|
||||
|
||||
I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
|
||||
I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
|
||||
I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
|
||||
I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
|
||||
I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
|
||||
I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
|
||||
|
||||
I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
|
||||
I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
|
||||
I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
|
||||
I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
|
||||
I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
|
||||
if (IS_I965G(dev))
|
||||
I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
|
||||
I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
|
||||
I915_WRITE(DSPABASE, I915_READ(DSPABASE));
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
|
||||
if(dev->mode_config.num_crtc == 2) {
|
||||
if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
|
||||
I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE);
|
||||
udelay(150);
|
||||
}
|
||||
I915_WRITE(FPB0, dev_priv->saveFPB0);
|
||||
I915_WRITE(FPB1, dev_priv->saveFPB1);
|
||||
I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
|
||||
udelay(150);
|
||||
if (IS_I965G(dev))
|
||||
I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
|
||||
else
|
||||
I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
|
||||
udelay(150);
|
||||
|
||||
I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
|
||||
I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
|
||||
I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
|
||||
I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
|
||||
I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
|
||||
I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
|
||||
I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
|
||||
I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
|
||||
I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
|
||||
I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
|
||||
I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
|
||||
if (IS_I965G(dev))
|
||||
I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
|
||||
I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
|
||||
I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
|
||||
i915_driver_wait_next_vblank(dev, 0);
|
||||
}
|
||||
|
||||
/* Restore outputs */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head)
|
||||
if (output->funcs->restore)
|
||||
output->funcs->restore(output);
|
||||
|
||||
I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
|
||||
|
||||
I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
|
||||
I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
|
||||
I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
|
||||
|
||||
for(i = 0; i < 256; i++)
|
||||
I915_WRITE(PALETTE_A + (i << 2), dev_priv->savePaletteA[i]);
|
||||
|
||||
if(dev->mode_config.num_crtc == 2)
|
||||
for(i= 0; i < 256; i++)
|
||||
I915_WRITE(PALETTE_B + (i << 2), dev_priv->savePaletteB[i]);
|
||||
|
||||
for(i = 0; i < 7; i++) {
|
||||
I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF[i]);
|
||||
I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF[i+7]);
|
||||
}
|
||||
|
||||
I915_WRITE(SWF30, dev_priv->saveSWF[14]);
|
||||
I915_WRITE(SWF31, dev_priv->saveSWF[15]);
|
||||
I915_WRITE(SWF32, dev_priv->saveSWF[16]);
|
||||
|
||||
#if 0 /* FIXME: restore VGA bits */
|
||||
vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS);
|
||||
vgaHWLock(hwp);
|
||||
#endif
|
||||
|
||||
drm_initial_config(dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static struct drm_driver driver = {
|
||||
/* don't use mtrr's here, the Xserver or user space app should
|
||||
|
@ -113,6 +342,8 @@ static struct drm_driver driver = {
|
|||
.id_table = pciidlist,
|
||||
.probe = probe,
|
||||
.remove = __devexit_p(drm_cleanup_pci),
|
||||
.suspend = i915_suspend,
|
||||
.resume = i915_resume,
|
||||
},
|
||||
#ifdef I915_HAVE_FENCE
|
||||
.fence_driver = &i915_fence_driver,
|
||||
|
|
|
@ -227,6 +227,7 @@ extern int i915_dma_cleanup(drm_device_t * dev);
|
|||
extern int i915_irq_emit(DRM_IOCTL_ARGS);
|
||||
extern int i915_irq_wait(DRM_IOCTL_ARGS);
|
||||
|
||||
extern void i915_driver_wait_next_vblank(drm_device_t *dev, int pipe);
|
||||
extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
|
||||
extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
|
||||
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
|
@ -395,6 +396,39 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
# define GPIO_DATA_VAL_IN (1 << 12)
|
||||
# define GPIO_DATA_PULLUP_DISABLE (1 << 13)
|
||||
|
||||
/* p317, 319
|
||||
*/
|
||||
#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */
|
||||
#define VCLK2_VCO_N 0x600a
|
||||
#define VCLK2_VCO_DIV_SEL 0x6012
|
||||
|
||||
#define VCLK_DIVISOR_VGA0 0x6000
|
||||
#define VCLK_DIVISOR_VGA1 0x6004
|
||||
#define VCLK_POST_DIV 0x6010
|
||||
/** Selects a post divisor of 4 instead of 2. */
|
||||
# define VGA1_PD_P2_DIV_4 (1 << 15)
|
||||
/** Overrides the p2 post divisor field */
|
||||
# define VGA1_PD_P1_DIV_2 (1 << 13)
|
||||
# define VGA1_PD_P1_SHIFT 8
|
||||
/** P1 value is 2 greater than this field */
|
||||
# define VGA1_PD_P1_MASK (0x1f << 8)
|
||||
/** Selects a post divisor of 4 instead of 2. */
|
||||
# define VGA0_PD_P2_DIV_4 (1 << 7)
|
||||
/** Overrides the p2 post divisor field */
|
||||
# define VGA0_PD_P1_DIV_2 (1 << 5)
|
||||
# define VGA0_PD_P1_SHIFT 0
|
||||
/** P1 value is 2 greater than this field */
|
||||
# define VGA0_PD_P1_MASK (0x1f << 0)
|
||||
|
||||
#define POST_DIV_SELECT 0x70
|
||||
#define POST_DIV_1 0x00
|
||||
#define POST_DIV_2 0x10
|
||||
#define POST_DIV_4 0x20
|
||||
#define POST_DIV_8 0x30
|
||||
#define POST_DIV_16 0x40
|
||||
#define POST_DIV_32 0x50
|
||||
#define VCO_LOOP_DIV_BY_4M 0x00
|
||||
#define VCO_LOOP_DIV_BY_16M 0x04
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
|
@ -906,6 +940,58 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
|
|||
# define VGA_2X_MODE (1 << 30)
|
||||
# define VGA_PIPE_B_SELECT (1 << 29)
|
||||
|
||||
/*
|
||||
* Some BIOS scratch area registers. The 845 (and 830?) store the amount
|
||||
* of video memory available to the BIOS in SWF1.
|
||||
*/
|
||||
|
||||
#define SWF0 0x71410
|
||||
#define SWF1 0x71414
|
||||
#define SWF2 0x71418
|
||||
#define SWF3 0x7141c
|
||||
#define SWF4 0x71420
|
||||
#define SWF5 0x71424
|
||||
#define SWF6 0x71428
|
||||
|
||||
/*
|
||||
* 855 scratch registers.
|
||||
*/
|
||||
#define SWF00 0x70410
|
||||
#define SWF01 0x70414
|
||||
#define SWF02 0x70418
|
||||
#define SWF03 0x7041c
|
||||
#define SWF04 0x70420
|
||||
#define SWF05 0x70424
|
||||
#define SWF06 0x70428
|
||||
|
||||
#define SWF10 SWF0
|
||||
#define SWF11 SWF1
|
||||
#define SWF12 SWF2
|
||||
#define SWF13 SWF3
|
||||
#define SWF14 SWF4
|
||||
#define SWF15 SWF5
|
||||
#define SWF16 SWF6
|
||||
|
||||
#define SWF30 0x72414
|
||||
#define SWF31 0x72418
|
||||
#define SWF32 0x7241c
|
||||
|
||||
/*
|
||||
* Overlay registers. These are overlay registers accessed via MMIO.
|
||||
* Those loaded via the overlay register page are defined in i830_video.c.
|
||||
*/
|
||||
#define OVADD 0x30000
|
||||
|
||||
#define DOVSTA 0x30008
|
||||
#define OC_BUF (0x3<<20)
|
||||
|
||||
#define OGAMC5 0x30010
|
||||
#define OGAMC4 0x30014
|
||||
#define OGAMC3 0x30018
|
||||
#define OGAMC2 0x3001c
|
||||
#define OGAMC1 0x30020
|
||||
#define OGAMC0 0x30024
|
||||
|
||||
/*
|
||||
* Palette registers
|
||||
*/
|
||||
|
|
|
@ -438,6 +438,19 @@ static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void i915_driver_wait_next_vblank(drm_device_t *dev, int pipe)
|
||||
{
|
||||
unsigned int seq;
|
||||
|
||||
seq = pipe ? atomic_read(&dev->vbl_received2) + 1 :
|
||||
atomic_read(&dev->vbl_received) + 1;
|
||||
|
||||
if (!pipe)
|
||||
i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received);
|
||||
else
|
||||
i915_driver_vblank_do_wait(dev, &seq, &dev->vbl_received2);
|
||||
}
|
||||
|
||||
int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
|
||||
{
|
||||
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
|
||||
|
|
Loading…
Reference in New Issue