1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "xe_step.h" 7 8 #include <linux/bitfield.h> 9 10 #include "xe_device.h" 11 #include "xe_platform_types.h" 12 13 /* 14 * Provide mapping between PCI's revision ID to the individual GMD 15 * (Graphics/Media/Display) stepping values that can be compared numerically. 16 * 17 * Some platforms may have unusual ways of mapping PCI revision ID to GMD 18 * steppings. E.g., in some cases a higher PCI revision may translate to a 19 * lower stepping of the GT and/or display IP. 20 * 21 * Also note that some revisions/steppings may have been set aside as 22 * placeholders but never materialized in real hardware; in those cases there 23 * may be jumps in the revision IDs or stepping values in the tables below. 24 */ 25 26 /* 27 * Some platforms always have the same stepping value for GT and display; 28 * use a macro to define these to make it easier to identify the platforms 29 * where the two steppings can deviate. 30 */ 31 #define COMMON_GT_MEDIA_STEP(x_) \ 32 .graphics = STEP_##x_, \ 33 .media = STEP_##x_ 34 35 #define COMMON_STEP(x_) \ 36 COMMON_GT_MEDIA_STEP(x_), \ 37 .graphics = STEP_##x_, \ 38 .media = STEP_##x_, \ 39 .display = STEP_##x_ 40 41 __diag_push(); 42 __diag_ignore_all("-Woverride-init", "Allow field overrides in table"); 43 44 /* Same GT stepping between tgl_uy_revids and tgl_revids don't mean the same HW */ 45 static const struct xe_step_info tgl_revids[] = { 46 [0] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_B0 }, 47 [1] = { COMMON_GT_MEDIA_STEP(B0), .display = STEP_D0 }, 48 }; 49 50 static const struct xe_step_info dg1_revids[] = { 51 [0] = { COMMON_STEP(A0) }, 52 [1] = { COMMON_STEP(B0) }, 53 }; 54 55 static const struct xe_step_info adls_revids[] = { 56 [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_A0 }, 57 [0x1] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_A2 }, 58 [0x4] = { COMMON_GT_MEDIA_STEP(B0), .display = STEP_B0 }, 59 [0x8] = { COMMON_GT_MEDIA_STEP(C0), .display = STEP_B0 }, 60 [0xC] = { COMMON_GT_MEDIA_STEP(D0), .display = STEP_C0 }, 61 }; 62 63 static const struct xe_step_info dg2_g10_revid_step_tbl[] = { 64 [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_A0 }, 65 [0x1] = { COMMON_GT_MEDIA_STEP(A1), .display = STEP_A0 }, 66 [0x4] = { COMMON_GT_MEDIA_STEP(B0), .display = STEP_B0 }, 67 [0x8] = { COMMON_GT_MEDIA_STEP(C0), .display = STEP_C0 }, 68 }; 69 70 static const struct xe_step_info dg2_g11_revid_step_tbl[] = { 71 [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_B0 }, 72 [0x4] = { COMMON_GT_MEDIA_STEP(B0), .display = STEP_C0 }, 73 [0x5] = { COMMON_GT_MEDIA_STEP(B1), .display = STEP_C0 }, 74 }; 75 76 static const struct xe_step_info dg2_g12_revid_step_tbl[] = { 77 [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display = STEP_C0 }, 78 [0x1] = { COMMON_GT_MEDIA_STEP(A1), .display = STEP_C0 }, 79 }; 80 81 static const struct xe_step_info pvc_revid_step_tbl[] = { 82 [0x3] = { .graphics = STEP_A0 }, 83 [0x5] = { .graphics = STEP_B0 }, 84 [0x6] = { .graphics = STEP_B1 }, 85 [0x7] = { .graphics = STEP_C0 }, 86 }; 87 88 static const int pvc_basedie_subids[] = { 89 [0x0] = STEP_A0, 90 [0x3] = STEP_B0, 91 [0x4] = STEP_B1, 92 [0x5] = STEP_B3, 93 }; 94 95 __diag_pop(); 96 97 struct xe_step_info xe_step_get(struct xe_device *xe) 98 { 99 const struct xe_step_info *revids = NULL; 100 struct xe_step_info step = {}; 101 u16 revid = xe->info.revid; 102 int size = 0; 103 const int *basedie_info = NULL; 104 int basedie_size = 0; 105 int baseid = 0; 106 107 if (xe->info.platform == XE_PVC) { 108 baseid = FIELD_GET(GENMASK(5, 3), xe->info.revid); 109 revid = FIELD_GET(GENMASK(2, 0), xe->info.revid); 110 revids = pvc_revid_step_tbl; 111 size = ARRAY_SIZE(pvc_revid_step_tbl); 112 basedie_info = pvc_basedie_subids; 113 basedie_size = ARRAY_SIZE(pvc_basedie_subids); 114 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G10) { 115 revids = dg2_g10_revid_step_tbl; 116 size = ARRAY_SIZE(dg2_g10_revid_step_tbl); 117 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G11) { 118 revids = dg2_g11_revid_step_tbl; 119 size = ARRAY_SIZE(dg2_g11_revid_step_tbl); 120 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G12) { 121 revids = dg2_g12_revid_step_tbl; 122 size = ARRAY_SIZE(dg2_g12_revid_step_tbl); 123 } else if (xe->info.platform == XE_ALDERLAKE_S) { 124 revids = adls_revids; 125 size = ARRAY_SIZE(adls_revids); 126 } else if (xe->info.platform == XE_DG1) { 127 revids = dg1_revids; 128 size = ARRAY_SIZE(dg1_revids); 129 } else if (xe->info.platform == XE_TIGERLAKE) { 130 revids = tgl_revids; 131 size = ARRAY_SIZE(tgl_revids); 132 } 133 134 /* Not using the stepping scheme for the platform yet. */ 135 if (!revids) 136 return step; 137 138 if (revid < size && revids[revid].graphics != STEP_NONE) { 139 step = revids[revid]; 140 } else { 141 drm_warn(&xe->drm, "Unknown revid 0x%02x\n", revid); 142 143 /* 144 * If we hit a gap in the revid array, use the information for 145 * the next revid. 146 * 147 * This may be wrong in all sorts of ways, especially if the 148 * steppings in the array are not monotonically increasing, but 149 * it's better than defaulting to 0. 150 */ 151 while (revid < size && revids[revid].graphics == STEP_NONE) 152 revid++; 153 154 if (revid < size) { 155 drm_dbg(&xe->drm, "Using steppings for revid 0x%02x\n", 156 revid); 157 step = revids[revid]; 158 } else { 159 drm_dbg(&xe->drm, "Using future steppings\n"); 160 step.graphics = STEP_FUTURE; 161 step.display = STEP_FUTURE; 162 } 163 } 164 165 drm_WARN_ON(&xe->drm, step.graphics == STEP_NONE); 166 167 if (basedie_info && basedie_size) { 168 if (baseid < basedie_size && basedie_info[baseid] != STEP_NONE) { 169 step.basedie = basedie_info[baseid]; 170 } else { 171 drm_warn(&xe->drm, "Unknown baseid 0x%02x\n", baseid); 172 step.basedie = STEP_FUTURE; 173 } 174 } 175 176 return step; 177 } 178 179 #define STEP_NAME_CASE(name) \ 180 case STEP_##name: \ 181 return #name; 182 183 const char *xe_step_name(enum xe_step step) 184 { 185 switch (step) { 186 STEP_NAME_LIST(STEP_NAME_CASE); 187 188 default: 189 return "**"; 190 } 191 } 192