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