18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright © 2016 Intel Corporation 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next 128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 138c2ecf20Sopenharmony_ci * Software. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218c2ecf20Sopenharmony_ci * IN THE SOFTWARE. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <drm/drm_print.h> 268c2ecf20Sopenharmony_ci#include <drm/i915_pciids.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "display/intel_cdclk.h" 298c2ecf20Sopenharmony_ci#include "display/intel_de.h" 308c2ecf20Sopenharmony_ci#include "intel_device_info.h" 318c2ecf20Sopenharmony_ci#include "i915_drv.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define PLATFORM_NAME(x) [INTEL_##x] = #x 348c2ecf20Sopenharmony_cistatic const char * const platform_names[] = { 358c2ecf20Sopenharmony_ci PLATFORM_NAME(I830), 368c2ecf20Sopenharmony_ci PLATFORM_NAME(I845G), 378c2ecf20Sopenharmony_ci PLATFORM_NAME(I85X), 388c2ecf20Sopenharmony_ci PLATFORM_NAME(I865G), 398c2ecf20Sopenharmony_ci PLATFORM_NAME(I915G), 408c2ecf20Sopenharmony_ci PLATFORM_NAME(I915GM), 418c2ecf20Sopenharmony_ci PLATFORM_NAME(I945G), 428c2ecf20Sopenharmony_ci PLATFORM_NAME(I945GM), 438c2ecf20Sopenharmony_ci PLATFORM_NAME(G33), 448c2ecf20Sopenharmony_ci PLATFORM_NAME(PINEVIEW), 458c2ecf20Sopenharmony_ci PLATFORM_NAME(I965G), 468c2ecf20Sopenharmony_ci PLATFORM_NAME(I965GM), 478c2ecf20Sopenharmony_ci PLATFORM_NAME(G45), 488c2ecf20Sopenharmony_ci PLATFORM_NAME(GM45), 498c2ecf20Sopenharmony_ci PLATFORM_NAME(IRONLAKE), 508c2ecf20Sopenharmony_ci PLATFORM_NAME(SANDYBRIDGE), 518c2ecf20Sopenharmony_ci PLATFORM_NAME(IVYBRIDGE), 528c2ecf20Sopenharmony_ci PLATFORM_NAME(VALLEYVIEW), 538c2ecf20Sopenharmony_ci PLATFORM_NAME(HASWELL), 548c2ecf20Sopenharmony_ci PLATFORM_NAME(BROADWELL), 558c2ecf20Sopenharmony_ci PLATFORM_NAME(CHERRYVIEW), 568c2ecf20Sopenharmony_ci PLATFORM_NAME(SKYLAKE), 578c2ecf20Sopenharmony_ci PLATFORM_NAME(BROXTON), 588c2ecf20Sopenharmony_ci PLATFORM_NAME(KABYLAKE), 598c2ecf20Sopenharmony_ci PLATFORM_NAME(GEMINILAKE), 608c2ecf20Sopenharmony_ci PLATFORM_NAME(COFFEELAKE), 618c2ecf20Sopenharmony_ci PLATFORM_NAME(COMETLAKE), 628c2ecf20Sopenharmony_ci PLATFORM_NAME(CANNONLAKE), 638c2ecf20Sopenharmony_ci PLATFORM_NAME(ICELAKE), 648c2ecf20Sopenharmony_ci PLATFORM_NAME(ELKHARTLAKE), 658c2ecf20Sopenharmony_ci PLATFORM_NAME(TIGERLAKE), 668c2ecf20Sopenharmony_ci PLATFORM_NAME(ROCKETLAKE), 678c2ecf20Sopenharmony_ci PLATFORM_NAME(DG1), 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci#undef PLATFORM_NAME 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciconst char *intel_platform_name(enum intel_platform platform) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(platform_names) != INTEL_MAX_PLATFORMS); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(platform >= ARRAY_SIZE(platform_names) || 768c2ecf20Sopenharmony_ci platform_names[platform] == NULL)) 778c2ecf20Sopenharmony_ci return "<unknown>"; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return platform_names[platform]; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic const char *iommu_name(void) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci const char *msg = "n/a"; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#ifdef CONFIG_INTEL_IOMMU 878c2ecf20Sopenharmony_ci msg = enableddisabled(intel_iommu_gfx_mapped); 888c2ecf20Sopenharmony_ci#endif 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci return msg; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_civoid intel_device_info_print_static(const struct intel_device_info *info, 948c2ecf20Sopenharmony_ci struct drm_printer *p) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci drm_printf(p, "gen: %d\n", info->gen); 978c2ecf20Sopenharmony_ci drm_printf(p, "gt: %d\n", info->gt); 988c2ecf20Sopenharmony_ci drm_printf(p, "iommu: %s\n", iommu_name()); 998c2ecf20Sopenharmony_ci drm_printf(p, "memory-regions: %x\n", info->memory_regions); 1008c2ecf20Sopenharmony_ci drm_printf(p, "page-sizes: %x\n", info->page_sizes); 1018c2ecf20Sopenharmony_ci drm_printf(p, "platform: %s\n", intel_platform_name(info->platform)); 1028c2ecf20Sopenharmony_ci drm_printf(p, "ppgtt-size: %d\n", info->ppgtt_size); 1038c2ecf20Sopenharmony_ci drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type); 1048c2ecf20Sopenharmony_ci drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name)); 1078c2ecf20Sopenharmony_ci DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); 1088c2ecf20Sopenharmony_ci#undef PRINT_FLAG 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name)); 1118c2ecf20Sopenharmony_ci DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); 1128c2ecf20Sopenharmony_ci#undef PRINT_FLAG 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_civoid intel_device_info_print_runtime(const struct intel_runtime_info *info, 1168c2ecf20Sopenharmony_ci struct drm_printer *p) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci drm_printf(p, "rawclk rate: %u kHz\n", info->rawclk_freq); 1198c2ecf20Sopenharmony_ci drm_printf(p, "CS timestamp frequency: %u Hz\n", 1208c2ecf20Sopenharmony_ci info->cs_timestamp_frequency_hz); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic u32 read_reference_ts_freq(struct drm_i915_private *dev_priv) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci u32 ts_override = intel_uncore_read(&dev_priv->uncore, 1268c2ecf20Sopenharmony_ci GEN9_TIMESTAMP_OVERRIDE); 1278c2ecf20Sopenharmony_ci u32 base_freq, frac_freq; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci base_freq = ((ts_override & GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_MASK) >> 1308c2ecf20Sopenharmony_ci GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DIVIDER_SHIFT) + 1; 1318c2ecf20Sopenharmony_ci base_freq *= 1000000; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci frac_freq = ((ts_override & 1348c2ecf20Sopenharmony_ci GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_MASK) >> 1358c2ecf20Sopenharmony_ci GEN9_TIMESTAMP_OVERRIDE_US_COUNTER_DENOMINATOR_SHIFT); 1368c2ecf20Sopenharmony_ci frac_freq = 1000000 / (frac_freq + 1); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci return base_freq + frac_freq; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic u32 gen10_get_crystal_clock_freq(struct drm_i915_private *dev_priv, 1428c2ecf20Sopenharmony_ci u32 rpm_config_reg) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci u32 f19_2_mhz = 19200000; 1458c2ecf20Sopenharmony_ci u32 f24_mhz = 24000000; 1468c2ecf20Sopenharmony_ci u32 crystal_clock = (rpm_config_reg & 1478c2ecf20Sopenharmony_ci GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> 1488c2ecf20Sopenharmony_ci GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci switch (crystal_clock) { 1518c2ecf20Sopenharmony_ci case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: 1528c2ecf20Sopenharmony_ci return f19_2_mhz; 1538c2ecf20Sopenharmony_ci case GEN9_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: 1548c2ecf20Sopenharmony_ci return f24_mhz; 1558c2ecf20Sopenharmony_ci default: 1568c2ecf20Sopenharmony_ci MISSING_CASE(crystal_clock); 1578c2ecf20Sopenharmony_ci return 0; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic u32 gen11_get_crystal_clock_freq(struct drm_i915_private *dev_priv, 1628c2ecf20Sopenharmony_ci u32 rpm_config_reg) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci u32 f19_2_mhz = 19200000; 1658c2ecf20Sopenharmony_ci u32 f24_mhz = 24000000; 1668c2ecf20Sopenharmony_ci u32 f25_mhz = 25000000; 1678c2ecf20Sopenharmony_ci u32 f38_4_mhz = 38400000; 1688c2ecf20Sopenharmony_ci u32 crystal_clock = (rpm_config_reg & 1698c2ecf20Sopenharmony_ci GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK) >> 1708c2ecf20Sopenharmony_ci GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_SHIFT; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci switch (crystal_clock) { 1738c2ecf20Sopenharmony_ci case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ: 1748c2ecf20Sopenharmony_ci return f24_mhz; 1758c2ecf20Sopenharmony_ci case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ: 1768c2ecf20Sopenharmony_ci return f19_2_mhz; 1778c2ecf20Sopenharmony_ci case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ: 1788c2ecf20Sopenharmony_ci return f38_4_mhz; 1798c2ecf20Sopenharmony_ci case GEN11_RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ: 1808c2ecf20Sopenharmony_ci return f25_mhz; 1818c2ecf20Sopenharmony_ci default: 1828c2ecf20Sopenharmony_ci MISSING_CASE(crystal_clock); 1838c2ecf20Sopenharmony_ci return 0; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic u32 read_timestamp_frequency(struct drm_i915_private *dev_priv) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct intel_uncore *uncore = &dev_priv->uncore; 1908c2ecf20Sopenharmony_ci u32 f12_5_mhz = 12500000; 1918c2ecf20Sopenharmony_ci u32 f19_2_mhz = 19200000; 1928c2ecf20Sopenharmony_ci u32 f24_mhz = 24000000; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) <= 4) { 1958c2ecf20Sopenharmony_ci /* PRMs say: 1968c2ecf20Sopenharmony_ci * 1978c2ecf20Sopenharmony_ci * "The value in this register increments once every 16 1988c2ecf20Sopenharmony_ci * hclks." (through the “Clocking Configuration” 1998c2ecf20Sopenharmony_ci * (“CLKCFG”) MCHBAR register) 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci return RUNTIME_INFO(dev_priv)->rawclk_freq * 1000 / 16; 2028c2ecf20Sopenharmony_ci } else if (INTEL_GEN(dev_priv) <= 8) { 2038c2ecf20Sopenharmony_ci /* PRMs say: 2048c2ecf20Sopenharmony_ci * 2058c2ecf20Sopenharmony_ci * "The PCU TSC counts 10ns increments; this timestamp 2068c2ecf20Sopenharmony_ci * reflects bits 38:3 of the TSC (i.e. 80ns granularity, 2078c2ecf20Sopenharmony_ci * rolling over every 1.5 hours). 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci return f12_5_mhz; 2108c2ecf20Sopenharmony_ci } else if (INTEL_GEN(dev_priv) <= 9) { 2118c2ecf20Sopenharmony_ci u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE); 2128c2ecf20Sopenharmony_ci u32 freq = 0; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { 2158c2ecf20Sopenharmony_ci freq = read_reference_ts_freq(dev_priv); 2168c2ecf20Sopenharmony_ci } else { 2178c2ecf20Sopenharmony_ci freq = IS_GEN9_LP(dev_priv) ? f19_2_mhz : f24_mhz; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Now figure out how the command stream's timestamp 2208c2ecf20Sopenharmony_ci * register increments from this frequency (it might 2218c2ecf20Sopenharmony_ci * increment only every few clock cycle). 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_ci freq >>= 3 - ((ctc_reg & CTC_SHIFT_PARAMETER_MASK) >> 2248c2ecf20Sopenharmony_ci CTC_SHIFT_PARAMETER_SHIFT); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return freq; 2288c2ecf20Sopenharmony_ci } else if (INTEL_GEN(dev_priv) <= 12) { 2298c2ecf20Sopenharmony_ci u32 ctc_reg = intel_uncore_read(uncore, CTC_MODE); 2308c2ecf20Sopenharmony_ci u32 freq = 0; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* First figure out the reference frequency. There are 2 ways 2338c2ecf20Sopenharmony_ci * we can compute the frequency, either through the 2348c2ecf20Sopenharmony_ci * TIMESTAMP_OVERRIDE register or through RPM_CONFIG. CTC_MODE 2358c2ecf20Sopenharmony_ci * tells us which one we should use. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ci if ((ctc_reg & CTC_SOURCE_PARAMETER_MASK) == CTC_SOURCE_DIVIDE_LOGIC) { 2388c2ecf20Sopenharmony_ci freq = read_reference_ts_freq(dev_priv); 2398c2ecf20Sopenharmony_ci } else { 2408c2ecf20Sopenharmony_ci u32 rpm_config_reg = intel_uncore_read(uncore, RPM_CONFIG0); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) <= 10) 2438c2ecf20Sopenharmony_ci freq = gen10_get_crystal_clock_freq(dev_priv, 2448c2ecf20Sopenharmony_ci rpm_config_reg); 2458c2ecf20Sopenharmony_ci else 2468c2ecf20Sopenharmony_ci freq = gen11_get_crystal_clock_freq(dev_priv, 2478c2ecf20Sopenharmony_ci rpm_config_reg); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Now figure out how the command stream's timestamp 2508c2ecf20Sopenharmony_ci * register increments from this frequency (it might 2518c2ecf20Sopenharmony_ci * increment only every few clock cycle). 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci freq >>= 3 - ((rpm_config_reg & 2548c2ecf20Sopenharmony_ci GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK) >> 2558c2ecf20Sopenharmony_ci GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_SHIFT); 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return freq; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci MISSING_CASE("Unknown gen, unable to read command streamer timestamp frequency\n"); 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#undef INTEL_VGA_DEVICE 2668c2ecf20Sopenharmony_ci#define INTEL_VGA_DEVICE(id, info) (id) 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic const u16 subplatform_ult_ids[] = { 2698c2ecf20Sopenharmony_ci INTEL_HSW_ULT_GT1_IDS(0), 2708c2ecf20Sopenharmony_ci INTEL_HSW_ULT_GT2_IDS(0), 2718c2ecf20Sopenharmony_ci INTEL_HSW_ULT_GT3_IDS(0), 2728c2ecf20Sopenharmony_ci INTEL_BDW_ULT_GT1_IDS(0), 2738c2ecf20Sopenharmony_ci INTEL_BDW_ULT_GT2_IDS(0), 2748c2ecf20Sopenharmony_ci INTEL_BDW_ULT_GT3_IDS(0), 2758c2ecf20Sopenharmony_ci INTEL_BDW_ULT_RSVD_IDS(0), 2768c2ecf20Sopenharmony_ci INTEL_SKL_ULT_GT1_IDS(0), 2778c2ecf20Sopenharmony_ci INTEL_SKL_ULT_GT2_IDS(0), 2788c2ecf20Sopenharmony_ci INTEL_SKL_ULT_GT3_IDS(0), 2798c2ecf20Sopenharmony_ci INTEL_KBL_ULT_GT1_IDS(0), 2808c2ecf20Sopenharmony_ci INTEL_KBL_ULT_GT2_IDS(0), 2818c2ecf20Sopenharmony_ci INTEL_KBL_ULT_GT3_IDS(0), 2828c2ecf20Sopenharmony_ci INTEL_CFL_U_GT2_IDS(0), 2838c2ecf20Sopenharmony_ci INTEL_CFL_U_GT3_IDS(0), 2848c2ecf20Sopenharmony_ci INTEL_WHL_U_GT1_IDS(0), 2858c2ecf20Sopenharmony_ci INTEL_WHL_U_GT2_IDS(0), 2868c2ecf20Sopenharmony_ci INTEL_WHL_U_GT3_IDS(0), 2878c2ecf20Sopenharmony_ci INTEL_CML_U_GT1_IDS(0), 2888c2ecf20Sopenharmony_ci INTEL_CML_U_GT2_IDS(0), 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic const u16 subplatform_ulx_ids[] = { 2928c2ecf20Sopenharmony_ci INTEL_HSW_ULX_GT1_IDS(0), 2938c2ecf20Sopenharmony_ci INTEL_HSW_ULX_GT2_IDS(0), 2948c2ecf20Sopenharmony_ci INTEL_BDW_ULX_GT1_IDS(0), 2958c2ecf20Sopenharmony_ci INTEL_BDW_ULX_GT2_IDS(0), 2968c2ecf20Sopenharmony_ci INTEL_BDW_ULX_GT3_IDS(0), 2978c2ecf20Sopenharmony_ci INTEL_BDW_ULX_RSVD_IDS(0), 2988c2ecf20Sopenharmony_ci INTEL_SKL_ULX_GT1_IDS(0), 2998c2ecf20Sopenharmony_ci INTEL_SKL_ULX_GT2_IDS(0), 3008c2ecf20Sopenharmony_ci INTEL_KBL_ULX_GT1_IDS(0), 3018c2ecf20Sopenharmony_ci INTEL_KBL_ULX_GT2_IDS(0), 3028c2ecf20Sopenharmony_ci INTEL_AML_KBL_GT2_IDS(0), 3038c2ecf20Sopenharmony_ci INTEL_AML_CFL_GT2_IDS(0), 3048c2ecf20Sopenharmony_ci}; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic const u16 subplatform_portf_ids[] = { 3078c2ecf20Sopenharmony_ci INTEL_CNL_PORT_F_IDS(0), 3088c2ecf20Sopenharmony_ci INTEL_ICL_PORT_F_IDS(0), 3098c2ecf20Sopenharmony_ci}; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic bool find_devid(u16 id, const u16 *p, unsigned int num) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci for (; num; num--, p++) { 3148c2ecf20Sopenharmony_ci if (*p == id) 3158c2ecf20Sopenharmony_ci return true; 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return false; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_civoid intel_device_info_subplatform_init(struct drm_i915_private *i915) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci const struct intel_device_info *info = INTEL_INFO(i915); 3248c2ecf20Sopenharmony_ci const struct intel_runtime_info *rinfo = RUNTIME_INFO(i915); 3258c2ecf20Sopenharmony_ci const unsigned int pi = __platform_mask_index(rinfo, info->platform); 3268c2ecf20Sopenharmony_ci const unsigned int pb = __platform_mask_bit(rinfo, info->platform); 3278c2ecf20Sopenharmony_ci u16 devid = INTEL_DEVID(i915); 3288c2ecf20Sopenharmony_ci u32 mask = 0; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* Make sure IS_<platform> checks are working. */ 3318c2ecf20Sopenharmony_ci RUNTIME_INFO(i915)->platform_mask[pi] = BIT(pb); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* Find and mark subplatform bits based on the PCI device id. */ 3348c2ecf20Sopenharmony_ci if (find_devid(devid, subplatform_ult_ids, 3358c2ecf20Sopenharmony_ci ARRAY_SIZE(subplatform_ult_ids))) { 3368c2ecf20Sopenharmony_ci mask = BIT(INTEL_SUBPLATFORM_ULT); 3378c2ecf20Sopenharmony_ci } else if (find_devid(devid, subplatform_ulx_ids, 3388c2ecf20Sopenharmony_ci ARRAY_SIZE(subplatform_ulx_ids))) { 3398c2ecf20Sopenharmony_ci mask = BIT(INTEL_SUBPLATFORM_ULX); 3408c2ecf20Sopenharmony_ci if (IS_HASWELL(i915) || IS_BROADWELL(i915)) { 3418c2ecf20Sopenharmony_ci /* ULX machines are also considered ULT. */ 3428c2ecf20Sopenharmony_ci mask |= BIT(INTEL_SUBPLATFORM_ULT); 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci } else if (find_devid(devid, subplatform_portf_ids, 3458c2ecf20Sopenharmony_ci ARRAY_SIZE(subplatform_portf_ids))) { 3468c2ecf20Sopenharmony_ci mask = BIT(INTEL_SUBPLATFORM_PORTF); 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (IS_TIGERLAKE(i915)) { 3508c2ecf20Sopenharmony_ci struct pci_dev *root, *pdev = i915->drm.pdev; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci root = list_first_entry(&pdev->bus->devices, typeof(*root), bus_list); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci drm_WARN_ON(&i915->drm, mask); 3558c2ecf20Sopenharmony_ci drm_WARN_ON(&i915->drm, (root->device & TGL_ROOT_DEVICE_MASK) != 3568c2ecf20Sopenharmony_ci TGL_ROOT_DEVICE_ID); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci switch (root->device & TGL_ROOT_DEVICE_SKU_MASK) { 3598c2ecf20Sopenharmony_ci case TGL_ROOT_DEVICE_SKU_ULX: 3608c2ecf20Sopenharmony_ci mask = BIT(INTEL_SUBPLATFORM_ULX); 3618c2ecf20Sopenharmony_ci break; 3628c2ecf20Sopenharmony_ci case TGL_ROOT_DEVICE_SKU_ULT: 3638c2ecf20Sopenharmony_ci mask = BIT(INTEL_SUBPLATFORM_ULT); 3648c2ecf20Sopenharmony_ci break; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_BITS); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci RUNTIME_INFO(i915)->platform_mask[pi] |= mask; 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/** 3748c2ecf20Sopenharmony_ci * intel_device_info_runtime_init - initialize runtime info 3758c2ecf20Sopenharmony_ci * @dev_priv: the i915 device 3768c2ecf20Sopenharmony_ci * 3778c2ecf20Sopenharmony_ci * Determine various intel_device_info fields at runtime. 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Use it when either: 3808c2ecf20Sopenharmony_ci * - it's judged too laborious to fill n static structures with the limit 3818c2ecf20Sopenharmony_ci * when a simple if statement does the job, 3828c2ecf20Sopenharmony_ci * - run-time checks (eg read fuse/strap registers) are needed. 3838c2ecf20Sopenharmony_ci * 3848c2ecf20Sopenharmony_ci * This function needs to be called: 3858c2ecf20Sopenharmony_ci * - after the MMIO has been setup as we are reading registers, 3868c2ecf20Sopenharmony_ci * - after the PCH has been detected, 3878c2ecf20Sopenharmony_ci * - before the first usage of the fields it can tweak. 3888c2ecf20Sopenharmony_ci */ 3898c2ecf20Sopenharmony_civoid intel_device_info_runtime_init(struct drm_i915_private *dev_priv) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci struct intel_device_info *info = mkwrite_device_info(dev_priv); 3928c2ecf20Sopenharmony_ci struct intel_runtime_info *runtime = RUNTIME_INFO(dev_priv); 3938c2ecf20Sopenharmony_ci enum pipe pipe; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 10) { 3968c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 3978c2ecf20Sopenharmony_ci runtime->num_scalers[pipe] = 2; 3988c2ecf20Sopenharmony_ci } else if (IS_GEN(dev_priv, 9)) { 3998c2ecf20Sopenharmony_ci runtime->num_scalers[PIPE_A] = 2; 4008c2ecf20Sopenharmony_ci runtime->num_scalers[PIPE_B] = 2; 4018c2ecf20Sopenharmony_ci runtime->num_scalers[PIPE_C] = 1; 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci BUILD_BUG_ON(BITS_PER_TYPE(intel_engine_mask_t) < I915_NUM_ENGINES); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (IS_ROCKETLAKE(dev_priv)) 4078c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 4088c2ecf20Sopenharmony_ci runtime->num_sprites[pipe] = 4; 4098c2ecf20Sopenharmony_ci else if (INTEL_GEN(dev_priv) >= 11) 4108c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 4118c2ecf20Sopenharmony_ci runtime->num_sprites[pipe] = 6; 4128c2ecf20Sopenharmony_ci else if (IS_GEN(dev_priv, 10) || IS_GEMINILAKE(dev_priv)) 4138c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 4148c2ecf20Sopenharmony_ci runtime->num_sprites[pipe] = 3; 4158c2ecf20Sopenharmony_ci else if (IS_BROXTON(dev_priv)) { 4168c2ecf20Sopenharmony_ci /* 4178c2ecf20Sopenharmony_ci * Skylake and Broxton currently don't expose the topmost plane as its 4188c2ecf20Sopenharmony_ci * use is exclusive with the legacy cursor and we only want to expose 4198c2ecf20Sopenharmony_ci * one of those, not both. Until we can safely expose the topmost plane 4208c2ecf20Sopenharmony_ci * as a DRM_PLANE_TYPE_CURSOR with all the features exposed/supported, 4218c2ecf20Sopenharmony_ci * we don't expose the topmost plane at all to prevent ABI breakage 4228c2ecf20Sopenharmony_ci * down the line. 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci runtime->num_sprites[PIPE_A] = 2; 4268c2ecf20Sopenharmony_ci runtime->num_sprites[PIPE_B] = 2; 4278c2ecf20Sopenharmony_ci runtime->num_sprites[PIPE_C] = 1; 4288c2ecf20Sopenharmony_ci } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { 4298c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 4308c2ecf20Sopenharmony_ci runtime->num_sprites[pipe] = 2; 4318c2ecf20Sopenharmony_ci } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) { 4328c2ecf20Sopenharmony_ci for_each_pipe(dev_priv, pipe) 4338c2ecf20Sopenharmony_ci runtime->num_sprites[pipe] = 1; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (HAS_DISPLAY(dev_priv) && IS_GEN_RANGE(dev_priv, 7, 8) && 4378c2ecf20Sopenharmony_ci HAS_PCH_SPLIT(dev_priv)) { 4388c2ecf20Sopenharmony_ci u32 fuse_strap = intel_de_read(dev_priv, FUSE_STRAP); 4398c2ecf20Sopenharmony_ci u32 sfuse_strap = intel_de_read(dev_priv, SFUSE_STRAP); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci /* 4428c2ecf20Sopenharmony_ci * SFUSE_STRAP is supposed to have a bit signalling the display 4438c2ecf20Sopenharmony_ci * is fused off. Unfortunately it seems that, at least in 4448c2ecf20Sopenharmony_ci * certain cases, fused off display means that PCH display 4458c2ecf20Sopenharmony_ci * reads don't land anywhere. In that case, we read 0s. 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * On CPT/PPT, we can detect this case as SFUSE_STRAP_FUSE_LOCK 4488c2ecf20Sopenharmony_ci * should be set when taking over after the firmware. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci if (fuse_strap & ILK_INTERNAL_DISPLAY_DISABLE || 4518c2ecf20Sopenharmony_ci sfuse_strap & SFUSE_STRAP_DISPLAY_DISABLED || 4528c2ecf20Sopenharmony_ci (HAS_PCH_CPT(dev_priv) && 4538c2ecf20Sopenharmony_ci !(sfuse_strap & SFUSE_STRAP_FUSE_LOCK))) { 4548c2ecf20Sopenharmony_ci drm_info(&dev_priv->drm, 4558c2ecf20Sopenharmony_ci "Display fused off, disabling\n"); 4568c2ecf20Sopenharmony_ci info->pipe_mask = 0; 4578c2ecf20Sopenharmony_ci info->cpu_transcoder_mask = 0; 4588c2ecf20Sopenharmony_ci } else if (fuse_strap & IVB_PIPE_C_DISABLE) { 4598c2ecf20Sopenharmony_ci drm_info(&dev_priv->drm, "PipeC fused off\n"); 4608c2ecf20Sopenharmony_ci info->pipe_mask &= ~BIT(PIPE_C); 4618c2ecf20Sopenharmony_ci info->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci } else if (HAS_DISPLAY(dev_priv) && INTEL_GEN(dev_priv) >= 9) { 4648c2ecf20Sopenharmony_ci u32 dfsm = intel_de_read(dev_priv, SKL_DFSM); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci if (dfsm & SKL_DFSM_PIPE_A_DISABLE) { 4678c2ecf20Sopenharmony_ci info->pipe_mask &= ~BIT(PIPE_A); 4688c2ecf20Sopenharmony_ci info->cpu_transcoder_mask &= ~BIT(TRANSCODER_A); 4698c2ecf20Sopenharmony_ci } 4708c2ecf20Sopenharmony_ci if (dfsm & SKL_DFSM_PIPE_B_DISABLE) { 4718c2ecf20Sopenharmony_ci info->pipe_mask &= ~BIT(PIPE_B); 4728c2ecf20Sopenharmony_ci info->cpu_transcoder_mask &= ~BIT(TRANSCODER_B); 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci if (dfsm & SKL_DFSM_PIPE_C_DISABLE) { 4758c2ecf20Sopenharmony_ci info->pipe_mask &= ~BIT(PIPE_C); 4768c2ecf20Sopenharmony_ci info->cpu_transcoder_mask &= ~BIT(TRANSCODER_C); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 12 && 4798c2ecf20Sopenharmony_ci (dfsm & TGL_DFSM_PIPE_D_DISABLE)) { 4808c2ecf20Sopenharmony_ci info->pipe_mask &= ~BIT(PIPE_D); 4818c2ecf20Sopenharmony_ci info->cpu_transcoder_mask &= ~BIT(TRANSCODER_D); 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (dfsm & SKL_DFSM_DISPLAY_HDCP_DISABLE) 4858c2ecf20Sopenharmony_ci info->display.has_hdcp = 0; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (dfsm & SKL_DFSM_DISPLAY_PM_DISABLE) 4888c2ecf20Sopenharmony_ci info->display.has_fbc = 0; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE)) 4918c2ecf20Sopenharmony_ci info->display.has_csr = 0; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci if (INTEL_GEN(dev_priv) >= 10 && 4948c2ecf20Sopenharmony_ci (dfsm & CNL_DFSM_DISPLAY_DSC_DISABLE)) 4958c2ecf20Sopenharmony_ci info->display.has_dsc = 0; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (IS_GEN(dev_priv, 6) && intel_vtd_active()) { 4998c2ecf20Sopenharmony_ci drm_info(&dev_priv->drm, 5008c2ecf20Sopenharmony_ci "Disabling ppGTT for VT-d support\n"); 5018c2ecf20Sopenharmony_ci info->ppgtt_type = INTEL_PPGTT_NONE; 5028c2ecf20Sopenharmony_ci } 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci runtime->rawclk_freq = intel_read_rawclk(dev_priv); 5058c2ecf20Sopenharmony_ci drm_dbg(&dev_priv->drm, "rawclk rate: %d kHz\n", runtime->rawclk_freq); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci /* Initialize command stream timestamp frequency */ 5088c2ecf20Sopenharmony_ci runtime->cs_timestamp_frequency_hz = 5098c2ecf20Sopenharmony_ci read_timestamp_frequency(dev_priv); 5108c2ecf20Sopenharmony_ci if (runtime->cs_timestamp_frequency_hz) { 5118c2ecf20Sopenharmony_ci runtime->cs_timestamp_period_ns = 5128c2ecf20Sopenharmony_ci i915_cs_timestamp_ticks_to_ns(dev_priv, 1); 5138c2ecf20Sopenharmony_ci drm_dbg(&dev_priv->drm, 5148c2ecf20Sopenharmony_ci "CS timestamp wraparound in %lldms\n", 5158c2ecf20Sopenharmony_ci div_u64(mul_u32_u32(runtime->cs_timestamp_period_ns, 5168c2ecf20Sopenharmony_ci S32_MAX), 5178c2ecf20Sopenharmony_ci USEC_PER_SEC)); 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (!HAS_DISPLAY(dev_priv)) { 5218c2ecf20Sopenharmony_ci dev_priv->drm.driver_features &= ~(DRIVER_MODESET | 5228c2ecf20Sopenharmony_ci DRIVER_ATOMIC); 5238c2ecf20Sopenharmony_ci memset(&info->display, 0, sizeof(info->display)); 5248c2ecf20Sopenharmony_ci memset(runtime->num_sprites, 0, sizeof(runtime->num_sprites)); 5258c2ecf20Sopenharmony_ci memset(runtime->num_scalers, 0, sizeof(runtime->num_scalers)); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_civoid intel_driver_caps_print(const struct intel_driver_caps *caps, 5308c2ecf20Sopenharmony_ci struct drm_printer *p) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci drm_printf(p, "Has logical contexts? %s\n", 5338c2ecf20Sopenharmony_ci yesno(caps->has_logical_contexts)); 5348c2ecf20Sopenharmony_ci drm_printf(p, "scheduler: %x\n", caps->scheduler); 5358c2ecf20Sopenharmony_ci} 536