]>
Commit | Line | Data |
---|---|---|
94b4f3ba CW |
1 | /* |
2 | * Copyright © 2016 Intel Corporation | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
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 | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
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 | |
13 | * Software. | |
14 | * | |
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, | |
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 | |
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 | |
21 | * IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
a8c9b849 MW |
25 | #include <drm/drm_print.h> |
26 | ||
b978520d | 27 | #include "intel_device_info.h" |
94b4f3ba CW |
28 | #include "i915_drv.h" |
29 | ||
2e0d26f8 JN |
30 | #define PLATFORM_NAME(x) [INTEL_##x] = #x |
31 | static const char * const platform_names[] = { | |
32 | PLATFORM_NAME(I830), | |
33 | PLATFORM_NAME(I845G), | |
34 | PLATFORM_NAME(I85X), | |
35 | PLATFORM_NAME(I865G), | |
36 | PLATFORM_NAME(I915G), | |
37 | PLATFORM_NAME(I915GM), | |
38 | PLATFORM_NAME(I945G), | |
39 | PLATFORM_NAME(I945GM), | |
40 | PLATFORM_NAME(G33), | |
41 | PLATFORM_NAME(PINEVIEW), | |
c0f86832 JN |
42 | PLATFORM_NAME(I965G), |
43 | PLATFORM_NAME(I965GM), | |
f69c11ae JN |
44 | PLATFORM_NAME(G45), |
45 | PLATFORM_NAME(GM45), | |
2e0d26f8 JN |
46 | PLATFORM_NAME(IRONLAKE), |
47 | PLATFORM_NAME(SANDYBRIDGE), | |
48 | PLATFORM_NAME(IVYBRIDGE), | |
49 | PLATFORM_NAME(VALLEYVIEW), | |
50 | PLATFORM_NAME(HASWELL), | |
51 | PLATFORM_NAME(BROADWELL), | |
52 | PLATFORM_NAME(CHERRYVIEW), | |
53 | PLATFORM_NAME(SKYLAKE), | |
54 | PLATFORM_NAME(BROXTON), | |
55 | PLATFORM_NAME(KABYLAKE), | |
56 | PLATFORM_NAME(GEMINILAKE), | |
71851fa8 | 57 | PLATFORM_NAME(COFFEELAKE), |
413f3c19 | 58 | PLATFORM_NAME(CANNONLAKE), |
41231001 | 59 | PLATFORM_NAME(ICELAKE), |
2e0d26f8 JN |
60 | }; |
61 | #undef PLATFORM_NAME | |
62 | ||
63 | const char *intel_platform_name(enum intel_platform platform) | |
64 | { | |
9160095c JN |
65 | BUILD_BUG_ON(ARRAY_SIZE(platform_names) != INTEL_MAX_PLATFORMS); |
66 | ||
2e0d26f8 JN |
67 | if (WARN_ON_ONCE(platform >= ARRAY_SIZE(platform_names) || |
68 | platform_names[platform] == NULL)) | |
69 | return "<unknown>"; | |
70 | ||
71 | return platform_names[platform]; | |
72 | } | |
73 | ||
a8c9b849 MW |
74 | void intel_device_info_dump_flags(const struct intel_device_info *info, |
75 | struct drm_printer *p) | |
76 | { | |
77 | #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name)); | |
78 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); | |
79 | #undef PRINT_FLAG | |
d53db442 JRS |
80 | |
81 | #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name)); | |
82 | DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); | |
83 | #undef PRINT_FLAG | |
a8c9b849 MW |
84 | } |
85 | ||
5fbbe8d4 MW |
86 | static void sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) |
87 | { | |
8cc76693 LL |
88 | int s; |
89 | ||
0ef904bb TU |
90 | drm_printf(p, "slice total: %u, mask=%04x\n", |
91 | hweight8(sseu->slice_mask), sseu->slice_mask); | |
5fbbe8d4 | 92 | drm_printf(p, "subslice total: %u\n", sseu_subslice_total(sseu)); |
0ef904bb TU |
93 | for (s = 0; s < sseu->max_slices; s++) { |
94 | drm_printf(p, "slice%d: %u subslices, mask=%04x\n", | |
8cc76693 LL |
95 | s, hweight8(sseu->subslice_mask[s]), |
96 | sseu->subslice_mask[s]); | |
97 | } | |
5fbbe8d4 MW |
98 | drm_printf(p, "EU total: %u\n", sseu->eu_total); |
99 | drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice); | |
100 | drm_printf(p, "has slice power gating: %s\n", | |
101 | yesno(sseu->has_slice_pg)); | |
102 | drm_printf(p, "has subslice power gating: %s\n", | |
103 | yesno(sseu->has_subslice_pg)); | |
104 | drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg)); | |
105 | } | |
106 | ||
0258404f | 107 | void intel_device_info_dump_runtime(const struct intel_runtime_info *info, |
5fbbe8d4 MW |
108 | struct drm_printer *p) |
109 | { | |
110 | sseu_dump(&info->sseu, p); | |
111 | ||
112 | drm_printf(p, "CS timestamp frequency: %u kHz\n", | |
113 | info->cs_timestamp_frequency_khz); | |
114 | } | |
115 | ||
79e9cd5f LL |
116 | void intel_device_info_dump_topology(const struct sseu_dev_info *sseu, |
117 | struct drm_printer *p) | |
118 | { | |
119 | int s, ss; | |
120 | ||
121 | if (sseu->max_slices == 0) { | |
122 | drm_printf(p, "Unavailable\n"); | |
123 | return; | |
124 | } | |
125 | ||
126 | for (s = 0; s < sseu->max_slices; s++) { | |
127 | drm_printf(p, "slice%d: %u subslice(s) (0x%hhx):\n", | |
128 | s, hweight8(sseu->subslice_mask[s]), | |
129 | sseu->subslice_mask[s]); | |
130 | ||
131 | for (ss = 0; ss < sseu->max_subslices; ss++) { | |
132 | u16 enabled_eus = sseu_get_eus(sseu, s, ss); | |
133 | ||
134 | drm_printf(p, "\tsubslice%d: %u EUs (0x%hx)\n", | |
135 | ss, hweight16(enabled_eus), enabled_eus); | |
136 | } | |
137 | } | |
138 | } | |
139 | ||
8cc76693 LL |
140 | static u16 compute_eu_total(const struct sseu_dev_info *sseu) |
141 | { | |
142 | u16 i, total = 0; | |
143 | ||
144 | for (i = 0; i < ARRAY_SIZE(sseu->eu_mask); i++) | |
145 | total += hweight8(sseu->eu_mask[i]); | |
146 | ||
147 | return total; | |
148 | } | |
149 | ||
8b5eb5e2 KG |
150 | static void gen11_sseu_info_init(struct drm_i915_private *dev_priv) |
151 | { | |
0258404f | 152 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
8b5eb5e2 KG |
153 | u8 s_en; |
154 | u32 ss_en, ss_en_mask; | |
155 | u8 eu_en; | |
156 | int s; | |
157 | ||
158 | sseu->max_slices = 1; | |
159 | sseu->max_subslices = 8; | |
160 | sseu->max_eus_per_subslice = 8; | |
161 | ||
162 | s_en = I915_READ(GEN11_GT_SLICE_ENABLE) & GEN11_GT_S_ENA_MASK; | |
163 | ss_en = ~I915_READ(GEN11_GT_SUBSLICE_DISABLE); | |
164 | ss_en_mask = BIT(sseu->max_subslices) - 1; | |
165 | eu_en = ~(I915_READ(GEN11_EU_DISABLE) & GEN11_EU_DIS_MASK); | |
166 | ||
167 | for (s = 0; s < sseu->max_slices; s++) { | |
168 | if (s_en & BIT(s)) { | |
169 | int ss_idx = sseu->max_subslices * s; | |
170 | int ss; | |
171 | ||
172 | sseu->slice_mask |= BIT(s); | |
173 | sseu->subslice_mask[s] = (ss_en >> ss_idx) & ss_en_mask; | |
174 | for (ss = 0; ss < sseu->max_subslices; ss++) { | |
175 | if (sseu->subslice_mask[s] & BIT(ss)) | |
176 | sseu_set_eus(sseu, s, ss, eu_en); | |
177 | } | |
178 | } | |
179 | } | |
180 | sseu->eu_per_subslice = hweight8(eu_en); | |
181 | sseu->eu_total = compute_eu_total(sseu); | |
182 | ||
183 | /* ICL has no power gating restrictions. */ | |
184 | sseu->has_slice_pg = 1; | |
185 | sseu->has_subslice_pg = 1; | |
186 | sseu->has_eu_pg = 1; | |
187 | } | |
188 | ||
4e9767bc BW |
189 | static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) |
190 | { | |
0258404f | 191 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
4e9767bc | 192 | const u32 fuse2 = I915_READ(GEN8_FUSE2); |
8cc76693 LL |
193 | int s, ss; |
194 | const int eu_mask = 0xff; | |
195 | u32 subslice_mask, eu_en; | |
4e9767bc BW |
196 | |
197 | sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >> | |
198 | GEN10_F2_S_ENA_SHIFT; | |
8cc76693 LL |
199 | sseu->max_slices = 6; |
200 | sseu->max_subslices = 4; | |
201 | sseu->max_eus_per_subslice = 8; | |
4e9767bc | 202 | |
8cc76693 LL |
203 | subslice_mask = (1 << 4) - 1; |
204 | subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >> | |
205 | GEN10_F2_SS_DIS_SHIFT); | |
206 | ||
207 | /* | |
208 | * Slice0 can have up to 3 subslices, but there are only 2 in | |
209 | * slice1/2. | |
210 | */ | |
211 | sseu->subslice_mask[0] = subslice_mask; | |
212 | for (s = 1; s < sseu->max_slices; s++) | |
213 | sseu->subslice_mask[s] = subslice_mask & 0x3; | |
214 | ||
215 | /* Slice0 */ | |
216 | eu_en = ~I915_READ(GEN8_EU_DISABLE0); | |
217 | for (ss = 0; ss < sseu->max_subslices; ss++) | |
218 | sseu_set_eus(sseu, 0, ss, (eu_en >> (8 * ss)) & eu_mask); | |
219 | /* Slice1 */ | |
220 | sseu_set_eus(sseu, 1, 0, (eu_en >> 24) & eu_mask); | |
221 | eu_en = ~I915_READ(GEN8_EU_DISABLE1); | |
222 | sseu_set_eus(sseu, 1, 1, eu_en & eu_mask); | |
223 | /* Slice2 */ | |
224 | sseu_set_eus(sseu, 2, 0, (eu_en >> 8) & eu_mask); | |
225 | sseu_set_eus(sseu, 2, 1, (eu_en >> 16) & eu_mask); | |
226 | /* Slice3 */ | |
227 | sseu_set_eus(sseu, 3, 0, (eu_en >> 24) & eu_mask); | |
228 | eu_en = ~I915_READ(GEN8_EU_DISABLE2); | |
229 | sseu_set_eus(sseu, 3, 1, eu_en & eu_mask); | |
230 | /* Slice4 */ | |
231 | sseu_set_eus(sseu, 4, 0, (eu_en >> 8) & eu_mask); | |
232 | sseu_set_eus(sseu, 4, 1, (eu_en >> 16) & eu_mask); | |
233 | /* Slice5 */ | |
234 | sseu_set_eus(sseu, 5, 0, (eu_en >> 24) & eu_mask); | |
235 | eu_en = ~I915_READ(GEN10_EU_DISABLE3); | |
236 | sseu_set_eus(sseu, 5, 1, eu_en & eu_mask); | |
237 | ||
238 | /* Do a second pass where we mark the subslices disabled if all their | |
239 | * eus are off. | |
240 | */ | |
241 | for (s = 0; s < sseu->max_slices; s++) { | |
242 | for (ss = 0; ss < sseu->max_subslices; ss++) { | |
243 | if (sseu_get_eus(sseu, s, ss) == 0) | |
244 | sseu->subslice_mask[s] &= ~BIT(ss); | |
245 | } | |
246 | } | |
247 | ||
248 | sseu->eu_total = compute_eu_total(sseu); | |
4e9767bc BW |
249 | |
250 | /* | |
251 | * CNL is expected to always have a uniform distribution | |
252 | * of EU across subslices with the exception that any one | |
253 | * EU in any one subslice may be fused off for die | |
254 | * recovery. | |
255 | */ | |
256 | sseu->eu_per_subslice = sseu_subslice_total(sseu) ? | |
257 | DIV_ROUND_UP(sseu->eu_total, | |
258 | sseu_subslice_total(sseu)) : 0; | |
259 | ||
260 | /* No restrictions on Power Gating */ | |
261 | sseu->has_slice_pg = 1; | |
262 | sseu->has_subslice_pg = 1; | |
263 | sseu->has_eu_pg = 1; | |
264 | } | |
265 | ||
94b4f3ba CW |
266 | static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) |
267 | { | |
0258404f | 268 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
8cc76693 | 269 | u32 fuse; |
94b4f3ba CW |
270 | |
271 | fuse = I915_READ(CHV_FUSE_GT); | |
272 | ||
f08a0c92 | 273 | sseu->slice_mask = BIT(0); |
8cc76693 LL |
274 | sseu->max_slices = 1; |
275 | sseu->max_subslices = 2; | |
276 | sseu->max_eus_per_subslice = 8; | |
94b4f3ba CW |
277 | |
278 | if (!(fuse & CHV_FGT_DISABLE_SS0)) { | |
8cc76693 LL |
279 | u8 disabled_mask = |
280 | ((fuse & CHV_FGT_EU_DIS_SS0_R0_MASK) >> | |
281 | CHV_FGT_EU_DIS_SS0_R0_SHIFT) | | |
282 | (((fuse & CHV_FGT_EU_DIS_SS0_R1_MASK) >> | |
283 | CHV_FGT_EU_DIS_SS0_R1_SHIFT) << 4); | |
284 | ||
285 | sseu->subslice_mask[0] |= BIT(0); | |
286 | sseu_set_eus(sseu, 0, 0, ~disabled_mask); | |
94b4f3ba CW |
287 | } |
288 | ||
289 | if (!(fuse & CHV_FGT_DISABLE_SS1)) { | |
8cc76693 LL |
290 | u8 disabled_mask = |
291 | ((fuse & CHV_FGT_EU_DIS_SS1_R0_MASK) >> | |
292 | CHV_FGT_EU_DIS_SS1_R0_SHIFT) | | |
293 | (((fuse & CHV_FGT_EU_DIS_SS1_R1_MASK) >> | |
294 | CHV_FGT_EU_DIS_SS1_R1_SHIFT) << 4); | |
295 | ||
296 | sseu->subslice_mask[0] |= BIT(1); | |
297 | sseu_set_eus(sseu, 0, 1, ~disabled_mask); | |
94b4f3ba CW |
298 | } |
299 | ||
8cc76693 LL |
300 | sseu->eu_total = compute_eu_total(sseu); |
301 | ||
94b4f3ba CW |
302 | /* |
303 | * CHV expected to always have a uniform distribution of EU | |
304 | * across subslices. | |
305 | */ | |
57ec171e ID |
306 | sseu->eu_per_subslice = sseu_subslice_total(sseu) ? |
307 | sseu->eu_total / sseu_subslice_total(sseu) : | |
94b4f3ba CW |
308 | 0; |
309 | /* | |
310 | * CHV supports subslice power gating on devices with more than | |
311 | * one subslice, and supports EU power gating on devices with | |
312 | * more than one EU pair per subslice. | |
313 | */ | |
43b67998 | 314 | sseu->has_slice_pg = 0; |
57ec171e | 315 | sseu->has_subslice_pg = sseu_subslice_total(sseu) > 1; |
43b67998 | 316 | sseu->has_eu_pg = (sseu->eu_per_subslice > 2); |
94b4f3ba CW |
317 | } |
318 | ||
319 | static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) | |
320 | { | |
321 | struct intel_device_info *info = mkwrite_device_info(dev_priv); | |
0258404f | 322 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
94b4f3ba | 323 | int s, ss; |
8cc76693 LL |
324 | u32 fuse2, eu_disable, subslice_mask; |
325 | const u8 eu_mask = 0xff; | |
94b4f3ba CW |
326 | |
327 | fuse2 = I915_READ(GEN8_FUSE2); | |
f08a0c92 | 328 | sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; |
94b4f3ba | 329 | |
8cc76693 LL |
330 | /* BXT has a single slice and at most 3 subslices. */ |
331 | sseu->max_slices = IS_GEN9_LP(dev_priv) ? 1 : 3; | |
332 | sseu->max_subslices = IS_GEN9_LP(dev_priv) ? 3 : 4; | |
333 | sseu->max_eus_per_subslice = 8; | |
334 | ||
94b4f3ba CW |
335 | /* |
336 | * The subslice disable field is global, i.e. it applies | |
337 | * to each of the enabled slices. | |
338 | */ | |
8cc76693 LL |
339 | subslice_mask = (1 << sseu->max_subslices) - 1; |
340 | subslice_mask &= ~((fuse2 & GEN9_F2_SS_DIS_MASK) >> | |
341 | GEN9_F2_SS_DIS_SHIFT); | |
94b4f3ba CW |
342 | |
343 | /* | |
344 | * Iterate through enabled slices and subslices to | |
345 | * count the total enabled EU. | |
346 | */ | |
8cc76693 | 347 | for (s = 0; s < sseu->max_slices; s++) { |
f08a0c92 | 348 | if (!(sseu->slice_mask & BIT(s))) |
94b4f3ba CW |
349 | /* skip disabled slice */ |
350 | continue; | |
351 | ||
8cc76693 LL |
352 | sseu->subslice_mask[s] = subslice_mask; |
353 | ||
94b4f3ba | 354 | eu_disable = I915_READ(GEN9_EU_DISABLE(s)); |
8cc76693 | 355 | for (ss = 0; ss < sseu->max_subslices; ss++) { |
94b4f3ba | 356 | int eu_per_ss; |
8cc76693 | 357 | u8 eu_disabled_mask; |
94b4f3ba | 358 | |
8cc76693 | 359 | if (!(sseu->subslice_mask[s] & BIT(ss))) |
94b4f3ba CW |
360 | /* skip disabled subslice */ |
361 | continue; | |
362 | ||
b3e7f866 | 363 | eu_disabled_mask = (eu_disable >> (ss * 8)) & eu_mask; |
8cc76693 LL |
364 | |
365 | sseu_set_eus(sseu, s, ss, ~eu_disabled_mask); | |
366 | ||
367 | eu_per_ss = sseu->max_eus_per_subslice - | |
368 | hweight8(eu_disabled_mask); | |
94b4f3ba CW |
369 | |
370 | /* | |
371 | * Record which subslice(s) has(have) 7 EUs. we | |
372 | * can tune the hash used to spread work among | |
373 | * subslices if they are unbalanced. | |
374 | */ | |
375 | if (eu_per_ss == 7) | |
43b67998 | 376 | sseu->subslice_7eu[s] |= BIT(ss); |
94b4f3ba CW |
377 | } |
378 | } | |
379 | ||
8cc76693 LL |
380 | sseu->eu_total = compute_eu_total(sseu); |
381 | ||
94b4f3ba CW |
382 | /* |
383 | * SKL is expected to always have a uniform distribution | |
384 | * of EU across subslices with the exception that any one | |
385 | * EU in any one subslice may be fused off for die | |
386 | * recovery. BXT is expected to be perfectly uniform in EU | |
387 | * distribution. | |
388 | */ | |
57ec171e | 389 | sseu->eu_per_subslice = sseu_subslice_total(sseu) ? |
43b67998 | 390 | DIV_ROUND_UP(sseu->eu_total, |
57ec171e | 391 | sseu_subslice_total(sseu)) : 0; |
94b4f3ba | 392 | /* |
c7ae7e9a | 393 | * SKL+ supports slice power gating on devices with more than |
94b4f3ba | 394 | * one slice, and supports EU power gating on devices with |
c7ae7e9a | 395 | * more than one EU pair per subslice. BXT+ supports subslice |
94b4f3ba CW |
396 | * power gating on devices with more than one subslice, and |
397 | * supports EU power gating on devices with more than one EU | |
398 | * pair per subslice. | |
399 | */ | |
43b67998 | 400 | sseu->has_slice_pg = |
c7ae7e9a | 401 | !IS_GEN9_LP(dev_priv) && hweight8(sseu->slice_mask) > 1; |
43b67998 | 402 | sseu->has_subslice_pg = |
254e0931 | 403 | IS_GEN9_LP(dev_priv) && sseu_subslice_total(sseu) > 1; |
43b67998 | 404 | sseu->has_eu_pg = sseu->eu_per_subslice > 2; |
94b4f3ba | 405 | |
234516af | 406 | if (IS_GEN9_LP(dev_priv)) { |
8cc76693 LL |
407 | #define IS_SS_DISABLED(ss) (!(sseu->subslice_mask[0] & BIT(ss))) |
408 | info->has_pooled_eu = hweight8(sseu->subslice_mask[0]) == 3; | |
234516af | 409 | |
43b67998 | 410 | sseu->min_eu_in_pool = 0; |
94b4f3ba | 411 | if (info->has_pooled_eu) { |
57ec171e | 412 | if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) |
43b67998 | 413 | sseu->min_eu_in_pool = 3; |
57ec171e | 414 | else if (IS_SS_DISABLED(1)) |
43b67998 | 415 | sseu->min_eu_in_pool = 6; |
94b4f3ba | 416 | else |
43b67998 | 417 | sseu->min_eu_in_pool = 9; |
94b4f3ba CW |
418 | } |
419 | #undef IS_SS_DISABLED | |
420 | } | |
421 | } | |
422 | ||
423 | static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) | |
424 | { | |
0258404f | 425 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
94b4f3ba | 426 | int s, ss; |
8cc76693 | 427 | u32 fuse2, subslice_mask, eu_disable[3]; /* s_max */ |
94b4f3ba CW |
428 | |
429 | fuse2 = I915_READ(GEN8_FUSE2); | |
f08a0c92 | 430 | sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; |
8cc76693 LL |
431 | sseu->max_slices = 3; |
432 | sseu->max_subslices = 3; | |
433 | sseu->max_eus_per_subslice = 8; | |
434 | ||
57ec171e ID |
435 | /* |
436 | * The subslice disable field is global, i.e. it applies | |
437 | * to each of the enabled slices. | |
438 | */ | |
8cc76693 LL |
439 | subslice_mask = GENMASK(sseu->max_subslices - 1, 0); |
440 | subslice_mask &= ~((fuse2 & GEN8_F2_SS_DIS_MASK) >> | |
441 | GEN8_F2_SS_DIS_SHIFT); | |
94b4f3ba CW |
442 | |
443 | eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK; | |
444 | eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) | | |
445 | ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) << | |
446 | (32 - GEN8_EU_DIS0_S1_SHIFT)); | |
447 | eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) | | |
448 | ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) << | |
449 | (32 - GEN8_EU_DIS1_S2_SHIFT)); | |
450 | ||
94b4f3ba CW |
451 | /* |
452 | * Iterate through enabled slices and subslices to | |
453 | * count the total enabled EU. | |
454 | */ | |
8cc76693 | 455 | for (s = 0; s < sseu->max_slices; s++) { |
f08a0c92 | 456 | if (!(sseu->slice_mask & BIT(s))) |
94b4f3ba CW |
457 | /* skip disabled slice */ |
458 | continue; | |
459 | ||
8cc76693 LL |
460 | sseu->subslice_mask[s] = subslice_mask; |
461 | ||
462 | for (ss = 0; ss < sseu->max_subslices; ss++) { | |
463 | u8 eu_disabled_mask; | |
94b4f3ba CW |
464 | u32 n_disabled; |
465 | ||
63ac3328 | 466 | if (!(sseu->subslice_mask[s] & BIT(ss))) |
94b4f3ba CW |
467 | /* skip disabled subslice */ |
468 | continue; | |
469 | ||
8cc76693 LL |
470 | eu_disabled_mask = |
471 | eu_disable[s] >> (ss * sseu->max_eus_per_subslice); | |
472 | ||
473 | sseu_set_eus(sseu, s, ss, ~eu_disabled_mask); | |
474 | ||
475 | n_disabled = hweight8(eu_disabled_mask); | |
94b4f3ba CW |
476 | |
477 | /* | |
478 | * Record which subslices have 7 EUs. | |
479 | */ | |
8cc76693 | 480 | if (sseu->max_eus_per_subslice - n_disabled == 7) |
43b67998 | 481 | sseu->subslice_7eu[s] |= 1 << ss; |
94b4f3ba CW |
482 | } |
483 | } | |
484 | ||
8cc76693 LL |
485 | sseu->eu_total = compute_eu_total(sseu); |
486 | ||
94b4f3ba CW |
487 | /* |
488 | * BDW is expected to always have a uniform distribution of EU across | |
489 | * subslices with the exception that any one EU in any one subslice may | |
490 | * be fused off for die recovery. | |
491 | */ | |
57ec171e ID |
492 | sseu->eu_per_subslice = sseu_subslice_total(sseu) ? |
493 | DIV_ROUND_UP(sseu->eu_total, | |
494 | sseu_subslice_total(sseu)) : 0; | |
94b4f3ba CW |
495 | |
496 | /* | |
497 | * BDW supports slice power gating on devices with more than | |
498 | * one slice. | |
499 | */ | |
f08a0c92 | 500 | sseu->has_slice_pg = hweight8(sseu->slice_mask) > 1; |
43b67998 ID |
501 | sseu->has_subslice_pg = 0; |
502 | sseu->has_eu_pg = 0; | |
94b4f3ba CW |
503 | } |
504 | ||
b8ec759e LL |
505 | static void haswell_sseu_info_init(struct drm_i915_private *dev_priv) |
506 | { | |
0258404f | 507 | struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu; |
b8ec759e | 508 | u32 fuse1; |
8cc76693 | 509 | int s, ss; |
b8ec759e LL |
510 | |
511 | /* | |
512 | * There isn't a register to tell us how many slices/subslices. We | |
513 | * work off the PCI-ids here. | |
514 | */ | |
0258404f | 515 | switch (INTEL_INFO(dev_priv)->gt) { |
b8ec759e | 516 | default: |
0258404f | 517 | MISSING_CASE(INTEL_INFO(dev_priv)->gt); |
b8ec759e LL |
518 | /* fall through */ |
519 | case 1: | |
520 | sseu->slice_mask = BIT(0); | |
8cc76693 | 521 | sseu->subslice_mask[0] = BIT(0); |
b8ec759e LL |
522 | break; |
523 | case 2: | |
524 | sseu->slice_mask = BIT(0); | |
8cc76693 | 525 | sseu->subslice_mask[0] = BIT(0) | BIT(1); |
b8ec759e LL |
526 | break; |
527 | case 3: | |
528 | sseu->slice_mask = BIT(0) | BIT(1); | |
8cc76693 LL |
529 | sseu->subslice_mask[0] = BIT(0) | BIT(1); |
530 | sseu->subslice_mask[1] = BIT(0) | BIT(1); | |
b8ec759e LL |
531 | break; |
532 | } | |
533 | ||
8cc76693 LL |
534 | sseu->max_slices = hweight8(sseu->slice_mask); |
535 | sseu->max_subslices = hweight8(sseu->subslice_mask[0]); | |
536 | ||
b8ec759e LL |
537 | fuse1 = I915_READ(HSW_PAVP_FUSE1); |
538 | switch ((fuse1 & HSW_F1_EU_DIS_MASK) >> HSW_F1_EU_DIS_SHIFT) { | |
539 | default: | |
540 | MISSING_CASE((fuse1 & HSW_F1_EU_DIS_MASK) >> | |
541 | HSW_F1_EU_DIS_SHIFT); | |
542 | /* fall through */ | |
543 | case HSW_F1_EU_DIS_10EUS: | |
544 | sseu->eu_per_subslice = 10; | |
545 | break; | |
546 | case HSW_F1_EU_DIS_8EUS: | |
547 | sseu->eu_per_subslice = 8; | |
548 | break; | |
549 | case HSW_F1_EU_DIS_6EUS: | |
550 | sseu->eu_per_subslice = 6; | |
551 | break; | |
552 | } | |
8cc76693 LL |
553 | sseu->max_eus_per_subslice = sseu->eu_per_subslice; |
554 | ||
555 | for (s = 0; s < sseu->max_slices; s++) { | |
556 | for (ss = 0; ss < sseu->max_subslices; ss++) { | |
557 | sseu_set_eus(sseu, s, ss, | |
558 | (1UL << sseu->eu_per_subslice) - 1); | |
559 | } | |
560 | } | |
b8ec759e | 561 | |
8cc76693 | 562 | sseu->eu_total = compute_eu_total(sseu); |
b8ec759e LL |
563 | |
564 | /* No powergating for you. */ | |
565 | sseu->has_slice_pg = 0; | |
566 | sseu->has_subslice_pg = 0; | |
567 | sseu->has_eu_pg = 0; | |
568 | } | |
569 | ||
f577a03b | 570 | static u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) |
dab91783 LL |
571 | { |
572 | u32 ts_override = I915_READ(GEN9_TIMESTAMP_OVERRIDE); | |
f577a03b | 573 | u32 base_freq, frac_freq; |
dab91783 LL |
574 | |
575 | base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >> | |
576 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1; | |
f577a03b | 577 | base_freq *= 1000; |
dab91783 LL |
578 | |
579 | frac_freq = ((ts_override & | |
580 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >> | |
581 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT); | |
f577a03b | 582 | frac_freq = 1000 / (frac_freq + 1); |
dab91783 LL |
583 | |
584 | return base_freq + frac_freq; | |
585 | } | |
586 | ||
d775a7b1 PZ |
587 | static u32 gen10_get_crystal_clock_freq(struct drm_i915_private *dev_priv, |
588 | u32 rpm_config_reg) | |
589 | { | |
590 | u32 f19_2_mhz = 19200; | |
591 | u32 f24_mhz = 24000; | |
592 | u32 crystal_clock = (rpm_config_reg & | |
593 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
594 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
595 | ||
596 | switch (crystal_clock) { | |
597 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
598 | return f19_2_mhz; | |
599 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
600 | return f24_mhz; | |
601 | default: | |
602 | MISSING_CASE(crystal_clock); | |
603 | return 0; | |
604 | } | |
605 | } | |
606 | ||
607 | static u32 gen11_get_crystal_clock_freq(struct drm_i915_private *dev_priv, | |
608 | u32 rpm_config_reg) | |
609 | { | |
610 | u32 f19_2_mhz = 19200; | |
611 | u32 f24_mhz = 24000; | |
612 | u32 f25_mhz = 25000; | |
613 | u32 f38_4_mhz = 38400; | |
614 | u32 crystal_clock = (rpm_config_reg & | |
615 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
616 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
617 | ||
618 | switch (crystal_clock) { | |
619 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
620 | return f24_mhz; | |
621 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
622 | return f19_2_mhz; | |
623 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ: | |
624 | return f38_4_mhz; | |
625 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ: | |
626 | return f25_mhz; | |
627 | default: | |
628 | MISSING_CASE(crystal_clock); | |
629 | return 0; | |
630 | } | |
631 | } | |
632 | ||
f577a03b | 633 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) |
dab91783 | 634 | { |
f577a03b LL |
635 | u32 f12_5_mhz = 12500; |
636 | u32 f19_2_mhz = 19200; | |
637 | u32 f24_mhz = 24000; | |
dab91783 LL |
638 | |
639 | if (INTEL_GEN(dev_priv) <= 4) { | |
640 | /* PRMs say: | |
641 | * | |
642 | * "The value in this register increments once every 16 | |
643 | * hclks." (through the “Clocking Configuration” | |
644 | * (“CLKCFG”) MCHBAR register) | |
645 | */ | |
f577a03b | 646 | return dev_priv->rawclk_freq / 16; |
dab91783 LL |
647 | } else if (INTEL_GEN(dev_priv) <= 8) { |
648 | /* PRMs say: | |
649 | * | |
650 | * "The PCU TSC counts 10ns increments; this timestamp | |
651 | * reflects bits 38:3 of the TSC (i.e. 80ns granularity, | |
652 | * rolling over every 1.5 hours). | |
653 | */ | |
654 | return f12_5_mhz; | |
655 | } else if (INTEL_GEN(dev_priv) <= 9) { | |
656 | u32 ctc_reg = I915_READ(CTC_MODE); | |
f577a03b | 657 | u32 freq = 0; |
dab91783 LL |
658 | |
659 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
660 | freq = read_reference_ts_freq(dev_priv); | |
661 | } else { | |
662 | freq = IS_GEN9_LP(dev_priv) ? f19_2_mhz : f24_mhz; | |
663 | ||
664 | /* Now figure out how the command stream's timestamp | |
665 | * register increments from this frequency (it might | |
666 | * increment only every few clock cycle). | |
667 | */ | |
668 | freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >> | |
669 | CTC_SHIFT_PARAMETER_SHIFT); | |
670 | } | |
671 | ||
672 | return freq; | |
d775a7b1 | 673 | } else if (INTEL_GEN(dev_priv) <= 11) { |
dab91783 | 674 | u32 ctc_reg = I915_READ(CTC_MODE); |
f577a03b | 675 | u32 freq = 0; |
dab91783 LL |
676 | |
677 | /* First figure out the reference frequency. There are 2 ways | |
678 | * we can compute the frequency, either through the | |
679 | * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE | |
680 | * tells us which one we should use. | |
681 | */ | |
682 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
683 | freq = read_reference_ts_freq(dev_priv); | |
684 | } else { | |
d775a7b1 PZ |
685 | u32 rpm_config_reg = I915_READ(RPM_CONFIG0); |
686 | ||
687 | if (INTEL_GEN(dev_priv) <= 10) | |
688 | freq = gen10_get_crystal_clock_freq(dev_priv, | |
689 | rpm_config_reg); | |
690 | else | |
691 | freq = gen11_get_crystal_clock_freq(dev_priv, | |
692 | rpm_config_reg); | |
dab91783 | 693 | |
53ff2641 LL |
694 | /* Now figure out how the command stream's timestamp |
695 | * register increments from this frequency (it might | |
696 | * increment only every few clock cycle). | |
697 | */ | |
698 | freq >>= 3 - ((rpm_config_reg & | |
699 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> | |
700 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); | |
701 | } | |
dab91783 LL |
702 | |
703 | return freq; | |
704 | } | |
705 | ||
fe66e928 | 706 | MISSING_CASE("Unknown gen, unable to read command streamer timestamp frequency\n"); |
dab91783 LL |
707 | return 0; |
708 | } | |
709 | ||
6a7e51f3 MW |
710 | /** |
711 | * intel_device_info_runtime_init - initialize runtime info | |
963cc126 | 712 | * @dev_priv: the i915 device |
6a7e51f3 | 713 | * |
94b4f3ba CW |
714 | * Determine various intel_device_info fields at runtime. |
715 | * | |
716 | * Use it when either: | |
717 | * - it's judged too laborious to fill n static structures with the limit | |
718 | * when a simple if statement does the job, | |
719 | * - run-time checks (eg read fuse/strap registers) are needed. | |
720 | * | |
721 | * This function needs to be called: | |
722 | * - after the MMIO has been setup as we are reading registers, | |
723 | * - after the PCH has been detected, | |
724 | * - before the first usage of the fields it can tweak. | |
725 | */ | |
1400cc7e | 726 | void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) |
94b4f3ba | 727 | { |
1400cc7e | 728 | struct intel_device_info *info = mkwrite_device_info(dev_priv); |
0258404f | 729 | struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv); |
94b4f3ba CW |
730 | enum pipe pipe; |
731 | ||
6e7406db MK |
732 | if (INTEL_GEN(dev_priv) >= 10) { |
733 | for_each_pipe(dev_priv, pipe) | |
0258404f | 734 | runtime->num_scalers[pipe] = 2; |
cf819eff | 735 | } else if (IS_GEN(dev_priv, 9)) { |
0258404f JN |
736 | runtime->num_scalers[PIPE_A] = 2; |
737 | runtime->num_scalers[PIPE_B] = 2; | |
738 | runtime->num_scalers[PIPE_C] = 1; | |
0bf0230e ACO |
739 | } |
740 | ||
74f6e183 | 741 | BUILD_BUG_ON(I915_NUM_ENGINES > BITS_PER_TYPE(intel_ring_mask_t)); |
022d3093 | 742 | |
cf819eff | 743 | if (IS_GEN(dev_priv, 11)) |
6711bd73 | 744 | for_each_pipe(dev_priv, pipe) |
0258404f | 745 | runtime->num_sprites[pipe] = 6; |
cf819eff | 746 | else if (IS_GEN(dev_priv, 10) || IS_GEMINILAKE(dev_priv)) |
e9c98825 | 747 | for_each_pipe(dev_priv, pipe) |
0258404f | 748 | runtime->num_sprites[pipe] = 3; |
e9c98825 | 749 | else if (IS_BROXTON(dev_priv)) { |
6711bd73 ML |
750 | /* |
751 | * Skylake and Broxton currently don't expose the topmost plane as its | |
752 | * use is exclusive with the legacy cursor and we only want to expose | |
753 | * one of those, not both. Until we can safely expose the topmost plane | |
754 | * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported, | |
755 | * we don't expose the topmost plane at all to prevent ABI breakage | |
756 | * down the line. | |
757 | */ | |
758 | ||
0258404f JN |
759 | runtime->num_sprites[PIPE_A] = 2; |
760 | runtime->num_sprites[PIPE_B] = 2; | |
761 | runtime->num_sprites[PIPE_C] = 1; | |
33edc24d | 762 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
94b4f3ba | 763 | for_each_pipe(dev_priv, pipe) |
0258404f | 764 | runtime->num_sprites[pipe] = 2; |
ab33081a | 765 | } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) { |
94b4f3ba | 766 | for_each_pipe(dev_priv, pipe) |
0258404f | 767 | runtime->num_sprites[pipe] = 1; |
33edc24d | 768 | } |
94b4f3ba | 769 | |
4f044a88 | 770 | if (i915_modparams.disable_display) { |
94b4f3ba CW |
771 | DRM_INFO("Display disabled (module parameter)\n"); |
772 | info->num_pipes = 0; | |
e1bf094b | 773 | } else if (HAS_DISPLAY(dev_priv) && |
f3ce44a0 | 774 | (IS_GEN_RANGE(dev_priv, 7, 8)) && |
94b4f3ba CW |
775 | HAS_PCH_SPLIT(dev_priv)) { |
776 | u32 fuse_strap = I915_READ(FUSE_STRAP); | |
777 | u32 sfuse_strap = I915_READ(SFUSE_STRAP); | |
778 | ||
779 | /* | |
780 | * SFUSE_STRAP is supposed to have a bit signalling the display | |
781 | * is fused off. Unfortunately it seems that, at least in | |
782 | * certain cases, fused off display means that PCH display | |
783 | * reads don't land anywhere. In that case, we read 0s. | |
784 | * | |
785 | * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK | |
786 | * should be set when taking over after the firmware. | |
787 | */ | |
788 | if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE || | |
789 | sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED || | |
b9eb89b2 | 790 | (HAS_PCH_CPT(dev_priv) && |
94b4f3ba CW |
791 | !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { |
792 | DRM_INFO("Display fused off, disabling\n"); | |
793 | info->num_pipes = 0; | |
794 | } else if (fuse_strap & IVB_PIPE_C_DISABLE) { | |
795 | DRM_INFO("PipeC fused off\n"); | |
796 | info->num_pipes -= 1; | |
797 | } | |
bea68f4a | 798 | } else if (HAS_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 9) { |
94b4f3ba CW |
799 | u32 dfsm = I915_READ(SKL_DFSM); |
800 | u8 disabled_mask = 0; | |
801 | bool invalid; | |
802 | int num_bits; | |
803 | ||
804 | if (dfsm & SKL_DFSM_PIPE_A_DISABLE) | |
805 | disabled_mask |= BIT(PIPE_A); | |
806 | if (dfsm & SKL_DFSM_PIPE_B_DISABLE) | |
807 | disabled_mask |= BIT(PIPE_B); | |
808 | if (dfsm & SKL_DFSM_PIPE_C_DISABLE) | |
809 | disabled_mask |= BIT(PIPE_C); | |
810 | ||
811 | num_bits = hweight8(disabled_mask); | |
812 | ||
813 | switch (disabled_mask) { | |
814 | case BIT(PIPE_A): | |
815 | case BIT(PIPE_B): | |
816 | case BIT(PIPE_A) | BIT(PIPE_B): | |
817 | case BIT(PIPE_A) | BIT(PIPE_C): | |
818 | invalid = true; | |
819 | break; | |
820 | default: | |
821 | invalid = false; | |
822 | } | |
823 | ||
824 | if (num_bits > info->num_pipes || invalid) | |
825 | DRM_ERROR("invalid pipe fuse configuration: 0x%x\n", | |
826 | disabled_mask); | |
827 | else | |
828 | info->num_pipes -= num_bits; | |
829 | } | |
830 | ||
831 | /* Initialize slice/subslice/EU info */ | |
b8ec759e LL |
832 | if (IS_HASWELL(dev_priv)) |
833 | haswell_sseu_info_init(dev_priv); | |
834 | else if (IS_CHERRYVIEW(dev_priv)) | |
94b4f3ba CW |
835 | cherryview_sseu_info_init(dev_priv); |
836 | else if (IS_BROADWELL(dev_priv)) | |
837 | broadwell_sseu_info_init(dev_priv); | |
cf819eff | 838 | else if (IS_GEN(dev_priv, 9)) |
94b4f3ba | 839 | gen9_sseu_info_init(dev_priv); |
cf819eff | 840 | else if (IS_GEN(dev_priv, 10)) |
4e9767bc | 841 | gen10_sseu_info_init(dev_priv); |
f60fa408 | 842 | else if (INTEL_GEN(dev_priv) >= 11) |
8b5eb5e2 | 843 | gen11_sseu_info_init(dev_priv); |
94b4f3ba | 844 | |
cf819eff | 845 | if (IS_GEN(dev_priv, 6) && intel_vtd_active()) { |
4bdafb9d CW |
846 | DRM_INFO("Disabling ppGTT for VT-d support\n"); |
847 | info->ppgtt = INTEL_PPGTT_NONE; | |
848 | } | |
849 | ||
dab91783 | 850 | /* Initialize command stream timestamp frequency */ |
0258404f | 851 | runtime->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); |
94b4f3ba | 852 | } |
3fed1808 CW |
853 | |
854 | void intel_driver_caps_print(const struct intel_driver_caps *caps, | |
855 | struct drm_printer *p) | |
856 | { | |
481827b4 CW |
857 | drm_printf(p, "Has logical contexts? %s\n", |
858 | yesno(caps->has_logical_contexts)); | |
3fed1808 CW |
859 | drm_printf(p, "scheduler: %x\n", caps->scheduler); |
860 | } | |
26376a7e OM |
861 | |
862 | /* | |
863 | * Determine which engines are fused off in our particular hardware. Since the | |
864 | * fuse register is in the blitter powerwell, we need forcewake to be ready at | |
865 | * this point (but later we need to prune the forcewake domains for engines that | |
866 | * are indeed fused off). | |
867 | */ | |
868 | void intel_device_info_init_mmio(struct drm_i915_private *dev_priv) | |
869 | { | |
870 | struct intel_device_info *info = mkwrite_device_info(dev_priv); | |
57b19d55 | 871 | unsigned int logical_vdbox = 0; |
9213e4f5 | 872 | unsigned int i; |
57b19d55 | 873 | u32 media_fuse; |
26376a7e OM |
874 | |
875 | if (INTEL_GEN(dev_priv) < 11) | |
876 | return; | |
877 | ||
9213e4f5 | 878 | media_fuse = ~I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE); |
26376a7e | 879 | |
0258404f JN |
880 | RUNTIME_INFO(dev_priv)->vdbox_enable = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK; |
881 | RUNTIME_INFO(dev_priv)->vebox_enable = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >> | |
882 | GEN11_GT_VEBOX_DISABLE_SHIFT; | |
26376a7e | 883 | |
0258404f | 884 | DRM_DEBUG_DRIVER("vdbox enable: %04x\n", RUNTIME_INFO(dev_priv)->vdbox_enable); |
26376a7e OM |
885 | for (i = 0; i < I915_MAX_VCS; i++) { |
886 | if (!HAS_ENGINE(dev_priv, _VCS(i))) | |
887 | continue; | |
888 | ||
0258404f | 889 | if (!(BIT(i) & RUNTIME_INFO(dev_priv)->vdbox_enable)) { |
9213e4f5 TU |
890 | info->ring_mask &= ~ENGINE_MASK(_VCS(i)); |
891 | DRM_DEBUG_DRIVER("vcs%u fused off\n", i); | |
57b19d55 | 892 | continue; |
9213e4f5 | 893 | } |
57b19d55 OM |
894 | |
895 | /* | |
896 | * In Gen11, only even numbered logical VDBOXes are | |
897 | * hooked up to an SFC (Scaler & Format Converter) unit. | |
898 | */ | |
899 | if (logical_vdbox++ % 2 == 0) | |
0258404f | 900 | RUNTIME_INFO(dev_priv)->vdbox_sfc_access |= BIT(i); |
26376a7e OM |
901 | } |
902 | ||
0258404f | 903 | DRM_DEBUG_DRIVER("vebox enable: %04x\n", RUNTIME_INFO(dev_priv)->vebox_enable); |
26376a7e OM |
904 | for (i = 0; i < I915_MAX_VECS; i++) { |
905 | if (!HAS_ENGINE(dev_priv, _VECS(i))) | |
906 | continue; | |
907 | ||
0258404f | 908 | if (!(BIT(i) & RUNTIME_INFO(dev_priv)->vebox_enable)) { |
9213e4f5 TU |
909 | info->ring_mask &= ~ENGINE_MASK(_VECS(i)); |
910 | DRM_DEBUG_DRIVER("vecs%u fused off\n", i); | |
911 | } | |
26376a7e OM |
912 | } |
913 | } |