linux/drivers/gpu/drm/i915/intel_pch.c
<<
>>
Prefs
   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. */
  10static enum intel_pch
  11intel_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, GRAPHICS_VER(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                            GRAPHICS_VER(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                            GRAPHICS_VER(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_COFFEELAKE(dev_priv) &&
  85                            !IS_COMETLAKE(dev_priv));
  86                return PCH_CNP;
  87        case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE:
  88                drm_dbg_kms(&dev_priv->drm,
  89                            "Found Cannon Lake LP PCH (CNP-LP)\n");
  90                drm_WARN_ON(&dev_priv->drm,
  91                            !IS_COFFEELAKE(dev_priv) &&
  92                            !IS_COMETLAKE(dev_priv));
  93                return PCH_CNP;
  94        case INTEL_PCH_CMP_DEVICE_ID_TYPE:
  95        case INTEL_PCH_CMP2_DEVICE_ID_TYPE:
  96                drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n");
  97                drm_WARN_ON(&dev_priv->drm,
  98                            !IS_COFFEELAKE(dev_priv) &&
  99                            !IS_COMETLAKE(dev_priv) &&
 100                            !IS_ROCKETLAKE(dev_priv));
 101                /* CometPoint is CNP Compatible */
 102                return PCH_CNP;
 103        case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:
 104                drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n");
 105                drm_WARN_ON(&dev_priv->drm,
 106                            !IS_COFFEELAKE(dev_priv) &&
 107                            !IS_COMETLAKE(dev_priv));
 108                /* Comet Lake V PCH is based on KBP, which is SPT compatible */
 109                return PCH_SPT;
 110        case INTEL_PCH_ICP_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_JSL_EHL(dev_priv));
 117                return PCH_MCC;
 118        case INTEL_PCH_TGP_DEVICE_ID_TYPE:
 119        case INTEL_PCH_TGP2_DEVICE_ID_TYPE:
 120                drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n");
 121                drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) &&
 122                            !IS_ROCKETLAKE(dev_priv) &&
 123                            !IS_GEN9_BC(dev_priv));
 124                return PCH_TGP;
 125        case INTEL_PCH_JSP_DEVICE_ID_TYPE:
 126        case INTEL_PCH_JSP2_DEVICE_ID_TYPE:
 127                drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n");
 128                drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv));
 129                return PCH_JSP;
 130        case INTEL_PCH_ADP_DEVICE_ID_TYPE:
 131        case INTEL_PCH_ADP2_DEVICE_ID_TYPE:
 132                drm_dbg_kms(&dev_priv->drm, "Found Alder Lake PCH\n");
 133                drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) &&
 134                            !IS_ALDERLAKE_P(dev_priv));
 135                return PCH_ADP;
 136        default:
 137                return PCH_NONE;
 138        }
 139}
 140
 141static bool intel_is_virt_pch(unsigned short id,
 142                              unsigned short svendor, unsigned short sdevice)
 143{
 144        return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE ||
 145                id == INTEL_PCH_P3X_DEVICE_ID_TYPE ||
 146                (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE &&
 147                 svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
 148                 sdevice == PCI_SUBDEVICE_ID_QEMU));
 149}
 150
 151static void
 152intel_virt_detect_pch(const struct drm_i915_private *dev_priv,
 153                      unsigned short *pch_id, enum intel_pch *pch_type)
 154{
 155        unsigned short id = 0;
 156
 157        /*
 158         * In a virtualized passthrough environment we can be in a
 159         * setup where the ISA bridge is not able to be passed through.
 160         * In this case, a south bridge can be emulated and we have to
 161         * make an educated guess as to which PCH is really there.
 162         */
 163
 164        if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
 165                id = INTEL_PCH_ADP_DEVICE_ID_TYPE;
 166        else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv))
 167                id = INTEL_PCH_TGP_DEVICE_ID_TYPE;
 168        else if (IS_JSL_EHL(dev_priv))
 169                id = INTEL_PCH_MCC_DEVICE_ID_TYPE;
 170        else if (IS_ICELAKE(dev_priv))
 171                id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
 172        else if (IS_COFFEELAKE(dev_priv) ||
 173                 IS_COMETLAKE(dev_priv))
 174                id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
 175        else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv))
 176                id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
 177        else if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
 178                id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
 179        else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 180                id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
 181        else if (GRAPHICS_VER(dev_priv) == 6 || IS_IVYBRIDGE(dev_priv))
 182                id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
 183        else if (GRAPHICS_VER(dev_priv) == 5)
 184                id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
 185
 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
 191        *pch_type = intel_pch_type(dev_priv, id);
 192
 193        /* Sanity check virtual PCH id */
 194        if (drm_WARN_ON(&dev_priv->drm,
 195                        id && *pch_type == PCH_NONE))
 196                id = 0;
 197
 198        *pch_id = id;
 199}
 200
 201void intel_detect_pch(struct drm_i915_private *dev_priv)
 202{
 203        struct pci_dev *pch = NULL;
 204        unsigned short id;
 205        enum intel_pch pch_type;
 206
 207        /* DG1 has south engine display on the same PCI device */
 208        if (IS_DG1(dev_priv)) {
 209                dev_priv->pch_type = PCH_DG1;
 210                return;
 211        } else if (IS_DG2(dev_priv)) {
 212                dev_priv->pch_type = PCH_DG2;
 213                return;
 214        }
 215
 216        /*
 217         * The reason to probe ISA bridge instead of Dev31:Fun0 is to
 218         * make graphics device passthrough work easy for VMM, that only
 219         * need to expose ISA bridge to let driver know the real hardware
 220         * underneath. This is a requirement from virtualization team.
 221         *
 222         * In some virtualized environments (e.g. XEN), there is irrelevant
 223         * ISA bridge in the system. To work reliably, we should scan trhough
 224         * all the ISA bridge devices and check for the first match, instead
 225         * of only checking the first one.
 226         */
 227        while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
 228                if (pch->vendor != PCI_VENDOR_ID_INTEL)
 229                        continue;
 230
 231                id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
 232
 233                pch_type = intel_pch_type(dev_priv, id);
 234                if (pch_type != PCH_NONE) {
 235                        dev_priv->pch_type = pch_type;
 236                        dev_priv->pch_id = id;
 237                        break;
 238                } else if (intel_is_virt_pch(id, pch->subsystem_vendor,
 239                                             pch->subsystem_device)) {
 240                        intel_virt_detect_pch(dev_priv, &id, &pch_type);
 241                        dev_priv->pch_type = pch_type;
 242                        dev_priv->pch_id = id;
 243                        break;
 244                }
 245        }
 246
 247        /*
 248         * Use PCH_NOP (PCH but no South Display) for PCH platforms without
 249         * display.
 250         */
 251        if (pch && !HAS_DISPLAY(dev_priv)) {
 252                drm_dbg_kms(&dev_priv->drm,
 253                            "Display disabled, reverting to NOP PCH\n");
 254                dev_priv->pch_type = PCH_NOP;
 255                dev_priv->pch_id = 0;
 256        } else if (!pch) {
 257                if (run_as_guest() && HAS_DISPLAY(dev_priv)) {
 258                        intel_virt_detect_pch(dev_priv, &id, &pch_type);
 259                        dev_priv->pch_type = pch_type;
 260                        dev_priv->pch_id = id;
 261                } else {
 262                        drm_dbg_kms(&dev_priv->drm, "No PCH found.\n");
 263                }
 264        }
 265
 266        pci_dev_put(pch);
 267}
 268