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 | 25 | #include <drm/drm_print.h> |
83d2bdb6 | 26 | #include <drm/i915_pciids.h> |
a8c9b849 | 27 | |
b04002f4 | 28 | #include "display/intel_cdclk.h" |
fdeb6d02 | 29 | #include "display/intel_de.h" |
b978520d | 30 | #include "intel_device_info.h" |
94b4f3ba CW |
31 | #include "i915_drv.h" |
32 | ||
2e0d26f8 JN |
33 | #define PLATFORM_NAME(x) [INTEL_##x] = #x |
34 | static const char * const platform_names[] = { | |
35 | PLATFORM_NAME(I830), | |
36 | PLATFORM_NAME(I845G), | |
37 | PLATFORM_NAME(I85X), | |
38 | PLATFORM_NAME(I865G), | |
39 | PLATFORM_NAME(I915G), | |
40 | PLATFORM_NAME(I915GM), | |
41 | PLATFORM_NAME(I945G), | |
42 | PLATFORM_NAME(I945GM), | |
43 | PLATFORM_NAME(G33), | |
44 | PLATFORM_NAME(PINEVIEW), | |
c0f86832 JN |
45 | PLATFORM_NAME(I965G), |
46 | PLATFORM_NAME(I965GM), | |
f69c11ae JN |
47 | PLATFORM_NAME(G45), |
48 | PLATFORM_NAME(GM45), | |
2e0d26f8 JN |
49 | PLATFORM_NAME(IRONLAKE), |
50 | PLATFORM_NAME(SANDYBRIDGE), | |
51 | PLATFORM_NAME(IVYBRIDGE), | |
52 | PLATFORM_NAME(VALLEYVIEW), | |
53 | PLATFORM_NAME(HASWELL), | |
54 | PLATFORM_NAME(BROADWELL), | |
55 | PLATFORM_NAME(CHERRYVIEW), | |
56 | PLATFORM_NAME(SKYLAKE), | |
57 | PLATFORM_NAME(BROXTON), | |
58 | PLATFORM_NAME(KABYLAKE), | |
59 | PLATFORM_NAME(GEMINILAKE), | |
71851fa8 | 60 | PLATFORM_NAME(COFFEELAKE), |
5f4ae270 | 61 | PLATFORM_NAME(COMETLAKE), |
413f3c19 | 62 | PLATFORM_NAME(CANNONLAKE), |
41231001 | 63 | PLATFORM_NAME(ICELAKE), |
897f2961 | 64 | PLATFORM_NAME(ELKHARTLAKE), |
abd3a0fe | 65 | PLATFORM_NAME(TIGERLAKE), |
123f62de | 66 | PLATFORM_NAME(ROCKETLAKE), |
05e26584 | 67 | PLATFORM_NAME(DG1), |
2e0d26f8 JN |
68 | }; |
69 | #undef PLATFORM_NAME | |
70 | ||
71 | const char *intel_platform_name(enum intel_platform platform) | |
72 | { | |
9160095c JN |
73 | BUILD_BUG_ON(ARRAY_SIZE(platform_names) != INTEL_MAX_PLATFORMS); |
74 | ||
2e0d26f8 JN |
75 | if (WARN_ON_ONCE(platform >= ARRAY_SIZE(platform_names) || |
76 | platform_names[platform] == NULL)) | |
77 | return "<unknown>"; | |
78 | ||
79 | return platform_names[platform]; | |
80 | } | |
81 | ||
72404978 | 82 | static const char *iommu_name(void) |
a8c9b849 | 83 | { |
72404978 CW |
84 | const char *msg = "n/a"; |
85 | ||
86 | #ifdef CONFIG_INTEL_IOMMU | |
87 | msg = enableddisabled(intel_iommu_gfx_mapped); | |
88 | #endif | |
89 | ||
90 | return msg; | |
91 | } | |
92 | ||
93 | void intel_device_info_print_static(const struct intel_device_info *info, | |
94 | struct drm_printer *p) | |
95 | { | |
72404978 CW |
96 | drm_printf(p, "gen: %d\n", info->gen); |
97 | drm_printf(p, "gt: %d\n", info->gt); | |
98 | drm_printf(p, "iommu: %s\n", iommu_name()); | |
99 | drm_printf(p, "memory-regions: %x\n", info->memory_regions); | |
100 | drm_printf(p, "page-sizes: %x\n", info->page_sizes); | |
101 | drm_printf(p, "platform: %s\n", intel_platform_name(info->platform)); | |
102 | drm_printf(p, "ppgtt-size: %d\n", info->ppgtt_size); | |
103 | drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type); | |
31a02eb7 | 104 | drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size); |
72404978 | 105 | |
a8c9b849 MW |
106 | #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name)); |
107 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); | |
108 | #undef PRINT_FLAG | |
d53db442 JRS |
109 | |
110 | #define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name)); | |
111 | DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); | |
112 | #undef PRINT_FLAG | |
a8c9b849 MW |
113 | } |
114 | ||
72404978 CW |
115 | void intel_device_info_print_runtime(const struct intel_runtime_info *info, |
116 | struct drm_printer *p) | |
5fbbe8d4 | 117 | { |
b04002f4 | 118 | drm_printf(p, "rawclk rate: %u kHz\n", info->rawclk_freq); |
56f1b31f VS |
119 | drm_printf(p, "CS timestamp frequency: %u Hz\n", |
120 | info->cs_timestamp_frequency_hz); | |
5fbbe8d4 MW |
121 | } |
122 | ||
f577a03b | 123 | static u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) |
dab91783 | 124 | { |
fdeb6d02 DCS |
125 | u32 ts_override = intel_uncore_read(&dev_priv->uncore, |
126 | GEN9_TIMESTAMP_OVERRIDE); | |
f577a03b | 127 | u32 base_freq, frac_freq; |
dab91783 LL |
128 | |
129 | base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >> | |
130 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1; | |
56f1b31f | 131 | base_freq *= 1000000; |
dab91783 LL |
132 | |
133 | frac_freq = ((ts_override & | |
134 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >> | |
135 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT); | |
56f1b31f | 136 | frac_freq = 1000000 / (frac_freq + 1); |
dab91783 LL |
137 | |
138 | return base_freq + frac_freq; | |
139 | } | |
140 | ||
d775a7b1 PZ |
141 | static u32 gen10_get_crystal_clock_freq(struct drm_i915_private *dev_priv, |
142 | u32 rpm_config_reg) | |
143 | { | |
56f1b31f VS |
144 | u32 f19_2_mhz = 19200000; |
145 | u32 f24_mhz = 24000000; | |
d775a7b1 PZ |
146 | u32 crystal_clock = (rpm_config_reg & |
147 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
148 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
149 | ||
150 | switch (crystal_clock) { | |
151 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
152 | return f19_2_mhz; | |
153 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
154 | return f24_mhz; | |
155 | default: | |
156 | MISSING_CASE(crystal_clock); | |
157 | return 0; | |
158 | } | |
159 | } | |
160 | ||
161 | static u32 gen11_get_crystal_clock_freq(struct drm_i915_private *dev_priv, | |
162 | u32 rpm_config_reg) | |
163 | { | |
56f1b31f VS |
164 | u32 f19_2_mhz = 19200000; |
165 | u32 f24_mhz = 24000000; | |
166 | u32 f25_mhz = 25000000; | |
167 | u32 f38_4_mhz = 38400000; | |
d775a7b1 PZ |
168 | u32 crystal_clock = (rpm_config_reg & |
169 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | |
170 | GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | |
171 | ||
172 | switch (crystal_clock) { | |
173 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | |
174 | return f24_mhz; | |
175 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | |
176 | return f19_2_mhz; | |
177 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ: | |
178 | return f38_4_mhz; | |
179 | case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ: | |
180 | return f25_mhz; | |
181 | default: | |
182 | MISSING_CASE(crystal_clock); | |
183 | return 0; | |
184 | } | |
185 | } | |
186 | ||
f577a03b | 187 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) |
dab91783 | 188 | { |
fdeb6d02 | 189 | struct intel_uncore *uncore = &dev_priv->uncore; |
56f1b31f VS |
190 | u32 f12_5_mhz = 12500000; |
191 | u32 f19_2_mhz = 19200000; | |
192 | u32 f24_mhz = 24000000; | |
dab91783 LL |
193 | |
194 | if (INTEL_GEN(dev_priv) <= 4) { | |
195 | /* PRMs say: | |
196 | * | |
197 | * "The value in this register increments once every 16 | |
198 | * hclks." (through the “Clocking Configuration” | |
199 | * (“CLKCFG”) MCHBAR register) | |
200 | */ | |
56f1b31f | 201 | return RUNTIME_INFO(dev_priv)->rawclk_freq * 1000 / 16; |
dab91783 LL |
202 | } else if (INTEL_GEN(dev_priv) <= 8) { |
203 | /* PRMs say: | |
204 | * | |
205 | * "The PCU TSC counts 10ns increments; this timestamp | |
206 | * reflects bits 38:3 of the TSC (i.e. 80ns granularity, | |
207 | * rolling over every 1.5 hours). | |
208 | */ | |
209 | return f12_5_mhz; | |
210 | } else if (INTEL_GEN(dev_priv) <= 9) { | |
fdeb6d02 | 211 | u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE); |
f577a03b | 212 | u32 freq = 0; |
dab91783 LL |
213 | |
214 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
215 | freq = read_reference_ts_freq(dev_priv); | |
216 | } else { | |
217 | freq = IS_GEN9_LP(dev_priv) ? f19_2_mhz : f24_mhz; | |
218 | ||
219 | /* Now figure out how the command stream's timestamp | |
220 | * register increments from this frequency (it might | |
221 | * increment only every few clock cycle). | |
222 | */ | |
223 | freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >> | |
224 | CTC_SHIFT_PARAMETER_SHIFT); | |
225 | } | |
226 | ||
227 | return freq; | |
465242ee | 228 | } else if (INTEL_GEN(dev_priv) <= 12) { |
fdeb6d02 | 229 | u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE); |
f577a03b | 230 | u32 freq = 0; |
dab91783 LL |
231 | |
232 | /* First figure out the reference frequency. There are 2 ways | |
233 | * we can compute the frequency, either through the | |
234 | * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE | |
235 | * tells us which one we should use. | |
236 | */ | |
237 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | |
238 | freq = read_reference_ts_freq(dev_priv); | |
239 | } else { | |
fdeb6d02 | 240 | u32 rpm_config_reg = intel_uncore_read(uncore, RPM_CONFIG0); |
d775a7b1 PZ |
241 | |
242 | if (INTEL_GEN(dev_priv) <= 10) | |
243 | freq = gen10_get_crystal_clock_freq(dev_priv, | |
244 | rpm_config_reg); | |
245 | else | |
246 | freq = gen11_get_crystal_clock_freq(dev_priv, | |
247 | rpm_config_reg); | |
dab91783 | 248 | |
53ff2641 LL |
249 | /* Now figure out how the command stream's timestamp |
250 | * register increments from this frequency (it might | |
251 | * increment only every few clock cycle). | |
252 | */ | |
253 | freq >>= 3 - ((rpm_config_reg & | |
254 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> | |
255 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); | |
256 | } | |
dab91783 LL |
257 | |
258 | return freq; | |
259 | } | |
260 | ||
fe66e928 | 261 | MISSING_CASE("Unknown gen, unable to read command streamer timestamp frequency\n"); |
dab91783 LL |
262 | return 0; |
263 | } | |
264 | ||
805446c8 TU |
265 | #undef INTEL_VGA_DEVICE |
266 | #define INTEL_VGA_DEVICE(id, info) (id) | |
267 | ||
268 | static const u16 subplatform_ult_ids[] = { | |
269 | INTEL_HSW_ULT_GT1_IDS(0), | |
270 | INTEL_HSW_ULT_GT2_IDS(0), | |
271 | INTEL_HSW_ULT_GT3_IDS(0), | |
272 | INTEL_BDW_ULT_GT1_IDS(0), | |
273 | INTEL_BDW_ULT_GT2_IDS(0), | |
274 | INTEL_BDW_ULT_GT3_IDS(0), | |
275 | INTEL_BDW_ULT_RSVD_IDS(0), | |
276 | INTEL_SKL_ULT_GT1_IDS(0), | |
277 | INTEL_SKL_ULT_GT2_IDS(0), | |
278 | INTEL_SKL_ULT_GT3_IDS(0), | |
279 | INTEL_KBL_ULT_GT1_IDS(0), | |
280 | INTEL_KBL_ULT_GT2_IDS(0), | |
281 | INTEL_KBL_ULT_GT3_IDS(0), | |
282 | INTEL_CFL_U_GT2_IDS(0), | |
283 | INTEL_CFL_U_GT3_IDS(0), | |
284 | INTEL_WHL_U_GT1_IDS(0), | |
285 | INTEL_WHL_U_GT2_IDS(0), | |
c3ad8d29 | 286 | INTEL_WHL_U_GT3_IDS(0), |
8717c6b7 LS |
287 | INTEL_CML_U_GT1_IDS(0), |
288 | INTEL_CML_U_GT2_IDS(0), | |
805446c8 TU |
289 | }; |
290 | ||
291 | static const u16 subplatform_ulx_ids[] = { | |
292 | INTEL_HSW_ULX_GT1_IDS(0), | |
293 | INTEL_HSW_ULX_GT2_IDS(0), | |
294 | INTEL_BDW_ULX_GT1_IDS(0), | |
295 | INTEL_BDW_ULX_GT2_IDS(0), | |
296 | INTEL_BDW_ULX_GT3_IDS(0), | |
297 | INTEL_BDW_ULX_RSVD_IDS(0), | |
298 | INTEL_SKL_ULX_GT1_IDS(0), | |
299 | INTEL_SKL_ULX_GT2_IDS(0), | |
300 | INTEL_KBL_ULX_GT1_IDS(0), | |
c3ad8d29 | 301 | INTEL_KBL_ULX_GT2_IDS(0), |
805446c8 | 302 | INTEL_AML_KBL_GT2_IDS(0), |
c3ad8d29 | 303 | INTEL_AML_CFL_GT2_IDS(0), |
805446c8 TU |
304 | }; |
305 | ||
306 | static const u16 subplatform_portf_ids[] = { | |
307 | INTEL_CNL_PORT_F_IDS(0), | |
c3ad8d29 | 308 | INTEL_ICL_PORT_F_IDS(0), |
805446c8 TU |
309 | }; |
310 | ||
311 | static bool find_devid(u16 id, const u16 *p, unsigned int num) | |
312 | { | |
313 | for (; num; num--, p++) { | |
314 | if (*p == id) | |
315 | return true; | |
316 | } | |
317 | ||
318 | return false; | |
319 | } | |
320 | ||
321 | void intel_device_info_subplatform_init(struct drm_i915_private *i915) | |
322 | { | |
323 | const struct intel_device_info *info = INTEL_INFO(i915); | |
324 | const struct intel_runtime_info *rinfo = RUNTIME_INFO(i915); | |
325 | const unsigned int pi = __platform_mask_index(rinfo, info->platform); | |
326 | const unsigned int pb = __platform_mask_bit(rinfo, info->platform); | |
327 | u16 devid = INTEL_DEVID(i915); | |
640cde65 | 328 | u32 mask = 0; |
805446c8 TU |
329 | |
330 | /* Make sure IS_<platform> checks are working. */ | |
331 | RUNTIME_INFO(i915)->platform_mask[pi] = BIT(pb); | |
332 | ||
333 | /* Find and mark subplatform bits based on the PCI device id. */ | |
334 | if (find_devid(devid, subplatform_ult_ids, | |
335 | ARRAY_SIZE(subplatform_ult_ids))) { | |
336 | mask = BIT(INTEL_SUBPLATFORM_ULT); | |
337 | } else if (find_devid(devid, subplatform_ulx_ids, | |
338 | ARRAY_SIZE(subplatform_ulx_ids))) { | |
339 | mask = BIT(INTEL_SUBPLATFORM_ULX); | |
340 | if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { | |
341 | /* ULX machines are also considered ULT. */ | |
342 | mask |= BIT(INTEL_SUBPLATFORM_ULT); | |
343 | } | |
805446c8 TU |
344 | } else if (find_devid(devid, subplatform_portf_ids, |
345 | ARRAY_SIZE(subplatform_portf_ids))) { | |
346 | mask = BIT(INTEL_SUBPLATFORM_PORTF); | |
347 | } | |
348 | ||
1d3cc7ab JRS |
349 | if (IS_TIGERLAKE(i915)) { |
350 | struct pci_dev *root, *pdev = i915->drm.pdev; | |
351 | ||
352 | root = list_first_entry(&pdev->bus->devices, typeof(*root), bus_list); | |
353 | ||
354 | drm_WARN_ON(&i915->drm, mask); | |
355 | drm_WARN_ON(&i915->drm, (root->device & TGL_ROOT_DEVICE_MASK) != | |
356 | TGL_ROOT_DEVICE_ID); | |
357 | ||
358 | switch (root->device & TGL_ROOT_DEVICE_SKU_MASK) { | |
359 | case TGL_ROOT_DEVICE_SKU_ULX: | |
360 | mask = BIT(INTEL_SUBPLATFORM_ULX); | |
361 | break; | |
362 | case TGL_ROOT_DEVICE_SKU_ULT: | |
363 | mask = BIT(INTEL_SUBPLATFORM_ULT); | |
364 | break; | |
365 | } | |
366 | } | |
367 | ||
805446c8 TU |
368 | GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_BITS); |
369 | ||
370 | RUNTIME_INFO(i915)->platform_mask[pi] |= mask; | |
371 | } | |
372 | ||
6a7e51f3 MW |
373 | /** |
374 | * intel_device_info_runtime_init - initialize runtime info | |
963cc126 | 375 | * @dev_priv: the i915 device |
6a7e51f3 | 376 | * |
94b4f3ba CW |
377 | * Determine various intel_device_info fields at runtime. |
378 | * | |
379 | * Use it when either: | |
380 | * - it's judged too laborious to fill n static structures with the limit | |
381 | * when a simple if statement does the job, | |
382 | * - run-time checks (eg read fuse/strap registers) are needed. | |
383 | * | |
384 | * This function needs to be called: | |
385 | * - after the MMIO has been setup as we are reading registers, | |
386 | * - after the PCH has been detected, | |
387 | * - before the first usage of the fields it can tweak. | |
388 | */ | |
1400cc7e | 389 | void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) |
94b4f3ba | 390 | { |
1400cc7e | 391 | struct intel_device_info *info = mkwrite_device_info(dev_priv); |
0258404f | 392 | struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv); |
94b4f3ba CW |
393 | enum pipe pipe; |
394 | ||
6e7406db MK |
395 | if (INTEL_GEN(dev_priv) >= 10) { |
396 | for_each_pipe(dev_priv, pipe) | |
0258404f | 397 | runtime->num_scalers[pipe] = 2; |
cf819eff | 398 | } else if (IS_GEN(dev_priv, 9)) { |
0258404f JN |
399 | runtime->num_scalers[PIPE_A] = 2; |
400 | runtime->num_scalers[PIPE_B] = 2; | |
401 | runtime->num_scalers[PIPE_C] = 1; | |
0bf0230e ACO |
402 | } |
403 | ||
8a68d464 | 404 | BUILD_BUG_ON(BITS_PER_TYPE(intel_engine_mask_t) < I915_NUM_ENGINES); |
022d3093 | 405 | |
99e2d8bc MR |
406 | if (IS_ROCKETLAKE(dev_priv)) |
407 | for_each_pipe(dev_priv, pipe) | |
408 | runtime->num_sprites[pipe] = 4; | |
409 | else if (INTEL_GEN(dev_priv) >= 11) | |
6711bd73 | 410 | for_each_pipe(dev_priv, pipe) |
0258404f | 411 | runtime->num_sprites[pipe] = 6; |
cf819eff | 412 | else if (IS_GEN(dev_priv, 10) || IS_GEMINILAKE(dev_priv)) |
e9c98825 | 413 | for_each_pipe(dev_priv, pipe) |
0258404f | 414 | runtime->num_sprites[pipe] = 3; |
e9c98825 | 415 | else if (IS_BROXTON(dev_priv)) { |
6711bd73 ML |
416 | /* |
417 | * Skylake and Broxton currently don't expose the topmost plane as its | |
418 | * use is exclusive with the legacy cursor and we only want to expose | |
419 | * one of those, not both. Until we can safely expose the topmost plane | |
420 | * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported, | |
421 | * we don't expose the topmost plane at all to prevent ABI breakage | |
422 | * down the line. | |
423 | */ | |
424 | ||
0258404f JN |
425 | runtime->num_sprites[PIPE_A] = 2; |
426 | runtime->num_sprites[PIPE_B] = 2; | |
427 | runtime->num_sprites[PIPE_C] = 1; | |
33edc24d | 428 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
94b4f3ba | 429 | for_each_pipe(dev_priv, pipe) |
0258404f | 430 | runtime->num_sprites[pipe] = 2; |
ab33081a | 431 | } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) { |
94b4f3ba | 432 | for_each_pipe(dev_priv, pipe) |
0258404f | 433 | runtime->num_sprites[pipe] = 1; |
33edc24d | 434 | } |
94b4f3ba | 435 | |
ef404bc6 JN |
436 | if (HAS_DISPLAY(dev_priv) && IS_GEN_RANGE(dev_priv, 7, 8) && |
437 | HAS_PCH_SPLIT(dev_priv)) { | |
fdeb6d02 DCS |
438 | u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); |
439 | u32 sfuse_strap = intel_de_read(dev_priv, SFUSE_STRAP); | |
94b4f3ba CW |
440 | |
441 | /* | |
442 | * SFUSE_STRAP is supposed to have a bit signalling the display | |
443 | * is fused off. Unfortunately it seems that, at least in | |
444 | * certain cases, fused off display means that PCH display | |
445 | * reads don't land anywhere. In that case, we read 0s. | |
446 | * | |
447 | * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK | |
448 | * should be set when taking over after the firmware. | |
449 | */ | |
450 | if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE || | |
451 | sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED || | |
b9eb89b2 | 452 | (HAS_PCH_CPT(dev_priv) && |
94b4f3ba | 453 | !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { |
68b32717 WK |
454 | drm_info(&dev_priv->drm, |
455 | "Display fused off, disabling\n"); | |
8d8b0031 | 456 | info->pipe_mask = 0; |
10cf8e75 | 457 | info->cpu_transcoder_mask = 0; |
94b4f3ba | 458 | } else if (fuse_strap & IVB_PIPE_C_DISABLE) { |
68b32717 | 459 | drm_info(&dev_priv->drm, "PipeC fused off\n"); |
8d8b0031 | 460 | info->pipe_mask &= ~BIT(PIPE_C); |
10cf8e75 | 461 | info->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); |
94b4f3ba | 462 | } |
bea68f4a | 463 | } else if (HAS_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 9) { |
fdeb6d02 | 464 | u32 dfsm = intel_de_read(dev_priv, SKL_DFSM); |
94b4f3ba | 465 | |
10cf8e75 VS |
466 | if (dfsm & SKL_DFSM_PIPE_A_DISABLE) { |
467 | info->pipe_mask &= ~BIT(PIPE_A); | |
468 | info->cpu_transcoder_mask &= ~BIT(TRANSCODER_A); | |
469 | } | |
470 | if (dfsm & SKL_DFSM_PIPE_B_DISABLE) { | |
471 | info->pipe_mask &= ~BIT(PIPE_B); | |
472 | info->cpu_transcoder_mask &= ~BIT(TRANSCODER_B); | |
473 | } | |
474 | if (dfsm & SKL_DFSM_PIPE_C_DISABLE) { | |
475 | info->pipe_mask &= ~BIT(PIPE_C); | |
476 | info->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); | |
477 | } | |
478 | if (INTEL_GEN(dev_priv) >= 12 && | |
479 | (dfsm & TGL_DFSM_PIPE_D_DISABLE)) { | |
480 | info->pipe_mask &= ~BIT(PIPE_D); | |
481 | info->cpu_transcoder_mask &= ~BIT(TRANSCODER_D); | |
482 | } | |
74393109 JRS |
483 | |
484 | if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE) | |
485 | info->display.has_hdcp = 0; | |
7a40aac1 JRS |
486 | |
487 | if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE) | |
488 | info->display.has_fbc = 0; | |
ee595888 JRS |
489 | |
490 | if (INTEL_GEN(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE)) | |
491 | info->display.has_csr = 0; | |
0f9ed3b2 JRS |
492 | |
493 | if (INTEL_GEN(dev_priv) >= 10 && | |
494 | (dfsm & CNL_DFSM_DISPLAY_DSC_DISABLE)) | |
495 | info->display.has_dsc = 0; | |
94b4f3ba CW |
496 | } |
497 | ||
cf819eff | 498 | if (IS_GEN(dev_priv, 6) && intel_vtd_active()) { |
68b32717 WK |
499 | drm_info(&dev_priv->drm, |
500 | "Disabling ppGTT for VT-d support\n"); | |
cbecbcca | 501 | info->ppgtt_type = INTEL_PPGTT_NONE; |
4bdafb9d CW |
502 | } |
503 | ||
b04002f4 CW |
504 | runtime->rawclk_freq = intel_read_rawclk(dev_priv); |
505 | drm_dbg(&dev_priv->drm, "rawclk rate: %d kHz\n", runtime->rawclk_freq); | |
506 | ||
dab91783 | 507 | /* Initialize command stream timestamp frequency */ |
56f1b31f | 508 | runtime->cs_timestamp_frequency_hz = |
d194314d | 509 | read_timestamp_frequency(dev_priv); |
56f1b31f | 510 | if (runtime->cs_timestamp_frequency_hz) { |
d194314d | 511 | runtime->cs_timestamp_period_ns = |
802a5820 | 512 | i915_cs_timestamp_ticks_to_ns(dev_priv, 1); |
d194314d CW |
513 | drm_dbg(&dev_priv->drm, |
514 | "CS timestamp wraparound in %lldms\n", | |
515 | div_u64(mul_u32_u32(runtime->cs_timestamp_period_ns, | |
516 | S32_MAX), | |
517 | USEC_PER_SEC)); | |
518 | } | |
94b4f3ba | 519 | } |
3fed1808 CW |
520 | |
521 | void intel_driver_caps_print(const struct intel_driver_caps *caps, | |
522 | struct drm_printer *p) | |
523 | { | |
481827b4 CW |
524 | drm_printf(p, "Has logical contexts? %s\n", |
525 | yesno(caps->has_logical_contexts)); | |
3fed1808 CW |
526 | drm_printf(p, "scheduler: %x\n", caps->scheduler); |
527 | } |