1317c35d1SJesse Barnes /* 2317c35d1SJesse Barnes * 3317c35d1SJesse Barnes * Copyright 2008 (c) Intel Corporation 4317c35d1SJesse Barnes * Jesse Barnes <jbarnes@virtuousgeek.org> 5317c35d1SJesse Barnes * 6317c35d1SJesse Barnes * Permission is hereby granted, free of charge, to any person obtaining a 7317c35d1SJesse Barnes * copy of this software and associated documentation files (the 8317c35d1SJesse Barnes * "Software"), to deal in the Software without restriction, including 9317c35d1SJesse Barnes * without limitation the rights to use, copy, modify, merge, publish, 10317c35d1SJesse Barnes * distribute, sub license, and/or sell copies of the Software, and to 11317c35d1SJesse Barnes * permit persons to whom the Software is furnished to do so, subject to 12317c35d1SJesse Barnes * the following conditions: 13317c35d1SJesse Barnes * 14317c35d1SJesse Barnes * The above copyright notice and this permission notice (including the 15317c35d1SJesse Barnes * next paragraph) shall be included in all copies or substantial portions 16317c35d1SJesse Barnes * of the Software. 17317c35d1SJesse Barnes * 18317c35d1SJesse Barnes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19317c35d1SJesse Barnes * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20317c35d1SJesse Barnes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21317c35d1SJesse Barnes * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22317c35d1SJesse Barnes * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23317c35d1SJesse Barnes * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24317c35d1SJesse Barnes * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25317c35d1SJesse Barnes */ 26317c35d1SJesse Barnes 27317c35d1SJesse Barnes #include "drmP.h" 28317c35d1SJesse Barnes #include "drm.h" 29317c35d1SJesse Barnes #include "i915_drm.h" 30317c35d1SJesse Barnes #include "i915_drv.h" 31317c35d1SJesse Barnes 32317c35d1SJesse Barnes static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe) 33317c35d1SJesse Barnes { 34317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 35317c35d1SJesse Barnes 36317c35d1SJesse Barnes if (pipe == PIPE_A) 37317c35d1SJesse Barnes return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE); 38317c35d1SJesse Barnes else 39317c35d1SJesse Barnes return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE); 40317c35d1SJesse Barnes } 41317c35d1SJesse Barnes 42317c35d1SJesse Barnes static void i915_save_palette(struct drm_device *dev, enum pipe pipe) 43317c35d1SJesse Barnes { 44317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 45317c35d1SJesse Barnes unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); 46317c35d1SJesse Barnes u32 *array; 47317c35d1SJesse Barnes int i; 48317c35d1SJesse Barnes 49317c35d1SJesse Barnes if (!i915_pipe_enabled(dev, pipe)) 50317c35d1SJesse Barnes return; 51317c35d1SJesse Barnes 52317c35d1SJesse Barnes if (pipe == PIPE_A) 53317c35d1SJesse Barnes array = dev_priv->save_palette_a; 54317c35d1SJesse Barnes else 55317c35d1SJesse Barnes array = dev_priv->save_palette_b; 56317c35d1SJesse Barnes 57317c35d1SJesse Barnes for(i = 0; i < 256; i++) 58317c35d1SJesse Barnes array[i] = I915_READ(reg + (i << 2)); 59317c35d1SJesse Barnes } 60317c35d1SJesse Barnes 61317c35d1SJesse Barnes static void i915_restore_palette(struct drm_device *dev, enum pipe pipe) 62317c35d1SJesse Barnes { 63317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 64317c35d1SJesse Barnes unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B); 65317c35d1SJesse Barnes u32 *array; 66317c35d1SJesse Barnes int i; 67317c35d1SJesse Barnes 68317c35d1SJesse Barnes if (!i915_pipe_enabled(dev, pipe)) 69317c35d1SJesse Barnes return; 70317c35d1SJesse Barnes 71317c35d1SJesse Barnes if (pipe == PIPE_A) 72317c35d1SJesse Barnes array = dev_priv->save_palette_a; 73317c35d1SJesse Barnes else 74317c35d1SJesse Barnes array = dev_priv->save_palette_b; 75317c35d1SJesse Barnes 76317c35d1SJesse Barnes for(i = 0; i < 256; i++) 77317c35d1SJesse Barnes I915_WRITE(reg + (i << 2), array[i]); 78317c35d1SJesse Barnes } 79317c35d1SJesse Barnes 80317c35d1SJesse Barnes static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg) 81317c35d1SJesse Barnes { 82317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 83317c35d1SJesse Barnes 84317c35d1SJesse Barnes I915_WRITE8(index_port, reg); 85317c35d1SJesse Barnes return I915_READ8(data_port); 86317c35d1SJesse Barnes } 87317c35d1SJesse Barnes 88317c35d1SJesse Barnes static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable) 89317c35d1SJesse Barnes { 90317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 91317c35d1SJesse Barnes 92317c35d1SJesse Barnes I915_READ8(st01); 93317c35d1SJesse Barnes I915_WRITE8(VGA_AR_INDEX, palette_enable | reg); 94317c35d1SJesse Barnes return I915_READ8(VGA_AR_DATA_READ); 95317c35d1SJesse Barnes } 96317c35d1SJesse Barnes 97317c35d1SJesse Barnes static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable) 98317c35d1SJesse Barnes { 99317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 100317c35d1SJesse Barnes 101317c35d1SJesse Barnes I915_READ8(st01); 102317c35d1SJesse Barnes I915_WRITE8(VGA_AR_INDEX, palette_enable | reg); 103317c35d1SJesse Barnes I915_WRITE8(VGA_AR_DATA_WRITE, val); 104317c35d1SJesse Barnes } 105317c35d1SJesse Barnes 106317c35d1SJesse Barnes static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val) 107317c35d1SJesse Barnes { 108317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 109317c35d1SJesse Barnes 110317c35d1SJesse Barnes I915_WRITE8(index_port, reg); 111317c35d1SJesse Barnes I915_WRITE8(data_port, val); 112317c35d1SJesse Barnes } 113317c35d1SJesse Barnes 114317c35d1SJesse Barnes static void i915_save_vga(struct drm_device *dev) 115317c35d1SJesse Barnes { 116317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 117317c35d1SJesse Barnes int i; 118317c35d1SJesse Barnes u16 cr_index, cr_data, st01; 119317c35d1SJesse Barnes 120317c35d1SJesse Barnes /* VGA color palette registers */ 121317c35d1SJesse Barnes dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); 122317c35d1SJesse Barnes /* DACCRX automatically increments during read */ 123317c35d1SJesse Barnes I915_WRITE8(VGA_DACRX, 0); 124317c35d1SJesse Barnes /* Read 3 bytes of color data from each index */ 125317c35d1SJesse Barnes for (i = 0; i < 256 * 3; i++) 126317c35d1SJesse Barnes dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); 127317c35d1SJesse Barnes 128317c35d1SJesse Barnes /* MSR bits */ 129317c35d1SJesse Barnes dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); 130317c35d1SJesse Barnes if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) { 131317c35d1SJesse Barnes cr_index = VGA_CR_INDEX_CGA; 132317c35d1SJesse Barnes cr_data = VGA_CR_DATA_CGA; 133317c35d1SJesse Barnes st01 = VGA_ST01_CGA; 134317c35d1SJesse Barnes } else { 135317c35d1SJesse Barnes cr_index = VGA_CR_INDEX_MDA; 136317c35d1SJesse Barnes cr_data = VGA_CR_DATA_MDA; 137317c35d1SJesse Barnes st01 = VGA_ST01_MDA; 138317c35d1SJesse Barnes } 139317c35d1SJesse Barnes 140317c35d1SJesse Barnes /* CRT controller regs */ 141317c35d1SJesse Barnes i915_write_indexed(dev, cr_index, cr_data, 0x11, 142317c35d1SJesse Barnes i915_read_indexed(dev, cr_index, cr_data, 0x11) & 143317c35d1SJesse Barnes (~0x80)); 144317c35d1SJesse Barnes for (i = 0; i <= 0x24; i++) 145317c35d1SJesse Barnes dev_priv->saveCR[i] = 146317c35d1SJesse Barnes i915_read_indexed(dev, cr_index, cr_data, i); 147317c35d1SJesse Barnes /* Make sure we don't turn off CR group 0 writes */ 148317c35d1SJesse Barnes dev_priv->saveCR[0x11] &= ~0x80; 149317c35d1SJesse Barnes 150317c35d1SJesse Barnes /* Attribute controller registers */ 151317c35d1SJesse Barnes I915_READ8(st01); 152317c35d1SJesse Barnes dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX); 153317c35d1SJesse Barnes for (i = 0; i <= 0x14; i++) 154317c35d1SJesse Barnes dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0); 155317c35d1SJesse Barnes I915_READ8(st01); 156317c35d1SJesse Barnes I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX); 157317c35d1SJesse Barnes I915_READ8(st01); 158317c35d1SJesse Barnes 159317c35d1SJesse Barnes /* Graphics controller registers */ 160317c35d1SJesse Barnes for (i = 0; i < 9; i++) 161317c35d1SJesse Barnes dev_priv->saveGR[i] = 162317c35d1SJesse Barnes i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i); 163317c35d1SJesse Barnes 164317c35d1SJesse Barnes dev_priv->saveGR[0x10] = 165317c35d1SJesse Barnes i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10); 166317c35d1SJesse Barnes dev_priv->saveGR[0x11] = 167317c35d1SJesse Barnes i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11); 168317c35d1SJesse Barnes dev_priv->saveGR[0x18] = 169317c35d1SJesse Barnes i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18); 170317c35d1SJesse Barnes 171317c35d1SJesse Barnes /* Sequencer registers */ 172317c35d1SJesse Barnes for (i = 0; i < 8; i++) 173317c35d1SJesse Barnes dev_priv->saveSR[i] = 174317c35d1SJesse Barnes i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i); 175317c35d1SJesse Barnes } 176317c35d1SJesse Barnes 177317c35d1SJesse Barnes static void i915_restore_vga(struct drm_device *dev) 178317c35d1SJesse Barnes { 179317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 180317c35d1SJesse Barnes int i; 181317c35d1SJesse Barnes u16 cr_index, cr_data, st01; 182317c35d1SJesse Barnes 183317c35d1SJesse Barnes /* MSR bits */ 184317c35d1SJesse Barnes I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR); 185317c35d1SJesse Barnes if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) { 186317c35d1SJesse Barnes cr_index = VGA_CR_INDEX_CGA; 187317c35d1SJesse Barnes cr_data = VGA_CR_DATA_CGA; 188317c35d1SJesse Barnes st01 = VGA_ST01_CGA; 189317c35d1SJesse Barnes } else { 190317c35d1SJesse Barnes cr_index = VGA_CR_INDEX_MDA; 191317c35d1SJesse Barnes cr_data = VGA_CR_DATA_MDA; 192317c35d1SJesse Barnes st01 = VGA_ST01_MDA; 193317c35d1SJesse Barnes } 194317c35d1SJesse Barnes 195317c35d1SJesse Barnes /* Sequencer registers, don't write SR07 */ 196317c35d1SJesse Barnes for (i = 0; i < 7; i++) 197317c35d1SJesse Barnes i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i, 198317c35d1SJesse Barnes dev_priv->saveSR[i]); 199317c35d1SJesse Barnes 200317c35d1SJesse Barnes /* CRT controller regs */ 201317c35d1SJesse Barnes /* Enable CR group 0 writes */ 202317c35d1SJesse Barnes i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]); 203317c35d1SJesse Barnes for (i = 0; i <= 0x24; i++) 204317c35d1SJesse Barnes i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]); 205317c35d1SJesse Barnes 206317c35d1SJesse Barnes /* Graphics controller regs */ 207317c35d1SJesse Barnes for (i = 0; i < 9; i++) 208317c35d1SJesse Barnes i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i, 209317c35d1SJesse Barnes dev_priv->saveGR[i]); 210317c35d1SJesse Barnes 211317c35d1SJesse Barnes i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10, 212317c35d1SJesse Barnes dev_priv->saveGR[0x10]); 213317c35d1SJesse Barnes i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11, 214317c35d1SJesse Barnes dev_priv->saveGR[0x11]); 215317c35d1SJesse Barnes i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18, 216317c35d1SJesse Barnes dev_priv->saveGR[0x18]); 217317c35d1SJesse Barnes 218317c35d1SJesse Barnes /* Attribute controller registers */ 219317c35d1SJesse Barnes I915_READ8(st01); /* switch back to index mode */ 220317c35d1SJesse Barnes for (i = 0; i <= 0x14; i++) 221317c35d1SJesse Barnes i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0); 222317c35d1SJesse Barnes I915_READ8(st01); /* switch back to index mode */ 223317c35d1SJesse Barnes I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20); 224317c35d1SJesse Barnes I915_READ8(st01); 225317c35d1SJesse Barnes 226317c35d1SJesse Barnes /* VGA color palette registers */ 227317c35d1SJesse Barnes I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); 228317c35d1SJesse Barnes /* DACCRX automatically increments during read */ 229317c35d1SJesse Barnes I915_WRITE8(VGA_DACWX, 0); 230317c35d1SJesse Barnes /* Read 3 bytes of color data from each index */ 231317c35d1SJesse Barnes for (i = 0; i < 256 * 3; i++) 232317c35d1SJesse Barnes I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); 233317c35d1SJesse Barnes 234317c35d1SJesse Barnes } 235317c35d1SJesse Barnes 236317c35d1SJesse Barnes int i915_save_state(struct drm_device *dev) 237317c35d1SJesse Barnes { 238317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 239317c35d1SJesse Barnes int i; 240317c35d1SJesse Barnes 241317c35d1SJesse Barnes pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); 242317c35d1SJesse Barnes 243317c35d1SJesse Barnes /* Display arbitration control */ 244317c35d1SJesse Barnes dev_priv->saveDSPARB = I915_READ(DSPARB); 245317c35d1SJesse Barnes 246317c35d1SJesse Barnes /* Pipe & plane A info */ 247317c35d1SJesse Barnes dev_priv->savePIPEACONF = I915_READ(PIPEACONF); 248317c35d1SJesse Barnes dev_priv->savePIPEASRC = I915_READ(PIPEASRC); 249317c35d1SJesse Barnes dev_priv->saveFPA0 = I915_READ(FPA0); 250317c35d1SJesse Barnes dev_priv->saveFPA1 = I915_READ(FPA1); 251317c35d1SJesse Barnes dev_priv->saveDPLL_A = I915_READ(DPLL_A); 252317c35d1SJesse Barnes if (IS_I965G(dev)) 253317c35d1SJesse Barnes dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); 254317c35d1SJesse Barnes dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); 255317c35d1SJesse Barnes dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); 256317c35d1SJesse Barnes dev_priv->saveHSYNC_A = I915_READ(HSYNC_A); 257317c35d1SJesse Barnes dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); 258317c35d1SJesse Barnes dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); 259317c35d1SJesse Barnes dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); 260317c35d1SJesse Barnes dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); 261317c35d1SJesse Barnes 262317c35d1SJesse Barnes dev_priv->saveDSPACNTR = I915_READ(DSPACNTR); 263317c35d1SJesse Barnes dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE); 264317c35d1SJesse Barnes dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); 265317c35d1SJesse Barnes dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); 266317c35d1SJesse Barnes dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); 267317c35d1SJesse Barnes if (IS_I965G(dev)) { 268317c35d1SJesse Barnes dev_priv->saveDSPASURF = I915_READ(DSPASURF); 269317c35d1SJesse Barnes dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); 270317c35d1SJesse Barnes } 271317c35d1SJesse Barnes i915_save_palette(dev, PIPE_A); 272317c35d1SJesse Barnes dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT); 273317c35d1SJesse Barnes 274317c35d1SJesse Barnes /* Pipe & plane B info */ 275317c35d1SJesse Barnes dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); 276317c35d1SJesse Barnes dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); 277317c35d1SJesse Barnes dev_priv->saveFPB0 = I915_READ(FPB0); 278317c35d1SJesse Barnes dev_priv->saveFPB1 = I915_READ(FPB1); 279317c35d1SJesse Barnes dev_priv->saveDPLL_B = I915_READ(DPLL_B); 280317c35d1SJesse Barnes if (IS_I965G(dev)) 281317c35d1SJesse Barnes dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); 282317c35d1SJesse Barnes dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); 283317c35d1SJesse Barnes dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); 284317c35d1SJesse Barnes dev_priv->saveHSYNC_B = I915_READ(HSYNC_B); 285317c35d1SJesse Barnes dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); 286317c35d1SJesse Barnes dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); 287317c35d1SJesse Barnes dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); 288317c35d1SJesse Barnes dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); 289317c35d1SJesse Barnes 290317c35d1SJesse Barnes dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); 291317c35d1SJesse Barnes dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); 292317c35d1SJesse Barnes dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); 293317c35d1SJesse Barnes dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); 294317c35d1SJesse Barnes dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); 295*b9bfdfe6SJesse Barnes if (IS_I965GM(dev) || IS_GM45(dev)) { 296317c35d1SJesse Barnes dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); 297317c35d1SJesse Barnes dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); 298317c35d1SJesse Barnes } 299317c35d1SJesse Barnes i915_save_palette(dev, PIPE_B); 300317c35d1SJesse Barnes dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); 301317c35d1SJesse Barnes 302317c35d1SJesse Barnes /* CRT state */ 303317c35d1SJesse Barnes dev_priv->saveADPA = I915_READ(ADPA); 304317c35d1SJesse Barnes 305317c35d1SJesse Barnes /* LVDS state */ 306317c35d1SJesse Barnes dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); 307317c35d1SJesse Barnes dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); 308317c35d1SJesse Barnes dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); 309317c35d1SJesse Barnes if (IS_I965G(dev)) 310317c35d1SJesse Barnes dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); 311317c35d1SJesse Barnes if (IS_MOBILE(dev) && !IS_I830(dev)) 312317c35d1SJesse Barnes dev_priv->saveLVDS = I915_READ(LVDS); 313317c35d1SJesse Barnes if (!IS_I830(dev) && !IS_845G(dev)) 314317c35d1SJesse Barnes dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); 315317c35d1SJesse Barnes dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); 316317c35d1SJesse Barnes dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); 317317c35d1SJesse Barnes dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); 318317c35d1SJesse Barnes 319317c35d1SJesse Barnes /* FIXME: save TV & SDVO state */ 320317c35d1SJesse Barnes 321317c35d1SJesse Barnes /* FBC state */ 322317c35d1SJesse Barnes dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); 323317c35d1SJesse Barnes dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); 324317c35d1SJesse Barnes dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); 325317c35d1SJesse Barnes dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); 326317c35d1SJesse Barnes 327317c35d1SJesse Barnes /* Interrupt state */ 328317c35d1SJesse Barnes dev_priv->saveIIR = I915_READ(IIR); 329317c35d1SJesse Barnes dev_priv->saveIER = I915_READ(IER); 330317c35d1SJesse Barnes dev_priv->saveIMR = I915_READ(IMR); 331317c35d1SJesse Barnes 332317c35d1SJesse Barnes /* VGA state */ 333317c35d1SJesse Barnes dev_priv->saveVGA0 = I915_READ(VGA0); 334317c35d1SJesse Barnes dev_priv->saveVGA1 = I915_READ(VGA1); 335317c35d1SJesse Barnes dev_priv->saveVGA_PD = I915_READ(VGA_PD); 336317c35d1SJesse Barnes dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); 337317c35d1SJesse Barnes 338317c35d1SJesse Barnes /* Clock gating state */ 339317c35d1SJesse Barnes dev_priv->saveD_STATE = I915_READ(D_STATE); 340317c35d1SJesse Barnes dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS); 341317c35d1SJesse Barnes 342317c35d1SJesse Barnes /* Cache mode state */ 343317c35d1SJesse Barnes dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); 344317c35d1SJesse Barnes 345317c35d1SJesse Barnes /* Memory Arbitration state */ 346317c35d1SJesse Barnes dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); 347317c35d1SJesse Barnes 348317c35d1SJesse Barnes /* Scratch space */ 349317c35d1SJesse Barnes for (i = 0; i < 16; i++) { 350317c35d1SJesse Barnes dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2)); 351317c35d1SJesse Barnes dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2)); 352317c35d1SJesse Barnes } 353317c35d1SJesse Barnes for (i = 0; i < 3; i++) 354317c35d1SJesse Barnes dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); 355317c35d1SJesse Barnes 356317c35d1SJesse Barnes i915_save_vga(dev); 357317c35d1SJesse Barnes 358317c35d1SJesse Barnes return 0; 359317c35d1SJesse Barnes } 360317c35d1SJesse Barnes 361317c35d1SJesse Barnes int i915_restore_state(struct drm_device *dev) 362317c35d1SJesse Barnes { 363317c35d1SJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 364317c35d1SJesse Barnes int i; 365317c35d1SJesse Barnes 366317c35d1SJesse Barnes pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); 367317c35d1SJesse Barnes 368317c35d1SJesse Barnes I915_WRITE(DSPARB, dev_priv->saveDSPARB); 369317c35d1SJesse Barnes 370317c35d1SJesse Barnes /* Pipe & plane A info */ 371317c35d1SJesse Barnes /* Prime the clock */ 372317c35d1SJesse Barnes if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { 373317c35d1SJesse Barnes I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & 374317c35d1SJesse Barnes ~DPLL_VCO_ENABLE); 375317c35d1SJesse Barnes DRM_UDELAY(150); 376317c35d1SJesse Barnes } 377317c35d1SJesse Barnes I915_WRITE(FPA0, dev_priv->saveFPA0); 378317c35d1SJesse Barnes I915_WRITE(FPA1, dev_priv->saveFPA1); 379317c35d1SJesse Barnes /* Actually enable it */ 380317c35d1SJesse Barnes I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); 381317c35d1SJesse Barnes DRM_UDELAY(150); 382317c35d1SJesse Barnes if (IS_I965G(dev)) 383317c35d1SJesse Barnes I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); 384317c35d1SJesse Barnes DRM_UDELAY(150); 385317c35d1SJesse Barnes 386317c35d1SJesse Barnes /* Restore mode */ 387317c35d1SJesse Barnes I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); 388317c35d1SJesse Barnes I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); 389317c35d1SJesse Barnes I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); 390317c35d1SJesse Barnes I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); 391317c35d1SJesse Barnes I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); 392317c35d1SJesse Barnes I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); 393317c35d1SJesse Barnes I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); 394317c35d1SJesse Barnes 395317c35d1SJesse Barnes /* Restore plane info */ 396317c35d1SJesse Barnes I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); 397317c35d1SJesse Barnes I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); 398317c35d1SJesse Barnes I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); 399317c35d1SJesse Barnes I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); 400317c35d1SJesse Barnes I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); 401317c35d1SJesse Barnes if (IS_I965G(dev)) { 402317c35d1SJesse Barnes I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); 403317c35d1SJesse Barnes I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); 404317c35d1SJesse Barnes } 405317c35d1SJesse Barnes 406317c35d1SJesse Barnes I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); 407317c35d1SJesse Barnes 408317c35d1SJesse Barnes i915_restore_palette(dev, PIPE_A); 409317c35d1SJesse Barnes /* Enable the plane */ 410317c35d1SJesse Barnes I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); 411317c35d1SJesse Barnes I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); 412317c35d1SJesse Barnes 413317c35d1SJesse Barnes /* Pipe & plane B info */ 414317c35d1SJesse Barnes if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { 415317c35d1SJesse Barnes I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & 416317c35d1SJesse Barnes ~DPLL_VCO_ENABLE); 417317c35d1SJesse Barnes DRM_UDELAY(150); 418317c35d1SJesse Barnes } 419317c35d1SJesse Barnes I915_WRITE(FPB0, dev_priv->saveFPB0); 420317c35d1SJesse Barnes I915_WRITE(FPB1, dev_priv->saveFPB1); 421317c35d1SJesse Barnes /* Actually enable it */ 422317c35d1SJesse Barnes I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); 423317c35d1SJesse Barnes DRM_UDELAY(150); 424317c35d1SJesse Barnes if (IS_I965G(dev)) 425317c35d1SJesse Barnes I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); 426317c35d1SJesse Barnes DRM_UDELAY(150); 427317c35d1SJesse Barnes 428317c35d1SJesse Barnes /* Restore mode */ 429317c35d1SJesse Barnes I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); 430317c35d1SJesse Barnes I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); 431317c35d1SJesse Barnes I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); 432317c35d1SJesse Barnes I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); 433317c35d1SJesse Barnes I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); 434317c35d1SJesse Barnes I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); 435317c35d1SJesse Barnes I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); 436317c35d1SJesse Barnes 437317c35d1SJesse Barnes /* Restore plane info */ 438317c35d1SJesse Barnes I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); 439317c35d1SJesse Barnes I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); 440317c35d1SJesse Barnes I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); 441317c35d1SJesse Barnes I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); 442317c35d1SJesse Barnes I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); 443317c35d1SJesse Barnes if (IS_I965G(dev)) { 444317c35d1SJesse Barnes I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); 445317c35d1SJesse Barnes I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); 446317c35d1SJesse Barnes } 447317c35d1SJesse Barnes 448317c35d1SJesse Barnes I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); 449317c35d1SJesse Barnes 450317c35d1SJesse Barnes i915_restore_palette(dev, PIPE_B); 451317c35d1SJesse Barnes /* Enable the plane */ 452317c35d1SJesse Barnes I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); 453317c35d1SJesse Barnes I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); 454317c35d1SJesse Barnes 455317c35d1SJesse Barnes /* CRT state */ 456317c35d1SJesse Barnes I915_WRITE(ADPA, dev_priv->saveADPA); 457317c35d1SJesse Barnes 458317c35d1SJesse Barnes /* LVDS state */ 459317c35d1SJesse Barnes if (IS_I965G(dev)) 460317c35d1SJesse Barnes I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); 461317c35d1SJesse Barnes if (IS_MOBILE(dev) && !IS_I830(dev)) 462317c35d1SJesse Barnes I915_WRITE(LVDS, dev_priv->saveLVDS); 463317c35d1SJesse Barnes if (!IS_I830(dev) && !IS_845G(dev)) 464317c35d1SJesse Barnes I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); 465317c35d1SJesse Barnes 466317c35d1SJesse Barnes I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); 467317c35d1SJesse Barnes I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); 468317c35d1SJesse Barnes I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); 469317c35d1SJesse Barnes I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); 470317c35d1SJesse Barnes I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); 471317c35d1SJesse Barnes I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); 472317c35d1SJesse Barnes 473317c35d1SJesse Barnes /* FIXME: restore TV & SDVO state */ 474317c35d1SJesse Barnes 475317c35d1SJesse Barnes /* FBC info */ 476317c35d1SJesse Barnes I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); 477317c35d1SJesse Barnes I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); 478317c35d1SJesse Barnes I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); 479317c35d1SJesse Barnes I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); 480317c35d1SJesse Barnes 481317c35d1SJesse Barnes /* VGA state */ 482317c35d1SJesse Barnes I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); 483317c35d1SJesse Barnes I915_WRITE(VGA0, dev_priv->saveVGA0); 484317c35d1SJesse Barnes I915_WRITE(VGA1, dev_priv->saveVGA1); 485317c35d1SJesse Barnes I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); 486317c35d1SJesse Barnes DRM_UDELAY(150); 487317c35d1SJesse Barnes 488317c35d1SJesse Barnes /* Clock gating state */ 489317c35d1SJesse Barnes I915_WRITE (D_STATE, dev_priv->saveD_STATE); 490317c35d1SJesse Barnes I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS); 491317c35d1SJesse Barnes 492317c35d1SJesse Barnes /* Cache mode state */ 493317c35d1SJesse Barnes I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); 494317c35d1SJesse Barnes 495317c35d1SJesse Barnes /* Memory arbitration state */ 496317c35d1SJesse Barnes I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); 497317c35d1SJesse Barnes 498317c35d1SJesse Barnes for (i = 0; i < 16; i++) { 499317c35d1SJesse Barnes I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]); 500317c35d1SJesse Barnes I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]); 501317c35d1SJesse Barnes } 502317c35d1SJesse Barnes for (i = 0; i < 3; i++) 503317c35d1SJesse Barnes I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); 504317c35d1SJesse Barnes 505317c35d1SJesse Barnes i915_restore_vga(dev); 506317c35d1SJesse Barnes 507317c35d1SJesse Barnes return 0; 508317c35d1SJesse Barnes } 509317c35d1SJesse Barnes 510