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 dev_priv
->regfile
.saveBLC_PWM_CTL
= I915_READ(BLC_PWM_PCH_CTL1
);
209 dev_priv
->regfile
.saveBLC_PWM_CTL2
= I915_READ(BLC_PWM_PCH_CTL2
);
210 dev_priv
->regfile
.saveBLC_CPU_PWM_CTL
= I915_READ(BLC_PWM_CPU_CTL
);
211 dev_priv
->regfile
.saveBLC_CPU_PWM_CTL2
= I915_READ(BLC_PWM_CPU_CTL2
);
212 if (HAS_PCH_IBX(dev
) || HAS_PCH_CPT(dev
))
213 dev_priv
->regfile
.saveLVDS
= I915_READ(PCH_LVDS
);
215 dev_priv
->regfile
.savePP_CONTROL
= I915_READ(PP_CONTROL
);
216 dev_priv
->regfile
.savePFIT_PGM_RATIOS
= I915_READ(PFIT_PGM_RATIOS
);
217 dev_priv
->regfile
.saveBLC_PWM_CTL
= I915_READ(BLC_PWM_CTL
);
218 dev_priv
->regfile
.saveBLC_HIST_CTL
= I915_READ(BLC_HIST_CTL
);
219 if (INTEL_INFO(dev
)->gen
>= 4)
220 dev_priv
->regfile
.saveBLC_PWM_CTL2
= I915_READ(BLC_PWM_CTL2
);
221 if (IS_MOBILE(dev
) && !IS_I830(dev
))
222 dev_priv
->regfile
.saveLVDS
= I915_READ(LVDS
);
225 if (!IS_I830(dev
) && !IS_845G(dev
) && !HAS_PCH_SPLIT(dev
))
226 dev_priv
->regfile
.savePFIT_CONTROL
= I915_READ(PFIT_CONTROL
);
228 if (HAS_PCH_SPLIT(dev
)) {
229 dev_priv
->regfile
.savePP_ON_DELAYS
= I915_READ(PCH_PP_ON_DELAYS
);
230 dev_priv
->regfile
.savePP_OFF_DELAYS
= I915_READ(PCH_PP_OFF_DELAYS
);
231 dev_priv
->regfile
.savePP_DIVISOR
= I915_READ(PCH_PP_DIVISOR
);
233 dev_priv
->regfile
.savePP_ON_DELAYS
= I915_READ(PP_ON_DELAYS
);
234 dev_priv
->regfile
.savePP_OFF_DELAYS
= I915_READ(PP_OFF_DELAYS
);
235 dev_priv
->regfile
.savePP_DIVISOR
= I915_READ(PP_DIVISOR
);
238 /* Only regfile.save FBC state on the platform that supports FBC */
239 if (I915_HAS_FBC(dev
)) {
240 if (HAS_PCH_SPLIT(dev
)) {
241 dev_priv
->regfile
.saveDPFC_CB_BASE
= I915_READ(ILK_DPFC_CB_BASE
);
242 } else if (IS_GM45(dev
)) {
243 dev_priv
->regfile
.saveDPFC_CB_BASE
= I915_READ(DPFC_CB_BASE
);
245 dev_priv
->regfile
.saveFBC_CFB_BASE
= I915_READ(FBC_CFB_BASE
);
246 dev_priv
->regfile
.saveFBC_LL_BASE
= I915_READ(FBC_LL_BASE
);
247 dev_priv
->regfile
.saveFBC_CONTROL2
= I915_READ(FBC_CONTROL2
);
248 dev_priv
->regfile
.saveFBC_CONTROL
= I915_READ(FBC_CONTROL
);
252 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
256 static void i915_restore_display(struct drm_device
*dev
)
258 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
259 u32 mask
= 0xffffffff;
261 /* Display arbitration */
262 if (INTEL_INFO(dev
)->gen
<= 4)
263 I915_WRITE(DSPARB
, dev_priv
->regfile
.saveDSPARB
);
265 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
266 i915_restore_display_reg(dev
);
269 if (INTEL_INFO(dev
)->gen
>= 4 && !HAS_PCH_SPLIT(dev
))
270 I915_WRITE(BLC_PWM_CTL2
, dev_priv
->regfile
.saveBLC_PWM_CTL2
);
272 if (drm_core_check_feature(dev
, DRIVER_MODESET
))
273 mask
= ~LVDS_PORT_EN
;
275 if (HAS_PCH_IBX(dev
) || HAS_PCH_CPT(dev
))
276 I915_WRITE(PCH_LVDS
, dev_priv
->regfile
.saveLVDS
& mask
);
277 else if (INTEL_INFO(dev
)->gen
<= 4 && IS_MOBILE(dev
) && !IS_I830(dev
))
278 I915_WRITE(LVDS
, dev_priv
->regfile
.saveLVDS
& mask
);
280 if (!IS_I830(dev
) && !IS_845G(dev
) && !HAS_PCH_SPLIT(dev
))
281 I915_WRITE(PFIT_CONTROL
, dev_priv
->regfile
.savePFIT_CONTROL
);
283 if (HAS_PCH_SPLIT(dev
)) {
284 I915_WRITE(BLC_PWM_PCH_CTL1
, dev_priv
->regfile
.saveBLC_PWM_CTL
);
285 I915_WRITE(BLC_PWM_PCH_CTL2
, dev_priv
->regfile
.saveBLC_PWM_CTL2
);
286 /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2;
287 * otherwise we get blank eDP screen after S3 on some machines
289 I915_WRITE(BLC_PWM_CPU_CTL2
, dev_priv
->regfile
.saveBLC_CPU_PWM_CTL2
);
290 I915_WRITE(BLC_PWM_CPU_CTL
, dev_priv
->regfile
.saveBLC_CPU_PWM_CTL
);
291 I915_WRITE(PCH_PP_ON_DELAYS
, dev_priv
->regfile
.savePP_ON_DELAYS
);
292 I915_WRITE(PCH_PP_OFF_DELAYS
, dev_priv
->regfile
.savePP_OFF_DELAYS
);
293 I915_WRITE(PCH_PP_DIVISOR
, dev_priv
->regfile
.savePP_DIVISOR
);
294 I915_WRITE(PCH_PP_CONTROL
, dev_priv
->regfile
.savePP_CONTROL
);
295 I915_WRITE(RSTDBYCTL
,
296 dev_priv
->regfile
.saveMCHBAR_RENDER_STANDBY
);
298 I915_WRITE(PFIT_PGM_RATIOS
, dev_priv
->regfile
.savePFIT_PGM_RATIOS
);
299 I915_WRITE(BLC_PWM_CTL
, dev_priv
->regfile
.saveBLC_PWM_CTL
);
300 I915_WRITE(BLC_HIST_CTL
, dev_priv
->regfile
.saveBLC_HIST_CTL
);
301 I915_WRITE(PP_ON_DELAYS
, dev_priv
->regfile
.savePP_ON_DELAYS
);
302 I915_WRITE(PP_OFF_DELAYS
, dev_priv
->regfile
.savePP_OFF_DELAYS
);
303 I915_WRITE(PP_DIVISOR
, dev_priv
->regfile
.savePP_DIVISOR
);
304 I915_WRITE(PP_CONTROL
, dev_priv
->regfile
.savePP_CONTROL
);
307 /* only restore FBC info on the platform that supports FBC*/
308 intel_disable_fbc(dev
);
309 if (I915_HAS_FBC(dev
)) {
310 if (HAS_PCH_SPLIT(dev
)) {
311 I915_WRITE(ILK_DPFC_CB_BASE
, dev_priv
->regfile
.saveDPFC_CB_BASE
);
312 } else if (IS_GM45(dev
)) {
313 I915_WRITE(DPFC_CB_BASE
, dev_priv
->regfile
.saveDPFC_CB_BASE
);
315 I915_WRITE(FBC_CFB_BASE
, dev_priv
->regfile
.saveFBC_CFB_BASE
);
316 I915_WRITE(FBC_LL_BASE
, dev_priv
->regfile
.saveFBC_LL_BASE
);
317 I915_WRITE(FBC_CONTROL2
, dev_priv
->regfile
.saveFBC_CONTROL2
);
318 I915_WRITE(FBC_CONTROL
, dev_priv
->regfile
.saveFBC_CONTROL
);
322 if (!drm_core_check_feature(dev
, DRIVER_MODESET
))
323 i915_restore_vga(dev
);
325 i915_redisable_vga(dev
);
328 int i915_save_state(struct drm_device
*dev
)
330 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
333 pci_read_config_byte(dev
->pdev
, LBB
, &dev_priv
->regfile
.saveLBB
);
335 mutex_lock(&dev
->struct_mutex
);
337 i915_save_display(dev
);
339 if (!drm_core_check_feature(dev
, DRIVER_MODESET
)) {
340 /* Interrupt state */
341 if (HAS_PCH_SPLIT(dev
)) {
342 dev_priv
->regfile
.saveDEIER
= I915_READ(DEIER
);
343 dev_priv
->regfile
.saveDEIMR
= I915_READ(DEIMR
);
344 dev_priv
->regfile
.saveGTIER
= I915_READ(GTIER
);
345 dev_priv
->regfile
.saveGTIMR
= I915_READ(GTIMR
);
346 dev_priv
->regfile
.saveFDI_RXA_IMR
= I915_READ(_FDI_RXA_IMR
);
347 dev_priv
->regfile
.saveFDI_RXB_IMR
= I915_READ(_FDI_RXB_IMR
);
348 dev_priv
->regfile
.saveMCHBAR_RENDER_STANDBY
=
349 I915_READ(RSTDBYCTL
);
350 dev_priv
->regfile
.savePCH_PORT_HOTPLUG
= I915_READ(PCH_PORT_HOTPLUG
);
352 dev_priv
->regfile
.saveIER
= I915_READ(IER
);
353 dev_priv
->regfile
.saveIMR
= I915_READ(IMR
);
357 intel_disable_gt_powersave(dev
);
359 /* Cache mode state */
360 dev_priv
->regfile
.saveCACHE_MODE_0
= I915_READ(CACHE_MODE_0
);
362 /* Memory Arbitration state */
363 dev_priv
->regfile
.saveMI_ARB_STATE
= I915_READ(MI_ARB_STATE
);
366 for (i
= 0; i
< 16; i
++) {
367 dev_priv
->regfile
.saveSWF0
[i
] = I915_READ(SWF00
+ (i
<< 2));
368 dev_priv
->regfile
.saveSWF1
[i
] = I915_READ(SWF10
+ (i
<< 2));
370 for (i
= 0; i
< 3; i
++)
371 dev_priv
->regfile
.saveSWF2
[i
] = I915_READ(SWF30
+ (i
<< 2));
373 mutex_unlock(&dev
->struct_mutex
);
378 int i915_restore_state(struct drm_device
*dev
)
380 struct drm_i915_private
*dev_priv
= dev
->dev_private
;
383 pci_write_config_byte(dev
->pdev
, LBB
, dev_priv
->regfile
.saveLBB
);
385 mutex_lock(&dev
->struct_mutex
);
387 i915_restore_display(dev
);
389 if (!drm_core_check_feature(dev
, DRIVER_MODESET
)) {
390 /* Interrupt state */
391 if (HAS_PCH_SPLIT(dev
)) {
392 I915_WRITE(DEIER
, dev_priv
->regfile
.saveDEIER
);
393 I915_WRITE(DEIMR
, dev_priv
->regfile
.saveDEIMR
);
394 I915_WRITE(GTIER
, dev_priv
->regfile
.saveGTIER
);
395 I915_WRITE(GTIMR
, dev_priv
->regfile
.saveGTIMR
);
396 I915_WRITE(_FDI_RXA_IMR
, dev_priv
->regfile
.saveFDI_RXA_IMR
);
397 I915_WRITE(_FDI_RXB_IMR
, dev_priv
->regfile
.saveFDI_RXB_IMR
);
398 I915_WRITE(PCH_PORT_HOTPLUG
, dev_priv
->regfile
.savePCH_PORT_HOTPLUG
);
400 I915_WRITE(IER
, dev_priv
->regfile
.saveIER
);
401 I915_WRITE(IMR
, dev_priv
->regfile
.saveIMR
);
405 /* Cache mode state */
406 I915_WRITE(CACHE_MODE_0
, dev_priv
->regfile
.saveCACHE_MODE_0
| 0xffff0000);
408 /* Memory arbitration state */
409 I915_WRITE(MI_ARB_STATE
, dev_priv
->regfile
.saveMI_ARB_STATE
| 0xffff0000);
411 for (i
= 0; i
< 16; i
++) {
412 I915_WRITE(SWF00
+ (i
<< 2), dev_priv
->regfile
.saveSWF0
[i
]);
413 I915_WRITE(SWF10
+ (i
<< 2), dev_priv
->regfile
.saveSWF1
[i
]);
415 for (i
= 0; i
< 3; i
++)
416 I915_WRITE(SWF30
+ (i
<< 2), dev_priv
->regfile
.saveSWF2
[i
]);
418 mutex_unlock(&dev
->struct_mutex
);
420 intel_i2c_reset(dev
);