1 1.1 riastrad /* $NetBSD: intel_pch.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright 2019 Intel Corporation. 6 1.1 riastrad */ 7 1.1 riastrad 8 1.1 riastrad #include <sys/cdefs.h> 9 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: intel_pch.c,v 1.2 2021/12/18 23:45:28 riastradh Exp $"); 10 1.1 riastrad 11 1.1 riastrad #include "i915_drv.h" 12 1.1 riastrad #include "intel_pch.h" 13 1.1 riastrad 14 1.1 riastrad /* Map PCH device id to PCH type, or PCH_NONE if unknown. */ 15 1.1 riastrad static enum intel_pch 16 1.1 riastrad intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) 17 1.1 riastrad { 18 1.1 riastrad switch (id) { 19 1.1 riastrad case INTEL_PCH_IBX_DEVICE_ID_TYPE: 20 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n"); 21 1.1 riastrad WARN_ON(!IS_GEN(dev_priv, 5)); 22 1.1 riastrad return PCH_IBX; 23 1.1 riastrad case INTEL_PCH_CPT_DEVICE_ID_TYPE: 24 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n"); 25 1.1 riastrad WARN_ON(!IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv)); 26 1.1 riastrad return PCH_CPT; 27 1.1 riastrad case INTEL_PCH_PPT_DEVICE_ID_TYPE: 28 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n"); 29 1.1 riastrad WARN_ON(!IS_GEN(dev_priv, 6) && !IS_IVYBRIDGE(dev_priv)); 30 1.1 riastrad /* PantherPoint is CPT compatible */ 31 1.1 riastrad return PCH_CPT; 32 1.1 riastrad case INTEL_PCH_LPT_DEVICE_ID_TYPE: 33 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n"); 34 1.1 riastrad WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 35 1.1 riastrad WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); 36 1.1 riastrad return PCH_LPT; 37 1.1 riastrad case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE: 38 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n"); 39 1.1 riastrad WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 40 1.1 riastrad WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); 41 1.1 riastrad return PCH_LPT; 42 1.1 riastrad case INTEL_PCH_WPT_DEVICE_ID_TYPE: 43 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n"); 44 1.1 riastrad WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 45 1.1 riastrad WARN_ON(IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)); 46 1.1 riastrad /* WildcatPoint is LPT compatible */ 47 1.1 riastrad return PCH_LPT; 48 1.1 riastrad case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE: 49 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n"); 50 1.1 riastrad WARN_ON(!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)); 51 1.1 riastrad WARN_ON(!IS_HSW_ULT(dev_priv) && !IS_BDW_ULT(dev_priv)); 52 1.1 riastrad /* WildcatPoint is LPT compatible */ 53 1.1 riastrad return PCH_LPT; 54 1.1 riastrad case INTEL_PCH_SPT_DEVICE_ID_TYPE: 55 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n"); 56 1.1 riastrad WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)); 57 1.1 riastrad return PCH_SPT; 58 1.1 riastrad case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE: 59 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n"); 60 1.1 riastrad WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv) && 61 1.1 riastrad !IS_COFFEELAKE(dev_priv)); 62 1.1 riastrad return PCH_SPT; 63 1.1 riastrad case INTEL_PCH_KBP_DEVICE_ID_TYPE: 64 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n"); 65 1.1 riastrad WARN_ON(!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv) && 66 1.1 riastrad !IS_COFFEELAKE(dev_priv)); 67 1.1 riastrad /* KBP is SPT compatible */ 68 1.1 riastrad return PCH_SPT; 69 1.1 riastrad case INTEL_PCH_CNP_DEVICE_ID_TYPE: 70 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n"); 71 1.1 riastrad WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); 72 1.1 riastrad return PCH_CNP; 73 1.1 riastrad case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE: 74 1.1 riastrad drm_dbg_kms(&dev_priv->drm, 75 1.1 riastrad "Found Cannon Lake LP PCH (CNP-LP)\n"); 76 1.1 riastrad WARN_ON(!IS_CANNONLAKE(dev_priv) && !IS_COFFEELAKE(dev_priv)); 77 1.1 riastrad return PCH_CNP; 78 1.1 riastrad case INTEL_PCH_CMP_DEVICE_ID_TYPE: 79 1.1 riastrad case INTEL_PCH_CMP2_DEVICE_ID_TYPE: 80 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n"); 81 1.1 riastrad WARN_ON(!IS_COFFEELAKE(dev_priv)); 82 1.1 riastrad /* CometPoint is CNP Compatible */ 83 1.1 riastrad return PCH_CNP; 84 1.1 riastrad case INTEL_PCH_CMP_V_DEVICE_ID_TYPE: 85 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n"); 86 1.1 riastrad WARN_ON(!IS_COFFEELAKE(dev_priv)); 87 1.1 riastrad /* Comet Lake V PCH is based on KBP, which is SPT compatible */ 88 1.1 riastrad return PCH_SPT; 89 1.1 riastrad case INTEL_PCH_ICP_DEVICE_ID_TYPE: 90 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); 91 1.1 riastrad WARN_ON(!IS_ICELAKE(dev_priv)); 92 1.1 riastrad return PCH_ICP; 93 1.1 riastrad case INTEL_PCH_MCC_DEVICE_ID_TYPE: 94 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n"); 95 1.1 riastrad WARN_ON(!IS_ELKHARTLAKE(dev_priv)); 96 1.1 riastrad return PCH_MCC; 97 1.1 riastrad case INTEL_PCH_TGP_DEVICE_ID_TYPE: 98 1.1 riastrad case INTEL_PCH_TGP2_DEVICE_ID_TYPE: 99 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n"); 100 1.1 riastrad WARN_ON(!IS_TIGERLAKE(dev_priv)); 101 1.1 riastrad return PCH_TGP; 102 1.1 riastrad case INTEL_PCH_JSP_DEVICE_ID_TYPE: 103 1.1 riastrad case INTEL_PCH_JSP2_DEVICE_ID_TYPE: 104 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); 105 1.1 riastrad WARN_ON(!IS_ELKHARTLAKE(dev_priv)); 106 1.1 riastrad return PCH_JSP; 107 1.1 riastrad default: 108 1.1 riastrad return PCH_NONE; 109 1.1 riastrad } 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad static bool intel_is_virt_pch(unsigned short id, 113 1.1 riastrad unsigned short svendor, unsigned short sdevice) 114 1.1 riastrad { 115 1.1 riastrad return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE || 116 1.1 riastrad id == INTEL_PCH_P3X_DEVICE_ID_TYPE || 117 1.1 riastrad (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE && 118 1.1 riastrad svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET && 119 1.1 riastrad sdevice == PCI_SUBDEVICE_ID_QEMU)); 120 1.1 riastrad } 121 1.1 riastrad 122 1.1 riastrad static unsigned short 123 1.1 riastrad intel_virt_detect_pch(const struct drm_i915_private *dev_priv) 124 1.1 riastrad { 125 1.1 riastrad unsigned short id = 0; 126 1.1 riastrad 127 1.1 riastrad /* 128 1.1 riastrad * In a virtualized passthrough environment we can be in a 129 1.1 riastrad * setup where the ISA bridge is not able to be passed through. 130 1.1 riastrad * In this case, a south bridge can be emulated and we have to 131 1.1 riastrad * make an educated guess as to which PCH is really there. 132 1.1 riastrad */ 133 1.1 riastrad 134 1.1 riastrad if (IS_TIGERLAKE(dev_priv)) 135 1.1 riastrad id = INTEL_PCH_TGP_DEVICE_ID_TYPE; 136 1.1 riastrad else if (IS_ELKHARTLAKE(dev_priv)) 137 1.1 riastrad id = INTEL_PCH_MCC_DEVICE_ID_TYPE; 138 1.1 riastrad else if (IS_ICELAKE(dev_priv)) 139 1.1 riastrad id = INTEL_PCH_ICP_DEVICE_ID_TYPE; 140 1.1 riastrad else if (IS_CANNONLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) 141 1.1 riastrad id = INTEL_PCH_CNP_DEVICE_ID_TYPE; 142 1.1 riastrad else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv)) 143 1.1 riastrad id = INTEL_PCH_SPT_DEVICE_ID_TYPE; 144 1.1 riastrad else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) 145 1.1 riastrad id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; 146 1.1 riastrad else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) 147 1.1 riastrad id = INTEL_PCH_LPT_DEVICE_ID_TYPE; 148 1.1 riastrad else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) 149 1.1 riastrad id = INTEL_PCH_CPT_DEVICE_ID_TYPE; 150 1.1 riastrad else if (IS_GEN(dev_priv, 5)) 151 1.1 riastrad id = INTEL_PCH_IBX_DEVICE_ID_TYPE; 152 1.1 riastrad 153 1.1 riastrad if (id) 154 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id); 155 1.1 riastrad else 156 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n"); 157 1.1 riastrad 158 1.1 riastrad return id; 159 1.1 riastrad } 160 1.1 riastrad 161 1.1 riastrad void intel_detect_pch(struct drm_i915_private *dev_priv) 162 1.1 riastrad { 163 1.1 riastrad struct pci_dev *pch = NULL; 164 1.1 riastrad 165 1.1 riastrad /* 166 1.1 riastrad * The reason to probe ISA bridge instead of Dev31:Fun0 is to 167 1.1 riastrad * make graphics device passthrough work easy for VMM, that only 168 1.1 riastrad * need to expose ISA bridge to let driver know the real hardware 169 1.1 riastrad * underneath. This is a requirement from virtualization team. 170 1.1 riastrad * 171 1.1 riastrad * In some virtualized environments (e.g. XEN), there is irrelevant 172 1.1 riastrad * ISA bridge in the system. To work reliably, we should scan trhough 173 1.1 riastrad * all the ISA bridge devices and check for the first match, instead 174 1.1 riastrad * of only checking the first one. 175 1.1 riastrad */ 176 1.1 riastrad while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) { 177 1.1 riastrad unsigned short id; 178 1.1 riastrad enum intel_pch pch_type; 179 1.1 riastrad 180 1.1 riastrad if (pch->vendor != PCI_VENDOR_ID_INTEL) 181 1.1 riastrad continue; 182 1.1 riastrad 183 1.1 riastrad id = pch->device & INTEL_PCH_DEVICE_ID_MASK; 184 1.1 riastrad 185 1.1 riastrad pch_type = intel_pch_type(dev_priv, id); 186 1.1 riastrad if (pch_type != PCH_NONE) { 187 1.1 riastrad dev_priv->pch_type = pch_type; 188 1.1 riastrad dev_priv->pch_id = id; 189 1.1 riastrad break; 190 1.1 riastrad } else if (intel_is_virt_pch(id, pch->subsystem_vendor, 191 1.1 riastrad pch->subsystem_device)) { 192 1.1 riastrad id = intel_virt_detect_pch(dev_priv); 193 1.1 riastrad pch_type = intel_pch_type(dev_priv, id); 194 1.1 riastrad 195 1.1 riastrad /* Sanity check virtual PCH id */ 196 1.1 riastrad if (WARN_ON(id && pch_type == PCH_NONE)) 197 1.1 riastrad id = 0; 198 1.1 riastrad 199 1.1 riastrad dev_priv->pch_type = pch_type; 200 1.1 riastrad dev_priv->pch_id = id; 201 1.1 riastrad break; 202 1.1 riastrad } 203 1.1 riastrad } 204 1.1 riastrad 205 1.1 riastrad /* 206 1.1 riastrad * Use PCH_NOP (PCH but no South Display) for PCH platforms without 207 1.1 riastrad * display. 208 1.1 riastrad */ 209 1.1 riastrad if (pch && !HAS_DISPLAY(dev_priv)) { 210 1.1 riastrad drm_dbg_kms(&dev_priv->drm, 211 1.1 riastrad "Display disabled, reverting to NOP PCH\n"); 212 1.1 riastrad dev_priv->pch_type = PCH_NOP; 213 1.1 riastrad dev_priv->pch_id = 0; 214 1.1 riastrad } 215 1.1 riastrad 216 1.1 riastrad if (!pch) 217 1.1 riastrad drm_dbg_kms(&dev_priv->drm, "No PCH found.\n"); 218 1.1 riastrad 219 1.1 riastrad pci_dev_put(pch); 220 1.1 riastrad } 221