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