intel_pch.c 9.4 KB

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