i915_suspend.c 31.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 *
 * Copyright 2008 (c) Intel Corporation
 *   Jesse Barnes <jbarnes@virtuousgeek.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

27 28
#include <drm/drmP.h>
#include <drm/i915_drm.h>
29
#include "intel_drv.h"
30
#include "i915_reg.h"
31 32 33 34

static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
35
	u32	dpll_reg;
36

E
Eugeni Dodonov 已提交
37 38 39 40
	/* On IVB, 3rd pipe shares PLL with another one */
	if (pipe > 1)
		return false;

41
	if (HAS_PCH_SPLIT(dev))
42
		dpll_reg = _PCH_DPLL(pipe);
43 44
	else
		dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
45 46

	return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
47 48 49 50 51
}

static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
52
	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
53 54 55 56 57 58
	u32 *array;
	int i;

	if (!i915_pipe_enabled(dev, pipe))
		return;

59
	if (HAS_PCH_SPLIT(dev))
60
		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
61

62
	if (pipe == PIPE_A)
63
		array = dev_priv->regfile.save_palette_a;
64
	else
65
		array = dev_priv->regfile.save_palette_b;
66

67
	for (i = 0; i < 256; i++)
68 69 70 71 72 73
		array[i] = I915_READ(reg + (i << 2));
}

static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
74
	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
75 76 77 78 79 80
	u32 *array;
	int i;

	if (!i915_pipe_enabled(dev, pipe))
		return;

81
	if (HAS_PCH_SPLIT(dev))
82
		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
83

84
	if (pipe == PIPE_A)
85
		array = dev_priv->regfile.save_palette_a;
86
	else
87
		array = dev_priv->regfile.save_palette_b;
88

89
	for (i = 0; i < 256; i++)
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
		I915_WRITE(reg + (i << 2), array[i]);
}

static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	I915_WRITE8(index_port, reg);
	return I915_READ8(data_port);
}

static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	I915_READ8(st01);
	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
	return I915_READ8(VGA_AR_DATA_READ);
}

static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	I915_READ8(st01);
	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
	I915_WRITE8(VGA_AR_DATA_WRITE, val);
}

static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	I915_WRITE8(index_port, reg);
	I915_WRITE8(data_port, val);
}

static void i915_save_vga(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int i;
	u16 cr_index, cr_data, st01;

	/* VGA color palette registers */
134
	dev_priv->regfile.saveDACMASK = I915_READ8(VGA_DACMASK);
135 136

	/* MSR bits */
137 138
	dev_priv->regfile.saveMSR = I915_READ8(VGA_MSR_READ);
	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
139 140 141 142 143 144 145 146 147 148 149 150 151 152
		cr_index = VGA_CR_INDEX_CGA;
		cr_data = VGA_CR_DATA_CGA;
		st01 = VGA_ST01_CGA;
	} else {
		cr_index = VGA_CR_INDEX_MDA;
		cr_data = VGA_CR_DATA_MDA;
		st01 = VGA_ST01_MDA;
	}

	/* CRT controller regs */
	i915_write_indexed(dev, cr_index, cr_data, 0x11,
			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
			   (~0x80));
	for (i = 0; i <= 0x24; i++)
153
		dev_priv->regfile.saveCR[i] =
154 155
			i915_read_indexed(dev, cr_index, cr_data, i);
	/* Make sure we don't turn off CR group 0 writes */
156
	dev_priv->regfile.saveCR[0x11] &= ~0x80;
157 158 159

	/* Attribute controller registers */
	I915_READ8(st01);
160
	dev_priv->regfile.saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
161
	for (i = 0; i <= 0x14; i++)
162
		dev_priv->regfile.saveAR[i] = i915_read_ar(dev, st01, i, 0);
163
	I915_READ8(st01);
164
	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX);
165 166 167 168
	I915_READ8(st01);

	/* Graphics controller registers */
	for (i = 0; i < 9; i++)
169
		dev_priv->regfile.saveGR[i] =
170 171
			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);

172
	dev_priv->regfile.saveGR[0x10] =
173
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
174
	dev_priv->regfile.saveGR[0x11] =
175
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
176
	dev_priv->regfile.saveGR[0x18] =
177 178 179 180
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);

	/* Sequencer registers */
	for (i = 0; i < 8; i++)
181
		dev_priv->regfile.saveSR[i] =
