diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 1ba15d9..b68fb55 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -31,12 +31,6 @@ #include "i915_drm.h" #include "i915_drv.h" -#define IS_I965G(dev) (dev->pci_device == 0x2972 || \ - dev->pci_device == 0x2982 || \ - dev->pci_device == 0x2992 || \ - dev->pci_device == 0x29A2 || \ - dev->pci_device == 0x2A02) - /* Really want an OS-independent resettable timer. Would like to have * this loop run for (eg) 3 sec, but have the timer reset every time * the head pointer changes, so that EBUSY only happens if the ring diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 85bcc27..f0c19ed 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c @@ -38,6 +38,208 @@ static struct pci_device_id pciidlist[] = { i915_PCI_IDS }; +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; + 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); + dev_priv->saveLDD = pci_read_config_long(dev, LDD, 4); + + for(i= 0; i < 256; i++) + dev_priv->savePaletteA[i] = I915_READ(PALETTE_A + (i << 2)); +#if 0 + 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)); + } +#endif + 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); + +#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; + int i; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + if (pci_enable_device(pdev)) + return -1; + + 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_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); + I915_WRITE(DSPABASE, I915_READ(DSPABASE)); + +#if 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_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); + I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); + } +#endif + 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 0 + if(dev->mode_config.num_crtc == 2) + for(i= 0; i < 256; i++) + I915_WRITE(PALETTE_B + (i << 2), dev_priv->savePaletteB[i]); +#endif + 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 + pci_write_config_long(pdev, dev_priv->saveLDD, 4); + + return 0; +} + static struct drm_driver driver = { /* don't use mtrr's here, the Xserver or user space app should * deal with them for intel hardware. @@ -76,6 +278,8 @@ static struct drm_driver driver = { .pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, + .suspend = i915_suspend, + .resume = i915_resume, }, .name = DRIVER_NAME, diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 93cdcfe..adb55f3 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -112,6 +112,63 @@ typedef struct drm_i915_private { spinlock_t swaps_lock; drm_i915_vbl_swap_t vbl_swaps; unsigned int swaps_pending; + + /* Register state */ + u32 saveLDD; + u32 saveDSPACNTR; + u32 saveDSPBCNTR; + u32 savePIPEACONF; + u32 savePIPEBCONF; + u32 savePIPEASRC; + u32 savePIPEBSRC; + u32 saveFPA0; + u32 saveFPA1; + u32 saveDPLL_A; + u32 saveDPLL_A_MD; + u32 saveHTOTAL_A; + u32 saveHBLANK_A; + u32 saveHSYNC_A; + u32 saveVTOTAL_A; + u32 saveVBLANK_A; + u32 saveVSYNC_A; + u32 saveDSPASTRIDE; + u32 saveDSPASIZE; + u32 saveDSPAPOS; + u32 saveDSPABASE; + u32 saveDSPASURF; + u32 saveFPB0; + u32 saveFPB1; + u32 saveDPLL_B; + u32 saveDPLL_B_MD; + u32 saveHTOTAL_B; + u32 saveHBLANK_B; + u32 saveHSYNC_B; + u32 saveVTOTAL_B; + u32 saveVBLANK_B; + u32 saveVSYNC_B; + u32 saveDSPBSTRIDE; + u32 saveDSPBSIZE; + u32 saveDSPBPOS; + u32 saveDSPBBASE; + u32 saveDSPBSURF; + u32 saveVCLK_DIVISOR_VGA0; + u32 saveVCLK_DIVISOR_VGA1; + u32 saveVCLK_POST_DIV; + u32 saveVGACNTRL; + u32 saveADPA; + u32 saveLVDS; + u32 saveDVOA; + u32 saveDVOB; + u32 saveDVOC; + u32 savePP_ON; + u32 savePP_OFF; + u32 savePP_CONTROL; + u32 savePP_CYCLE; + u32 savePFIT_CONTROL; + u32 savePaletteA[256]; + u32 savePaletteB[256]; + u32 saveSWF[17]; + u32 saveBLC_PWM_CTL; } drm_i915_private_t; extern drm_ioctl_desc_t i915_ioctls[]; @@ -198,6 +255,9 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define INST_OP_FLUSH 0x02000000 #define INST_FLUSH_MAP_CACHE 0x00000001 +/* Config space */ +#define LDD 0xf4 + #define BB1_START_ADDR_MASK (~0x7) #define BB1_PROTECTED (1<<0) #define BB1_UNPROTECTED (0<<0) @@ -294,4 +354,526 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5]) +#define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +/** + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BLM_LEGACY_MODE (1 << 16) +/** + * This is the number of cycles out of the backlight modulation cycle for which + * the backlight is on. + * + * This field must be no greater than the number of cycles in the complete + * backlight modulation cycle. + */ +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) + +#define I915_GCFGC 0xf0 +#define I915_LOW_FREQUENCY_ENABLE (1 << 7) +#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) +#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) +#define I915_DISPLAY_CLOCK_MASK (7 << 4) + +#define I855_HPLLCC 0xc0 +#define I855_CLOCK_CONTROL_MASK (3 << 0) +#define I855_CLOCK_133_200 (0 << 0) +#define I855_CLOCK_100_200 (1 << 0) +#define I855_CLOCK_100_133 (2 << 0) +#define I855_CLOCK_166_250 (3 << 0) + +/* 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) + +/* I830 CRTC registers */ +#define HTOTAL_A 0x60000 +#define HBLANK_A 0x60004 +#define HSYNC_A 0x60008 +#define VTOTAL_A 0x6000c +#define VBLANK_A 0x60010 +#define VSYNC_A 0x60014 +#define PIPEASRC 0x6001c +#define BCLRPAT_A 0x60020 +#define VSYNCSHIFT_A 0x60028 + +#define HTOTAL_B 0x61000 +#define HBLANK_B 0x61004 +#define HSYNC_B 0x61008 +#define VTOTAL_B 0x6100c +#define VBLANK_B 0x61010 +#define VSYNC_B 0x61014 +#define PIPEBSRC 0x6101c +#define BCLRPAT_B 0x61020 +#define VSYNCSHIFT_B 0x61028 + +#define PP_STATUS 0x61200 +# define PP_ON (1 << 31) +/** + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +# define PP_READY (1 << 30) +# define PP_SEQUENCE_NONE (0 << 28) +# define PP_SEQUENCE_ON (1 << 28) +# define PP_SEQUENCE_OFF (2 << 28) +# define PP_SEQUENCE_MASK 0x30000000 +#define PP_CONTROL 0x61204 +# define POWER_TARGET_ON (1 << 0) + +#define LVDSPP_ON 0x61208 +#define LVDSPP_OFF 0x6120c +#define PP_CYCLE 0x61210 + +#define PFIT_CONTROL 0x61230 +# define PFIT_ENABLE (1 << 31) +# define PFIT_PIPE_MASK (3 << 29) +# define PFIT_PIPE_SHIFT 29 +# define VERT_INTERP_DISABLE (0 << 10) +# define VERT_INTERP_BILINEAR (1 << 10) +# define VERT_INTERP_MASK (3 << 10) +# define VERT_AUTO_SCALE (1 << 9) +# define HORIZ_INTERP_DISABLE (0 << 6) +# define HORIZ_INTERP_BILINEAR (1 << 6) +# define HORIZ_INTERP_MASK (3 << 6) +# define HORIZ_AUTO_SCALE (1 << 5) +# define PANEL_8TO6_DITHER_ENABLE (1 << 3) + +#define PFIT_PGM_RATIOS 0x61234 +# define PFIT_VERT_SCALE_MASK 0xfff00000 +# define PFIT_HORIZ_SCALE_MASK 0x0000fff0 + +#define PFIT_AUTO_RATIOS 0x61238 + + +#define DPLL_A 0x06014 +#define DPLL_B 0x06018 +# define DPLL_VCO_ENABLE (1 << 31) +# define DPLL_DVO_HIGH_SPEED (1 << 30) +# define DPLL_SYNCLOCK_ENABLE (1 << 29) +# define DPLL_VGA_MODE_DIS (1 << 28) +# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +# define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +# define DPLL_MODE_MASK (3 << 26) +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +/** + * The i830 generation, in DAC/serial mode, defines p1 as two plus this + * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. + */ +# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 +/** + * The i830 generation, in LVDS mode, defines P1 as the bit number set within + * this field (only one bit may be set). + */ +# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +# define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */ +# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +# define PLL_REF_INPUT_DREFCLK (0 << 13) +# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ +# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +# define PLL_REF_INPUT_MASK (3 << 13) +# define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +# define DISPLAY_RATE_SELECT_FPA1 (1 << 8) + +/** + * SDVO multiplier for 945G/GM. Not used on 965. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +# define SDVO_MULTIPLIER_MASK 0x000000ff +# define SDVO_MULTIPLIER_SHIFT_HIRES 4 +# define SDVO_MULTIPLIER_SHIFT_VGA 0 + +/** @defgroup DPLL_MD + * @{ + */ +/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_A_MD 0x0601c +/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_B_MD 0x06020 +/** + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +# define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/** + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ +# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +/** @} */ + +#define DPLL_TEST 0x606c +# define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +# define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +# define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +# define DPLLB_TEST_N_BYPASS (1 << 19) +# define DPLLB_TEST_M_BYPASS (1 << 18) +# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +# define DPLLA_TEST_N_BYPASS (1 << 3) +# define DPLLA_TEST_M_BYPASS (1 << 2) +# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) + +#define ADPA 0x61100 +#define ADPA_DAC_ENABLE (1<<31) +#define ADPA_DAC_DISABLE 0 +#define ADPA_PIPE_SELECT_MASK (1<<30) +#define ADPA_PIPE_A_SELECT 0 +#define ADPA_PIPE_B_SELECT (1<<30) +#define ADPA_USE_VGA_HVPOLARITY (1<<15) +#define ADPA_SETS_HVPOLARITY 0 +#define ADPA_VSYNC_CNTL_DISABLE (1<<11) +#define ADPA_VSYNC_CNTL_ENABLE 0 +#define ADPA_HSYNC_CNTL_DISABLE (1<<10) +#define ADPA_HSYNC_CNTL_ENABLE 0 +#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) +#define ADPA_VSYNC_ACTIVE_LOW 0 +#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) +#define ADPA_HSYNC_ACTIVE_LOW 0 + +#define FPA0 0x06040 +#define FPA1 0x06044 +#define FPB0 0x06048 +#define FPB1 0x0604c +# define FP_N_DIV_MASK 0x003f0000 +# define FP_N_DIV_SHIFT 16 +# define FP_M1_DIV_MASK 0x00003f00 +# define FP_M1_DIV_SHIFT 8 +# define FP_M2_DIV_MASK 0x0000003f +# define FP_M2_DIV_SHIFT 0 + + +#define PORT_HOTPLUG_EN 0x61110 +# define SDVOB_HOTPLUG_INT_EN (1 << 26) +# define SDVOC_HOTPLUG_INT_EN (1 << 25) +# define TV_HOTPLUG_INT_EN (1 << 18) +# define CRT_HOTPLUG_INT_EN (1 << 9) +# define CRT_HOTPLUG_FORCE_DETECT (1 << 3) + +#define PORT_HOTPLUG_STAT 0x61114 +# define CRT_HOTPLUG_INT_STATUS (1 << 11) +# define TV_HOTPLUG_INT_STATUS (1 << 10) +# define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +# define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +# define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +# define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +# define SDVOB_HOTPLUG_INT_STATUS (1 << 6) + +#define SDVOB 0x61140 +#define SDVOC 0x61160 +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_B_SELECT (1 << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/** + * 915G/GM SDVO pixel multiplier. + * + * Programmed value is multiplier - 1, up to 5x. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) +#define SDVO_BORDER_ENABLE (1 << 7) +#define SDVOB_PCIE_CONCURRENCY (1 << 3) +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) +#define SDVOC_PRESERVE_MASK (1 << 17) + +/** @defgroup LVDS + * @{ + */ +/** + * This register controls the LVDS output enable, pipe selection, and data + * format selection. + * + * All of the clock/data pairs are force powered down by power sequencing. + */ +#define LVDS 0x61180 +/** + * Enables the LVDS port. This bit must be set before DPLLs are enabled, as + * the DPLL semantics change when the LVDS is assigned to that pipe. + */ +# define LVDS_PORT_EN (1 << 31) +/** Selects pipe B for LVDS data. Must be set on pre-965. */ +# define LVDS_PIPEB_SELECT (1 << 30) + +/** + * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per + * pixel. + */ +# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) +# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) +# define LVDS_A0A2_CLKA_POWER_UP (3 << 8) +/** + * Controls the A3 data pair, which contains the additional LSBs for 24 bit + * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be + * on. + */ +# define LVDS_A3_POWER_MASK (3 << 6) +# define LVDS_A3_POWER_DOWN (0 << 6) +# define LVDS_A3_POWER_UP (3 << 6) +/** + * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP + * is set. + */ +# define LVDS_CLKB_POWER_MASK (3 << 4) +# define LVDS_CLKB_POWER_DOWN (0 << 4) +# define LVDS_CLKB_POWER_UP (3 << 4) + +/** + * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 + * setting for whether we are in dual-channel mode. The B3 pair will + * additionally only be powered up when LVDS_A3_POWER_UP is set. + */ +# define LVDS_B0B3_POWER_MASK (3 << 2) +# define LVDS_B0B3_POWER_DOWN (0 << 2) +# define LVDS_B0B3_POWER_UP (3 << 2) + +#define PIPEACONF 0x70008 +#define PIPEACONF_ENABLE (1<<31) +#define PIPEACONF_DISABLE 0 +#define PIPEACONF_DOUBLE_WIDE (1<<30) +#define I965_PIPECONF_ACTIVE (1<<30) +#define PIPEACONF_SINGLE_WIDE 0 +#define PIPEACONF_PIPE_UNLOCKED 0 +#define PIPEACONF_PIPE_LOCKED (1<<25) +#define PIPEACONF_PALETTE 0 +#define PIPEACONF_GAMMA (1<<24) +#define PIPECONF_FORCE_BORDER (1<<25) +#define PIPECONF_PROGRESSIVE (0 << 21) +#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) + +#define PIPEBCONF 0x71008 +#define PIPEBCONF_ENABLE (1<<31) +#define PIPEBCONF_DISABLE 0 +#define PIPEBCONF_DOUBLE_WIDE (1<<30) +#define PIPEBCONF_DISABLE 0 +#define PIPEBCONF_GAMMA (1<<24) +#define PIPEBCONF_PALETTE 0 + +#define PIPEBGCMAXRED 0x71010 +#define PIPEBGCMAXGREEN 0x71014 +#define PIPEBGCMAXBLUE 0x71018 +#define PIPEBSTAT 0x71024 +#define PIPEBFRAMEHIGH 0x71040 +#define PIPEBFRAMEPIXEL 0x71044 + +#define DSPACNTR 0x70180 +#define DSPBCNTR 0x71180 +#define DISPLAY_PLANE_ENABLE (1<<31) +#define DISPLAY_PLANE_DISABLE 0 +#define DISPPLANE_GAMMA_ENABLE (1<<30) +#define DISPPLANE_GAMMA_DISABLE 0 +#define DISPPLANE_PIXFORMAT_MASK (0xf<<26) +#define DISPPLANE_8BPP (0x2<<26) +#define DISPPLANE_15_16BPP (0x4<<26) +#define DISPPLANE_16BPP (0x5<<26) +#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) +#define DISPPLANE_32BPP (0x7<<26) +#define DISPPLANE_STEREO_ENABLE (1<<25) +#define DISPPLANE_STEREO_DISABLE 0 +#define DISPPLANE_SEL_PIPE_MASK (1<<24) +#define DISPPLANE_SEL_PIPE_A 0 +#define DISPPLANE_SEL_PIPE_B (1<<24) +#define DISPPLANE_SRC_KEY_ENABLE (1<<22) +#define DISPPLANE_SRC_KEY_DISABLE 0 +#define DISPPLANE_LINE_DOUBLE (1<<20) +#define DISPPLANE_NO_LINE_DOUBLE 0 +#define DISPPLANE_STEREO_POLARITY_FIRST 0 +#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) +/* plane B only */ +#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15) +#define DISPPLANE_ALPHA_TRANS_DISABLE 0 +#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 +#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) + +#define DSPABASE 0x70184 +#define DSPASTRIDE 0x70188 + +#define DSPBBASE 0x71184 +#define DSPBADDR DSPBBASE +#define DSPBSTRIDE 0x71188 + +#define DSPAKEYVAL 0x70194 +#define DSPAKEYMASK 0x70198 + +#define DSPAPOS 0x7018C /* reserved */ +#define DSPASIZE 0x70190 +#define DSPBPOS 0x7118C +#define DSPBSIZE 0x71190 + +#define DSPASURF 0x7019C +#define DSPATILEOFF 0x701A4 + +#define DSPBSURF 0x7119C +#define DSPBTILEOFF 0x711A4 + +#define VGACNTRL 0x71400 +# define VGA_DISP_DISABLE (1 << 31) +# 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 + */ +#define PALETTE_A 0x0a000 +#define PALETTE_B 0x0a800 + +#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC) +#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG) +#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) +#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG) +#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG) + +#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G)*/ +#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG) +#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG) +#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG) + +#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \ + (dev)->pci_device == 0x2982 || \ + (dev)->pci_device == 0x2992 || \ + (dev)->pci_device == 0x29A2 || \ + (dev)->pci_device == 0x2A02 || \ + (dev)->pci_device == 0x2A12) + +#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ + (dev)->pci_device == 0x29B2 || \ + (dev)->pci_device == 0x29D2) + +#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ + IS_I945GM(dev) || IS_I965G(dev)) + +#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ + IS_I945GM(dev)) + +#define PRIMARY_RINGBUFFER_SIZE (128*1024) + #endif