xref: /openbsd-src/sys/dev/pci/drm/i915/i915_suspend.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: i915_suspend.c,v 1.7 2015/09/23 23:12:12 kettenis Exp $	*/
2 /*
3  *
4  * Copyright 2008 (c) Intel Corporation
5  *   Jesse Barnes <jbarnes@virtuousgeek.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <dev/pci/drm/drmP.h>
29 #include <dev/pci/drm/i915_drm.h>
30 #include "intel_drv.h"
31 #include "i915_reg.h"
32 
33 static u8 i915_read_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg)
34 {
35 	struct drm_i915_private *dev_priv = dev->dev_private;
36 
37 	I915_WRITE8(index_port, reg);
38 	return I915_READ8(data_port);
39 }
40 
41 static u8 i915_read_ar(struct drm_device *dev, u16 st01, u8 reg, u16 palette_enable)
42 {
43 	struct drm_i915_private *dev_priv = dev->dev_private;
44 
45 	I915_READ8(st01);
46 	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
47 	return I915_READ8(VGA_AR_DATA_READ);
48 }
49 
50 static void i915_write_ar(struct drm_device *dev, u16 st01, u8 reg, u8 val, u16 palette_enable)
51 {
52 	struct drm_i915_private *dev_priv = dev->dev_private;
53 
54 	I915_READ8(st01);
55 	I915_WRITE8(VGA_AR_INDEX, palette_enable | reg);
56 	I915_WRITE8(VGA_AR_DATA_WRITE, val);
57 }
58 
59 static void i915_write_indexed(struct drm_device *dev, u16 index_port, u16 data_port, u8 reg, u8 val)
60 {
61 	struct drm_i915_private *dev_priv = dev->dev_private;
62 
63 	I915_WRITE8(index_port, reg);
64 	I915_WRITE8(data_port, val);
65 }
66 
67 static void i915_save_vga(struct drm_device *dev)
68 {
69 	struct drm_i915_private *dev_priv = dev->dev_private;
70 	int i;
71 	u16 cr_index, cr_data, st01;
72 
73 	/* VGA state */
74 	dev_priv->regfile.saveVGA0 = I915_READ(VGA0);
75 	dev_priv->regfile.saveVGA1 = I915_READ(VGA1);
76 	dev_priv->regfile.saveVGA_PD = I915_READ(VGA_PD);
77 	dev_priv->regfile.saveVGACNTRL = I915_READ(i915_vgacntrl_reg(dev));
78 
79 	/* VGA color palette registers */
80 	dev_priv->regfile.saveDACMASK = I915_READ8(VGA_DACMASK);
81 
82 	/* MSR bits */
83 	dev_priv->regfile.saveMSR = I915_READ8(VGA_MSR_READ);
84 	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
85 		cr_index = VGA_CR_INDEX_CGA;
86 		cr_data = VGA_CR_DATA_CGA;
87 		st01 = VGA_ST01_CGA;
88 	} else {
89 		cr_index = VGA_CR_INDEX_MDA;
90 		cr_data = VGA_CR_DATA_MDA;
91 		st01 = VGA_ST01_MDA;
92 	}
93 
94 	/* CRT controller regs */
95 	i915_write_indexed(dev, cr_index, cr_data, 0x11,
96 			   i915_read_indexed(dev, cr_index, cr_data, 0x11) &
97 			   (~0x80));
98 	for (i = 0; i <= 0x24; i++)
99 		dev_priv->regfile.saveCR[i] =
100 			i915_read_indexed(dev, cr_index, cr_data, i);
101 	/* Make sure we don't turn off CR group 0 writes */
102 	dev_priv->regfile.saveCR[0x11] &= ~0x80;
103 
104 	/* Attribute controller registers */
105 	I915_READ8(st01);
106 	dev_priv->regfile.saveAR_INDEX = I915_READ8(VGA_AR_INDEX);
107 	for (i = 0; i <= 0x14; i++)
108 		dev_priv->regfile.saveAR[i] = i915_read_ar(dev, st01, i, 0);
109 	I915_READ8(st01);
110 	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX);
111 	I915_READ8(st01);
112 
113 	/* Graphics controller registers */
114 	for (i = 0; i < 9; i++)
115 		dev_priv->regfile.saveGR[i] =
116 			i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i);
117 
118 	dev_priv->regfile.saveGR[0x10] =
119 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10);
120 	dev_priv->regfile.saveGR[0x11] =
121 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11);
122 	dev_priv->regfile.saveGR[0x18] =
123 		i915_read_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18);
124 
125 	/* Sequencer registers */
126 	for (i = 0; i < 8; i++)
127 		dev_priv->regfile.saveSR[i] =
128 			i915_read_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i);
129 }
130 
131 static void i915_restore_vga(struct drm_device *dev)
132 {
133 	struct drm_i915_private *dev_priv = dev->dev_private;
134 	int i;
135 	u16 cr_index, cr_data, st01;
136 
137 	/* VGA state */
138 	I915_WRITE(i915_vgacntrl_reg(dev), dev_priv->regfile.saveVGACNTRL);
139 
140 	I915_WRITE(VGA0, dev_priv->regfile.saveVGA0);
141 	I915_WRITE(VGA1, dev_priv->regfile.saveVGA1);
142 	I915_WRITE(VGA_PD, dev_priv->regfile.saveVGA_PD);
143 	POSTING_READ(VGA_PD);
144 	udelay(150);
145 
146 	/* MSR bits */
147 	I915_WRITE8(VGA_MSR_WRITE, dev_priv->regfile.saveMSR);
148 	if (dev_priv->regfile.saveMSR & VGA_MSR_CGA_MODE) {
149 		cr_index = VGA_CR_INDEX_CGA;
150 		cr_data = VGA_CR_DATA_CGA;
151 		st01 = VGA_ST01_CGA;
152 	} else {
153 		cr_index = VGA_CR_INDEX_MDA;
154 		cr_data = VGA_CR_DATA_MDA;
155 		st01 = VGA_ST01_MDA;
156 	}
157 
158 	/* Sequencer registers, don't write SR07 */
159 	for (i = 0; i < 7; i++)
160 		i915_write_indexed(dev, VGA_SR_INDEX, VGA_SR_DATA, i,
161 				   dev_priv->regfile.saveSR[i]);
162 
163 	/* CRT controller regs */
164 	/* Enable CR group 0 writes */
165 	i915_write_indexed(dev, cr_index, cr_data, 0x11, dev_priv->regfile.saveCR[0x11]);
166 	for (i = 0; i <= 0x24; i++)
167 		i915_write_indexed(dev, cr_index, cr_data, i, dev_priv->regfile.saveCR[i]);
168 
169 	/* Graphics controller regs */
170 	for (i = 0; i < 9; i++)
171 		i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, i,
172 				   dev_priv->regfile.saveGR[i]);
173 
174 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x10,
175 			   dev_priv->regfile.saveGR[0x10]);
176 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x11,
177 			   dev_priv->regfile.saveGR[0x11]);
178 	i915_write_indexed(dev, VGA_GR_INDEX, VGA_GR_DATA, 0x18,
179 			   dev_priv->regfile.saveGR[0x18]);
180 
181 	/* Attribute controller registers */
182 	I915_READ8(st01); /* switch back to index mode */
183 	for (i = 0; i <= 0x14; i++)
184 		i915_write_ar(dev, st01, i, dev_priv->regfile.saveAR[i], 0);
185 	I915_READ8(st01); /* switch back to index mode */
186 	I915_WRITE8(VGA_AR_INDEX, dev_priv->regfile.saveAR_INDEX | 0x20);
187 	I915_READ8(st01);
188 
189 	/* VGA color palette registers */
190 	I915_WRITE8(VGA_DACMASK, dev_priv->regfile.saveDACMASK);
191 }
192 
193 static void i915_save_display(struct drm_device *dev)
194 {
195 	struct drm_i915_private *dev_priv = dev->dev_private;
196 
197 	/* Display arbitration control */
198 	if (INTEL_INFO(dev)->gen <= 4)
199 		dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
200 
201 	/* This is only meaningful in non-KMS mode */
202 	/* Don't regfile.save them in KMS mode */
203 #ifdef __linux__
204 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
205 		i915_save_display_reg(dev);
206 #endif
207 
208 	/* LVDS state */
209 	if (HAS_PCH_SPLIT(dev)) {
210 		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
211 		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
212 			dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
213 	} else if (IS_VALLEYVIEW(dev)) {
214 		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
215 		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
216 
217 		dev_priv->regfile.saveBLC_HIST_CTL =
218 			I915_READ(VLV_BLC_HIST_CTL(PIPE_A));
219 		dev_priv->regfile.saveBLC_HIST_CTL_B =
220 			I915_READ(VLV_BLC_HIST_CTL(PIPE_B));
221 	} else {
222 		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
223 		dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
224 		dev_priv->regfile.saveBLC_HIST_CTL = I915_READ(BLC_HIST_CTL);
225 		if (IS_MOBILE(dev) && !IS_I830(dev))
226 			dev_priv->regfile.saveLVDS = I915_READ(LVDS);
227 	}
228 
229 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
230 		dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
231 
232 	if (HAS_PCH_SPLIT(dev)) {
233 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
234 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
235 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
236 	} else {
237 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
238 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
239 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
240 	}
241 
242 	/* Only regfile.save FBC state on the platform that supports FBC */
243 	if (HAS_FBC(dev)) {
244 		if (HAS_PCH_SPLIT(dev)) {
245 			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
246 		} else if (IS_GM45(dev)) {
247 			dev_priv->regfile.saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
248 		} else {
249 			dev_priv->regfile.saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
250 			dev_priv->regfile.saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
251 			dev_priv->regfile.saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
252 			dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
253 		}
254 	}
255 
256 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
257 		i915_save_vga(dev);
258 }
259 
260 static void i915_restore_display(struct drm_device *dev)
261 {
262 	struct drm_i915_private *dev_priv = dev->dev_private;
263 	u32 mask = 0xffffffff;
264 
265 	/* Display arbitration */
266 	if (INTEL_INFO(dev)->gen <= 4)
267 		I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
268 
269 #ifdef __linux__
270 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
271 		i915_restore_display_reg(dev);
272 #endif
273 
274 	if (drm_core_check_feature(dev, DRIVER_MODESET))
275 		mask = ~LVDS_PORT_EN;
276 
277 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
278 		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask);
279 	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
280 		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
281 
282 	if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
283 		I915_WRITE(PFIT_CONTROL, dev_priv->regfile.savePFIT_CONTROL);
284 
285 	if (HAS_PCH_SPLIT(dev)) {
286 		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
287 		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
288 		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
289 		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
290 		I915_WRITE(RSTDBYCTL,
291 			   dev_priv->regfile.saveMCHBAR_RENDER_STANDBY);
292 	} else if (IS_VALLEYVIEW(dev)) {
293 		I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A),
294 			   dev_priv->regfile.saveBLC_HIST_CTL);
295 		I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B),
296 			   dev_priv->regfile.saveBLC_HIST_CTL);
297 	} else {
298 		I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS);
299 		I915_WRITE(BLC_HIST_CTL, dev_priv->regfile.saveBLC_HIST_CTL);
300 		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
301 		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
302 		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
303 		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
304 	}
305 
306 	/* only restore FBC info on the platform that supports FBC*/
307 	intel_disable_fbc(dev);
308 	if (HAS_FBC(dev)) {
309 		if (HAS_PCH_SPLIT(dev)) {
310 			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
311 		} else if (IS_GM45(dev)) {
312 			I915_WRITE(DPFC_CB_BASE, dev_priv->regfile.saveDPFC_CB_BASE);
313 		} else {
314 			I915_WRITE(FBC_CFB_BASE, dev_priv->regfile.saveFBC_CFB_BASE);
315 			I915_WRITE(FBC_LL_BASE, dev_priv->regfile.saveFBC_LL_BASE);
316 			I915_WRITE(FBC_CONTROL2, dev_priv->regfile.saveFBC_CONTROL2);
317 			I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
318 		}
319 	}
320 
321 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
322 		i915_restore_vga(dev);
323 	else
324 		i915_redisable_vga(dev);
325 }
326 
327 int i915_save_state(struct drm_device *dev)
328 {
329 	struct drm_i915_private *dev_priv = dev->dev_private;
330 	int i;
331 
332 	if (INTEL_INFO(dev)->gen <= 4)
333 		pci_read_config_byte(dev->pdev, LBB,
334 				     &dev_priv->regfile.saveLBB);
335 
336 	mutex_lock(&dev->struct_mutex);
337 
338 	i915_save_display(dev);
339 
340 	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
341 		/* Interrupt state */
342 		if (HAS_PCH_SPLIT(dev)) {
343 			dev_priv->regfile.saveDEIER = I915_READ(DEIER);
344 			dev_priv->regfile.saveDEIMR = I915_READ(DEIMR);
345 			dev_priv->regfile.saveGTIER = I915_READ(GTIER);
346 			dev_priv->regfile.saveGTIMR = I915_READ(GTIMR);
347 			dev_priv->regfile.saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
348 			dev_priv->regfile.saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
349 			dev_priv->regfile.saveMCHBAR_RENDER_STANDBY =
350 				I915_READ(RSTDBYCTL);
351 			dev_priv->regfile.savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG);
352 		} else {
353 			dev_priv->regfile.saveIER = I915_READ(IER);
354 			dev_priv->regfile.saveIMR = I915_READ(IMR);
355 		}
356 	}
357 
358 	intel_disable_gt_powersave(dev);
359 
360 	/* Cache mode state */
361 	if (INTEL_INFO(dev)->gen < 7)
362 		dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
363 
364 	/* Memory Arbitration state */
365 	dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
366 
367 	/* Scratch space */
368 	for (i = 0; i < 16; i++) {
369 		dev_priv->regfile.saveSWF0[i] = I915_READ(SWF00 + (i << 2));
370 		dev_priv->regfile.saveSWF1[i] = I915_READ(SWF10 + (i << 2));
371 	}
372 	for (i = 0; i < 3; i++)
373 		dev_priv->regfile.saveSWF2[i] = I915_READ(SWF30 + (i << 2));
374 
375 	mutex_unlock(&dev->struct_mutex);
376 
377 	return 0;
378 }
379 
380 int i915_restore_state(struct drm_device *dev)
381 {
382 	struct drm_i915_private *dev_priv = dev->dev_private;
383 	int i;
384 
385 	if (INTEL_INFO(dev)->gen <= 4)
386 		pci_write_config_byte(dev->pdev, LBB,
387 				      dev_priv->regfile.saveLBB);
388 
389 	mutex_lock(&dev->struct_mutex);
390 
391 	i915_gem_restore_fences(dev);
392 	i915_restore_display(dev);
393 
394 	if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
395 		/* Interrupt state */
396 		if (HAS_PCH_SPLIT(dev)) {
397 			I915_WRITE(DEIER, dev_priv->regfile.saveDEIER);
398 			I915_WRITE(DEIMR, dev_priv->regfile.saveDEIMR);
399 			I915_WRITE(GTIER, dev_priv->regfile.saveGTIER);
400 			I915_WRITE(GTIMR, dev_priv->regfile.saveGTIMR);
401 			I915_WRITE(_FDI_RXA_IMR, dev_priv->regfile.saveFDI_RXA_IMR);
402 			I915_WRITE(_FDI_RXB_IMR, dev_priv->regfile.saveFDI_RXB_IMR);
403 			I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->regfile.savePCH_PORT_HOTPLUG);
404 		} else {
405 			I915_WRITE(IER, dev_priv->regfile.saveIER);
406 			I915_WRITE(IMR, dev_priv->regfile.saveIMR);
407 		}
408 	}
409 
410 	/* Cache mode state */
411 	if (INTEL_INFO(dev)->gen < 7)
412 		I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 |
413 			   0xffff0000);
414 
415 	/* Memory arbitration state */
416 	I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
417 
418 	for (i = 0; i < 16; i++) {
419 		I915_WRITE(SWF00 + (i << 2), dev_priv->regfile.saveSWF0[i]);
420 		I915_WRITE(SWF10 + (i << 2), dev_priv->regfile.saveSWF1[i]);
421 	}
422 	for (i = 0; i < 3; i++)
423 		I915_WRITE(SWF30 + (i << 2), dev_priv->regfile.saveSWF2[i]);
424 
425 	mutex_unlock(&dev->struct_mutex);
426 
427 	intel_i2c_reset(dev);
428 
429 	return 0;
430 }
431