288 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright 2019 Intel Corporation.4 */5 6#include "i915_drv.h"7#include "i915_utils.h"8#include "intel_pch.h"9 10/* Map PCH device id to PCH type, or PCH_NONE if unknown. */11static enum intel_pch12intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)13{14 switch (id) {15 case INTEL_PCH_IBX_DEVICE_ID_TYPE:16 drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n");17 drm_WARN_ON(&dev_priv->drm, GRAPHICS_VER(dev_priv) != 5);18 return PCH_IBX;19 case INTEL_PCH_CPT_DEVICE_ID_TYPE:20 drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n");21 drm_WARN_ON(&dev_priv->drm,22 GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv));23 return PCH_CPT;24 case INTEL_PCH_PPT_DEVICE_ID_TYPE:25 drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n");26 drm_WARN_ON(&dev_priv->drm,27 GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv));28 /* PPT is CPT compatible */29 return PCH_CPT;30 case INTEL_PCH_LPT_DEVICE_ID_TYPE:31 drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n");32 drm_WARN_ON(&dev_priv->drm,33 !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));34 drm_WARN_ON(&dev_priv->drm,35 IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv));36 return PCH_LPT;37 case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE:38 drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n");39 drm_WARN_ON(&dev_priv->drm,40 !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));41 drm_WARN_ON(&dev_priv->drm,42 !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv));43 return PCH_LPT;44 case INTEL_PCH_WPT_DEVICE_ID_TYPE:45 drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n");46 drm_WARN_ON(&dev_priv->drm,47 !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));48 drm_WARN_ON(&dev_priv->drm,49 IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv));50 /* WPT is LPT compatible */51 return PCH_LPT;52 case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE:53 drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n");54 drm_WARN_ON(&dev_priv->drm,55 !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));56 drm_WARN_ON(&dev_priv->drm,57 !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv));58 /* WPT is LPT compatible */59 return PCH_LPT;60 case INTEL_PCH_SPT_DEVICE_ID_TYPE:61 drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n");62 drm_WARN_ON(&dev_priv->drm,63 !IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv));64 return PCH_SPT;65 case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE:66 drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n");67 drm_WARN_ON(&dev_priv->drm,68 !IS_SKYLAKE(dev_priv) &&69 !IS_KABYLAKE(dev_priv) &&70 !IS_COFFEELAKE(dev_priv) &&71 !IS_COMETLAKE(dev_priv));72 return PCH_SPT;73 case INTEL_PCH_KBP_DEVICE_ID_TYPE:74 drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n");75 drm_WARN_ON(&dev_priv->drm,76 !IS_SKYLAKE(dev_priv) &&77 !IS_KABYLAKE(dev_priv) &&78 !IS_COFFEELAKE(dev_priv) &&79 !IS_COMETLAKE(dev_priv));80 /* KBP is SPT compatible */81 return PCH_SPT;82 case INTEL_PCH_CNP_DEVICE_ID_TYPE:83 drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n");84 drm_WARN_ON(&dev_priv->drm,85 !IS_COFFEELAKE(dev_priv) &&86 !IS_COMETLAKE(dev_priv));87 return PCH_CNP;88 case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE:89 drm_dbg_kms(&dev_priv->drm,90 "Found Cannon Lake LP PCH (CNP-LP)\n");91 drm_WARN_ON(&dev_priv->drm,92 !IS_COFFEELAKE(dev_priv) &&93 !IS_COMETLAKE(dev_priv));94 return PCH_CNP;95 case INTEL_PCH_CMP_DEVICE_ID_TYPE:96 case INTEL_PCH_CMP2_DEVICE_ID_TYPE:97 drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n");98 drm_WARN_ON(&dev_priv->drm,99 !IS_COFFEELAKE(dev_priv) &&100 !IS_COMETLAKE(dev_priv) &&101 !IS_ROCKETLAKE(dev_priv));102 /* CMP is CNP compatible */103 return PCH_CNP;104 case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:105 drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n");106 drm_WARN_ON(&dev_priv->drm,107 !IS_COFFEELAKE(dev_priv) &&108 !IS_COMETLAKE(dev_priv));109 /* CMP-V is based on KBP, which is SPT compatible */110 return PCH_SPT;111 case INTEL_PCH_ICP_DEVICE_ID_TYPE:112 case INTEL_PCH_ICP2_DEVICE_ID_TYPE:113 drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n");114 drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));115 return PCH_ICP;116 case INTEL_PCH_MCC_DEVICE_ID_TYPE:117 drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n");118 drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) ||119 IS_ELKHARTLAKE(dev_priv)));120 /* MCC is TGP compatible */121 return PCH_TGP;122 case INTEL_PCH_TGP_DEVICE_ID_TYPE:123 case INTEL_PCH_TGP2_DEVICE_ID_TYPE:124 drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n");125 drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) &&126 !IS_ROCKETLAKE(dev_priv) &&127 !IS_GEN9_BC(dev_priv));128 return PCH_TGP;129 case INTEL_PCH_JSP_DEVICE_ID_TYPE:130 drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n");131 drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) ||132 IS_ELKHARTLAKE(dev_priv)));133 /* JSP is ICP compatible */134 return PCH_ICP;135 case INTEL_PCH_ADP_DEVICE_ID_TYPE:136 case INTEL_PCH_ADP2_DEVICE_ID_TYPE:137 case INTEL_PCH_ADP3_DEVICE_ID_TYPE:138 case INTEL_PCH_ADP4_DEVICE_ID_TYPE:139 drm_dbg_kms(&dev_priv->drm, "Found Alder Lake PCH\n");140 drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) &&141 !IS_ALDERLAKE_P(dev_priv));142 return PCH_ADP;143 default:144 return PCH_NONE;145 }146}147 148static bool intel_is_virt_pch(unsigned short id,149 unsigned short svendor, unsigned short sdevice)150{151 return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE ||152 id == INTEL_PCH_P3X_DEVICE_ID_TYPE ||153 (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE &&154 svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&155 sdevice == PCI_SUBDEVICE_ID_QEMU));156}157 158static void159intel_virt_detect_pch(const struct drm_i915_private *dev_priv,160 unsigned short *pch_id, enum intel_pch *pch_type)161{162 unsigned short id = 0;163 164 /*165 * In a virtualized passthrough environment we can be in a166 * setup where the ISA bridge is not able to be passed through.167 * In this case, a south bridge can be emulated and we have to168 * make an educated guess as to which PCH is really there.169 */170 171 if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))172 id = INTEL_PCH_ADP_DEVICE_ID_TYPE;173 else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv))174 id = INTEL_PCH_TGP_DEVICE_ID_TYPE;175 else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv))176 id = INTEL_PCH_MCC_DEVICE_ID_TYPE;177 else if (IS_ICELAKE(dev_priv))178 id = INTEL_PCH_ICP_DEVICE_ID_TYPE;179 else if (IS_COFFEELAKE(dev_priv) ||180 IS_COMETLAKE(dev_priv))181 id = INTEL_PCH_CNP_DEVICE_ID_TYPE;182 else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv))183 id = INTEL_PCH_SPT_DEVICE_ID_TYPE;184 else if (IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv))185 id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;186 else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))187 id = INTEL_PCH_LPT_DEVICE_ID_TYPE;188 else if (GRAPHICS_VER(dev_priv) == 6 || IS_IVYBRIDGE(dev_priv))189 id = INTEL_PCH_CPT_DEVICE_ID_TYPE;190 else if (GRAPHICS_VER(dev_priv) == 5)191 id = INTEL_PCH_IBX_DEVICE_ID_TYPE;192 193 if (id)194 drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id);195 else196 drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n");197 198 *pch_type = intel_pch_type(dev_priv, id);199 200 /* Sanity check virtual PCH id */201 if (drm_WARN_ON(&dev_priv->drm,202 id && *pch_type == PCH_NONE))203 id = 0;204 205 *pch_id = id;206}207 208void intel_detect_pch(struct drm_i915_private *dev_priv)209{210 struct pci_dev *pch = NULL;211 unsigned short id;212 enum intel_pch pch_type;213 214 /*215 * South display engine on the same PCI device: just assign the fake216 * PCH.217 */218 if (DISPLAY_VER(dev_priv) >= 20) {219 dev_priv->pch_type = PCH_LNL;220 return;221 } else if (IS_BATTLEMAGE(dev_priv) || IS_METEORLAKE(dev_priv)) {222 /*223 * Both north display and south display are on the SoC die.224 * The real PCH (if it even exists) is uninvolved in display.225 */226 dev_priv->pch_type = PCH_MTL;227 return;228 } else if (IS_DG2(dev_priv)) {229 dev_priv->pch_type = PCH_DG2;230 return;231 } else if (IS_DG1(dev_priv)) {232 dev_priv->pch_type = PCH_DG1;233 return;234 }235 236 /*237 * The reason to probe ISA bridge instead of Dev31:Fun0 is to238 * make graphics device passthrough work easy for VMM, that only239 * need to expose ISA bridge to let driver know the real hardware240 * underneath. This is a requirement from virtualization team.241 *242 * In some virtualized environments (e.g. XEN), there is irrelevant243 * ISA bridge in the system. To work reliably, we should scan trhough244 * all the ISA bridge devices and check for the first match, instead245 * of only checking the first one.246 */247 while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {248 if (pch->vendor != PCI_VENDOR_ID_INTEL)249 continue;250 251 id = pch->device & INTEL_PCH_DEVICE_ID_MASK;252 253 pch_type = intel_pch_type(dev_priv, id);254 if (pch_type != PCH_NONE) {255 dev_priv->pch_type = pch_type;256 dev_priv->pch_id = id;257 break;258 } else if (intel_is_virt_pch(id, pch->subsystem_vendor,259 pch->subsystem_device)) {260 intel_virt_detect_pch(dev_priv, &id, &pch_type);261 dev_priv->pch_type = pch_type;262 dev_priv->pch_id = id;263 break;264 }265 }266 267 /*268 * Use PCH_NOP (PCH but no South Display) for PCH platforms without269 * display.270 */271 if (pch && !HAS_DISPLAY(dev_priv)) {272 drm_dbg_kms(&dev_priv->drm,273 "Display disabled, reverting to NOP PCH\n");274 dev_priv->pch_type = PCH_NOP;275 dev_priv->pch_id = 0;276 } else if (!pch) {277 if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) {278 intel_virt_detect_pch(dev_priv, &id, &pch_type);279 dev_priv->pch_type = pch_type;280 dev_priv->pch_id = id;281 } else {282 drm_dbg_kms(&dev_priv->drm, "No PCH found.\n");283 }284 }285 286 pci_dev_put(pch);287}288