182 183 184 185 186 187 188 189 190 191
			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
}

static void i915_restore_vga(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int i;
	u16 cr_index, cr_data, st01;

	/* MSR bits */
192 193
	I915_WRITE8(VGA_MSR_WRITE, dev_priv->regfile.saveMSR);
	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
194 195 196 197 198 199 200 201 202 203 204 205
		cr_index = VGA_CR_INDEX_CGA;
		cr_data = VGA_CR_DATA_CGA;
		st01 = VGA_ST01_CGA;
	} else {
		cr_index = VGA_CR_INDEX_MDA;
		cr_data = VGA_CR_DATA_MDA;
		st01 = VGA_ST01_MDA;
	}

	/* Sequencer registers, don't write SR07 */
	for (i = 0; i < 7; i++)
		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
206
				   dev_priv->regfile.saveSR[i]);
207 208 209

	/* CRT controller regs */
	/* Enable CR group 0 writes */
210
	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->regfile.saveCR[0x11]);
211
	for (i = 0; i <= 0x24; i++)
212
		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->regfile.saveCR[i]);
213 214 215 216

	/* Graphics controller regs */
	for (i = 0; i < 9; i++)
		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
217
				   dev_priv->regfile.saveGR[i]);
218 219

	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
220
			   dev_priv->regfile.saveGR[0x10]);
221
	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
222
			   dev_priv->regfile.saveGR[0x11]);
223
	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
224
			   dev_priv->regfile.saveGR[0x18]);
225 226 227 228

	/* Attribute controller registers */
	I915_READ8(st01); /* switch back to index mode */
	for (i = 0; i <= 0x14; i++)
229
		i915_write_ar(dev, st01, i, dev_priv->regfile.saveAR[i], 0);
230
	I915_READ8(st01); /* switch back to index mode */
231
	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX | 0x20);
232 233 234
	I915_READ8(st01);

	/* VGA color palette registers */
235
	I915_WRITE8(VGA_DACMASK, dev_priv->regfile.saveDACMASK);
236 237
}

238
static void i915_save_modeset_reg(struct drm_device *dev)
239 240
{
	struct drm_i915_private *dev_priv = dev->dev_private;
241
	int i;
242

243 244
	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return;
245

246
	/* Cursor state */
247 248 249 250 251 252
	dev_priv->regfile.saveCURACNTR = I915_READ(_CURACNTR);
	dev_priv->regfile.saveCURAPOS = I915_READ(_CURAPOS);
	dev_priv->regfile.saveCURABASE = I915_READ(_CURABASE);
	dev_priv->regfile.saveCURBCNTR = I915_READ(_CURBCNTR);
	dev_priv->regfile.saveCURBPOS = I915_READ(_CURBPOS);
	dev_priv->regfile.saveCURBBASE = I915_READ(_CURBBASE);
253
	if (IS_GEN2(dev))
254
		dev_priv->regfile.saveCURSIZE = I915_READ(CURSIZE);
255

256
	if (HAS_PCH_SPLIT(dev)) {
257 258
		dev_priv->regfile.savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
		dev_priv->regfile.saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
259 260
	}

261
	/* Pipe & plane A info */
262 263
	dev_priv->regfile.savePIPEACONF = I915_READ(_PIPEACONF);
	dev_priv->regfile.savePIPEASRC = I915_READ(_PIPEASRC);
264
	if (HAS_PCH_SPLIT(dev)) {
265 266 267
		dev_priv->regfile.saveFPA0 = I915_READ(_PCH_FPA0);
		dev_priv->regfile.saveFPA1 = I915_READ(_PCH_FPA1);
		dev_priv->regfile.saveDPLL_A = I915_READ(_PCH_DPLL_A);
268
	} else {
269 270 271
		dev_priv->regfile.saveFPA0 = I915_READ(_FPA0);
		dev_priv->regfile.saveFPA1 = I915_READ(_FPA1);
		dev_priv->regfile.saveDPLL_A = I915_READ(_DPLL_A);
272
	}
273
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
274 275 276 277 278 279 280
		dev_priv->regfile.saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
	dev_priv->regfile.saveHTOTAL_A = I915_READ(_HTOTAL_A);
	dev_priv->regfile.saveHBLANK_A = I915_READ(_HBLANK_A);
	dev_priv->regfile.saveHSYNC_A = I915_READ(_HSYNC_A);
	dev_priv->regfile.saveVTOTAL_A = I915_READ(_VTOTAL_A);
	dev_priv->regfile.saveVBLANK_A = I915_READ(_VBLANK_A);
	dev_priv->regfile.saveVSYNC_A = I915_READ(_VSYNC_A);
281
	if (!HAS_PCH_SPLIT(dev))
282
		dev_priv->regfile.saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
283

284
	if (HAS_PCH_SPLIT(dev)) {
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
		dev_priv->regfile.savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
		dev_priv->regfile.savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
		dev_priv->regfile.savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
		dev_priv->regfile.savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);

		dev_priv->regfile.saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
		dev_priv->regfile.saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);

		dev_priv->regfile.savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
		dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
		dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);

		dev_priv->regfile.saveTRANSACONF = I915_READ(_TRANSACONF);
		dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
		dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
		dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
		dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
		dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
		dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
	}

	dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR);
	dev_priv->regfile.saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
	dev_priv->regfile.saveDSPASIZE = I915_READ(_DSPASIZE);
	dev_priv->regfile.saveDSPAPOS = I915_READ(_DSPAPOS);
	dev_priv->regfile.saveDSPAADDR = I915_READ(_DSPAADDR);
