i915_suspend.c 28.9 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 27 28 29
/*
 *
 * 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.
 */

#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
30
#include "intel_drv.h"
31
#include "i915_reg.h"
32 33 34 35

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

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

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

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

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

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

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

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

68
	for (i = 0; i < 256; i++)
69 70 71 72 73 74
		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;
75
	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
76 77 78 79 80 81
	u32 *array;
	int i;

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

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

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

90
	for (i = 0; i < 256; i++)
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 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
		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 */
	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);

	/* MSR bits */
	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
		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++)
		dev_priv->saveCR[i] =
			i915_read_indexed(dev, cr_index, cr_data, i);
	/* Make sure we don't turn off CR group 0 writes */
	dev_priv->saveCR[0x11] &= ~0x80;

	/* Attribute controller registers */
	I915_READ8(st01);
	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
	for (i = 0; i <= 0x14; i++)
		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
	I915_READ8(st01);
	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
	I915_READ8(st01);

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

	dev_priv->saveGR[0x10] =
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
	dev_priv->saveGR[0x11] =
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
	dev_priv->saveGR[0x18] =
		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);

	/* Sequencer registers */
	for (i = 0; i < 8; i++)
		dev_priv->saveSR[i] =
			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 */
	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
		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,
				   dev_priv->saveSR[i]);

	/* CRT controller regs */
	/* Enable CR group 0 writes */
	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
	for (i = 0; i <= 0x24; i++)
		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);

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

	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
			   dev_priv->saveGR[0x10]);
	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
			   dev_priv->saveGR[0x11]);
	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
			   dev_priv->saveGR[0x18]);

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

	/* VGA color palette registers */
	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
}

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

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

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

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

262
	/* Pipe & plane A info */
263 264
	dev_priv->savePIPEACONF = I915_READ(_PIPEACONF);
	dev_priv->savePIPEASRC = I915_READ(_PIPEASRC);
265
	if (HAS_PCH_SPLIT(dev)) {
266 267 268
		dev_priv->saveFPA0 = I915_READ(_PCH_FPA0);
		dev_priv->saveFPA1 = I915_READ(_PCH_FPA1);
		dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A);
269
	} else {
270 271 272
		dev_priv->saveFPA0 = I915_READ(_FPA0);
		dev_priv->saveFPA1 = I915_READ(_FPA1);
		dev_priv->saveDPLL_A = I915_READ(_DPLL_A);
273
	}
274
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
275 276 277 278 279 280 281
		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);
282
	if (!HAS_PCH_SPLIT(dev))
283
		dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
284

285
	if (HAS_PCH_SPLIT(dev)) {
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 311
		dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
		dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
		dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
		dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);

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

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

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

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

	/* Pipe & plane B info */
320 321
	dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF);
	dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC);
322
	if (HAS_PCH_SPLIT(dev)) {
323 324 325
		dev_priv->saveFPB0 = I915_READ(_PCH_FPB0);
		dev_priv->saveFPB1 = I915_READ(_PCH_FPB1);
		dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B);
326
	} else {
327 328 329
		dev_priv->saveFPB0 = I915_READ(_FPB0);
		dev_priv->saveFPB1 = I915_READ(_FPB1);
		dev_priv->saveDPLL_B = I915_READ(_DPLL_B);
330
	}
331
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
332 333 334 335 336 337 338
		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);
339
	if (!HAS_PCH_SPLIT(dev))
340
		dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
341

342
	if (HAS_PCH_SPLIT(dev)) {
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 368
		dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
		dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
		dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
		dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);

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

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

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

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

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

398 399
	return;
}
400

