i915_suspend.c revision 296548
11541Srgrimes/*
21541Srgrimes *
31541Srgrimes * Copyright 2008 (c) Intel Corporation
41541Srgrimes *   Jesse Barnes <jbarnes@virtuousgeek.org>
51541Srgrimes *
61541Srgrimes * Permission is hereby granted, free of charge, to any person obtaining a
71541Srgrimes * copy of this software and associated documentation files (the
81541Srgrimes * "Software"), to deal in the Software without restriction, including
91541Srgrimes * without limitation the rights to use, copy, modify, merge, publish,
101541Srgrimes * distribute, sub license, and/or sell copies of the Software, and to
111541Srgrimes * permit persons to whom the Software is furnished to do so, subject to
121541Srgrimes * the following conditions:
131541Srgrimes *
141541Srgrimes * The above copyright notice and this permission notice (including the
151541Srgrimes * next paragraph) shall be included in all copies or substantial portions
161541Srgrimes * of the Software.
171541Srgrimes *
181541Srgrimes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
191541Srgrimes * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
201541Srgrimes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
211541Srgrimes * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
221541Srgrimes * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
231541Srgrimes * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
241541Srgrimes * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
251541Srgrimes */
261541Srgrimes
271541Srgrimes#include <sys/cdefs.h>
281541Srgrimes__FBSDID("$FreeBSD: head/sys/dev/drm2/i915/i915_suspend.c 296548 2016-03-08 20:33:02Z dumbbell $");
291541Srgrimes
301541Srgrimes#include <dev/drm2/drmP.h>
311541Srgrimes#include <dev/drm2/i915/i915_drm.h>
321541Srgrimes#include <dev/drm2/i915/intel_drv.h>
3314511Shsu#include <dev/drm2/i915/i915_reg.h>
3450477Speter
351541Srgrimesstatic bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
361541Srgrimes{
371541Srgrimes	struct drm_i915_private *dev_priv = dev->dev_private;
381541Srgrimes	u32	dpll_reg;
391541Srgrimes
401541Srgrimes	/* On IVB, 3rd pipe shares PLL with another one */
411541Srgrimes	if (pipe > 1)
4231778Seivind		return false;
431541Srgrimes
441541Srgrimes	if (HAS_PCH_SPLIT(dev))
4524207Sbde		dpll_reg = _PCH_DPLL(pipe);
4624207Sbde	else
4724207Sbde		dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
481541Srgrimes
491541Srgrimes	return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
501541Srgrimes}
5124131Sbde
5229354Speterstatic void i915_save_palette(struct drm_device *dev, enum pipe pipe)
531541Srgrimes{
541541Srgrimes	struct drm_i915_private *dev_priv = dev->dev_private;
553308Sphk	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
5649536Sphk	u32 *array;
571541Srgrimes	int i;
5849536Sphk
5912517Sjulian	if (!i915_pipe_enabled(dev, pipe))
6012819Sphk		return;
6112819Sphk
6249536Sphk	if (HAS_PCH_SPLIT(dev))
6311789Sbde		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
6412675Sjulian
6512675Sjulian	if (pipe == PIPE_A)
6612675Sjulian		array = dev_priv->regfile.save_palette_a;
6712675Sjulian	else
6812675Sjulian		array = dev_priv->regfile.save_palette_b;
6912675Sjulian
7012731Sbde	for (i = 0; i < 256; i++)
7112675Sjulian		array[i] = I915_READ(reg + (i << 2));
7212675Sjulian}
7312675Sjulian
7412675Sjulianstatic void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
7529354Speter{
7612675Sjulian	struct drm_i915_private *dev_priv = dev->dev_private;
7738485Sbde	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
7847625Sphk	u32 *array;
7947625Sphk	int i;
8047625Sphk
8147625Sphk	if (!i915_pipe_enabled(dev, pipe))
8247625Sphk		return;
8347625Sphk
8447625Sphk	if (HAS_PCH_SPLIT(dev))
8547625Sphk		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
8647625Sphk
8747625Sphk	if (pipe == PIPE_A)
8847625Sphk		array = dev_priv->regfile.save_palette_a;
8947625Sphk	else
9047625Sphk		array = dev_priv->regfile.save_palette_b;
9147625Sphk
9247625Sphk	for (i = 0; i < 256; i++)
9347625Sphk		I915_WRITE(reg + (i << 2), array[i]);
9447625Sphk}
9547625Sphk
9647625Sphkstatic u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
9747625Sphk{
9838485Sbde	struct drm_i915_private *dev_priv = dev->dev_private;
9912675Sjulian
10038485Sbde	I915_WRITE8(index_port, reg);
10147625Sphk	return I915_READ8(data_port);
10247625Sphk}
10347625Sphk
10447625Sphkstatic u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
10547625Sphk{
10647625Sphk	struct drm_i915_private *dev_priv = dev->dev_private;
10747625Sphk
10847625Sphk	I915_READ8(st01);
10947625Sphk	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
11047625Sphk	return I915_READ8(VGA_AR_DATA_READ);
11147625Sphk}
11247625Sphk
11347625Sphkstatic void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
11447625Sphk{
11547625Sphk	struct drm_i915_private *dev_priv = dev->dev_private;
11647625Sphk
11747625Sphk	I915_READ8(st01);
11847625Sphk	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
11947625Sphk	I915_WRITE8(VGA_AR_DATA_WRITE, val);
12047625Sphk}
12138485Sbde
12212675Sjulianstatic void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
1231541Srgrimes{
1241541Srgrimes	struct drm_i915_private *dev_priv = dev->dev_private;
12549536Sphk
1261541Srgrimes	I915_WRITE8(index_port, reg);
1271541Srgrimes	I915_WRITE8(data_port, val);
1281541Srgrimes}
1291541Srgrimes
13049536Sphkstatic void i915_save_vga(struct drm_device *dev)
13150092Sjulian{
13249536Sphk	struct drm_i915_private *dev_priv = dev->dev_private;
1331541Srgrimes	int i;
1341541Srgrimes	u16 cr_index, cr_data, st01;
1351541Srgrimes
1361541Srgrimes	/* VGA color palette registers */
1371541Srgrimes	dev_priv->regfile.saveDACMASK = I915_READ8(VGA_DACMASK);
1381541Srgrimes
1391541Srgrimes	/* MSR bits */
1401541Srgrimes	dev_priv->regfile.saveMSR = I915_READ8(VGA_MSR_READ);
14149536Sphk	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
1421541Srgrimes		cr_index = VGA_CR_INDEX_CGA;
14349536Sphk		cr_data = VGA_CR_DATA_CGA;
14449536Sphk		st01 = VGA_ST01_CGA;
14549536Sphk	} else {
14649536Sphk		cr_index = VGA_CR_INDEX_MDA;
14749536Sphk		cr_data = VGA_CR_DATA_MDA;
1481541Srgrimes		st01 = VGA_ST01_MDA;
14912819Sphk	}
15049536Sphk
1511541Srgrimes	/* CRT controller regs */
1521541Srgrimes	i915_write_indexed(dev, cr_index, cr_data, 0x11,
15349536Sphk			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
15449536Sphk			   (~0x80));
15549536Sphk	for (i = 0; i <= 0x24; i++)
1561541Srgrimes		dev_priv->regfile.saveCR[i] =
15749536Sphk			i915_read_indexed(dev, cr_index, cr_data, i);
15849536Sphk	/* Make sure we don't turn off CR group 0 writes */
15949536Sphk	dev_priv->regfile.saveCR[0x11] &= ~0x80;
16049536Sphk
16150092Sjulian	/* Attribute controller registers */
16250092Sjulian	I915_READ8(st01);
16350092Sjulian	dev_priv->regfile.saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
16449536Sphk	for (i = 0; i <= 0x14; i++)
16550092Sjulian		dev_priv->regfile.saveAR[i] = i915_read_ar(dev, st01, i, 0);
16649536Sphk	I915_READ8(st01);
16749536Sphk	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX);
16849536Sphk	I915_READ8(st01);
16950652Sphk
17049540Sphk	/* Graphics controller registers */
17116322Sgpalmer	for (i = 0; i < 9; i++)
1721541Srgrimes		dev_priv->regfile.saveGR[i] =
1731541Srgrimes			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
17412675Sjulian
1751541Srgrimes	dev_priv->regfile.saveGR[0x10] =
1761541Srgrimes		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
1771541Srgrimes	dev_priv->regfile.saveGR[0x11] =
1781541Srgrimes		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
1791541Srgrimes	dev_priv->regfile.saveGR[0x18] =
1801541Srgrimes		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
1811541Srgrimes
18249992Sjulian	/* Sequencer registers */
18349992Sjulian	for (i = 0; i < 8; i++)
1841541Srgrimes		dev_priv->regfile.saveSR[i] =
18549992Sjulian			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
18650254Sphk}
18749992Sjulian
18850254Sphkstatic void i915_restore_vga(struct drm_device *dev)
18949992Sjulian{
19049992Sjulian	struct drm_i915_private *dev_priv = dev->dev_private;
19149992Sjulian	int i;
19249992Sjulian	u16 cr_index, cr_data, st01;
19349992Sjulian
19449992Sjulian	/* MSR bits */
19549992Sjulian	I915_WRITE8(VGA_MSR_WRITE, dev_priv->regfile.saveMSR);
19649992Sjulian	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
19749536Sphk		cr_index = VGA_CR_INDEX_CGA;
19849536Sphk		cr_data = VGA_CR_DATA_CGA;
19949536Sphk		st01 = VGA_ST01_CGA;
20049536Sphk	} else {
20150652Sphk		cr_index = VGA_CR_INDEX_MDA;
2021541Srgrimes		cr_data = VGA_CR_DATA_MDA;
2031541Srgrimes		st01 = VGA_ST01_MDA;
2041541Srgrimes	}
2051541Srgrimes
2061541Srgrimes	/* Sequencer registers, don't write SR07 */
2071541Srgrimes	for (i = 0; i < 7; i++)
2081541Srgrimes		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
20946112Sphk				   dev_priv->regfile.saveSR[i]);
2101541Srgrimes
2111541Srgrimes	/* CRT controller regs */
2129824Sbde	/* Enable CR group 0 writes */
2131541Srgrimes	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->regfile.saveCR[0x11]);
2141541Srgrimes	for (i = 0; i <= 0x24; i++)
2151541Srgrimes		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->regfile.saveCR[i]);
2169639Sbde
2179624Sbde	/* Graphics controller regs */
2183308Sphk	for (i = 0; i < 9; i++)
2191541Srgrimes		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
2201541Srgrimes				   dev_priv->regfile.saveGR[i]);
2211541Srgrimes
2227724Sache	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
2237724Sache			   dev_priv->regfile.saveGR[0x10]);
2241541Srgrimes	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
2251541Srgrimes			   dev_priv->regfile.saveGR[0x11]);
2261541Srgrimes	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
22712675Sjulian			   dev_priv->regfile.saveGR[0x18]);
2281541Srgrimes
2291541Srgrimes	/* Attribute controller registers */
2301541Srgrimes	I915_READ8(st01); /* switch back to index mode */
2311541Srgrimes	for (i = 0; i <= 0x14; i++)
2321541Srgrimes		i915_write_ar(dev, st01, i, dev_priv->regfile.saveAR[i], 0);
2331541Srgrimes	I915_READ8(st01); /* switch back to index mode */
2341541Srgrimes	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX | 0x20);
2351541Srgrimes	I915_READ8(st01);
23650652Sphk
2371541Srgrimes	/* VGA color palette registers */
2387730Sache	I915_WRITE8(VGA_DACMASK, dev_priv->regfile.saveDACMASK);
2397724Sache}
2401541Srgrimes
2411541Srgrimesstatic void i915_save_modeset_reg(struct drm_device *dev)
2421541Srgrimes{
24312675Sjulian	struct drm_i915_private *dev_priv = dev->dev_private;
2441541Srgrimes	int i;
2451541Srgrimes
2461541Srgrimes	if (drm_core_check_feature(dev, DRIVER_MODESET))
2471541Srgrimes		return;
2481541Srgrimes
2491541Srgrimes	/* Cursor state */
25050652Sphk	dev_priv->regfile.saveCURACNTR = I915_READ(_CURACNTR);
25149536Sphk	dev_priv->regfile.saveCURAPOS = I915_READ(_CURAPOS);
2521541Srgrimes	dev_priv->regfile.saveCURABASE = I915_READ(_CURABASE);
2531541Srgrimes	dev_priv->regfile.saveCURBCNTR = I915_READ(_CURBCNTR);
2541541Srgrimes	dev_priv->regfile.saveCURBPOS = I915_READ(_CURBPOS);
2551541Srgrimes	dev_priv->regfile.saveCURBBASE = I915_READ(_CURBBASE);
2561541Srgrimes	if (IS_GEN2(dev))
2571541Srgrimes		dev_priv->regfile.saveCURSIZE = I915_READ(CURSIZE);
2581541Srgrimes
2591541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
2601541Srgrimes		dev_priv->regfile.savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
2611541Srgrimes		dev_priv->regfile.saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
2621541Srgrimes	}
2639624Sbde
2649624Sbde	/* Pipe & plane A info */
2653308Sphk	dev_priv->regfile.savePIPEACONF = I915_READ(_PIPEACONF);
2661541Srgrimes	dev_priv->regfile.savePIPEASRC = I915_READ(_PIPEASRC);
2671541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
2681541Srgrimes		dev_priv->regfile.saveFPA0 = I915_READ(_PCH_FPA0);
2691541Srgrimes		dev_priv->regfile.saveFPA1 = I915_READ(_PCH_FPA1);
2701541Srgrimes		dev_priv->regfile.saveDPLL_A = I915_READ(_PCH_DPLL_A);
2719639Sbde	} else {
2729624Sbde		dev_priv->regfile.saveFPA0 = I915_READ(_FPA0);
2733308Sphk		dev_priv->regfile.saveFPA1 = I915_READ(_FPA1);
2741541Srgrimes		dev_priv->regfile.saveDPLL_A = I915_READ(_DPLL_A);
2751541Srgrimes	}
2761541Srgrimes	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
2771541Srgrimes		dev_priv->regfile.saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
2781541Srgrimes	dev_priv->regfile.saveHTOTAL_A = I915_READ(_HTOTAL_A);
2791541Srgrimes	dev_priv->regfile.saveHBLANK_A = I915_READ(_HBLANK_A);
2801541Srgrimes	dev_priv->regfile.saveHSYNC_A = I915_READ(_HSYNC_A);
2811541Srgrimes	dev_priv->regfile.saveVTOTAL_A = I915_READ(_VTOTAL_A);
2821541Srgrimes	dev_priv->regfile.saveVBLANK_A = I915_READ(_VBLANK_A);
2831541Srgrimes	dev_priv->regfile.saveVSYNC_A = I915_READ(_VSYNC_A);
2841541Srgrimes	if (!HAS_PCH_SPLIT(dev))
2851541Srgrimes		dev_priv->regfile.saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
2861541Srgrimes
2871541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
2881541Srgrimes		dev_priv->regfile.savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
2891541Srgrimes		dev_priv->regfile.savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
2901541Srgrimes		dev_priv->regfile.savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
2911541Srgrimes		dev_priv->regfile.savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);
2921541Srgrimes
2931541Srgrimes		dev_priv->regfile.saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
2941541Srgrimes		dev_priv->regfile.saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);
2951541Srgrimes
2961541Srgrimes		dev_priv->regfile.savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
2971541Srgrimes		dev_priv->regfile.savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
29812675Sjulian		dev_priv->regfile.savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
2991541Srgrimes
3001541Srgrimes		dev_priv->regfile.saveTRANSACONF = I915_READ(_TRANSACONF);
3011541Srgrimes		dev_priv->regfile.saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
3021541Srgrimes		dev_priv->regfile.saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
3031541Srgrimes		dev_priv->regfile.saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
3041541Srgrimes		dev_priv->regfile.saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
3051541Srgrimes		dev_priv->regfile.saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
30650652Sphk		dev_priv->regfile.saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
3071541Srgrimes	}
3081541Srgrimes
3091541Srgrimes	dev_priv->regfile.saveDSPACNTR = I915_READ(_DSPACNTR);
3101541Srgrimes	dev_priv->regfile.saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
3111541Srgrimes	dev_priv->regfile.saveDSPASIZE = I915_READ(_DSPASIZE);
3121541Srgrimes	dev_priv->regfile.saveDSPAPOS = I915_READ(_DSPAPOS);
3131541Srgrimes	dev_priv->regfile.saveDSPAADDR = I915_READ(_DSPAADDR);
3141541Srgrimes	if (INTEL_INFO(dev)->gen >= 4) {
3151541Srgrimes		dev_priv->regfile.saveDSPASURF = I915_READ(_DSPASURF);
31612819Sphk		dev_priv->regfile.saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
3171541Srgrimes	}
3181541Srgrimes	i915_save_palette(dev, PIPE_A);
3191541Srgrimes	dev_priv->regfile.savePIPEASTAT = I915_READ(_PIPEASTAT);
32049536Sphk
3211541Srgrimes	/* Pipe & plane B info */
3221541Srgrimes	dev_priv->regfile.savePIPEBCONF = I915_READ(_PIPEBCONF);
3231541Srgrimes	dev_priv->regfile.savePIPEBSRC = I915_READ(_PIPEBSRC);
3241541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
3251541Srgrimes		dev_priv->regfile.saveFPB0 = I915_READ(_PCH_FPB0);
3261541Srgrimes		dev_priv->regfile.saveFPB1 = I915_READ(_PCH_FPB1);
3271541Srgrimes		dev_priv->regfile.saveDPLL_B = I915_READ(_PCH_DPLL_B);
3281541Srgrimes	} else {
3291541Srgrimes		dev_priv->regfile.saveFPB0 = I915_READ(_FPB0);
3301541Srgrimes		dev_priv->regfile.saveFPB1 = I915_READ(_FPB1);
33112819Sphk		dev_priv->regfile.saveDPLL_B = I915_READ(_DPLL_B);
3321541Srgrimes	}
3331541Srgrimes	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
3341541Srgrimes		dev_priv->regfile.saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
3351541Srgrimes	dev_priv->regfile.saveHTOTAL_B = I915_READ(_HTOTAL_B);
33649536Sphk	dev_priv->regfile.saveHBLANK_B = I915_READ(_HBLANK_B);
3371541Srgrimes	dev_priv->regfile.saveHSYNC_B = I915_READ(_HSYNC_B);
3381541Srgrimes	dev_priv->regfile.saveVTOTAL_B = I915_READ(_VTOTAL_B);
3391541Srgrimes	dev_priv->regfile.saveVBLANK_B = I915_READ(_VBLANK_B);
3409639Sbde	dev_priv->regfile.saveVSYNC_B = I915_READ(_VSYNC_B);
3411541Srgrimes	if (!HAS_PCH_SPLIT(dev))
3421541Srgrimes		dev_priv->regfile.saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
3431541Srgrimes
3449639Sbde	if (HAS_PCH_SPLIT(dev)) {
3451541Srgrimes		dev_priv->regfile.savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
3461541Srgrimes		dev_priv->regfile.savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
3471541Srgrimes		dev_priv->regfile.savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
34812675Sjulian		dev_priv->regfile.savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);
3491541Srgrimes
3501541Srgrimes		dev_priv->regfile.saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
3511541Srgrimes		dev_priv->regfile.saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);
3521541Srgrimes
3531541Srgrimes		dev_priv->regfile.savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
3541541Srgrimes		dev_priv->regfile.savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
3551541Srgrimes		dev_priv->regfile.savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
3561541Srgrimes
35749536Sphk		dev_priv->regfile.saveTRANSBCONF = I915_READ(_TRANSBCONF);
35849536Sphk		dev_priv->regfile.saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
35949536Sphk		dev_priv->regfile.saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
36049536Sphk		dev_priv->regfile.saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
36150652Sphk		dev_priv->regfile.saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
3621541Srgrimes		dev_priv->regfile.saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
3631541Srgrimes		dev_priv->regfile.saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
3641541Srgrimes	}
3651541Srgrimes
3661541Srgrimes	dev_priv->regfile.saveDSPBCNTR = I915_READ(_DSPBCNTR);
36749536Sphk	dev_priv->regfile.saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
3681541Srgrimes	dev_priv->regfile.saveDSPBSIZE = I915_READ(_DSPBSIZE);
3691541Srgrimes	dev_priv->regfile.saveDSPBPOS = I915_READ(_DSPBPOS);
3701541Srgrimes	dev_priv->regfile.saveDSPBADDR = I915_READ(_DSPBADDR);
3711541Srgrimes	if (INTEL_INFO(dev)->gen >= 4) {
3721541Srgrimes		dev_priv->regfile.saveDSPBSURF = I915_READ(_DSPBSURF);
3731541Srgrimes		dev_priv->regfile.saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
37412675Sjulian	}
37510624Sbde	i915_save_palette(dev, PIPE_B);
3761541Srgrimes	dev_priv->regfile.savePIPEBSTAT = I915_READ(_PIPEBSTAT);
37710624Sbde
37810624Sbde	/* Fences */
37910624Sbde	switch (INTEL_INFO(dev)->gen) {
3801541Srgrimes	case 7:
3811541Srgrimes	case 6:
3821541Srgrimes		for (i = 0; i < 16; i++)
38350652Sphk			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
3841541Srgrimes		break;
3859824Sbde	case 5:
3869824Sbde	case 4:
3879824Sbde		for (i = 0; i < 16; i++)
3889824Sbde			dev_priv->regfile.saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
3899824Sbde		break;
3909824Sbde	case 3:
3919824Sbde		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
3929824Sbde			for (i = 0; i < 8; i++)
3939824Sbde				dev_priv->regfile.saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
3949850Sbde	case 2:
3959850Sbde		for (i = 0; i < 8; i++)
3969850Sbde			dev_priv->regfile.saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
3979850Sbde		break;
3989850Sbde	}
3999824Sbde
4001541Srgrimes	/* CRT state */
4011541Srgrimes	if (HAS_PCH_SPLIT(dev))
4021541Srgrimes		dev_priv->regfile.saveADPA = I915_READ(PCH_ADPA);
4031541Srgrimes	else
40412675Sjulian		dev_priv->regfile.saveADPA = I915_READ(ADPA);
4051541Srgrimes
4061541Srgrimes	return;
4071541Srgrimes}
4081541Srgrimes
4091541Srgrimesstatic void i915_restore_modeset_reg(struct drm_device *dev)
41050652Sphk{
41149536Sphk	struct drm_i915_private *dev_priv = dev->dev_private;
4121541Srgrimes	int dpll_a_reg, fpa0_reg, fpa1_reg;
4131541Srgrimes	int dpll_b_reg, fpb0_reg, fpb1_reg;
4141541Srgrimes	int i;
4151541Srgrimes
4161541Srgrimes	if (drm_core_check_feature(dev, DRIVER_MODESET))
4171541Srgrimes		return;
4181541Srgrimes
4191541Srgrimes	/* Fences */
4201541Srgrimes	switch (INTEL_INFO(dev)->gen) {
4211541Srgrimes	case 7:
4221541Srgrimes	case 6:
4231541Srgrimes		for (i = 0; i < 16; i++)
4241541Srgrimes			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
4251541Srgrimes		break;
4261541Srgrimes	case 5:
4271541Srgrimes	case 4:
4281541Srgrimes		for (i = 0; i < 16; i++)
4291541Srgrimes			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->regfile.saveFENCE[i]);
4302807Sbde		break;
4312807Sbde	case 3:
4321541Srgrimes	case 2:
4331541Srgrimes		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
4341541Srgrimes			for (i = 0; i < 8; i++)
4351541Srgrimes				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->regfile.saveFENCE[i+8]);
4361541Srgrimes		for (i = 0; i < 8; i++)
4371541Srgrimes			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->regfile.saveFENCE[i]);
4381541Srgrimes		break;
4391541Srgrimes	}
4401541Srgrimes
4411541Srgrimes
4421541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
4431541Srgrimes		dpll_a_reg = _PCH_DPLL_A;
4441541Srgrimes		dpll_b_reg = _PCH_DPLL_B;
4451541Srgrimes		fpa0_reg = _PCH_FPA0;
4469824Sbde		fpb0_reg = _PCH_FPB0;
4471541Srgrimes		fpa1_reg = _PCH_FPA1;
4481541Srgrimes		fpb1_reg = _PCH_FPB1;
4491541Srgrimes	} else {
4509639Sbde		dpll_a_reg = _DPLL_A;
4513308Sphk		dpll_b_reg = _DPLL_B;
4521541Srgrimes		fpa0_reg = _FPA0;
4531541Srgrimes		fpb0_reg = _FPB0;
4541541Srgrimes		fpa1_reg = _FPA1;
4551541Srgrimes		fpb1_reg = _FPB1;
4561541Srgrimes	}
4571541Srgrimes
4581541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
4591541Srgrimes		I915_WRITE(PCH_DREF_CONTROL, dev_priv->regfile.savePCH_DREF_CONTROL);
4601541Srgrimes		I915_WRITE(DISP_ARB_CTL, dev_priv->regfile.saveDISP_ARB_CTL);
4611541Srgrimes	}
4629626Sbde
4631541Srgrimes	/* Pipe & plane A info */
4641541Srgrimes	/* Prime the clock */
4651541Srgrimes	if (dev_priv->regfile.saveDPLL_A & DPLL_VCO_ENABLE) {
46612675Sjulian		I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A &
4671541Srgrimes			   ~DPLL_VCO_ENABLE);
4681541Srgrimes		POSTING_READ(dpll_a_reg);
4691541Srgrimes		udelay(150);
4701541Srgrimes	}
47149536Sphk	I915_WRITE(fpa0_reg, dev_priv->regfile.saveFPA0);
4721541Srgrimes	I915_WRITE(fpa1_reg, dev_priv->regfile.saveFPA1);
4731541Srgrimes	/* Actually enable it */
4741541Srgrimes	I915_WRITE(dpll_a_reg, dev_priv->regfile.saveDPLL_A);
4751541Srgrimes	POSTING_READ(dpll_a_reg);
4761541Srgrimes	udelay(150);
4771541Srgrimes	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
4781541Srgrimes		I915_WRITE(_DPLL_A_MD, dev_priv->regfile.saveDPLL_A_MD);
4791541Srgrimes		POSTING_READ(_DPLL_A_MD);
4801541Srgrimes	}
4811541Srgrimes	udelay(150);
4821541Srgrimes
4831541Srgrimes	/* Restore mode */
4841541Srgrimes	I915_WRITE(_HTOTAL_A, dev_priv->regfile.saveHTOTAL_A);
4851541Srgrimes	I915_WRITE(_HBLANK_A, dev_priv->regfile.saveHBLANK_A);
4861541Srgrimes	I915_WRITE(_HSYNC_A, dev_priv->regfile.saveHSYNC_A);
4871541Srgrimes	I915_WRITE(_VTOTAL_A, dev_priv->regfile.saveVTOTAL_A);
4881541Srgrimes	I915_WRITE(_VBLANK_A, dev_priv->regfile.saveVBLANK_A);
4891541Srgrimes	I915_WRITE(_VSYNC_A, dev_priv->regfile.saveVSYNC_A);
49012675Sjulian	if (!HAS_PCH_SPLIT(dev))
49129354Speter		I915_WRITE(_BCLRPAT_A, dev_priv->regfile.saveBCLRPAT_A);
4921541Srgrimes
49329354Speter	if (HAS_PCH_SPLIT(dev)) {
4941541Srgrimes		I915_WRITE(_PIPEA_DATA_M1, dev_priv->regfile.savePIPEA_DATA_M1);
4951541Srgrimes		I915_WRITE(_PIPEA_DATA_N1, dev_priv->regfile.savePIPEA_DATA_N1);
49650652Sphk		I915_WRITE(_PIPEA_LINK_M1, dev_priv->regfile.savePIPEA_LINK_M1);
49749536Sphk		I915_WRITE(_PIPEA_LINK_N1, dev_priv->regfile.savePIPEA_LINK_N1);
49829354Speter
4991541Srgrimes		I915_WRITE(_FDI_RXA_CTL, dev_priv->regfile.saveFDI_RXA_CTL);
5001541Srgrimes		I915_WRITE(_FDI_TXA_CTL, dev_priv->regfile.saveFDI_TXA_CTL);
5019824Sbde
50229354Speter		I915_WRITE(_PFA_CTL_1, dev_priv->regfile.savePFA_CTL_1);
5031541Srgrimes		I915_WRITE(_PFA_WIN_SZ, dev_priv->regfile.savePFA_WIN_SZ);
50429354Speter		I915_WRITE(_PFA_WIN_POS, dev_priv->regfile.savePFA_WIN_POS);
50529354Speter
50629354Speter		I915_WRITE(_TRANSACONF, dev_priv->regfile.saveTRANSACONF);
50729354Speter		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->regfile.saveTRANS_HTOTAL_A);
5081541Srgrimes		I915_WRITE(_TRANS_HBLANK_A, dev_priv->regfile.saveTRANS_HBLANK_A);
50929354Speter		I915_WRITE(_TRANS_HSYNC_A, dev_priv->regfile.saveTRANS_HSYNC_A);
51029354Speter		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->regfile.saveTRANS_VTOTAL_A);
51129354Speter		I915_WRITE(_TRANS_VBLANK_A, dev_priv->regfile.saveTRANS_VBLANK_A);
51229354Speter		I915_WRITE(_TRANS_VSYNC_A, dev_priv->regfile.saveTRANS_VSYNC_A);
51329354Speter	}
51429354Speter
5151541Srgrimes	/* Restore plane info */
51629354Speter	I915_WRITE(_DSPASIZE, dev_priv->regfile.saveDSPASIZE);
51729354Speter	I915_WRITE(_DSPAPOS, dev_priv->regfile.saveDSPAPOS);
51829354Speter	I915_WRITE(_PIPEASRC, dev_priv->regfile.savePIPEASRC);
51929354Speter	I915_WRITE(_DSPAADDR, dev_priv->regfile.saveDSPAADDR);
52029354Speter	I915_WRITE(_DSPASTRIDE, dev_priv->regfile.saveDSPASTRIDE);
52129354Speter	if (INTEL_INFO(dev)->gen >= 4) {
52229354Speter		I915_WRITE(_DSPASURF, dev_priv->regfile.saveDSPASURF);
5231541Srgrimes		I915_WRITE(_DSPATILEOFF, dev_priv->regfile.saveDSPATILEOFF);
52429354Speter	}
52529354Speter
52629354Speter	I915_WRITE(_PIPEACONF, dev_priv->regfile.savePIPEACONF);
5271541Srgrimes
52829354Speter	i915_restore_palette(dev, PIPE_A);
52929354Speter	/* Enable the plane */
53029354Speter	I915_WRITE(_DSPACNTR, dev_priv->regfile.saveDSPACNTR);
53129354Speter	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
53229354Speter
53329354Speter	/* Pipe & plane B info */
5341541Srgrimes	if (dev_priv->regfile.saveDPLL_B & DPLL_VCO_ENABLE) {
53529354Speter		I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B &
53629354Speter			   ~DPLL_VCO_ENABLE);
53729354Speter		POSTING_READ(dpll_b_reg);
5381541Srgrimes		udelay(150);
5391541Srgrimes	}
54012675Sjulian	I915_WRITE(fpb0_reg, dev_priv->regfile.saveFPB0);
5411541Srgrimes	I915_WRITE(fpb1_reg, dev_priv->regfile.saveFPB1);
5421541Srgrimes	/* Actually enable it */
5431541Srgrimes	I915_WRITE(dpll_b_reg, dev_priv->regfile.saveDPLL_B);
5441541Srgrimes	POSTING_READ(dpll_b_reg);
5451541Srgrimes	udelay(150);
54650652Sphk	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
5471549Srgrimes		I915_WRITE(_DPLL_B_MD, dev_priv->regfile.saveDPLL_B_MD);
5481541Srgrimes		POSTING_READ(_DPLL_B_MD);
5491541Srgrimes	}
5501541Srgrimes	udelay(150);
55149536Sphk
5521541Srgrimes	/* Restore mode */
5531541Srgrimes	I915_WRITE(_HTOTAL_B, dev_priv->regfile.saveHTOTAL_B);
5541541Srgrimes	I915_WRITE(_HBLANK_B, dev_priv->regfile.saveHBLANK_B);
5551541Srgrimes	I915_WRITE(_HSYNC_B, dev_priv->regfile.saveHSYNC_B);
5561541Srgrimes	I915_WRITE(_VTOTAL_B, dev_priv->regfile.saveVTOTAL_B);
5571541Srgrimes	I915_WRITE(_VBLANK_B, dev_priv->regfile.saveVBLANK_B);
5581541Srgrimes	I915_WRITE(_VSYNC_B, dev_priv->regfile.saveVSYNC_B);
5591541Srgrimes	if (!HAS_PCH_SPLIT(dev))
56011789Sbde		I915_WRITE(_BCLRPAT_B, dev_priv->regfile.saveBCLRPAT_B);
56111789Sbde
5621541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
5631541Srgrimes		I915_WRITE(_PIPEB_DATA_M1, dev_priv->regfile.savePIPEB_DATA_M1);
5641541Srgrimes		I915_WRITE(_PIPEB_DATA_N1, dev_priv->regfile.savePIPEB_DATA_N1);
5651541Srgrimes		I915_WRITE(_PIPEB_LINK_M1, dev_priv->regfile.savePIPEB_LINK_M1);
5661541Srgrimes		I915_WRITE(_PIPEB_LINK_N1, dev_priv->regfile.savePIPEB_LINK_N1);
5671541Srgrimes
5681541Srgrimes		I915_WRITE(_FDI_RXB_CTL, dev_priv->regfile.saveFDI_RXB_CTL);
5691541Srgrimes		I915_WRITE(_FDI_TXB_CTL, dev_priv->regfile.saveFDI_TXB_CTL);
57011789Sbde
57111789Sbde		I915_WRITE(_PFB_CTL_1, dev_priv->regfile.savePFB_CTL_1);
57211789Sbde		I915_WRITE(_PFB_WIN_SZ, dev_priv->regfile.savePFB_WIN_SZ);
5731541Srgrimes		I915_WRITE(_PFB_WIN_POS, dev_priv->regfile.savePFB_WIN_POS);
57411789Sbde
5751541Srgrimes		I915_WRITE(_TRANSBCONF, dev_priv->regfile.saveTRANSBCONF);
57615199Sbde		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->regfile.saveTRANS_HTOTAL_B);
57715199Sbde		I915_WRITE(_TRANS_HBLANK_B, dev_priv->regfile.saveTRANS_HBLANK_B);
57815199Sbde		I915_WRITE(_TRANS_HSYNC_B, dev_priv->regfile.saveTRANS_HSYNC_B);
57915199Sbde		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->regfile.saveTRANS_VTOTAL_B);
58015199Sbde		I915_WRITE(_TRANS_VBLANK_B, dev_priv->regfile.saveTRANS_VBLANK_B);
58115199Sbde		I915_WRITE(_TRANS_VSYNC_B, dev_priv->regfile.saveTRANS_VSYNC_B);
58215199Sbde	}
58315199Sbde
58415199Sbde	/* Restore plane info */
58515199Sbde	I915_WRITE(_DSPBSIZE, dev_priv->regfile.saveDSPBSIZE);
58615199Sbde	I915_WRITE(_DSPBPOS, dev_priv->regfile.saveDSPBPOS);
58715199Sbde	I915_WRITE(_PIPEBSRC, dev_priv->regfile.savePIPEBSRC);
58815199Sbde	I915_WRITE(_DSPBADDR, dev_priv->regfile.saveDSPBADDR);
5891541Srgrimes	I915_WRITE(_DSPBSTRIDE, dev_priv->regfile.saveDSPBSTRIDE);
59011789Sbde	if (INTEL_INFO(dev)->gen >= 4) {
59111789Sbde		I915_WRITE(_DSPBSURF, dev_priv->regfile.saveDSPBSURF);
5921541Srgrimes		I915_WRITE(_DSPBTILEOFF, dev_priv->regfile.saveDSPBTILEOFF);
5931541Srgrimes	}
5949639Sbde
5951541Srgrimes	I915_WRITE(_PIPEBCONF, dev_priv->regfile.savePIPEBCONF);
5961541Srgrimes
59711789Sbde	i915_restore_palette(dev, PIPE_B);
5981541Srgrimes	/* Enable the plane */
5991541Srgrimes	I915_WRITE(_DSPBCNTR, dev_priv->regfile.saveDSPBCNTR);
6001541Srgrimes	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
6011541Srgrimes
6021541Srgrimes	/* Cursor state */
6031541Srgrimes	I915_WRITE(_CURAPOS, dev_priv->regfile.saveCURAPOS);
6041541Srgrimes	I915_WRITE(_CURACNTR, dev_priv->regfile.saveCURACNTR);
60511789Sbde	I915_WRITE(_CURABASE, dev_priv->regfile.saveCURABASE);
60611789Sbde	I915_WRITE(_CURBPOS, dev_priv->regfile.saveCURBPOS);
60711789Sbde	I915_WRITE(_CURBCNTR, dev_priv->regfile.saveCURBCNTR);
6081541Srgrimes	I915_WRITE(_CURBBASE, dev_priv->regfile.saveCURBBASE);
60911789Sbde	if (IS_GEN2(dev))
6101541Srgrimes		I915_WRITE(CURSIZE, dev_priv->regfile.saveCURSIZE);
6111541Srgrimes
6121541Srgrimes	/* CRT state */
6131541Srgrimes	if (HAS_PCH_SPLIT(dev))
6149824Sbde		I915_WRITE(PCH_ADPA, dev_priv->regfile.saveADPA);
6151541Srgrimes	else
6161541Srgrimes		I915_WRITE(ADPA, dev_priv->regfile.saveADPA);
6171541Srgrimes
6181541Srgrimes	return;
6191541Srgrimes}
6201541Srgrimes
6211541Srgrimesstatic void i915_save_display(struct drm_device *dev)
6221541Srgrimes{
6231541Srgrimes	struct drm_i915_private *dev_priv = dev->dev_private;
6241541Srgrimes
6251541Srgrimes	/* Display arbitration control */
6261541Srgrimes	dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
62715199Sbde
6281541Srgrimes	/* This is only meaningful in non-KMS mode */
62911789Sbde	/* Don't regfile.save them in KMS mode */
63011789Sbde	i915_save_modeset_reg(dev);
63111789Sbde
6321541Srgrimes	/* LVDS state */
63311789Sbde	if (HAS_PCH_SPLIT(dev)) {
6341541Srgrimes		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
6351541Srgrimes		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
6361541Srgrimes		dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
6371541Srgrimes		dev_priv->regfile.saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
6381541Srgrimes		dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
6391541Srgrimes		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
6401541Srgrimes	} else {
6419639Sbde		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
6423308Sphk		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
6431541Srgrimes		dev_priv->regfile.saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
6441541Srgrimes		dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
6451541Srgrimes		if (INTEL_INFO(dev)->gen >= 4)
6461541Srgrimes			dev_priv->regfile.saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
6471541Srgrimes		if (IS_MOBILE(dev) && !IS_I830(dev))
6481541Srgrimes			dev_priv->regfile.saveLVDS = I915_READ(LVDS);
6491541Srgrimes	}
65012675Sjulian
6516712Spst	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
6526712Spst		dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
6536712Spst
65449536Sphk	if (HAS_PCH_SPLIT(dev)) {
6556712Spst		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
6566712Spst		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
65750652Sphk		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
6586712Spst	} else {
6596712Spst		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
6601541Srgrimes		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
66112675Sjulian		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
6621541Srgrimes	}
6631541Srgrimes
66436735Sdfr	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
6651541Srgrimes		/* Display Port state */
6661541Srgrimes		if (SUPPORTS_INTEGRATED_DP(dev)) {
6671541Srgrimes			dev_priv->regfile.saveDP_B = I915_READ(DP_B);
6681541Srgrimes			dev_priv->regfile.saveDP_C = I915_READ(DP_C);
66950652Sphk			dev_priv->regfile.saveDP_D = I915_READ(DP_D);
67049536Sphk			dev_priv->regfile.savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
6711541Srgrimes			dev_priv->regfile.savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
6721541Srgrimes			dev_priv->regfile.savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
6731541Srgrimes			dev_priv->regfile.savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
67447301Sluoqi			dev_priv->regfile.savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
6751541Srgrimes			dev_priv->regfile.savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
6761541Srgrimes			dev_priv->regfile.savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
6771541Srgrimes			dev_priv->regfile.savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
6781541Srgrimes		}
67933826Sbde		/* FIXME: regfile.save TV & SDVO state */
6801541Srgrimes	}
6811541Srgrimes
6821541Srgrimes	/* Only regfile.save FBC state on the platform that supports FBC */
6831541Srgrimes	if (I915_HAS_FBC(dev)) {
6841541Srgrimes		if (HAS_PCH_SPLIT(dev)) {
6851541Srgrimes			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
6861541Srgrimes		} else if (IS_GM45(dev)) {
6871541Srgrimes			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
6881541Srgrimes		} else {
6891541Srgrimes			dev_priv->regfile.saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
6901541Srgrimes			dev_priv->regfile.saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
6911541Srgrimes			dev_priv->regfile.saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
6921541Srgrimes			dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
6931541Srgrimes		}
6941541Srgrimes	}
6951541Srgrimes
6961541Srgrimes	/* VGA state */
6971541Srgrimes	dev_priv->regfile.saveVGA0 = I915_READ(VGA0);
6981541Srgrimes	dev_priv->regfile.saveVGA1 = I915_READ(VGA1);
6991541Srgrimes	dev_priv->regfile.saveVGA_PD = I915_READ(VGA_PD);
7001541Srgrimes	if (HAS_PCH_SPLIT(dev))
7011541Srgrimes		dev_priv->regfile.saveVGACNTRL = I915_READ(CPU_VGACNTRL);
7021541Srgrimes	else
7031541Srgrimes		dev_priv->regfile.saveVGACNTRL = I915_READ(VGACNTRL);
7041541Srgrimes
7051541Srgrimes	i915_save_vga(dev);
7061541Srgrimes}
7071541Srgrimes
7081541Srgrimesstatic void i915_restore_display(struct drm_device *dev)
7091541Srgrimes{
71047203Sluoqi	struct drm_i915_private *dev_priv = dev->dev_private;
7111541Srgrimes
71247203Sluoqi	/* Display arbitration */
71347203Sluoqi	I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
71447301Sluoqi
71547203Sluoqi	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
71647203Sluoqi		/* Display port ratios (must be done before clock is set) */
71747301Sluoqi		if (SUPPORTS_INTEGRATED_DP(dev)) {
71847203Sluoqi			I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->regfile.savePIPEA_GMCH_DATA_M);
71947203Sluoqi			I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->regfile.savePIPEB_GMCH_DATA_M);
7201541Srgrimes			I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->regfile.savePIPEA_GMCH_DATA_N);
7218876Srgrimes			I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->regfile.savePIPEB_GMCH_DATA_N);
7221541Srgrimes			I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->regfile.savePIPEA_DP_LINK_M);
7231541Srgrimes			I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->regfile.savePIPEB_DP_LINK_M);
7241541Srgrimes			I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->regfile.savePIPEA_DP_LINK_N);
7251541Srgrimes			I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->regfile.savePIPEB_DP_LINK_N);
7261541Srgrimes		}
7279858Sache	}
72847301Sluoqi
72947301Sluoqi	/* This is only meaningful in non-KMS mode */
73047301Sluoqi	/* Don't restore them in KMS mode */
73147301Sluoqi	i915_restore_modeset_reg(dev);
73247301Sluoqi
7331541Srgrimes	/* LVDS state */
7341541Srgrimes	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
7351541Srgrimes		I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
7361541Srgrimes
73727770Sjmg	if (HAS_PCH_SPLIT(dev)) {
73827770Sjmg		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS);
7391541Srgrimes	} else if (IS_MOBILE(dev) && !IS_I830(dev))
7401541Srgrimes		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS);
7411541Srgrimes
7421541Srgrimes	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
7431541Srgrimes		I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
7441541Srgrimes
7451541Srgrimes	if (HAS_PCH_SPLIT(dev)) {
7461541Srgrimes		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->regfile.saveBLC_PWM_CTL);
7471541Srgrimes		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
74847203Sluoqi		/* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
74947301Sluoqi		 * otherwise we get blank eDP screen after S3 on some machines
75047301Sluoqi		 */
75147301Sluoqi		I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->regfile.saveBLC_CPU_PWM_CTL2);
75247301Sluoqi		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->regfile.saveBLC_CPU_PWM_CTL);
75347301Sluoqi		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
75447301Sluoqi		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
75547301Sluoqi		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
75647301Sluoqi		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
75747301Sluoqi		I915_WRITE(RSTDBYCTL,
75847301Sluoqi			   dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
75947301Sluoqi	} else {
76047301Sluoqi		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
76147301Sluoqi		I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL);
76247301Sluoqi		I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
76347301Sluoqi		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
76447301Sluoqi		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
76547301Sluoqi		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
76647301Sluoqi		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
76747301Sluoqi	}
76847301Sluoqi
76947301Sluoqi	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
77047301Sluoqi		/* Display Port state */
7711541Srgrimes		if (SUPPORTS_INTEGRATED_DP(dev)) {
77231577Sbde			I915_WRITE(DP_B, dev_priv->regfile.saveDP_B);
7731541Srgrimes			I915_WRITE(DP_C, dev_priv->regfile.saveDP_C);
77431577Sbde			I915_WRITE(DP_D, dev_priv->regfile.saveDP_D);
7751541Srgrimes		}
7761541Srgrimes		/* FIXME: restore TV & SDVO state */
7771541Srgrimes	}
7781541Srgrimes
7791541Srgrimes	/* only restore FBC info on the platform that supports FBC*/
7801541Srgrimes	intel_disable_fbc(dev);
7811541Srgrimes	if (I915_HAS_FBC(dev)) {
7821541Srgrimes		if (HAS_PCH_SPLIT(dev)) {
7831541Srgrimes			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
7841541Srgrimes		} else if (IS_GM45(dev)) {
7851541Srgrimes			I915_WRITE(DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
7861541Srgrimes		} else {
7871541Srgrimes			I915_WRITE(FBC_CFB_BASE, dev_priv->regfile.saveFBC_CFB_BASE);
7881541Srgrimes			I915_WRITE(FBC_LL_BASE, dev_priv->regfile.saveFBC_LL_BASE);
7891541Srgrimes			I915_WRITE(FBC_CONTROL2, dev_priv->regfile.saveFBC_CONTROL2);
7901541Srgrimes			I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
7911541Srgrimes		}
7921541Srgrimes	}
7931541Srgrimes	/* VGA state */
7941541Srgrimes	if (HAS_PCH_SPLIT(dev))
7951541Srgrimes		I915_WRITE(CPU_VGACNTRL, dev_priv->regfile.saveVGACNTRL);
7961541Srgrimes	else
7971541Srgrimes		I915_WRITE(VGACNTRL, dev_priv->regfile.saveVGACNTRL);
7981541Srgrimes
7991541Srgrimes	I915_WRITE(VGA0, dev_priv->regfile.saveVGA0);
8001541Srgrimes	I915_WRITE(VGA1, dev_priv->regfile.saveVGA1);
8011541Srgrimes	I915_WRITE(VGA_PD, dev_priv->regfile.saveVGA_PD);
8021541Srgrimes	POSTING_READ(VGA_PD);
8031541Srgrimes	udelay(150);
8041541Srgrimes
8051541Srgrimes	i915_restore_vga(dev);
8061541Srgrimes}
8071541Srgrimes
8081541Srgrimesint i915_save_state(struct drm_device *dev)
8091541Srgrimes{
8108876Srgrimes	struct drm_i915_private *dev_priv = dev->dev_private;
8111541Srgrimes	int i;
8121541Srgrimes
8131541Srgrimes	pci_read_config_byte(dev->dev, LBB, &dev_priv->regfile.saveLBB);
8141541Srgrimes
8151541Srgrimes	DRM_LOCK(dev);
8161541Srgrimes
8171541Srgrimes	i915_save_display(dev);
8181541Srgrimes
8191541Srgrimes	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
8201541Srgrimes		/* Interrupt state */
8211541Srgrimes		if (HAS_PCH_SPLIT(dev)) {
8221541Srgrimes			dev_priv->regfile.saveDEIER = I915_READ(DEIER);
8231541Srgrimes			dev_priv->regfile.saveDEIMR = I915_READ(DEIMR);
8241541Srgrimes			dev_priv->regfile.saveGTIER = I915_READ(GTIER);
8251541Srgrimes			dev_priv->regfile.saveGTIMR = I915_READ(GTIMR);
8261541Srgrimes			dev_priv->regfile.saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
8271541Srgrimes			dev_priv->regfile.saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
8281541Srgrimes			dev_priv->regfile.saveMCHBAR_RENDER_STANDBY =
82912517Sjulian				I915_READ(RSTDBYCTL);
83012517Sjulian			dev_priv->regfile.savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
83129506Sbde		} else {
83249536Sphk			dev_priv->regfile.saveIER = I915_READ(IER);
83312675Sjulian			dev_priv->regfile.saveIMR = I915_READ(IMR);
83429506Sbde		}
83529506Sbde	}
83612517Sjulian
83750254Sphk	intel_disable_gt_powersave(dev);
83850254Sphk
83950254Sphk	/* Cache mode state */
84050254Sphk	dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
84112517Sjulian
84212517Sjulian	/* Memory Arbitration state */
84312517Sjulian	dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
844
845	/* Scratch space */
846	for (i = 0; i < 16; i++) {
847		dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
848		dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
849	}
850	for (i = 0; i < 3; i++)
851		dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
852
853	DRM_UNLOCK(dev);
854
855	return 0;
856}
857
858int i915_restore_state(struct drm_device *dev)
859{
860	struct drm_i915_private *dev_priv = dev->dev_private;
861	int i;
862
863	pci_write_config_byte(dev->dev, LBB, dev_priv->regfile.saveLBB);
864
865	DRM_LOCK(dev);
866
867	i915_restore_display(dev);
868
869	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
870		/* Interrupt state */
871		if (HAS_PCH_SPLIT(dev)) {
872			I915_WRITE(DEIER, dev_priv->regfile.saveDEIER);
873			I915_WRITE(DEIMR, dev_priv->regfile.saveDEIMR);
874			I915_WRITE(GTIER, dev_priv->regfile.saveGTIER);
875			I915_WRITE(GTIMR, dev_priv->regfile.saveGTIMR);
876			I915_WRITE(_FDI_RXA_IMR, dev_priv->regfile.saveFDI_RXA_IMR);
877			I915_WRITE(_FDI_RXB_IMR, dev_priv->regfile.saveFDI_RXB_IMR);
878			I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->regfile.savePCH_PORT_HOTPLUG);
879		} else {
880			I915_WRITE(IER, dev_priv->regfile.saveIER);
881			I915_WRITE(IMR, dev_priv->regfile.saveIMR);
882		}
883	}
884
885	/* Cache mode state */
886	I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | 0xffff0000);
887
888	/* Memory arbitration state */
889	I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
890
891	for (i = 0; i < 16; i++) {
892		I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
893		I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
894	}
895	for (i = 0; i < 3; i++)
896		I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
897
898	DRM_UNLOCK(dev);
899
900	intel_i2c_reset(dev);
901
902	return 0;
903}
904