311
	if (INTEL_INFO(dev)->gen >= 4) {
312 313
		dev_priv->regfile.saveDSPASURF = I915_READ(_DSPASURF);
		dev_priv->regfile.saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
314 315
	}
	i915_save_palette(dev, PIPE_A);
316
	dev_priv->regfile.savePIPEASTAT = I915_READ(_PIPEASTAT);
317 318

	/* Pipe & plane B info */
319 320
	dev_priv->regfile.savePIPEBCONF = I915_READ(_PIPEBCONF);
	dev_priv->regfile.savePIPEBSRC = I915_READ(_PIPEBSRC);
321
	if (HAS_PCH_SPLIT(dev)) {
322 323 324
		dev_priv->regfile.saveFPB0 = I915_READ(_PCH_FPB0);
		dev_priv->regfile.saveFPB1 = I915_READ(_PCH_FPB1);
		dev_priv->regfile.saveDPLL_B = I915_READ(_PCH_DPLL_B);
325
	} else {
326 327 328
		dev_priv->regfile.saveFPB0 = I915_READ(_FPB0);
		dev_priv->regfile.saveFPB1 = I915_READ(_FPB1);
		dev_priv->regfile.saveDPLL_B = I915_READ(_DPLL_B);
329
	}
330
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
331 332 333 334 335 336 337
		dev_priv->regfile.saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
	dev_priv->regfile.saveHTOTAL_B = I915_READ(_HTOTAL_B);
	dev_priv->regfile.saveHBLANK_B = I915_READ(_HBLANK_B);
	dev_priv->regfile.saveHSYNC_B = I915_READ(_HSYNC_B);
	dev_priv->regfile.saveVTOTAL_B = I915_READ(_VTOTAL_B);
	dev_priv->regfile.saveVBLANK_B = I915_READ(_VBLANK_B);
	dev_priv->regfile.saveVSYNC_B = I915_READ(_VSYNC_B);
338
	if (!HAS_PCH_SPLIT(dev))
339
		dev_priv->regfile.saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
340

341
	if (HAS_PCH_SPLIT(dev)) {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
		dev_priv->regfile.savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
		dev_priv->regfile.savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
		dev_priv->regfile.savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
		dev_priv->regfile.savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);

		dev_priv->regfile.saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
		dev_priv->regfile.saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);

		dev_priv->regfile.savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
		dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
		dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);

		dev_priv->regfile.saveTRANSBCONF = I915_READ(_TRANSBCONF);
		dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
		dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
		dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
		dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
		dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
		dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
	}

	dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR);
	dev_priv->regfile.saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
	dev_priv->regfile.saveDSPBSIZE = I915_READ(_DSPBSIZE);
	dev_priv->regfile.saveDSPBPOS = I915_READ(_DSPBPOS);
	dev_priv->regfile.saveDSPBADDR = I915_READ(_DSPBADDR);
