linux/drivers/gpu/drm/i915/intel_step.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2020,2021 Intel Corporation
   4 */
   5
   6#include "i915_drv.h"
   7#include "intel_step.h"
   8
   9/*
  10 * Some platforms have unusual ways of mapping PCI revision ID to GT/display
  11 * steppings.  E.g., in some cases a higher PCI revision may translate to a
  12 * lower stepping of the GT and/or display IP.  This file provides lookup
  13 * tables to map the PCI revision into a standard set of stepping values that
  14 * can be compared numerically.
  15 *
  16 * Also note that some revisions/steppings may have been set aside as
  17 * placeholders but never materialized in real hardware; in those cases there
  18 * may be jumps in the revision IDs or stepping values in the tables below.
  19 */
  20
  21/*
  22 * Some platforms always have the same stepping value for GT and display;
  23 * use a macro to define these to make it easier to identify the platforms
  24 * where the two steppings can deviate.
  25 */
  26#define COMMON_STEP(x)  .gt_step = STEP_##x, .display_step = STEP_##x
  27
  28static const struct intel_step_info skl_revids[] = {
  29        [0x6] = { COMMON_STEP(G0) },
  30        [0x7] = { COMMON_STEP(H0) },
  31        [0x9] = { COMMON_STEP(J0) },
  32        [0xA] = { COMMON_STEP(I1) },
  33};
  34
  35static const struct intel_step_info kbl_revids[] = {
  36        [1] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
  37        [2] = { .gt_step = STEP_C0, .display_step = STEP_B0 },
  38        [3] = { .gt_step = STEP_D0, .display_step = STEP_B0 },
  39        [4] = { .gt_step = STEP_F0, .display_step = STEP_C0 },
  40        [5] = { .gt_step = STEP_C0, .display_step = STEP_B1 },
  41        [6] = { .gt_step = STEP_D1, .display_step = STEP_B1 },
  42        [7] = { .gt_step = STEP_G0, .display_step = STEP_C0 },
  43};
  44
  45static const struct intel_step_info bxt_revids[] = {
  46        [0xA] = { COMMON_STEP(C0) },
  47        [0xB] = { COMMON_STEP(C0) },
  48        [0xC] = { COMMON_STEP(D0) },
  49        [0xD] = { COMMON_STEP(E0) },
  50};
  51
  52static const struct intel_step_info glk_revids[] = {
  53        [3] = { COMMON_STEP(B0) },
  54};
  55
  56static const struct intel_step_info icl_revids[] = {
  57        [7] = { COMMON_STEP(D0) },
  58};
  59
  60static const struct intel_step_info jsl_ehl_revids[] = {
  61        [0] = { COMMON_STEP(A0) },
  62        [1] = { COMMON_STEP(B0) },
  63};
  64
  65static const struct intel_step_info tgl_uy_revids[] = {
  66        [0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
  67        [1] = { .gt_step = STEP_B0, .display_step = STEP_C0 },
  68        [2] = { .gt_step = STEP_B1, .display_step = STEP_C0 },
  69        [3] = { .gt_step = STEP_C0, .display_step = STEP_D0 },
  70};
  71
  72/* Same GT stepping between tgl_uy_revids and tgl_revids don't mean the same HW */
  73static const struct intel_step_info tgl_revids[] = {
  74        [0] = { .gt_step = STEP_A0, .display_step = STEP_B0 },
  75        [1] = { .gt_step = STEP_B0, .display_step = STEP_D0 },
  76};
  77
  78static const struct intel_step_info rkl_revids[] = {
  79        [0] = { COMMON_STEP(A0) },
  80        [1] = { COMMON_STEP(B0) },
  81        [4] = { COMMON_STEP(C0) },
  82};
  83
  84static const struct intel_step_info dg1_revids[] = {
  85        [0] = { COMMON_STEP(A0) },
  86        [1] = { COMMON_STEP(B0) },
  87};
  88
  89static const struct intel_step_info adls_revids[] = {
  90        [0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
  91        [0x1] = { .gt_step = STEP_A0, .display_step = STEP_A2 },
  92        [0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
  93        [0x8] = { .gt_step = STEP_C0, .display_step = STEP_B0 },
  94        [0xC] = { .gt_step = STEP_D0, .display_step = STEP_C0 },
  95};
  96
  97static const struct intel_step_info adlp_revids[] = {
  98        [0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
  99        [0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
 100        [0x8] = { .gt_step = STEP_C0, .display_step = STEP_C0 },
 101        [0xC] = { .gt_step = STEP_C0, .display_step = STEP_D0 },
 102};
 103
 104static const struct intel_step_info xehpsdv_revids[] = {
 105        [0x0] = { .gt_step = STEP_A0 },
 106        [0x1] = { .gt_step = STEP_A1 },
 107        [0x4] = { .gt_step = STEP_B0 },
 108        [0x8] = { .gt_step = STEP_C0 },
 109};
 110
 111static const struct intel_step_info dg2_g10_revid_step_tbl[] = {
 112        [0x0] = { .gt_step = STEP_A0, .display_step = STEP_A0 },
 113        [0x1] = { .gt_step = STEP_A1, .display_step = STEP_A0 },
 114        [0x4] = { .gt_step = STEP_B0, .display_step = STEP_B0 },
 115        [0x8] = { .gt_step = STEP_C0, .display_step = STEP_C0 },
 116};
 117
 118static const struct intel_step_info dg2_g11_revid_step_tbl[] = {
 119        [0x0] = { .gt_step = STEP_A0, .display_step = STEP_B0 },
 120        [0x4] = { .gt_step = STEP_B0, .display_step = STEP_C0 },
 121        [0x5] = { .gt_step = STEP_B1, .display_step = STEP_C0 },
 122};
 123
 124void intel_step_init(struct drm_i915_private *i915)
 125{
 126        const struct intel_step_info *revids = NULL;
 127        int size = 0;
 128        int revid = INTEL_REVID(i915);
 129        struct intel_step_info step = {};
 130
 131        if (IS_DG2_G10(i915)) {
 132                revids = dg2_g10_revid_step_tbl;
 133                size = ARRAY_SIZE(dg2_g10_revid_step_tbl);
 134        } else if (IS_DG2_G11(i915)) {
 135                revids = dg2_g11_revid_step_tbl;
 136                size = ARRAY_SIZE(dg2_g11_revid_step_tbl);
 137        } else if (IS_XEHPSDV(i915)) {
 138                revids = xehpsdv_revids;
 139                size = ARRAY_SIZE(xehpsdv_revids);
 140        } else if (IS_ALDERLAKE_P(i915)) {
 141                revids = adlp_revids;
 142                size = ARRAY_SIZE(adlp_revids);
 143        } else if (IS_ALDERLAKE_S(i915)) {
 144                revids = adls_revids;
 145                size = ARRAY_SIZE(adls_revids);
 146        } else if (IS_DG1(i915)) {
 147                revids = dg1_revids;
 148                size = ARRAY_SIZE(dg1_revids);
 149        } else if (IS_ROCKETLAKE(i915)) {
 150                revids = rkl_revids;
 151                size = ARRAY_SIZE(rkl_revids);
 152        } else if (IS_TGL_U(i915) || IS_TGL_Y(i915)) {
 153                revids = tgl_uy_revids;
 154                size = ARRAY_SIZE(tgl_uy_revids);
 155        } else if (IS_TIGERLAKE(i915)) {
 156                revids = tgl_revids;
 157                size = ARRAY_SIZE(tgl_revids);
 158        } else if (IS_JSL_EHL(i915)) {
 159                revids = jsl_ehl_revids;
 160                size = ARRAY_SIZE(jsl_ehl_revids);
 161        } else if (IS_ICELAKE(i915)) {
 162                revids = icl_revids;
 163                size = ARRAY_SIZE(icl_revids);
 164        } else if (IS_GEMINILAKE(i915)) {
 165                revids = glk_revids;
 166                size = ARRAY_SIZE(glk_revids);
 167        } else if (IS_BROXTON(i915)) {
 168                revids = bxt_revids;
 169                size = ARRAY_SIZE(bxt_revids);
 170        } else if (IS_KABYLAKE(i915)) {
 171                revids = kbl_revids;
 172                size = ARRAY_SIZE(kbl_revids);
 173        } else if (IS_SKYLAKE(i915)) {
 174                revids = skl_revids;
 175                size = ARRAY_SIZE(skl_revids);
 176        }
 177
 178        /* Not using the stepping scheme for the platform yet. */
 179        if (!revids)
 180                return;
 181
 182        if (revid < size && revids[revid].gt_step != STEP_NONE) {
 183                step = revids[revid];
 184        } else {
 185                drm_warn(&i915->drm, "Unknown revid 0x%02x\n", revid);
 186
 187                /*
 188                 * If we hit a gap in the revid array, use the information for
 189                 * the next revid.
 190                 *
 191                 * This may be wrong in all sorts of ways, especially if the
 192                 * steppings in the array are not monotonically increasing, but
 193                 * it's better than defaulting to 0.
 194                 */
 195                while (revid < size && revids[revid].gt_step == STEP_NONE)
 196                        revid++;
 197
 198                if (revid < size) {
 199                        drm_dbg(&i915->drm, "Using steppings for revid 0x%02x\n",
 200                                revid);
 201                        step = revids[revid];
 202                } else {
 203                        drm_dbg(&i915->drm, "Using future steppings\n");
 204                        step.gt_step = STEP_FUTURE;
 205                        step.display_step = STEP_FUTURE;
 206                }
 207        }
 208
 209        if (drm_WARN_ON(&i915->drm, step.gt_step == STEP_NONE))
 210                return;
 211
 212        RUNTIME_INFO(i915)->step = step;
 213}
 214
 215#define STEP_NAME_CASE(name)    \
 216        case STEP_##name:       \
 217                return #name;
 218
 219const char *intel_step_name(enum intel_step step)
 220{
 221        switch (step) {
 222        STEP_NAME_LIST(STEP_NAME_CASE);
 223
 224        default:
 225                return "**";
 226        }
 227}
 228