1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "i915_drv.h"
26
27void intel_device_info_dump(struct drm_i915_private *dev_priv)
28{
29 const struct intel_device_info *info = &dev_priv->info;
30
31#define PRINT_S(name) "%s"
32#define SEP_EMPTY
33#define PRINT_FLAG(name) info->name ? #name "," : ""
34#define SEP_COMMA ,
35 DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
36 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
37 info->gen,
38 dev_priv->drm.pdev->device,
39 dev_priv->drm.pdev->revision,
40 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
41#undef PRINT_S
42#undef SEP_EMPTY
43#undef PRINT_FLAG
44#undef SEP_COMMA
45}
46
47static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
48{
49 struct intel_device_info *info = mkwrite_device_info(dev_priv);
50 u32 fuse, eu_dis;
51
52 fuse = I915_READ(CHV_FUSE_GT);
53
54 info->slice_total = 1;
55
56 if (!(fuse & CHV_FGT_DISABLE_SS0)) {
57 info->subslice_per_slice++;
58 eu_dis = fuse & (CHV_FGT_EU_DIS_SS0_R0_MASK |
59 CHV_FGT_EU_DIS_SS0_R1_MASK);
60 info->eu_total += 8 - hweight32(eu_dis);
61 }
62
63 if (!(fuse & CHV_FGT_DISABLE_SS1)) {
64 info->subslice_per_slice++;
65 eu_dis = fuse & (CHV_FGT_EU_DIS_SS1_R0_MASK |
66 CHV_FGT_EU_DIS_SS1_R1_MASK);
67 info->eu_total += 8 - hweight32(eu_dis);
68 }
69
70 info->subslice_total = info->subslice_per_slice;
71
72
73
74
75 info->eu_per_subslice = info->subslice_total ?
76 info->eu_total / info->subslice_total :
77 0;
78
79
80
81
82
83 info->has_slice_pg = 0;
84 info->has_subslice_pg = (info->subslice_total > 1);
85 info->has_eu_pg = (info->eu_per_subslice > 2);
86}
87
88static void gen9_sseu_info_init(struct drm_i915_private *dev_priv)
89{
90 struct intel_device_info *info = mkwrite_device_info(dev_priv);
91 int s_max = 3, ss_max = 4, eu_max = 8;
92 int s, ss;
93 u32 fuse2, s_enable, ss_disable, eu_disable;
94 u8 eu_mask = 0xff;
95
96 fuse2 = I915_READ(GEN8_FUSE2);
97 s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
98 ss_disable = (fuse2 & GEN9_F2_SS_DIS_MASK) >> GEN9_F2_SS_DIS_SHIFT;
99
100 info->slice_total = hweight32(s_enable);
101
102
103
104
105 info->subslice_per_slice = ss_max - hweight32(ss_disable);
106 info->subslice_total = info->slice_total * info->subslice_per_slice;
107
108
109
110
111
112 for (s = 0; s < s_max; s++) {
113 if (!(s_enable & BIT(s)))
114
115 continue;
116
117 eu_disable = I915_READ(GEN9_EU_DISABLE(s));
118 for (ss = 0; ss < ss_max; ss++) {
119 int eu_per_ss;
120
121 if (ss_disable & BIT(ss))
122
123 continue;
124
125 eu_per_ss = eu_max - hweight8((eu_disable >> (ss*8)) &
126 eu_mask);
127
128
129
130
131
132
133 if (eu_per_ss == 7)
134 info->subslice_7eu[s] |= BIT(ss);
135
136 info->eu_total += eu_per_ss;
137 }
138 }
139
140
141
142
143
144
145
146
147 info->eu_per_subslice = info->subslice_total ?
148 DIV_ROUND_UP(info->eu_total,
149 info->subslice_total) : 0;
150
151
152
153
154
155
156
157
158 info->has_slice_pg =
159 (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
160 info->slice_total > 1;
161 info->has_subslice_pg =
162 IS_BROXTON(dev_priv) && info->subslice_total > 1;
163 info->has_eu_pg = info->eu_per_subslice > 2;
164
165 if (IS_BROXTON(dev_priv)) {
166#define IS_SS_DISABLED(_ss_disable, ss) (_ss_disable & BIT(ss))
167
168
169
170
171
172
173
174 info->has_pooled_eu = ((info->subslice_per_slice == 3) ||
175 (info->subslice_per_slice == 2 &&
176 INTEL_REVID(dev_priv) < BXT_REVID_C0));
177
178 info->min_eu_in_pool = 0;
179 if (info->has_pooled_eu) {
180 if (IS_SS_DISABLED(ss_disable, 0) ||
181 IS_SS_DISABLED(ss_disable, 2))
182 info->min_eu_in_pool = 3;
183 else if (IS_SS_DISABLED(ss_disable, 1))
184 info->min_eu_in_pool = 6;
185 else
186 info->min_eu_in_pool = 9;
187 }
188#undef IS_SS_DISABLED
189 }
190}
191
192static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
193{
194 struct intel_device_info *info = mkwrite_device_info(dev_priv);
195 const int s_max = 3, ss_max = 3, eu_max = 8;
196 int s, ss;
197 u32 fuse2, eu_disable[s_max], s_enable, ss_disable;
198
199 fuse2 = I915_READ(GEN8_FUSE2);
200 s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT;
201 ss_disable = (fuse2 & GEN8_F2_SS_DIS_MASK) >> GEN8_F2_SS_DIS_SHIFT;
202
203 eu_disable[0] = I915_READ(GEN8_EU_DISABLE0) & GEN8_EU_DIS0_S0_MASK;
204 eu_disable[1] = (I915_READ(GEN8_EU_DISABLE0) >> GEN8_EU_DIS0_S1_SHIFT) |
205 ((I915_READ(GEN8_EU_DISABLE1) & GEN8_EU_DIS1_S1_MASK) <<
206 (32 - GEN8_EU_DIS0_S1_SHIFT));
207 eu_disable[2] = (I915_READ(GEN8_EU_DISABLE1) >> GEN8_EU_DIS1_S2_SHIFT) |
208 ((I915_READ(GEN8_EU_DISABLE2) & GEN8_EU_DIS2_S2_MASK) <<
209 (32 - GEN8_EU_DIS1_S2_SHIFT));
210
211 info->slice_total = hweight32(s_enable);
212
213
214
215
216
217 info->subslice_per_slice = ss_max - hweight32(ss_disable);
218 info->subslice_total = info->slice_total * info->subslice_per_slice;
219
220
221
222
223
224 for (s = 0; s < s_max; s++) {
225 if (!(s_enable & (0x1 << s)))
226
227 continue;
228
229 for (ss = 0; ss < ss_max; ss++) {
230 u32 n_disabled;
231
232 if (ss_disable & (0x1 << ss))
233
234 continue;
235
236 n_disabled = hweight8(eu_disable[s] >> (ss * eu_max));
237
238
239
240
241 if (eu_max - n_disabled == 7)
242 info->subslice_7eu[s] |= 1 << ss;
243
244 info->eu_total += eu_max - n_disabled;
245 }
246 }
247
248
249
250
251
252
253 info->eu_per_subslice = info->subslice_total ?
254 DIV_ROUND_UP(info->eu_total, info->subslice_total) : 0;
255
256
257
258
259
260 info->has_slice_pg = (info->slice_total > 1);
261 info->has_subslice_pg = 0;
262 info->has_eu_pg = 0;
263}
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
279{
280 struct intel_device_info *info = mkwrite_device_info(dev_priv);
281 enum pipe pipe;
282
283
284
285
286
287
288
289
290
291 if (IS_BROXTON(dev_priv)) {
292 info->num_sprites[PIPE_A] = 2;
293 info->num_sprites[PIPE_B] = 2;
294 info->num_sprites[PIPE_C] = 1;
295 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
296 for_each_pipe(dev_priv, pipe)
297 info->num_sprites[pipe] = 2;
298 else
299 for_each_pipe(dev_priv, pipe)
300 info->num_sprites[pipe] = 1;
301
302 if (i915.disable_display) {
303 DRM_INFO("Display disabled (module parameter)\n");
304 info->num_pipes = 0;
305 } else if (info->num_pipes > 0 &&
306 (IS_GEN7(dev_priv) || IS_GEN8(dev_priv)) &&
307 HAS_PCH_SPLIT(dev_priv)) {
308 u32 fuse_strap = I915_READ(FUSE_STRAP);
309 u32 sfuse_strap = I915_READ(SFUSE_STRAP);
310
311
312
313
314
315
316
317
318
319
320 if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE ||
321 sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED ||
322 (dev_priv->pch_type == PCH_CPT &&
323 !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) {
324 DRM_INFO("Display fused off, disabling\n");
325 info->num_pipes = 0;
326 } else if (fuse_strap & IVB_PIPE_C_DISABLE) {
327 DRM_INFO("PipeC fused off\n");
328 info->num_pipes -= 1;
329 }
330 } else if (info->num_pipes > 0 && IS_GEN9(dev_priv)) {
331 u32 dfsm = I915_READ(SKL_DFSM);
332 u8 disabled_mask = 0;
333 bool invalid;
334 int num_bits;
335
336 if (dfsm & SKL_DFSM_PIPE_A_DISABLE)
337 disabled_mask |= BIT(PIPE_A);
338 if (dfsm & SKL_DFSM_PIPE_B_DISABLE)
339 disabled_mask |= BIT(PIPE_B);
340 if (dfsm & SKL_DFSM_PIPE_C_DISABLE)
341 disabled_mask |= BIT(PIPE_C);
342
343 num_bits = hweight8(disabled_mask);
344
345 switch (disabled_mask) {
346 case BIT(PIPE_A):
347 case BIT(PIPE_B):
348 case BIT(PIPE_A) | BIT(PIPE_B):
349 case BIT(PIPE_A) | BIT(PIPE_C):
350 invalid = true;
351 break;
352 default:
353 invalid = false;
354 }
355
356 if (num_bits > info->num_pipes || invalid)
357 DRM_ERROR("invalid pipe fuse configuration: 0x%x\n",
358 disabled_mask);
359 else
360 info->num_pipes -= num_bits;
361 }
362
363
364 if (IS_CHERRYVIEW(dev_priv))
365 cherryview_sseu_info_init(dev_priv);
366 else if (IS_BROADWELL(dev_priv))
367 broadwell_sseu_info_init(dev_priv);
368 else if (INTEL_INFO(dev_priv)->gen >= 9)
369 gen9_sseu_info_init(dev_priv);
370
371 info->has_snoop = !info->has_llc;
372
373
374 if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
375 info->has_snoop = false;
376
377 DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
378 DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
379 DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
380 DRM_DEBUG_DRIVER("EU total: %u\n", info->eu_total);
381 DRM_DEBUG_DRIVER("EU per subslice: %u\n", info->eu_per_subslice);
382 DRM_DEBUG_DRIVER("has slice power gating: %s\n",
383 info->has_slice_pg ? "y" : "n");
384 DRM_DEBUG_DRIVER("has subslice power gating: %s\n",
385 info->has_subslice_pg ? "y" : "n");
386 DRM_DEBUG_DRIVER("has EU power gating: %s\n",
387 info->has_eu_pg ? "y" : "n");
388}
389