368
	if (INTEL_INFO(dev)->gen >= 4) {
369 370
		dev_priv->regfile.saveDSPBSURF = I915_READ(_DSPBSURF);
		dev_priv->regfile.saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
371 372
	}
	i915_save_palette(dev, PIPE_B);
373
	dev_priv->regfile.savePIPEBSTAT = I915_READ(_PIPEBSTAT);
374 375 376

	/* Fences */
	switch (INTEL_INFO(dev)->gen) {
377
	case 7:
378 379
	case 6:
		for (i = 0; i < 16; i++)
380
			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
381 382 383 384
		break;
	case 5:
	case 4:
		for (i = 0; i < 16; i++)
385
			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
386 387 388 389
		break;
	case 3:
		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
			for (i = 0; i < 8; i++)
390
				dev_priv->regfile.saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
391 392
	case 2:
		for (i = 0; i < 8; i++)
393
			dev_priv->regfile.saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
394 395 396
		break;
	}

397 398
	/* CRT state */
	if (HAS_PCH_SPLIT(dev))
399
		dev_priv->regfile.saveADPA = I915_READ(PCH_ADPA);
400
	else
401
		dev_priv->regfile.saveADPA = I915_READ(ADPA);
402

403 404
	return;
}
405

406 407 408
static void i915_restore_modeset_reg(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
409 410
	int dpll_a_reg, fpa0_reg, fpa1_reg;
	int dpll_b_reg, fpb0_reg, fpb1_reg;
411
	int i;
412 413 414 415

	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return;

416 417
	/* Fences */
	switch (INTEL_INFO(dev)->gen) {
418
	case 7:
419 420
	case 6:
		for (i = 0; i < 16; i++)
421
			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
422 423 424 425
		break;
	case 5:
	case 4:
		for (i = 0; i < 16; i++)
426
			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
427 428 429 430 431
		break;
	case 3:
	case 2:
		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
			for (i = 0; i < 8; i++)
432
				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->regfile.saveFENCE[i+8]);
433
		for (i = 0; i < 8; i++)
434
			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->regfile.saveFENCE[i]);
435 436 437 438
		break;
	}


439
	if (HAS_PCH_SPLIT(dev)) {
440 441 442 443 444 445
		dpll_a_reg = _PCH_DPLL_A;
		dpll_b_reg = _PCH_DPLL_B;
		fpa0_reg = _PCH_FPA0;
		fpb0_reg = _PCH_FPB0;
		fpa1_reg = _PCH_FPA1;
		fpb1_reg = _PCH_FPB1;
446
	} else {
447 448 449 450 451 452
		dpll_a_reg = _DPLL_A;
		dpll_b_reg = _DPLL_B;
		fpa0_reg = _FPA0;
		fpb0_reg = _FPB0;
		fpa1_reg = _FPA1;
		fpb1_reg = _FPB1;
453 454
	}

455
	if (HAS_PCH_SPLIT(dev)) {
456 457
		I915_WRITE(PCH_DREF_CONTROL, dev_priv->regfile.savePCH_DREF_CONTROL);
		I915_WRITE(DISP_ARB_CTL, dev_priv->regfile.saveDISP_ARB_CTL);
458 459
	}

460 461
	/* Pipe & plane A info */
	/* Prime the clock */
462 463
	if (dev_priv->regfile.saveDPLL_A & DPLL_VCO_ENABLE) {
		I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A &
464
			   ~DPLL_VCO_ENABLE);
465 466
		POSTING_READ(dpll_a_reg);
		udelay(150);
467
	}
468 469
	I915_WRITE(fpa0_reg, dev_priv->regfile.saveFPA0);
	I915_WRITE(fpa1_reg, dev_priv->regfile.saveFPA1);
470
	/* Actually enable it */
471
	I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A);
472 473
	POSTING_READ(dpll_a_reg);
	udelay(150);
474
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
475
		I915_WRITE(_DPLL_A_MD, dev_priv->regfile.saveDPLL_A_MD);
476
		POSTING_READ(_DPLL_A_MD);
477 478
	}
	udelay(150);
479 480

	/* Restore mode */
