diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_device_info.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_device_info.c | 121 |
1 files changed, 110 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 875d428ea75f..02f8bf101ccd 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c | |||
@@ -235,16 +235,6 @@ static void gen9_sseu_info_init(struct drm_i915_private *dev_priv) | |||
235 | #define IS_SS_DISABLED(ss) (!(sseu->subslice_mask & BIT(ss))) | 235 | #define IS_SS_DISABLED(ss) (!(sseu->subslice_mask & BIT(ss))) |
236 | info->has_pooled_eu = hweight8(sseu->subslice_mask) == 3; | 236 | info->has_pooled_eu = hweight8(sseu->subslice_mask) == 3; |
237 | 237 | ||
238 | /* | ||
239 | * There is a HW issue in 2x6 fused down parts that requires | ||
240 | * Pooled EU to be enabled as a WA. The pool configuration | ||
241 | * changes depending upon which subslice is fused down. This | ||
242 | * doesn't affect if the device has all 3 subslices enabled. | ||
243 | */ | ||
244 | /* WaEnablePooledEuFor2x6:bxt */ | ||
245 | info->has_pooled_eu |= (hweight8(sseu->subslice_mask) == 2 && | ||
246 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST)); | ||
247 | |||
248 | sseu->min_eu_in_pool = 0; | 238 | sseu->min_eu_in_pool = 0; |
249 | if (info->has_pooled_eu) { | 239 | if (info->has_pooled_eu) { |
250 | if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) | 240 | if (IS_SS_DISABLED(2) || IS_SS_DISABLED(0)) |
@@ -329,6 +319,107 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) | |||
329 | sseu->has_eu_pg = 0; | 319 | sseu->has_eu_pg = 0; |
330 | } | 320 | } |
331 | 321 | ||
322 | static u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) | ||
323 | { | ||
324 | u32 ts_override = I915_READ(GEN9_TIMESTAMP_OVERRIDE); | ||
325 | u32 base_freq, frac_freq; | ||
326 | |||
327 | base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >> | ||
328 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1; | ||
329 | base_freq *= 1000; | ||
330 | |||
331 | frac_freq = ((ts_override & | ||
332 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >> | ||
333 | GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT); | ||
334 | frac_freq = 1000 / (frac_freq + 1); | ||
335 | |||
336 | return base_freq + frac_freq; | ||
337 | } | ||
338 | |||
339 | static u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) | ||
340 | { | ||
341 | u32 f12_5_mhz = 12500; | ||
342 | u32 f19_2_mhz = 19200; | ||
343 | u32 f24_mhz = 24000; | ||
344 | |||
345 | if (INTEL_GEN(dev_priv) <= 4) { | ||
346 | /* PRMs say: | ||
347 | * | ||
348 | * "The value in this register increments once every 16 | ||
349 | * hclks." (through the “Clocking Configuration” | ||
350 | * (“CLKCFG”) MCHBAR register) | ||
351 | */ | ||
352 | return dev_priv->rawclk_freq / 16; | ||
353 | } else if (INTEL_GEN(dev_priv) <= 8) { | ||
354 | /* PRMs say: | ||
355 | * | ||
356 | * "The PCU TSC counts 10ns increments; this timestamp | ||
357 | * reflects bits 38:3 of the TSC (i.e. 80ns granularity, | ||
358 | * rolling over every 1.5 hours). | ||
359 | */ | ||
360 | return f12_5_mhz; | ||
361 | } else if (INTEL_GEN(dev_priv) <= 9) { | ||
362 | u32 ctc_reg = I915_READ(CTC_MODE); | ||
363 | u32 freq = 0; | ||
364 | |||
365 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | ||
366 | freq = read_reference_ts_freq(dev_priv); | ||
367 | } else { | ||
368 | freq = IS_GEN9_LP(dev_priv) ? f19_2_mhz : f24_mhz; | ||
369 | |||
370 | /* Now figure out how the command stream's timestamp | ||
371 | * register increments from this frequency (it might | ||
372 | * increment only every few clock cycle). | ||
373 | */ | ||
374 | freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >> | ||
375 | CTC_SHIFT_PARAMETER_SHIFT); | ||
376 | } | ||
377 | |||
378 | return freq; | ||
379 | } else if (INTEL_GEN(dev_priv) <= 10) { | ||
380 | u32 ctc_reg = I915_READ(CTC_MODE); | ||
381 | u32 freq = 0; | ||
382 | u32 rpm_config_reg = 0; | ||
383 | |||
384 | /* First figure out the reference frequency. There are 2 ways | ||
385 | * we can compute the frequency, either through the | ||
386 | * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE | ||
387 | * tells us which one we should use. | ||
388 | */ | ||
389 | if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { | ||
390 | freq = read_reference_ts_freq(dev_priv); | ||
391 | } else { | ||
392 | u32 crystal_clock; | ||
393 | |||
394 | rpm_config_reg = I915_READ(RPM_CONFIG0); | ||
395 | crystal_clock = (rpm_config_reg & | ||
396 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> | ||
397 | GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; | ||
398 | switch (crystal_clock) { | ||
399 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: | ||
400 | freq = f19_2_mhz; | ||
401 | break; | ||
402 | case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: | ||
403 | freq = f24_mhz; | ||
404 | break; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | /* Now figure out how the command stream's timestamp register | ||
409 | * increments from this frequency (it might increment only | ||
410 | * every few clock cycle). | ||
411 | */ | ||
412 | freq >>= 3 - ((rpm_config_reg & | ||
413 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> | ||
414 | GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); | ||
415 | |||
416 | return freq; | ||
417 | } | ||
418 | |||
419 | DRM_ERROR("Unknown gen, unable to compute command stream timestamp frequency\n"); | ||
420 | return 0; | ||
421 | } | ||
422 | |||
332 | /* | 423 | /* |
333 | * Determine various intel_device_info fields at runtime. | 424 | * Determine various intel_device_info fields at runtime. |
334 | * | 425 | * |
@@ -347,7 +438,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) | |||
347 | struct intel_device_info *info = mkwrite_device_info(dev_priv); | 438 | struct intel_device_info *info = mkwrite_device_info(dev_priv); |
348 | enum pipe pipe; | 439 | enum pipe pipe; |
349 | 440 | ||
350 | if (INTEL_GEN(dev_priv) >= 9) { | 441 | if (INTEL_GEN(dev_priv) >= 10) { |
442 | for_each_pipe(dev_priv, pipe) | ||
443 | info->num_scalers[pipe] = 2; | ||
444 | } else if (INTEL_GEN(dev_priv) == 9) { | ||
351 | info->num_scalers[PIPE_A] = 2; | 445 | info->num_scalers[PIPE_A] = 2; |
352 | info->num_scalers[PIPE_B] = 2; | 446 | info->num_scalers[PIPE_B] = 2; |
353 | info->num_scalers[PIPE_C] = 1; | 447 | info->num_scalers[PIPE_C] = 1; |
@@ -447,6 +541,9 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) | |||
447 | else if (INTEL_GEN(dev_priv) >= 10) | 541 | else if (INTEL_GEN(dev_priv) >= 10) |
448 | gen10_sseu_info_init(dev_priv); | 542 | gen10_sseu_info_init(dev_priv); |
449 | 543 | ||
544 | /* Initialize command stream timestamp frequency */ | ||
545 | info->cs_timestamp_frequency_khz = read_timestamp_frequency(dev_priv); | ||
546 | |||
450 | DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); | 547 | DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); |
451 | DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); | 548 | DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); |
452 | DRM_DEBUG_DRIVER("subslice total: %u\n", | 549 | DRM_DEBUG_DRIVER("subslice total: %u\n", |
@@ -462,4 +559,6 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) | |||
462 | info->sseu.has_subslice_pg ? "y" : "n"); | 559 | info->sseu.has_subslice_pg ? "y" : "n"); |
463 | DRM_DEBUG_DRIVER("has EU power gating: %s\n", | 560 | DRM_DEBUG_DRIVER("has EU power gating: %s\n", |
464 | info->sseu.has_eu_pg ? "y" : "n"); | 561 | info->sseu.has_eu_pg ? "y" : "n"); |
562 | DRM_DEBUG_DRIVER("CS timestamp frequency: %u kHz\n", | ||
563 | info->cs_timestamp_frequency_khz); | ||
465 | } | 564 | } |