| @@ -1,1030 +1,1032 @@ | | | @@ -1,1030 +1,1032 @@ |
1 | /* | | 1 | /* |
2 | * Copyright © 2012 Intel Corporation | | 2 | * Copyright © 2012 Intel Corporation |
3 | * | | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | | 5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation | | 6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | | 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the | | 8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: | | 9 | * Software is furnished to do so, subject to the following conditions: |
10 | * | | 10 | * |
11 | * The above copyright notice and this permission notice (including the next | | 11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the | | 12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. | | 13 | * Software. |
14 | * | | 14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | | 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | | 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | | 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | | 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | | 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | | 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
21 | * IN THE SOFTWARE. | | 21 | * IN THE SOFTWARE. |
22 | * | | 22 | * |
23 | * Authors: | | 23 | * Authors: |
24 | * Eugeni Dodonov <eugeni.dodonov@intel.com> | | 24 | * Eugeni Dodonov <eugeni.dodonov@intel.com> |
25 | * | | 25 | * |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <linux/cpufreq.h> | | 28 | #include <linux/cpufreq.h> |
29 | #include "i915_drv.h" | | 29 | #include "i915_drv.h" |
30 | #include "intel_drv.h" | | 30 | #include "intel_drv.h" |
| | | 31 | #ifndef __NetBSD__ |
31 | #include "../../../platform/x86/intel_ips.h" | | 32 | #include "../../../platform/x86/intel_ips.h" |
| | | 33 | #endif |
32 | #include <linux/module.h> | | 34 | #include <linux/module.h> |
33 | | | 35 | |
34 | #define FORCEWAKE_ACK_TIMEOUT_MS 2 | | 36 | #define FORCEWAKE_ACK_TIMEOUT_MS 2 |
35 | | | 37 | |
36 | /* FBC, or Frame Buffer Compression, is a technique employed to compress the | | 38 | /* FBC, or Frame Buffer Compression, is a technique employed to compress the |
37 | * framebuffer contents in-memory, aiming at reducing the required bandwidth | | 39 | * framebuffer contents in-memory, aiming at reducing the required bandwidth |
38 | * during in-memory transfers and, therefore, reduce the power packet. | | 40 | * during in-memory transfers and, therefore, reduce the power packet. |
39 | * | | 41 | * |
40 | * The benefits of FBC are mostly visible with solid backgrounds and | | 42 | * The benefits of FBC are mostly visible with solid backgrounds and |
41 | * variation-less patterns. | | 43 | * variation-less patterns. |
42 | * | | 44 | * |
43 | * FBC-related functionality can be enabled by the means of the | | 45 | * FBC-related functionality can be enabled by the means of the |
44 | * i915.i915_enable_fbc parameter | | 46 | * i915.i915_enable_fbc parameter |
45 | */ | | 47 | */ |
46 | | | 48 | |
47 | static bool intel_crtc_active(struct drm_crtc *crtc) | | 49 | static bool intel_crtc_active(struct drm_crtc *crtc) |
48 | { | | 50 | { |
49 | /* Be paranoid as we can arrive here with only partial | | 51 | /* Be paranoid as we can arrive here with only partial |
50 | * state retrieved from the hardware during setup. | | 52 | * state retrieved from the hardware during setup. |
51 | */ | | 53 | */ |
52 | return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; | | 54 | return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; |
53 | } | | 55 | } |
54 | | | 56 | |
55 | static void i8xx_disable_fbc(struct drm_device *dev) | | 57 | static void i8xx_disable_fbc(struct drm_device *dev) |
56 | { | | 58 | { |
57 | struct drm_i915_private *dev_priv = dev->dev_private; | | 59 | struct drm_i915_private *dev_priv = dev->dev_private; |
58 | u32 fbc_ctl; | | 60 | u32 fbc_ctl; |
59 | | | 61 | |
60 | /* Disable compression */ | | 62 | /* Disable compression */ |
61 | fbc_ctl = I915_READ(FBC_CONTROL); | | 63 | fbc_ctl = I915_READ(FBC_CONTROL); |
62 | if ((fbc_ctl & FBC_CTL_EN) == 0) | | 64 | if ((fbc_ctl & FBC_CTL_EN) == 0) |
63 | return; | | 65 | return; |
64 | | | 66 | |
65 | fbc_ctl &= ~FBC_CTL_EN; | | 67 | fbc_ctl &= ~FBC_CTL_EN; |
66 | I915_WRITE(FBC_CONTROL, fbc_ctl); | | 68 | I915_WRITE(FBC_CONTROL, fbc_ctl); |
67 | | | 69 | |
68 | /* Wait for compressing bit to clear */ | | 70 | /* Wait for compressing bit to clear */ |
69 | if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { | | 71 | if (wait_for((I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) == 0, 10)) { |
70 | DRM_DEBUG_KMS("FBC idle timed out\n"); | | 72 | DRM_DEBUG_KMS("FBC idle timed out\n"); |
71 | return; | | 73 | return; |
72 | } | | 74 | } |
73 | | | 75 | |
74 | DRM_DEBUG_KMS("disabled FBC\n"); | | 76 | DRM_DEBUG_KMS("disabled FBC\n"); |
75 | } | | 77 | } |
76 | | | 78 | |
77 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | | 79 | static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
78 | { | | 80 | { |
79 | struct drm_device *dev = crtc->dev; | | 81 | struct drm_device *dev = crtc->dev; |
80 | struct drm_i915_private *dev_priv = dev->dev_private; | | 82 | struct drm_i915_private *dev_priv = dev->dev_private; |
81 | struct drm_framebuffer *fb = crtc->fb; | | 83 | struct drm_framebuffer *fb = crtc->fb; |
82 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | | 84 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
83 | struct drm_i915_gem_object *obj = intel_fb->obj; | | 85 | struct drm_i915_gem_object *obj = intel_fb->obj; |
84 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | | 86 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
85 | int cfb_pitch; | | 87 | int cfb_pitch; |
86 | int plane, i; | | 88 | int plane, i; |
87 | u32 fbc_ctl, fbc_ctl2; | | 89 | u32 fbc_ctl, fbc_ctl2; |
88 | | | 90 | |
89 | cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; | | 91 | cfb_pitch = dev_priv->cfb_size / FBC_LL_SIZE; |
90 | if (fb->pitches[0] < cfb_pitch) | | 92 | if (fb->pitches[0] < cfb_pitch) |
91 | cfb_pitch = fb->pitches[0]; | | 93 | cfb_pitch = fb->pitches[0]; |
92 | | | 94 | |
93 | /* FBC_CTL wants 64B units */ | | 95 | /* FBC_CTL wants 64B units */ |
94 | cfb_pitch = (cfb_pitch / 64) - 1; | | 96 | cfb_pitch = (cfb_pitch / 64) - 1; |
95 | plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; | | 97 | plane = intel_crtc->plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; |
96 | | | 98 | |
97 | /* Clear old tags */ | | 99 | /* Clear old tags */ |
98 | for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) | | 100 | for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) |
99 | I915_WRITE(FBC_TAG + (i * 4), 0); | | 101 | I915_WRITE(FBC_TAG + (i * 4), 0); |
100 | | | 102 | |
101 | /* Set it up... */ | | 103 | /* Set it up... */ |
102 | fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; | | 104 | fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; |
103 | fbc_ctl2 |= plane; | | 105 | fbc_ctl2 |= plane; |
104 | I915_WRITE(FBC_CONTROL2, fbc_ctl2); | | 106 | I915_WRITE(FBC_CONTROL2, fbc_ctl2); |
105 | I915_WRITE(FBC_FENCE_OFF, crtc->y); | | 107 | I915_WRITE(FBC_FENCE_OFF, crtc->y); |
106 | | | 108 | |
107 | /* enable it... */ | | 109 | /* enable it... */ |
108 | fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; | | 110 | fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC; |
109 | if (IS_I945GM(dev)) | | 111 | if (IS_I945GM(dev)) |
110 | fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ | | 112 | fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ |
111 | fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; | | 113 | fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; |
112 | fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; | | 114 | fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; |
113 | fbc_ctl |= obj->fence_reg; | | 115 | fbc_ctl |= obj->fence_reg; |
114 | I915_WRITE(FBC_CONTROL, fbc_ctl); | | 116 | I915_WRITE(FBC_CONTROL, fbc_ctl); |
115 | | | 117 | |
116 | DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", | | 118 | DRM_DEBUG_KMS("enabled FBC, pitch %d, yoff %d, plane %d, ", |
117 | cfb_pitch, crtc->y, intel_crtc->plane); | | 119 | cfb_pitch, crtc->y, intel_crtc->plane); |
118 | } | | 120 | } |
119 | | | 121 | |
120 | static bool i8xx_fbc_enabled(struct drm_device *dev) | | 122 | static bool i8xx_fbc_enabled(struct drm_device *dev) |
121 | { | | 123 | { |
122 | struct drm_i915_private *dev_priv = dev->dev_private; | | 124 | struct drm_i915_private *dev_priv = dev->dev_private; |
123 | | | 125 | |
124 | return I915_READ(FBC_CONTROL) & FBC_CTL_EN; | | 126 | return I915_READ(FBC_CONTROL) & FBC_CTL_EN; |
125 | } | | 127 | } |
126 | | | 128 | |
127 | static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | | 129 | static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
128 | { | | 130 | { |
129 | struct drm_device *dev = crtc->dev; | | 131 | struct drm_device *dev = crtc->dev; |
130 | struct drm_i915_private *dev_priv = dev->dev_private; | | 132 | struct drm_i915_private *dev_priv = dev->dev_private; |
131 | struct drm_framebuffer *fb = crtc->fb; | | 133 | struct drm_framebuffer *fb = crtc->fb; |
132 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | | 134 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
133 | struct drm_i915_gem_object *obj = intel_fb->obj; | | 135 | struct drm_i915_gem_object *obj = intel_fb->obj; |
134 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | | 136 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
135 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; | | 137 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; |
136 | unsigned long stall_watermark = 200; | | 138 | unsigned long stall_watermark = 200; |
137 | u32 dpfc_ctl; | | 139 | u32 dpfc_ctl; |
138 | | | 140 | |
139 | dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; | | 141 | dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; |
140 | dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; | | 142 | dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; |
141 | I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); | | 143 | I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); |
142 | | | 144 | |
143 | I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | | | 145 | I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | |
144 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | | | 146 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | |
145 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); | | 147 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); |
146 | I915_WRITE(DPFC_FENCE_YOFF, crtc->y); | | 148 | I915_WRITE(DPFC_FENCE_YOFF, crtc->y); |
147 | | | 149 | |
148 | /* enable it... */ | | 150 | /* enable it... */ |
149 | I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); | | 151 | I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN); |
150 | | | 152 | |
151 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); | | 153 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); |
152 | } | | 154 | } |
153 | | | 155 | |
154 | static void g4x_disable_fbc(struct drm_device *dev) | | 156 | static void g4x_disable_fbc(struct drm_device *dev) |
155 | { | | 157 | { |
156 | struct drm_i915_private *dev_priv = dev->dev_private; | | 158 | struct drm_i915_private *dev_priv = dev->dev_private; |
157 | u32 dpfc_ctl; | | 159 | u32 dpfc_ctl; |
158 | | | 160 | |
159 | /* Disable compression */ | | 161 | /* Disable compression */ |
160 | dpfc_ctl = I915_READ(DPFC_CONTROL); | | 162 | dpfc_ctl = I915_READ(DPFC_CONTROL); |
161 | if (dpfc_ctl & DPFC_CTL_EN) { | | 163 | if (dpfc_ctl & DPFC_CTL_EN) { |
162 | dpfc_ctl &= ~DPFC_CTL_EN; | | 164 | dpfc_ctl &= ~DPFC_CTL_EN; |
163 | I915_WRITE(DPFC_CONTROL, dpfc_ctl); | | 165 | I915_WRITE(DPFC_CONTROL, dpfc_ctl); |
164 | | | 166 | |
165 | DRM_DEBUG_KMS("disabled FBC\n"); | | 167 | DRM_DEBUG_KMS("disabled FBC\n"); |
166 | } | | 168 | } |
167 | } | | 169 | } |
168 | | | 170 | |
169 | static bool g4x_fbc_enabled(struct drm_device *dev) | | 171 | static bool g4x_fbc_enabled(struct drm_device *dev) |
170 | { | | 172 | { |
171 | struct drm_i915_private *dev_priv = dev->dev_private; | | 173 | struct drm_i915_private *dev_priv = dev->dev_private; |
172 | | | 174 | |
173 | return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; | | 175 | return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; |
174 | } | | 176 | } |
175 | | | 177 | |
176 | static void sandybridge_blit_fbc_update(struct drm_device *dev) | | 178 | static void sandybridge_blit_fbc_update(struct drm_device *dev) |
177 | { | | 179 | { |
178 | struct drm_i915_private *dev_priv = dev->dev_private; | | 180 | struct drm_i915_private *dev_priv = dev->dev_private; |
179 | u32 blt_ecoskpd; | | 181 | u32 blt_ecoskpd; |
180 | | | 182 | |
181 | /* Make sure blitter notifies FBC of writes */ | | 183 | /* Make sure blitter notifies FBC of writes */ |
182 | gen6_gt_force_wake_get(dev_priv); | | 184 | gen6_gt_force_wake_get(dev_priv); |
183 | blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); | | 185 | blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD); |
184 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << | | 186 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY << |
185 | GEN6_BLITTER_LOCK_SHIFT; | | 187 | GEN6_BLITTER_LOCK_SHIFT; |
186 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | | 188 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); |
187 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; | | 189 | blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY; |
188 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | | 190 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); |
189 | blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << | | 191 | blt_ecoskpd &= ~(GEN6_BLITTER_FBC_NOTIFY << |
190 | GEN6_BLITTER_LOCK_SHIFT); | | 192 | GEN6_BLITTER_LOCK_SHIFT); |
191 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); | | 193 | I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd); |
192 | POSTING_READ(GEN6_BLITTER_ECOSKPD); | | 194 | POSTING_READ(GEN6_BLITTER_ECOSKPD); |
193 | gen6_gt_force_wake_put(dev_priv); | | 195 | gen6_gt_force_wake_put(dev_priv); |
194 | } | | 196 | } |
195 | | | 197 | |
196 | static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | | 198 | static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
197 | { | | 199 | { |
198 | struct drm_device *dev = crtc->dev; | | 200 | struct drm_device *dev = crtc->dev; |
199 | struct drm_i915_private *dev_priv = dev->dev_private; | | 201 | struct drm_i915_private *dev_priv = dev->dev_private; |
200 | struct drm_framebuffer *fb = crtc->fb; | | 202 | struct drm_framebuffer *fb = crtc->fb; |
201 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | | 203 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
202 | struct drm_i915_gem_object *obj = intel_fb->obj; | | 204 | struct drm_i915_gem_object *obj = intel_fb->obj; |
203 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | | 205 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
204 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; | | 206 | int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; |
205 | unsigned long stall_watermark = 200; | | 207 | unsigned long stall_watermark = 200; |
206 | u32 dpfc_ctl; | | 208 | u32 dpfc_ctl; |
207 | | | 209 | |
208 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); | | 210 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); |
209 | dpfc_ctl &= DPFC_RESERVED; | | 211 | dpfc_ctl &= DPFC_RESERVED; |
210 | dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); | | 212 | dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); |
211 | /* Set persistent mode for front-buffer rendering, ala X. */ | | 213 | /* Set persistent mode for front-buffer rendering, ala X. */ |
212 | dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; | | 214 | dpfc_ctl |= DPFC_CTL_PERSISTENT_MODE; |
213 | dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg); | | 215 | dpfc_ctl |= (DPFC_CTL_FENCE_EN | obj->fence_reg); |
214 | I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); | | 216 | I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); |
215 | | | 217 | |
216 | I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | | | 218 | I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN | |
217 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | | | 219 | (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | |
218 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); | | 220 | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); |
219 | I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); | | 221 | I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); |
220 | I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); | | 222 | I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); |
221 | /* enable it... */ | | 223 | /* enable it... */ |
222 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); | | 224 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); |
223 | | | 225 | |
224 | if (IS_GEN6(dev)) { | | 226 | if (IS_GEN6(dev)) { |
225 | I915_WRITE(SNB_DPFC_CTL_SA, | | 227 | I915_WRITE(SNB_DPFC_CTL_SA, |
226 | SNB_CPU_FENCE_ENABLE | obj->fence_reg); | | 228 | SNB_CPU_FENCE_ENABLE | obj->fence_reg); |
227 | I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); | | 229 | I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); |
228 | sandybridge_blit_fbc_update(dev); | | 230 | sandybridge_blit_fbc_update(dev); |
229 | } | | 231 | } |
230 | | | 232 | |
231 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); | | 233 | DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); |
232 | } | | 234 | } |
233 | | | 235 | |
234 | static void ironlake_disable_fbc(struct drm_device *dev) | | 236 | static void ironlake_disable_fbc(struct drm_device *dev) |
235 | { | | 237 | { |
236 | struct drm_i915_private *dev_priv = dev->dev_private; | | 238 | struct drm_i915_private *dev_priv = dev->dev_private; |
237 | u32 dpfc_ctl; | | 239 | u32 dpfc_ctl; |
238 | | | 240 | |
239 | /* Disable compression */ | | 241 | /* Disable compression */ |
240 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); | | 242 | dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); |
241 | if (dpfc_ctl & DPFC_CTL_EN) { | | 243 | if (dpfc_ctl & DPFC_CTL_EN) { |
242 | dpfc_ctl &= ~DPFC_CTL_EN; | | 244 | dpfc_ctl &= ~DPFC_CTL_EN; |
243 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); | | 245 | I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); |
244 | | | 246 | |
245 | DRM_DEBUG_KMS("disabled FBC\n"); | | 247 | DRM_DEBUG_KMS("disabled FBC\n"); |
246 | } | | 248 | } |
247 | } | | 249 | } |
248 | | | 250 | |
249 | static bool ironlake_fbc_enabled(struct drm_device *dev) | | 251 | static bool ironlake_fbc_enabled(struct drm_device *dev) |
250 | { | | 252 | { |
251 | struct drm_i915_private *dev_priv = dev->dev_private; | | 253 | struct drm_i915_private *dev_priv = dev->dev_private; |
252 | | | 254 | |
253 | return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; | | 255 | return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN; |
254 | } | | 256 | } |
255 | | | 257 | |
256 | bool intel_fbc_enabled(struct drm_device *dev) | | 258 | bool intel_fbc_enabled(struct drm_device *dev) |
257 | { | | 259 | { |
258 | struct drm_i915_private *dev_priv = dev->dev_private; | | 260 | struct drm_i915_private *dev_priv = dev->dev_private; |
259 | | | 261 | |
260 | if (!dev_priv->display.fbc_enabled) | | 262 | if (!dev_priv->display.fbc_enabled) |
261 | return false; | | 263 | return false; |
262 | | | 264 | |
263 | return dev_priv->display.fbc_enabled(dev); | | 265 | return dev_priv->display.fbc_enabled(dev); |
264 | } | | 266 | } |
265 | | | 267 | |
266 | static void intel_fbc_work_fn(struct work_struct *__work) | | 268 | static void intel_fbc_work_fn(struct work_struct *__work) |
267 | { | | 269 | { |
268 | struct intel_fbc_work *work = | | 270 | struct intel_fbc_work *work = |
269 | container_of(to_delayed_work(__work), | | 271 | container_of(to_delayed_work(__work), |
270 | struct intel_fbc_work, work); | | 272 | struct intel_fbc_work, work); |
271 | struct drm_device *dev = work->crtc->dev; | | 273 | struct drm_device *dev = work->crtc->dev; |
272 | struct drm_i915_private *dev_priv = dev->dev_private; | | 274 | struct drm_i915_private *dev_priv = dev->dev_private; |
273 | | | 275 | |
274 | mutex_lock(&dev->struct_mutex); | | 276 | mutex_lock(&dev->struct_mutex); |
275 | if (work == dev_priv->fbc_work) { | | 277 | if (work == dev_priv->fbc_work) { |
276 | /* Double check that we haven't switched fb without cancelling | | 278 | /* Double check that we haven't switched fb without cancelling |
277 | * the prior work. | | 279 | * the prior work. |
278 | */ | | 280 | */ |
279 | if (work->crtc->fb == work->fb) { | | 281 | if (work->crtc->fb == work->fb) { |
280 | dev_priv->display.enable_fbc(work->crtc, | | 282 | dev_priv->display.enable_fbc(work->crtc, |
281 | work->interval); | | 283 | work->interval); |
282 | | | 284 | |
283 | dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane; | | 285 | dev_priv->cfb_plane = to_intel_crtc(work->crtc)->plane; |
284 | dev_priv->cfb_fb = work->crtc->fb->base.id; | | 286 | dev_priv->cfb_fb = work->crtc->fb->base.id; |
285 | dev_priv->cfb_y = work->crtc->y; | | 287 | dev_priv->cfb_y = work->crtc->y; |
286 | } | | 288 | } |
287 | | | 289 | |
288 | dev_priv->fbc_work = NULL; | | 290 | dev_priv->fbc_work = NULL; |
289 | } | | 291 | } |
290 | mutex_unlock(&dev->struct_mutex); | | 292 | mutex_unlock(&dev->struct_mutex); |
291 | | | 293 | |
292 | kfree(work); | | 294 | kfree(work); |
293 | } | | 295 | } |
294 | | | 296 | |
295 | static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) | | 297 | static void intel_cancel_fbc_work(struct drm_i915_private *dev_priv) |
296 | { | | 298 | { |
297 | if (dev_priv->fbc_work == NULL) | | 299 | if (dev_priv->fbc_work == NULL) |
298 | return; | | 300 | return; |
299 | | | 301 | |
300 | DRM_DEBUG_KMS("cancelling pending FBC enable\n"); | | 302 | DRM_DEBUG_KMS("cancelling pending FBC enable\n"); |
301 | | | 303 | |
302 | /* Synchronisation is provided by struct_mutex and checking of | | 304 | /* Synchronisation is provided by struct_mutex and checking of |
303 | * dev_priv->fbc_work, so we can perform the cancellation | | 305 | * dev_priv->fbc_work, so we can perform the cancellation |
304 | * entirely asynchronously. | | 306 | * entirely asynchronously. |
305 | */ | | 307 | */ |
306 | if (cancel_delayed_work(&dev_priv->fbc_work->work)) | | 308 | if (cancel_delayed_work(&dev_priv->fbc_work->work)) |
307 | /* tasklet was killed before being run, clean up */ | | 309 | /* tasklet was killed before being run, clean up */ |
308 | kfree(dev_priv->fbc_work); | | 310 | kfree(dev_priv->fbc_work); |
309 | | | 311 | |
310 | /* Mark the work as no longer wanted so that if it does | | 312 | /* Mark the work as no longer wanted so that if it does |
311 | * wake-up (because the work was already running and waiting | | 313 | * wake-up (because the work was already running and waiting |
312 | * for our mutex), it will discover that is no longer | | 314 | * for our mutex), it will discover that is no longer |
313 | * necessary to run. | | 315 | * necessary to run. |
314 | */ | | 316 | */ |
315 | dev_priv->fbc_work = NULL; | | 317 | dev_priv->fbc_work = NULL; |
316 | } | | 318 | } |
317 | | | 319 | |
318 | void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) | | 320 | void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) |
319 | { | | 321 | { |
320 | struct intel_fbc_work *work; | | 322 | struct intel_fbc_work *work; |
321 | struct drm_device *dev = crtc->dev; | | 323 | struct drm_device *dev = crtc->dev; |
322 | struct drm_i915_private *dev_priv = dev->dev_private; | | 324 | struct drm_i915_private *dev_priv = dev->dev_private; |
323 | | | 325 | |
324 | if (!dev_priv->display.enable_fbc) | | 326 | if (!dev_priv->display.enable_fbc) |
325 | return; | | 327 | return; |
326 | | | 328 | |
327 | intel_cancel_fbc_work(dev_priv); | | 329 | intel_cancel_fbc_work(dev_priv); |
328 | | | 330 | |
329 | work = kzalloc(sizeof *work, GFP_KERNEL); | | 331 | work = kzalloc(sizeof *work, GFP_KERNEL); |
330 | if (work == NULL) { | | 332 | if (work == NULL) { |
331 | dev_priv->display.enable_fbc(crtc, interval); | | 333 | dev_priv->display.enable_fbc(crtc, interval); |
332 | return; | | 334 | return; |
333 | } | | 335 | } |
334 | | | 336 | |
335 | work->crtc = crtc; | | 337 | work->crtc = crtc; |
336 | work->fb = crtc->fb; | | 338 | work->fb = crtc->fb; |
337 | work->interval = interval; | | 339 | work->interval = interval; |
338 | INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); | | 340 | INIT_DELAYED_WORK(&work->work, intel_fbc_work_fn); |
339 | | | 341 | |
340 | dev_priv->fbc_work = work; | | 342 | dev_priv->fbc_work = work; |
341 | | | 343 | |
342 | DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); | | 344 | DRM_DEBUG_KMS("scheduling delayed FBC enable\n"); |
343 | | | 345 | |
344 | /* Delay the actual enabling to let pageflipping cease and the | | 346 | /* Delay the actual enabling to let pageflipping cease and the |
345 | * display to settle before starting the compression. Note that | | 347 | * display to settle before starting the compression. Note that |
346 | * this delay also serves a second purpose: it allows for a | | 348 | * this delay also serves a second purpose: it allows for a |
347 | * vblank to pass after disabling the FBC before we attempt | | 349 | * vblank to pass after disabling the FBC before we attempt |
348 | * to modify the control registers. | | 350 | * to modify the control registers. |
349 | * | | 351 | * |
350 | * A more complicated solution would involve tracking vblanks | | 352 | * A more complicated solution would involve tracking vblanks |
351 | * following the termination of the page-flipping sequence | | 353 | * following the termination of the page-flipping sequence |
352 | * and indeed performing the enable as a co-routine and not | | 354 | * and indeed performing the enable as a co-routine and not |
353 | * waiting synchronously upon the vblank. | | 355 | * waiting synchronously upon the vblank. |
354 | */ | | 356 | */ |
355 | schedule_delayed_work(&work->work, msecs_to_jiffies(50)); | | 357 | schedule_delayed_work(&work->work, msecs_to_jiffies(50)); |
356 | } | | 358 | } |
357 | | | 359 | |
358 | void intel_disable_fbc(struct drm_device *dev) | | 360 | void intel_disable_fbc(struct drm_device *dev) |
359 | { | | 361 | { |
360 | struct drm_i915_private *dev_priv = dev->dev_private; | | 362 | struct drm_i915_private *dev_priv = dev->dev_private; |
361 | | | 363 | |
362 | intel_cancel_fbc_work(dev_priv); | | 364 | intel_cancel_fbc_work(dev_priv); |
363 | | | 365 | |
364 | if (!dev_priv->display.disable_fbc) | | 366 | if (!dev_priv->display.disable_fbc) |
365 | return; | | 367 | return; |
366 | | | 368 | |
367 | dev_priv->display.disable_fbc(dev); | | 369 | dev_priv->display.disable_fbc(dev); |
368 | dev_priv->cfb_plane = -1; | | 370 | dev_priv->cfb_plane = -1; |
369 | } | | 371 | } |
370 | | | 372 | |
371 | /** | | 373 | /** |
372 | * intel_update_fbc - enable/disable FBC as needed | | 374 | * intel_update_fbc - enable/disable FBC as needed |
373 | * @dev: the drm_device | | 375 | * @dev: the drm_device |
374 | * | | 376 | * |
375 | * Set up the framebuffer compression hardware at mode set time. We | | 377 | * Set up the framebuffer compression hardware at mode set time. We |
376 | * enable it if possible: | | 378 | * enable it if possible: |
377 | * - plane A only (on pre-965) | | 379 | * - plane A only (on pre-965) |
378 | * - no pixel mulitply/line duplication | | 380 | * - no pixel mulitply/line duplication |
379 | * - no alpha buffer discard | | 381 | * - no alpha buffer discard |
380 | * - no dual wide | | 382 | * - no dual wide |
381 | * - framebuffer <= 2048 in width, 1536 in height | | 383 | * - framebuffer <= 2048 in width, 1536 in height |
382 | * | | 384 | * |
383 | * We can't assume that any compression will take place (worst case), | | 385 | * We can't assume that any compression will take place (worst case), |
384 | * so the compressed buffer has to be the same size as the uncompressed | | 386 | * so the compressed buffer has to be the same size as the uncompressed |
385 | * one. It also must reside (along with the line length buffer) in | | 387 | * one. It also must reside (along with the line length buffer) in |
386 | * stolen memory. | | 388 | * stolen memory. |
387 | * | | 389 | * |
388 | * We need to enable/disable FBC on a global basis. | | 390 | * We need to enable/disable FBC on a global basis. |
389 | */ | | 391 | */ |
390 | void intel_update_fbc(struct drm_device *dev) | | 392 | void intel_update_fbc(struct drm_device *dev) |
391 | { | | 393 | { |
392 | struct drm_i915_private *dev_priv = dev->dev_private; | | 394 | struct drm_i915_private *dev_priv = dev->dev_private; |
393 | struct drm_crtc *crtc = NULL, *tmp_crtc; | | 395 | struct drm_crtc *crtc = NULL, *tmp_crtc; |
394 | struct intel_crtc *intel_crtc; | | 396 | struct intel_crtc *intel_crtc; |
395 | struct drm_framebuffer *fb; | | 397 | struct drm_framebuffer *fb; |
396 | struct intel_framebuffer *intel_fb; | | 398 | struct intel_framebuffer *intel_fb; |
397 | struct drm_i915_gem_object *obj; | | 399 | struct drm_i915_gem_object *obj; |
398 | int enable_fbc; | | 400 | int enable_fbc; |
399 | | | 401 | |
400 | if (!i915_powersave) | | 402 | if (!i915_powersave) |
401 | return; | | 403 | return; |
402 | | | 404 | |
403 | if (!I915_HAS_FBC(dev)) | | 405 | if (!I915_HAS_FBC(dev)) |
404 | return; | | 406 | return; |
405 | | | 407 | |
406 | /* | | 408 | /* |
407 | * If FBC is already on, we just have to verify that we can | | 409 | * If FBC is already on, we just have to verify that we can |
408 | * keep it that way... | | 410 | * keep it that way... |
409 | * Need to disable if: | | 411 | * Need to disable if: |
410 | * - more than one pipe is active | | 412 | * - more than one pipe is active |
411 | * - changing FBC params (stride, fence, mode) | | 413 | * - changing FBC params (stride, fence, mode) |
412 | * - new fb is too large to fit in compressed buffer | | 414 | * - new fb is too large to fit in compressed buffer |
413 | * - going to an unsupported config (interlace, pixel multiply, etc.) | | 415 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
414 | */ | | 416 | */ |
415 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | | 417 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
416 | if (intel_crtc_active(tmp_crtc) && | | 418 | if (intel_crtc_active(tmp_crtc) && |
417 | !to_intel_crtc(tmp_crtc)->primary_disabled) { | | 419 | !to_intel_crtc(tmp_crtc)->primary_disabled) { |
418 | if (crtc) { | | 420 | if (crtc) { |
419 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | | 421 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
420 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | | 422 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
421 | goto out_disable; | | 423 | goto out_disable; |
422 | } | | 424 | } |
423 | crtc = tmp_crtc; | | 425 | crtc = tmp_crtc; |
424 | } | | 426 | } |
425 | } | | 427 | } |
426 | | | 428 | |
427 | if (!crtc || crtc->fb == NULL) { | | 429 | if (!crtc || crtc->fb == NULL) { |
428 | DRM_DEBUG_KMS("no output, disabling\n"); | | 430 | DRM_DEBUG_KMS("no output, disabling\n"); |
429 | dev_priv->no_fbc_reason = FBC_NO_OUTPUT; | | 431 | dev_priv->no_fbc_reason = FBC_NO_OUTPUT; |
430 | goto out_disable; | | 432 | goto out_disable; |
431 | } | | 433 | } |
432 | | | 434 | |
433 | intel_crtc = to_intel_crtc(crtc); | | 435 | intel_crtc = to_intel_crtc(crtc); |
434 | fb = crtc->fb; | | 436 | fb = crtc->fb; |
435 | intel_fb = to_intel_framebuffer(fb); | | 437 | intel_fb = to_intel_framebuffer(fb); |
436 | obj = intel_fb->obj; | | 438 | obj = intel_fb->obj; |
437 | | | 439 | |
438 | enable_fbc = i915_enable_fbc; | | 440 | enable_fbc = i915_enable_fbc; |
439 | if (enable_fbc < 0) { | | 441 | if (enable_fbc < 0) { |
440 | DRM_DEBUG_KMS("fbc set to per-chip default\n"); | | 442 | DRM_DEBUG_KMS("fbc set to per-chip default\n"); |
441 | enable_fbc = 1; | | 443 | enable_fbc = 1; |
442 | if (INTEL_INFO(dev)->gen <= 6) | | 444 | if (INTEL_INFO(dev)->gen <= 6) |
443 | enable_fbc = 0; | | 445 | enable_fbc = 0; |
444 | } | | 446 | } |
445 | if (!enable_fbc) { | | 447 | if (!enable_fbc) { |
446 | DRM_DEBUG_KMS("fbc disabled per module param\n"); | | 448 | DRM_DEBUG_KMS("fbc disabled per module param\n"); |
447 | dev_priv->no_fbc_reason = FBC_MODULE_PARAM; | | 449 | dev_priv->no_fbc_reason = FBC_MODULE_PARAM; |
448 | goto out_disable; | | 450 | goto out_disable; |
449 | } | | 451 | } |
450 | if (intel_fb->obj->base.size > dev_priv->cfb_size) { | | 452 | if (intel_fb->obj->base.size > dev_priv->cfb_size) { |
451 | DRM_DEBUG_KMS("framebuffer too large, disabling " | | 453 | DRM_DEBUG_KMS("framebuffer too large, disabling " |
452 | "compression\n"); | | 454 | "compression\n"); |
453 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; | | 455 | dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; |
454 | goto out_disable; | | 456 | goto out_disable; |
455 | } | | 457 | } |
456 | if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || | | 458 | if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || |
457 | (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { | | 459 | (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { |
458 | DRM_DEBUG_KMS("mode incompatible with compression, " | | 460 | DRM_DEBUG_KMS("mode incompatible with compression, " |
459 | "disabling\n"); | | 461 | "disabling\n"); |
460 | dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; | | 462 | dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE; |
461 | goto out_disable; | | 463 | goto out_disable; |
462 | } | | 464 | } |
463 | if ((crtc->mode.hdisplay > 2048) || | | 465 | if ((crtc->mode.hdisplay > 2048) || |
464 | (crtc->mode.vdisplay > 1536)) { | | 466 | (crtc->mode.vdisplay > 1536)) { |
465 | DRM_DEBUG_KMS("mode too large for compression, disabling\n"); | | 467 | DRM_DEBUG_KMS("mode too large for compression, disabling\n"); |
466 | dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; | | 468 | dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE; |
467 | goto out_disable; | | 469 | goto out_disable; |
468 | } | | 470 | } |
469 | if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { | | 471 | if ((IS_I915GM(dev) || IS_I945GM(dev)) && intel_crtc->plane != 0) { |
470 | DRM_DEBUG_KMS("plane not 0, disabling compression\n"); | | 472 | DRM_DEBUG_KMS("plane not 0, disabling compression\n"); |
471 | dev_priv->no_fbc_reason = FBC_BAD_PLANE; | | 473 | dev_priv->no_fbc_reason = FBC_BAD_PLANE; |
472 | goto out_disable; | | 474 | goto out_disable; |
473 | } | | 475 | } |
474 | | | 476 | |
475 | /* The use of a CPU fence is mandatory in order to detect writes | | 477 | /* The use of a CPU fence is mandatory in order to detect writes |
476 | * by the CPU to the scanout and trigger updates to the FBC. | | 478 | * by the CPU to the scanout and trigger updates to the FBC. |
477 | */ | | 479 | */ |
478 | if (obj->tiling_mode != I915_TILING_X || | | 480 | if (obj->tiling_mode != I915_TILING_X || |
479 | obj->fence_reg == I915_FENCE_REG_NONE) { | | 481 | obj->fence_reg == I915_FENCE_REG_NONE) { |
480 | DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); | | 482 | DRM_DEBUG_KMS("framebuffer not tiled or fenced, disabling compression\n"); |
481 | dev_priv->no_fbc_reason = FBC_NOT_TILED; | | 483 | dev_priv->no_fbc_reason = FBC_NOT_TILED; |
482 | goto out_disable; | | 484 | goto out_disable; |
483 | } | | 485 | } |
484 | | | 486 | |
485 | /* If the kernel debugger is active, always disable compression */ | | 487 | /* If the kernel debugger is active, always disable compression */ |
486 | if (in_dbg_master()) | | 488 | if (in_dbg_master()) |
487 | goto out_disable; | | 489 | goto out_disable; |
488 | | | 490 | |
489 | /* If the scanout has not changed, don't modify the FBC settings. | | 491 | /* If the scanout has not changed, don't modify the FBC settings. |
490 | * Note that we make the fundamental assumption that the fb->obj | | 492 | * Note that we make the fundamental assumption that the fb->obj |
491 | * cannot be unpinned (and have its GTT offset and fence revoked) | | 493 | * cannot be unpinned (and have its GTT offset and fence revoked) |
492 | * without first being decoupled from the scanout and FBC disabled. | | 494 | * without first being decoupled from the scanout and FBC disabled. |
493 | */ | | 495 | */ |
494 | if (dev_priv->cfb_plane == intel_crtc->plane && | | 496 | if (dev_priv->cfb_plane == intel_crtc->plane && |
495 | dev_priv->cfb_fb == fb->base.id && | | 497 | dev_priv->cfb_fb == fb->base.id && |
496 | dev_priv->cfb_y == crtc->y) | | 498 | dev_priv->cfb_y == crtc->y) |
497 | return; | | 499 | return; |
498 | | | 500 | |
499 | if (intel_fbc_enabled(dev)) { | | 501 | if (intel_fbc_enabled(dev)) { |
500 | /* We update FBC along two paths, after changing fb/crtc | | 502 | /* We update FBC along two paths, after changing fb/crtc |
501 | * configuration (modeswitching) and after page-flipping | | 503 | * configuration (modeswitching) and after page-flipping |
502 | * finishes. For the latter, we know that not only did | | 504 | * finishes. For the latter, we know that not only did |
503 | * we disable the FBC at the start of the page-flip | | 505 | * we disable the FBC at the start of the page-flip |
504 | * sequence, but also more than one vblank has passed. | | 506 | * sequence, but also more than one vblank has passed. |
505 | * | | 507 | * |
506 | * For the former case of modeswitching, it is possible | | 508 | * For the former case of modeswitching, it is possible |
507 | * to switch between two FBC valid configurations | | 509 | * to switch between two FBC valid configurations |
508 | * instantaneously so we do need to disable the FBC | | 510 | * instantaneously so we do need to disable the FBC |
509 | * before we can modify its control registers. We also | | 511 | * before we can modify its control registers. We also |
510 | * have to wait for the next vblank for that to take | | 512 | * have to wait for the next vblank for that to take |
511 | * effect. However, since we delay enabling FBC we can | | 513 | * effect. However, since we delay enabling FBC we can |
512 | * assume that a vblank has passed since disabling and | | 514 | * assume that a vblank has passed since disabling and |
513 | * that we can safely alter the registers in the deferred | | 515 | * that we can safely alter the registers in the deferred |
514 | * callback. | | 516 | * callback. |
515 | * | | 517 | * |
516 | * In the scenario that we go from a valid to invalid | | 518 | * In the scenario that we go from a valid to invalid |
517 | * and then back to valid FBC configuration we have | | 519 | * and then back to valid FBC configuration we have |
518 | * no strict enforcement that a vblank occurred since | | 520 | * no strict enforcement that a vblank occurred since |
519 | * disabling the FBC. However, along all current pipe | | 521 | * disabling the FBC. However, along all current pipe |
520 | * disabling paths we do need to wait for a vblank at | | 522 | * disabling paths we do need to wait for a vblank at |
521 | * some point. And we wait before enabling FBC anyway. | | 523 | * some point. And we wait before enabling FBC anyway. |
522 | */ | | 524 | */ |
523 | DRM_DEBUG_KMS("disabling active FBC for update\n"); | | 525 | DRM_DEBUG_KMS("disabling active FBC for update\n"); |
524 | intel_disable_fbc(dev); | | 526 | intel_disable_fbc(dev); |
525 | } | | 527 | } |
526 | | | 528 | |
527 | intel_enable_fbc(crtc, 500); | | 529 | intel_enable_fbc(crtc, 500); |
528 | return; | | 530 | return; |
529 | | | 531 | |
530 | out_disable: | | 532 | out_disable: |
531 | /* Multiple disables should be harmless */ | | 533 | /* Multiple disables should be harmless */ |
532 | if (intel_fbc_enabled(dev)) { | | 534 | if (intel_fbc_enabled(dev)) { |
533 | DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); | | 535 | DRM_DEBUG_KMS("unsupported config, disabling FBC\n"); |
534 | intel_disable_fbc(dev); | | 536 | intel_disable_fbc(dev); |
535 | } | | 537 | } |
536 | } | | 538 | } |
537 | | | 539 | |
538 | static void i915_pineview_get_mem_freq(struct drm_device *dev) | | 540 | static void i915_pineview_get_mem_freq(struct drm_device *dev) |
539 | { | | 541 | { |
540 | drm_i915_private_t *dev_priv = dev->dev_private; | | 542 | drm_i915_private_t *dev_priv = dev->dev_private; |
541 | u32 tmp; | | 543 | u32 tmp; |
542 | | | 544 | |
543 | tmp = I915_READ(CLKCFG); | | 545 | tmp = I915_READ(CLKCFG); |
544 | | | 546 | |
545 | switch (tmp & CLKCFG_FSB_MASK) { | | 547 | switch (tmp & CLKCFG_FSB_MASK) { |
546 | case CLKCFG_FSB_533: | | 548 | case CLKCFG_FSB_533: |
547 | dev_priv->fsb_freq = 533; /* 133*4 */ | | 549 | dev_priv->fsb_freq = 533; /* 133*4 */ |
548 | break; | | 550 | break; |
549 | case CLKCFG_FSB_800: | | 551 | case CLKCFG_FSB_800: |
550 | dev_priv->fsb_freq = 800; /* 200*4 */ | | 552 | dev_priv->fsb_freq = 800; /* 200*4 */ |
551 | break; | | 553 | break; |
552 | case CLKCFG_FSB_667: | | 554 | case CLKCFG_FSB_667: |
553 | dev_priv->fsb_freq = 667; /* 167*4 */ | | 555 | dev_priv->fsb_freq = 667; /* 167*4 */ |
554 | break; | | 556 | break; |
555 | case CLKCFG_FSB_400: | | 557 | case CLKCFG_FSB_400: |
556 | dev_priv->fsb_freq = 400; /* 100*4 */ | | 558 | dev_priv->fsb_freq = 400; /* 100*4 */ |
557 | break; | | 559 | break; |
558 | } | | 560 | } |
559 | | | 561 | |
560 | switch (tmp & CLKCFG_MEM_MASK) { | | 562 | switch (tmp & CLKCFG_MEM_MASK) { |
561 | case CLKCFG_MEM_533: | | 563 | case CLKCFG_MEM_533: |
562 | dev_priv->mem_freq = 533; | | 564 | dev_priv->mem_freq = 533; |
563 | break; | | 565 | break; |
564 | case CLKCFG_MEM_667: | | 566 | case CLKCFG_MEM_667: |
565 | dev_priv->mem_freq = 667; | | 567 | dev_priv->mem_freq = 667; |
566 | break; | | 568 | break; |
567 | case CLKCFG_MEM_800: | | 569 | case CLKCFG_MEM_800: |
568 | dev_priv->mem_freq = 800; | | 570 | dev_priv->mem_freq = 800; |
569 | break; | | 571 | break; |
570 | } | | 572 | } |
571 | | | 573 | |
572 | /* detect pineview DDR3 setting */ | | 574 | /* detect pineview DDR3 setting */ |
573 | tmp = I915_READ(CSHRDDR3CTL); | | 575 | tmp = I915_READ(CSHRDDR3CTL); |
574 | dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; | | 576 | dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; |
575 | } | | 577 | } |
576 | | | 578 | |
577 | static void i915_ironlake_get_mem_freq(struct drm_device *dev) | | 579 | static void i915_ironlake_get_mem_freq(struct drm_device *dev) |
578 | { | | 580 | { |
579 | drm_i915_private_t *dev_priv = dev->dev_private; | | 581 | drm_i915_private_t *dev_priv = dev->dev_private; |
580 | u16 ddrpll, csipll; | | 582 | u16 ddrpll, csipll; |
581 | | | 583 | |
582 | ddrpll = I915_READ16(DDRMPLL1); | | 584 | ddrpll = I915_READ16(DDRMPLL1); |
583 | csipll = I915_READ16(CSIPLL0); | | 585 | csipll = I915_READ16(CSIPLL0); |
584 | | | 586 | |
585 | switch (ddrpll & 0xff) { | | 587 | switch (ddrpll & 0xff) { |
586 | case 0xc: | | 588 | case 0xc: |
587 | dev_priv->mem_freq = 800; | | 589 | dev_priv->mem_freq = 800; |
588 | break; | | 590 | break; |
589 | case 0x10: | | 591 | case 0x10: |
590 | dev_priv->mem_freq = 1066; | | 592 | dev_priv->mem_freq = 1066; |
591 | break; | | 593 | break; |
592 | case 0x14: | | 594 | case 0x14: |
593 | dev_priv->mem_freq = 1333; | | 595 | dev_priv->mem_freq = 1333; |
594 | break; | | 596 | break; |
595 | case 0x18: | | 597 | case 0x18: |
596 | dev_priv->mem_freq = 1600; | | 598 | dev_priv->mem_freq = 1600; |
597 | break; | | 599 | break; |
598 | default: | | 600 | default: |
599 | DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n", | | 601 | DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n", |
600 | ddrpll & 0xff); | | 602 | ddrpll & 0xff); |
601 | dev_priv->mem_freq = 0; | | 603 | dev_priv->mem_freq = 0; |
602 | break; | | 604 | break; |
603 | } | | 605 | } |
604 | | | 606 | |
605 | dev_priv->ips.r_t = dev_priv->mem_freq; | | 607 | dev_priv->ips.r_t = dev_priv->mem_freq; |
606 | | | 608 | |
607 | switch (csipll & 0x3ff) { | | 609 | switch (csipll & 0x3ff) { |
608 | case 0x00c: | | 610 | case 0x00c: |
609 | dev_priv->fsb_freq = 3200; | | 611 | dev_priv->fsb_freq = 3200; |
610 | break; | | 612 | break; |
611 | case 0x00e: | | 613 | case 0x00e: |
612 | dev_priv->fsb_freq = 3733; | | 614 | dev_priv->fsb_freq = 3733; |
613 | break; | | 615 | break; |
614 | case 0x010: | | 616 | case 0x010: |
615 | dev_priv->fsb_freq = 4266; | | 617 | dev_priv->fsb_freq = 4266; |
616 | break; | | 618 | break; |
617 | case 0x012: | | 619 | case 0x012: |
618 | dev_priv->fsb_freq = 4800; | | 620 | dev_priv->fsb_freq = 4800; |
619 | break; | | 621 | break; |
620 | case 0x014: | | 622 | case 0x014: |
621 | dev_priv->fsb_freq = 5333; | | 623 | dev_priv->fsb_freq = 5333; |
622 | break; | | 624 | break; |
623 | case 0x016: | | 625 | case 0x016: |
624 | dev_priv->fsb_freq = 5866; | | 626 | dev_priv->fsb_freq = 5866; |
625 | break; | | 627 | break; |
626 | case 0x018: | | 628 | case 0x018: |
627 | dev_priv->fsb_freq = 6400; | | 629 | dev_priv->fsb_freq = 6400; |
628 | break; | | 630 | break; |
629 | default: | | 631 | default: |
630 | DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n", | | 632 | DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n", |
631 | csipll & 0x3ff); | | 633 | csipll & 0x3ff); |
632 | dev_priv->fsb_freq = 0; | | 634 | dev_priv->fsb_freq = 0; |
633 | break; | | 635 | break; |
634 | } | | 636 | } |
635 | | | 637 | |
636 | if (dev_priv->fsb_freq == 3200) { | | 638 | if (dev_priv->fsb_freq == 3200) { |
637 | dev_priv->ips.c_m = 0; | | 639 | dev_priv->ips.c_m = 0; |
638 | } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) { | | 640 | } else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) { |
639 | dev_priv->ips.c_m = 1; | | 641 | dev_priv->ips.c_m = 1; |
640 | } else { | | 642 | } else { |
641 | dev_priv->ips.c_m = 2; | | 643 | dev_priv->ips.c_m = 2; |
642 | } | | 644 | } |
643 | } | | 645 | } |
644 | | | 646 | |
645 | static const struct cxsr_latency cxsr_latency_table[] = { | | 647 | static const struct cxsr_latency cxsr_latency_table[] = { |
646 | {1, 0, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ | | 648 | {1, 0, 800, 400, 3382, 33382, 3983, 33983}, /* DDR2-400 SC */ |
647 | {1, 0, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ | | 649 | {1, 0, 800, 667, 3354, 33354, 3807, 33807}, /* DDR2-667 SC */ |
648 | {1, 0, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ | | 650 | {1, 0, 800, 800, 3347, 33347, 3763, 33763}, /* DDR2-800 SC */ |
649 | {1, 1, 800, 667, 6420, 36420, 6873, 36873}, /* DDR3-667 SC */ | | 651 | {1, 1, 800, 667, 6420, 36420, 6873, 36873}, /* DDR3-667 SC */ |
650 | {1, 1, 800, 800, 5902, 35902, 6318, 36318}, /* DDR3-800 SC */ | | 652 | {1, 1, 800, 800, 5902, 35902, 6318, 36318}, /* DDR3-800 SC */ |
651 | | | 653 | |
652 | {1, 0, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ | | 654 | {1, 0, 667, 400, 3400, 33400, 4021, 34021}, /* DDR2-400 SC */ |
653 | {1, 0, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ | | 655 | {1, 0, 667, 667, 3372, 33372, 3845, 33845}, /* DDR2-667 SC */ |
654 | {1, 0, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ | | 656 | {1, 0, 667, 800, 3386, 33386, 3822, 33822}, /* DDR2-800 SC */ |
655 | {1, 1, 667, 667, 6438, 36438, 6911, 36911}, /* DDR3-667 SC */ | | 657 | {1, 1, 667, 667, 6438, 36438, 6911, 36911}, /* DDR3-667 SC */ |
656 | {1, 1, 667, 800, 5941, 35941, 6377, 36377}, /* DDR3-800 SC */ | | 658 | {1, 1, 667, 800, 5941, 35941, 6377, 36377}, /* DDR3-800 SC */ |
657 | | | 659 | |
658 | {1, 0, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ | | 660 | {1, 0, 400, 400, 3472, 33472, 4173, 34173}, /* DDR2-400 SC */ |
659 | {1, 0, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ | | 661 | {1, 0, 400, 667, 3443, 33443, 3996, 33996}, /* DDR2-667 SC */ |
660 | {1, 0, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ | | 662 | {1, 0, 400, 800, 3430, 33430, 3946, 33946}, /* DDR2-800 SC */ |
661 | {1, 1, 400, 667, 6509, 36509, 7062, 37062}, /* DDR3-667 SC */ | | 663 | {1, 1, 400, 667, 6509, 36509, 7062, 37062}, /* DDR3-667 SC */ |
662 | {1, 1, 400, 800, 5985, 35985, 6501, 36501}, /* DDR3-800 SC */ | | 664 | {1, 1, 400, 800, 5985, 35985, 6501, 36501}, /* DDR3-800 SC */ |
663 | | | 665 | |
664 | {0, 0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ | | 666 | {0, 0, 800, 400, 3438, 33438, 4065, 34065}, /* DDR2-400 SC */ |
665 | {0, 0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ | | 667 | {0, 0, 800, 667, 3410, 33410, 3889, 33889}, /* DDR2-667 SC */ |
666 | {0, 0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ | | 668 | {0, 0, 800, 800, 3403, 33403, 3845, 33845}, /* DDR2-800 SC */ |
667 | {0, 1, 800, 667, 6476, 36476, 6955, 36955}, /* DDR3-667 SC */ | | 669 | {0, 1, 800, 667, 6476, 36476, 6955, 36955}, /* DDR3-667 SC */ |
668 | {0, 1, 800, 800, 5958, 35958, 6400, 36400}, /* DDR3-800 SC */ | | 670 | {0, 1, 800, 800, 5958, 35958, 6400, 36400}, /* DDR3-800 SC */ |
669 | | | 671 | |
670 | {0, 0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ | | 672 | {0, 0, 667, 400, 3456, 33456, 4103, 34106}, /* DDR2-400 SC */ |
671 | {0, 0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ | | 673 | {0, 0, 667, 667, 3428, 33428, 3927, 33927}, /* DDR2-667 SC */ |
672 | {0, 0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ | | 674 | {0, 0, 667, 800, 3443, 33443, 3905, 33905}, /* DDR2-800 SC */ |
673 | {0, 1, 667, 667, 6494, 36494, 6993, 36993}, /* DDR3-667 SC */ | | 675 | {0, 1, 667, 667, 6494, 36494, 6993, 36993}, /* DDR3-667 SC */ |
674 | {0, 1, 667, 800, 5998, 35998, 6460, 36460}, /* DDR3-800 SC */ | | 676 | {0, 1, 667, 800, 5998, 35998, 6460, 36460}, /* DDR3-800 SC */ |
675 | | | 677 | |
676 | {0, 0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ | | 678 | {0, 0, 400, 400, 3528, 33528, 4255, 34255}, /* DDR2-400 SC */ |
677 | {0, 0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ | | 679 | {0, 0, 400, 667, 3500, 33500, 4079, 34079}, /* DDR2-667 SC */ |
678 | {0, 0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ | | 680 | {0, 0, 400, 800, 3487, 33487, 4029, 34029}, /* DDR2-800 SC */ |
679 | {0, 1, 400, 667, 6566, 36566, 7145, 37145}, /* DDR3-667 SC */ | | 681 | {0, 1, 400, 667, 6566, 36566, 7145, 37145}, /* DDR3-667 SC */ |
680 | {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ | | 682 | {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ |
681 | }; | | 683 | }; |
682 | | | 684 | |
683 | static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, | | 685 | static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, |
684 | int is_ddr3, | | 686 | int is_ddr3, |
685 | int fsb, | | 687 | int fsb, |
686 | int mem) | | 688 | int mem) |
687 | { | | 689 | { |
688 | const struct cxsr_latency *latency; | | 690 | const struct cxsr_latency *latency; |
689 | int i; | | 691 | int i; |
690 | | | 692 | |
691 | if (fsb == 0 || mem == 0) | | 693 | if (fsb == 0 || mem == 0) |
692 | return NULL; | | 694 | return NULL; |
693 | | | 695 | |
694 | for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { | | 696 | for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) { |
695 | latency = &cxsr_latency_table[i]; | | 697 | latency = &cxsr_latency_table[i]; |
696 | if (is_desktop == latency->is_desktop && | | 698 | if (is_desktop == latency->is_desktop && |
697 | is_ddr3 == latency->is_ddr3 && | | 699 | is_ddr3 == latency->is_ddr3 && |
698 | fsb == latency->fsb_freq && mem == latency->mem_freq) | | 700 | fsb == latency->fsb_freq && mem == latency->mem_freq) |
699 | return latency; | | 701 | return latency; |
700 | } | | 702 | } |
701 | | | 703 | |
702 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); | | 704 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); |
703 | | | 705 | |
704 | return NULL; | | 706 | return NULL; |
705 | } | | 707 | } |
706 | | | 708 | |
707 | static void pineview_disable_cxsr(struct drm_device *dev) | | 709 | static void pineview_disable_cxsr(struct drm_device *dev) |
708 | { | | 710 | { |
709 | struct drm_i915_private *dev_priv = dev->dev_private; | | 711 | struct drm_i915_private *dev_priv = dev->dev_private; |
710 | | | 712 | |
711 | /* deactivate cxsr */ | | 713 | /* deactivate cxsr */ |
712 | I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN); | | 714 | I915_WRITE(DSPFW3, I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN); |
713 | } | | 715 | } |
714 | | | 716 | |
715 | /* | | 717 | /* |
716 | * Latency for FIFO fetches is dependent on several factors: | | 718 | * Latency for FIFO fetches is dependent on several factors: |
717 | * - memory configuration (speed, channels) | | 719 | * - memory configuration (speed, channels) |
718 | * - chipset | | 720 | * - chipset |
719 | * - current MCH state | | 721 | * - current MCH state |
720 | * It can be fairly high in some situations, so here we assume a fairly | | 722 | * It can be fairly high in some situations, so here we assume a fairly |
721 | * pessimal value. It's a tradeoff between extra memory fetches (if we | | 723 | * pessimal value. It's a tradeoff between extra memory fetches (if we |
722 | * set this value too high, the FIFO will fetch frequently to stay full) | | 724 | * set this value too high, the FIFO will fetch frequently to stay full) |
723 | * and power consumption (set it too low to save power and we might see | | 725 | * and power consumption (set it too low to save power and we might see |
724 | * FIFO underruns and display "flicker"). | | 726 | * FIFO underruns and display "flicker"). |
725 | * | | 727 | * |
726 | * A value of 5us seems to be a good balance; safe for very low end | | 728 | * A value of 5us seems to be a good balance; safe for very low end |
727 | * platforms but not overly aggressive on lower latency configs. | | 729 | * platforms but not overly aggressive on lower latency configs. |
728 | */ | | 730 | */ |
729 | static const int latency_ns = 5000; | | 731 | static const int latency_ns = 5000; |
730 | | | 732 | |
731 | static int i9xx_get_fifo_size(struct drm_device *dev, int plane) | | 733 | static int i9xx_get_fifo_size(struct drm_device *dev, int plane) |
732 | { | | 734 | { |
733 | struct drm_i915_private *dev_priv = dev->dev_private; | | 735 | struct drm_i915_private *dev_priv = dev->dev_private; |
734 | uint32_t dsparb = I915_READ(DSPARB); | | 736 | uint32_t dsparb = I915_READ(DSPARB); |
735 | int size; | | 737 | int size; |
736 | | | 738 | |
737 | size = dsparb & 0x7f; | | 739 | size = dsparb & 0x7f; |
738 | if (plane) | | 740 | if (plane) |
739 | size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; | | 741 | size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) - size; |
740 | | | 742 | |
741 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | | 743 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
742 | plane ? "B" : "A", size); | | 744 | plane ? "B" : "A", size); |
743 | | | 745 | |
744 | return size; | | 746 | return size; |
745 | } | | 747 | } |
746 | | | 748 | |
747 | static int i85x_get_fifo_size(struct drm_device *dev, int plane) | | 749 | static int i85x_get_fifo_size(struct drm_device *dev, int plane) |
748 | { | | 750 | { |
749 | struct drm_i915_private *dev_priv = dev->dev_private; | | 751 | struct drm_i915_private *dev_priv = dev->dev_private; |
750 | uint32_t dsparb = I915_READ(DSPARB); | | 752 | uint32_t dsparb = I915_READ(DSPARB); |
751 | int size; | | 753 | int size; |
752 | | | 754 | |
753 | size = dsparb & 0x1ff; | | 755 | size = dsparb & 0x1ff; |
754 | if (plane) | | 756 | if (plane) |
755 | size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size; | | 757 | size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) - size; |
756 | size >>= 1; /* Convert to cachelines */ | | 758 | size >>= 1; /* Convert to cachelines */ |
757 | | | 759 | |
758 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | | 760 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
759 | plane ? "B" : "A", size); | | 761 | plane ? "B" : "A", size); |
760 | | | 762 | |
761 | return size; | | 763 | return size; |
762 | } | | 764 | } |
763 | | | 765 | |
764 | static int i845_get_fifo_size(struct drm_device *dev, int plane) | | 766 | static int i845_get_fifo_size(struct drm_device *dev, int plane) |
765 | { | | 767 | { |
766 | struct drm_i915_private *dev_priv = dev->dev_private; | | 768 | struct drm_i915_private *dev_priv = dev->dev_private; |
767 | uint32_t dsparb = I915_READ(DSPARB); | | 769 | uint32_t dsparb = I915_READ(DSPARB); |
768 | int size; | | 770 | int size; |
769 | | | 771 | |
770 | size = dsparb & 0x7f; | | 772 | size = dsparb & 0x7f; |
771 | size >>= 2; /* Convert to cachelines */ | | 773 | size >>= 2; /* Convert to cachelines */ |
772 | | | 774 | |
773 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | | 775 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
774 | plane ? "B" : "A", | | 776 | plane ? "B" : "A", |
775 | size); | | 777 | size); |
776 | | | 778 | |
777 | return size; | | 779 | return size; |
778 | } | | 780 | } |
779 | | | 781 | |
780 | static int i830_get_fifo_size(struct drm_device *dev, int plane) | | 782 | static int i830_get_fifo_size(struct drm_device *dev, int plane) |
781 | { | | 783 | { |
782 | struct drm_i915_private *dev_priv = dev->dev_private; | | 784 | struct drm_i915_private *dev_priv = dev->dev_private; |
783 | uint32_t dsparb = I915_READ(DSPARB); | | 785 | uint32_t dsparb = I915_READ(DSPARB); |
784 | int size; | | 786 | int size; |
785 | | | 787 | |
786 | size = dsparb & 0x7f; | | 788 | size = dsparb & 0x7f; |
787 | size >>= 1; /* Convert to cachelines */ | | 789 | size >>= 1; /* Convert to cachelines */ |
788 | | | 790 | |
789 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, | | 791 | DRM_DEBUG_KMS("FIFO size - (0x%08x) %s: %d\n", dsparb, |
790 | plane ? "B" : "A", size); | | 792 | plane ? "B" : "A", size); |
791 | | | 793 | |
792 | return size; | | 794 | return size; |
793 | } | | 795 | } |
794 | | | 796 | |
795 | /* Pineview has different values for various configs */ | | 797 | /* Pineview has different values for various configs */ |
796 | static const struct intel_watermark_params pineview_display_wm = { | | 798 | static const struct intel_watermark_params pineview_display_wm = { |
797 | PINEVIEW_DISPLAY_FIFO, | | 799 | PINEVIEW_DISPLAY_FIFO, |
798 | PINEVIEW_MAX_WM, | | 800 | PINEVIEW_MAX_WM, |
799 | PINEVIEW_DFT_WM, | | 801 | PINEVIEW_DFT_WM, |
800 | PINEVIEW_GUARD_WM, | | 802 | PINEVIEW_GUARD_WM, |
801 | PINEVIEW_FIFO_LINE_SIZE | | 803 | PINEVIEW_FIFO_LINE_SIZE |
802 | }; | | 804 | }; |
803 | static const struct intel_watermark_params pineview_display_hplloff_wm = { | | 805 | static const struct intel_watermark_params pineview_display_hplloff_wm = { |
804 | PINEVIEW_DISPLAY_FIFO, | | 806 | PINEVIEW_DISPLAY_FIFO, |
805 | PINEVIEW_MAX_WM, | | 807 | PINEVIEW_MAX_WM, |
806 | PINEVIEW_DFT_HPLLOFF_WM, | | 808 | PINEVIEW_DFT_HPLLOFF_WM, |
807 | PINEVIEW_GUARD_WM, | | 809 | PINEVIEW_GUARD_WM, |
808 | PINEVIEW_FIFO_LINE_SIZE | | 810 | PINEVIEW_FIFO_LINE_SIZE |
809 | }; | | 811 | }; |
810 | static const struct intel_watermark_params pineview_cursor_wm = { | | 812 | static const struct intel_watermark_params pineview_cursor_wm = { |
811 | PINEVIEW_CURSOR_FIFO, | | 813 | PINEVIEW_CURSOR_FIFO, |
812 | PINEVIEW_CURSOR_MAX_WM, | | 814 | PINEVIEW_CURSOR_MAX_WM, |
813 | PINEVIEW_CURSOR_DFT_WM, | | 815 | PINEVIEW_CURSOR_DFT_WM, |
814 | PINEVIEW_CURSOR_GUARD_WM, | | 816 | PINEVIEW_CURSOR_GUARD_WM, |
815 | PINEVIEW_FIFO_LINE_SIZE, | | 817 | PINEVIEW_FIFO_LINE_SIZE, |
816 | }; | | 818 | }; |
817 | static const struct intel_watermark_params pineview_cursor_hplloff_wm = { | | 819 | static const struct intel_watermark_params pineview_cursor_hplloff_wm = { |
818 | PINEVIEW_CURSOR_FIFO, | | 820 | PINEVIEW_CURSOR_FIFO, |
819 | PINEVIEW_CURSOR_MAX_WM, | | 821 | PINEVIEW_CURSOR_MAX_WM, |
820 | PINEVIEW_CURSOR_DFT_WM, | | 822 | PINEVIEW_CURSOR_DFT_WM, |
821 | PINEVIEW_CURSOR_GUARD_WM, | | 823 | PINEVIEW_CURSOR_GUARD_WM, |
822 | PINEVIEW_FIFO_LINE_SIZE | | 824 | PINEVIEW_FIFO_LINE_SIZE |
823 | }; | | 825 | }; |
824 | static const struct intel_watermark_params g4x_wm_info = { | | 826 | static const struct intel_watermark_params g4x_wm_info = { |
825 | G4X_FIFO_SIZE, | | 827 | G4X_FIFO_SIZE, |
826 | G4X_MAX_WM, | | 828 | G4X_MAX_WM, |
827 | G4X_MAX_WM, | | 829 | G4X_MAX_WM, |
828 | 2, | | 830 | 2, |
829 | G4X_FIFO_LINE_SIZE, | | 831 | G4X_FIFO_LINE_SIZE, |
830 | }; | | 832 | }; |
831 | static const struct intel_watermark_params g4x_cursor_wm_info = { | | 833 | static const struct intel_watermark_params g4x_cursor_wm_info = { |
832 | I965_CURSOR_FIFO, | | 834 | I965_CURSOR_FIFO, |
833 | I965_CURSOR_MAX_WM, | | 835 | I965_CURSOR_MAX_WM, |
834 | I965_CURSOR_DFT_WM, | | 836 | I965_CURSOR_DFT_WM, |
835 | 2, | | 837 | 2, |
836 | G4X_FIFO_LINE_SIZE, | | 838 | G4X_FIFO_LINE_SIZE, |
837 | }; | | 839 | }; |
838 | static const struct intel_watermark_params valleyview_wm_info = { | | 840 | static const struct intel_watermark_params valleyview_wm_info = { |
839 | VALLEYVIEW_FIFO_SIZE, | | 841 | VALLEYVIEW_FIFO_SIZE, |
840 | VALLEYVIEW_MAX_WM, | | 842 | VALLEYVIEW_MAX_WM, |
841 | VALLEYVIEW_MAX_WM, | | 843 | VALLEYVIEW_MAX_WM, |
842 | 2, | | 844 | 2, |
843 | G4X_FIFO_LINE_SIZE, | | 845 | G4X_FIFO_LINE_SIZE, |
844 | }; | | 846 | }; |
845 | static const struct intel_watermark_params valleyview_cursor_wm_info = { | | 847 | static const struct intel_watermark_params valleyview_cursor_wm_info = { |
846 | I965_CURSOR_FIFO, | | 848 | I965_CURSOR_FIFO, |
847 | VALLEYVIEW_CURSOR_MAX_WM, | | 849 | VALLEYVIEW_CURSOR_MAX_WM, |
848 | I965_CURSOR_DFT_WM, | | 850 | I965_CURSOR_DFT_WM, |
849 | 2, | | 851 | 2, |
850 | G4X_FIFO_LINE_SIZE, | | 852 | G4X_FIFO_LINE_SIZE, |
851 | }; | | 853 | }; |
852 | static const struct intel_watermark_params i965_cursor_wm_info = { | | 854 | static const struct intel_watermark_params i965_cursor_wm_info = { |
853 | I965_CURSOR_FIFO, | | 855 | I965_CURSOR_FIFO, |
854 | I965_CURSOR_MAX_WM, | | 856 | I965_CURSOR_MAX_WM, |
855 | I965_CURSOR_DFT_WM, | | 857 | I965_CURSOR_DFT_WM, |
856 | 2, | | 858 | 2, |
857 | I915_FIFO_LINE_SIZE, | | 859 | I915_FIFO_LINE_SIZE, |
858 | }; | | 860 | }; |
859 | static const struct intel_watermark_params i945_wm_info = { | | 861 | static const struct intel_watermark_params i945_wm_info = { |
860 | I945_FIFO_SIZE, | | 862 | I945_FIFO_SIZE, |
861 | I915_MAX_WM, | | 863 | I915_MAX_WM, |
862 | 1, | | 864 | 1, |
863 | 2, | | 865 | 2, |
864 | I915_FIFO_LINE_SIZE | | 866 | I915_FIFO_LINE_SIZE |
865 | }; | | 867 | }; |
866 | static const struct intel_watermark_params i915_wm_info = { | | 868 | static const struct intel_watermark_params i915_wm_info = { |
867 | I915_FIFO_SIZE, | | 869 | I915_FIFO_SIZE, |
868 | I915_MAX_WM, | | 870 | I915_MAX_WM, |
869 | 1, | | 871 | 1, |
870 | 2, | | 872 | 2, |
871 | I915_FIFO_LINE_SIZE | | 873 | I915_FIFO_LINE_SIZE |
872 | }; | | 874 | }; |
873 | static const struct intel_watermark_params i855_wm_info = { | | 875 | static const struct intel_watermark_params i855_wm_info = { |
874 | I855GM_FIFO_SIZE, | | 876 | I855GM_FIFO_SIZE, |
875 | I915_MAX_WM, | | 877 | I915_MAX_WM, |
876 | 1, | | 878 | 1, |
877 | 2, | | 879 | 2, |
878 | I830_FIFO_LINE_SIZE | | 880 | I830_FIFO_LINE_SIZE |
879 | }; | | 881 | }; |
880 | static const struct intel_watermark_params i830_wm_info = { | | 882 | static const struct intel_watermark_params i830_wm_info = { |
881 | I830_FIFO_SIZE, | | 883 | I830_FIFO_SIZE, |
882 | I915_MAX_WM, | | 884 | I915_MAX_WM, |
883 | 1, | | 885 | 1, |
884 | 2, | | 886 | 2, |
885 | I830_FIFO_LINE_SIZE | | 887 | I830_FIFO_LINE_SIZE |
886 | }; | | 888 | }; |
887 | | | 889 | |
888 | static const struct intel_watermark_params ironlake_display_wm_info = { | | 890 | static const struct intel_watermark_params ironlake_display_wm_info = { |
889 | ILK_DISPLAY_FIFO, | | 891 | ILK_DISPLAY_FIFO, |
890 | ILK_DISPLAY_MAXWM, | | 892 | ILK_DISPLAY_MAXWM, |
891 | ILK_DISPLAY_DFTWM, | | 893 | ILK_DISPLAY_DFTWM, |
892 | 2, | | 894 | 2, |
893 | ILK_FIFO_LINE_SIZE | | 895 | ILK_FIFO_LINE_SIZE |
894 | }; | | 896 | }; |
895 | static const struct intel_watermark_params ironlake_cursor_wm_info = { | | 897 | static const struct intel_watermark_params ironlake_cursor_wm_info = { |
896 | ILK_CURSOR_FIFO, | | 898 | ILK_CURSOR_FIFO, |
897 | ILK_CURSOR_MAXWM, | | 899 | ILK_CURSOR_MAXWM, |
898 | ILK_CURSOR_DFTWM, | | 900 | ILK_CURSOR_DFTWM, |
899 | 2, | | 901 | 2, |
900 | ILK_FIFO_LINE_SIZE | | 902 | ILK_FIFO_LINE_SIZE |
901 | }; | | 903 | }; |
902 | static const struct intel_watermark_params ironlake_display_srwm_info = { | | 904 | static const struct intel_watermark_params ironlake_display_srwm_info = { |
903 | ILK_DISPLAY_SR_FIFO, | | 905 | ILK_DISPLAY_SR_FIFO, |
904 | ILK_DISPLAY_MAX_SRWM, | | 906 | ILK_DISPLAY_MAX_SRWM, |
905 | ILK_DISPLAY_DFT_SRWM, | | 907 | ILK_DISPLAY_DFT_SRWM, |
906 | 2, | | 908 | 2, |
907 | ILK_FIFO_LINE_SIZE | | 909 | ILK_FIFO_LINE_SIZE |
908 | }; | | 910 | }; |
909 | static const struct intel_watermark_params ironlake_cursor_srwm_info = { | | 911 | static const struct intel_watermark_params ironlake_cursor_srwm_info = { |
910 | ILK_CURSOR_SR_FIFO, | | 912 | ILK_CURSOR_SR_FIFO, |
911 | ILK_CURSOR_MAX_SRWM, | | 913 | ILK_CURSOR_MAX_SRWM, |
912 | ILK_CURSOR_DFT_SRWM, | | 914 | ILK_CURSOR_DFT_SRWM, |
913 | 2, | | 915 | 2, |
914 | ILK_FIFO_LINE_SIZE | | 916 | ILK_FIFO_LINE_SIZE |
915 | }; | | 917 | }; |
916 | | | 918 | |
917 | static const struct intel_watermark_params sandybridge_display_wm_info = { | | 919 | static const struct intel_watermark_params sandybridge_display_wm_info = { |
918 | SNB_DISPLAY_FIFO, | | 920 | SNB_DISPLAY_FIFO, |
919 | SNB_DISPLAY_MAXWM, | | 921 | SNB_DISPLAY_MAXWM, |
920 | SNB_DISPLAY_DFTWM, | | 922 | SNB_DISPLAY_DFTWM, |
921 | 2, | | 923 | 2, |
922 | SNB_FIFO_LINE_SIZE | | 924 | SNB_FIFO_LINE_SIZE |
923 | }; | | 925 | }; |
924 | static const struct intel_watermark_params sandybridge_cursor_wm_info = { | | 926 | static const struct intel_watermark_params sandybridge_cursor_wm_info = { |
925 | SNB_CURSOR_FIFO, | | 927 | SNB_CURSOR_FIFO, |
926 | SNB_CURSOR_MAXWM, | | 928 | SNB_CURSOR_MAXWM, |
927 | SNB_CURSOR_DFTWM, | | 929 | SNB_CURSOR_DFTWM, |
928 | 2, | | 930 | 2, |
929 | SNB_FIFO_LINE_SIZE | | 931 | SNB_FIFO_LINE_SIZE |
930 | }; | | 932 | }; |
931 | static const struct intel_watermark_params sandybridge_display_srwm_info = { | | 933 | static const struct intel_watermark_params sandybridge_display_srwm_info = { |
932 | SNB_DISPLAY_SR_FIFO, | | 934 | SNB_DISPLAY_SR_FIFO, |
933 | SNB_DISPLAY_MAX_SRWM, | | 935 | SNB_DISPLAY_MAX_SRWM, |
934 | SNB_DISPLAY_DFT_SRWM, | | 936 | SNB_DISPLAY_DFT_SRWM, |
935 | 2, | | 937 | 2, |
936 | SNB_FIFO_LINE_SIZE | | 938 | SNB_FIFO_LINE_SIZE |
937 | }; | | 939 | }; |
938 | static const struct intel_watermark_params sandybridge_cursor_srwm_info = { | | 940 | static const struct intel_watermark_params sandybridge_cursor_srwm_info = { |
939 | SNB_CURSOR_SR_FIFO, | | 941 | SNB_CURSOR_SR_FIFO, |
940 | SNB_CURSOR_MAX_SRWM, | | 942 | SNB_CURSOR_MAX_SRWM, |
941 | SNB_CURSOR_DFT_SRWM, | | 943 | SNB_CURSOR_DFT_SRWM, |
942 | 2, | | 944 | 2, |
943 | SNB_FIFO_LINE_SIZE | | 945 | SNB_FIFO_LINE_SIZE |
944 | }; | | 946 | }; |
945 | | | 947 | |
946 | | | 948 | |
947 | /** | | 949 | /** |
948 | * intel_calculate_wm - calculate watermark level | | 950 | * intel_calculate_wm - calculate watermark level |
949 | * @clock_in_khz: pixel clock | | 951 | * @clock_in_khz: pixel clock |
950 | * @wm: chip FIFO params | | 952 | * @wm: chip FIFO params |
951 | * @pixel_size: display pixel size | | 953 | * @pixel_size: display pixel size |
952 | * @latency_ns: memory latency for the platform | | 954 | * @latency_ns: memory latency for the platform |
953 | * | | 955 | * |
954 | * Calculate the watermark level (the level at which the display plane will | | 956 | * Calculate the watermark level (the level at which the display plane will |
955 | * start fetching from memory again). Each chip has a different display | | 957 | * start fetching from memory again). Each chip has a different display |
956 | * FIFO size and allocation, so the caller needs to figure that out and pass | | 958 | * FIFO size and allocation, so the caller needs to figure that out and pass |
957 | * in the correct intel_watermark_params structure. | | 959 | * in the correct intel_watermark_params structure. |
958 | * | | 960 | * |
959 | * As the pixel clock runs, the FIFO will be drained at a rate that depends | | 961 | * As the pixel clock runs, the FIFO will be drained at a rate that depends |
960 | * on the pixel size. When it reaches the watermark level, it'll start | | 962 | * on the pixel size. When it reaches the watermark level, it'll start |
961 | * fetching FIFO line sized based chunks from memory until the FIFO fills | | 963 | * fetching FIFO line sized based chunks from memory until the FIFO fills |
962 | * past the watermark point. If the FIFO drains completely, a FIFO underrun | | 964 | * past the watermark point. If the FIFO drains completely, a FIFO underrun |
963 | * will occur, and a display engine hang could result. | | 965 | * will occur, and a display engine hang could result. |
964 | */ | | 966 | */ |
965 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, | | 967 | static unsigned long intel_calculate_wm(unsigned long clock_in_khz, |
966 | const struct intel_watermark_params *wm, | | 968 | const struct intel_watermark_params *wm, |
967 | int fifo_size, | | 969 | int fifo_size, |
968 | int pixel_size, | | 970 | int pixel_size, |
969 | unsigned long latency_ns) | | 971 | unsigned long latency_ns) |
970 | { | | 972 | { |
971 | long entries_required, wm_size; | | 973 | long entries_required, wm_size; |
972 | | | 974 | |
973 | /* | | 975 | /* |
974 | * Note: we need to make sure we don't overflow for various clock & | | 976 | * Note: we need to make sure we don't overflow for various clock & |
975 | * latency values. | | 977 | * latency values. |
976 | * clocks go from a few thousand to several hundred thousand. | | 978 | * clocks go from a few thousand to several hundred thousand. |
977 | * latency is usually a few thousand | | 979 | * latency is usually a few thousand |
978 | */ | | 980 | */ |
979 | entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) / | | 981 | entries_required = ((clock_in_khz / 1000) * pixel_size * latency_ns) / |
980 | 1000; | | 982 | 1000; |
981 | entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); | | 983 | entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); |
982 | | | 984 | |
983 | DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required); | | 985 | DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required); |
984 | | | 986 | |
985 | wm_size = fifo_size - (entries_required + wm->guard_size); | | 987 | wm_size = fifo_size - (entries_required + wm->guard_size); |
986 | | | 988 | |
987 | DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size); | | 989 | DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size); |
988 | | | 990 | |
989 | /* Don't promote wm_size to unsigned... */ | | 991 | /* Don't promote wm_size to unsigned... */ |
990 | if (wm_size > (long)wm->max_wm) | | 992 | if (wm_size > (long)wm->max_wm) |
991 | wm_size = wm->max_wm; | | 993 | wm_size = wm->max_wm; |
992 | if (wm_size <= 0) | | 994 | if (wm_size <= 0) |
993 | wm_size = wm->default_wm; | | 995 | wm_size = wm->default_wm; |
994 | return wm_size; | | 996 | return wm_size; |
995 | } | | 997 | } |
996 | | | 998 | |
997 | static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) | | 999 | static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) |
998 | { | | 1000 | { |
999 | struct drm_crtc *crtc, *enabled = NULL; | | 1001 | struct drm_crtc *crtc, *enabled = NULL; |
1000 | | | 1002 | |
1001 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | | 1003 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
1002 | if (intel_crtc_active(crtc)) { | | 1004 | if (intel_crtc_active(crtc)) { |
1003 | if (enabled) | | 1005 | if (enabled) |
1004 | return NULL; | | 1006 | return NULL; |
1005 | enabled = crtc; | | 1007 | enabled = crtc; |
1006 | } | | 1008 | } |
1007 | } | | 1009 | } |
1008 | | | 1010 | |
1009 | return enabled; | | 1011 | return enabled; |
1010 | } | | 1012 | } |
1011 | | | 1013 | |
1012 | static void pineview_update_wm(struct drm_device *dev) | | 1014 | static void pineview_update_wm(struct drm_device *dev) |
1013 | { | | 1015 | { |
1014 | struct drm_i915_private *dev_priv = dev->dev_private; | | 1016 | struct drm_i915_private *dev_priv = dev->dev_private; |
1015 | struct drm_crtc *crtc; | | 1017 | struct drm_crtc *crtc; |
1016 | const struct cxsr_latency *latency; | | 1018 | const struct cxsr_latency *latency; |
1017 | u32 reg; | | 1019 | u32 reg; |
1018 | unsigned long wm; | | 1020 | unsigned long wm; |
1019 | | | 1021 | |
1020 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, | | 1022 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, |
1021 | dev_priv->fsb_freq, dev_priv->mem_freq); | | 1023 | dev_priv->fsb_freq, dev_priv->mem_freq); |
1022 | if (!latency) { | | 1024 | if (!latency) { |
1023 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); | | 1025 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); |
1024 | pineview_disable_cxsr(dev); | | 1026 | pineview_disable_cxsr(dev); |
1025 | return; | | 1027 | return; |
1026 | } | | 1028 | } |
1027 | | | 1029 | |
1028 | crtc = single_enabled_crtc(dev); | | 1030 | crtc = single_enabled_crtc(dev); |
1029 | if (crtc) { | | 1031 | if (crtc) { |
1030 | int clock = crtc->mode.clock; | | 1032 | int clock = crtc->mode.clock; |
| @@ -2338,2005 +2340,2007 @@ static void ironlake_enable_drps(struct | | | @@ -2338,2005 +2340,2007 @@ static void ironlake_enable_drps(struct |
2338 | /* 100ms RC evaluation intervals */ | | 2340 | /* 100ms RC evaluation intervals */ |
2339 | I915_WRITE(RCUPEI, 100000); | | 2341 | I915_WRITE(RCUPEI, 100000); |
2340 | I915_WRITE(RCDNEI, 100000); | | 2342 | I915_WRITE(RCDNEI, 100000); |
2341 | | | 2343 | |
2342 | /* Set max/min thresholds to 90ms and 80ms respectively */ | | 2344 | /* Set max/min thresholds to 90ms and 80ms respectively */ |
2343 | I915_WRITE(RCBMAXAVG, 90000); | | 2345 | I915_WRITE(RCBMAXAVG, 90000); |
2344 | I915_WRITE(RCBMINAVG, 80000); | | 2346 | I915_WRITE(RCBMINAVG, 80000); |
2345 | | | 2347 | |
2346 | I915_WRITE(MEMIHYST, 1); | | 2348 | I915_WRITE(MEMIHYST, 1); |
2347 | | | 2349 | |
2348 | /* Set up min, max, and cur for interrupt handling */ | | 2350 | /* Set up min, max, and cur for interrupt handling */ |
2349 | fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT; | | 2351 | fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT; |
2350 | fmin = (rgvmodectl & MEMMODE_FMIN_MASK); | | 2352 | fmin = (rgvmodectl & MEMMODE_FMIN_MASK); |
2351 | fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> | | 2353 | fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> |
2352 | MEMMODE_FSTART_SHIFT; | | 2354 | MEMMODE_FSTART_SHIFT; |
2353 | | | 2355 | |
2354 | vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> | | 2356 | vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> |
2355 | PXVFREQ_PX_SHIFT; | | 2357 | PXVFREQ_PX_SHIFT; |
2356 | | | 2358 | |
2357 | dev_priv->ips.fmax = fmax; /* IPS callback will increase this */ | | 2359 | dev_priv->ips.fmax = fmax; /* IPS callback will increase this */ |
2358 | dev_priv->ips.fstart = fstart; | | 2360 | dev_priv->ips.fstart = fstart; |
2359 | | | 2361 | |
2360 | dev_priv->ips.max_delay = fstart; | | 2362 | dev_priv->ips.max_delay = fstart; |
2361 | dev_priv->ips.min_delay = fmin; | | 2363 | dev_priv->ips.min_delay = fmin; |
2362 | dev_priv->ips.cur_delay = fstart; | | 2364 | dev_priv->ips.cur_delay = fstart; |
2363 | | | 2365 | |
2364 | DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", | | 2366 | DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", |
2365 | fmax, fmin, fstart); | | 2367 | fmax, fmin, fstart); |
2366 | | | 2368 | |
2367 | I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); | | 2369 | I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN); |
2368 | | | 2370 | |
2369 | /* | | 2371 | /* |
2370 | * Interrupts will be enabled in ironlake_irq_postinstall | | 2372 | * Interrupts will be enabled in ironlake_irq_postinstall |
2371 | */ | | 2373 | */ |
2372 | | | 2374 | |
2373 | I915_WRITE(VIDSTART, vstart); | | 2375 | I915_WRITE(VIDSTART, vstart); |
2374 | POSTING_READ(VIDSTART); | | 2376 | POSTING_READ(VIDSTART); |
2375 | | | 2377 | |
2376 | rgvmodectl |= MEMMODE_SWMODE_EN; | | 2378 | rgvmodectl |= MEMMODE_SWMODE_EN; |
2377 | I915_WRITE(MEMMODECTL, rgvmodectl); | | 2379 | I915_WRITE(MEMMODECTL, rgvmodectl); |
2378 | | | 2380 | |
2379 | if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) | | 2381 | if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10)) |
2380 | DRM_ERROR("stuck trying to change perf mode\n"); | | 2382 | DRM_ERROR("stuck trying to change perf mode\n"); |
2381 | mdelay(1); | | 2383 | mdelay(1); |
2382 | | | 2384 | |
2383 | ironlake_set_drps(dev, fstart); | | 2385 | ironlake_set_drps(dev, fstart); |
2384 | | | 2386 | |
2385 | dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) + | | 2387 | dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) + |
2386 | I915_READ(0x112e0); | | 2388 | I915_READ(0x112e0); |
2387 | dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies); | | 2389 | dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies); |
2388 | dev_priv->ips.last_count2 = I915_READ(0x112f4); | | 2390 | dev_priv->ips.last_count2 = I915_READ(0x112f4); |
2389 | getrawmonotonic(&dev_priv->ips.last_time2); | | 2391 | getrawmonotonic(&dev_priv->ips.last_time2); |
2390 | | | 2392 | |
2391 | spin_unlock_irq(&mchdev_lock); | | 2393 | spin_unlock_irq(&mchdev_lock); |
2392 | } | | 2394 | } |
2393 | | | 2395 | |
2394 | static void ironlake_disable_drps(struct drm_device *dev) | | 2396 | static void ironlake_disable_drps(struct drm_device *dev) |
2395 | { | | 2397 | { |
2396 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2398 | struct drm_i915_private *dev_priv = dev->dev_private; |
2397 | u16 rgvswctl; | | 2399 | u16 rgvswctl; |
2398 | | | 2400 | |
2399 | spin_lock_irq(&mchdev_lock); | | 2401 | spin_lock_irq(&mchdev_lock); |
2400 | | | 2402 | |
2401 | rgvswctl = I915_READ16(MEMSWCTL); | | 2403 | rgvswctl = I915_READ16(MEMSWCTL); |
2402 | | | 2404 | |
2403 | /* Ack interrupts, disable EFC interrupt */ | | 2405 | /* Ack interrupts, disable EFC interrupt */ |
2404 | I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); | | 2406 | I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN); |
2405 | I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG); | | 2407 | I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG); |
2406 | I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT); | | 2408 | I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT); |
2407 | I915_WRITE(DEIIR, DE_PCU_EVENT); | | 2409 | I915_WRITE(DEIIR, DE_PCU_EVENT); |
2408 | I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT); | | 2410 | I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT); |
2409 | | | 2411 | |
2410 | /* Go back to the starting frequency */ | | 2412 | /* Go back to the starting frequency */ |
2411 | ironlake_set_drps(dev, dev_priv->ips.fstart); | | 2413 | ironlake_set_drps(dev, dev_priv->ips.fstart); |
2412 | mdelay(1); | | 2414 | mdelay(1); |
2413 | rgvswctl |= MEMCTL_CMD_STS; | | 2415 | rgvswctl |= MEMCTL_CMD_STS; |
2414 | I915_WRITE(MEMSWCTL, rgvswctl); | | 2416 | I915_WRITE(MEMSWCTL, rgvswctl); |
2415 | mdelay(1); | | 2417 | mdelay(1); |
2416 | | | 2418 | |
2417 | spin_unlock_irq(&mchdev_lock); | | 2419 | spin_unlock_irq(&mchdev_lock); |
2418 | } | | 2420 | } |
2419 | | | 2421 | |
2420 | /* There's a funny hw issue where the hw returns all 0 when reading from | | 2422 | /* There's a funny hw issue where the hw returns all 0 when reading from |
2421 | * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value | | 2423 | * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value |
2422 | * ourselves, instead of doing a rmw cycle (which might result in us clearing | | 2424 | * ourselves, instead of doing a rmw cycle (which might result in us clearing |
2423 | * all limits and the gpu stuck at whatever frequency it is at atm). | | 2425 | * all limits and the gpu stuck at whatever frequency it is at atm). |
2424 | */ | | 2426 | */ |
2425 | static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) | | 2427 | static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) |
2426 | { | | 2428 | { |
2427 | u32 limits; | | 2429 | u32 limits; |
2428 | | | 2430 | |
2429 | limits = 0; | | 2431 | limits = 0; |
2430 | | | 2432 | |
2431 | if (*val >= dev_priv->rps.max_delay) | | 2433 | if (*val >= dev_priv->rps.max_delay) |
2432 | *val = dev_priv->rps.max_delay; | | 2434 | *val = dev_priv->rps.max_delay; |
2433 | limits |= dev_priv->rps.max_delay << 24; | | 2435 | limits |= dev_priv->rps.max_delay << 24; |
2434 | | | 2436 | |
2435 | /* Only set the down limit when we've reached the lowest level to avoid | | 2437 | /* Only set the down limit when we've reached the lowest level to avoid |
2436 | * getting more interrupts, otherwise leave this clear. This prevents a | | 2438 | * getting more interrupts, otherwise leave this clear. This prevents a |
2437 | * race in the hw when coming out of rc6: There's a tiny window where | | 2439 | * race in the hw when coming out of rc6: There's a tiny window where |
2438 | * the hw runs at the minimal clock before selecting the desired | | 2440 | * the hw runs at the minimal clock before selecting the desired |
2439 | * frequency, if the down threshold expires in that window we will not | | 2441 | * frequency, if the down threshold expires in that window we will not |
2440 | * receive a down interrupt. */ | | 2442 | * receive a down interrupt. */ |
2441 | if (*val <= dev_priv->rps.min_delay) { | | 2443 | if (*val <= dev_priv->rps.min_delay) { |
2442 | *val = dev_priv->rps.min_delay; | | 2444 | *val = dev_priv->rps.min_delay; |
2443 | limits |= dev_priv->rps.min_delay << 16; | | 2445 | limits |= dev_priv->rps.min_delay << 16; |
2444 | } | | 2446 | } |
2445 | | | 2447 | |
2446 | return limits; | | 2448 | return limits; |
2447 | } | | 2449 | } |
2448 | | | 2450 | |
2449 | void gen6_set_rps(struct drm_device *dev, u8 val) | | 2451 | void gen6_set_rps(struct drm_device *dev, u8 val) |
2450 | { | | 2452 | { |
2451 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2453 | struct drm_i915_private *dev_priv = dev->dev_private; |
2452 | u32 limits = gen6_rps_limits(dev_priv, &val); | | 2454 | u32 limits = gen6_rps_limits(dev_priv, &val); |
2453 | | | 2455 | |
2454 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | | 2456 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
2455 | WARN_ON(val > dev_priv->rps.max_delay); | | 2457 | WARN_ON(val > dev_priv->rps.max_delay); |
2456 | WARN_ON(val < dev_priv->rps.min_delay); | | 2458 | WARN_ON(val < dev_priv->rps.min_delay); |
2457 | | | 2459 | |
2458 | if (val == dev_priv->rps.cur_delay) | | 2460 | if (val == dev_priv->rps.cur_delay) |
2459 | return; | | 2461 | return; |
2460 | | | 2462 | |
2461 | I915_WRITE(GEN6_RPNSWREQ, | | 2463 | I915_WRITE(GEN6_RPNSWREQ, |
2462 | GEN6_FREQUENCY(val) | | | 2464 | GEN6_FREQUENCY(val) | |
2463 | GEN6_OFFSET(0) | | | 2465 | GEN6_OFFSET(0) | |
2464 | GEN6_AGGRESSIVE_TURBO); | | 2466 | GEN6_AGGRESSIVE_TURBO); |
2465 | | | 2467 | |
2466 | /* Make sure we continue to get interrupts | | 2468 | /* Make sure we continue to get interrupts |
2467 | * until we hit the minimum or maximum frequencies. | | 2469 | * until we hit the minimum or maximum frequencies. |
2468 | */ | | 2470 | */ |
2469 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); | | 2471 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); |
2470 | | | 2472 | |
2471 | POSTING_READ(GEN6_RPNSWREQ); | | 2473 | POSTING_READ(GEN6_RPNSWREQ); |
2472 | | | 2474 | |
2473 | dev_priv->rps.cur_delay = val; | | 2475 | dev_priv->rps.cur_delay = val; |
2474 | | | 2476 | |
2475 | trace_intel_gpu_freq_change(val * 50); | | 2477 | trace_intel_gpu_freq_change(val * 50); |
2476 | } | | 2478 | } |
2477 | | | 2479 | |
2478 | static void gen6_disable_rps(struct drm_device *dev) | | 2480 | static void gen6_disable_rps(struct drm_device *dev) |
2479 | { | | 2481 | { |
2480 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2482 | struct drm_i915_private *dev_priv = dev->dev_private; |
2481 | | | 2483 | |
2482 | I915_WRITE(GEN6_RC_CONTROL, 0); | | 2484 | I915_WRITE(GEN6_RC_CONTROL, 0); |
2483 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); | | 2485 | I915_WRITE(GEN6_RPNSWREQ, 1 << 31); |
2484 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); | | 2486 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); |
2485 | I915_WRITE(GEN6_PMIER, 0); | | 2487 | I915_WRITE(GEN6_PMIER, 0); |
2486 | /* Complete PM interrupt masking here doesn't race with the rps work | | 2488 | /* Complete PM interrupt masking here doesn't race with the rps work |
2487 | * item again unmasking PM interrupts because that is using a different | | 2489 | * item again unmasking PM interrupts because that is using a different |
2488 | * register (PMIMR) to mask PM interrupts. The only risk is in leaving | | 2490 | * register (PMIMR) to mask PM interrupts. The only risk is in leaving |
2489 | * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */ | | 2491 | * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */ |
2490 | | | 2492 | |
2491 | spin_lock_irq(&dev_priv->rps.lock); | | 2493 | spin_lock_irq(&dev_priv->rps.lock); |
2492 | dev_priv->rps.pm_iir = 0; | | 2494 | dev_priv->rps.pm_iir = 0; |
2493 | spin_unlock_irq(&dev_priv->rps.lock); | | 2495 | spin_unlock_irq(&dev_priv->rps.lock); |
2494 | | | 2496 | |
2495 | I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); | | 2497 | I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); |
2496 | } | | 2498 | } |
2497 | | | 2499 | |
2498 | int intel_enable_rc6(const struct drm_device *dev) | | 2500 | int intel_enable_rc6(const struct drm_device *dev) |
2499 | { | | 2501 | { |
2500 | /* Respect the kernel parameter if it is set */ | | 2502 | /* Respect the kernel parameter if it is set */ |
2501 | if (i915_enable_rc6 >= 0) | | 2503 | if (i915_enable_rc6 >= 0) |
2502 | return i915_enable_rc6; | | 2504 | return i915_enable_rc6; |
2503 | | | 2505 | |
2504 | /* Disable RC6 on Ironlake */ | | 2506 | /* Disable RC6 on Ironlake */ |
2505 | if (INTEL_INFO(dev)->gen == 5) | | 2507 | if (INTEL_INFO(dev)->gen == 5) |
2506 | return 0; | | 2508 | return 0; |
2507 | | | 2509 | |
2508 | if (IS_HASWELL(dev)) { | | 2510 | if (IS_HASWELL(dev)) { |
2509 | DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); | | 2511 | DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); |
2510 | return INTEL_RC6_ENABLE; | | 2512 | return INTEL_RC6_ENABLE; |
2511 | } | | 2513 | } |
2512 | | | 2514 | |
2513 | /* snb/ivb have more than one rc6 state. */ | | 2515 | /* snb/ivb have more than one rc6 state. */ |
2514 | if (INTEL_INFO(dev)->gen == 6) { | | 2516 | if (INTEL_INFO(dev)->gen == 6) { |
2515 | DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); | | 2517 | DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); |
2516 | return INTEL_RC6_ENABLE; | | 2518 | return INTEL_RC6_ENABLE; |
2517 | } | | 2519 | } |
2518 | | | 2520 | |
2519 | DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); | | 2521 | DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); |
2520 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); | | 2522 | return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); |
2521 | } | | 2523 | } |
2522 | | | 2524 | |
2523 | static void gen6_enable_rps(struct drm_device *dev) | | 2525 | static void gen6_enable_rps(struct drm_device *dev) |
2524 | { | | 2526 | { |
2525 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2527 | struct drm_i915_private *dev_priv = dev->dev_private; |
2526 | struct intel_ring_buffer *ring; | | 2528 | struct intel_ring_buffer *ring; |
2527 | u32 rp_state_cap; | | 2529 | u32 rp_state_cap; |
2528 | u32 gt_perf_status; | | 2530 | u32 gt_perf_status; |
2529 | u32 rc6vids, pcu_mbox, rc6_mask = 0; | | 2531 | u32 rc6vids, pcu_mbox, rc6_mask = 0; |
2530 | u32 gtfifodbg; | | 2532 | u32 gtfifodbg; |
2531 | int rc6_mode; | | 2533 | int rc6_mode; |
2532 | int i, ret; | | 2534 | int i, ret; |
2533 | | | 2535 | |
2534 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | | 2536 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
2535 | | | 2537 | |
2536 | /* Here begins a magic sequence of register writes to enable | | 2538 | /* Here begins a magic sequence of register writes to enable |
2537 | * auto-downclocking. | | 2539 | * auto-downclocking. |
2538 | * | | 2540 | * |
2539 | * Perhaps there might be some value in exposing these to | | 2541 | * Perhaps there might be some value in exposing these to |
2540 | * userspace... | | 2542 | * userspace... |
2541 | */ | | 2543 | */ |
2542 | I915_WRITE(GEN6_RC_STATE, 0); | | 2544 | I915_WRITE(GEN6_RC_STATE, 0); |
2543 | | | 2545 | |
2544 | /* Clear the DBG now so we don't confuse earlier errors */ | | 2546 | /* Clear the DBG now so we don't confuse earlier errors */ |
2545 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { | | 2547 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { |
2546 | DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); | | 2548 | DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); |
2547 | I915_WRITE(GTFIFODBG, gtfifodbg); | | 2549 | I915_WRITE(GTFIFODBG, gtfifodbg); |
2548 | } | | 2550 | } |
2549 | | | 2551 | |
2550 | gen6_gt_force_wake_get(dev_priv); | | 2552 | gen6_gt_force_wake_get(dev_priv); |
2551 | | | 2553 | |
2552 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | | 2554 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
2553 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | | 2555 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); |
2554 | | | 2556 | |
2555 | /* In units of 100MHz */ | | 2557 | /* In units of 100MHz */ |
2556 | dev_priv->rps.max_delay = rp_state_cap & 0xff; | | 2558 | dev_priv->rps.max_delay = rp_state_cap & 0xff; |
2557 | dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; | | 2559 | dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; |
2558 | dev_priv->rps.cur_delay = 0; | | 2560 | dev_priv->rps.cur_delay = 0; |
2559 | | | 2561 | |
2560 | /* disable the counters and set deterministic thresholds */ | | 2562 | /* disable the counters and set deterministic thresholds */ |
2561 | I915_WRITE(GEN6_RC_CONTROL, 0); | | 2563 | I915_WRITE(GEN6_RC_CONTROL, 0); |
2562 | | | 2564 | |
2563 | I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16); | | 2565 | I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16); |
2564 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); | | 2566 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); |
2565 | I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30); | | 2567 | I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30); |
2566 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); | | 2568 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); |
2567 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); | | 2569 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); |
2568 | | | 2570 | |
2569 | for_each_ring(ring, dev_priv, i) | | 2571 | for_each_ring(ring, dev_priv, i) |
2570 | I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); | | 2572 | I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); |
2571 | | | 2573 | |
2572 | I915_WRITE(GEN6_RC_SLEEP, 0); | | 2574 | I915_WRITE(GEN6_RC_SLEEP, 0); |
2573 | I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); | | 2575 | I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); |
2574 | I915_WRITE(GEN6_RC6_THRESHOLD, 50000); | | 2576 | I915_WRITE(GEN6_RC6_THRESHOLD, 50000); |
2575 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); | | 2577 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); |
2576 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ | | 2578 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ |
2577 | | | 2579 | |
2578 | /* Check if we are enabling RC6 */ | | 2580 | /* Check if we are enabling RC6 */ |
2579 | rc6_mode = intel_enable_rc6(dev_priv->dev); | | 2581 | rc6_mode = intel_enable_rc6(dev_priv->dev); |
2580 | if (rc6_mode & INTEL_RC6_ENABLE) | | 2582 | if (rc6_mode & INTEL_RC6_ENABLE) |
2581 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; | | 2583 | rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; |
2582 | | | 2584 | |
2583 | /* We don't use those on Haswell */ | | 2585 | /* We don't use those on Haswell */ |
2584 | if (!IS_HASWELL(dev)) { | | 2586 | if (!IS_HASWELL(dev)) { |
2585 | if (rc6_mode & INTEL_RC6p_ENABLE) | | 2587 | if (rc6_mode & INTEL_RC6p_ENABLE) |
2586 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; | | 2588 | rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; |
2587 | | | 2589 | |
2588 | if (rc6_mode & INTEL_RC6pp_ENABLE) | | 2590 | if (rc6_mode & INTEL_RC6pp_ENABLE) |
2589 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; | | 2591 | rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; |
2590 | } | | 2592 | } |
2591 | | | 2593 | |
2592 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", | | 2594 | DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", |
2593 | (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", | | 2595 | (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", |
2594 | (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", | | 2596 | (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", |
2595 | (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); | | 2597 | (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); |
2596 | | | 2598 | |
2597 | I915_WRITE(GEN6_RC_CONTROL, | | 2599 | I915_WRITE(GEN6_RC_CONTROL, |
2598 | rc6_mask | | | 2600 | rc6_mask | |
2599 | GEN6_RC_CTL_EI_MODE(1) | | | 2601 | GEN6_RC_CTL_EI_MODE(1) | |
2600 | GEN6_RC_CTL_HW_ENABLE); | | 2602 | GEN6_RC_CTL_HW_ENABLE); |
2601 | | | 2603 | |
2602 | I915_WRITE(GEN6_RPNSWREQ, | | 2604 | I915_WRITE(GEN6_RPNSWREQ, |
2603 | GEN6_FREQUENCY(10) | | | 2605 | GEN6_FREQUENCY(10) | |
2604 | GEN6_OFFSET(0) | | | 2606 | GEN6_OFFSET(0) | |
2605 | GEN6_AGGRESSIVE_TURBO); | | 2607 | GEN6_AGGRESSIVE_TURBO); |
2606 | I915_WRITE(GEN6_RC_VIDEO_FREQ, | | 2608 | I915_WRITE(GEN6_RC_VIDEO_FREQ, |
2607 | GEN6_FREQUENCY(12)); | | 2609 | GEN6_FREQUENCY(12)); |
2608 | | | 2610 | |
2609 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); | | 2611 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); |
2610 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | | 2612 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
2611 | dev_priv->rps.max_delay << 24 | | | 2613 | dev_priv->rps.max_delay << 24 | |
2612 | dev_priv->rps.min_delay << 16); | | 2614 | dev_priv->rps.min_delay << 16); |
2613 | | | 2615 | |
2614 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); | | 2616 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); |
2615 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); | | 2617 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); |
2616 | I915_WRITE(GEN6_RP_UP_EI, 66000); | | 2618 | I915_WRITE(GEN6_RP_UP_EI, 66000); |
2617 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); | | 2619 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); |
2618 | | | 2620 | |
2619 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | | 2621 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
2620 | I915_WRITE(GEN6_RP_CONTROL, | | 2622 | I915_WRITE(GEN6_RP_CONTROL, |
2621 | GEN6_RP_MEDIA_TURBO | | | 2623 | GEN6_RP_MEDIA_TURBO | |
2622 | GEN6_RP_MEDIA_HW_NORMAL_MODE | | | 2624 | GEN6_RP_MEDIA_HW_NORMAL_MODE | |
2623 | GEN6_RP_MEDIA_IS_GFX | | | 2625 | GEN6_RP_MEDIA_IS_GFX | |
2624 | GEN6_RP_ENABLE | | | 2626 | GEN6_RP_ENABLE | |
2625 | GEN6_RP_UP_BUSY_AVG | | | 2627 | GEN6_RP_UP_BUSY_AVG | |
2626 | (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); | | 2628 | (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); |
2627 | | | 2629 | |
2628 | ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); | | 2630 | ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); |
2629 | if (!ret) { | | 2631 | if (!ret) { |
2630 | pcu_mbox = 0; | | 2632 | pcu_mbox = 0; |
2631 | ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox); | | 2633 | ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox); |
2632 | if (ret && pcu_mbox & (1<<31)) { /* OC supported */ | | 2634 | if (ret && pcu_mbox & (1<<31)) { /* OC supported */ |
2633 | dev_priv->rps.max_delay = pcu_mbox & 0xff; | | 2635 | dev_priv->rps.max_delay = pcu_mbox & 0xff; |
2634 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); | | 2636 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); |
2635 | } | | 2637 | } |
2636 | } else { | | 2638 | } else { |
2637 | DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); | | 2639 | DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); |
2638 | } | | 2640 | } |
2639 | | | 2641 | |
2640 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); | | 2642 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); |
2641 | | | 2643 | |
2642 | /* requires MSI enabled */ | | 2644 | /* requires MSI enabled */ |
2643 | I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); | | 2645 | I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); |
2644 | spin_lock_irq(&dev_priv->rps.lock); | | 2646 | spin_lock_irq(&dev_priv->rps.lock); |
2645 | WARN_ON(dev_priv->rps.pm_iir != 0); | | 2647 | WARN_ON(dev_priv->rps.pm_iir != 0); |
2646 | I915_WRITE(GEN6_PMIMR, 0); | | 2648 | I915_WRITE(GEN6_PMIMR, 0); |
2647 | spin_unlock_irq(&dev_priv->rps.lock); | | 2649 | spin_unlock_irq(&dev_priv->rps.lock); |
2648 | /* enable all PM interrupts */ | | 2650 | /* enable all PM interrupts */ |
2649 | I915_WRITE(GEN6_PMINTRMSK, 0); | | 2651 | I915_WRITE(GEN6_PMINTRMSK, 0); |
2650 | | | 2652 | |
2651 | rc6vids = 0; | | 2653 | rc6vids = 0; |
2652 | ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); | | 2654 | ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); |
2653 | if (IS_GEN6(dev) && ret) { | | 2655 | if (IS_GEN6(dev) && ret) { |
2654 | DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n"); | | 2656 | DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n"); |
2655 | } else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) { | | 2657 | } else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) { |
2656 | DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n", | | 2658 | DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n", |
2657 | GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450); | | 2659 | GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450); |
2658 | rc6vids &= 0xffff00; | | 2660 | rc6vids &= 0xffff00; |
2659 | rc6vids |= GEN6_ENCODE_RC6_VID(450); | | 2661 | rc6vids |= GEN6_ENCODE_RC6_VID(450); |
2660 | ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids); | | 2662 | ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids); |
2661 | if (ret) | | 2663 | if (ret) |
2662 | DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); | | 2664 | DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); |
2663 | } | | 2665 | } |
2664 | | | 2666 | |
2665 | gen6_gt_force_wake_put(dev_priv); | | 2667 | gen6_gt_force_wake_put(dev_priv); |
2666 | } | | 2668 | } |
2667 | | | 2669 | |
2668 | static void gen6_update_ring_freq(struct drm_device *dev) | | 2670 | static void gen6_update_ring_freq(struct drm_device *dev) |
2669 | { | | 2671 | { |
2670 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2672 | struct drm_i915_private *dev_priv = dev->dev_private; |
2671 | int min_freq = 15; | | 2673 | int min_freq = 15; |
2672 | int gpu_freq; | | 2674 | int gpu_freq; |
2673 | unsigned int ia_freq, max_ia_freq; | | 2675 | unsigned int ia_freq, max_ia_freq; |
2674 | int scaling_factor = 180; | | 2676 | int scaling_factor = 180; |
2675 | | | 2677 | |
2676 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | | 2678 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
2677 | | | 2679 | |
2678 | max_ia_freq = cpufreq_quick_get_max(0); | | 2680 | max_ia_freq = cpufreq_quick_get_max(0); |
2679 | /* | | 2681 | /* |
2680 | * Default to measured freq if none found, PCU will ensure we don't go | | 2682 | * Default to measured freq if none found, PCU will ensure we don't go |
2681 | * over | | 2683 | * over |
2682 | */ | | 2684 | */ |
2683 | if (!max_ia_freq) | | 2685 | if (!max_ia_freq) |
2684 | max_ia_freq = tsc_khz; | | 2686 | max_ia_freq = tsc_khz; |
2685 | | | 2687 | |
2686 | /* Convert from kHz to MHz */ | | 2688 | /* Convert from kHz to MHz */ |
2687 | max_ia_freq /= 1000; | | 2689 | max_ia_freq /= 1000; |
2688 | | | 2690 | |
2689 | /* | | 2691 | /* |
2690 | * For each potential GPU frequency, load a ring frequency we'd like | | 2692 | * For each potential GPU frequency, load a ring frequency we'd like |
2691 | * to use for memory access. We do this by specifying the IA frequency | | 2693 | * to use for memory access. We do this by specifying the IA frequency |
2692 | * the PCU should use as a reference to determine the ring frequency. | | 2694 | * the PCU should use as a reference to determine the ring frequency. |
2693 | */ | | 2695 | */ |
2694 | for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay; | | 2696 | for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay; |
2695 | gpu_freq--) { | | 2697 | gpu_freq--) { |
2696 | int diff = dev_priv->rps.max_delay - gpu_freq; | | 2698 | int diff = dev_priv->rps.max_delay - gpu_freq; |
2697 | | | 2699 | |
2698 | /* | | 2700 | /* |
2699 | * For GPU frequencies less than 750MHz, just use the lowest | | 2701 | * For GPU frequencies less than 750MHz, just use the lowest |
2700 | * ring freq. | | 2702 | * ring freq. |
2701 | */ | | 2703 | */ |
2702 | if (gpu_freq < min_freq) | | 2704 | if (gpu_freq < min_freq) |
2703 | ia_freq = 800; | | 2705 | ia_freq = 800; |
2704 | else | | 2706 | else |
2705 | ia_freq = max_ia_freq - ((diff * scaling_factor) / 2); | | 2707 | ia_freq = max_ia_freq - ((diff * scaling_factor) / 2); |
2706 | ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100); | | 2708 | ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100); |
2707 | ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT; | | 2709 | ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT; |
2708 | | | 2710 | |
2709 | sandybridge_pcode_write(dev_priv, | | 2711 | sandybridge_pcode_write(dev_priv, |
2710 | GEN6_PCODE_WRITE_MIN_FREQ_TABLE, | | 2712 | GEN6_PCODE_WRITE_MIN_FREQ_TABLE, |
2711 | ia_freq | gpu_freq); | | 2713 | ia_freq | gpu_freq); |
2712 | } | | 2714 | } |
2713 | } | | 2715 | } |
2714 | | | 2716 | |
2715 | void ironlake_teardown_rc6(struct drm_device *dev) | | 2717 | void ironlake_teardown_rc6(struct drm_device *dev) |
2716 | { | | 2718 | { |
2717 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2719 | struct drm_i915_private *dev_priv = dev->dev_private; |
2718 | | | 2720 | |
2719 | if (dev_priv->ips.renderctx) { | | 2721 | if (dev_priv->ips.renderctx) { |
2720 | i915_gem_object_unpin(dev_priv->ips.renderctx); | | 2722 | i915_gem_object_unpin(dev_priv->ips.renderctx); |
2721 | drm_gem_object_unreference(&dev_priv->ips.renderctx->base); | | 2723 | drm_gem_object_unreference(&dev_priv->ips.renderctx->base); |
2722 | dev_priv->ips.renderctx = NULL; | | 2724 | dev_priv->ips.renderctx = NULL; |
2723 | } | | 2725 | } |
2724 | | | 2726 | |
2725 | if (dev_priv->ips.pwrctx) { | | 2727 | if (dev_priv->ips.pwrctx) { |
2726 | i915_gem_object_unpin(dev_priv->ips.pwrctx); | | 2728 | i915_gem_object_unpin(dev_priv->ips.pwrctx); |
2727 | drm_gem_object_unreference(&dev_priv->ips.pwrctx->base); | | 2729 | drm_gem_object_unreference(&dev_priv->ips.pwrctx->base); |
2728 | dev_priv->ips.pwrctx = NULL; | | 2730 | dev_priv->ips.pwrctx = NULL; |
2729 | } | | 2731 | } |
2730 | } | | 2732 | } |
2731 | | | 2733 | |
2732 | static void ironlake_disable_rc6(struct drm_device *dev) | | 2734 | static void ironlake_disable_rc6(struct drm_device *dev) |
2733 | { | | 2735 | { |
2734 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2736 | struct drm_i915_private *dev_priv = dev->dev_private; |
2735 | | | 2737 | |
2736 | if (I915_READ(PWRCTXA)) { | | 2738 | if (I915_READ(PWRCTXA)) { |
2737 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | | 2739 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ |
2738 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | | 2740 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); |
2739 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | | 2741 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), |
2740 | 50); | | 2742 | 50); |
2741 | | | 2743 | |
2742 | I915_WRITE(PWRCTXA, 0); | | 2744 | I915_WRITE(PWRCTXA, 0); |
2743 | POSTING_READ(PWRCTXA); | | 2745 | POSTING_READ(PWRCTXA); |
2744 | | | 2746 | |
2745 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | | 2747 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
2746 | POSTING_READ(RSTDBYCTL); | | 2748 | POSTING_READ(RSTDBYCTL); |
2747 | } | | 2749 | } |
2748 | } | | 2750 | } |
2749 | | | 2751 | |
2750 | static int ironlake_setup_rc6(struct drm_device *dev) | | 2752 | static int ironlake_setup_rc6(struct drm_device *dev) |
2751 | { | | 2753 | { |
2752 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2754 | struct drm_i915_private *dev_priv = dev->dev_private; |
2753 | | | 2755 | |
2754 | if (dev_priv->ips.renderctx == NULL) | | 2756 | if (dev_priv->ips.renderctx == NULL) |
2755 | dev_priv->ips.renderctx = intel_alloc_context_page(dev); | | 2757 | dev_priv->ips.renderctx = intel_alloc_context_page(dev); |
2756 | if (!dev_priv->ips.renderctx) | | 2758 | if (!dev_priv->ips.renderctx) |
2757 | return -ENOMEM; | | 2759 | return -ENOMEM; |
2758 | | | 2760 | |
2759 | if (dev_priv->ips.pwrctx == NULL) | | 2761 | if (dev_priv->ips.pwrctx == NULL) |
2760 | dev_priv->ips.pwrctx = intel_alloc_context_page(dev); | | 2762 | dev_priv->ips.pwrctx = intel_alloc_context_page(dev); |
2761 | if (!dev_priv->ips.pwrctx) { | | 2763 | if (!dev_priv->ips.pwrctx) { |
2762 | ironlake_teardown_rc6(dev); | | 2764 | ironlake_teardown_rc6(dev); |
2763 | return -ENOMEM; | | 2765 | return -ENOMEM; |
2764 | } | | 2766 | } |
2765 | | | 2767 | |
2766 | return 0; | | 2768 | return 0; |
2767 | } | | 2769 | } |
2768 | | | 2770 | |
2769 | static void ironlake_enable_rc6(struct drm_device *dev) | | 2771 | static void ironlake_enable_rc6(struct drm_device *dev) |
2770 | { | | 2772 | { |
2771 | struct drm_i915_private *dev_priv = dev->dev_private; | | 2773 | struct drm_i915_private *dev_priv = dev->dev_private; |
2772 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; | | 2774 | struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; |
2773 | bool was_interruptible; | | 2775 | bool was_interruptible; |
2774 | int ret; | | 2776 | int ret; |
2775 | | | 2777 | |
2776 | /* rc6 disabled by default due to repeated reports of hanging during | | 2778 | /* rc6 disabled by default due to repeated reports of hanging during |
2777 | * boot and resume. | | 2779 | * boot and resume. |
2778 | */ | | 2780 | */ |
2779 | if (!intel_enable_rc6(dev)) | | 2781 | if (!intel_enable_rc6(dev)) |
2780 | return; | | 2782 | return; |
2781 | | | 2783 | |
2782 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | | 2784 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
2783 | | | 2785 | |
2784 | ret = ironlake_setup_rc6(dev); | | 2786 | ret = ironlake_setup_rc6(dev); |
2785 | if (ret) | | 2787 | if (ret) |
2786 | return; | | 2788 | return; |
2787 | | | 2789 | |
2788 | was_interruptible = dev_priv->mm.interruptible; | | 2790 | was_interruptible = dev_priv->mm.interruptible; |
2789 | dev_priv->mm.interruptible = false; | | 2791 | dev_priv->mm.interruptible = false; |
2790 | | | 2792 | |
2791 | /* | | 2793 | /* |
2792 | * GPU can automatically power down the render unit if given a page | | 2794 | * GPU can automatically power down the render unit if given a page |
2793 | * to save state. | | 2795 | * to save state. |
2794 | */ | | 2796 | */ |
2795 | ret = intel_ring_begin(ring, 6); | | 2797 | ret = intel_ring_begin(ring, 6); |
2796 | if (ret) { | | 2798 | if (ret) { |
2797 | ironlake_teardown_rc6(dev); | | 2799 | ironlake_teardown_rc6(dev); |
2798 | dev_priv->mm.interruptible = was_interruptible; | | 2800 | dev_priv->mm.interruptible = was_interruptible; |
2799 | return; | | 2801 | return; |
2800 | } | | 2802 | } |
2801 | | | 2803 | |
2802 | intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); | | 2804 | intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); |
2803 | intel_ring_emit(ring, MI_SET_CONTEXT); | | 2805 | intel_ring_emit(ring, MI_SET_CONTEXT); |
2804 | intel_ring_emit(ring, dev_priv->ips.renderctx->gtt_offset | | | 2806 | intel_ring_emit(ring, dev_priv->ips.renderctx->gtt_offset | |
2805 | MI_MM_SPACE_GTT | | | 2807 | MI_MM_SPACE_GTT | |
2806 | MI_SAVE_EXT_STATE_EN | | | 2808 | MI_SAVE_EXT_STATE_EN | |
2807 | MI_RESTORE_EXT_STATE_EN | | | 2809 | MI_RESTORE_EXT_STATE_EN | |
2808 | MI_RESTORE_INHIBIT); | | 2810 | MI_RESTORE_INHIBIT); |
2809 | intel_ring_emit(ring, MI_SUSPEND_FLUSH); | | 2811 | intel_ring_emit(ring, MI_SUSPEND_FLUSH); |
2810 | intel_ring_emit(ring, MI_NOOP); | | 2812 | intel_ring_emit(ring, MI_NOOP); |
2811 | intel_ring_emit(ring, MI_FLUSH); | | 2813 | intel_ring_emit(ring, MI_FLUSH); |
2812 | intel_ring_advance(ring); | | 2814 | intel_ring_advance(ring); |
2813 | | | 2815 | |
2814 | /* | | 2816 | /* |
2815 | * Wait for the command parser to advance past MI_SET_CONTEXT. The HW | | 2817 | * Wait for the command parser to advance past MI_SET_CONTEXT. The HW |
2816 | * does an implicit flush, combined with MI_FLUSH above, it should be | | 2818 | * does an implicit flush, combined with MI_FLUSH above, it should be |
2817 | * safe to assume that renderctx is valid | | 2819 | * safe to assume that renderctx is valid |
2818 | */ | | 2820 | */ |
2819 | ret = intel_ring_idle(ring); | | 2821 | ret = intel_ring_idle(ring); |
2820 | dev_priv->mm.interruptible = was_interruptible; | | 2822 | dev_priv->mm.interruptible = was_interruptible; |
2821 | if (ret) { | | 2823 | if (ret) { |
2822 | DRM_ERROR("failed to enable ironlake power power savings\n"); | | 2824 | DRM_ERROR("failed to enable ironlake power power savings\n"); |
2823 | ironlake_teardown_rc6(dev); | | 2825 | ironlake_teardown_rc6(dev); |
2824 | return; | | 2826 | return; |
2825 | } | | 2827 | } |
2826 | | | 2828 | |
2827 | I915_WRITE(PWRCTXA, dev_priv->ips.pwrctx->gtt_offset | PWRCTX_EN); | | 2829 | I915_WRITE(PWRCTXA, dev_priv->ips.pwrctx->gtt_offset | PWRCTX_EN); |
2828 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | | 2830 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
2829 | } | | 2831 | } |
2830 | | | 2832 | |
2831 | static unsigned long intel_pxfreq(u32 vidfreq) | | 2833 | static unsigned long intel_pxfreq(u32 vidfreq) |
2832 | { | | 2834 | { |
2833 | unsigned long freq; | | 2835 | unsigned long freq; |
2834 | int div = (vidfreq & 0x3f0000) >> 16; | | 2836 | int div = (vidfreq & 0x3f0000) >> 16; |
2835 | int post = (vidfreq & 0x3000) >> 12; | | 2837 | int post = (vidfreq & 0x3000) >> 12; |
2836 | int pre = (vidfreq & 0x7); | | 2838 | int pre = (vidfreq & 0x7); |
2837 | | | 2839 | |
2838 | if (!pre) | | 2840 | if (!pre) |
2839 | return 0; | | 2841 | return 0; |
2840 | | | 2842 | |
2841 | freq = ((div * 133333) / ((1<<post) * pre)); | | 2843 | freq = ((div * 133333) / ((1<<post) * pre)); |
2842 | | | 2844 | |
2843 | return freq; | | 2845 | return freq; |
2844 | } | | 2846 | } |
2845 | | | 2847 | |
2846 | static const struct cparams { | | 2848 | static const struct cparams { |
2847 | u16 i; | | 2849 | u16 i; |
2848 | u16 t; | | 2850 | u16 t; |
2849 | u16 m; | | 2851 | u16 m; |
2850 | u16 c; | | 2852 | u16 c; |
2851 | } cparams[] = { | | 2853 | } cparams[] = { |
2852 | { 1, 1333, 301, 28664 }, | | 2854 | { 1, 1333, 301, 28664 }, |
2853 | { 1, 1066, 294, 24460 }, | | 2855 | { 1, 1066, 294, 24460 }, |
2854 | { 1, 800, 294, 25192 }, | | 2856 | { 1, 800, 294, 25192 }, |
2855 | { 0, 1333, 276, 27605 }, | | 2857 | { 0, 1333, 276, 27605 }, |
2856 | { 0, 1066, 276, 27605 }, | | 2858 | { 0, 1066, 276, 27605 }, |
2857 | { 0, 800, 231, 23784 }, | | 2859 | { 0, 800, 231, 23784 }, |
2858 | }; | | 2860 | }; |
2859 | | | 2861 | |
2860 | static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv) | | 2862 | static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv) |
2861 | { | | 2863 | { |
2862 | u64 total_count, diff, ret; | | 2864 | u64 total_count, diff, ret; |
2863 | u32 count1, count2, count3, m = 0, c = 0; | | 2865 | u32 count1, count2, count3, m = 0, c = 0; |
2864 | unsigned long now = jiffies_to_msecs(jiffies), diff1; | | 2866 | unsigned long now = jiffies_to_msecs(jiffies), diff1; |
2865 | int i; | | 2867 | int i; |
2866 | | | 2868 | |
2867 | assert_spin_locked(&mchdev_lock); | | 2869 | assert_spin_locked(&mchdev_lock); |
2868 | | | 2870 | |
2869 | diff1 = now - dev_priv->ips.last_time1; | | 2871 | diff1 = now - dev_priv->ips.last_time1; |
2870 | | | 2872 | |
2871 | /* Prevent division-by-zero if we are asking too fast. | | 2873 | /* Prevent division-by-zero if we are asking too fast. |
2872 | * Also, we don't get interesting results if we are polling | | 2874 | * Also, we don't get interesting results if we are polling |
2873 | * faster than once in 10ms, so just return the saved value | | 2875 | * faster than once in 10ms, so just return the saved value |
2874 | * in such cases. | | 2876 | * in such cases. |
2875 | */ | | 2877 | */ |
2876 | if (diff1 <= 10) | | 2878 | if (diff1 <= 10) |
2877 | return dev_priv->ips.chipset_power; | | 2879 | return dev_priv->ips.chipset_power; |
2878 | | | 2880 | |
2879 | count1 = I915_READ(DMIEC); | | 2881 | count1 = I915_READ(DMIEC); |
2880 | count2 = I915_READ(DDREC); | | 2882 | count2 = I915_READ(DDREC); |
2881 | count3 = I915_READ(CSIEC); | | 2883 | count3 = I915_READ(CSIEC); |
2882 | | | 2884 | |
2883 | total_count = count1 + count2 + count3; | | 2885 | total_count = count1 + count2 + count3; |
2884 | | | 2886 | |
2885 | /* FIXME: handle per-counter overflow */ | | 2887 | /* FIXME: handle per-counter overflow */ |
2886 | if (total_count < dev_priv->ips.last_count1) { | | 2888 | if (total_count < dev_priv->ips.last_count1) { |
2887 | diff = ~0UL - dev_priv->ips.last_count1; | | 2889 | diff = ~0UL - dev_priv->ips.last_count1; |
2888 | diff += total_count; | | 2890 | diff += total_count; |
2889 | } else { | | 2891 | } else { |
2890 | diff = total_count - dev_priv->ips.last_count1; | | 2892 | diff = total_count - dev_priv->ips.last_count1; |
2891 | } | | 2893 | } |
2892 | | | 2894 | |
2893 | for (i = 0; i < ARRAY_SIZE(cparams); i++) { | | 2895 | for (i = 0; i < ARRAY_SIZE(cparams); i++) { |
2894 | if (cparams[i].i == dev_priv->ips.c_m && | | 2896 | if (cparams[i].i == dev_priv->ips.c_m && |
2895 | cparams[i].t == dev_priv->ips.r_t) { | | 2897 | cparams[i].t == dev_priv->ips.r_t) { |
2896 | m = cparams[i].m; | | 2898 | m = cparams[i].m; |
2897 | c = cparams[i].c; | | 2899 | c = cparams[i].c; |
2898 | break; | | 2900 | break; |
2899 | } | | 2901 | } |
2900 | } | | 2902 | } |
2901 | | | 2903 | |
2902 | diff = div_u64(diff, diff1); | | 2904 | diff = div_u64(diff, diff1); |
2903 | ret = ((m * diff) + c); | | 2905 | ret = ((m * diff) + c); |
2904 | ret = div_u64(ret, 10); | | 2906 | ret = div_u64(ret, 10); |
2905 | | | 2907 | |
2906 | dev_priv->ips.last_count1 = total_count; | | 2908 | dev_priv->ips.last_count1 = total_count; |
2907 | dev_priv->ips.last_time1 = now; | | 2909 | dev_priv->ips.last_time1 = now; |
2908 | | | 2910 | |
2909 | dev_priv->ips.chipset_power = ret; | | 2911 | dev_priv->ips.chipset_power = ret; |
2910 | | | 2912 | |
2911 | return ret; | | 2913 | return ret; |
2912 | } | | 2914 | } |
2913 | | | 2915 | |
2914 | unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) | | 2916 | unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) |
2915 | { | | 2917 | { |
2916 | unsigned long val; | | 2918 | unsigned long val; |
2917 | | | 2919 | |
2918 | if (dev_priv->info->gen != 5) | | 2920 | if (dev_priv->info->gen != 5) |
2919 | return 0; | | 2921 | return 0; |
2920 | | | 2922 | |
2921 | spin_lock_irq(&mchdev_lock); | | 2923 | spin_lock_irq(&mchdev_lock); |
2922 | | | 2924 | |
2923 | val = __i915_chipset_val(dev_priv); | | 2925 | val = __i915_chipset_val(dev_priv); |
2924 | | | 2926 | |
2925 | spin_unlock_irq(&mchdev_lock); | | 2927 | spin_unlock_irq(&mchdev_lock); |
2926 | | | 2928 | |
2927 | return val; | | 2929 | return val; |
2928 | } | | 2930 | } |
2929 | | | 2931 | |
2930 | unsigned long i915_mch_val(struct drm_i915_private *dev_priv) | | 2932 | unsigned long i915_mch_val(struct drm_i915_private *dev_priv) |
2931 | { | | 2933 | { |
2932 | unsigned long m, x, b; | | 2934 | unsigned long m, x, b; |
2933 | u32 tsfs; | | 2935 | u32 tsfs; |
2934 | | | 2936 | |
2935 | tsfs = I915_READ(TSFS); | | 2937 | tsfs = I915_READ(TSFS); |
2936 | | | 2938 | |
2937 | m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT); | | 2939 | m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT); |
2938 | x = I915_READ8(TR1); | | 2940 | x = I915_READ8(TR1); |
2939 | | | 2941 | |
2940 | b = tsfs & TSFS_INTR_MASK; | | 2942 | b = tsfs & TSFS_INTR_MASK; |
2941 | | | 2943 | |
2942 | return ((m * x) / 127) - b; | | 2944 | return ((m * x) / 127) - b; |
2943 | } | | 2945 | } |
2944 | | | 2946 | |
2945 | static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) | | 2947 | static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) |
2946 | { | | 2948 | { |
2947 | static const struct v_table { | | 2949 | static const struct v_table { |
2948 | u16 vd; /* in .1 mil */ | | 2950 | u16 vd; /* in .1 mil */ |
2949 | u16 vm; /* in .1 mil */ | | 2951 | u16 vm; /* in .1 mil */ |
2950 | } v_table[] = { | | 2952 | } v_table[] = { |
2951 | { 0, 0, }, | | 2953 | { 0, 0, }, |
2952 | { 375, 0, }, | | 2954 | { 375, 0, }, |
2953 | { 500, 0, }, | | 2955 | { 500, 0, }, |
2954 | { 625, 0, }, | | 2956 | { 625, 0, }, |
2955 | { 750, 0, }, | | 2957 | { 750, 0, }, |
2956 | { 875, 0, }, | | 2958 | { 875, 0, }, |
2957 | { 1000, 0, }, | | 2959 | { 1000, 0, }, |
2958 | { 1125, 0, }, | | 2960 | { 1125, 0, }, |
2959 | { 4125, 3000, }, | | 2961 | { 4125, 3000, }, |
2960 | { 4125, 3000, }, | | 2962 | { 4125, 3000, }, |
2961 | { 4125, 3000, }, | | 2963 | { 4125, 3000, }, |
2962 | { 4125, 3000, }, | | 2964 | { 4125, 3000, }, |
2963 | { 4125, 3000, }, | | 2965 | { 4125, 3000, }, |
2964 | { 4125, 3000, }, | | 2966 | { 4125, 3000, }, |
2965 | { 4125, 3000, }, | | 2967 | { 4125, 3000, }, |
2966 | { 4125, 3000, }, | | 2968 | { 4125, 3000, }, |
2967 | { 4125, 3000, }, | | 2969 | { 4125, 3000, }, |
2968 | { 4125, 3000, }, | | 2970 | { 4125, 3000, }, |
2969 | { 4125, 3000, }, | | 2971 | { 4125, 3000, }, |
2970 | { 4125, 3000, }, | | 2972 | { 4125, 3000, }, |
2971 | { 4125, 3000, }, | | 2973 | { 4125, 3000, }, |
2972 | { 4125, 3000, }, | | 2974 | { 4125, 3000, }, |
2973 | { 4125, 3000, }, | | 2975 | { 4125, 3000, }, |
2974 | { 4125, 3000, }, | | 2976 | { 4125, 3000, }, |
2975 | { 4125, 3000, }, | | 2977 | { 4125, 3000, }, |
2976 | { 4125, 3000, }, | | 2978 | { 4125, 3000, }, |
2977 | { 4125, 3000, }, | | 2979 | { 4125, 3000, }, |
2978 | { 4125, 3000, }, | | 2980 | { 4125, 3000, }, |
2979 | { 4125, 3000, }, | | 2981 | { 4125, 3000, }, |
2980 | { 4125, 3000, }, | | 2982 | { 4125, 3000, }, |
2981 | { 4125, 3000, }, | | 2983 | { 4125, 3000, }, |
2982 | { 4125, 3000, }, | | 2984 | { 4125, 3000, }, |
2983 | { 4250, 3125, }, | | 2985 | { 4250, 3125, }, |
2984 | { 4375, 3250, }, | | 2986 | { 4375, 3250, }, |
2985 | { 4500, 3375, }, | | 2987 | { 4500, 3375, }, |
2986 | { 4625, 3500, }, | | 2988 | { 4625, 3500, }, |
2987 | { 4750, 3625, }, | | 2989 | { 4750, 3625, }, |
2988 | { 4875, 3750, }, | | 2990 | { 4875, 3750, }, |
2989 | { 5000, 3875, }, | | 2991 | { 5000, 3875, }, |
2990 | { 5125, 4000, }, | | 2992 | { 5125, 4000, }, |
2991 | { 5250, 4125, }, | | 2993 | { 5250, 4125, }, |
2992 | { 5375, 4250, }, | | 2994 | { 5375, 4250, }, |
2993 | { 5500, 4375, }, | | 2995 | { 5500, 4375, }, |
2994 | { 5625, 4500, }, | | 2996 | { 5625, 4500, }, |
2995 | { 5750, 4625, }, | | 2997 | { 5750, 4625, }, |
2996 | { 5875, 4750, }, | | 2998 | { 5875, 4750, }, |
2997 | { 6000, 4875, }, | | 2999 | { 6000, 4875, }, |
2998 | { 6125, 5000, }, | | 3000 | { 6125, 5000, }, |
2999 | { 6250, 5125, }, | | 3001 | { 6250, 5125, }, |
3000 | { 6375, 5250, }, | | 3002 | { 6375, 5250, }, |
3001 | { 6500, 5375, }, | | 3003 | { 6500, 5375, }, |
3002 | { 6625, 5500, }, | | 3004 | { 6625, 5500, }, |
3003 | { 6750, 5625, }, | | 3005 | { 6750, 5625, }, |
3004 | { 6875, 5750, }, | | 3006 | { 6875, 5750, }, |
3005 | { 7000, 5875, }, | | 3007 | { 7000, 5875, }, |
3006 | { 7125, 6000, }, | | 3008 | { 7125, 6000, }, |
3007 | { 7250, 6125, }, | | 3009 | { 7250, 6125, }, |
3008 | { 7375, 6250, }, | | 3010 | { 7375, 6250, }, |
3009 | { 7500, 6375, }, | | 3011 | { 7500, 6375, }, |
3010 | { 7625, 6500, }, | | 3012 | { 7625, 6500, }, |
3011 | { 7750, 6625, }, | | 3013 | { 7750, 6625, }, |
3012 | { 7875, 6750, }, | | 3014 | { 7875, 6750, }, |
3013 | { 8000, 6875, }, | | 3015 | { 8000, 6875, }, |
3014 | { 8125, 7000, }, | | 3016 | { 8125, 7000, }, |
3015 | { 8250, 7125, }, | | 3017 | { 8250, 7125, }, |
3016 | { 8375, 7250, }, | | 3018 | { 8375, 7250, }, |
3017 | { 8500, 7375, }, | | 3019 | { 8500, 7375, }, |
3018 | { 8625, 7500, }, | | 3020 | { 8625, 7500, }, |
3019 | { 8750, 7625, }, | | 3021 | { 8750, 7625, }, |
3020 | { 8875, 7750, }, | | 3022 | { 8875, 7750, }, |
3021 | { 9000, 7875, }, | | 3023 | { 9000, 7875, }, |
3022 | { 9125, 8000, }, | | 3024 | { 9125, 8000, }, |
3023 | { 9250, 8125, }, | | 3025 | { 9250, 8125, }, |
3024 | { 9375, 8250, }, | | 3026 | { 9375, 8250, }, |
3025 | { 9500, 8375, }, | | 3027 | { 9500, 8375, }, |
3026 | { 9625, 8500, }, | | 3028 | { 9625, 8500, }, |
3027 | { 9750, 8625, }, | | 3029 | { 9750, 8625, }, |
3028 | { 9875, 8750, }, | | 3030 | { 9875, 8750, }, |
3029 | { 10000, 8875, }, | | 3031 | { 10000, 8875, }, |
3030 | { 10125, 9000, }, | | 3032 | { 10125, 9000, }, |
3031 | { 10250, 9125, }, | | 3033 | { 10250, 9125, }, |
3032 | { 10375, 9250, }, | | 3034 | { 10375, 9250, }, |
3033 | { 10500, 9375, }, | | 3035 | { 10500, 9375, }, |
3034 | { 10625, 9500, }, | | 3036 | { 10625, 9500, }, |
3035 | { 10750, 9625, }, | | 3037 | { 10750, 9625, }, |
3036 | { 10875, 9750, }, | | 3038 | { 10875, 9750, }, |
3037 | { 11000, 9875, }, | | 3039 | { 11000, 9875, }, |
3038 | { 11125, 10000, }, | | 3040 | { 11125, 10000, }, |
3039 | { 11250, 10125, }, | | 3041 | { 11250, 10125, }, |
3040 | { 11375, 10250, }, | | 3042 | { 11375, 10250, }, |
3041 | { 11500, 10375, }, | | 3043 | { 11500, 10375, }, |
3042 | { 11625, 10500, }, | | 3044 | { 11625, 10500, }, |
3043 | { 11750, 10625, }, | | 3045 | { 11750, 10625, }, |
3044 | { 11875, 10750, }, | | 3046 | { 11875, 10750, }, |
3045 | { 12000, 10875, }, | | 3047 | { 12000, 10875, }, |
3046 | { 12125, 11000, }, | | 3048 | { 12125, 11000, }, |
3047 | { 12250, 11125, }, | | 3049 | { 12250, 11125, }, |
3048 | { 12375, 11250, }, | | 3050 | { 12375, 11250, }, |
3049 | { 12500, 11375, }, | | 3051 | { 12500, 11375, }, |
3050 | { 12625, 11500, }, | | 3052 | { 12625, 11500, }, |
3051 | { 12750, 11625, }, | | 3053 | { 12750, 11625, }, |
3052 | { 12875, 11750, }, | | 3054 | { 12875, 11750, }, |
3053 | { 13000, 11875, }, | | 3055 | { 13000, 11875, }, |
3054 | { 13125, 12000, }, | | 3056 | { 13125, 12000, }, |
3055 | { 13250, 12125, }, | | 3057 | { 13250, 12125, }, |
3056 | { 13375, 12250, }, | | 3058 | { 13375, 12250, }, |
3057 | { 13500, 12375, }, | | 3059 | { 13500, 12375, }, |
3058 | { 13625, 12500, }, | | 3060 | { 13625, 12500, }, |
3059 | { 13750, 12625, }, | | 3061 | { 13750, 12625, }, |
3060 | { 13875, 12750, }, | | 3062 | { 13875, 12750, }, |
3061 | { 14000, 12875, }, | | 3063 | { 14000, 12875, }, |
3062 | { 14125, 13000, }, | | 3064 | { 14125, 13000, }, |
3063 | { 14250, 13125, }, | | 3065 | { 14250, 13125, }, |
3064 | { 14375, 13250, }, | | 3066 | { 14375, 13250, }, |
3065 | { 14500, 13375, }, | | 3067 | { 14500, 13375, }, |
3066 | { 14625, 13500, }, | | 3068 | { 14625, 13500, }, |
3067 | { 14750, 13625, }, | | 3069 | { 14750, 13625, }, |
3068 | { 14875, 13750, }, | | 3070 | { 14875, 13750, }, |
3069 | { 15000, 13875, }, | | 3071 | { 15000, 13875, }, |
3070 | { 15125, 14000, }, | | 3072 | { 15125, 14000, }, |
3071 | { 15250, 14125, }, | | 3073 | { 15250, 14125, }, |
3072 | { 15375, 14250, }, | | 3074 | { 15375, 14250, }, |
3073 | { 15500, 14375, }, | | 3075 | { 15500, 14375, }, |
3074 | { 15625, 14500, }, | | 3076 | { 15625, 14500, }, |
3075 | { 15750, 14625, }, | | 3077 | { 15750, 14625, }, |
3076 | { 15875, 14750, }, | | 3078 | { 15875, 14750, }, |
3077 | { 16000, 14875, }, | | 3079 | { 16000, 14875, }, |
3078 | { 16125, 15000, }, | | 3080 | { 16125, 15000, }, |
3079 | }; | | 3081 | }; |
3080 | if (dev_priv->info->is_mobile) | | 3082 | if (dev_priv->info->is_mobile) |
3081 | return v_table[pxvid].vm; | | 3083 | return v_table[pxvid].vm; |
3082 | else | | 3084 | else |
3083 | return v_table[pxvid].vd; | | 3085 | return v_table[pxvid].vd; |
3084 | } | | 3086 | } |
3085 | | | 3087 | |
3086 | static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) | | 3088 | static void __i915_update_gfx_val(struct drm_i915_private *dev_priv) |
3087 | { | | 3089 | { |
3088 | struct timespec now, diff1; | | 3090 | struct timespec now, diff1; |
3089 | u64 diff; | | 3091 | u64 diff; |
3090 | unsigned long diffms; | | 3092 | unsigned long diffms; |
3091 | u32 count; | | 3093 | u32 count; |
3092 | | | 3094 | |
3093 | assert_spin_locked(&mchdev_lock); | | 3095 | assert_spin_locked(&mchdev_lock); |
3094 | | | 3096 | |
3095 | getrawmonotonic(&now); | | 3097 | getrawmonotonic(&now); |
3096 | diff1 = timespec_sub(now, dev_priv->ips.last_time2); | | 3098 | diff1 = timespec_sub(now, dev_priv->ips.last_time2); |
3097 | | | 3099 | |
3098 | /* Don't divide by 0 */ | | 3100 | /* Don't divide by 0 */ |
3099 | diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000; | | 3101 | diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000; |
3100 | if (!diffms) | | 3102 | if (!diffms) |
3101 | return; | | 3103 | return; |
3102 | | | 3104 | |
3103 | count = I915_READ(GFXEC); | | 3105 | count = I915_READ(GFXEC); |
3104 | | | 3106 | |
3105 | if (count < dev_priv->ips.last_count2) { | | 3107 | if (count < dev_priv->ips.last_count2) { |
3106 | diff = ~0UL - dev_priv->ips.last_count2; | | 3108 | diff = ~0UL - dev_priv->ips.last_count2; |
3107 | diff += count; | | 3109 | diff += count; |
3108 | } else { | | 3110 | } else { |
3109 | diff = count - dev_priv->ips.last_count2; | | 3111 | diff = count - dev_priv->ips.last_count2; |
3110 | } | | 3112 | } |
3111 | | | 3113 | |
3112 | dev_priv->ips.last_count2 = count; | | 3114 | dev_priv->ips.last_count2 = count; |
3113 | dev_priv->ips.last_time2 = now; | | 3115 | dev_priv->ips.last_time2 = now; |
3114 | | | 3116 | |
3115 | /* More magic constants... */ | | 3117 | /* More magic constants... */ |
3116 | diff = diff * 1181; | | 3118 | diff = diff * 1181; |
3117 | diff = div_u64(diff, diffms * 10); | | 3119 | diff = div_u64(diff, diffms * 10); |
3118 | dev_priv->ips.gfx_power = diff; | | 3120 | dev_priv->ips.gfx_power = diff; |
3119 | } | | 3121 | } |
3120 | | | 3122 | |
3121 | void i915_update_gfx_val(struct drm_i915_private *dev_priv) | | 3123 | void i915_update_gfx_val(struct drm_i915_private *dev_priv) |
3122 | { | | 3124 | { |
3123 | if (dev_priv->info->gen != 5) | | 3125 | if (dev_priv->info->gen != 5) |
3124 | return; | | 3126 | return; |
3125 | | | 3127 | |
3126 | spin_lock_irq(&mchdev_lock); | | 3128 | spin_lock_irq(&mchdev_lock); |
3127 | | | 3129 | |
3128 | __i915_update_gfx_val(dev_priv); | | 3130 | __i915_update_gfx_val(dev_priv); |
3129 | | | 3131 | |
3130 | spin_unlock_irq(&mchdev_lock); | | 3132 | spin_unlock_irq(&mchdev_lock); |
3131 | } | | 3133 | } |
3132 | | | 3134 | |
3133 | static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) | | 3135 | static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) |
3134 | { | | 3136 | { |
3135 | unsigned long t, corr, state1, corr2, state2; | | 3137 | unsigned long t, corr, state1, corr2, state2; |
3136 | u32 pxvid, ext_v; | | 3138 | u32 pxvid, ext_v; |
3137 | | | 3139 | |
3138 | assert_spin_locked(&mchdev_lock); | | 3140 | assert_spin_locked(&mchdev_lock); |
3139 | | | 3141 | |
3140 | pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4)); | | 3142 | pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4)); |
3141 | pxvid = (pxvid >> 24) & 0x7f; | | 3143 | pxvid = (pxvid >> 24) & 0x7f; |
3142 | ext_v = pvid_to_extvid(dev_priv, pxvid); | | 3144 | ext_v = pvid_to_extvid(dev_priv, pxvid); |
3143 | | | 3145 | |
3144 | state1 = ext_v; | | 3146 | state1 = ext_v; |
3145 | | | 3147 | |
3146 | t = i915_mch_val(dev_priv); | | 3148 | t = i915_mch_val(dev_priv); |
3147 | | | 3149 | |
3148 | /* Revel in the empirically derived constants */ | | 3150 | /* Revel in the empirically derived constants */ |
3149 | | | 3151 | |
3150 | /* Correction factor in 1/100000 units */ | | 3152 | /* Correction factor in 1/100000 units */ |
3151 | if (t > 80) | | 3153 | if (t > 80) |
3152 | corr = ((t * 2349) + 135940); | | 3154 | corr = ((t * 2349) + 135940); |
3153 | else if (t >= 50) | | 3155 | else if (t >= 50) |
3154 | corr = ((t * 964) + 29317); | | 3156 | corr = ((t * 964) + 29317); |
3155 | else /* < 50 */ | | 3157 | else /* < 50 */ |
3156 | corr = ((t * 301) + 1004); | | 3158 | corr = ((t * 301) + 1004); |
3157 | | | 3159 | |
3158 | corr = corr * ((150142 * state1) / 10000 - 78642); | | 3160 | corr = corr * ((150142 * state1) / 10000 - 78642); |
3159 | corr /= 100000; | | 3161 | corr /= 100000; |
3160 | corr2 = (corr * dev_priv->ips.corr); | | 3162 | corr2 = (corr * dev_priv->ips.corr); |
3161 | | | 3163 | |
3162 | state2 = (corr2 * state1) / 10000; | | 3164 | state2 = (corr2 * state1) / 10000; |
3163 | state2 /= 100; /* convert to mW */ | | 3165 | state2 /= 100; /* convert to mW */ |
3164 | | | 3166 | |
3165 | __i915_update_gfx_val(dev_priv); | | 3167 | __i915_update_gfx_val(dev_priv); |
3166 | | | 3168 | |
3167 | return dev_priv->ips.gfx_power + state2; | | 3169 | return dev_priv->ips.gfx_power + state2; |
3168 | } | | 3170 | } |
3169 | | | 3171 | |
3170 | unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) | | 3172 | unsigned long i915_gfx_val(struct drm_i915_private *dev_priv) |
3171 | { | | 3173 | { |
3172 | unsigned long val; | | 3174 | unsigned long val; |
3173 | | | 3175 | |
3174 | if (dev_priv->info->gen != 5) | | 3176 | if (dev_priv->info->gen != 5) |
3175 | return 0; | | 3177 | return 0; |
3176 | | | 3178 | |
3177 | spin_lock_irq(&mchdev_lock); | | 3179 | spin_lock_irq(&mchdev_lock); |
3178 | | | 3180 | |
3179 | val = __i915_gfx_val(dev_priv); | | 3181 | val = __i915_gfx_val(dev_priv); |
3180 | | | 3182 | |
3181 | spin_unlock_irq(&mchdev_lock); | | 3183 | spin_unlock_irq(&mchdev_lock); |
3182 | | | 3184 | |
3183 | return val; | | 3185 | return val; |
3184 | } | | 3186 | } |
3185 | | | 3187 | |
3186 | /** | | 3188 | /** |
3187 | * i915_read_mch_val - return value for IPS use | | 3189 | * i915_read_mch_val - return value for IPS use |
3188 | * | | 3190 | * |
3189 | * Calculate and return a value for the IPS driver to use when deciding whether | | 3191 | * Calculate and return a value for the IPS driver to use when deciding whether |
3190 | * we have thermal and power headroom to increase CPU or GPU power budget. | | 3192 | * we have thermal and power headroom to increase CPU or GPU power budget. |
3191 | */ | | 3193 | */ |
3192 | unsigned long i915_read_mch_val(void) | | 3194 | unsigned long i915_read_mch_val(void) |
3193 | { | | 3195 | { |
3194 | struct drm_i915_private *dev_priv; | | 3196 | struct drm_i915_private *dev_priv; |
3195 | unsigned long chipset_val, graphics_val, ret = 0; | | 3197 | unsigned long chipset_val, graphics_val, ret = 0; |
3196 | | | 3198 | |
3197 | spin_lock_irq(&mchdev_lock); | | 3199 | spin_lock_irq(&mchdev_lock); |
3198 | if (!i915_mch_dev) | | 3200 | if (!i915_mch_dev) |
3199 | goto out_unlock; | | 3201 | goto out_unlock; |
3200 | dev_priv = i915_mch_dev; | | 3202 | dev_priv = i915_mch_dev; |
3201 | | | 3203 | |
3202 | chipset_val = __i915_chipset_val(dev_priv); | | 3204 | chipset_val = __i915_chipset_val(dev_priv); |
3203 | graphics_val = __i915_gfx_val(dev_priv); | | 3205 | graphics_val = __i915_gfx_val(dev_priv); |
3204 | | | 3206 | |
3205 | ret = chipset_val + graphics_val; | | 3207 | ret = chipset_val + graphics_val; |
3206 | | | 3208 | |
3207 | out_unlock: | | 3209 | out_unlock: |
3208 | spin_unlock_irq(&mchdev_lock); | | 3210 | spin_unlock_irq(&mchdev_lock); |
3209 | | | 3211 | |
3210 | return ret; | | 3212 | return ret; |
3211 | } | | 3213 | } |
3212 | EXPORT_SYMBOL_GPL(i915_read_mch_val); | | 3214 | EXPORT_SYMBOL_GPL(i915_read_mch_val); |
3213 | | | 3215 | |
3214 | /** | | 3216 | /** |
3215 | * i915_gpu_raise - raise GPU frequency limit | | 3217 | * i915_gpu_raise - raise GPU frequency limit |
3216 | * | | 3218 | * |
3217 | * Raise the limit; IPS indicates we have thermal headroom. | | 3219 | * Raise the limit; IPS indicates we have thermal headroom. |
3218 | */ | | 3220 | */ |
3219 | bool i915_gpu_raise(void) | | 3221 | bool i915_gpu_raise(void) |
3220 | { | | 3222 | { |
3221 | struct drm_i915_private *dev_priv; | | 3223 | struct drm_i915_private *dev_priv; |
3222 | bool ret = true; | | 3224 | bool ret = true; |
3223 | | | 3225 | |
3224 | spin_lock_irq(&mchdev_lock); | | 3226 | spin_lock_irq(&mchdev_lock); |
3225 | if (!i915_mch_dev) { | | 3227 | if (!i915_mch_dev) { |
3226 | ret = false; | | 3228 | ret = false; |
3227 | goto out_unlock; | | 3229 | goto out_unlock; |
3228 | } | | 3230 | } |
3229 | dev_priv = i915_mch_dev; | | 3231 | dev_priv = i915_mch_dev; |
3230 | | | 3232 | |
3231 | if (dev_priv->ips.max_delay > dev_priv->ips.fmax) | | 3233 | if (dev_priv->ips.max_delay > dev_priv->ips.fmax) |
3232 | dev_priv->ips.max_delay--; | | 3234 | dev_priv->ips.max_delay--; |
3233 | | | 3235 | |
3234 | out_unlock: | | 3236 | out_unlock: |
3235 | spin_unlock_irq(&mchdev_lock); | | 3237 | spin_unlock_irq(&mchdev_lock); |
3236 | | | 3238 | |
3237 | return ret; | | 3239 | return ret; |
3238 | } | | 3240 | } |
3239 | EXPORT_SYMBOL_GPL(i915_gpu_raise); | | 3241 | EXPORT_SYMBOL_GPL(i915_gpu_raise); |
3240 | | | 3242 | |
3241 | /** | | 3243 | /** |
3242 | * i915_gpu_lower - lower GPU frequency limit | | 3244 | * i915_gpu_lower - lower GPU frequency limit |
3243 | * | | 3245 | * |
3244 | * IPS indicates we're close to a thermal limit, so throttle back the GPU | | 3246 | * IPS indicates we're close to a thermal limit, so throttle back the GPU |
3245 | * frequency maximum. | | 3247 | * frequency maximum. |
3246 | */ | | 3248 | */ |
3247 | bool i915_gpu_lower(void) | | 3249 | bool i915_gpu_lower(void) |
3248 | { | | 3250 | { |
3249 | struct drm_i915_private *dev_priv; | | 3251 | struct drm_i915_private *dev_priv; |
3250 | bool ret = true; | | 3252 | bool ret = true; |
3251 | | | 3253 | |
3252 | spin_lock_irq(&mchdev_lock); | | 3254 | spin_lock_irq(&mchdev_lock); |
3253 | if (!i915_mch_dev) { | | 3255 | if (!i915_mch_dev) { |
3254 | ret = false; | | 3256 | ret = false; |
3255 | goto out_unlock; | | 3257 | goto out_unlock; |
3256 | } | | 3258 | } |
3257 | dev_priv = i915_mch_dev; | | 3259 | dev_priv = i915_mch_dev; |
3258 | | | 3260 | |
3259 | if (dev_priv->ips.max_delay < dev_priv->ips.min_delay) | | 3261 | if (dev_priv->ips.max_delay < dev_priv->ips.min_delay) |
3260 | dev_priv->ips.max_delay++; | | 3262 | dev_priv->ips.max_delay++; |
3261 | | | 3263 | |
3262 | out_unlock: | | 3264 | out_unlock: |
3263 | spin_unlock_irq(&mchdev_lock); | | 3265 | spin_unlock_irq(&mchdev_lock); |
3264 | | | 3266 | |
3265 | return ret; | | 3267 | return ret; |
3266 | } | | 3268 | } |
3267 | EXPORT_SYMBOL_GPL(i915_gpu_lower); | | 3269 | EXPORT_SYMBOL_GPL(i915_gpu_lower); |
3268 | | | 3270 | |
3269 | /** | | 3271 | /** |
3270 | * i915_gpu_busy - indicate GPU business to IPS | | 3272 | * i915_gpu_busy - indicate GPU business to IPS |
3271 | * | | 3273 | * |
3272 | * Tell the IPS driver whether or not the GPU is busy. | | 3274 | * Tell the IPS driver whether or not the GPU is busy. |
3273 | */ | | 3275 | */ |
3274 | bool i915_gpu_busy(void) | | 3276 | bool i915_gpu_busy(void) |
3275 | { | | 3277 | { |
3276 | struct drm_i915_private *dev_priv; | | 3278 | struct drm_i915_private *dev_priv; |
3277 | struct intel_ring_buffer *ring; | | 3279 | struct intel_ring_buffer *ring; |
3278 | bool ret = false; | | 3280 | bool ret = false; |
3279 | int i; | | 3281 | int i; |
3280 | | | 3282 | |
3281 | spin_lock_irq(&mchdev_lock); | | 3283 | spin_lock_irq(&mchdev_lock); |
3282 | if (!i915_mch_dev) | | 3284 | if (!i915_mch_dev) |
3283 | goto out_unlock; | | 3285 | goto out_unlock; |
3284 | dev_priv = i915_mch_dev; | | 3286 | dev_priv = i915_mch_dev; |
3285 | | | 3287 | |
3286 | for_each_ring(ring, dev_priv, i) | | 3288 | for_each_ring(ring, dev_priv, i) |
3287 | ret |= !list_empty(&ring->request_list); | | 3289 | ret |= !list_empty(&ring->request_list); |
3288 | | | 3290 | |
3289 | out_unlock: | | 3291 | out_unlock: |
3290 | spin_unlock_irq(&mchdev_lock); | | 3292 | spin_unlock_irq(&mchdev_lock); |
3291 | | | 3293 | |
3292 | return ret; | | 3294 | return ret; |
3293 | } | | 3295 | } |
3294 | EXPORT_SYMBOL_GPL(i915_gpu_busy); | | 3296 | EXPORT_SYMBOL_GPL(i915_gpu_busy); |
3295 | | | 3297 | |
3296 | /** | | 3298 | /** |
3297 | * i915_gpu_turbo_disable - disable graphics turbo | | 3299 | * i915_gpu_turbo_disable - disable graphics turbo |
3298 | * | | 3300 | * |
3299 | * Disable graphics turbo by resetting the max frequency and setting the | | 3301 | * Disable graphics turbo by resetting the max frequency and setting the |
3300 | * current frequency to the default. | | 3302 | * current frequency to the default. |
3301 | */ | | 3303 | */ |
3302 | bool i915_gpu_turbo_disable(void) | | 3304 | bool i915_gpu_turbo_disable(void) |
3303 | { | | 3305 | { |
3304 | struct drm_i915_private *dev_priv; | | 3306 | struct drm_i915_private *dev_priv; |
3305 | bool ret = true; | | 3307 | bool ret = true; |
3306 | | | 3308 | |
3307 | spin_lock_irq(&mchdev_lock); | | 3309 | spin_lock_irq(&mchdev_lock); |
3308 | if (!i915_mch_dev) { | | 3310 | if (!i915_mch_dev) { |
3309 | ret = false; | | 3311 | ret = false; |
3310 | goto out_unlock; | | 3312 | goto out_unlock; |
3311 | } | | 3313 | } |
3312 | dev_priv = i915_mch_dev; | | 3314 | dev_priv = i915_mch_dev; |
3313 | | | 3315 | |
3314 | dev_priv->ips.max_delay = dev_priv->ips.fstart; | | 3316 | dev_priv->ips.max_delay = dev_priv->ips.fstart; |
3315 | | | 3317 | |
3316 | if (!ironlake_set_drps(dev_priv->dev, dev_priv->ips.fstart)) | | 3318 | if (!ironlake_set_drps(dev_priv->dev, dev_priv->ips.fstart)) |
3317 | ret = false; | | 3319 | ret = false; |
3318 | | | 3320 | |
3319 | out_unlock: | | 3321 | out_unlock: |
3320 | spin_unlock_irq(&mchdev_lock); | | 3322 | spin_unlock_irq(&mchdev_lock); |
3321 | | | 3323 | |
3322 | return ret; | | 3324 | return ret; |
3323 | } | | 3325 | } |
3324 | EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); | | 3326 | EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); |
3325 | | | 3327 | |
3326 | /** | | 3328 | /** |
3327 | * Tells the intel_ips driver that the i915 driver is now loaded, if | | 3329 | * Tells the intel_ips driver that the i915 driver is now loaded, if |
3328 | * IPS got loaded first. | | 3330 | * IPS got loaded first. |
3329 | * | | 3331 | * |
3330 | * This awkward dance is so that neither module has to depend on the | | 3332 | * This awkward dance is so that neither module has to depend on the |
3331 | * other in order for IPS to do the appropriate communication of | | 3333 | * other in order for IPS to do the appropriate communication of |
3332 | * GPU turbo limits to i915. | | 3334 | * GPU turbo limits to i915. |
3333 | */ | | 3335 | */ |
3334 | static void | | 3336 | static void |
3335 | ips_ping_for_i915_load(void) | | 3337 | ips_ping_for_i915_load(void) |
3336 | { | | 3338 | { |
| | | 3339 | #ifndef __NetBSD__ /* XXX whattakludge for Linux module mania */ |
3337 | void (*link)(void); | | 3340 | void (*link)(void); |
3338 | | | 3341 | |
3339 | link = symbol_get(ips_link_to_i915_driver); | | 3342 | link = symbol_get(ips_link_to_i915_driver); |
3340 | if (link) { | | 3343 | if (link) { |
3341 | link(); | | 3344 | link(); |
3342 | symbol_put(ips_link_to_i915_driver); | | 3345 | symbol_put(ips_link_to_i915_driver); |
3343 | } | | 3346 | } |
| | | 3347 | #endif |
3344 | } | | 3348 | } |
3345 | | | 3349 | |
3346 | void intel_gpu_ips_init(struct drm_i915_private *dev_priv) | | 3350 | void intel_gpu_ips_init(struct drm_i915_private *dev_priv) |
3347 | { | | 3351 | { |
3348 | /* We only register the i915 ips part with intel-ips once everything is | | 3352 | /* We only register the i915 ips part with intel-ips once everything is |
3349 | * set up, to avoid intel-ips sneaking in and reading bogus values. */ | | 3353 | * set up, to avoid intel-ips sneaking in and reading bogus values. */ |
3350 | spin_lock_irq(&mchdev_lock); | | 3354 | spin_lock_irq(&mchdev_lock); |
3351 | i915_mch_dev = dev_priv; | | 3355 | i915_mch_dev = dev_priv; |
3352 | spin_unlock_irq(&mchdev_lock); | | 3356 | spin_unlock_irq(&mchdev_lock); |
3353 | | | 3357 | |
3354 | ips_ping_for_i915_load(); | | 3358 | ips_ping_for_i915_load(); |
3355 | } | | 3359 | } |
3356 | | | 3360 | |
3357 | void intel_gpu_ips_teardown(void) | | 3361 | void intel_gpu_ips_teardown(void) |
3358 | { | | 3362 | { |
3359 | spin_lock_irq(&mchdev_lock); | | 3363 | spin_lock_irq(&mchdev_lock); |
3360 | i915_mch_dev = NULL; | | 3364 | i915_mch_dev = NULL; |
3361 | spin_unlock_irq(&mchdev_lock); | | 3365 | spin_unlock_irq(&mchdev_lock); |
3362 | } | | 3366 | } |
3363 | static void intel_init_emon(struct drm_device *dev) | | 3367 | static void intel_init_emon(struct drm_device *dev) |
3364 | { | | 3368 | { |
3365 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3369 | struct drm_i915_private *dev_priv = dev->dev_private; |
3366 | u32 lcfuse; | | 3370 | u32 lcfuse; |
3367 | u8 pxw[16]; | | 3371 | u8 pxw[16]; |
3368 | int i; | | 3372 | int i; |
3369 | | | 3373 | |
3370 | /* Disable to program */ | | 3374 | /* Disable to program */ |
3371 | I915_WRITE(ECR, 0); | | 3375 | I915_WRITE(ECR, 0); |
3372 | POSTING_READ(ECR); | | 3376 | POSTING_READ(ECR); |
3373 | | | 3377 | |
3374 | /* Program energy weights for various events */ | | 3378 | /* Program energy weights for various events */ |
3375 | I915_WRITE(SDEW, 0x15040d00); | | 3379 | I915_WRITE(SDEW, 0x15040d00); |
3376 | I915_WRITE(CSIEW0, 0x007f0000); | | 3380 | I915_WRITE(CSIEW0, 0x007f0000); |
3377 | I915_WRITE(CSIEW1, 0x1e220004); | | 3381 | I915_WRITE(CSIEW1, 0x1e220004); |
3378 | I915_WRITE(CSIEW2, 0x04000004); | | 3382 | I915_WRITE(CSIEW2, 0x04000004); |
3379 | | | 3383 | |
3380 | for (i = 0; i < 5; i++) | | 3384 | for (i = 0; i < 5; i++) |
3381 | I915_WRITE(PEW + (i * 4), 0); | | 3385 | I915_WRITE(PEW + (i * 4), 0); |
3382 | for (i = 0; i < 3; i++) | | 3386 | for (i = 0; i < 3; i++) |
3383 | I915_WRITE(DEW + (i * 4), 0); | | 3387 | I915_WRITE(DEW + (i * 4), 0); |
3384 | | | 3388 | |
3385 | /* Program P-state weights to account for frequency power adjustment */ | | 3389 | /* Program P-state weights to account for frequency power adjustment */ |
3386 | for (i = 0; i < 16; i++) { | | 3390 | for (i = 0; i < 16; i++) { |
3387 | u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4)); | | 3391 | u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4)); |
3388 | unsigned long freq = intel_pxfreq(pxvidfreq); | | 3392 | unsigned long freq = intel_pxfreq(pxvidfreq); |
3389 | unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >> | | 3393 | unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >> |
3390 | PXVFREQ_PX_SHIFT; | | 3394 | PXVFREQ_PX_SHIFT; |
3391 | unsigned long val; | | 3395 | unsigned long val; |
3392 | | | 3396 | |
3393 | val = vid * vid; | | 3397 | val = vid * vid; |
3394 | val *= (freq / 1000); | | 3398 | val *= (freq / 1000); |
3395 | val *= 255; | | 3399 | val *= 255; |
3396 | val /= (127*127*900); | | 3400 | val /= (127*127*900); |
3397 | if (val > 0xff) | | 3401 | if (val > 0xff) |
3398 | DRM_ERROR("bad pxval: %ld\n", val); | | 3402 | DRM_ERROR("bad pxval: %ld\n", val); |
3399 | pxw[i] = val; | | 3403 | pxw[i] = val; |
3400 | } | | 3404 | } |
3401 | /* Render standby states get 0 weight */ | | 3405 | /* Render standby states get 0 weight */ |
3402 | pxw[14] = 0; | | 3406 | pxw[14] = 0; |
3403 | pxw[15] = 0; | | 3407 | pxw[15] = 0; |
3404 | | | 3408 | |
3405 | for (i = 0; i < 4; i++) { | | 3409 | for (i = 0; i < 4; i++) { |
3406 | u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) | | | 3410 | u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) | |
3407 | (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]); | | 3411 | (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]); |
3408 | I915_WRITE(PXW + (i * 4), val); | | 3412 | I915_WRITE(PXW + (i * 4), val); |
3409 | } | | 3413 | } |
3410 | | | 3414 | |
3411 | /* Adjust magic regs to magic values (more experimental results) */ | | 3415 | /* Adjust magic regs to magic values (more experimental results) */ |
3412 | I915_WRITE(OGW0, 0); | | 3416 | I915_WRITE(OGW0, 0); |
3413 | I915_WRITE(OGW1, 0); | | 3417 | I915_WRITE(OGW1, 0); |
3414 | I915_WRITE(EG0, 0x00007f00); | | 3418 | I915_WRITE(EG0, 0x00007f00); |
3415 | I915_WRITE(EG1, 0x0000000e); | | 3419 | I915_WRITE(EG1, 0x0000000e); |
3416 | I915_WRITE(EG2, 0x000e0000); | | 3420 | I915_WRITE(EG2, 0x000e0000); |
3417 | I915_WRITE(EG3, 0x68000300); | | 3421 | I915_WRITE(EG3, 0x68000300); |
3418 | I915_WRITE(EG4, 0x42000000); | | 3422 | I915_WRITE(EG4, 0x42000000); |
3419 | I915_WRITE(EG5, 0x00140031); | | 3423 | I915_WRITE(EG5, 0x00140031); |
3420 | I915_WRITE(EG6, 0); | | 3424 | I915_WRITE(EG6, 0); |
3421 | I915_WRITE(EG7, 0); | | 3425 | I915_WRITE(EG7, 0); |
3422 | | | 3426 | |
3423 | for (i = 0; i < 8; i++) | | 3427 | for (i = 0; i < 8; i++) |
3424 | I915_WRITE(PXWL + (i * 4), 0); | | 3428 | I915_WRITE(PXWL + (i * 4), 0); |
3425 | | | 3429 | |
3426 | /* Enable PMON + select events */ | | 3430 | /* Enable PMON + select events */ |
3427 | I915_WRITE(ECR, 0x80000019); | | 3431 | I915_WRITE(ECR, 0x80000019); |
3428 | | | 3432 | |
3429 | lcfuse = I915_READ(LCFUSE02); | | 3433 | lcfuse = I915_READ(LCFUSE02); |
3430 | | | 3434 | |
3431 | dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK); | | 3435 | dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK); |
3432 | } | | 3436 | } |
3433 | | | 3437 | |
3434 | void intel_disable_gt_powersave(struct drm_device *dev) | | 3438 | void intel_disable_gt_powersave(struct drm_device *dev) |
3435 | { | | 3439 | { |
3436 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3440 | struct drm_i915_private *dev_priv = dev->dev_private; |
3437 | | | 3441 | |
3438 | if (IS_IRONLAKE_M(dev)) { | | 3442 | if (IS_IRONLAKE_M(dev)) { |
3439 | ironlake_disable_drps(dev); | | 3443 | ironlake_disable_drps(dev); |
3440 | ironlake_disable_rc6(dev); | | 3444 | ironlake_disable_rc6(dev); |
3441 | } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { | | 3445 | } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { |
3442 | cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); | | 3446 | cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); |
3443 | mutex_lock(&dev_priv->rps.hw_lock); | | 3447 | mutex_lock(&dev_priv->rps.hw_lock); |
3444 | gen6_disable_rps(dev); | | 3448 | gen6_disable_rps(dev); |
3445 | mutex_unlock(&dev_priv->rps.hw_lock); | | 3449 | mutex_unlock(&dev_priv->rps.hw_lock); |
3446 | } | | 3450 | } |
3447 | } | | 3451 | } |
3448 | | | 3452 | |
3449 | static void intel_gen6_powersave_work(struct work_struct *work) | | 3453 | static void intel_gen6_powersave_work(struct work_struct *work) |
3450 | { | | 3454 | { |
3451 | struct drm_i915_private *dev_priv = | | 3455 | struct drm_i915_private *dev_priv = |
3452 | container_of(work, struct drm_i915_private, | | 3456 | container_of(work, struct drm_i915_private, |
3453 | rps.delayed_resume_work.work); | | 3457 | rps.delayed_resume_work.work); |
3454 | struct drm_device *dev = dev_priv->dev; | | 3458 | struct drm_device *dev = dev_priv->dev; |
3455 | | | 3459 | |
3456 | mutex_lock(&dev_priv->rps.hw_lock); | | 3460 | mutex_lock(&dev_priv->rps.hw_lock); |
3457 | gen6_enable_rps(dev); | | 3461 | gen6_enable_rps(dev); |
3458 | gen6_update_ring_freq(dev); | | 3462 | gen6_update_ring_freq(dev); |
3459 | mutex_unlock(&dev_priv->rps.hw_lock); | | 3463 | mutex_unlock(&dev_priv->rps.hw_lock); |
3460 | } | | 3464 | } |
3461 | | | 3465 | |
3462 | void intel_enable_gt_powersave(struct drm_device *dev) | | 3466 | void intel_enable_gt_powersave(struct drm_device *dev) |
3463 | { | | 3467 | { |
3464 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3468 | struct drm_i915_private *dev_priv = dev->dev_private; |
3465 | | | 3469 | |
3466 | if (IS_IRONLAKE_M(dev)) { | | 3470 | if (IS_IRONLAKE_M(dev)) { |
3467 | ironlake_enable_drps(dev); | | 3471 | ironlake_enable_drps(dev); |
3468 | ironlake_enable_rc6(dev); | | 3472 | ironlake_enable_rc6(dev); |
3469 | intel_init_emon(dev); | | 3473 | intel_init_emon(dev); |
3470 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | | 3474 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { |
3471 | /* | | 3475 | /* |
3472 | * PCU communication is slow and this doesn't need to be | | 3476 | * PCU communication is slow and this doesn't need to be |
3473 | * done at any specific time, so do this out of our fast path | | 3477 | * done at any specific time, so do this out of our fast path |
3474 | * to make resume and init faster. | | 3478 | * to make resume and init faster. |
3475 | */ | | 3479 | */ |
3476 | schedule_delayed_work(&dev_priv->rps.delayed_resume_work, | | 3480 | schedule_delayed_work(&dev_priv->rps.delayed_resume_work, |
3477 | round_jiffies_up_relative(HZ)); | | 3481 | round_jiffies_up_relative(HZ)); |
3478 | } | | 3482 | } |
3479 | } | | 3483 | } |
3480 | | | 3484 | |
3481 | static void ibx_init_clock_gating(struct drm_device *dev) | | 3485 | static void ibx_init_clock_gating(struct drm_device *dev) |
3482 | { | | 3486 | { |
3483 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3487 | struct drm_i915_private *dev_priv = dev->dev_private; |
3484 | | | 3488 | |
3485 | /* | | 3489 | /* |
3486 | * On Ibex Peak and Cougar Point, we need to disable clock | | 3490 | * On Ibex Peak and Cougar Point, we need to disable clock |
3487 | * gating for the panel power sequencer or it will fail to | | 3491 | * gating for the panel power sequencer or it will fail to |
3488 | * start up when no ports are active. | | 3492 | * start up when no ports are active. |
3489 | */ | | 3493 | */ |
3490 | I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); | | 3494 | I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); |
3491 | } | | 3495 | } |
3492 | | | 3496 | |
3493 | static void ironlake_init_clock_gating(struct drm_device *dev) | | 3497 | static void ironlake_init_clock_gating(struct drm_device *dev) |
3494 | { | | 3498 | { |
3495 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3499 | struct drm_i915_private *dev_priv = dev->dev_private; |
3496 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; | | 3500 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; |
3497 | | | 3501 | |
3498 | /* Required for FBC */ | | 3502 | /* Required for FBC */ |
3499 | dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | | | 3503 | dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE | |
3500 | ILK_DPFCUNIT_CLOCK_GATE_DISABLE | | | 3504 | ILK_DPFCUNIT_CLOCK_GATE_DISABLE | |
3501 | ILK_DPFDUNIT_CLOCK_GATE_ENABLE; | | 3505 | ILK_DPFDUNIT_CLOCK_GATE_ENABLE; |
3502 | | | 3506 | |
3503 | I915_WRITE(PCH_3DCGDIS0, | | 3507 | I915_WRITE(PCH_3DCGDIS0, |
3504 | MARIUNIT_CLOCK_GATE_DISABLE | | | 3508 | MARIUNIT_CLOCK_GATE_DISABLE | |
3505 | SVSMUNIT_CLOCK_GATE_DISABLE); | | 3509 | SVSMUNIT_CLOCK_GATE_DISABLE); |
3506 | I915_WRITE(PCH_3DCGDIS1, | | 3510 | I915_WRITE(PCH_3DCGDIS1, |
3507 | VFMUNIT_CLOCK_GATE_DISABLE); | | 3511 | VFMUNIT_CLOCK_GATE_DISABLE); |
3508 | | | 3512 | |
3509 | /* | | 3513 | /* |
3510 | * According to the spec the following bits should be set in | | 3514 | * According to the spec the following bits should be set in |
3511 | * order to enable memory self-refresh | | 3515 | * order to enable memory self-refresh |
3512 | * The bit 22/21 of 0x42004 | | 3516 | * The bit 22/21 of 0x42004 |
3513 | * The bit 5 of 0x42020 | | 3517 | * The bit 5 of 0x42020 |
3514 | * The bit 15 of 0x45000 | | 3518 | * The bit 15 of 0x45000 |
3515 | */ | | 3519 | */ |
3516 | I915_WRITE(ILK_DISPLAY_CHICKEN2, | | 3520 | I915_WRITE(ILK_DISPLAY_CHICKEN2, |
3517 | (I915_READ(ILK_DISPLAY_CHICKEN2) | | | 3521 | (I915_READ(ILK_DISPLAY_CHICKEN2) | |
3518 | ILK_DPARB_GATE | ILK_VSDPFD_FULL)); | | 3522 | ILK_DPARB_GATE | ILK_VSDPFD_FULL)); |
3519 | dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; | | 3523 | dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE; |
3520 | I915_WRITE(DISP_ARB_CTL, | | 3524 | I915_WRITE(DISP_ARB_CTL, |
3521 | (I915_READ(DISP_ARB_CTL) | | | 3525 | (I915_READ(DISP_ARB_CTL) | |
3522 | DISP_FBC_WM_DIS)); | | 3526 | DISP_FBC_WM_DIS)); |
3523 | I915_WRITE(WM3_LP_ILK, 0); | | 3527 | I915_WRITE(WM3_LP_ILK, 0); |
3524 | I915_WRITE(WM2_LP_ILK, 0); | | 3528 | I915_WRITE(WM2_LP_ILK, 0); |
3525 | I915_WRITE(WM1_LP_ILK, 0); | | 3529 | I915_WRITE(WM1_LP_ILK, 0); |
3526 | | | 3530 | |
3527 | /* | | 3531 | /* |
3528 | * Based on the document from hardware guys the following bits | | 3532 | * Based on the document from hardware guys the following bits |
3529 | * should be set unconditionally in order to enable FBC. | | 3533 | * should be set unconditionally in order to enable FBC. |
3530 | * The bit 22 of 0x42000 | | 3534 | * The bit 22 of 0x42000 |
3531 | * The bit 22 of 0x42004 | | 3535 | * The bit 22 of 0x42004 |
3532 | * The bit 7,8,9 of 0x42020. | | 3536 | * The bit 7,8,9 of 0x42020. |
3533 | */ | | 3537 | */ |
3534 | if (IS_IRONLAKE_M(dev)) { | | 3538 | if (IS_IRONLAKE_M(dev)) { |
3535 | I915_WRITE(ILK_DISPLAY_CHICKEN1, | | 3539 | I915_WRITE(ILK_DISPLAY_CHICKEN1, |
3536 | I915_READ(ILK_DISPLAY_CHICKEN1) | | | 3540 | I915_READ(ILK_DISPLAY_CHICKEN1) | |
3537 | ILK_FBCQ_DIS); | | 3541 | ILK_FBCQ_DIS); |
3538 | I915_WRITE(ILK_DISPLAY_CHICKEN2, | | 3542 | I915_WRITE(ILK_DISPLAY_CHICKEN2, |
3539 | I915_READ(ILK_DISPLAY_CHICKEN2) | | | 3543 | I915_READ(ILK_DISPLAY_CHICKEN2) | |
3540 | ILK_DPARB_GATE); | | 3544 | ILK_DPARB_GATE); |
3541 | } | | 3545 | } |
3542 | | | 3546 | |
3543 | I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); | | 3547 | I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); |
3544 | | | 3548 | |
3545 | I915_WRITE(ILK_DISPLAY_CHICKEN2, | | 3549 | I915_WRITE(ILK_DISPLAY_CHICKEN2, |
3546 | I915_READ(ILK_DISPLAY_CHICKEN2) | | | 3550 | I915_READ(ILK_DISPLAY_CHICKEN2) | |
3547 | ILK_ELPIN_409_SELECT); | | 3551 | ILK_ELPIN_409_SELECT); |
3548 | I915_WRITE(_3D_CHICKEN2, | | 3552 | I915_WRITE(_3D_CHICKEN2, |
3549 | _3D_CHICKEN2_WM_READ_PIPELINED << 16 | | | 3553 | _3D_CHICKEN2_WM_READ_PIPELINED << 16 | |
3550 | _3D_CHICKEN2_WM_READ_PIPELINED); | | 3554 | _3D_CHICKEN2_WM_READ_PIPELINED); |
3551 | | | 3555 | |
3552 | /* WaDisableRenderCachePipelinedFlush */ | | 3556 | /* WaDisableRenderCachePipelinedFlush */ |
3553 | I915_WRITE(CACHE_MODE_0, | | 3557 | I915_WRITE(CACHE_MODE_0, |
3554 | _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); | | 3558 | _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); |
3555 | | | 3559 | |
3556 | ibx_init_clock_gating(dev); | | 3560 | ibx_init_clock_gating(dev); |
3557 | } | | 3561 | } |
3558 | | | 3562 | |
3559 | static void cpt_init_clock_gating(struct drm_device *dev) | | 3563 | static void cpt_init_clock_gating(struct drm_device *dev) |
3560 | { | | 3564 | { |
3561 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3565 | struct drm_i915_private *dev_priv = dev->dev_private; |
3562 | int pipe; | | 3566 | int pipe; |
3563 | | | 3567 | |
3564 | /* | | 3568 | /* |
3565 | * On Ibex Peak and Cougar Point, we need to disable clock | | 3569 | * On Ibex Peak and Cougar Point, we need to disable clock |
3566 | * gating for the panel power sequencer or it will fail to | | 3570 | * gating for the panel power sequencer or it will fail to |
3567 | * start up when no ports are active. | | 3571 | * start up when no ports are active. |
3568 | */ | | 3572 | */ |
3569 | I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); | | 3573 | I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); |
3570 | I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | | | 3574 | I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | |
3571 | DPLS_EDP_PPS_FIX_DIS); | | 3575 | DPLS_EDP_PPS_FIX_DIS); |
3572 | /* The below fixes the weird display corruption, a few pixels shifted | | 3576 | /* The below fixes the weird display corruption, a few pixels shifted |
3573 | * downward, on (only) LVDS of some HP laptops with IVY. | | 3577 | * downward, on (only) LVDS of some HP laptops with IVY. |
3574 | */ | | 3578 | */ |
3575 | for_each_pipe(pipe) | | 3579 | for_each_pipe(pipe) |
3576 | I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_CHICKEN2_TIMING_OVERRIDE); | | 3580 | I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_CHICKEN2_TIMING_OVERRIDE); |
3577 | /* WADP0ClockGatingDisable */ | | 3581 | /* WADP0ClockGatingDisable */ |
3578 | for_each_pipe(pipe) { | | 3582 | for_each_pipe(pipe) { |
3579 | I915_WRITE(TRANS_CHICKEN1(pipe), | | 3583 | I915_WRITE(TRANS_CHICKEN1(pipe), |
3580 | TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); | | 3584 | TRANS_CHICKEN1_DP0UNIT_GC_DISABLE); |
3581 | } | | 3585 | } |
3582 | } | | 3586 | } |
3583 | | | 3587 | |
3584 | static void gen6_init_clock_gating(struct drm_device *dev) | | 3588 | static void gen6_init_clock_gating(struct drm_device *dev) |
3585 | { | | 3589 | { |
3586 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3590 | struct drm_i915_private *dev_priv = dev->dev_private; |
3587 | int pipe; | | 3591 | int pipe; |
3588 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; | | 3592 | uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; |
3589 | | | 3593 | |
3590 | I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); | | 3594 | I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate); |
3591 | | | 3595 | |
3592 | I915_WRITE(ILK_DISPLAY_CHICKEN2, | | 3596 | I915_WRITE(ILK_DISPLAY_CHICKEN2, |
3593 | I915_READ(ILK_DISPLAY_CHICKEN2) | | | 3597 | I915_READ(ILK_DISPLAY_CHICKEN2) | |
3594 | ILK_ELPIN_409_SELECT); | | 3598 | ILK_ELPIN_409_SELECT); |
3595 | | | 3599 | |
3596 | /* WaDisableHiZPlanesWhenMSAAEnabled */ | | 3600 | /* WaDisableHiZPlanesWhenMSAAEnabled */ |
3597 | I915_WRITE(_3D_CHICKEN, | | 3601 | I915_WRITE(_3D_CHICKEN, |
3598 | _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); | | 3602 | _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); |
3599 | | | 3603 | |
3600 | /* WaSetupGtModeTdRowDispatch */ | | 3604 | /* WaSetupGtModeTdRowDispatch */ |
3601 | if (IS_SNB_GT1(dev)) | | 3605 | if (IS_SNB_GT1(dev)) |
3602 | I915_WRITE(GEN6_GT_MODE, | | 3606 | I915_WRITE(GEN6_GT_MODE, |
3603 | _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE)); | | 3607 | _MASKED_BIT_ENABLE(GEN6_TD_FOUR_ROW_DISPATCH_DISABLE)); |
3604 | | | 3608 | |
3605 | I915_WRITE(WM3_LP_ILK, 0); | | 3609 | I915_WRITE(WM3_LP_ILK, 0); |
3606 | I915_WRITE(WM2_LP_ILK, 0); | | 3610 | I915_WRITE(WM2_LP_ILK, 0); |
3607 | I915_WRITE(WM1_LP_ILK, 0); | | 3611 | I915_WRITE(WM1_LP_ILK, 0); |
3608 | | | 3612 | |
3609 | I915_WRITE(CACHE_MODE_0, | | 3613 | I915_WRITE(CACHE_MODE_0, |
3610 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); | | 3614 | _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); |
3611 | | | 3615 | |
3612 | I915_WRITE(GEN6_UCGCTL1, | | 3616 | I915_WRITE(GEN6_UCGCTL1, |
3613 | I915_READ(GEN6_UCGCTL1) | | | 3617 | I915_READ(GEN6_UCGCTL1) | |
3614 | GEN6_BLBUNIT_CLOCK_GATE_DISABLE | | | 3618 | GEN6_BLBUNIT_CLOCK_GATE_DISABLE | |
3615 | GEN6_CSUNIT_CLOCK_GATE_DISABLE); | | 3619 | GEN6_CSUNIT_CLOCK_GATE_DISABLE); |
3616 | | | 3620 | |
3617 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | | 3621 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock |
3618 | * gating disable must be set. Failure to set it results in | | 3622 | * gating disable must be set. Failure to set it results in |
3619 | * flickering pixels due to Z write ordering failures after | | 3623 | * flickering pixels due to Z write ordering failures after |
3620 | * some amount of runtime in the Mesa "fire" demo, and Unigine | | 3624 | * some amount of runtime in the Mesa "fire" demo, and Unigine |
3621 | * Sanctuary and Tropics, and apparently anything else with | | 3625 | * Sanctuary and Tropics, and apparently anything else with |
3622 | * alpha test or pixel discard. | | 3626 | * alpha test or pixel discard. |
3623 | * | | 3627 | * |
3624 | * According to the spec, bit 11 (RCCUNIT) must also be set, | | 3628 | * According to the spec, bit 11 (RCCUNIT) must also be set, |
3625 | * but we didn't debug actual testcases to find it out. | | 3629 | * but we didn't debug actual testcases to find it out. |
3626 | * | | 3630 | * |
3627 | * Also apply WaDisableVDSUnitClockGating and | | 3631 | * Also apply WaDisableVDSUnitClockGating and |
3628 | * WaDisableRCPBUnitClockGating. | | 3632 | * WaDisableRCPBUnitClockGating. |
3629 | */ | | 3633 | */ |
3630 | I915_WRITE(GEN6_UCGCTL2, | | 3634 | I915_WRITE(GEN6_UCGCTL2, |
3631 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | | 3635 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | |
3632 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | | 3636 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | |
3633 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | | 3637 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); |
3634 | | | 3638 | |
3635 | /* Bspec says we need to always set all mask bits. */ | | 3639 | /* Bspec says we need to always set all mask bits. */ |
3636 | I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | | | 3640 | I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | |
3637 | _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); | | 3641 | _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); |
3638 | | | 3642 | |
3639 | /* | | 3643 | /* |
3640 | * According to the spec the following bits should be | | 3644 | * According to the spec the following bits should be |
3641 | * set in order to enable memory self-refresh and fbc: | | 3645 | * set in order to enable memory self-refresh and fbc: |
3642 | * The bit21 and bit22 of 0x42000 | | 3646 | * The bit21 and bit22 of 0x42000 |
3643 | * The bit21 and bit22 of 0x42004 | | 3647 | * The bit21 and bit22 of 0x42004 |
3644 | * The bit5 and bit7 of 0x42020 | | 3648 | * The bit5 and bit7 of 0x42020 |
3645 | * The bit14 of 0x70180 | | 3649 | * The bit14 of 0x70180 |
3646 | * The bit14 of 0x71180 | | 3650 | * The bit14 of 0x71180 |
3647 | */ | | 3651 | */ |
3648 | I915_WRITE(ILK_DISPLAY_CHICKEN1, | | 3652 | I915_WRITE(ILK_DISPLAY_CHICKEN1, |
3649 | I915_READ(ILK_DISPLAY_CHICKEN1) | | | 3653 | I915_READ(ILK_DISPLAY_CHICKEN1) | |
3650 | ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); | | 3654 | ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); |
3651 | I915_WRITE(ILK_DISPLAY_CHICKEN2, | | 3655 | I915_WRITE(ILK_DISPLAY_CHICKEN2, |
3652 | I915_READ(ILK_DISPLAY_CHICKEN2) | | | 3656 | I915_READ(ILK_DISPLAY_CHICKEN2) | |
3653 | ILK_DPARB_GATE | ILK_VSDPFD_FULL); | | 3657 | ILK_DPARB_GATE | ILK_VSDPFD_FULL); |
3654 | I915_WRITE(ILK_DSPCLK_GATE_D, | | 3658 | I915_WRITE(ILK_DSPCLK_GATE_D, |
3655 | I915_READ(ILK_DSPCLK_GATE_D) | | | 3659 | I915_READ(ILK_DSPCLK_GATE_D) | |
3656 | ILK_DPARBUNIT_CLOCK_GATE_ENABLE | | | 3660 | ILK_DPARBUNIT_CLOCK_GATE_ENABLE | |
3657 | ILK_DPFDUNIT_CLOCK_GATE_ENABLE); | | 3661 | ILK_DPFDUNIT_CLOCK_GATE_ENABLE); |
3658 | | | 3662 | |
3659 | /* WaMbcDriverBootEnable */ | | 3663 | /* WaMbcDriverBootEnable */ |
3660 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | | 3664 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | |
3661 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | | 3665 | GEN6_MBCTL_ENABLE_BOOT_FETCH); |
3662 | | | 3666 | |
3663 | for_each_pipe(pipe) { | | 3667 | for_each_pipe(pipe) { |
3664 | I915_WRITE(DSPCNTR(pipe), | | 3668 | I915_WRITE(DSPCNTR(pipe), |
3665 | I915_READ(DSPCNTR(pipe)) | | | 3669 | I915_READ(DSPCNTR(pipe)) | |
3666 | DISPPLANE_TRICKLE_FEED_DISABLE); | | 3670 | DISPPLANE_TRICKLE_FEED_DISABLE); |
3667 | intel_flush_display_plane(dev_priv, pipe); | | 3671 | intel_flush_display_plane(dev_priv, pipe); |
3668 | } | | 3672 | } |
3669 | | | 3673 | |
3670 | /* The default value should be 0x200 according to docs, but the two | | 3674 | /* The default value should be 0x200 according to docs, but the two |
3671 | * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ | | 3675 | * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ |
3672 | I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff)); | | 3676 | I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_DISABLE(0xffff)); |
3673 | I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI)); | | 3677 | I915_WRITE(GEN6_GT_MODE, _MASKED_BIT_ENABLE(GEN6_GT_MODE_HI)); |
3674 | | | 3678 | |
3675 | cpt_init_clock_gating(dev); | | 3679 | cpt_init_clock_gating(dev); |
3676 | } | | 3680 | } |
3677 | | | 3681 | |
3678 | static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) | | 3682 | static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) |
3679 | { | | 3683 | { |
3680 | uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE); | | 3684 | uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE); |
3681 | | | 3685 | |
3682 | reg &= ~GEN7_FF_SCHED_MASK; | | 3686 | reg &= ~GEN7_FF_SCHED_MASK; |
3683 | reg |= GEN7_FF_TS_SCHED_HW; | | 3687 | reg |= GEN7_FF_TS_SCHED_HW; |
3684 | reg |= GEN7_FF_VS_SCHED_HW; | | 3688 | reg |= GEN7_FF_VS_SCHED_HW; |
3685 | reg |= GEN7_FF_DS_SCHED_HW; | | 3689 | reg |= GEN7_FF_DS_SCHED_HW; |
3686 | | | 3690 | |
3687 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); | | 3691 | I915_WRITE(GEN7_FF_THREAD_MODE, reg); |
3688 | } | | 3692 | } |
3689 | | | 3693 | |
3690 | static void lpt_init_clock_gating(struct drm_device *dev) | | 3694 | static void lpt_init_clock_gating(struct drm_device *dev) |
3691 | { | | 3695 | { |
3692 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3696 | struct drm_i915_private *dev_priv = dev->dev_private; |
3693 | | | 3697 | |
3694 | /* | | 3698 | /* |
3695 | * TODO: this bit should only be enabled when really needed, then | | 3699 | * TODO: this bit should only be enabled when really needed, then |
3696 | * disabled when not needed anymore in order to save power. | | 3700 | * disabled when not needed anymore in order to save power. |
3697 | */ | | 3701 | */ |
3698 | if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) | | 3702 | if (dev_priv->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) |
3699 | I915_WRITE(SOUTH_DSPCLK_GATE_D, | | 3703 | I915_WRITE(SOUTH_DSPCLK_GATE_D, |
3700 | I915_READ(SOUTH_DSPCLK_GATE_D) | | | 3704 | I915_READ(SOUTH_DSPCLK_GATE_D) | |
3701 | PCH_LP_PARTITION_LEVEL_DISABLE); | | 3705 | PCH_LP_PARTITION_LEVEL_DISABLE); |
3702 | } | | 3706 | } |
3703 | | | 3707 | |
3704 | static void haswell_init_clock_gating(struct drm_device *dev) | | 3708 | static void haswell_init_clock_gating(struct drm_device *dev) |
3705 | { | | 3709 | { |
3706 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3710 | struct drm_i915_private *dev_priv = dev->dev_private; |
3707 | int pipe; | | 3711 | int pipe; |
3708 | | | 3712 | |
3709 | I915_WRITE(WM3_LP_ILK, 0); | | 3713 | I915_WRITE(WM3_LP_ILK, 0); |
3710 | I915_WRITE(WM2_LP_ILK, 0); | | 3714 | I915_WRITE(WM2_LP_ILK, 0); |
3711 | I915_WRITE(WM1_LP_ILK, 0); | | 3715 | I915_WRITE(WM1_LP_ILK, 0); |
3712 | | | 3716 | |
3713 | /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. | | 3717 | /* According to the spec, bit 13 (RCZUNIT) must be set on IVB. |
3714 | * This implements the WaDisableRCZUnitClockGating workaround. | | 3718 | * This implements the WaDisableRCZUnitClockGating workaround. |
3715 | */ | | 3719 | */ |
3716 | I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); | | 3720 | I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); |
3717 | | | 3721 | |
3718 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | | 3722 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ |
3719 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | | 3723 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, |
3720 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | | 3724 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); |
3721 | | | 3725 | |
3722 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | | 3726 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ |
3723 | I915_WRITE(GEN7_L3CNTLREG1, | | 3727 | I915_WRITE(GEN7_L3CNTLREG1, |
3724 | GEN7_WA_FOR_GEN7_L3_CONTROL); | | 3728 | GEN7_WA_FOR_GEN7_L3_CONTROL); |
3725 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | | 3729 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, |
3726 | GEN7_WA_L3_CHICKEN_MODE); | | 3730 | GEN7_WA_L3_CHICKEN_MODE); |
3727 | | | 3731 | |
3728 | /* This is required by WaCatErrorRejectionIssue */ | | 3732 | /* This is required by WaCatErrorRejectionIssue */ |
3729 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | | 3733 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, |
3730 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | | 3734 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | |
3731 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | | 3735 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); |
3732 | | | 3736 | |
3733 | for_each_pipe(pipe) { | | 3737 | for_each_pipe(pipe) { |
3734 | I915_WRITE(DSPCNTR(pipe), | | 3738 | I915_WRITE(DSPCNTR(pipe), |
3735 | I915_READ(DSPCNTR(pipe)) | | | 3739 | I915_READ(DSPCNTR(pipe)) | |
3736 | DISPPLANE_TRICKLE_FEED_DISABLE); | | 3740 | DISPPLANE_TRICKLE_FEED_DISABLE); |
3737 | intel_flush_display_plane(dev_priv, pipe); | | 3741 | intel_flush_display_plane(dev_priv, pipe); |
3738 | } | | 3742 | } |
3739 | | | 3743 | |
3740 | gen7_setup_fixed_func_scheduler(dev_priv); | | 3744 | gen7_setup_fixed_func_scheduler(dev_priv); |
3741 | | | 3745 | |
3742 | /* WaDisable4x2SubspanOptimization */ | | 3746 | /* WaDisable4x2SubspanOptimization */ |
3743 | I915_WRITE(CACHE_MODE_1, | | 3747 | I915_WRITE(CACHE_MODE_1, |
3744 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | | 3748 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
3745 | | | 3749 | |
3746 | /* WaMbcDriverBootEnable */ | | 3750 | /* WaMbcDriverBootEnable */ |
3747 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | | 3751 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | |
3748 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | | 3752 | GEN6_MBCTL_ENABLE_BOOT_FETCH); |
3749 | | | 3753 | |
3750 | /* XXX: This is a workaround for early silicon revisions and should be | | 3754 | /* XXX: This is a workaround for early silicon revisions and should be |
3751 | * removed later. | | 3755 | * removed later. |
3752 | */ | | 3756 | */ |
3753 | I915_WRITE(WM_DBG, | | 3757 | I915_WRITE(WM_DBG, |
3754 | I915_READ(WM_DBG) | | | 3758 | I915_READ(WM_DBG) | |
3755 | WM_DBG_DISALLOW_MULTIPLE_LP | | | 3759 | WM_DBG_DISALLOW_MULTIPLE_LP | |
3756 | WM_DBG_DISALLOW_SPRITE | | | 3760 | WM_DBG_DISALLOW_SPRITE | |
3757 | WM_DBG_DISALLOW_MAXFIFO); | | 3761 | WM_DBG_DISALLOW_MAXFIFO); |
3758 | | | 3762 | |
3759 | lpt_init_clock_gating(dev); | | 3763 | lpt_init_clock_gating(dev); |
3760 | } | | 3764 | } |
3761 | | | 3765 | |
3762 | static void ivybridge_init_clock_gating(struct drm_device *dev) | | 3766 | static void ivybridge_init_clock_gating(struct drm_device *dev) |
3763 | { | | 3767 | { |
3764 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3768 | struct drm_i915_private *dev_priv = dev->dev_private; |
3765 | int pipe; | | 3769 | int pipe; |
3766 | uint32_t snpcr; | | 3770 | uint32_t snpcr; |
3767 | | | 3771 | |
3768 | I915_WRITE(WM3_LP_ILK, 0); | | 3772 | I915_WRITE(WM3_LP_ILK, 0); |
3769 | I915_WRITE(WM2_LP_ILK, 0); | | 3773 | I915_WRITE(WM2_LP_ILK, 0); |
3770 | I915_WRITE(WM1_LP_ILK, 0); | | 3774 | I915_WRITE(WM1_LP_ILK, 0); |
3771 | | | 3775 | |
3772 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); | | 3776 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); |
3773 | | | 3777 | |
3774 | /* WaDisableEarlyCull */ | | 3778 | /* WaDisableEarlyCull */ |
3775 | I915_WRITE(_3D_CHICKEN3, | | 3779 | I915_WRITE(_3D_CHICKEN3, |
3776 | _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); | | 3780 | _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); |
3777 | | | 3781 | |
3778 | /* WaDisableBackToBackFlipFix */ | | 3782 | /* WaDisableBackToBackFlipFix */ |
3779 | I915_WRITE(IVB_CHICKEN3, | | 3783 | I915_WRITE(IVB_CHICKEN3, |
3780 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | | | 3784 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | |
3781 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | | 3785 | CHICKEN3_DGMG_DONE_FIX_DISABLE); |
3782 | | | 3786 | |
3783 | /* WaDisablePSDDualDispatchEnable */ | | 3787 | /* WaDisablePSDDualDispatchEnable */ |
3784 | if (IS_IVB_GT1(dev)) | | 3788 | if (IS_IVB_GT1(dev)) |
3785 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, | | 3789 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, |
3786 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); | | 3790 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); |
3787 | else | | 3791 | else |
3788 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2, | | 3792 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1_GT2, |
3789 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); | | 3793 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); |
3790 | | | 3794 | |
3791 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | | 3795 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ |
3792 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | | 3796 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, |
3793 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | | 3797 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); |
3794 | | | 3798 | |
3795 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | | 3799 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ |
3796 | I915_WRITE(GEN7_L3CNTLREG1, | | 3800 | I915_WRITE(GEN7_L3CNTLREG1, |
3797 | GEN7_WA_FOR_GEN7_L3_CONTROL); | | 3801 | GEN7_WA_FOR_GEN7_L3_CONTROL); |
3798 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | | 3802 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, |
3799 | GEN7_WA_L3_CHICKEN_MODE); | | 3803 | GEN7_WA_L3_CHICKEN_MODE); |
3800 | if (IS_IVB_GT1(dev)) | | 3804 | if (IS_IVB_GT1(dev)) |
3801 | I915_WRITE(GEN7_ROW_CHICKEN2, | | 3805 | I915_WRITE(GEN7_ROW_CHICKEN2, |
3802 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | | 3806 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); |
3803 | else | | 3807 | else |
3804 | I915_WRITE(GEN7_ROW_CHICKEN2_GT2, | | 3808 | I915_WRITE(GEN7_ROW_CHICKEN2_GT2, |
3805 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | | 3809 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); |
3806 | | | 3810 | |
3807 | | | 3811 | |
3808 | /* WaForceL3Serialization */ | | 3812 | /* WaForceL3Serialization */ |
3809 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & | | 3813 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & |
3810 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); | | 3814 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); |
3811 | | | 3815 | |
3812 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | | 3816 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock |
3813 | * gating disable must be set. Failure to set it results in | | 3817 | * gating disable must be set. Failure to set it results in |
3814 | * flickering pixels due to Z write ordering failures after | | 3818 | * flickering pixels due to Z write ordering failures after |
3815 | * some amount of runtime in the Mesa "fire" demo, and Unigine | | 3819 | * some amount of runtime in the Mesa "fire" demo, and Unigine |
3816 | * Sanctuary and Tropics, and apparently anything else with | | 3820 | * Sanctuary and Tropics, and apparently anything else with |
3817 | * alpha test or pixel discard. | | 3821 | * alpha test or pixel discard. |
3818 | * | | 3822 | * |
3819 | * According to the spec, bit 11 (RCCUNIT) must also be set, | | 3823 | * According to the spec, bit 11 (RCCUNIT) must also be set, |
3820 | * but we didn't debug actual testcases to find it out. | | 3824 | * but we didn't debug actual testcases to find it out. |
3821 | * | | 3825 | * |
3822 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | | 3826 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. |
3823 | * This implements the WaDisableRCZUnitClockGating workaround. | | 3827 | * This implements the WaDisableRCZUnitClockGating workaround. |
3824 | */ | | 3828 | */ |
3825 | I915_WRITE(GEN6_UCGCTL2, | | 3829 | I915_WRITE(GEN6_UCGCTL2, |
3826 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | | 3830 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | |
3827 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | | 3831 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); |
3828 | | | 3832 | |
3829 | /* This is required by WaCatErrorRejectionIssue */ | | 3833 | /* This is required by WaCatErrorRejectionIssue */ |
3830 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | | 3834 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, |
3831 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | | 3835 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | |
3832 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | | 3836 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); |
3833 | | | 3837 | |
3834 | for_each_pipe(pipe) { | | 3838 | for_each_pipe(pipe) { |
3835 | I915_WRITE(DSPCNTR(pipe), | | 3839 | I915_WRITE(DSPCNTR(pipe), |
3836 | I915_READ(DSPCNTR(pipe)) | | | 3840 | I915_READ(DSPCNTR(pipe)) | |
3837 | DISPPLANE_TRICKLE_FEED_DISABLE); | | 3841 | DISPPLANE_TRICKLE_FEED_DISABLE); |
3838 | intel_flush_display_plane(dev_priv, pipe); | | 3842 | intel_flush_display_plane(dev_priv, pipe); |
3839 | } | | 3843 | } |
3840 | | | 3844 | |
3841 | /* WaMbcDriverBootEnable */ | | 3845 | /* WaMbcDriverBootEnable */ |
3842 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | | 3846 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | |
3843 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | | 3847 | GEN6_MBCTL_ENABLE_BOOT_FETCH); |
3844 | | | 3848 | |
3845 | gen7_setup_fixed_func_scheduler(dev_priv); | | 3849 | gen7_setup_fixed_func_scheduler(dev_priv); |
3846 | | | 3850 | |
3847 | /* WaDisable4x2SubspanOptimization */ | | 3851 | /* WaDisable4x2SubspanOptimization */ |
3848 | I915_WRITE(CACHE_MODE_1, | | 3852 | I915_WRITE(CACHE_MODE_1, |
3849 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | | 3853 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
3850 | | | 3854 | |
3851 | snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); | | 3855 | snpcr = I915_READ(GEN6_MBCUNIT_SNPCR); |
3852 | snpcr &= ~GEN6_MBC_SNPCR_MASK; | | 3856 | snpcr &= ~GEN6_MBC_SNPCR_MASK; |
3853 | snpcr |= GEN6_MBC_SNPCR_MED; | | 3857 | snpcr |= GEN6_MBC_SNPCR_MED; |
3854 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); | | 3858 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); |
3855 | | | 3859 | |
3856 | cpt_init_clock_gating(dev); | | 3860 | cpt_init_clock_gating(dev); |
3857 | } | | 3861 | } |
3858 | | | 3862 | |
3859 | static void valleyview_init_clock_gating(struct drm_device *dev) | | 3863 | static void valleyview_init_clock_gating(struct drm_device *dev) |
3860 | { | | 3864 | { |
3861 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3865 | struct drm_i915_private *dev_priv = dev->dev_private; |
3862 | int pipe; | | 3866 | int pipe; |
3863 | | | 3867 | |
3864 | I915_WRITE(WM3_LP_ILK, 0); | | 3868 | I915_WRITE(WM3_LP_ILK, 0); |
3865 | I915_WRITE(WM2_LP_ILK, 0); | | 3869 | I915_WRITE(WM2_LP_ILK, 0); |
3866 | I915_WRITE(WM1_LP_ILK, 0); | | 3870 | I915_WRITE(WM1_LP_ILK, 0); |
3867 | | | 3871 | |
3868 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); | | 3872 | I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); |
3869 | | | 3873 | |
3870 | /* WaDisableEarlyCull */ | | 3874 | /* WaDisableEarlyCull */ |
3871 | I915_WRITE(_3D_CHICKEN3, | | 3875 | I915_WRITE(_3D_CHICKEN3, |
3872 | _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); | | 3876 | _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL)); |
3873 | | | 3877 | |
3874 | /* WaDisableBackToBackFlipFix */ | | 3878 | /* WaDisableBackToBackFlipFix */ |
3875 | I915_WRITE(IVB_CHICKEN3, | | 3879 | I915_WRITE(IVB_CHICKEN3, |
3876 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | | | 3880 | CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | |
3877 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | | 3881 | CHICKEN3_DGMG_DONE_FIX_DISABLE); |
3878 | | | 3882 | |
3879 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, | | 3883 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, |
3880 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); | | 3884 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); |
3881 | | | 3885 | |
3882 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ | | 3886 | /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ |
3883 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, | | 3887 | I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, |
3884 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); | | 3888 | GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); |
3885 | | | 3889 | |
3886 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ | | 3890 | /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ |
3887 | I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS); | | 3891 | I915_WRITE(GEN7_L3CNTLREG1, I915_READ(GEN7_L3CNTLREG1) | GEN7_L3AGDIS); |
3888 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); | | 3892 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); |
3889 | | | 3893 | |
3890 | /* WaForceL3Serialization */ | | 3894 | /* WaForceL3Serialization */ |
3891 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & | | 3895 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & |
3892 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); | | 3896 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); |
3893 | | | 3897 | |
3894 | /* WaDisableDopClockGating */ | | 3898 | /* WaDisableDopClockGating */ |
3895 | I915_WRITE(GEN7_ROW_CHICKEN2, | | 3899 | I915_WRITE(GEN7_ROW_CHICKEN2, |
3896 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | | 3900 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); |
3897 | | | 3901 | |
3898 | /* WaForceL3Serialization */ | | 3902 | /* WaForceL3Serialization */ |
3899 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & | | 3903 | I915_WRITE(GEN7_L3SQCREG4, I915_READ(GEN7_L3SQCREG4) & |
3900 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); | | 3904 | ~L3SQ_URB_READ_CAM_MATCH_DISABLE); |
3901 | | | 3905 | |
3902 | /* This is required by WaCatErrorRejectionIssue */ | | 3906 | /* This is required by WaCatErrorRejectionIssue */ |
3903 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | | 3907 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, |
3904 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | | 3908 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | |
3905 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); | | 3909 | GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); |
3906 | | | 3910 | |
3907 | /* WaMbcDriverBootEnable */ | | 3911 | /* WaMbcDriverBootEnable */ |
3908 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | | | 3912 | I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) | |
3909 | GEN6_MBCTL_ENABLE_BOOT_FETCH); | | 3913 | GEN6_MBCTL_ENABLE_BOOT_FETCH); |
3910 | | | 3914 | |
3911 | | | 3915 | |
3912 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock | | 3916 | /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock |
3913 | * gating disable must be set. Failure to set it results in | | 3917 | * gating disable must be set. Failure to set it results in |
3914 | * flickering pixels due to Z write ordering failures after | | 3918 | * flickering pixels due to Z write ordering failures after |
3915 | * some amount of runtime in the Mesa "fire" demo, and Unigine | | 3919 | * some amount of runtime in the Mesa "fire" demo, and Unigine |
3916 | * Sanctuary and Tropics, and apparently anything else with | | 3920 | * Sanctuary and Tropics, and apparently anything else with |
3917 | * alpha test or pixel discard. | | 3921 | * alpha test or pixel discard. |
3918 | * | | 3922 | * |
3919 | * According to the spec, bit 11 (RCCUNIT) must also be set, | | 3923 | * According to the spec, bit 11 (RCCUNIT) must also be set, |
3920 | * but we didn't debug actual testcases to find it out. | | 3924 | * but we didn't debug actual testcases to find it out. |
3921 | * | | 3925 | * |
3922 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. | | 3926 | * According to the spec, bit 13 (RCZUNIT) must be set on IVB. |
3923 | * This implements the WaDisableRCZUnitClockGating workaround. | | 3927 | * This implements the WaDisableRCZUnitClockGating workaround. |
3924 | * | | 3928 | * |
3925 | * Also apply WaDisableVDSUnitClockGating and | | 3929 | * Also apply WaDisableVDSUnitClockGating and |
3926 | * WaDisableRCPBUnitClockGating. | | 3930 | * WaDisableRCPBUnitClockGating. |
3927 | */ | | 3931 | */ |
3928 | I915_WRITE(GEN6_UCGCTL2, | | 3932 | I915_WRITE(GEN6_UCGCTL2, |
3929 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | | | 3933 | GEN7_VDSUNIT_CLOCK_GATE_DISABLE | |
3930 | GEN7_TDLUNIT_CLOCK_GATE_DISABLE | | | 3934 | GEN7_TDLUNIT_CLOCK_GATE_DISABLE | |
3931 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | | | 3935 | GEN6_RCZUNIT_CLOCK_GATE_DISABLE | |
3932 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | | | 3936 | GEN6_RCPBUNIT_CLOCK_GATE_DISABLE | |
3933 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); | | 3937 | GEN6_RCCUNIT_CLOCK_GATE_DISABLE); |
3934 | | | 3938 | |
3935 | I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); | | 3939 | I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE); |
3936 | | | 3940 | |
3937 | for_each_pipe(pipe) { | | 3941 | for_each_pipe(pipe) { |
3938 | I915_WRITE(DSPCNTR(pipe), | | 3942 | I915_WRITE(DSPCNTR(pipe), |
3939 | I915_READ(DSPCNTR(pipe)) | | | 3943 | I915_READ(DSPCNTR(pipe)) | |
3940 | DISPPLANE_TRICKLE_FEED_DISABLE); | | 3944 | DISPPLANE_TRICKLE_FEED_DISABLE); |
3941 | intel_flush_display_plane(dev_priv, pipe); | | 3945 | intel_flush_display_plane(dev_priv, pipe); |
3942 | } | | 3946 | } |
3943 | | | 3947 | |
3944 | I915_WRITE(CACHE_MODE_1, | | 3948 | I915_WRITE(CACHE_MODE_1, |
3945 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); | | 3949 | _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE)); |
3946 | | | 3950 | |
3947 | /* | | 3951 | /* |
3948 | * On ValleyView, the GUnit needs to signal the GT | | 3952 | * On ValleyView, the GUnit needs to signal the GT |
3949 | * when flip and other events complete. So enable | | 3953 | * when flip and other events complete. So enable |
3950 | * all the GUnit->GT interrupts here | | 3954 | * all the GUnit->GT interrupts here |
3951 | */ | | 3955 | */ |
3952 | I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | | | 3956 | I915_WRITE(VLV_DPFLIPSTAT, PIPEB_LINE_COMPARE_INT_EN | |
3953 | PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | | | 3957 | PIPEB_HLINE_INT_EN | PIPEB_VBLANK_INT_EN | |
3954 | SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | | | 3958 | SPRITED_FLIPDONE_INT_EN | SPRITEC_FLIPDONE_INT_EN | |
3955 | PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | | | 3959 | PLANEB_FLIPDONE_INT_EN | PIPEA_LINE_COMPARE_INT_EN | |
3956 | PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | | | 3960 | PIPEA_HLINE_INT_EN | PIPEA_VBLANK_INT_EN | |
3957 | SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | | | 3961 | SPRITEB_FLIPDONE_INT_EN | SPRITEA_FLIPDONE_INT_EN | |
3958 | PLANEA_FLIPDONE_INT_EN); | | 3962 | PLANEA_FLIPDONE_INT_EN); |
3959 | | | 3963 | |
3960 | /* | | 3964 | /* |
3961 | * WaDisableVLVClockGating_VBIIssue | | 3965 | * WaDisableVLVClockGating_VBIIssue |
3962 | * Disable clock gating on th GCFG unit to prevent a delay | | 3966 | * Disable clock gating on th GCFG unit to prevent a delay |
3963 | * in the reporting of vblank events. | | 3967 | * in the reporting of vblank events. |
3964 | */ | | 3968 | */ |
3965 | I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS); | | 3969 | I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS); |
3966 | } | | 3970 | } |
3967 | | | 3971 | |
3968 | static void g4x_init_clock_gating(struct drm_device *dev) | | 3972 | static void g4x_init_clock_gating(struct drm_device *dev) |
3969 | { | | 3973 | { |
3970 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3974 | struct drm_i915_private *dev_priv = dev->dev_private; |
3971 | uint32_t dspclk_gate; | | 3975 | uint32_t dspclk_gate; |
3972 | | | 3976 | |
3973 | I915_WRITE(RENCLK_GATE_D1, 0); | | 3977 | I915_WRITE(RENCLK_GATE_D1, 0); |
3974 | I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | | | 3978 | I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE | |
3975 | GS_UNIT_CLOCK_GATE_DISABLE | | | 3979 | GS_UNIT_CLOCK_GATE_DISABLE | |
3976 | CL_UNIT_CLOCK_GATE_DISABLE); | | 3980 | CL_UNIT_CLOCK_GATE_DISABLE); |
3977 | I915_WRITE(RAMCLK_GATE_D, 0); | | 3981 | I915_WRITE(RAMCLK_GATE_D, 0); |
3978 | dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | | | 3982 | dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | |
3979 | OVRUNIT_CLOCK_GATE_DISABLE | | | 3983 | OVRUNIT_CLOCK_GATE_DISABLE | |
3980 | OVCUNIT_CLOCK_GATE_DISABLE; | | 3984 | OVCUNIT_CLOCK_GATE_DISABLE; |
3981 | if (IS_GM45(dev)) | | 3985 | if (IS_GM45(dev)) |
3982 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; | | 3986 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; |
3983 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); | | 3987 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); |
3984 | | | 3988 | |
3985 | /* WaDisableRenderCachePipelinedFlush */ | | 3989 | /* WaDisableRenderCachePipelinedFlush */ |
3986 | I915_WRITE(CACHE_MODE_0, | | 3990 | I915_WRITE(CACHE_MODE_0, |
3987 | _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); | | 3991 | _MASKED_BIT_ENABLE(CM0_PIPELINED_RENDER_FLUSH_DISABLE)); |
3988 | } | | 3992 | } |
3989 | | | 3993 | |
3990 | static void crestline_init_clock_gating(struct drm_device *dev) | | 3994 | static void crestline_init_clock_gating(struct drm_device *dev) |
3991 | { | | 3995 | { |
3992 | struct drm_i915_private *dev_priv = dev->dev_private; | | 3996 | struct drm_i915_private *dev_priv = dev->dev_private; |
3993 | | | 3997 | |
3994 | I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); | | 3998 | I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE); |
3995 | I915_WRITE(RENCLK_GATE_D2, 0); | | 3999 | I915_WRITE(RENCLK_GATE_D2, 0); |
3996 | I915_WRITE(DSPCLK_GATE_D, 0); | | 4000 | I915_WRITE(DSPCLK_GATE_D, 0); |
3997 | I915_WRITE(RAMCLK_GATE_D, 0); | | 4001 | I915_WRITE(RAMCLK_GATE_D, 0); |
3998 | I915_WRITE16(DEUC, 0); | | 4002 | I915_WRITE16(DEUC, 0); |
3999 | } | | 4003 | } |
4000 | | | 4004 | |
4001 | static void broadwater_init_clock_gating(struct drm_device *dev) | | 4005 | static void broadwater_init_clock_gating(struct drm_device *dev) |
4002 | { | | 4006 | { |
4003 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4007 | struct drm_i915_private *dev_priv = dev->dev_private; |
4004 | | | 4008 | |
4005 | I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | | | 4009 | I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE | |
4006 | I965_RCC_CLOCK_GATE_DISABLE | | | 4010 | I965_RCC_CLOCK_GATE_DISABLE | |
4007 | I965_RCPB_CLOCK_GATE_DISABLE | | | 4011 | I965_RCPB_CLOCK_GATE_DISABLE | |
4008 | I965_ISC_CLOCK_GATE_DISABLE | | | 4012 | I965_ISC_CLOCK_GATE_DISABLE | |
4009 | I965_FBC_CLOCK_GATE_DISABLE); | | 4013 | I965_FBC_CLOCK_GATE_DISABLE); |
4010 | I915_WRITE(RENCLK_GATE_D2, 0); | | 4014 | I915_WRITE(RENCLK_GATE_D2, 0); |
4011 | } | | 4015 | } |
4012 | | | 4016 | |
4013 | static void gen3_init_clock_gating(struct drm_device *dev) | | 4017 | static void gen3_init_clock_gating(struct drm_device *dev) |
4014 | { | | 4018 | { |
4015 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4019 | struct drm_i915_private *dev_priv = dev->dev_private; |
4016 | u32 dstate = I915_READ(D_STATE); | | 4020 | u32 dstate = I915_READ(D_STATE); |
4017 | | | 4021 | |
4018 | dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | | | 4022 | dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING | |
4019 | DSTATE_DOT_CLOCK_GATING; | | 4023 | DSTATE_DOT_CLOCK_GATING; |
4020 | I915_WRITE(D_STATE, dstate); | | 4024 | I915_WRITE(D_STATE, dstate); |
4021 | | | 4025 | |
4022 | if (IS_PINEVIEW(dev)) | | 4026 | if (IS_PINEVIEW(dev)) |
4023 | I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); | | 4027 | I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); |
4024 | | | 4028 | |
4025 | /* IIR "flip pending" means done if this bit is set */ | | 4029 | /* IIR "flip pending" means done if this bit is set */ |
4026 | I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); | | 4030 | I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); |
4027 | } | | 4031 | } |
4028 | | | 4032 | |
4029 | static void i85x_init_clock_gating(struct drm_device *dev) | | 4033 | static void i85x_init_clock_gating(struct drm_device *dev) |
4030 | { | | 4034 | { |
4031 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4035 | struct drm_i915_private *dev_priv = dev->dev_private; |
4032 | | | 4036 | |
4033 | I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); | | 4037 | I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE); |
4034 | } | | 4038 | } |
4035 | | | 4039 | |
4036 | static void i830_init_clock_gating(struct drm_device *dev) | | 4040 | static void i830_init_clock_gating(struct drm_device *dev) |
4037 | { | | 4041 | { |
4038 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4042 | struct drm_i915_private *dev_priv = dev->dev_private; |
4039 | | | 4043 | |
4040 | I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); | | 4044 | I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); |
4041 | } | | 4045 | } |
4042 | | | 4046 | |
4043 | void intel_init_clock_gating(struct drm_device *dev) | | 4047 | void intel_init_clock_gating(struct drm_device *dev) |
4044 | { | | 4048 | { |
4045 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4049 | struct drm_i915_private *dev_priv = dev->dev_private; |
4046 | | | 4050 | |
4047 | dev_priv->display.init_clock_gating(dev); | | 4051 | dev_priv->display.init_clock_gating(dev); |
4048 | } | | 4052 | } |
4049 | | | 4053 | |
4050 | /* Starting with Haswell, we have different power wells for | | 4054 | /* Starting with Haswell, we have different power wells for |
4051 | * different parts of the GPU. This attempts to enable them all. | | 4055 | * different parts of the GPU. This attempts to enable them all. |
4052 | */ | | 4056 | */ |
4053 | void intel_init_power_wells(struct drm_device *dev) | | 4057 | void intel_init_power_wells(struct drm_device *dev) |
4054 | { | | 4058 | { |
4055 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4059 | struct drm_i915_private *dev_priv = dev->dev_private; |
4056 | unsigned long power_wells[] = { | | 4060 | unsigned long power_wells[] = { |
4057 | HSW_PWR_WELL_CTL1, | | 4061 | HSW_PWR_WELL_CTL1, |
4058 | HSW_PWR_WELL_CTL2, | | 4062 | HSW_PWR_WELL_CTL2, |
4059 | HSW_PWR_WELL_CTL4 | | 4063 | HSW_PWR_WELL_CTL4 |
4060 | }; | | 4064 | }; |
4061 | int i; | | 4065 | int i; |
4062 | | | 4066 | |
4063 | if (!IS_HASWELL(dev)) | | 4067 | if (!IS_HASWELL(dev)) |
4064 | return; | | 4068 | return; |
4065 | | | 4069 | |
4066 | mutex_lock(&dev->struct_mutex); | | 4070 | mutex_lock(&dev->struct_mutex); |
4067 | | | 4071 | |
4068 | for (i = 0; i < ARRAY_SIZE(power_wells); i++) { | | 4072 | for (i = 0; i < ARRAY_SIZE(power_wells); i++) { |
4069 | int well = I915_READ(power_wells[i]); | | 4073 | int well = I915_READ(power_wells[i]); |
4070 | | | 4074 | |
4071 | if ((well & HSW_PWR_WELL_STATE) == 0) { | | 4075 | if ((well & HSW_PWR_WELL_STATE) == 0) { |
4072 | I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE); | | 4076 | I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE); |
4073 | if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20)) | | 4077 | if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20)) |
4074 | DRM_ERROR("Error enabling power well %lx\n", power_wells[i]); | | 4078 | DRM_ERROR("Error enabling power well %lx\n", power_wells[i]); |
4075 | } | | 4079 | } |
4076 | } | | 4080 | } |
4077 | | | 4081 | |
4078 | mutex_unlock(&dev->struct_mutex); | | 4082 | mutex_unlock(&dev->struct_mutex); |
4079 | } | | 4083 | } |
4080 | | | 4084 | |
4081 | /* Set up chip specific power management-related functions */ | | 4085 | /* Set up chip specific power management-related functions */ |
4082 | void intel_init_pm(struct drm_device *dev) | | 4086 | void intel_init_pm(struct drm_device *dev) |
4083 | { | | 4087 | { |
4084 | struct drm_i915_private *dev_priv = dev->dev_private; | | 4088 | struct drm_i915_private *dev_priv = dev->dev_private; |
4085 | | | 4089 | |
4086 | if (I915_HAS_FBC(dev)) { | | 4090 | if (I915_HAS_FBC(dev)) { |
4087 | if (HAS_PCH_SPLIT(dev)) { | | 4091 | if (HAS_PCH_SPLIT(dev)) { |
4088 | dev_priv->display.fbc_enabled = ironlake_fbc_enabled; | | 4092 | dev_priv->display.fbc_enabled = ironlake_fbc_enabled; |
4089 | dev_priv->display.enable_fbc = ironlake_enable_fbc; | | 4093 | dev_priv->display.enable_fbc = ironlake_enable_fbc; |
4090 | dev_priv->display.disable_fbc = ironlake_disable_fbc; | | 4094 | dev_priv->display.disable_fbc = ironlake_disable_fbc; |
4091 | } else if (IS_GM45(dev)) { | | 4095 | } else if (IS_GM45(dev)) { |
4092 | dev_priv->display.fbc_enabled = g4x_fbc_enabled; | | 4096 | dev_priv->display.fbc_enabled = g4x_fbc_enabled; |
4093 | dev_priv->display.enable_fbc = g4x_enable_fbc; | | 4097 | dev_priv->display.enable_fbc = g4x_enable_fbc; |
4094 | dev_priv->display.disable_fbc = g4x_disable_fbc; | | 4098 | dev_priv->display.disable_fbc = g4x_disable_fbc; |
4095 | } else if (IS_CRESTLINE(dev)) { | | 4099 | } else if (IS_CRESTLINE(dev)) { |
4096 | dev_priv->display.fbc_enabled = i8xx_fbc_enabled; | | 4100 | dev_priv->display.fbc_enabled = i8xx_fbc_enabled; |
4097 | dev_priv->display.enable_fbc = i8xx_enable_fbc; | | 4101 | dev_priv->display.enable_fbc = i8xx_enable_fbc; |
4098 | dev_priv->display.disable_fbc = i8xx_disable_fbc; | | 4102 | dev_priv->display.disable_fbc = i8xx_disable_fbc; |
4099 | } | | 4103 | } |
4100 | /* 855GM needs testing */ | | 4104 | /* 855GM needs testing */ |
4101 | } | | 4105 | } |
4102 | | | 4106 | |
4103 | /* For cxsr */ | | 4107 | /* For cxsr */ |
4104 | if (IS_PINEVIEW(dev)) | | 4108 | if (IS_PINEVIEW(dev)) |
4105 | i915_pineview_get_mem_freq(dev); | | 4109 | i915_pineview_get_mem_freq(dev); |
4106 | else if (IS_GEN5(dev)) | | 4110 | else if (IS_GEN5(dev)) |
4107 | i915_ironlake_get_mem_freq(dev); | | 4111 | i915_ironlake_get_mem_freq(dev); |
4108 | | | 4112 | |
4109 | /* For FIFO watermark updates */ | | 4113 | /* For FIFO watermark updates */ |
4110 | if (HAS_PCH_SPLIT(dev)) { | | 4114 | if (HAS_PCH_SPLIT(dev)) { |
4111 | if (IS_GEN5(dev)) { | | 4115 | if (IS_GEN5(dev)) { |
4112 | if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK) | | 4116 | if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK) |
4113 | dev_priv->display.update_wm = ironlake_update_wm; | | 4117 | dev_priv->display.update_wm = ironlake_update_wm; |
4114 | else { | | 4118 | else { |
4115 | DRM_DEBUG_KMS("Failed to get proper latency. " | | 4119 | DRM_DEBUG_KMS("Failed to get proper latency. " |
4116 | "Disable CxSR\n"); | | 4120 | "Disable CxSR\n"); |
4117 | dev_priv->display.update_wm = NULL; | | 4121 | dev_priv->display.update_wm = NULL; |
4118 | } | | 4122 | } |
4119 | dev_priv->display.init_clock_gating = ironlake_init_clock_gating; | | 4123 | dev_priv->display.init_clock_gating = ironlake_init_clock_gating; |
4120 | } else if (IS_GEN6(dev)) { | | 4124 | } else if (IS_GEN6(dev)) { |
4121 | if (SNB_READ_WM0_LATENCY()) { | | 4125 | if (SNB_READ_WM0_LATENCY()) { |
4122 | dev_priv->display.update_wm = sandybridge_update_wm; | | 4126 | dev_priv->display.update_wm = sandybridge_update_wm; |
4123 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | | 4127 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; |
4124 | } else { | | 4128 | } else { |
4125 | DRM_DEBUG_KMS("Failed to read display plane latency. " | | 4129 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
4126 | "Disable CxSR\n"); | | 4130 | "Disable CxSR\n"); |
4127 | dev_priv->display.update_wm = NULL; | | 4131 | dev_priv->display.update_wm = NULL; |
4128 | } | | 4132 | } |
4129 | dev_priv->display.init_clock_gating = gen6_init_clock_gating; | | 4133 | dev_priv->display.init_clock_gating = gen6_init_clock_gating; |
4130 | } else if (IS_IVYBRIDGE(dev)) { | | 4134 | } else if (IS_IVYBRIDGE(dev)) { |
4131 | /* FIXME: detect B0+ stepping and use auto training */ | | 4135 | /* FIXME: detect B0+ stepping and use auto training */ |
4132 | if (SNB_READ_WM0_LATENCY()) { | | 4136 | if (SNB_READ_WM0_LATENCY()) { |
4133 | dev_priv->display.update_wm = ivybridge_update_wm; | | 4137 | dev_priv->display.update_wm = ivybridge_update_wm; |
4134 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | | 4138 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; |
4135 | } else { | | 4139 | } else { |
4136 | DRM_DEBUG_KMS("Failed to read display plane latency. " | | 4140 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
4137 | "Disable CxSR\n"); | | 4141 | "Disable CxSR\n"); |
4138 | dev_priv->display.update_wm = NULL; | | 4142 | dev_priv->display.update_wm = NULL; |
4139 | } | | 4143 | } |
4140 | dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; | | 4144 | dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; |
4141 | } else if (IS_HASWELL(dev)) { | | 4145 | } else if (IS_HASWELL(dev)) { |
4142 | if (SNB_READ_WM0_LATENCY()) { | | 4146 | if (SNB_READ_WM0_LATENCY()) { |
4143 | dev_priv->display.update_wm = sandybridge_update_wm; | | 4147 | dev_priv->display.update_wm = sandybridge_update_wm; |
4144 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; | | 4148 | dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; |
4145 | dev_priv->display.update_linetime_wm = haswell_update_linetime_wm; | | 4149 | dev_priv->display.update_linetime_wm = haswell_update_linetime_wm; |
4146 | } else { | | 4150 | } else { |
4147 | DRM_DEBUG_KMS("Failed to read display plane latency. " | | 4151 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
4148 | "Disable CxSR\n"); | | 4152 | "Disable CxSR\n"); |
4149 | dev_priv->display.update_wm = NULL; | | 4153 | dev_priv->display.update_wm = NULL; |
4150 | } | | 4154 | } |
4151 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; | | 4155 | dev_priv->display.init_clock_gating = haswell_init_clock_gating; |
4152 | } else | | 4156 | } else |
4153 | dev_priv->display.update_wm = NULL; | | 4157 | dev_priv->display.update_wm = NULL; |
4154 | } else if (IS_VALLEYVIEW(dev)) { | | 4158 | } else if (IS_VALLEYVIEW(dev)) { |
4155 | dev_priv->display.update_wm = valleyview_update_wm; | | 4159 | dev_priv->display.update_wm = valleyview_update_wm; |
4156 | dev_priv->display.init_clock_gating = | | 4160 | dev_priv->display.init_clock_gating = |
4157 | valleyview_init_clock_gating; | | 4161 | valleyview_init_clock_gating; |
4158 | } else if (IS_PINEVIEW(dev)) { | | 4162 | } else if (IS_PINEVIEW(dev)) { |
4159 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), | | 4163 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), |
4160 | dev_priv->is_ddr3, | | 4164 | dev_priv->is_ddr3, |
4161 | dev_priv->fsb_freq, | | 4165 | dev_priv->fsb_freq, |
4162 | dev_priv->mem_freq)) { | | 4166 | dev_priv->mem_freq)) { |
4163 | DRM_INFO("failed to find known CxSR latency " | | 4167 | DRM_INFO("failed to find known CxSR latency " |
4164 | "(found ddr%s fsb freq %d, mem freq %d), " | | 4168 | "(found ddr%s fsb freq %d, mem freq %d), " |
4165 | "disabling CxSR\n", | | 4169 | "disabling CxSR\n", |
4166 | (dev_priv->is_ddr3 == 1) ? "3" : "2", | | 4170 | (dev_priv->is_ddr3 == 1) ? "3" : "2", |
4167 | dev_priv->fsb_freq, dev_priv->mem_freq); | | 4171 | dev_priv->fsb_freq, dev_priv->mem_freq); |
4168 | /* Disable CxSR and never update its watermark again */ | | 4172 | /* Disable CxSR and never update its watermark again */ |
4169 | pineview_disable_cxsr(dev); | | 4173 | pineview_disable_cxsr(dev); |
4170 | dev_priv->display.update_wm = NULL; | | 4174 | dev_priv->display.update_wm = NULL; |
4171 | } else | | 4175 | } else |
4172 | dev_priv->display.update_wm = pineview_update_wm; | | 4176 | dev_priv->display.update_wm = pineview_update_wm; |
4173 | dev_priv->display.init_clock_gating = gen3_init_clock_gating; | | 4177 | dev_priv->display.init_clock_gating = gen3_init_clock_gating; |
4174 | } else if (IS_G4X(dev)) { | | 4178 | } else if (IS_G4X(dev)) { |
4175 | dev_priv->display.update_wm = g4x_update_wm; | | 4179 | dev_priv->display.update_wm = g4x_update_wm; |
4176 | dev_priv->display.init_clock_gating = g4x_init_clock_gating; | | 4180 | dev_priv->display.init_clock_gating = g4x_init_clock_gating; |
4177 | } else if (IS_GEN4(dev)) { | | 4181 | } else if (IS_GEN4(dev)) { |
4178 | dev_priv->display.update_wm = i965_update_wm; | | 4182 | dev_priv->display.update_wm = i965_update_wm; |
4179 | if (IS_CRESTLINE(dev)) | | 4183 | if (IS_CRESTLINE(dev)) |
4180 | dev_priv->display.init_clock_gating = crestline_init_clock_gating; | | 4184 | dev_priv->display.init_clock_gating = crestline_init_clock_gating; |
4181 | else if (IS_BROADWATER(dev)) | | 4185 | else if (IS_BROADWATER(dev)) |
4182 | dev_priv->display.init_clock_gating = broadwater_init_clock_gating; | | 4186 | dev_priv->display.init_clock_gating = broadwater_init_clock_gating; |
4183 | } else if (IS_GEN3(dev)) { | | 4187 | } else if (IS_GEN3(dev)) { |
4184 | dev_priv->display.update_wm = i9xx_update_wm; | | 4188 | dev_priv->display.update_wm = i9xx_update_wm; |
4185 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; | | 4189 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; |
4186 | dev_priv->display.init_clock_gating = gen3_init_clock_gating; | | 4190 | dev_priv->display.init_clock_gating = gen3_init_clock_gating; |
4187 | } else if (IS_I865G(dev)) { | | 4191 | } else if (IS_I865G(dev)) { |
4188 | dev_priv->display.update_wm = i830_update_wm; | | 4192 | dev_priv->display.update_wm = i830_update_wm; |
4189 | dev_priv->display.init_clock_gating = i85x_init_clock_gating; | | 4193 | dev_priv->display.init_clock_gating = i85x_init_clock_gating; |
4190 | dev_priv->display.get_fifo_size = i830_get_fifo_size; | | 4194 | dev_priv->display.get_fifo_size = i830_get_fifo_size; |
4191 | } else if (IS_I85X(dev)) { | | 4195 | } else if (IS_I85X(dev)) { |
4192 | dev_priv->display.update_wm = i9xx_update_wm; | | 4196 | dev_priv->display.update_wm = i9xx_update_wm; |
4193 | dev_priv->display.get_fifo_size = i85x_get_fifo_size; | | 4197 | dev_priv->display.get_fifo_size = i85x_get_fifo_size; |
4194 | dev_priv->display.init_clock_gating = i85x_init_clock_gating; | | 4198 | dev_priv->display.init_clock_gating = i85x_init_clock_gating; |
4195 | } else { | | 4199 | } else { |
4196 | dev_priv->display.update_wm = i830_update_wm; | | 4200 | dev_priv->display.update_wm = i830_update_wm; |
4197 | dev_priv->display.init_clock_gating = i830_init_clock_gating; | | 4201 | dev_priv->display.init_clock_gating = i830_init_clock_gating; |
4198 | if (IS_845G(dev)) | | 4202 | if (IS_845G(dev)) |
4199 | dev_priv->display.get_fifo_size = i845_get_fifo_size; | | 4203 | dev_priv->display.get_fifo_size = i845_get_fifo_size; |
4200 | else | | 4204 | else |
4201 | dev_priv->display.get_fifo_size = i830_get_fifo_size; | | 4205 | dev_priv->display.get_fifo_size = i830_get_fifo_size; |
4202 | } | | 4206 | } |
4203 | } | | 4207 | } |
4204 | | | 4208 | |
4205 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) | | 4209 | static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) |
4206 | { | | 4210 | { |
4207 | u32 gt_thread_status_mask; | | 4211 | u32 gt_thread_status_mask; |
4208 | | | 4212 | |
4209 | if (IS_HASWELL(dev_priv->dev)) | | 4213 | if (IS_HASWELL(dev_priv->dev)) |
4210 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; | | 4214 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK_HSW; |
4211 | else | | 4215 | else |
4212 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; | | 4216 | gt_thread_status_mask = GEN6_GT_THREAD_STATUS_CORE_MASK; |
4213 | | | 4217 | |
4214 | /* w/a for a sporadic read returning 0 by waiting for the GT | | 4218 | /* w/a for a sporadic read returning 0 by waiting for the GT |
4215 | * thread to wake up. | | 4219 | * thread to wake up. |
4216 | */ | | 4220 | */ |
4217 | if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) | | 4221 | if (wait_for_atomic_us((I915_READ_NOTRACE(GEN6_GT_THREAD_STATUS_REG) & gt_thread_status_mask) == 0, 500)) |
4218 | DRM_ERROR("GT thread status wait timed out\n"); | | 4222 | DRM_ERROR("GT thread status wait timed out\n"); |
4219 | } | | 4223 | } |
4220 | | | 4224 | |
4221 | static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) | | 4225 | static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv) |
4222 | { | | 4226 | { |
4223 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | | 4227 | I915_WRITE_NOTRACE(FORCEWAKE, 0); |
4224 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | | 4228 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ |
4225 | } | | 4229 | } |
4226 | | | 4230 | |
4227 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | | 4231 | static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) |
4228 | { | | 4232 | { |
4229 | u32 forcewake_ack; | | 4233 | u32 forcewake_ack; |
4230 | | | 4234 | |
4231 | if (IS_HASWELL(dev_priv->dev)) | | 4235 | if (IS_HASWELL(dev_priv->dev)) |
4232 | forcewake_ack = FORCEWAKE_ACK_HSW; | | 4236 | forcewake_ack = FORCEWAKE_ACK_HSW; |
4233 | else | | 4237 | else |
4234 | forcewake_ack = FORCEWAKE_ACK; | | 4238 | forcewake_ack = FORCEWAKE_ACK; |
4235 | | | 4239 | |
4236 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, | | 4240 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, |
4237 | FORCEWAKE_ACK_TIMEOUT_MS)) | | 4241 | FORCEWAKE_ACK_TIMEOUT_MS)) |
4238 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); | | 4242 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); |
4239 | | | 4243 | |
4240 | I915_WRITE_NOTRACE(FORCEWAKE, FORCEWAKE_KERNEL); | | 4244 | I915_WRITE_NOTRACE(FORCEWAKE, FORCEWAKE_KERNEL); |
4241 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | | 4245 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ |
4242 | | | 4246 | |
4243 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), | | 4247 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), |
4244 | FORCEWAKE_ACK_TIMEOUT_MS)) | | 4248 | FORCEWAKE_ACK_TIMEOUT_MS)) |
4245 | DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); | | 4249 | DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); |
4246 | | | 4250 | |
4247 | __gen6_gt_wait_for_thread_c0(dev_priv); | | 4251 | __gen6_gt_wait_for_thread_c0(dev_priv); |
4248 | } | | 4252 | } |
4249 | | | 4253 | |
4250 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | | 4254 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) |
4251 | { | | 4255 | { |
4252 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); | | 4256 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); |
4253 | /* something from same cacheline, but !FORCEWAKE_MT */ | | 4257 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4254 | POSTING_READ(ECOBUS); | | 4258 | POSTING_READ(ECOBUS); |
4255 | } | | 4259 | } |
4256 | | | 4260 | |
4257 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | | 4261 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) |
4258 | { | | 4262 | { |
4259 | u32 forcewake_ack; | | 4263 | u32 forcewake_ack; |
4260 | | | 4264 | |
4261 | if (IS_HASWELL(dev_priv->dev)) | | 4265 | if (IS_HASWELL(dev_priv->dev)) |
4262 | forcewake_ack = FORCEWAKE_ACK_HSW; | | 4266 | forcewake_ack = FORCEWAKE_ACK_HSW; |
4263 | else | | 4267 | else |
4264 | forcewake_ack = FORCEWAKE_MT_ACK; | | 4268 | forcewake_ack = FORCEWAKE_MT_ACK; |
4265 | | | 4269 | |
4266 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, | | 4270 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, |
4267 | FORCEWAKE_ACK_TIMEOUT_MS)) | | 4271 | FORCEWAKE_ACK_TIMEOUT_MS)) |
4268 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); | | 4272 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); |
4269 | | | 4273 | |
4270 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | | 4274 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); |
4271 | /* something from same cacheline, but !FORCEWAKE_MT */ | | 4275 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4272 | POSTING_READ(ECOBUS); | | 4276 | POSTING_READ(ECOBUS); |
4273 | | | 4277 | |
4274 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), | | 4278 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), |
4275 | FORCEWAKE_ACK_TIMEOUT_MS)) | | 4279 | FORCEWAKE_ACK_TIMEOUT_MS)) |
4276 | DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); | | 4280 | DRM_ERROR("Timed out waiting for forcewake to ack request.\n"); |
4277 | | | 4281 | |
4278 | __gen6_gt_wait_for_thread_c0(dev_priv); | | 4282 | __gen6_gt_wait_for_thread_c0(dev_priv); |
4279 | } | | 4283 | } |
4280 | | | 4284 | |
4281 | /* | | 4285 | /* |
4282 | * Generally this is called implicitly by the register read function. However, | | 4286 | * Generally this is called implicitly by the register read function. However, |
4283 | * if some sequence requires the GT to not power down then this function should | | 4287 | * if some sequence requires the GT to not power down then this function should |
4284 | * be called at the beginning of the sequence followed by a call to | | 4288 | * be called at the beginning of the sequence followed by a call to |
4285 | * gen6_gt_force_wake_put() at the end of the sequence. | | 4289 | * gen6_gt_force_wake_put() at the end of the sequence. |
4286 | */ | | 4290 | */ |
4287 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | | 4291 | void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) |
4288 | { | | 4292 | { |
4289 | unsigned long irqflags; | | 4293 | unsigned long irqflags; |
4290 | | | 4294 | |
4291 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | | 4295 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); |
4292 | if (dev_priv->forcewake_count++ == 0) | | 4296 | if (dev_priv->forcewake_count++ == 0) |
4293 | dev_priv->gt.force_wake_get(dev_priv); | | 4297 | dev_priv->gt.force_wake_get(dev_priv); |
4294 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | | 4298 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); |
4295 | } | | 4299 | } |
4296 | | | 4300 | |
4297 | void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | | 4301 | void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) |
4298 | { | | 4302 | { |
4299 | u32 gtfifodbg; | | 4303 | u32 gtfifodbg; |
4300 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); | | 4304 | gtfifodbg = I915_READ_NOTRACE(GTFIFODBG); |
4301 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, | | 4305 | if (WARN(gtfifodbg & GT_FIFO_CPU_ERROR_MASK, |
4302 | "MMIO read or write has been dropped %x\n", gtfifodbg)) | | 4306 | "MMIO read or write has been dropped %x\n", gtfifodbg)) |
4303 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); | | 4307 | I915_WRITE_NOTRACE(GTFIFODBG, GT_FIFO_CPU_ERROR_MASK); |
4304 | } | | 4308 | } |
4305 | | | 4309 | |
4306 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | | 4310 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
4307 | { | | 4311 | { |
4308 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | | 4312 | I915_WRITE_NOTRACE(FORCEWAKE, 0); |
4309 | /* something from same cacheline, but !FORCEWAKE */ | | 4313 | /* something from same cacheline, but !FORCEWAKE */ |
4310 | POSTING_READ(ECOBUS); | | 4314 | POSTING_READ(ECOBUS); |
4311 | gen6_gt_check_fifodbg(dev_priv); | | 4315 | gen6_gt_check_fifodbg(dev_priv); |
4312 | } | | 4316 | } |
4313 | | | 4317 | |
4314 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | | 4318 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) |
4315 | { | | 4319 | { |
4316 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | | 4320 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
4317 | /* something from same cacheline, but !FORCEWAKE_MT */ | | 4321 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4318 | POSTING_READ(ECOBUS); | | 4322 | POSTING_READ(ECOBUS); |
4319 | gen6_gt_check_fifodbg(dev_priv); | | 4323 | gen6_gt_check_fifodbg(dev_priv); |
4320 | } | | 4324 | } |
4321 | | | 4325 | |
4322 | /* | | 4326 | /* |
4323 | * see gen6_gt_force_wake_get() | | 4327 | * see gen6_gt_force_wake_get() |
4324 | */ | | 4328 | */ |
4325 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | | 4329 | void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
4326 | { | | 4330 | { |
4327 | unsigned long irqflags; | | 4331 | unsigned long irqflags; |
4328 | | | 4332 | |
4329 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); | | 4333 | spin_lock_irqsave(&dev_priv->gt_lock, irqflags); |
4330 | if (--dev_priv->forcewake_count == 0) | | 4334 | if (--dev_priv->forcewake_count == 0) |
4331 | dev_priv->gt.force_wake_put(dev_priv); | | 4335 | dev_priv->gt.force_wake_put(dev_priv); |
4332 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); | | 4336 | spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); |
4333 | } | | 4337 | } |
4334 | | | 4338 | |
4335 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | | 4339 | int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) |
4336 | { | | 4340 | { |
4337 | int ret = 0; | | 4341 | int ret = 0; |
4338 | | | 4342 | |
4339 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { | | 4343 | if (dev_priv->gt_fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) { |
4340 | int loop = 500; | | 4344 | int loop = 500; |
4341 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); | | 4345 | u32 fifo = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES); |
4342 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { | | 4346 | while (fifo <= GT_FIFO_NUM_RESERVED_ENTRIES && loop--) { |