xref: /linux/drivers/gpu/drm/i915/display/intel_pch.c (revision b08494a8f7416e5f09907318c5460ad6f6e2a548)
16ca37b86SRodrigo Vivi // SPDX-License-Identifier: MIT
26ca37b86SRodrigo Vivi /*
36ca37b86SRodrigo Vivi  * Copyright 2025 Intel Corporation.
46ca37b86SRodrigo Vivi  */
56ca37b86SRodrigo Vivi 
66a5cfab0SJani Nikula #include <drm/drm_print.h>
76a5cfab0SJani Nikula 
86ca37b86SRodrigo Vivi #include "i915_utils.h"
96a5cfab0SJani Nikula #include "intel_display_core.h"
106ca37b86SRodrigo Vivi #include "intel_pch.h"
116ca37b86SRodrigo Vivi 
126ca37b86SRodrigo Vivi #define INTEL_PCH_DEVICE_ID_MASK		0xff80
136ca37b86SRodrigo Vivi #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
146ca37b86SRodrigo Vivi #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
156ca37b86SRodrigo Vivi #define INTEL_PCH_PPT_DEVICE_ID_TYPE		0x1e00
166ca37b86SRodrigo Vivi #define INTEL_PCH_LPT_DEVICE_ID_TYPE		0x8c00
176ca37b86SRodrigo Vivi #define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE		0x9c00
186ca37b86SRodrigo Vivi #define INTEL_PCH_WPT_DEVICE_ID_TYPE		0x8c80
196ca37b86SRodrigo Vivi #define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE		0x9c80
206ca37b86SRodrigo Vivi #define INTEL_PCH_SPT_DEVICE_ID_TYPE		0xA100
216ca37b86SRodrigo Vivi #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE		0x9D00
226ca37b86SRodrigo Vivi #define INTEL_PCH_KBP_DEVICE_ID_TYPE		0xA280
236ca37b86SRodrigo Vivi #define INTEL_PCH_CNP_DEVICE_ID_TYPE		0xA300
246ca37b86SRodrigo Vivi #define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE		0x9D80
256ca37b86SRodrigo Vivi #define INTEL_PCH_CMP_DEVICE_ID_TYPE		0x0280
266ca37b86SRodrigo Vivi #define INTEL_PCH_CMP2_DEVICE_ID_TYPE		0x0680
276ca37b86SRodrigo Vivi #define INTEL_PCH_CMP_V_DEVICE_ID_TYPE		0xA380
286ca37b86SRodrigo Vivi #define INTEL_PCH_ICP_DEVICE_ID_TYPE		0x3480
296ca37b86SRodrigo Vivi #define INTEL_PCH_ICP2_DEVICE_ID_TYPE		0x3880
306ca37b86SRodrigo Vivi #define INTEL_PCH_MCC_DEVICE_ID_TYPE		0x4B00
316ca37b86SRodrigo Vivi #define INTEL_PCH_TGP_DEVICE_ID_TYPE		0xA080
326ca37b86SRodrigo Vivi #define INTEL_PCH_TGP2_DEVICE_ID_TYPE		0x4380
336ca37b86SRodrigo Vivi #define INTEL_PCH_JSP_DEVICE_ID_TYPE		0x4D80
346ca37b86SRodrigo Vivi #define INTEL_PCH_ADP_DEVICE_ID_TYPE		0x7A80
356ca37b86SRodrigo Vivi #define INTEL_PCH_ADP2_DEVICE_ID_TYPE		0x5180
366ca37b86SRodrigo Vivi #define INTEL_PCH_ADP3_DEVICE_ID_TYPE		0x7A00
376ca37b86SRodrigo Vivi #define INTEL_PCH_ADP4_DEVICE_ID_TYPE		0x5480
386ca37b86SRodrigo Vivi #define INTEL_PCH_P2X_DEVICE_ID_TYPE		0x7100
396ca37b86SRodrigo Vivi #define INTEL_PCH_P3X_DEVICE_ID_TYPE		0x7000
406ca37b86SRodrigo Vivi #define INTEL_PCH_QEMU_DEVICE_ID_TYPE		0x2900 /* qemu q35 has 2918 */
416ca37b86SRodrigo Vivi 
42246b259fSJani Nikula /*
43246b259fSJani Nikula  * Check for platforms where the south display is on the same PCI device or SoC
44246b259fSJani Nikula  * die as the north display. The PCH (if it even exists) is not involved in
45246b259fSJani Nikula  * display. Return a fake PCH type for south display handling on these
46246b259fSJani Nikula  * platforms, without actually detecting the PCH, and PCH_NONE otherwise.
47246b259fSJani Nikula  */
48246b259fSJani Nikula static enum intel_pch intel_pch_fake_for_south_display(struct intel_display *display)
49246b259fSJani Nikula {
50246b259fSJani Nikula 	enum intel_pch pch_type = PCH_NONE;
51246b259fSJani Nikula 
52246b259fSJani Nikula 	if (DISPLAY_VER(display) >= 20)
53246b259fSJani Nikula 		pch_type = PCH_LNL;
54246b259fSJani Nikula 	else if (display->platform.battlemage || display->platform.meteorlake)
55246b259fSJani Nikula 		pch_type = PCH_MTL;
56246b259fSJani Nikula 	else if (display->platform.dg2)
57246b259fSJani Nikula 		pch_type = PCH_DG2;
58246b259fSJani Nikula 	else if (display->platform.dg1)
59246b259fSJani Nikula 		pch_type = PCH_DG1;
60246b259fSJani Nikula 
61246b259fSJani Nikula 	return pch_type;
62246b259fSJani Nikula }
63246b259fSJani Nikula 
646ca37b86SRodrigo Vivi /* Map PCH device id to PCH type, or PCH_NONE if unknown. */
656ca37b86SRodrigo Vivi static enum intel_pch
66ad283764SRodrigo Vivi intel_pch_type(const struct intel_display *display, unsigned short id)
676ca37b86SRodrigo Vivi {
686ca37b86SRodrigo Vivi 	switch (id) {
696ca37b86SRodrigo Vivi 	case INTEL_PCH_IBX_DEVICE_ID_TYPE:
70ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Ibex Peak PCH\n");
71ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, DISPLAY_VER(display) != 5);
726ca37b86SRodrigo Vivi 		return PCH_IBX;
736ca37b86SRodrigo Vivi 	case INTEL_PCH_CPT_DEVICE_ID_TYPE:
74ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found CougarPoint PCH\n");
75ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
76ad283764SRodrigo Vivi 			    DISPLAY_VER(display) != 6 &&
77ad283764SRodrigo Vivi 			    !display->platform.ivybridge);
786ca37b86SRodrigo Vivi 		return PCH_CPT;
796ca37b86SRodrigo Vivi 	case INTEL_PCH_PPT_DEVICE_ID_TYPE:
80ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found PantherPoint PCH\n");
81ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
82ad283764SRodrigo Vivi 			    DISPLAY_VER(display) != 6 &&
83ad283764SRodrigo Vivi 			    !display->platform.ivybridge);
846ca37b86SRodrigo Vivi 		/* PPT is CPT compatible */
856ca37b86SRodrigo Vivi 		return PCH_CPT;
866ca37b86SRodrigo Vivi 	case INTEL_PCH_LPT_DEVICE_ID_TYPE:
87ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found LynxPoint PCH\n");
88ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
89ad283764SRodrigo Vivi 			    !display->platform.haswell &&
90ad283764SRodrigo Vivi 			    !display->platform.broadwell);
91ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
92ad283764SRodrigo Vivi 			    display->platform.haswell_ult ||
93ad283764SRodrigo Vivi 			    display->platform.broadwell_ult);
946ca37b86SRodrigo Vivi 		return PCH_LPT_H;
956ca37b86SRodrigo Vivi 	case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE:
96ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found LynxPoint LP PCH\n");
97ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
98ad283764SRodrigo Vivi 			    !display->platform.haswell &&
99ad283764SRodrigo Vivi 			    !display->platform.broadwell);
100ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
101ad283764SRodrigo Vivi 			    !display->platform.haswell_ult &&
102ad283764SRodrigo Vivi 			    !display->platform.broadwell_ult);
1036ca37b86SRodrigo Vivi 		return PCH_LPT_LP;
1046ca37b86SRodrigo Vivi 	case INTEL_PCH_WPT_DEVICE_ID_TYPE:
105ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found WildcatPoint PCH\n");
106ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
107ad283764SRodrigo Vivi 			    !display->platform.haswell &&
108ad283764SRodrigo Vivi 			    !display->platform.broadwell);
109ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
110ad283764SRodrigo Vivi 			    display->platform.haswell_ult ||
111ad283764SRodrigo Vivi 			    display->platform.broadwell_ult);
1126ca37b86SRodrigo Vivi 		/* WPT is LPT compatible */
1136ca37b86SRodrigo Vivi 		return PCH_LPT_H;
1146ca37b86SRodrigo Vivi 	case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE:
115ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found WildcatPoint LP PCH\n");
116ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
117ad283764SRodrigo Vivi 			    !display->platform.haswell &&
118ad283764SRodrigo Vivi 			    !display->platform.broadwell);
119ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
120ad283764SRodrigo Vivi 			    !display->platform.haswell_ult &&
121ad283764SRodrigo Vivi 			    !display->platform.broadwell_ult);
1226ca37b86SRodrigo Vivi 		/* WPT is LPT compatible */
1236ca37b86SRodrigo Vivi 		return PCH_LPT_LP;
1246ca37b86SRodrigo Vivi 	case INTEL_PCH_SPT_DEVICE_ID_TYPE:
125ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found SunrisePoint PCH\n");
126ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
127ad283764SRodrigo Vivi 			    !display->platform.skylake &&
128*090a47b4SJiajia Liu 			    !display->platform.kabylake &&
129*090a47b4SJiajia Liu 			    !display->platform.coffeelake);
1306ca37b86SRodrigo Vivi 		return PCH_SPT;
1316ca37b86SRodrigo Vivi 	case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE:
132ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found SunrisePoint LP PCH\n");
133ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
134ad283764SRodrigo Vivi 			    !display->platform.skylake &&
135ad283764SRodrigo Vivi 			    !display->platform.kabylake &&
136ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
137ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1386ca37b86SRodrigo Vivi 		return PCH_SPT;
1396ca37b86SRodrigo Vivi 	case INTEL_PCH_KBP_DEVICE_ID_TYPE:
140ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Kaby Lake PCH (KBP)\n");
141ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
142ad283764SRodrigo Vivi 			    !display->platform.skylake &&
143ad283764SRodrigo Vivi 			    !display->platform.kabylake &&
144ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
145ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1466ca37b86SRodrigo Vivi 		/* KBP is SPT compatible */
1476ca37b86SRodrigo Vivi 		return PCH_SPT;
1486ca37b86SRodrigo Vivi 	case INTEL_PCH_CNP_DEVICE_ID_TYPE:
149ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Cannon Lake PCH (CNP)\n");
150ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
151ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
152ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1536ca37b86SRodrigo Vivi 		return PCH_CNP;
1546ca37b86SRodrigo Vivi 	case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE:
155ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm,
1566ca37b86SRodrigo Vivi 			    "Found Cannon Lake LP PCH (CNP-LP)\n");
157ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
158ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
159ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1606ca37b86SRodrigo Vivi 		return PCH_CNP;
1616ca37b86SRodrigo Vivi 	case INTEL_PCH_CMP_DEVICE_ID_TYPE:
1626ca37b86SRodrigo Vivi 	case INTEL_PCH_CMP2_DEVICE_ID_TYPE:
163ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Comet Lake PCH (CMP)\n");
164ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
165ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
166ad283764SRodrigo Vivi 			    !display->platform.cometlake &&
167ad283764SRodrigo Vivi 			    !display->platform.rocketlake);
1686ca37b86SRodrigo Vivi 		/* CMP is CNP compatible */
1696ca37b86SRodrigo Vivi 		return PCH_CNP;
1706ca37b86SRodrigo Vivi 	case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:
171ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Comet Lake V PCH (CMP-V)\n");
172ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm,
173ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
174ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1756ca37b86SRodrigo Vivi 		/* CMP-V is based on KBP, which is SPT compatible */
1766ca37b86SRodrigo Vivi 		return PCH_SPT;
1776ca37b86SRodrigo Vivi 	case INTEL_PCH_ICP_DEVICE_ID_TYPE:
1786ca37b86SRodrigo Vivi 	case INTEL_PCH_ICP2_DEVICE_ID_TYPE:
179ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Ice Lake PCH\n");
180ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, !display->platform.icelake);
1816ca37b86SRodrigo Vivi 		return PCH_ICP;
1826ca37b86SRodrigo Vivi 	case INTEL_PCH_MCC_DEVICE_ID_TYPE:
183ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Mule Creek Canyon PCH\n");
184ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, !(display->platform.jasperlake ||
185ad283764SRodrigo Vivi 					    display->platform.elkhartlake));
1866ca37b86SRodrigo Vivi 		/* MCC is TGP compatible */
1876ca37b86SRodrigo Vivi 		return PCH_TGP;
1886ca37b86SRodrigo Vivi 	case INTEL_PCH_TGP_DEVICE_ID_TYPE:
1896ca37b86SRodrigo Vivi 	case INTEL_PCH_TGP2_DEVICE_ID_TYPE:
190ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Tiger Lake LP PCH\n");
191ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, !display->platform.tigerlake &&
192ad283764SRodrigo Vivi 			    !display->platform.rocketlake &&
193ad283764SRodrigo Vivi 			    !display->platform.skylake &&
194ad283764SRodrigo Vivi 			    !display->platform.kabylake &&
195ad283764SRodrigo Vivi 			    !display->platform.coffeelake &&
196ad283764SRodrigo Vivi 			    !display->platform.cometlake);
1976ca37b86SRodrigo Vivi 		return PCH_TGP;
1986ca37b86SRodrigo Vivi 	case INTEL_PCH_JSP_DEVICE_ID_TYPE:
199ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Jasper Lake PCH\n");
200ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, !(display->platform.jasperlake ||
201ad283764SRodrigo Vivi 					    display->platform.elkhartlake));
2026ca37b86SRodrigo Vivi 		/* JSP is ICP compatible */
2036ca37b86SRodrigo Vivi 		return PCH_ICP;
2046ca37b86SRodrigo Vivi 	case INTEL_PCH_ADP_DEVICE_ID_TYPE:
2056ca37b86SRodrigo Vivi 	case INTEL_PCH_ADP2_DEVICE_ID_TYPE:
2066ca37b86SRodrigo Vivi 	case INTEL_PCH_ADP3_DEVICE_ID_TYPE:
2076ca37b86SRodrigo Vivi 	case INTEL_PCH_ADP4_DEVICE_ID_TYPE:
208ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Found Alder Lake PCH\n");
209ad283764SRodrigo Vivi 		drm_WARN_ON(display->drm, !display->platform.alderlake_s &&
210ad283764SRodrigo Vivi 			    !display->platform.alderlake_p);
2116ca37b86SRodrigo Vivi 		return PCH_ADP;
2126ca37b86SRodrigo Vivi 	default:
2136ca37b86SRodrigo Vivi 		return PCH_NONE;
2146ca37b86SRodrigo Vivi 	}
2156ca37b86SRodrigo Vivi }
2166ca37b86SRodrigo Vivi 
2176ca37b86SRodrigo Vivi static bool intel_is_virt_pch(unsigned short id,
2186ca37b86SRodrigo Vivi 			      unsigned short svendor, unsigned short sdevice)
2196ca37b86SRodrigo Vivi {
2206ca37b86SRodrigo Vivi 	return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE ||
2216ca37b86SRodrigo Vivi 		id == INTEL_PCH_P3X_DEVICE_ID_TYPE ||
2226ca37b86SRodrigo Vivi 		(id == INTEL_PCH_QEMU_DEVICE_ID_TYPE &&
2236ca37b86SRodrigo Vivi 		 svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
2246ca37b86SRodrigo Vivi 		 sdevice == PCI_SUBDEVICE_ID_QEMU));
2256ca37b86SRodrigo Vivi }
2266ca37b86SRodrigo Vivi 
2276ca37b86SRodrigo Vivi static void
228ad283764SRodrigo Vivi intel_virt_detect_pch(const struct intel_display *display,
2296ca37b86SRodrigo Vivi 		      unsigned short *pch_id, enum intel_pch *pch_type)
2306ca37b86SRodrigo Vivi {
2316ca37b86SRodrigo Vivi 	unsigned short id = 0;
2326ca37b86SRodrigo Vivi 
2336ca37b86SRodrigo Vivi 	/*
2346ca37b86SRodrigo Vivi 	 * In a virtualized passthrough environment we can be in a
2356ca37b86SRodrigo Vivi 	 * setup where the ISA bridge is not able to be passed through.
2366ca37b86SRodrigo Vivi 	 * In this case, a south bridge can be emulated and we have to
2376ca37b86SRodrigo Vivi 	 * make an educated guess as to which PCH is really there.
2386ca37b86SRodrigo Vivi 	 */
2396ca37b86SRodrigo Vivi 
240ad283764SRodrigo Vivi 	if (display->platform.alderlake_s || display->platform.alderlake_p)
2416ca37b86SRodrigo Vivi 		id = INTEL_PCH_ADP_DEVICE_ID_TYPE;
242ad283764SRodrigo Vivi 	else if (display->platform.tigerlake || display->platform.rocketlake)
2436ca37b86SRodrigo Vivi 		id = INTEL_PCH_TGP_DEVICE_ID_TYPE;
244ad283764SRodrigo Vivi 	else if (display->platform.jasperlake || display->platform.elkhartlake)
2456ca37b86SRodrigo Vivi 		id = INTEL_PCH_MCC_DEVICE_ID_TYPE;
246ad283764SRodrigo Vivi 	else if (display->platform.icelake)
2476ca37b86SRodrigo Vivi 		id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
248ad283764SRodrigo Vivi 	else if (display->platform.coffeelake ||
249ad283764SRodrigo Vivi 		 display->platform.cometlake)
2506ca37b86SRodrigo Vivi 		id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
251ad283764SRodrigo Vivi 	else if (display->platform.kabylake || display->platform.skylake)
2526ca37b86SRodrigo Vivi 		id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
253ad283764SRodrigo Vivi 	else if (display->platform.haswell_ult ||
254ad283764SRodrigo Vivi 		 display->platform.broadwell_ult)
2556ca37b86SRodrigo Vivi 		id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
256ad283764SRodrigo Vivi 	else if (display->platform.haswell || display->platform.broadwell)
2576ca37b86SRodrigo Vivi 		id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
258ad283764SRodrigo Vivi 	else if (DISPLAY_VER(display) == 6 || display->platform.ivybridge)
2596ca37b86SRodrigo Vivi 		id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
260ad283764SRodrigo Vivi 	else if (DISPLAY_VER(display) == 5)
2616ca37b86SRodrigo Vivi 		id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
2626ca37b86SRodrigo Vivi 
2636ca37b86SRodrigo Vivi 	if (id)
264ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Assuming PCH ID %04x\n", id);
2656ca37b86SRodrigo Vivi 	else
266ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm, "Assuming no PCH\n");
2676ca37b86SRodrigo Vivi 
268ad283764SRodrigo Vivi 	*pch_type = intel_pch_type(display, id);
2696ca37b86SRodrigo Vivi 
2706ca37b86SRodrigo Vivi 	/* Sanity check virtual PCH id */
271ad283764SRodrigo Vivi 	if (drm_WARN_ON(display->drm,
2726ca37b86SRodrigo Vivi 			id && *pch_type == PCH_NONE))
2736ca37b86SRodrigo Vivi 		id = 0;
2746ca37b86SRodrigo Vivi 
2756ca37b86SRodrigo Vivi 	*pch_id = id;
2766ca37b86SRodrigo Vivi }
2776ca37b86SRodrigo Vivi 
2783090ea03SJani Nikula void intel_pch_detect(struct intel_display *display)
2796ca37b86SRodrigo Vivi {
2806ca37b86SRodrigo Vivi 	struct pci_dev *pch = NULL;
2816ca37b86SRodrigo Vivi 	unsigned short id;
2826ca37b86SRodrigo Vivi 	enum intel_pch pch_type;
2836ca37b86SRodrigo Vivi 
284246b259fSJani Nikula 	pch_type = intel_pch_fake_for_south_display(display);
285246b259fSJani Nikula 	if (pch_type != PCH_NONE) {
286246b259fSJani Nikula 		display->pch_type = pch_type;
287246b259fSJani Nikula 		drm_dbg_kms(display->drm,
288246b259fSJani Nikula 			    "PCH not involved in display, using fake PCH type %d for south display\n",
289246b259fSJani Nikula 			    pch_type);
2906ca37b86SRodrigo Vivi 		return;
2916ca37b86SRodrigo Vivi 	}
2926ca37b86SRodrigo Vivi 
2936ca37b86SRodrigo Vivi 	/*
2946ca37b86SRodrigo Vivi 	 * The reason to probe ISA bridge instead of Dev31:Fun0 is to
2956ca37b86SRodrigo Vivi 	 * make graphics device passthrough work easy for VMM, that only
2966ca37b86SRodrigo Vivi 	 * need to expose ISA bridge to let driver know the real hardware
2976ca37b86SRodrigo Vivi 	 * underneath. This is a requirement from virtualization team.
2986ca37b86SRodrigo Vivi 	 *
2996ca37b86SRodrigo Vivi 	 * In some virtualized environments (e.g. XEN), there is irrelevant
3006ca37b86SRodrigo Vivi 	 * ISA bridge in the system. To work reliably, we should scan through
3016ca37b86SRodrigo Vivi 	 * all the ISA bridge devices and check for the first match, instead
3026ca37b86SRodrigo Vivi 	 * of only checking the first one.
3036ca37b86SRodrigo Vivi 	 */
3046ca37b86SRodrigo Vivi 	while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
3056ca37b86SRodrigo Vivi 		if (pch->vendor != PCI_VENDOR_ID_INTEL)
3066ca37b86SRodrigo Vivi 			continue;
3076ca37b86SRodrigo Vivi 
3086ca37b86SRodrigo Vivi 		id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
3096ca37b86SRodrigo Vivi 
310ad283764SRodrigo Vivi 		pch_type = intel_pch_type(display, id);
3116ca37b86SRodrigo Vivi 		if (pch_type != PCH_NONE) {
312ad283764SRodrigo Vivi 			display->pch_type = pch_type;
3136ca37b86SRodrigo Vivi 			break;
3146ca37b86SRodrigo Vivi 		} else if (intel_is_virt_pch(id, pch->subsystem_vendor,
3156ca37b86SRodrigo Vivi 					     pch->subsystem_device)) {
316ad283764SRodrigo Vivi 			intel_virt_detect_pch(display, &id, &pch_type);
317ad283764SRodrigo Vivi 			display->pch_type = pch_type;
3186ca37b86SRodrigo Vivi 			break;
3196ca37b86SRodrigo Vivi 		}
3206ca37b86SRodrigo Vivi 	}
3216ca37b86SRodrigo Vivi 
3226ca37b86SRodrigo Vivi 	/*
3236ca37b86SRodrigo Vivi 	 * Use PCH_NOP (PCH but no South Display) for PCH platforms without
3246ca37b86SRodrigo Vivi 	 * display.
3256ca37b86SRodrigo Vivi 	 */
326ad283764SRodrigo Vivi 	if (pch && !HAS_DISPLAY(display)) {
327ad283764SRodrigo Vivi 		drm_dbg_kms(display->drm,
3286ca37b86SRodrigo Vivi 			    "Display disabled, reverting to NOP PCH\n");
329ad283764SRodrigo Vivi 		display->pch_type = PCH_NOP;
3306ca37b86SRodrigo Vivi 	} else if (!pch) {
331ad283764SRodrigo Vivi 		if (i915_run_as_guest() && HAS_DISPLAY(display)) {
332ad283764SRodrigo Vivi 			intel_virt_detect_pch(display, &id, &pch_type);
333ad283764SRodrigo Vivi 			display->pch_type = pch_type;
3346ca37b86SRodrigo Vivi 		} else {
335ad283764SRodrigo Vivi 			drm_dbg_kms(display->drm, "No PCH found.\n");
3366ca37b86SRodrigo Vivi 		}
3376ca37b86SRodrigo Vivi 	}
3386ca37b86SRodrigo Vivi 
3396ca37b86SRodrigo Vivi 	pci_dev_put(pch);
3406ca37b86SRodrigo Vivi }
341