3 * Copyright 2008 (c) Intel Corporation
4 * Jesse Barnes <jbarnes@virtuousgeek.org>
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
28 #include <drm/i915_drm.h>
29 #include "intel_drv.h"
32 static u8
i915_read_indexed(struct drm_device
*dev
, u16 index_port
, u16 data_port
, u8 reg
)
34 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
36 I915_WRITE8(index_port
, reg
);
37 return I915_READ8(data_port
);
40 static u8
i915_read_ar(struct drm_device
*dev
, u16 st01
, u8 reg
, u16 palette_enable
)
42 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
45 I915_WRITE8(VGA_AR_INDEX
, palette_enable
| reg
);
46 return I915_READ8(VGA_AR_DATA_READ
);
49 static void i915_write_ar(struct drm_device
*dev
, u16 st01
, u8 reg
, u8 val
, u16 palette_enable
)
51 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
54 I915_WRITE8(VGA_AR_INDEX
, palette_enable
| reg
);
55 I915_WRITE8(VGA_AR_DATA_WRITE
, val
);
58 static void i915_write_indexed(struct drm_device
*dev
, u16 index_port
, u16 data_port
, u8 reg
, u8 val
)
60 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
62 I915_WRITE8(index_port
, reg
);
63 I915_WRITE8(data_port
, val
);
66 static void i915_save_vga(struct drm_device
*dev
)
68 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
70 u16 cr_index
, cr_data
, st01
;
73 dev_priv
->regfile
.saveVGA0
= I915_READ(VGA0
);
74 dev_priv
->regfile
.saveVGA1
= I915_READ(VGA1
);
75 dev_priv
->regfile
.saveVGA_PD
= I915_READ(VGA_PD
);
76 dev_priv
->regfile
.saveVGACNTRL
= I915_READ(i915_vgacntrl_reg(dev
));
78 /* VGA color palette registers */
79 dev_priv
->regfile
.saveDACMASK
= I915_READ8(VGA_DACMASK
);
82 dev_priv
->regfile
.saveMSR
= I915_READ8(VGA_MSR_READ
);
83 if (dev_priv
->regfile
.saveMSR
& VGA_MSR_CGA_MODE
) {
84 cr_index
= VGA_CR_INDEX_CGA
;
85 cr_data
= VGA_CR_DATA_CGA
;
88 cr_index
= VGA_CR_INDEX_MDA
;
89 cr_data
= VGA_CR_DATA_MDA
;
93 /* CRT controller regs */
94 i915_write_indexed(dev
, cr_index
, cr_data
, 0x11,
95 i915_read_indexed(dev
, cr_index
, cr_data
, 0x11) &
97 for (i
= 0; i
<= 0x24; i
++)
98 dev_priv
->regfile
.saveCR
[i
] =
99 i915_read_indexed(dev
, cr_index
, cr_data
, i
);
100 /* Make sure we don't turn off CR group 0 writes */
101 dev_priv
->regfile
.saveCR
[0x11] &= ~0x80;
103 /* Attribute controller registers */
105 dev_priv
->regfile
.saveAR_INDEX
= I915_READ8(VGA_AR_INDEX
);
106 for (i
= 0; i
<= 0x14; i
++)
107 dev_priv
->regfile
.saveAR
[i
] = i915_read_ar(dev
, st01
, i
, 0);
109 I915_WRITE8(VGA_AR_INDEX
, dev_priv
->regfile
.saveAR_INDEX
);
112 /* Graphics controller registers */
113 for (i
= 0; i
< 9; i
++)
114 dev_priv
->regfile
.saveGR
[i
] =
115 i915_read_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, i
);
117 dev_priv
->regfile
.saveGR
[0x10] =
118 i915_read_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x10);
119 dev_priv
->regfile
.saveGR
[0x11] =
120 i915_read_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x11);
121 dev_priv
->regfile
.saveGR
[0x18] =
122 i915_read_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x18);
124 /* Sequencer registers */
125 for (i
= 0; i
< 8; i
++)
126 dev_priv
->regfile
.saveSR
[i
] =
127 i915_read_indexed(dev
, VGA_SR_INDEX
, VGA_SR_DATA
, i
);
130 static void i915_restore_vga(struct drm_device
*dev
)
132 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
134 u16 cr_index
, cr_data
, st01
;
137 I915_WRITE(i915_vgacntrl_reg(dev
), dev_priv
->regfile
.saveVGACNTRL
);
139 I915_WRITE(VGA0
, dev_priv
->regfile
.saveVGA0
);
140 I915_WRITE(VGA1
, dev_priv
->regfile
.saveVGA1
);
141 I915_WRITE(VGA_PD
, dev_priv
->regfile
.saveVGA_PD
);
142 POSTING_READ(VGA_PD
);
146 I915_WRITE8(VGA_MSR_WRITE
, dev_priv
->regfile
.saveMSR
);
147 if (dev_priv
->regfile
.saveMSR
& VGA_MSR_CGA_MODE
) {
148 cr_index
= VGA_CR_INDEX_CGA
;
149 cr_data
= VGA_CR_DATA_CGA
;
152 cr_index
= VGA_CR_INDEX_MDA
;
153 cr_data
= VGA_CR_DATA_MDA
;
157 /* Sequencer registers, don't write SR07 */
158 for (i
= 0; i
< 7; i
++)
159 i915_write_indexed(dev
, VGA_SR_INDEX
, VGA_SR_DATA
, i
,
160 dev_priv
->regfile
.saveSR
[i
]);
162 /* CRT controller regs */
163 /* Enable CR group 0 writes */
164 i915_write_indexed(dev
, cr_index
, cr_data
, 0x11, dev_priv
->regfile
.saveCR
[0x11]);
165 for (i
= 0; i
<= 0x24; i
++)
166 i915_write_indexed(dev
, cr_index
, cr_data
, i
, dev_priv
->regfile
.saveCR
[i
]);
168 /* Graphics controller regs */
169 for (i
= 0; i
< 9; i
++)
170 i915_write_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, i
,
171 dev_priv
->regfile
.saveGR
[i
]);
173 i915_write_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x10,
174 dev_priv
->regfile
.saveGR
[0x10]);
175 i915_write_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x11,
176 dev_priv
->regfile
.saveGR
[0x11]);
177 i915_write_indexed(dev
, VGA_GR_INDEX
, VGA_GR_DATA
, 0x18,
178 dev_priv
->regfile
.saveGR
[0x18]);
180 /* Attribute controller registers */
181 I915_READ8(st01
); /* switch back to index mode */
182 for (i
= 0; i
<= 0x14; i
++)
183 i915_write_ar(dev
, st01
, i
, dev_priv
->regfile
.saveAR
[i
], 0);
184 I915_READ8(st01
); /* switch back to index mode */
185 I915_WRITE8(VGA_AR_INDEX
, dev_priv
->regfile
.saveAR_INDEX
| 0x20);
188 /* VGA color palette registers */
189 I915_WRITE8(VGA_DACMASK
, dev_priv
->regfile
.saveDACMASK
);
192 static void i915_save_display(struct drm_device
*dev
)
194 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
196 /* Display arbitration control */
197 if (INTEL_INFO(dev
)->gen
<= 4)
198 dev_priv
->regfile
.saveDSPARB
= I915_READ(DSPARB
);
200 /* This is only meaningful in non-KMS mode */
201 /* Don't regfile.save them in KMS mode */
202 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
203 i915_save_display_reg(dev
);
206 if (HAS_PCH_SPLIT(dev
)) {
207 dev_priv
->regfile
.savePP_CONTROL
= I915_READ(PCH_PP_CONTROL
);
208 if (HAS_PCH_IBX(dev
) || HAS_PCH_CPT(dev
))
209 dev_priv
->regfile
.saveLVDS
= I915_READ(PCH_LVDS
);
210 } else if (IS_VALLEYVIEW(dev
)) {
211 dev_priv
->regfile
.savePP_CONTROL
= I915_READ(PP_CONTROL
);
212 dev_priv
->regfile
.savePFIT_PGM_RATIOS
= I915_READ(PFIT_PGM_RATIOS
);
214 dev_priv
->regfile
.saveBLC_HIST_CTL
=
215 I915_READ(VLV_BLC_HIST_CTL(PIPE_A
));
216 dev_priv
->regfile
.saveBLC_HIST_CTL_B
=
217 I915_READ(VLV_BLC_HIST_CTL(PIPE_B
));
219 dev_priv
->regfile
.savePP_CONTROL
= I915_READ(PP_CONTROL
);
220 dev_priv
->regfile
.savePFIT_PGM_RATIOS
= I915_READ(PFIT_PGM_RATIOS
);
221 dev_priv
->regfile
.saveBLC_HIST_CTL
= I915_READ(BLC_HIST_CTL
);
222 if (IS_MOBILE(dev
) && !IS_I830(dev
))
223 dev_priv
->regfile
.saveLVDS
= I915_READ(LVDS
);
226 if (!IS_I830(dev
) && !IS_845G(dev
) && !HAS_PCH_SPLIT(dev
))
227 dev_priv
->regfile
.savePFIT_CONTROL
= I915_READ(PFIT_CONTROL
);
229 if (HAS_PCH_SPLIT(dev
)) {
230 dev_priv
->regfile
.savePP_ON_DELAYS
= I915_READ(PCH_PP_ON_DELAYS
);
231 dev_priv
->regfile
.savePP_OFF_DELAYS
= I915_READ(PCH_PP_OFF_DELAYS
);
232 dev_priv
->regfile
.savePP_DIVISOR
= I915_READ(PCH_PP_DIVISOR
);
234 dev_priv
->regfile
.savePP_ON_DELAYS
= I915_READ(PP_ON_DELAYS
);
235 dev_priv
->regfile
.savePP_OFF_DELAYS
= I915_READ(PP_OFF_DELAYS
);
236 dev_priv
->regfile
.savePP_DIVISOR
= I915_READ(PP_DIVISOR
);
239 /* save FBC interval */
240 if (HAS_FBC(dev
) && INTEL_INFO(dev
)->gen
<= 4 && !IS_G4X(dev
))
241 dev_priv
->regfile
.saveFBC_CONTROL
= I915_READ(FBC_CONTROL
);
243 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
247 static void i915_restore_display(struct drm_device
*dev
)
249 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
250 u32 mask
= 0xffffffff;
252 /* Display arbitration */
253 if (INTEL_INFO(dev
)->gen
<= 4)
254 I915_WRITE(DSPARB
, dev_priv
->regfile
.saveDSPARB
);
256 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
257 i915_restore_display_reg(dev
);
259 if (drm_core_check_feature(dev
, DRIVER_MODESET
))
260 mask
= ~LVDS_PORT_EN
;
262 if (HAS_PCH_IBX(dev
) || HAS_PCH_CPT(dev
))
263 I915_WRITE(PCH_LVDS
, dev_priv
->regfile
.saveLVDS
& mask
);
264 else if (INTEL_INFO(dev
)->gen
<= 4 && IS_MOBILE(dev
) && !IS_I830(dev
))
265 I915_WRITE(LVDS
, dev_priv
->regfile
.saveLVDS
& mask
);
267 if (!IS_I830(dev
) && !IS_845G(dev
) && !HAS_PCH_SPLIT(dev
))
268 I915_WRITE(PFIT_CONTROL
, dev_priv
->regfile
.savePFIT_CONTROL
);
270 if (HAS_PCH_SPLIT(dev
)) {
271 I915_WRITE(PCH_PP_ON_DELAYS
, dev_priv
->regfile
.savePP_ON_DELAYS
);
272 I915_WRITE(PCH_PP_OFF_DELAYS
, dev_priv
->regfile
.savePP_OFF_DELAYS
);
273 I915_WRITE(PCH_PP_DIVISOR
, dev_priv
->regfile
.savePP_DIVISOR
);
274 I915_WRITE(PCH_PP_CONTROL
, dev_priv
->regfile
.savePP_CONTROL
);
275 I915_WRITE(RSTDBYCTL
,
276 dev_priv
->regfile
.saveMCHBAR_RENDER_STANDBY
);
277 } else if (IS_VALLEYVIEW(dev
)) {
278 I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A
),
279 dev_priv
->regfile
.saveBLC_HIST_CTL
);
280 I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B
),
281 dev_priv
->regfile
.saveBLC_HIST_CTL
);
283 I915_WRITE(PFIT_PGM_RATIOS
, dev_priv
->regfile
.savePFIT_PGM_RATIOS
);
284 I915_WRITE(BLC_HIST_CTL
, dev_priv
->regfile
.saveBLC_HIST_CTL
);
285 I915_WRITE(PP_ON_DELAYS
, dev_priv
->regfile
.savePP_ON_DELAYS
);
286 I915_WRITE(PP_OFF_DELAYS
, dev_priv
->regfile
.savePP_OFF_DELAYS
);
287 I915_WRITE(PP_DIVISOR
, dev_priv
->regfile
.savePP_DIVISOR
);
288 I915_WRITE(PP_CONTROL
, dev_priv
->regfile
.savePP_CONTROL
);
291 /* only restore FBC info on the platform that supports FBC*/
292 intel_disable_fbc(dev
);
294 /* restore FBC interval */
295 if (HAS_FBC(dev
) && INTEL_INFO(dev
)->gen
<= 4 && !IS_G4X(dev
))
296 I915_WRITE(FBC_CONTROL
, dev_priv
->regfile
.saveFBC_CONTROL
);
298 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
299 i915_restore_vga(dev
);
301 i915_redisable_vga(dev
);
304 int i915_save_state(struct drm_device
*dev
)
306 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
309 mutex_lock(&dev
->struct_mutex
);
311 i915_save_display(dev
);
313 if (!drm_core_check_feature(dev
, DRIVER_MODESET
)) {
314 /* Interrupt state */
315 if (HAS_PCH_SPLIT(dev
)) {
316 dev_priv
->regfile
.saveDEIER
= I915_READ(DEIER
);
317 dev_priv
->regfile
.saveDEIMR
= I915_READ(DEIMR
);
318 dev_priv
->regfile
.saveGTIER
= I915_READ(GTIER
);
319 dev_priv
->regfile
.saveGTIMR
= I915_READ(GTIMR
);
320 dev_priv
->regfile
.saveFDI_RXA_IMR
= I915_READ(_FDI_RXA_IMR
);
321 dev_priv
->regfile
.saveFDI_RXB_IMR
= I915_READ(_FDI_RXB_IMR
);
322 dev_priv
->regfile
.saveMCHBAR_RENDER_STANDBY
=
323 I915_READ(RSTDBYCTL
);
324 dev_priv
->regfile
.savePCH_PORT_HOTPLUG
= I915_READ(PCH_PORT_HOTPLUG
);
326 dev_priv
->regfile
.saveIER
= I915_READ(IER
);
327 dev_priv
->regfile
.saveIMR
= I915_READ(IMR
);
331 /* Cache mode state */
332 if (INTEL_INFO(dev
)->gen
< 7)
333 dev_priv
->regfile
.saveCACHE_MODE_0
= I915_READ(CACHE_MODE_0
);
335 /* Memory Arbitration state */
336 dev_priv
->regfile
.saveMI_ARB_STATE
= I915_READ(MI_ARB_STATE
);
339 for (i
= 0; i
< 16; i
++) {
340 dev_priv
->regfile
.saveSWF0
[i
] = I915_READ(SWF00
+ (i
<< 2));
341 dev_priv
->regfile
.saveSWF1
[i
] = I915_READ(SWF10
+ (i
<< 2));
343 for (i
= 0; i
< 3; i
++)
344 dev_priv
->regfile
.saveSWF2
[i
] = I915_READ(SWF30
+ (i
<< 2));
346 mutex_unlock(&dev
->struct_mutex
);
351 int i915_restore_state(struct drm_device
*dev
)
353 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
356 mutex_lock(&dev
->struct_mutex
);
358 i915_gem_restore_fences(dev
);
359 i915_restore_display(dev
);
361 if (!drm_core_check_feature(dev
, DRIVER_MODESET
)) {
362 /* Interrupt state */
363 if (HAS_PCH_SPLIT(dev
)) {
364 I915_WRITE(DEIER
, dev_priv
->regfile
.saveDEIER
);
365 I915_WRITE(DEIMR
, dev_priv
->regfile
.saveDEIMR
);
366 I915_WRITE(GTIER
, dev_priv
->regfile
.saveGTIER
);
367 I915_WRITE(GTIMR
, dev_priv
->regfile
.saveGTIMR
);
368 I915_WRITE(_FDI_RXA_IMR
, dev_priv
->regfile
.saveFDI_RXA_IMR
);
369 I915_WRITE(_FDI_RXB_IMR
, dev_priv
->regfile
.saveFDI_RXB_IMR
);
370 I915_WRITE(PCH_PORT_HOTPLUG
, dev_priv
->regfile
.savePCH_PORT_HOTPLUG
);
372 I915_WRITE(IER
, dev_priv
->regfile
.saveIER
);
373 I915_WRITE(IMR
, dev_priv
->regfile
.saveIMR
);
377 /* Cache mode state */
378 if (INTEL_INFO(dev
)->gen
< 7)
379 I915_WRITE(CACHE_MODE_0
, dev_priv
->regfile
.saveCACHE_MODE_0
|
382 /* Memory arbitration state */
383 I915_WRITE(MI_ARB_STATE
, dev_priv
->regfile
.saveMI_ARB_STATE
| 0xffff0000);
385 for (i
= 0; i
< 16; i
++) {
386 I915_WRITE(SWF00
+ (i
<< 2), dev_priv
->regfile
.saveSWF0
[i
]);
387 I915_WRITE(SWF10
+ (i
<< 2), dev_priv
->regfile
.saveSWF1
[i
]);
389 for (i
= 0; i
< 3; i
++)
390 I915_WRITE(SWF30
+ (i
<< 2), dev_priv
->regfile
.saveSWF2
[i
]);
392 mutex_unlock(&dev
->struct_mutex
);
394 intel_i2c_reset(dev
);