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