481 482 483 484 485 486
	I915_WRITE(_HTOTAL_A, dev_priv->regfile.saveHTOTAL_A);
	I915_WRITE(_HBLANK_A, dev_priv->regfile.saveHBLANK_A);
	I915_WRITE(_HSYNC_A, dev_priv->regfile.saveHSYNC_A);
	I915_WRITE(_VTOTAL_A, dev_priv->regfile.saveVTOTAL_A);
	I915_WRITE(_VBLANK_A, dev_priv->regfile.saveVBLANK_A);
	I915_WRITE(_VSYNC_A, dev_priv->regfile.saveVSYNC_A);
487
	if (!HAS_PCH_SPLIT(dev))
488
		I915_WRITE(_BCLRPAT_A, dev_priv->regfile.saveBCLRPAT_A);
489

490
	if (HAS_PCH_SPLIT(dev)) {
491 492 493 494
		I915_WRITE(_PIPEA_DATA_M1, dev_priv->regfile.savePIPEA_DATA_M1);
		I915_WRITE(_PIPEA_DATA_N1, dev_priv->regfile.savePIPEA_DATA_N1);
		I915_WRITE(_PIPEA_LINK_M1, dev_priv->regfile.savePIPEA_LINK_M1);
		I915_WRITE(_PIPEA_LINK_N1, dev_priv->regfile.savePIPEA_LINK_N1);
495

496 497
		I915_WRITE(_FDI_RXA_CTL, dev_priv->regfile.saveFDI_RXA_CTL);
		I915_WRITE(_FDI_TXA_CTL, dev_priv->regfile.saveFDI_TXA_CTL);
498

499 500 501
		I915_WRITE(_PFA_CTL_1, dev_priv->regfile.savePFA_CTL_1);
		I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ);
		I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS);
502

503 504 505 506 507 508 509
		I915_WRITE(_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
		I915_WRITE(_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
		I915_WRITE(_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
		I915_WRITE(_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
		I915_WRITE(_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
510
	}
511 512

	/* Restore plane info */
513 514 515 516 517
	I915_WRITE(_DSPASIZE, dev_priv->regfile.saveDSPASIZE);
	I915_WRITE(_DSPAPOS, dev_priv->regfile.saveDSPAPOS);
	I915_WRITE(_PIPEASRC, dev_priv->regfile.savePIPEASRC);
	I915_WRITE(_DSPAADDR, dev_priv->regfile.saveDSPAADDR);
	I915_WRITE(_DSPASTRIDE, dev_priv->regfile.saveDSPASTRIDE);
518
	if (INTEL_INFO(dev)->gen >= 4) {
519 520
		I915_WRITE(_DSPASURF, dev_priv->regfile.saveDSPASURF);
		I915_WRITE(_DSPATILEOFF, dev_priv->regfile.saveDSPATILEOFF);
521 522
	}

523
	I915_WRITE(_PIPEACONF, dev_priv->regfile.savePIPEACONF);
524 525 526

	i915_restore_palette(dev, PIPE_A);
	/* Enable the plane */
527
	I915_WRITE(_DSPACNTR, dev_priv->regfile.saveDSPACNTR);
528
	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
529 530

	/* Pipe & plane B info */
531 532
	if (dev_priv->regfile.saveDPLL_B & DPLL_VCO_ENABLE) {
		I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B &
533
			   ~DPLL_VCO_ENABLE);
534 535
		POSTING_READ(dpll_b_reg);
		udelay(150);
536
	}
537 538
	I915_WRITE(fpb0_reg, dev_priv->regfile.saveFPB0);
	I915_WRITE(fpb1_reg, dev_priv->regfile.saveFPB1);
539
	/* Actually enable it */
540
	I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B);
541 542
	POSTING_READ(dpll_b_reg);
	udelay(150);
543
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
544
		I915_WRITE(_DPLL_B_MD, dev_priv->regfile.saveDPLL_B_MD);
545
		POSTING_READ(_DPLL_B_MD);
546 547
	}
	udelay(150);
548 549

	/* Restore mode */
550 551 552 553 554 555
	I915_WRITE(_HTOTAL_B, dev_priv->regfile.saveHTOTAL_B);
	I915_WRITE(_HBLANK_B, dev_priv->regfile.saveHBLANK_B);
	I915_WRITE(_HSYNC_B, dev_priv->regfile.saveHSYNC_B);
	I915_WRITE(_VTOTAL_B, dev_priv->regfile.saveVTOTAL_B);
	I915_WRITE(_VBLANK_B, dev_priv->regfile.saveVBLANK_B);
	I915_WRITE(_VSYNC_B, dev_priv->regfile.saveVSYNC_B);
556
	if (!HAS_PCH_SPLIT(dev))
557
		I915_WRITE(_BCLRPAT_B, dev_priv->regfile.saveBCLRPAT_B);
558

559
	if (HAS_PCH_SPLIT(dev)) {
560 561 562 563
		I915_WRITE(_PIPEB_DATA_M1, dev_priv->regfile.savePIPEB_DATA_M1);
		I915_WRITE(_PIPEB_DATA_N1, dev_priv->regfile.savePIPEB_DATA_N1);
		I915_WRITE(_PIPEB_LINK_M1, dev_priv->regfile.savePIPEB_LINK_M1);
		I915_WRITE(_PIPEB_LINK_N1, dev_priv->regfile.savePIPEB_LINK_N1);
564

565 566
		I915_WRITE(_FDI_RXB_CTL, dev_priv->regfile.saveFDI_RXB_CTL);
		I915_WRITE(_FDI_TXB_CTL, dev_priv->regfile.saveFDI_TXB_CTL);
567

568 569 570
		I915_WRITE(_PFB_CTL_1, dev_priv->regfile.savePFB_CTL_1);
		I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ);
		I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS);
