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