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