571

572 573 574 575 576 577 578
		I915_WRITE(_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
		I915_WRITE(_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
		I915_WRITE(_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
		I915_WRITE(_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
		I915_WRITE(_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
579
	}
580 581

	/* Restore plane info */
582 583 584 585 586
	I915_WRITE(_DSPBSIZE, dev_priv->regfile.saveDSPBSIZE);
	I915_WRITE(_DSPBPOS, dev_priv->regfile.saveDSPBPOS);
	I915_WRITE(_PIPEBSRC, dev_priv->regfile.savePIPEBSRC);
	I915_WRITE(_DSPBADDR, dev_priv->regfile.saveDSPBADDR);
	I915_WRITE(_DSPBSTRIDE, dev_priv->regfile.saveDSPBSTRIDE);
587
	if (INTEL_INFO(dev)->gen >= 4) {
588 589
		I915_WRITE(_DSPBSURF, dev_priv->regfile.saveDSPBSURF);
		I915_WRITE(_DSPBTILEOFF, dev_priv->regfile.saveDSPBTILEOFF);
590 591
	}

592
	I915_WRITE(_PIPEBCONF, dev_priv->regfile.savePIPEBCONF);
593 594 595

	i915_restore_palette(dev, PIPE_B);
	/* Enable the plane */
596
	I915_WRITE(_DSPBCNTR, dev_priv->regfile.saveDSPBCNTR);
597
	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
598

599
	/* Cursor state */
600 601 602 603 604 605
	I915_WRITE(_CURAPOS, dev_priv->regfile.saveCURAPOS);
	I915_WRITE(_CURACNTR, dev_priv->regfile.saveCURACNTR);
	I915_WRITE(_CURABASE, dev_priv->regfile.saveCURABASE);
	I915_WRITE(_CURBPOS, dev_priv->regfile.saveCURBPOS);
	I915_WRITE(_CURBCNTR, dev_priv->regfile.saveCURBCNTR);
	I915_WRITE(_CURBBASE, dev_priv->regfile.saveCURBBASE);
606
	if (IS_GEN2(dev))
607
		I915_WRITE(CURSIZE, dev_priv->regfile.saveCURSIZE);
608

609 610
	/* CRT state */
	if (HAS_PCH_SPLIT(dev))
611
		I915_WRITE(PCH_ADPA, dev_priv->regfile.saveADPA);
612
	else
613
		I915_WRITE(ADPA, dev_priv->regfile.saveADPA);
614

615 616
	return;
}
617

618
static void i915_save_display(struct drm_device *dev)
619 620 621 622
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	/* Display arbitration control */
623
	dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
624 625

	/* This is only meaningful in non-KMS mode */
626
	/* Don't regfile.save them in KMS mode */
627
	i915_save_modeset_reg(dev);
628

629
	/* LVDS state */
630
	if (HAS_PCH_SPLIT(dev)) {
631 632 633 634 635 636
		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
		dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
		dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
		dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
637
	} else {
638 639 640 641
		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
		dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
642
		if (INTEL_INFO(dev)->gen >= 4)
643
			dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
644
		if (IS_MOBILE(dev) && !IS_I830(dev))
645
			dev_priv->regfile.saveLVDS = I915_READ(LVDS);
646 647
	}

648
	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
649
		dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
650

651
	if (HAS_PCH_SPLIT(dev)) {
652 653 654
		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
655
	} else {
656 657 658
		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
659
	}
660

661 662 663
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Display Port state */
		if (SUPPORTS_INTEGRATED_DP(dev)) {
664 665 666 667 668 669 670 671 672 673 674
			dev_priv->regfile.saveDP_B = I915_READ(DP_B);
			dev_priv->regfile.saveDP_C = I915_READ(DP_C);
			dev_priv->regfile.saveDP_D = I915_READ(DP_D);
			dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
			dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
			dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
			dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
			dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
			dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
			dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
			dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
675
		}
676
		/* FIXME: regfile.save TV & SDVO state */
677
	}
678

679
	/* Only regfile.save FBC state on the platform that supports FBC */
680
	if (I915_HAS_FBC(dev)) {
681
		if (HAS_PCH_SPLIT(dev)) {
682
			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
683
		} else if (IS_GM45(dev)) {
684
			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
685
		} else {
686 687 688 689
			dev_priv->regfile.saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
			dev_priv->regfile.saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
			dev_priv->regfile.saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
			dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
690
		}
691
	}
692 693

	/* VGA state */
694 695 696
	dev_priv->regfile.saveVGA0 = I915_READ(VGA0);
	dev_priv->regfile.saveVGA1 = I915_READ(VGA1);
	dev_priv->regfile.saveVGA_PD = I915_READ(VGA_PD);
697
	if (HAS_PCH_SPLIT(dev))
698
		dev_priv->regfile.saveVGACNTRL = I915_READ(CPU_VGACNTRL);
699
	else
700
		dev_priv->regfile.saveVGACNTRL = I915_READ(VGACNTRL);
701 702 703 704

	i915_save_vga(dev);
}

705
static void i915_restore_display(struct drm_device *dev)
706 707
{
	struct drm_i915_private *dev_priv = dev->dev_private;
708

709
	/* Display arbitration */
710
	I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
711

712 713 714
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Display port ratios (must be done before clock is set) */
		if (SUPPORTS_INTEGRATED_DP(dev)) {
715 716 717 718 719 720 721 722
			I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
			I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
			I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
			I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
			I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->regfile.savePIPEA_DP_LINK_M);
			I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->regfile.savePIPEB_DP_LINK_M);
			I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->regfile.savePIPEA_DP_LINK_N);
			I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->regfile.savePIPEB_DP_LINK_N);
