Commit | Line | Data |
---|---|---|
317c35d1 JB |
1 | /* |
2 | * | |
3 | * Copyright 2008 (c) Intel Corporation | |
4 | * Jesse Barnes <jbarnes@virtuousgeek.org> | |
5 | * | |
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: | |
13 | * | |
14 | * The above copyright notice and this permission notice (including the | |
15 | * next paragraph) shall be included in all copies or substantial portions | |
16 | * of the Software. | |
17 | * | |
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. | |
25 | */ | |
26 | ||
760285e7 DH |
27 | #include <drm/drmP.h> |
28 | #include <drm/i915_drm.h> | |
f0217c42 | 29 | #include "intel_drv.h" |
5e5b7fa2 | 30 | #include "i915_reg.h" |
317c35d1 | 31 | |
d70bed19 | 32 | static void i915_save_display(struct drm_device *dev) |
fccdaba4 ZY |
33 | { |
34 | struct drm_i915_private *dev_priv = dev->dev_private; | |
fccdaba4 ZY |
35 | |
36 | /* Display arbitration control */ | |
8de0add7 PZ |
37 | if (INTEL_INFO(dev)->gen <= 4) |
38 | dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); | |
fccdaba4 | 39 | |
317c35d1 | 40 | /* LVDS state */ |
1c5bb42c JN |
41 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
42 | dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS); | |
43 | else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev)) | |
44 | dev_priv->regfile.saveLVDS = I915_READ(LVDS); | |
42048781 | 45 | |
1c5bb42c | 46 | /* Panel power sequencer */ |
90eb77ba | 47 | if (HAS_PCH_SPLIT(dev)) { |
1c5bb42c | 48 | dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL); |
f4c956ad DV |
49 | dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS); |
50 | dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS); | |
51 | dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR); | |
e1ea0754 | 52 | } else if (INTEL_INFO(dev)->gen <= 4) { |
1c5bb42c | 53 | dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); |
f4c956ad DV |
54 | dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); |
55 | dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); | |
56 | dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR); | |
42048781 | 57 | } |
317c35d1 | 58 | |
768cf7f4 VS |
59 | /* save FBC interval */ |
60 | if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) | |
61 | dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); | |
317c35d1 JB |
62 | } |
63 | ||
d70bed19 | 64 | static void i915_restore_display(struct drm_device *dev) |
317c35d1 JB |
65 | { |
66 | struct drm_i915_private *dev_priv = dev->dev_private; | |
2ec90668 | 67 | u32 mask = 0xffffffff; |
461cba2d | 68 | |
881ee988 | 69 | /* Display arbitration */ |
8de0add7 PZ |
70 | if (INTEL_INFO(dev)->gen <= 4) |
71 | I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB); | |
317c35d1 | 72 | |
8634bd4a | 73 | mask = ~LVDS_PORT_EN; |
2ec90668 | 74 | |
1c5bb42c | 75 | /* LVDS state */ |
4deb88a6 | 76 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) |
2ec90668 | 77 | I915_WRITE(PCH_LVDS, dev_priv->regfile.saveLVDS & mask); |
4deb88a6 | 78 | else if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev)) |
2ec90668 | 79 | I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask); |
42048781 | 80 | |
1c5bb42c | 81 | /* Panel power sequencer */ |
90eb77ba | 82 | if (HAS_PCH_SPLIT(dev)) { |
f4c956ad DV |
83 | I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); |
84 | I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); | |
85 | I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); | |
86 | I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL); | |
e1ea0754 | 87 | } else if (INTEL_INFO(dev)->gen <= 4) { |
f4c956ad DV |
88 | I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS); |
89 | I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS); | |
90 | I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR); | |
91 | I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL); | |
42048781 | 92 | } |
317c35d1 | 93 | |
a2c459ee | 94 | /* only restore FBC info on the platform that supports FBC*/ |
c937ab3e | 95 | intel_fbc_global_disable(dev_priv); |
768cf7f4 VS |
96 | |
97 | /* restore FBC interval */ | |
98 | if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) | |
99 | I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); | |
a65e827d | 100 | |
8634bd4a | 101 | i915_redisable_vga(dev); |
1341d655 BG |
102 | } |
103 | ||
104 | int i915_save_state(struct drm_device *dev) | |
105 | { | |
106 | struct drm_i915_private *dev_priv = dev->dev_private; | |
107 | int i; | |
108 | ||
d70bed19 KP |
109 | mutex_lock(&dev->struct_mutex); |
110 | ||
1341d655 BG |
111 | i915_save_display(dev); |
112 | ||
9f49c376 JB |
113 | if (IS_GEN4(dev)) |
114 | pci_read_config_word(dev->pdev, GCDGMBUS, | |
115 | &dev_priv->regfile.saveGCDGMBUS); | |
116 | ||
1341d655 | 117 | /* Cache mode state */ |
e8cde23b JB |
118 | if (INTEL_INFO(dev)->gen < 7) |
119 | dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); | |
1341d655 BG |
120 | |
121 | /* Memory Arbitration state */ | |
f4c956ad | 122 | dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); |
1341d655 BG |
123 | |
124 | /* Scratch space */ | |
85fa792b VS |
125 | if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) { |
126 | for (i = 0; i < 7; i++) { | |
127 | dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i)); | |
128 | dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i)); | |
129 | } | |
130 | for (i = 0; i < 3; i++) | |
131 | dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i)); | |
132 | } else if (IS_GEN2(dev_priv)) { | |
133 | for (i = 0; i < 7; i++) | |
134 | dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i)); | |
135 | } else if (HAS_GMCH_DISPLAY(dev_priv)) { | |
136 | for (i = 0; i < 16; i++) { | |
137 | dev_priv->regfile.saveSWF0[i] = I915_READ(SWF0(i)); | |
138 | dev_priv->regfile.saveSWF1[i] = I915_READ(SWF1(i)); | |
139 | } | |
140 | for (i = 0; i < 3; i++) | |
141 | dev_priv->regfile.saveSWF3[i] = I915_READ(SWF3(i)); | |
1341d655 | 142 | } |
1341d655 | 143 | |
d70bed19 KP |
144 | mutex_unlock(&dev->struct_mutex); |
145 | ||
1341d655 BG |
146 | return 0; |
147 | } | |
148 | ||
149 | int i915_restore_state(struct drm_device *dev) | |
150 | { | |
151 | struct drm_i915_private *dev_priv = dev->dev_private; | |
152 | int i; | |
153 | ||
d70bed19 KP |
154 | mutex_lock(&dev->struct_mutex); |
155 | ||
19b2dbde | 156 | i915_gem_restore_fences(dev); |
9f49c376 JB |
157 | |
158 | if (IS_GEN4(dev)) | |
159 | pci_write_config_word(dev->pdev, GCDGMBUS, | |
160 | dev_priv->regfile.saveGCDGMBUS); | |
1341d655 BG |
161 | i915_restore_display(dev); |
162 | ||
317c35d1 | 163 | /* Cache mode state */ |
e8cde23b JB |
164 | if (INTEL_INFO(dev)->gen < 7) |
165 | I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | | |
166 | 0xffff0000); | |
317c35d1 JB |
167 | |
168 | /* Memory arbitration state */ | |
f4c956ad | 169 | I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000); |
317c35d1 | 170 | |
85fa792b VS |
171 | /* Scratch space */ |
172 | if (IS_GEN2(dev_priv) && IS_MOBILE(dev_priv)) { | |
173 | for (i = 0; i < 7; i++) { | |
174 | I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]); | |
175 | I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]); | |
176 | } | |
177 | for (i = 0; i < 3; i++) | |
178 | I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]); | |
179 | } else if (IS_GEN2(dev_priv)) { | |
180 | for (i = 0; i < 7; i++) | |
181 | I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]); | |
182 | } else if (HAS_GMCH_DISPLAY(dev_priv)) { | |
183 | for (i = 0; i < 16; i++) { | |
184 | I915_WRITE(SWF0(i), dev_priv->regfile.saveSWF0[i]); | |
185 | I915_WRITE(SWF1(i), dev_priv->regfile.saveSWF1[i]); | |
186 | } | |
187 | for (i = 0; i < 3; i++) | |
188 | I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]); | |
317c35d1 | 189 | } |
317c35d1 | 190 | |
d70bed19 KP |
191 | mutex_unlock(&dev->struct_mutex); |
192 | ||
f899fc64 | 193 | intel_i2c_reset(dev); |
f0217c42 | 194 | |
317c35d1 JB |
195 | return 0; |
196 | } |