• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/gpu/drm/i915/
1/*
2 *
3 * Copyright 2008 (c) Intel Corporation
4 *   Jesse Barnes <jbarnes@virtuousgeek.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27#include "drmP.h"
28#include "drm.h"
29#include "i915_drm.h"
30#include "intel_drv.h"
31
32static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
33{
34	struct drm_i915_private *dev_priv = dev->dev_private;
35	u32	dpll_reg;
36
37	if (HAS_PCH_SPLIT(dev)) {
38		dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
39	} else {
40		dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
41	}
42
43	return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
44}
45
46static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
47{
48	struct drm_i915_private *dev_priv = dev->dev_private;
49	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
50	u32 *array;
51	int i;
52
53	if (!i915_pipe_enabled(dev, pipe))
54		return;
55
56	if (HAS_PCH_SPLIT(dev))
57		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
58
59	if (pipe == PIPE_A)
60		array = dev_priv->save_palette_a;
61	else
62		array = dev_priv->save_palette_b;
63
64	for(i = 0; i < 256; i++)
65		array[i] = I915_READ(reg + (i << 2));
66}
67
68static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
69{
70	struct drm_i915_private *dev_priv = dev->dev_private;
71	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
72	u32 *array;
73	int i;
74
75	if (!i915_pipe_enabled(dev, pipe))
76		return;
77
78	if (HAS_PCH_SPLIT(dev))
79		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
80
81	if (pipe == PIPE_A)
82		array = dev_priv->save_palette_a;
83	else
84		array = dev_priv->save_palette_b;
85
86	for(i = 0; i < 256; i++)
87		I915_WRITE(reg + (i << 2), array[i]);
88}
89
90static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
91{
92	struct drm_i915_private *dev_priv = dev->dev_private;
93
94	I915_WRITE8(index_port, reg);
95	return I915_READ8(data_port);
96}
97
98static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
99{
100	struct drm_i915_private *dev_priv = dev->dev_private;
101
102	I915_READ8(st01);
103	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
104	return I915_READ8(VGA_AR_DATA_READ);
105}
106
107static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
108{
109	struct drm_i915_private *dev_priv = dev->dev_private;
110
111	I915_READ8(st01);
112	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
113	I915_WRITE8(VGA_AR_DATA_WRITE, val);
114}
115
116static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
117{
118	struct drm_i915_private *dev_priv = dev->dev_private;
119
120	I915_WRITE8(index_port, reg);
121	I915_WRITE8(data_port, val);
122}
123
124static void i915_save_vga(struct drm_device *dev)
125{
126	struct drm_i915_private *dev_priv = dev->dev_private;
127	int i;
128	u16 cr_index, cr_data, st01;
129
130	/* VGA color palette registers */
131	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
132
133	/* MSR bits */
134	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
135	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
136		cr_index = VGA_CR_INDEX_CGA;
137		cr_data = VGA_CR_DATA_CGA;
138		st01 = VGA_ST01_CGA;
139	} else {
140		cr_index = VGA_CR_INDEX_MDA;
141		cr_data = VGA_CR_DATA_MDA;
142		st01 = VGA_ST01_MDA;
143	}
144
145	/* CRT controller regs */
146	i915_write_indexed(dev, cr_index, cr_data, 0x11,
147			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
148			   (~0x80));
149	for (i = 0; i <= 0x24; i++)
150		dev_priv->saveCR[i] =
151			i915_read_indexed(dev, cr_index, cr_data, i);
152	/* Make sure we don't turn off CR group 0 writes */
153	dev_priv->saveCR[0x11] &= ~0x80;
154
155	/* Attribute controller registers */
156	I915_READ8(st01);
157	dev_priv->saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
158	for (i = 0; i <= 0x14; i++)
159		dev_priv->saveAR[i] = i915_read_ar(dev, st01, i, 0);
160	I915_READ8(st01);
161	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX);
162	I915_READ8(st01);
163
164	/* Graphics controller registers */
165	for (i = 0; i < 9; i++)
166		dev_priv->saveGR[i] =
167			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
168
169	dev_priv->saveGR[0x10] =
170		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
171	dev_priv->saveGR[0x11] =
172		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
173	dev_priv->saveGR[0x18] =
174		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
175
176	/* Sequencer registers */
177	for (i = 0; i < 8; i++)
178		dev_priv->saveSR[i] =
179			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
180}
181
182static void i915_restore_vga(struct drm_device *dev)
183{
184	struct drm_i915_private *dev_priv = dev->dev_private;
185	int i;
186	u16 cr_index, cr_data, st01;
187
188	/* MSR bits */
189	I915_WRITE8(VGA_MSR_WRITE, dev_priv->saveMSR);
190	if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
191		cr_index = VGA_CR_INDEX_CGA;
192		cr_data = VGA_CR_DATA_CGA;
193		st01 = VGA_ST01_CGA;
194	} else {
195		cr_index = VGA_CR_INDEX_MDA;
196		cr_data = VGA_CR_DATA_MDA;
197		st01 = VGA_ST01_MDA;
198	}
199
200	/* Sequencer registers, don't write SR07 */
201	for (i = 0; i < 7; i++)
202		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
203				   dev_priv->saveSR[i]);
204
205	/* CRT controller regs */
206	/* Enable CR group 0 writes */
207	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
208	for (i = 0; i <= 0x24; i++)
209		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->saveCR[i]);
210
211	/* Graphics controller regs */
212	for (i = 0; i < 9; i++)
213		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
214				   dev_priv->saveGR[i]);
215
216	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
217			   dev_priv->saveGR[0x10]);
218	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
219			   dev_priv->saveGR[0x11]);
220	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
221			   dev_priv->saveGR[0x18]);
222
223	/* Attribute controller registers */
224	I915_READ8(st01); /* switch back to index mode */
225	for (i = 0; i <= 0x14; i++)
226		i915_write_ar(dev, st01, i, dev_priv->saveAR[i], 0);
227	I915_READ8(st01); /* switch back to index mode */
228	I915_WRITE8(VGA_AR_INDEX, dev_priv->saveAR_INDEX | 0x20);
229	I915_READ8(st01);
230
231	/* VGA color palette registers */
232	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
233}
234
235static void i915_save_modeset_reg(struct drm_device *dev)
236{
237	struct drm_i915_private *dev_priv = dev->dev_private;
238
239	if (drm_core_check_feature(dev, DRIVER_MODESET))
240		return;
241
242	if (HAS_PCH_SPLIT(dev)) {
243		dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
244		dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
245	}
246
247	/* Pipe & plane A info */
248	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
249	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
250	if (HAS_PCH_SPLIT(dev)) {
251		dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
252		dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
253		dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
254	} else {
255		dev_priv->saveFPA0 = I915_READ(FPA0);
256		dev_priv->saveFPA1 = I915_READ(FPA1);
257		dev_priv->saveDPLL_A = I915_READ(DPLL_A);
258	}
259	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
260		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
261	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
262	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
263	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
264	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
265	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
266	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
267	if (!HAS_PCH_SPLIT(dev))
268		dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
269
270	if (HAS_PCH_SPLIT(dev)) {
271		dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
272		dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
273		dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
274		dev_priv->savePIPEA_LINK_N1 = I915_READ(PIPEA_LINK_N1);
275
276		dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL);
277		dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL);
278
279		dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1);
280		dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ);
281		dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS);
282
283		dev_priv->saveTRANSACONF = I915_READ(TRANSACONF);
284		dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A);
285		dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A);
286		dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A);
287		dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A);
288		dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A);
289		dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A);
290	}
291
292	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
293	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
294	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
295	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
296	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
297	if (IS_I965G(dev)) {
298		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
299		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
300	}
301	i915_save_palette(dev, PIPE_A);
302	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
303
304	/* Pipe & plane B info */
305	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
306	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
307	if (HAS_PCH_SPLIT(dev)) {
308		dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
309		dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
310		dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
311	} else {
312		dev_priv->saveFPB0 = I915_READ(FPB0);
313		dev_priv->saveFPB1 = I915_READ(FPB1);
314		dev_priv->saveDPLL_B = I915_READ(DPLL_B);
315	}
316	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
317		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
318	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
319	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
320	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
321	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
322	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
323	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
324	if (!HAS_PCH_SPLIT(dev))
325		dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
326
327	if (HAS_PCH_SPLIT(dev)) {
328		dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
329		dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
330		dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
331		dev_priv->savePIPEB_LINK_N1 = I915_READ(PIPEB_LINK_N1);
332
333		dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL);
334		dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL);
335
336		dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1);
337		dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ);
338		dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS);
339
340		dev_priv->saveTRANSBCONF = I915_READ(TRANSBCONF);
341		dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B);
342		dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B);
343		dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B);
344		dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B);
345		dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B);
346		dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B);
347	}
348
349	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
350	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
351	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
352	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
353	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
354	if (IS_I965GM(dev) || IS_GM45(dev)) {
355		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
356		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
357	}
358	i915_save_palette(dev, PIPE_B);
359	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
360	return;
361}
362
363static void i915_restore_modeset_reg(struct drm_device *dev)
364{
365	struct drm_i915_private *dev_priv = dev->dev_private;
366	int dpll_a_reg, fpa0_reg, fpa1_reg;
367	int dpll_b_reg, fpb0_reg, fpb1_reg;
368
369	if (drm_core_check_feature(dev, DRIVER_MODESET))
370		return;
371
372	if (HAS_PCH_SPLIT(dev)) {
373		dpll_a_reg = PCH_DPLL_A;
374		dpll_b_reg = PCH_DPLL_B;
375		fpa0_reg = PCH_FPA0;
376		fpb0_reg = PCH_FPB0;
377		fpa1_reg = PCH_FPA1;
378		fpb1_reg = PCH_FPB1;
379	} else {
380		dpll_a_reg = DPLL_A;
381		dpll_b_reg = DPLL_B;
382		fpa0_reg = FPA0;
383		fpb0_reg = FPB0;
384		fpa1_reg = FPA1;
385		fpb1_reg = FPB1;
386	}
387
388	if (HAS_PCH_SPLIT(dev)) {
389		I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
390		I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
391	}
392
393	/* Pipe & plane A info */
394	/* Prime the clock */
395	if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
396		I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A &
397			   ~DPLL_VCO_ENABLE);
398		POSTING_READ(dpll_a_reg);
399		udelay(150);
400	}
401	I915_WRITE(fpa0_reg, dev_priv->saveFPA0);
402	I915_WRITE(fpa1_reg, dev_priv->saveFPA1);
403	/* Actually enable it */
404	I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
405	POSTING_READ(dpll_a_reg);
406	udelay(150);
407	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
408		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
409		POSTING_READ(DPLL_A_MD);
410	}
411	udelay(150);
412
413	/* Restore mode */
414	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
415	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
416	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
417	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
418	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
419	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
420	if (!HAS_PCH_SPLIT(dev))
421		I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
422
423	if (HAS_PCH_SPLIT(dev)) {
424		I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
425		I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
426		I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
427		I915_WRITE(PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
428
429		I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
430		I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
431
432		I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1);
433		I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
434		I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
435
436		I915_WRITE(TRANSACONF, dev_priv->saveTRANSACONF);
437		I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
438		I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
439		I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
440		I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
441		I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
442		I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
443	}
444
445	/* Restore plane info */
446	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
447	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
448	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
449	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
450	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
451	if (IS_I965G(dev)) {
452		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
453		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
454	}
455
456	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
457
458	i915_restore_palette(dev, PIPE_A);
459	/* Enable the plane */
460	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
461	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
462
463	/* Pipe & plane B info */
464	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
465		I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B &
466			   ~DPLL_VCO_ENABLE);
467		POSTING_READ(dpll_b_reg);
468		udelay(150);
469	}
470	I915_WRITE(fpb0_reg, dev_priv->saveFPB0);
471	I915_WRITE(fpb1_reg, dev_priv->saveFPB1);
472	/* Actually enable it */
473	I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
474	POSTING_READ(dpll_b_reg);
475	udelay(150);
476	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
477		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
478		POSTING_READ(DPLL_B_MD);
479	}
480	udelay(150);
481
482	/* Restore mode */
483	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
484	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
485	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
486	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
487	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
488	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
489	if (!HAS_PCH_SPLIT(dev))
490		I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
491
492	if (HAS_PCH_SPLIT(dev)) {
493		I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
494		I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
495		I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
496		I915_WRITE(PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
497
498		I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
499		I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
500
501		I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1);
502		I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
503		I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
504
505		I915_WRITE(TRANSBCONF, dev_priv->saveTRANSBCONF);
506		I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
507		I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
508		I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
509		I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
510		I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
511		I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
512	}
513
514	/* Restore plane info */
515	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
516	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
517	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
518	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
519	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
520	if (IS_I965G(dev)) {
521		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
522		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
523	}
524
525	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
526
527	i915_restore_palette(dev, PIPE_B);
528	/* Enable the plane */
529	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
530	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
531
532	return;
533}
534
535void i915_save_display(struct drm_device *dev)
536{
537	struct drm_i915_private *dev_priv = dev->dev_private;
538
539	/* Display arbitration control */
540	dev_priv->saveDSPARB = I915_READ(DSPARB);
541
542	/* This is only meaningful in non-KMS mode */
543	/* Don't save them in KMS mode */
544	i915_save_modeset_reg(dev);
545
546	/* Cursor state */
547	dev_priv->saveCURACNTR = I915_READ(CURACNTR);
548	dev_priv->saveCURAPOS = I915_READ(CURAPOS);
549	dev_priv->saveCURABASE = I915_READ(CURABASE);
550	dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
551	dev_priv->saveCURBPOS = I915_READ(CURBPOS);
552	dev_priv->saveCURBBASE = I915_READ(CURBBASE);
553	if (!IS_I9XX(dev))
554		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
555
556	/* CRT state */
557	if (HAS_PCH_SPLIT(dev)) {
558		dev_priv->saveADPA = I915_READ(PCH_ADPA);
559	} else {
560		dev_priv->saveADPA = I915_READ(ADPA);
561	}
562
563	/* LVDS state */
564	if (HAS_PCH_SPLIT(dev)) {
565		dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
566		dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
567		dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
568		dev_priv->saveBLC_CPU_PWM_CTL = I915_READ(BLC_PWM_CPU_CTL);
569		dev_priv->saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2);
570		dev_priv->saveLVDS = I915_READ(PCH_LVDS);
571	} else {
572		dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
573		dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
574		dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
575		dev_priv->saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
576		if (IS_I965G(dev))
577			dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
578		if (IS_MOBILE(dev) && !IS_I830(dev))
579			dev_priv->saveLVDS = I915_READ(LVDS);
580	}
581
582	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
583		dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
584
585	if (HAS_PCH_SPLIT(dev)) {
586		dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
587		dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
588		dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
589	} else {
590		dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
591		dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
592		dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
593	}
594
595	/* Display Port state */
596	if (SUPPORTS_INTEGRATED_DP(dev)) {
597		dev_priv->saveDP_B = I915_READ(DP_B);
598		dev_priv->saveDP_C = I915_READ(DP_C);
599		dev_priv->saveDP_D = I915_READ(DP_D);
600		dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M);
601		dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M);
602		dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N);
603		dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N);
604		dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M);
605		dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M);
606		dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N);
607		dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N);
608	}
609
610	/* Only save FBC state on the platform that supports FBC */
611	if (I915_HAS_FBC(dev)) {
612		if (HAS_PCH_SPLIT(dev)) {
613			dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
614		} else if (IS_GM45(dev)) {
615			dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
616		} else {
617			dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
618			dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
619			dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
620			dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
621		}
622	}
623
624	/* VGA state */
625	dev_priv->saveVGA0 = I915_READ(VGA0);
626	dev_priv->saveVGA1 = I915_READ(VGA1);
627	dev_priv->saveVGA_PD = I915_READ(VGA_PD);
628	if (HAS_PCH_SPLIT(dev))
629		dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
630	else
631		dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
632
633	i915_save_vga(dev);
634}
635
636void i915_restore_display(struct drm_device *dev)
637{
638	struct drm_i915_private *dev_priv = dev->dev_private;
639
640	/* Display arbitration */
641	I915_WRITE(DSPARB, dev_priv->saveDSPARB);
642
643	/* Display port ratios (must be done before clock is set) */
644	if (SUPPORTS_INTEGRATED_DP(dev)) {
645		I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
646		I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
647		I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
648		I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
649		I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
650		I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
651		I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
652		I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
653	}
654
655	/* This is only meaningful in non-KMS mode */
656	/* Don't restore them in KMS mode */
657	i915_restore_modeset_reg(dev);
658
659	/* Cursor state */
660	I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
661	I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
662	I915_WRITE(CURABASE, dev_priv->saveCURABASE);
663	I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
664	I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
665	I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
666	if (!IS_I9XX(dev))
667		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
668
669	/* CRT state */
670	if (HAS_PCH_SPLIT(dev))
671		I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
672	else
673		I915_WRITE(ADPA, dev_priv->saveADPA);
674
675	/* LVDS state */
676	if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
677		I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
678
679	if (HAS_PCH_SPLIT(dev)) {
680		I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
681	} else if (IS_MOBILE(dev) && !IS_I830(dev))
682		I915_WRITE(LVDS, dev_priv->saveLVDS);
683
684	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
685		I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
686
687	if (HAS_PCH_SPLIT(dev)) {
688		I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
689		I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
690		I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
691		I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2);
692		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
693		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
694		I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
695		I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
696		I915_WRITE(MCHBAR_RENDER_STANDBY,
697			   dev_priv->saveMCHBAR_RENDER_STANDBY);
698	} else {
699		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
700		I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
701		I915_WRITE(BLC_HIST_CTL, dev_priv->saveBLC_HIST_CTL);
702		I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS);
703		I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
704		I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
705		I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
706	}
707
708	/* Display Port state */
709	if (SUPPORTS_INTEGRATED_DP(dev)) {
710		I915_WRITE(DP_B, dev_priv->saveDP_B);
711		I915_WRITE(DP_C, dev_priv->saveDP_C);
712		I915_WRITE(DP_D, dev_priv->saveDP_D);
713	}
714
715	/* only restore FBC info on the platform that supports FBC*/
716	if (I915_HAS_FBC(dev)) {
717		if (HAS_PCH_SPLIT(dev)) {
718			ironlake_disable_fbc(dev);
719			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
720		} else if (IS_GM45(dev)) {
721			g4x_disable_fbc(dev);
722			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
723		} else {
724			i8xx_disable_fbc(dev);
725			I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
726			I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
727			I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
728			I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
729		}
730	}
731	/* VGA state */
732	if (HAS_PCH_SPLIT(dev))
733		I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
734	else
735		I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
736	I915_WRITE(VGA0, dev_priv->saveVGA0);
737	I915_WRITE(VGA1, dev_priv->saveVGA1);
738	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
739	POSTING_READ(VGA_PD);
740	udelay(150);
741
742	i915_restore_vga(dev);
743}
744
745int i915_save_state(struct drm_device *dev)
746{
747	struct drm_i915_private *dev_priv = dev->dev_private;
748	int i;
749
750	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
751
752	/* Hardware status page */
753	dev_priv->saveHWS = I915_READ(HWS_PGA);
754
755	i915_save_display(dev);
756
757	/* Interrupt state */
758	if (HAS_PCH_SPLIT(dev)) {
759		dev_priv->saveDEIER = I915_READ(DEIER);
760		dev_priv->saveDEIMR = I915_READ(DEIMR);
761		dev_priv->saveGTIER = I915_READ(GTIER);
762		dev_priv->saveGTIMR = I915_READ(GTIMR);
763		dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
764		dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
765		dev_priv->saveMCHBAR_RENDER_STANDBY =
766			I915_READ(MCHBAR_RENDER_STANDBY);
767	} else {
768		dev_priv->saveIER = I915_READ(IER);
769		dev_priv->saveIMR = I915_READ(IMR);
770	}
771
772	if (HAS_PCH_SPLIT(dev))
773		ironlake_disable_drps(dev);
774
775	/* Cache mode state */
776	dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
777
778	/* Memory Arbitration state */
779	dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
780
781	/* Scratch space */
782	for (i = 0; i < 16; i++) {
783		dev_priv->saveSWF0[i] = I915_READ(SWF00 + (i << 2));
784		dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
785	}
786	for (i = 0; i < 3; i++)
787		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
788
789	/* Fences */
790	switch (INTEL_INFO(dev)->gen) {
791	case 6:
792		for (i = 0; i < 16; i++)
793			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
794		break;
795	case 5:
796	case 4:
797		for (i = 0; i < 16; i++)
798			dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8));
799		break;
800	case 3:
801		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
802			for (i = 0; i < 8; i++)
803				dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4));
804	case 2:
805		for (i = 0; i < 8; i++)
806			dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4));
807		break;
808
809	}
810
811	return 0;
812}
813
814int i915_restore_state(struct drm_device *dev)
815{
816	struct drm_i915_private *dev_priv = dev->dev_private;
817	int i;
818
819	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
820
821	/* Hardware status page */
822	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
823
824	/* Fences */
825	switch (INTEL_INFO(dev)->gen) {
826	case 6:
827		for (i = 0; i < 16; i++)
828			I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
829		break;
830	case 5:
831	case 4:
832		for (i = 0; i < 16; i++)
833			I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]);
834		break;
835	case 3:
836	case 2:
837		if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
838			for (i = 0; i < 8; i++)
839				I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
840		for (i = 0; i < 8; i++)
841			I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]);
842		break;
843	}
844
845	i915_restore_display(dev);
846
847	/* Interrupt state */
848	if (HAS_PCH_SPLIT(dev)) {
849		I915_WRITE(DEIER, dev_priv->saveDEIER);
850		I915_WRITE(DEIMR, dev_priv->saveDEIMR);
851		I915_WRITE(GTIER, dev_priv->saveGTIER);
852		I915_WRITE(GTIMR, dev_priv->saveGTIMR);
853		I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
854		I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
855	} else {
856		I915_WRITE (IER, dev_priv->saveIER);
857		I915_WRITE (IMR,  dev_priv->saveIMR);
858	}
859
860	/* Clock gating state */
861	intel_init_clock_gating(dev);
862
863	if (HAS_PCH_SPLIT(dev)) {
864		ironlake_enable_drps(dev);
865		intel_init_emon(dev);
866	}
867
868	/* Cache mode state */
869	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
870
871	/* Memory arbitration state */
872	I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
873
874	for (i = 0; i < 16; i++) {
875		I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
876		I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
877	}
878	for (i = 0; i < 3; i++)
879		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
880
881	/* I2C state */
882	intel_i2c_reset_gmbus(dev);
883
884	return 0;
885}
886