Home | History | Annotate | Line # | Download | only in shared-core
      1 /* i915_suspend.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
      2  */
      3 /*
      4  *
      5  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     23  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
     24  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     25  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     26  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  *
     28  */
     29 
     30 #include "drmP.h"
     31 #include "drm.h"
     32 #include "i915_drm.h"
     33 #include "i915_drv.h"
     34 
     35 static bool i915_pipe_enabled(struct drm_device *dev, enum pipex pipe)
     36 {
     37 	struct drm_i915_private *dev_priv = dev->dev_private;
     38 
     39 	if (pipe == PIPE_A)
     40 		return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
     41 	else
     42 		return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
     43 }
     44 
     45 static void i915_save_palette(struct drm_device *dev, enum pipex pipe)
     46 {
     47 	struct drm_i915_private *dev_priv = dev->dev_private;
     48 	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
     49 	u32 *array;
     50 	int i;
     51 
     52 	if (!i915_pipe_enabled(dev, pipe))
     53 		return;
     54 
     55 	if (pipe == PIPE_A)
     56 		array = dev_priv->save_palette_a;
     57 	else
     58 		array = dev_priv->save_palette_b;
     59 
     60 	for(i = 0; i < 256; i++)
     61 		array[i] = I915_READ(reg + (i << 2));
     62 }
     63 
     64 static void i915_restore_palette(struct drm_device *dev, enum pipex pipe)
     65 {
     66 	struct drm_i915_private *dev_priv = dev->dev_private;
     67 	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
     68 	u32 *array;
     69 	int i;
     70 
     71 	if (!i915_pipe_enabled(dev, pipe))
     72 		return;
     73 
     74 	if (pipe == PIPE_A)
     75 		array = dev_priv->save_palette_a;
     76 	else
     77 		array = dev_priv->save_palette_b;
     78 
     79 	for(i = 0; i < 256; i++)
     80 		I915_WRITE(reg + (i << 2), array[i]);
     81 }
     82 
     83 static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
     84 {
     85 	struct drm_i915_private *dev_priv = dev->dev_private;
     86 
     87 	I915_WRITE8(index_port, reg);
     88 	return I915_READ8(data_port);
     89 }
     90 
     91 static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
     92 {
     93 	struct drm_i915_private *dev_priv = dev->dev_private;
     94 
     95 	I915_READ8(st01);
     96 	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
     97 	return I915_READ8(VGA_AR_DATA_READ);
     98 }
     99 
    100 static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
    101 {
    102 	struct drm_i915_private *dev_priv = dev->dev_private;
    103 
    104 	I915_READ8(st01);
    105 	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
    106 	I915_WRITE8(VGA_AR_DATA_WRITE, val);
    107 }
    108 
    109 static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
    110 {
    111 	struct drm_i915_private *dev_priv = dev->dev_private;
    112 
    113 	I915_WRITE8(index_port, reg);
    114 	I915_WRITE8(data_port, val);
    115 }
    116 
    117 static void i915_save_vga(struct drm_device *dev)
    118 {
    119 	struct drm_i915_private *dev_priv = dev->dev_private;
    120 	int i;
    121 	u16 cr_index, cr_data, st01;
    122 
    123 	/* VGA color palette registers */
    124 	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
    125 	/* DACCRX automatically increments during read */
    126 	I915_WRITE8(VGA_DACRX, 0);
    127 	/* Read 3 bytes of color data from each index */
    128 	for (i = 0; i < 256 * 3; i++)
    129 		dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
    130 
    131 	/* MSR bits */
    132 	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
    133 	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
    134 		cr_index = VGA_CR_INDEX_CGA;
    135 		cr_data = VGA_CR_DATA_CGA;
    136 		st01 = VGA_ST01_CGA;
    137 	} else {
    138 		cr_index = VGA_CR_INDEX_MDA;
    139 		cr_data = VGA_CR_DATA_MDA;
    140 		st01 = VGA_ST01_MDA;
    141 	}
    142 
    143 	/* CRT controller regs */
    144 	i915_write_indexed(dev, cr_index, cr_data, 0x11,
    145 			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
    146 			   (~0x80));
    147 	for (i = 0; i <= 0x24; i++)
    148 		dev_priv->saveCR[i] =
    149 			i915_read_indexed(dev, cr_index, cr_data, i);
    150 	/* Make sure we don't turn off CR group 0 writes */
    151 	dev_priv->saveCR[0x11] &= ~0x80;
    152 
    153 	/* Attribute controller registers */
    154 	I915_READ8(st01);
    155 	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
    156 	for (i = 0; i <= 0x14; i++)
    157 		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
    158 	I915_READ8(st01);
    159 	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
    160 	I915_READ8(st01);
    161 
    162 	/* Graphics controller registers */
    163 	for (i = 0; i < 9; i++)
    164 		dev_priv->saveGR[i] =
    165 			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
    166 
    167 	dev_priv->saveGR[0x10] =
    168 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
    169 	dev_priv->saveGR[0x11] =
    170 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
    171 	dev_priv->saveGR[0x18] =
    172 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
    173 
    174 	/* Sequencer registers */
    175 	for (i = 0; i < 8; i++)
    176 		dev_priv->saveSR[i] =
    177 			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
    178 }
    179 
    180 static void i915_restore_vga(struct drm_device *dev)
    181 {
    182 	struct drm_i915_private *dev_priv = dev->dev_private;
    183 	int i;
    184 	u16 cr_index, cr_data, st01;
    185 
    186 	/* MSR bits */
    187 	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
    188 	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
    189 		cr_index = VGA_CR_INDEX_CGA;
    190 		cr_data = VGA_CR_DATA_CGA;
    191 		st01 = VGA_ST01_CGA;
    192 	} else {
    193 		cr_index = VGA_CR_INDEX_MDA;
    194 		cr_data = VGA_CR_DATA_MDA;
    195 		st01 = VGA_ST01_MDA;
    196 	}
    197 
    198 	/* Sequencer registers, don't write SR07 */
    199 	for (i = 0; i < 7; i++)
    200 		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
    201 				   dev_priv->saveSR[i]);
    202 
    203 	/* CRT controller regs */
    204 	/* Enable CR group 0 writes */
    205 	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
    206 	for (i = 0; i <= 0x24; i++)
    207 		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
    208 
    209 	/* Graphics controller regs */
    210 	for (i = 0; i < 9; i++)
    211 		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
    212 				   dev_priv->saveGR[i]);
    213 
    214 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
    215 			   dev_priv->saveGR[0x10]);
    216 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
    217 			   dev_priv->saveGR[0x11]);
    218 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
    219 			   dev_priv->saveGR[0x18]);
    220 
    221 	/* Attribute controller registers */
    222 	I915_READ8(st01); /* switch back to index mode */
    223 	for (i = 0; i <= 0x14; i++)
    224 		i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
    225 	I915_READ8(st01); /* switch back to index mode */
    226 	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
    227 	I915_READ8(st01);
    228 
    229 	/* VGA color palette registers */
    230 	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
    231 	/* DACCRX automatically increments during read */
    232 	I915_WRITE8(VGA_DACWX, 0);
    233 	/* Read 3 bytes of color data from each index */
    234 	for (i = 0; i < 256 * 3; i++)
    235 		I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
    236 
    237 }
    238 
    239 int i915_save_state(struct drm_device *dev)
    240 {
    241 	struct drm_i915_private *dev_priv = dev->dev_private;
    242 	int i;
    243 
    244 #if defined(__FreeBSD__)
    245 	dev_priv->saveLBB = (u8) pci_read_config(dev->device, LBB, 1);
    246 #elif   defined(__NetBSD__)
    247 	dev_priv->saveLBB = (u8) pci_conf_read(dev->pa.pa_pc, dev->pa.pa_tag, LBB);
    248 #else
    249 	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
    250 #endif
    251 
    252 	/* Display arbitration control */
    253 	dev_priv->saveDSPARB = I915_READ(DSPARB);
    254 
    255 	/* Pipe & plane A info */
    256 	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
    257 	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
    258 	dev_priv->saveFPA0 = I915_READ(FPA0);
    259 	dev_priv->saveFPA1 = I915_READ(FPA1);
    260 	dev_priv->saveDPLL_A = I915_READ(DPLL_A);
    261 	if (IS_I965G(dev))
    262 		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
    263 	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
    264 	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
    265 	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
    266 	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
    267 	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
    268 	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
    269 	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
    270 
    271 	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
    272 	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
    273 	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
    274 	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
    275 	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
    276 	if (IS_I965G(dev)) {
    277 		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
    278 		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
    279 	}
    280 	i915_save_palette(dev, PIPE_A);
    281 	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
    282 
    283 	/* Pipe & plane B info */
    284 	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
    285 	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
    286 	dev_priv->saveFPB0 = I915_READ(FPB0);
    287 	dev_priv->saveFPB1 = I915_READ(FPB1);
    288 	dev_priv->saveDPLL_B = I915_READ(DPLL_B);
    289 	if (IS_I965G(dev))
    290 		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
    291 	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
    292 	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
    293 	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
    294 	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
    295 	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
    296 	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
    297 	dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
    298 
    299 	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
    300 	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
    301 	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
    302 	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
    303 	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
    304 	if (IS_I965GM(dev) || IS_GM45(dev)) {
    305 		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
    306 		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
    307 	}
    308 	i915_save_palette(dev, PIPE_B);
    309 	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
    310 
    311 	/* CRT state */
    312 	dev_priv->saveADPA = I915_READ(ADPA);
    313 
    314 	/* LVDS state */
    315 	dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
    316 	dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
    317 	dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
    318 	if (IS_I965G(dev))
    319 		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
    320 	if (IS_MOBILE(dev) && !IS_I830(dev))
    321 		dev_priv->saveLVDS = I915_READ(LVDS);
    322 	if (!IS_I830(dev) && !IS_845G(dev))
    323 		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
    324 	dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
    325 	dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
    326 	dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
    327 
    328 	/* FIXME: save TV & SDVO state */
    329 
    330 	/* FBC state */
    331 	dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
    332 	dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
    333 	dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
    334 	dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
    335 
    336 	/* Interrupt state */
    337 	dev_priv->saveIIR = I915_READ(IIR);
    338 	dev_priv->saveIER = I915_READ(IER);
    339 	dev_priv->saveIMR = I915_READ(IMR);
    340 
    341 	/* VGA state */
    342 	dev_priv->saveVGA0 = I915_READ(VGA0);
    343 	dev_priv->saveVGA1 = I915_READ(VGA1);
    344 	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
    345 	dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
    346 
    347 	/* Clock gating state */
    348 	dev_priv->saveD_STATE = I915_READ(D_STATE);
    349 	dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
    350 
    351 	/* Cache mode state */
    352 	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
    353 
    354 	/* Memory Arbitration state */
    355 	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
    356 
    357 	/* Scratch space */
    358 	for (i = 0; i < 16; i++) {
    359 		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
    360 		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
    361 	}
    362 	for (i = 0; i < 3; i++)
    363 		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
    364 
    365 	i915_save_vga(dev);
    366 
    367 	return 0;
    368 }
    369 
    370 int i915_restore_state(struct drm_device *dev)
    371 {
    372 	struct drm_i915_private *dev_priv = dev->dev_private;
    373 	int i;
    374 
    375 #if defined(__FreeBSD__)
    376 	pci_write_config(dev->device, LBB, dev_priv->saveLBB, 1);
    377 #elif   defined(__NetBSD__)
    378 	pci_conf_write(dev->pa.pa_pc, dev->pa.pa_tag, LBB, dev_priv->saveLBB);
    379 #else
    380 	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
    381 #endif
    382 
    383 	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
    384 
    385 	/* Pipe & plane A info */
    386 	/* Prime the clock */
    387 	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
    388 		I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
    389 			   ~DPLL_VCO_ENABLE);
    390 		DRM_UDELAY(150);
    391 	}
    392 	I915_WRITE(FPA0, dev_priv->saveFPA0);
    393 	I915_WRITE(FPA1, dev_priv->saveFPA1);
    394 	/* Actually enable it */
    395 	I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
    396 	DRM_UDELAY(150);
    397 	if (IS_I965G(dev))
    398 		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
    399 	DRM_UDELAY(150);
    400 
    401 	/* Restore mode */
    402 	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
    403 	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
    404 	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
    405 	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
    406 	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
    407 	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
    408 	I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
    409 
    410 	/* Restore plane info */
    411 	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
    412 	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
    413 	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
    414 	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
    415 	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
    416 	if (IS_I965G(dev)) {
    417 		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
    418 		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
    419 	}
    420 
    421 	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
    422 
    423 	i915_restore_palette(dev, PIPE_A);
    424 	/* Enable the plane */
    425 	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
    426 	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
    427 
    428 	/* Pipe & plane B info */
    429 	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
    430 		I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
    431 			   ~DPLL_VCO_ENABLE);
    432 		DRM_UDELAY(150);
    433 	}
    434 	I915_WRITE(FPB0, dev_priv->saveFPB0);
    435 	I915_WRITE(FPB1, dev_priv->saveFPB1);
    436 	/* Actually enable it */
    437 	I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
    438 	DRM_UDELAY(150);
    439 	if (IS_I965G(dev))
    440 		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
    441 	DRM_UDELAY(150);
    442 
    443 	/* Restore mode */
    444 	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
    445 	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
    446 	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
    447 	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
    448 	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
    449 	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
    450 	I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
    451 
    452 	/* Restore plane info */
    453 	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
    454 	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
    455 	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
    456 	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
    457 	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
    458 	if (IS_I965G(dev)) {
    459 		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
    460 		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
    461 	}
    462 
    463 	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
    464 
    465 	i915_restore_palette(dev, PIPE_B);
    466 	/* Enable the plane */
    467 	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
    468 	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
    469 
    470 	/* CRT state */
    471 	I915_WRITE(ADPA, dev_priv->saveADPA);
    472 
    473 	/* LVDS state */
    474 	if (IS_I965G(dev))
    475 		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
    476 	if (IS_MOBILE(dev) && !IS_I830(dev))
    477 		I915_WRITE(LVDS, dev_priv->saveLVDS);
    478 	if (!IS_I830(dev) && !IS_845G(dev))
    479 		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
    480 
    481 	I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
    482 	I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
    483 	I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
    484 	I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
    485 	I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
    486 	I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
    487 
    488 	/* FIXME: restore TV & SDVO state */
    489 
    490 	/* FBC info */
    491 	I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
    492 	I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
    493 	I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
    494 	I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
    495 
    496 	/* VGA state */
    497 	I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
    498 	I915_WRITE(VGA0, dev_priv->saveVGA0);
    499 	I915_WRITE(VGA1, dev_priv->saveVGA1);
    500 	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
    501 	DRM_UDELAY(150);
    502 
    503 	/* Clock gating state */
    504 	I915_WRITE (D_STATE, dev_priv->saveD_STATE);
    505 	I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
    506 
    507 	/* Cache mode state */
    508 	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
    509 
    510 	/* Memory arbitration state */
    511 	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
    512 
    513 	for (i = 0; i < 16; i++) {
    514 		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
    515 		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
    516 	}
    517 	for (i = 0; i < 3; i++)
    518 		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
    519 
    520 	i915_restore_vga(dev);
    521 
    522 	return 0;
    523 }
    524 
    525