18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: MIT 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2019 Intel Corporation. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "i915_drv.h" 78c2ecf20Sopenharmony_ci#include "intel_pch.h" 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* Map PCH device id to PCH type, or PCH_NONE if unknown. */ 108c2ecf20Sopenharmony_cistatic enum intel_pch 118c2ecf20Sopenharmony_ciintel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci switch (id) { 148c2ecf20Sopenharmony_ci case INTEL_PCH_IBX_DEVICE_ID_TYPE: 158c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n"); 168c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, !IS_GEN(dev_priv, 5)); 178c2ecf20Sopenharmony_ci return PCH_IBX; 188c2ecf20Sopenharmony_ci case INTEL_PCH_CPT_DEVICE_ID_TYPE: 198c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n"); 208c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 218c2ecf20Sopenharmony_ci !IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv)); 228c2ecf20Sopenharmony_ci return PCH_CPT; 238c2ecf20Sopenharmony_ci case INTEL_PCH_PPT_DEVICE_ID_TYPE: 248c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n"); 258c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 268c2ecf20Sopenharmony_ci !IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv)); 278c2ecf20Sopenharmony_ci /* PantherPoint is CPT compatible */ 288c2ecf20Sopenharmony_ci return PCH_CPT; 298c2ecf20Sopenharmony_ci case INTEL_PCH_LPT_DEVICE_ID_TYPE: 308c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n"); 318c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 328c2ecf20Sopenharmony_ci !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 338c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 348c2ecf20Sopenharmony_ci IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); 358c2ecf20Sopenharmony_ci return PCH_LPT; 368c2ecf20Sopenharmony_ci case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: 378c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n"); 388c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 398c2ecf20Sopenharmony_ci !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 408c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 418c2ecf20Sopenharmony_ci !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); 428c2ecf20Sopenharmony_ci return PCH_LPT; 438c2ecf20Sopenharmony_ci case INTEL_PCH_WPT_DEVICE_ID_TYPE: 448c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n"); 458c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 468c2ecf20Sopenharmony_ci !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 478c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 488c2ecf20Sopenharmony_ci IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); 498c2ecf20Sopenharmony_ci /* WildcatPoint is LPT compatible */ 508c2ecf20Sopenharmony_ci return PCH_LPT; 518c2ecf20Sopenharmony_ci case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: 528c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n"); 538c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 548c2ecf20Sopenharmony_ci !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 558c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 568c2ecf20Sopenharmony_ci !IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); 578c2ecf20Sopenharmony_ci /* WildcatPoint is LPT compatible */ 588c2ecf20Sopenharmony_ci return PCH_LPT; 598c2ecf20Sopenharmony_ci case INTEL_PCH_SPT_DEVICE_ID_TYPE: 608c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n"); 618c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 628c2ecf20Sopenharmony_ci !IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); 638c2ecf20Sopenharmony_ci return PCH_SPT; 648c2ecf20Sopenharmony_ci case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: 658c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n"); 668c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 678c2ecf20Sopenharmony_ci !IS_SKYLAKE(dev_priv) && 688c2ecf20Sopenharmony_ci !IS_KABYLAKE(dev_priv) && 698c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 708c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv)); 718c2ecf20Sopenharmony_ci return PCH_SPT; 728c2ecf20Sopenharmony_ci case INTEL_PCH_KBP_DEVICE_ID_TYPE: 738c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n"); 748c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 758c2ecf20Sopenharmony_ci !IS_SKYLAKE(dev_priv) && 768c2ecf20Sopenharmony_ci !IS_KABYLAKE(dev_priv) && 778c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 788c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv)); 798c2ecf20Sopenharmony_ci /* KBP is SPT compatible */ 808c2ecf20Sopenharmony_ci return PCH_SPT; 818c2ecf20Sopenharmony_ci case INTEL_PCH_CNP_DEVICE_ID_TYPE: 828c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n"); 838c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 848c2ecf20Sopenharmony_ci !IS_CANNONLAKE(dev_priv) && 858c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 868c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv)); 878c2ecf20Sopenharmony_ci return PCH_CNP; 888c2ecf20Sopenharmony_ci case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: 898c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, 908c2ecf20Sopenharmony_ci "Found Cannon Lake LP PCH (CNP-LP)\n"); 918c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 928c2ecf20Sopenharmony_ci !IS_CANNONLAKE(dev_priv) && 938c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 948c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv)); 958c2ecf20Sopenharmony_ci return PCH_CNP; 968c2ecf20Sopenharmony_ci case INTEL_PCH_CMP_DEVICE_ID_TYPE: 978c2ecf20Sopenharmony_ci case INTEL_PCH_CMP2_DEVICE_ID_TYPE: 988c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n"); 998c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 1008c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 1018c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv) && 1028c2ecf20Sopenharmony_ci !IS_ROCKETLAKE(dev_priv)); 1038c2ecf20Sopenharmony_ci /* CometPoint is CNP Compatible */ 1048c2ecf20Sopenharmony_ci return PCH_CNP; 1058c2ecf20Sopenharmony_ci case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: 1068c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n"); 1078c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, 1088c2ecf20Sopenharmony_ci !IS_COFFEELAKE(dev_priv) && 1098c2ecf20Sopenharmony_ci !IS_COMETLAKE(dev_priv)); 1108c2ecf20Sopenharmony_ci /* Comet Lake V PCH is based on KBP, which is SPT compatible */ 1118c2ecf20Sopenharmony_ci return PCH_SPT; 1128c2ecf20Sopenharmony_ci case INTEL_PCH_ICP_DEVICE_ID_TYPE: 1138c2ecf20Sopenharmony_ci case INTEL_PCH_ICP2_DEVICE_ID_TYPE: 1148c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); 1158c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); 1168c2ecf20Sopenharmony_ci return PCH_ICP; 1178c2ecf20Sopenharmony_ci case INTEL_PCH_MCC_DEVICE_ID_TYPE: 1188c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); 1198c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, !IS_ELKHARTLAKE(dev_priv)); 1208c2ecf20Sopenharmony_ci return PCH_MCC; 1218c2ecf20Sopenharmony_ci case INTEL_PCH_TGP_DEVICE_ID_TYPE: 1228c2ecf20Sopenharmony_ci case INTEL_PCH_TGP2_DEVICE_ID_TYPE: 1238c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n"); 1248c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) && 1258c2ecf20Sopenharmony_ci !IS_ROCKETLAKE(dev_priv)); 1268c2ecf20Sopenharmony_ci return PCH_TGP; 1278c2ecf20Sopenharmony_ci case INTEL_PCH_JSP_DEVICE_ID_TYPE: 1288c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); 1298c2ecf20Sopenharmony_ci drm_WARN_ON(&dev_priv->drm, !IS_ELKHARTLAKE(dev_priv)); 1308c2ecf20Sopenharmony_ci return PCH_JSP; 1318c2ecf20Sopenharmony_ci default: 1328c2ecf20Sopenharmony_ci return PCH_NONE; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic bool intel_is_virt_pch(unsigned short id, 1378c2ecf20Sopenharmony_ci unsigned short svendor, unsigned short sdevice) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || 1408c2ecf20Sopenharmony_ci id == INTEL_PCH_P3X_DEVICE_ID_TYPE || 1418c2ecf20Sopenharmony_ci (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && 1428c2ecf20Sopenharmony_ci svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && 1438c2ecf20Sopenharmony_ci sdevice == PCI_SUBDEVICE_ID_QEMU)); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic unsigned short 1478c2ecf20Sopenharmony_ciintel_virt_detect_pch(const struct drm_i915_private *dev_priv) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci unsigned short id = 0; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* 1528c2ecf20Sopenharmony_ci * In a virtualized passthrough environment we can be in a 1538c2ecf20Sopenharmony_ci * setup where the ISA bridge is not able to be passed through. 1548c2ecf20Sopenharmony_ci * In this case, a south bridge can be emulated and we have to 1558c2ecf20Sopenharmony_ci * make an educated guess as to which PCH is really there. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) 1598c2ecf20Sopenharmony_ci id = INTEL_PCH_TGP_DEVICE_ID_TYPE; 1608c2ecf20Sopenharmony_ci else if (IS_ELKHARTLAKE(dev_priv)) 1618c2ecf20Sopenharmony_ci id = INTEL_PCH_MCC_DEVICE_ID_TYPE; 1628c2ecf20Sopenharmony_ci else if (IS_ICELAKE(dev_priv)) 1638c2ecf20Sopenharmony_ci id = INTEL_PCH_ICP_DEVICE_ID_TYPE; 1648c2ecf20Sopenharmony_ci else if (IS_CANNONLAKE(dev_priv) || 1658c2ecf20Sopenharmony_ci IS_COFFEELAKE(dev_priv) || 1668c2ecf20Sopenharmony_ci IS_COMETLAKE(dev_priv)) 1678c2ecf20Sopenharmony_ci id = INTEL_PCH_CNP_DEVICE_ID_TYPE; 1688c2ecf20Sopenharmony_ci else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv)) 1698c2ecf20Sopenharmony_ci id = INTEL_PCH_SPT_DEVICE_ID_TYPE; 1708c2ecf20Sopenharmony_ci else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) 1718c2ecf20Sopenharmony_ci id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; 1728c2ecf20Sopenharmony_ci else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) 1738c2ecf20Sopenharmony_ci id = INTEL_PCH_LPT_DEVICE_ID_TYPE; 1748c2ecf20Sopenharmony_ci else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) 1758c2ecf20Sopenharmony_ci id = INTEL_PCH_CPT_DEVICE_ID_TYPE; 1768c2ecf20Sopenharmony_ci else if (IS_GEN(dev_priv, 5)) 1778c2ecf20Sopenharmony_ci id = INTEL_PCH_IBX_DEVICE_ID_TYPE; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (id) 1808c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id); 1818c2ecf20Sopenharmony_ci else 1828c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n"); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci return id; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_civoid intel_detect_pch(struct drm_i915_private *dev_priv) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci struct pci_dev *pch = NULL; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* DG1 has south engine display on the same PCI device */ 1928c2ecf20Sopenharmony_ci if (IS_DG1(dev_priv)) { 1938c2ecf20Sopenharmony_ci dev_priv->pch_type = PCH_DG1; 1948c2ecf20Sopenharmony_ci return; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * The reason to probe ISA bridge instead of Dev31:Fun0 is to 1998c2ecf20Sopenharmony_ci * make graphics device passthrough work easy for VMM, that only 2008c2ecf20Sopenharmony_ci * need to expose ISA bridge to let driver know the real hardware 2018c2ecf20Sopenharmony_ci * underneath. This is a requirement from virtualization team. 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * In some virtualized environments (e.g. XEN), there is irrelevant 2048c2ecf20Sopenharmony_ci * ISA bridge in the system. To work reliably, we should scan trhough 2058c2ecf20Sopenharmony_ci * all the ISA bridge devices and check for the first match, instead 2068c2ecf20Sopenharmony_ci * of only checking the first one. 2078c2ecf20Sopenharmony_ci */ 2088c2ecf20Sopenharmony_ci while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { 2098c2ecf20Sopenharmony_ci unsigned short id; 2108c2ecf20Sopenharmony_ci enum intel_pch pch_type; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (pch->vendor != PCI_VENDOR_ID_INTEL) 2138c2ecf20Sopenharmony_ci continue; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci id = pch->device & INTEL_PCH_DEVICE_ID_MASK; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci pch_type = intel_pch_type(dev_priv, id); 2188c2ecf20Sopenharmony_ci if (pch_type != PCH_NONE) { 2198c2ecf20Sopenharmony_ci dev_priv->pch_type = pch_type; 2208c2ecf20Sopenharmony_ci dev_priv->pch_id = id; 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci } else if (intel_is_virt_pch(id, pch->subsystem_vendor, 2238c2ecf20Sopenharmony_ci pch->subsystem_device)) { 2248c2ecf20Sopenharmony_ci id = intel_virt_detect_pch(dev_priv); 2258c2ecf20Sopenharmony_ci pch_type = intel_pch_type(dev_priv, id); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Sanity check virtual PCH id */ 2288c2ecf20Sopenharmony_ci if (drm_WARN_ON(&dev_priv->drm, 2298c2ecf20Sopenharmony_ci id && pch_type == PCH_NONE)) 2308c2ecf20Sopenharmony_ci id = 0; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci dev_priv->pch_type = pch_type; 2338c2ecf20Sopenharmony_ci dev_priv->pch_id = id; 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* 2398c2ecf20Sopenharmony_ci * Use PCH_NOP (PCH but no South Display) for PCH platforms without 2408c2ecf20Sopenharmony_ci * display. 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci if (pch && !HAS_DISPLAY(dev_priv)) { 2438c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, 2448c2ecf20Sopenharmony_ci "Display disabled, reverting to NOP PCH\n"); 2458c2ecf20Sopenharmony_ci dev_priv->pch_type = PCH_NOP; 2468c2ecf20Sopenharmony_ci dev_priv->pch_id = 0; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (!pch) 2508c2ecf20Sopenharmony_ci drm_dbg_kms(&dev_priv->drm, "No PCH found.\n"); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci pci_dev_put(pch); 2538c2ecf20Sopenharmony_ci} 254