723
		}
724
	}
725

726 727 728
	/* This is only meaningful in non-KMS mode */
	/* Don't restore them in KMS mode */
	i915_restore_modeset_reg(dev);
729

730
	/* LVDS state */
731
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
732
		I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
733

734
	if (HAS_PCH_SPLIT(dev)) {
735
		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS);
736
	} else if (IS_MOBILE(dev) && !IS_I830(dev))
737
		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS);
738

739
	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
740
		I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
741

742
	if (HAS_PCH_SPLIT(dev)) {
743 744
		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
745 746 747
		/* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
		 * otherwise we get blank eDP screen after S3 on some machines
		 */
748 749 750 751 752 753
		I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
754
		I915_WRITE(RSTDBYCTL,
755
			   dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
756
	} else {
757 758 759 760 761 762 763
		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
		I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
		I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
764
	}
765

766 767 768
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Display Port state */
		if (SUPPORTS_INTEGRATED_DP(dev)) {
769 770 771
			I915_WRITE(DP_B, dev_priv->regfile.saveDP_B);
			I915_WRITE(DP_C, dev_priv->regfile.saveDP_C);
			I915_WRITE(DP_D, dev_priv->regfile.saveDP_D);
772 773
		}
		/* FIXME: restore TV & SDVO state */
774
	}
775

776
	/* only restore FBC info on the platform that supports FBC*/
777
	intel_disable_fbc(dev);
