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 | |
25 | #include <linux/string_helpers.h> |
26 | |
27 | #include <drm/drm_print.h> |
28 | #include <drm/i915_pciids.h> |
29 | |
30 | #include "gt/intel_gt_regs.h" |
31 | #include "i915_drv.h" |
32 | #include "i915_reg.h" |
33 | #include "i915_utils.h" |
34 | #include "intel_device_info.h" |
35 | |
36 | #define PLATFORM_NAME(x) [INTEL_##x] = #x |
37 | static const char * const platform_names[] = { |
38 | PLATFORM_NAME(I830), |
39 | PLATFORM_NAME(I845G), |
40 | PLATFORM_NAME(I85X), |
41 | PLATFORM_NAME(I865G), |
42 | PLATFORM_NAME(I915G), |
43 | PLATFORM_NAME(I915GM), |
44 | PLATFORM_NAME(I945G), |
45 | PLATFORM_NAME(I945GM), |
46 | PLATFORM_NAME(G33), |
47 | PLATFORM_NAME(PINEVIEW), |
48 | PLATFORM_NAME(I965G), |
49 | PLATFORM_NAME(I965GM), |
50 | PLATFORM_NAME(G45), |
51 | PLATFORM_NAME(GM45), |
52 | PLATFORM_NAME(IRONLAKE), |
53 | PLATFORM_NAME(SANDYBRIDGE), |
54 | PLATFORM_NAME(IVYBRIDGE), |
55 | PLATFORM_NAME(VALLEYVIEW), |
56 | PLATFORM_NAME(HASWELL), |
57 | PLATFORM_NAME(BROADWELL), |
58 | PLATFORM_NAME(CHERRYVIEW), |
59 | PLATFORM_NAME(SKYLAKE), |
60 | PLATFORM_NAME(BROXTON), |
61 | PLATFORM_NAME(KABYLAKE), |
62 | PLATFORM_NAME(GEMINILAKE), |
63 | PLATFORM_NAME(COFFEELAKE), |
64 | PLATFORM_NAME(COMETLAKE), |
65 | PLATFORM_NAME(ICELAKE), |
66 | PLATFORM_NAME(ELKHARTLAKE), |
67 | PLATFORM_NAME(JASPERLAKE), |
68 | PLATFORM_NAME(TIGERLAKE), |
69 | PLATFORM_NAME(ROCKETLAKE), |
70 | PLATFORM_NAME(DG1), |
71 | PLATFORM_NAME(ALDERLAKE_S), |
72 | PLATFORM_NAME(ALDERLAKE_P), |
73 | PLATFORM_NAME(XEHPSDV), |
74 | PLATFORM_NAME(DG2), |
75 | PLATFORM_NAME(PONTEVECCHIO), |
76 | PLATFORM_NAME(METEORLAKE), |
77 | }; |
78 | #undef PLATFORM_NAME |
79 | |
80 | const char *intel_platform_name(enum intel_platform platform) |
81 | { |
82 | BUILD_BUG_ON(ARRAY_SIZE(platform_names) != INTEL_MAX_PLATFORMS); |
83 | |
84 | if (WARN_ON_ONCE(platform >= ARRAY_SIZE(platform_names) || |
85 | platform_names[platform] == NULL)) |
86 | return "<unknown>" ; |
87 | |
88 | return platform_names[platform]; |
89 | } |
90 | |
91 | void intel_device_info_print(const struct intel_device_info *info, |
92 | const struct intel_runtime_info *runtime, |
93 | struct drm_printer *p) |
94 | { |
95 | if (runtime->graphics.ip.rel) |
96 | drm_printf(p, f: "graphics version: %u.%02u\n" , |
97 | runtime->graphics.ip.ver, |
98 | runtime->graphics.ip.rel); |
99 | else |
100 | drm_printf(p, f: "graphics version: %u\n" , |
101 | runtime->graphics.ip.ver); |
102 | |
103 | if (runtime->media.ip.rel) |
104 | drm_printf(p, f: "media version: %u.%02u\n" , |
105 | runtime->media.ip.ver, |
106 | runtime->media.ip.rel); |
107 | else |
108 | drm_printf(p, f: "media version: %u\n" , |
109 | runtime->media.ip.ver); |
110 | |
111 | drm_printf(p, f: "graphics stepping: %s\n" , intel_step_name(step: runtime->step.graphics_step)); |
112 | drm_printf(p, f: "media stepping: %s\n" , intel_step_name(step: runtime->step.media_step)); |
113 | drm_printf(p, f: "display stepping: %s\n" , intel_step_name(step: runtime->step.display_step)); |
114 | drm_printf(p, f: "base die stepping: %s\n" , intel_step_name(step: runtime->step.basedie_step)); |
115 | |
116 | drm_printf(p, f: "gt: %d\n" , info->gt); |
117 | drm_printf(p, f: "memory-regions: 0x%x\n" , info->memory_regions); |
118 | drm_printf(p, f: "page-sizes: 0x%x\n" , runtime->page_sizes); |
119 | drm_printf(p, f: "platform: %s\n" , intel_platform_name(platform: info->platform)); |
120 | drm_printf(p, f: "ppgtt-size: %d\n" , runtime->ppgtt_size); |
121 | drm_printf(p, f: "ppgtt-type: %d\n" , runtime->ppgtt_type); |
122 | drm_printf(p, f: "dma_mask_size: %u\n" , info->dma_mask_size); |
123 | |
124 | #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name)) |
125 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); |
126 | #undef PRINT_FLAG |
127 | |
128 | drm_printf(p, f: "has_pooled_eu: %s\n" , str_yes_no(v: runtime->has_pooled_eu)); |
129 | drm_printf(p, f: "rawclk rate: %u kHz\n" , runtime->rawclk_freq); |
130 | } |
131 | |
132 | #undef INTEL_VGA_DEVICE |
133 | #define INTEL_VGA_DEVICE(id, info) (id) |
134 | |
135 | static const u16 subplatform_ult_ids[] = { |
136 | INTEL_HSW_ULT_GT1_IDS(0), |
137 | INTEL_HSW_ULT_GT2_IDS(0), |
138 | INTEL_HSW_ULT_GT3_IDS(0), |
139 | INTEL_BDW_ULT_GT1_IDS(0), |
140 | INTEL_BDW_ULT_GT2_IDS(0), |
141 | INTEL_BDW_ULT_GT3_IDS(0), |
142 | INTEL_BDW_ULT_RSVD_IDS(0), |
143 | INTEL_SKL_ULT_GT1_IDS(0), |
144 | INTEL_SKL_ULT_GT2_IDS(0), |
145 | INTEL_SKL_ULT_GT3_IDS(0), |
146 | INTEL_KBL_ULT_GT1_IDS(0), |
147 | INTEL_KBL_ULT_GT2_IDS(0), |
148 | INTEL_KBL_ULT_GT3_IDS(0), |
149 | INTEL_CFL_U_GT2_IDS(0), |
150 | INTEL_CFL_U_GT3_IDS(0), |
151 | INTEL_WHL_U_GT1_IDS(0), |
152 | INTEL_WHL_U_GT2_IDS(0), |
153 | INTEL_WHL_U_GT3_IDS(0), |
154 | INTEL_CML_U_GT1_IDS(0), |
155 | INTEL_CML_U_GT2_IDS(0), |
156 | }; |
157 | |
158 | static const u16 subplatform_ulx_ids[] = { |
159 | INTEL_HSW_ULX_GT1_IDS(0), |
160 | INTEL_HSW_ULX_GT2_IDS(0), |
161 | INTEL_BDW_ULX_GT1_IDS(0), |
162 | INTEL_BDW_ULX_GT2_IDS(0), |
163 | INTEL_BDW_ULX_GT3_IDS(0), |
164 | INTEL_BDW_ULX_RSVD_IDS(0), |
165 | INTEL_SKL_ULX_GT1_IDS(0), |
166 | INTEL_SKL_ULX_GT2_IDS(0), |
167 | INTEL_KBL_ULX_GT1_IDS(0), |
168 | INTEL_KBL_ULX_GT2_IDS(0), |
169 | INTEL_AML_KBL_GT2_IDS(0), |
170 | INTEL_AML_CFL_GT2_IDS(0), |
171 | }; |
172 | |
173 | static const u16 subplatform_portf_ids[] = { |
174 | INTEL_ICL_PORT_F_IDS(0), |
175 | }; |
176 | |
177 | static const u16 subplatform_uy_ids[] = { |
178 | INTEL_TGL_12_GT2_IDS(0), |
179 | }; |
180 | |
181 | static const u16 subplatform_n_ids[] = { |
182 | INTEL_ADLN_IDS(0), |
183 | }; |
184 | |
185 | static const u16 subplatform_rpl_ids[] = { |
186 | INTEL_RPLS_IDS(0), |
187 | INTEL_RPLP_IDS(0), |
188 | }; |
189 | |
190 | static const u16 subplatform_rplu_ids[] = { |
191 | INTEL_RPLU_IDS(0), |
192 | }; |
193 | |
194 | static const u16 subplatform_g10_ids[] = { |
195 | INTEL_DG2_G10_IDS(0), |
196 | INTEL_ATS_M150_IDS(0), |
197 | }; |
198 | |
199 | static const u16 subplatform_g11_ids[] = { |
200 | INTEL_DG2_G11_IDS(0), |
201 | INTEL_ATS_M75_IDS(0), |
202 | }; |
203 | |
204 | static const u16 subplatform_g12_ids[] = { |
205 | INTEL_DG2_G12_IDS(0), |
206 | }; |
207 | |
208 | static bool find_devid(u16 id, const u16 *p, unsigned int num) |
209 | { |
210 | for (; num; num--, p++) { |
211 | if (*p == id) |
212 | return true; |
213 | } |
214 | |
215 | return false; |
216 | } |
217 | |
218 | static void intel_device_info_subplatform_init(struct drm_i915_private *i915) |
219 | { |
220 | const struct intel_device_info *info = INTEL_INFO(i915); |
221 | const struct intel_runtime_info *rinfo = RUNTIME_INFO(i915); |
222 | const unsigned int pi = __platform_mask_index(info: rinfo, p: info->platform); |
223 | const unsigned int pb = __platform_mask_bit(info: rinfo, p: info->platform); |
224 | u16 devid = INTEL_DEVID(i915); |
225 | u32 mask = 0; |
226 | |
227 | /* Make sure IS_<platform> checks are working. */ |
228 | RUNTIME_INFO(i915)->platform_mask[pi] = BIT(pb); |
229 | |
230 | /* Find and mark subplatform bits based on the PCI device id. */ |
231 | if (find_devid(id: devid, p: subplatform_ult_ids, |
232 | ARRAY_SIZE(subplatform_ult_ids))) { |
233 | mask = BIT(INTEL_SUBPLATFORM_ULT); |
234 | } else if (find_devid(id: devid, p: subplatform_ulx_ids, |
235 | ARRAY_SIZE(subplatform_ulx_ids))) { |
236 | mask = BIT(INTEL_SUBPLATFORM_ULX); |
237 | if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { |
238 | /* ULX machines are also considered ULT. */ |
239 | mask |= BIT(INTEL_SUBPLATFORM_ULT); |
240 | } |
241 | } else if (find_devid(id: devid, p: subplatform_portf_ids, |
242 | ARRAY_SIZE(subplatform_portf_ids))) { |
243 | mask = BIT(INTEL_SUBPLATFORM_PORTF); |
244 | } else if (find_devid(id: devid, p: subplatform_uy_ids, |
245 | ARRAY_SIZE(subplatform_uy_ids))) { |
246 | mask = BIT(INTEL_SUBPLATFORM_UY); |
247 | } else if (find_devid(id: devid, p: subplatform_n_ids, |
248 | ARRAY_SIZE(subplatform_n_ids))) { |
249 | mask = BIT(INTEL_SUBPLATFORM_N); |
250 | } else if (find_devid(id: devid, p: subplatform_rpl_ids, |
251 | ARRAY_SIZE(subplatform_rpl_ids))) { |
252 | mask = BIT(INTEL_SUBPLATFORM_RPL); |
253 | if (find_devid(id: devid, p: subplatform_rplu_ids, |
254 | ARRAY_SIZE(subplatform_rplu_ids))) |
255 | mask |= BIT(INTEL_SUBPLATFORM_RPLU); |
256 | } else if (find_devid(id: devid, p: subplatform_g10_ids, |
257 | ARRAY_SIZE(subplatform_g10_ids))) { |
258 | mask = BIT(INTEL_SUBPLATFORM_G10); |
259 | } else if (find_devid(id: devid, p: subplatform_g11_ids, |
260 | ARRAY_SIZE(subplatform_g11_ids))) { |
261 | mask = BIT(INTEL_SUBPLATFORM_G11); |
262 | } else if (find_devid(id: devid, p: subplatform_g12_ids, |
263 | ARRAY_SIZE(subplatform_g12_ids))) { |
264 | mask = BIT(INTEL_SUBPLATFORM_G12); |
265 | } |
266 | |
267 | GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_MASK); |
268 | |
269 | RUNTIME_INFO(i915)->platform_mask[pi] |= mask; |
270 | } |
271 | |
272 | static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ip_version *ip) |
273 | { |
274 | struct pci_dev *pdev = to_pci_dev(i915->drm.dev); |
275 | void __iomem *addr; |
276 | u32 val; |
277 | u8 expected_ver = ip->ver; |
278 | u8 expected_rel = ip->rel; |
279 | |
280 | addr = pci_iomap_range(dev: pdev, bar: 0, offset, maxlen: sizeof(u32)); |
281 | if (drm_WARN_ON(&i915->drm, !addr)) |
282 | return; |
283 | |
284 | val = ioread32(addr); |
285 | pci_iounmap(dev: pdev, addr); |
286 | |
287 | ip->ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val); |
288 | ip->rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val); |
289 | ip->step = REG_FIELD_GET(GMD_ID_STEP, val); |
290 | |
291 | /* Sanity check against expected versions from device info */ |
292 | if (IP_VER(ip->ver, ip->rel) < IP_VER(expected_ver, expected_rel)) |
293 | drm_dbg(&i915->drm, |
294 | "Hardware reports GMD IP version %u.%u (REG[0x%x] = 0x%08x) but minimum expected is %u.%u\n" , |
295 | ip->ver, ip->rel, offset, val, expected_ver, expected_rel); |
296 | } |
297 | |
298 | /* |
299 | * Setup the graphics version for the current device. This must be done before |
300 | * any code that performs checks on GRAPHICS_VER or DISPLAY_VER, so this |
301 | * function should be called very early in the driver initialization sequence. |
302 | * |
303 | * Regular MMIO access is not yet setup at the point this function is called so |
304 | * we peek at the appropriate MMIO offset directly. The GMD_ID register is |
305 | * part of an 'always on' power well by design, so we don't need to worry about |
306 | * forcewake while reading it. |
307 | */ |
308 | static void intel_ipver_early_init(struct drm_i915_private *i915) |
309 | { |
310 | struct intel_runtime_info *runtime = RUNTIME_INFO(i915); |
311 | |
312 | if (!HAS_GMD_ID(i915)) { |
313 | drm_WARN_ON(&i915->drm, RUNTIME_INFO(i915)->graphics.ip.ver > 12); |
314 | /* |
315 | * On older platforms, graphics and media share the same ip |
316 | * version and release. |
317 | */ |
318 | RUNTIME_INFO(i915)->media.ip = |
319 | RUNTIME_INFO(i915)->graphics.ip; |
320 | return; |
321 | } |
322 | |
323 | ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_GRAPHICS), |
324 | ip: &runtime->graphics.ip); |
325 | /* Wa_22012778468 */ |
326 | if (runtime->graphics.ip.ver == 0x0 && |
327 | INTEL_INFO(i915)->platform == INTEL_METEORLAKE) { |
328 | RUNTIME_INFO(i915)->graphics.ip.ver = 12; |
329 | RUNTIME_INFO(i915)->graphics.ip.rel = 70; |
330 | } |
331 | ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_MEDIA), |
332 | ip: &runtime->media.ip); |
333 | } |
334 | |
335 | /** |
336 | * intel_device_info_runtime_init_early - initialize early runtime info |
337 | * @i915: the i915 device |
338 | * |
339 | * Determine early intel_device_info fields at runtime. This function needs |
340 | * to be called before the MMIO has been setup. |
341 | */ |
342 | void intel_device_info_runtime_init_early(struct drm_i915_private *i915) |
343 | { |
344 | intel_ipver_early_init(i915); |
345 | intel_device_info_subplatform_init(i915); |
346 | } |
347 | |
348 | /** |
349 | * intel_device_info_runtime_init - initialize runtime info |
350 | * @dev_priv: the i915 device |
351 | * |
352 | * Determine various intel_device_info fields at runtime. |
353 | * |
354 | * Use it when either: |
355 | * - it's judged too laborious to fill n static structures with the limit |
356 | * when a simple if statement does the job, |
357 | * - run-time checks (eg read fuse/strap registers) are needed. |
358 | * |
359 | * This function needs to be called: |
360 | * - after the MMIO has been setup as we are reading registers, |
361 | * - after the PCH has been detected, |
362 | * - before the first usage of the fields it can tweak. |
363 | */ |
364 | void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) |
365 | { |
366 | struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv); |
367 | |
368 | BUILD_BUG_ON(BITS_PER_TYPE(intel_engine_mask_t) < I915_NUM_ENGINES); |
369 | |
370 | if (GRAPHICS_VER(dev_priv) == 6 && i915_vtd_active(i915: dev_priv)) { |
371 | drm_info(&dev_priv->drm, |
372 | "Disabling ppGTT for VT-d support\n" ); |
373 | runtime->ppgtt_type = INTEL_PPGTT_NONE; |
374 | } |
375 | |
376 | runtime->rawclk_freq = intel_read_rawclk(dev_priv); |
377 | drm_dbg(&dev_priv->drm, "rawclk rate: %d kHz\n" , runtime->rawclk_freq); |
378 | |
379 | } |
380 | |
381 | /* |
382 | * Set up device info and initial runtime info at driver create. |
383 | * |
384 | * Note: i915 is only an allocated blob of memory at this point. |
385 | */ |
386 | void intel_device_info_driver_create(struct drm_i915_private *i915, |
387 | u16 device_id, |
388 | const struct intel_device_info *match_info) |
389 | { |
390 | struct intel_runtime_info *runtime; |
391 | |
392 | /* Setup INTEL_INFO() */ |
393 | i915->__info = match_info; |
394 | |
395 | /* Initialize initial runtime info from static const data and pdev. */ |
396 | runtime = RUNTIME_INFO(i915); |
397 | memcpy(runtime, &INTEL_INFO(i915)->__runtime, sizeof(*runtime)); |
398 | |
399 | runtime->device_id = device_id; |
400 | } |
401 | |
402 | void intel_driver_caps_print(const struct intel_driver_caps *caps, |
403 | struct drm_printer *p) |
404 | { |
405 | drm_printf(p, f: "Has logical contexts? %s\n" , |
406 | str_yes_no(v: caps->has_logical_contexts)); |
407 | drm_printf(p, f: "scheduler: 0x%x\n" , caps->scheduler); |
408 | } |
409 | |