401 402 403
static void i915_restore_modeset_reg(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
404 405
	int dpll_a_reg, fpa0_reg, fpa1_reg;
	int dpll_b_reg, fpb0_reg, fpb1_reg;
406
	int i;
407 408 409 410

	if (drm_core_check_feature(dev, DRIVER_MODESET))
		return;

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


434
	if (HAS_PCH_SPLIT(dev)) {
435 436 437 438 439 440
		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;
441
	} else {
442 443 444 445 446 447
		dpll_a_reg = _DPLL_A;
		dpll_b_reg = _DPLL_B;
		fpa0_reg = _FPA0;
		fpb0_reg = _FPB0;
		fpa1_reg = _FPA1;
		fpb1_reg = _FPB1;
448 449
	}

450
	if (HAS_PCH_SPLIT(dev)) {
451 452 453 454
		I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
		I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
	}

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

	/* Restore mode */
476 477 478 479 480 481
	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);
482
	if (!HAS_PCH_SPLIT(dev))
483
		I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A);
484

485
	if (HAS_PCH_SPLIT(dev)) {
486 487 488 489
		I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
		I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
		I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
		I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
490

491 492
		I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
		I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
493

494 495 496
		I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1);
		I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
		I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
497

498 499 500 501 502 503 504
		I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF);
		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
		I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
		I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
		I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
		I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
505
	}
506 507

	/* Restore plane info */
508 509 510 511 512
	I915_WRITE(_DSPASIZE, dev_priv->saveDSPASIZE);
	I915_WRITE(_DSPAPOS, dev_priv->saveDSPAPOS);
	I915_WRITE(_PIPEASRC, dev_priv->savePIPEASRC);
	I915_WRITE(_DSPAADDR, dev_priv->saveDSPAADDR);
	I915_WRITE(_DSPASTRIDE, dev_priv->saveDSPASTRIDE);
513
	if (INTEL_INFO(dev)->gen >= 4) {
514 515
		I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF);
		I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF);
516 517
	}

518
	I915_WRITE(_PIPEACONF, dev_priv->savePIPEACONF);
519 520 521

	i915_restore_palette(dev, PIPE_A);
	/* Enable the plane */
522 523
	I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR);
	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
524 525 526

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

	/* Restore mode */
545 546 547 548 549 550
	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);
551
	if (!HAS_PCH_SPLIT(dev))
552
		I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B);
553

554
	if (HAS_PCH_SPLIT(dev)) {
555 556 557 558
		I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
		I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
		I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
		I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
559

560 561
		I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
		I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
562

563 564 565
		I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1);
		I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
		I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
566

567 568 569 570 571 572 573
		I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF);
		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
		I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
		I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
		I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
		I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
574
	}
575 576

	/* Restore plane info */
577 578 579 580 581
	I915_WRITE(_DSPBSIZE, dev_priv->saveDSPBSIZE);
	I915_WRITE(_DSPBPOS, dev_priv->saveDSPBPOS);
	I915_WRITE(_PIPEBSRC, dev_priv->savePIPEBSRC);
	I915_WRITE(_DSPBADDR, dev_priv->saveDSPBADDR);
	I915_WRITE(_DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
582
	if (INTEL_INFO(dev)->gen >= 4) {
583 584
		I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF);
		I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
585 586
	}

587
	I915_WRITE(_PIPEBCONF, dev_priv->savePIPEBCONF);
588 589 590

	i915_restore_palette(dev, PIPE_B);
	/* Enable the plane */
591 592
	I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR);
	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
593

594
	/* Cursor state */
595 596 597 598 599 600
	I915_WRITE(_CURAPOS, dev_priv->saveCURAPOS);
	I915_WRITE(_CURACNTR, dev_priv->saveCURACNTR);
	I915_WRITE(_CURABASE, dev_priv->saveCURABASE);
	I915_WRITE(_CURBPOS, dev_priv->saveCURBPOS);
	I915_WRITE(_CURBCNTR, dev_priv->saveCURBCNTR);
	I915_WRITE(_CURBBASE, dev_priv->saveCURBBASE);
601 602 603
	if (IS_GEN2(dev))
		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);

604 605
	return;
}
606