778
	if (I915_HAS_FBC(dev)) {
779
		if (HAS_PCH_SPLIT(dev)) {
780
			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
781
		} else if (IS_GM45(dev)) {
782
			I915_WRITE(DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
783
		} else {
784 785 786 787
			I915_WRITE(FBC_CFB_BASE, dev_priv->regfile.saveFBC_CFB_BASE);
			I915_WRITE(FBC_LL_BASE, dev_priv->regfile.saveFBC_LL_BASE);
			I915_WRITE(FBC_CONTROL2, dev_priv->regfile.saveFBC_CONTROL2);
			I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
788
		}
789
	}
790
	/* VGA state */
791
	if (HAS_PCH_SPLIT(dev))
792
		I915_WRITE(CPU_VGACNTRL, dev_priv->regfile.saveVGACNTRL);
793
	else
794
		I915_WRITE(VGACNTRL, dev_priv->regfile.saveVGACNTRL);
795

796 797 798
	I915_WRITE(VGA0, dev_priv->regfile.saveVGA0);
	I915_WRITE(VGA1, dev_priv->regfile.saveVGA1);
	I915_WRITE(VGA_PD, dev_priv->regfile.saveVGA_PD);
799 800
	POSTING_READ(VGA_PD);
	udelay(150);
801

802 803 804 805 806 807 808 809
	i915_restore_vga(dev);
}

int i915_save_state(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int i;

810
	pci_read_config_byte(dev->pdev, LBB, &dev_priv->regfile.saveLBB);
811

812 813
	mutex_lock(&dev->struct_mutex);

814 815
	i915_save_display(dev);

816 817 818
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Interrupt state */
		if (HAS_PCH_SPLIT(dev)) {
819 820 821 822 823 824 825
			dev_priv->regfile.saveDEIER = I915_READ(DEIER);
			dev_priv->regfile.saveDEIMR = I915_READ(DEIMR);
			dev_priv->regfile.saveGTIER = I915_READ(GTIER);
			dev_priv->regfile.saveGTIMR = I915_READ(GTIMR);
			dev_priv->regfile.saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
			dev_priv->regfile.saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
			dev_priv->regfile.saveMCHBAR_RENDER_STANDBY =
826
				I915_READ(RSTDBYCTL);
827
			dev_priv->regfile.savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
828
		} else {
829 830
			dev_priv->regfile.saveIER = I915_READ(IER);
			dev_priv->regfile.saveIMR = I915_READ(IMR);
831
		}
832
	}
833

834
	intel_disable_gt_powersave(dev);
835

836
	/* Cache mode state */
837
	dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
838 839

	/* Memory Arbitration state */
840
	dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
841 842 843

	/* Scratch space */
	for (i = 0; i < 16; i++) {
844 845
		dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
		dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
846 847
	}
	for (i = 0; i < 3; i++)
848
		dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
849

850 851
	mutex_unlock(&dev->struct_mutex);

852 853 854 855 856 857 858 859
	return 0;
}

int i915_restore_state(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int i;

860
	pci_write_config_byte(dev->pdev, LBB, dev_priv->regfile.saveLBB);
861

862 863
	mutex_lock(&dev->struct_mutex);

864 865
	i915_restore_display(dev);

866 867 868
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Interrupt state */
		if (HAS_PCH_SPLIT(dev)) {
869 870 871 872 873 874 875
			I915_WRITE(DEIER, dev_priv->regfile.saveDEIER);
			I915_WRITE(DEIMR, dev_priv->regfile.saveDEIMR);
			I915_WRITE(GTIER, dev_priv->regfile.saveGTIER);
			I915_WRITE(GTIMR, dev_priv->regfile.saveGTIMR);
			I915_WRITE(_FDI_RXA_IMR, dev_priv->regfile.saveFDI_RXA_IMR);
			I915_WRITE(_FDI_RXB_IMR, dev_priv->regfile.saveFDI_RXB_IMR);
			I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->regfile.savePCH_PORT_HOTPLUG);
876
		} else {
877 878
			I915_WRITE(IER, dev_priv->regfile.saveIER);
			I915_WRITE(IMR, dev_priv->regfile.saveIMR);
879
		}
880
	}
881

882
	/* Cache mode state */
883
	I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | 0xffff0000);
884 885

	/* Memory arbitration state */
886
	I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
887 888

	for (i = 0; i < 16; i++) {
889 890
		I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
		I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
891 892
	}
	for (i = 0; i < 3; i++)
893
		I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
894

895 896
	mutex_unlock(&dev->struct_mutex);

897
	intel_i2c_reset(dev);
898

899 900
	return 0;
}