i915_suspend.c revision 1.1.1.2.28.1 1 /* $NetBSD: i915_suspend.c,v 1.1.1.2.28.1 2018/09/06 06:56:17 pgoyette Exp $ */
2
3 /*
4 *
5 * Copyright 2008 (c) Intel Corporation
6 * Jesse Barnes <jbarnes (at) 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.1.1.2.28.1 2018/09/06 06:56:17 pgoyette 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