xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/i915/i915_suspend.c (revision b5c47949a45ac972130c38cf13dfd8afb1f09285)
1 /*	$NetBSD: i915_suspend.c,v 1.2 2018/08/27 04:58:23 riastradh Exp $	*/
2 
3 /*
4  *
5  * Copyright 2008 (c) Intel Corporation
6  *   Jesse Barnes <jbarnes@virtuousgeek.org>
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 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: i915_suspend.c,v 1.2 2018/08/27 04:58:23 riastradh Exp $");
31 
32 #include <drm/drmP.h>
33 #include <drm/i915_drm.h>
34 #include "intel_drv.h"
35 #include "i915_reg.h"
36 
37 static void i915_save_display(struct drm_device *dev)
38 {
39 	struct drm_i915_private *dev_priv = dev->dev_private;
40 
41 	/* Display arbitration control */
42 	if (INTEL_INFO(dev)->gen <= 4)
43 		dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
44 
45 	/* LVDS state */
46 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
47 		dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS);
48 	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
49 		dev_priv->regfile.saveLVDS = I915_READ(LVDS);
50 
51 	/* Panel power sequencer */
52 	if (HAS_PCH_SPLIT(dev)) {
53 		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
54 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
55 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
56 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
57 	} else if (!IS_VALLEYVIEW(dev)) {
58 		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
59 		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
60 		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
61 		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
62 	}
63 
64 	/* save FBC interval */
65 	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
66 		dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
67 }
68 
69 static void i915_restore_display(struct drm_device *dev)
70 {
71 	struct drm_i915_private *dev_priv = dev->dev_private;
72 	u32 mask = 0xffffffff;
73 
74 	/* Display arbitration */
75 	if (INTEL_INFO(dev)->gen <= 4)
76 		I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
77 
78 	mask = ~LVDS_PORT_EN;
79 
80 	/* LVDS state */
81 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
82 		I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask);
83 	else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
84 		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);
85 
86 	/* Panel power sequencer */
87 	if (HAS_PCH_SPLIT(dev)) {
88 		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
89 		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
90 		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
91 		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
92 	} else if (!IS_VALLEYVIEW(dev)) {
93 		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
94 		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
95 		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
96 		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
97 	}
98 
99 	/* only restore FBC info on the platform that supports FBC*/
100 	intel_fbc_disable(dev_priv);
101 
102 	/* restore FBC interval */
103 	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
104 		I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
105 
106 	i915_redisable_vga(dev);
107 }
108 
109 int i915_save_state(struct drm_device *dev)
110 {
111 	struct drm_i915_private *dev_priv = dev->dev_private;
112 	int i;
113 
114 	mutex_lock(&dev->struct_mutex);
115 
116 	i915_save_display(dev);
117 
118 	if (IS_GEN4(dev))
119 		pci_read_config_word(dev->pdev, GCDGMBUS,
120 				     &dev_priv->regfile.saveGCDGMBUS);
121 
122 	/* Cache mode state */
123 	if (INTEL_INFO(dev)->gen < 7)
124 		dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
125 
126 	/* Memory Arbitration state */
127 	dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
128 
129 	/* Scratch space */
130 	if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
131 		for (i = 0; i < 7; i++) {
132 			dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
133 			dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
134 		}
135 		for (i = 0; i < 3; i++)
136 			dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
137 	} else if (IS_GEN2(dev_priv)) {
138 		for (i = 0; i < 7; i++)
139 			dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
140 	} else if (HAS_GMCH_DISPLAY(dev_priv)) {
141 		for (i = 0; i < 16; i++) {
142 			dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i));
143 			dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i));
144 		}
145 		for (i = 0; i < 3; i++)
146 			dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i));
147 	}
148 
149 	mutex_unlock(&dev->struct_mutex);
150 
151 	return 0;
152 }
153 
154 int i915_restore_state(struct drm_device *dev)
155 {
156 	struct drm_i915_private *dev_priv = dev->dev_private;
157 	int i;
158 
159 	mutex_lock(&dev->struct_mutex);
160 
161 	i915_gem_restore_fences(dev);
162 
163 	if (IS_GEN4(dev))
164 		pci_write_config_word(dev->pdev, GCDGMBUS,
165 				      dev_priv->regfile.saveGCDGMBUS);
166 	i915_restore_display(dev);
167 
168 	/* Cache mode state */
169 	if (INTEL_INFO(dev)->gen < 7)
170 		I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 |
171 			   0xffff0000);
172 
173 	/* Memory arbitration state */
174 	I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000);
175 
176 	/* Scratch space */
177 	if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) {
178 		for (i = 0; i < 7; i++) {
179 			I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
180 			I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
181 		}
182 		for (i = 0; i < 3; i++)
183 			I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
184 	} else if (IS_GEN2(dev_priv)) {
185 		for (i = 0; i < 7; i++)
186 			I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
187 	} else if (HAS_GMCH_DISPLAY(dev_priv)) {
188 		for (i = 0; i < 16; i++) {
189 			I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]);
190 			I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]);
191 		}
192 		for (i = 0; i < 3; i++)
193 			I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]);
194 	}
195 
196 	mutex_unlock(&dev->struct_mutex);
197 
198 	intel_i2c_reset(dev);
199 
200 	return 0;
201 }
202