607
static void i915_save_display(struct drm_device *dev)
608 609 610 611 612 613 614 615 616
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	/* Display arbitration control */
	dev_priv->saveDSPARB = I915_READ(DSPARB);

	/* This is only meaningful in non-KMS mode */
	/* Don't save them in KMS mode */
	i915_save_modeset_reg(dev);
617

618
	/* CRT state */
619
	if (HAS_PCH_SPLIT(dev)) {
620 621 622 623
		dev_priv->saveADPA = I915_READ(PCH_ADPA);
	} else {
		dev_priv->saveADPA = I915_READ(ADPA);
	}
624 625

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

644
	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
645
		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
646

647
	if (HAS_PCH_SPLIT(dev)) {
648 649 650 651 652 653 654 655
		dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
		dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
		dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
	} else {
		dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
		dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
		dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
	}
656

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

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

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

	i915_save_vga(dev);
}

701
static void i915_restore_display(struct drm_device *dev)
702 703
{
	struct drm_i915_private *dev_priv = dev->dev_private;
704

705
	/* Display arbitration */
706 707
	I915_WRITE(DSPARB, dev_priv->saveDSPARB);

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

722 723 724
	/* This is only meaningful in non-KMS mode */
	/* Don't restore them in KMS mode */
	i915_restore_modeset_reg(dev);
725

726
	/* CRT state */
727
	if (HAS_PCH_SPLIT(dev))
728 729 730
		I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
	else
		I915_WRITE(ADPA, dev_priv->saveADPA);
731 732

	/* LVDS state */
733
	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
734
		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
735

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

741
	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
742 743
		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);

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

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

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

798 799 800
	I915_WRITE(VGA0, dev_priv->saveVGA0);
	I915_WRITE(VGA1, dev_priv->saveVGA1);
	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
801 802
	POSTING_READ(VGA_PD);
	udelay(150);
803

804 805 806 807 808 809 810 811 812 813
	i915_restore_vga(dev);
}

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

	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);

814 815
	mutex_lock(&dev->struct_mutex);

816 817 818
	/* Hardware status page */
	dev_priv->saveHWS = I915_READ(HWS_PGA);

819 820
	i915_save_display(dev);

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

839
	intel_disable_gt_powersave(dev);
840

841 842 843 844 845 846 847 848 849 850 851 852 853 854
	/* Cache mode state */
	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);

	/* Memory Arbitration state */
	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);

	/* Scratch space */
	for (i = 0; i < 16; i++) {
		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
	}
	for (i = 0; i < 3; i++)
		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));

855 856
	mutex_unlock(&dev->struct_mutex);

857 858 859 860 861 862 863 864 865 866
	return 0;
}

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

	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);

867 868
	mutex_lock(&dev->struct_mutex);

869 870 871
	/* Hardware status page */
	I915_WRITE(HWS_PGA, dev_priv->saveHWS);

872 873
	i915_restore_display(dev);

874 875 876 877 878 879 880 881 882 883 884 885 886 887
	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
		/* Interrupt state */
		if (HAS_PCH_SPLIT(dev)) {
			I915_WRITE(DEIER, dev_priv->saveDEIER);
			I915_WRITE(DEIMR, dev_priv->saveDEIMR);
			I915_WRITE(GTIER, dev_priv->saveGTIER);
			I915_WRITE(GTIMR, dev_priv->saveGTIMR);
			I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
			I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
			I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->savePCH_PORT_HOTPLUG);
		} else {
			I915_WRITE(IER, dev_priv->saveIER);
			I915_WRITE(IMR, dev_priv->saveIMR);
		}
888
	}
889

890
	/* Cache mode state */
891
	I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
892 893

	/* Memory arbitration state */
894
	I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
895 896 897

	for (i = 0; i < 16; i++) {
		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
898
		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
899 900 901 902
	}
	for (i = 0; i < 3; i++)
		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);

903 904
	mutex_unlock(&dev->struct_mutex);

905
	intel_i2c_reset(dev);
906

907 908
	return 0;
}