Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: add si dpm support in amdgpu_atombios

v2: renamed _atom_ to _atombios_ for consistency
added ulClockParams to _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 and
_COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 to avoid build break

Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Maruthi Srinivas Bayyavarapu and committed by
Alex Deucher
9139d731 da69c161

+175 -1
+158
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
··· 978 978 return -EINVAL; 979 979 980 980 switch (crev) { 981 + case 2: 982 + case 3: 983 + case 5: 984 + /* r6xx, r7xx, evergreen, ni, si. 985 + * TODO: add support for asic_type <= CHIP_RV770*/ 986 + if (clock_type == COMPUTE_ENGINE_PLL_PARAM) { 987 + args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock); 988 + 989 + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); 990 + 991 + dividers->post_div = args.v3.ucPostDiv; 992 + dividers->enable_post_div = (args.v3.ucCntlFlag & 993 + ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; 994 + dividers->enable_dithen = (args.v3.ucCntlFlag & 995 + ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; 996 + dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv); 997 + dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac); 998 + dividers->ref_div = args.v3.ucRefDiv; 999 + dividers->vco_mode = (args.v3.ucCntlFlag & 1000 + ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; 1001 + } else { 1002 + /* for SI we use ComputeMemoryClockParam for memory plls */ 1003 + if (adev->asic_type >= CHIP_TAHITI) 1004 + return -EINVAL; 1005 + args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock); 1006 + if (strobe_mode) 1007 + args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN; 1008 + 1009 + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); 1010 + 1011 + dividers->post_div = args.v5.ucPostDiv; 1012 + dividers->enable_post_div = (args.v5.ucCntlFlag & 1013 + ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; 1014 + dividers->enable_dithen = (args.v5.ucCntlFlag & 1015 + ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; 1016 + dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv); 1017 + dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac); 1018 + dividers->ref_div = args.v5.ucRefDiv; 1019 + dividers->vco_mode = (args.v5.ucCntlFlag & 1020 + ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; 1021 + } 1022 + break; 981 1023 case 4: 982 1024 /* fusion */ 983 1025 args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ ··· 1164 1122 amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); 1165 1123 } 1166 1124 1125 + void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, 1126 + u16 *vddc, u16 *vddci, u16 *mvdd) 1127 + { 1128 + struct amdgpu_mode_info *mode_info = &adev->mode_info; 1129 + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); 1130 + u8 frev, crev; 1131 + u16 data_offset; 1132 + union firmware_info *firmware_info; 1133 + 1134 + *vddc = 0; 1135 + *vddci = 0; 1136 + *mvdd = 0; 1137 + 1138 + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 1139 + &frev, &crev, &data_offset)) { 1140 + firmware_info = 1141 + (union firmware_info *)(mode_info->atom_context->bios + 1142 + data_offset); 1143 + *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); 1144 + if ((frev == 2) && (crev >= 2)) { 1145 + *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); 1146 + *mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage); 1147 + } 1148 + } 1149 + } 1150 + 1167 1151 union set_voltage { 1168 1152 struct _SET_VOLTAGE_PS_ALLOCATION alloc; 1169 1153 struct _SET_VOLTAGE_PARAMETERS v1; 1170 1154 struct _SET_VOLTAGE_PARAMETERS_V2 v2; 1171 1155 struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; 1172 1156 }; 1157 + 1158 + int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, 1159 + u16 voltage_id, u16 *voltage) 1160 + { 1161 + union set_voltage args; 1162 + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); 1163 + u8 frev, crev; 1164 + 1165 + if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) 1166 + return -EINVAL; 1167 + 1168 + switch (crev) { 1169 + case 1: 1170 + return -EINVAL; 1171 + case 2: 1172 + args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; 1173 + args.v2.ucVoltageMode = 0; 1174 + args.v2.usVoltageLevel = 0; 1175 + 1176 + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); 1177 + 1178 + *voltage = le16_to_cpu(args.v2.usVoltageLevel); 1179 + break; 1180 + case 3: 1181 + args.v3.ucVoltageType = voltage_type; 1182 + args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; 1183 + args.v3.usVoltageLevel = cpu_to_le16(voltage_id); 1184 + 1185 + amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); 1186 + 1187 + *voltage = le16_to_cpu(args.v3.usVoltageLevel); 1188 + break; 1189 + default: 1190 + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); 1191 + return -EINVAL; 1192 + } 1193 + 1194 + return 0; 1195 + } 1196 + 1197 + int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, 1198 + u16 *voltage, 1199 + u16 leakage_idx) 1200 + { 1201 + return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); 1202 + } 1173 1203 1174 1204 void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, 1175 1205 u16 voltage_level, ··· 1461 1347 offset += le16_to_cpu(vo->asGpioVoltageObj.sHeader.usSize); 1462 1348 } 1463 1349 return NULL; 1350 + } 1351 + 1352 + int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, 1353 + u8 voltage_type, 1354 + u8 *svd_gpio_id, u8 *svc_gpio_id) 1355 + { 1356 + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); 1357 + u8 frev, crev; 1358 + u16 data_offset, size; 1359 + union voltage_object_info *voltage_info; 1360 + union voltage_object *voltage_object = NULL; 1361 + 1362 + if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size, 1363 + &frev, &crev, &data_offset)) { 1364 + voltage_info = (union voltage_object_info *) 1365 + (adev->mode_info.atom_context->bios + data_offset); 1366 + 1367 + switch (frev) { 1368 + case 3: 1369 + switch (crev) { 1370 + case 1: 1371 + voltage_object = (union voltage_object *) 1372 + amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, 1373 + voltage_type, 1374 + VOLTAGE_OBJ_SVID2); 1375 + if (voltage_object) { 1376 + *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId; 1377 + *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId; 1378 + } else { 1379 + return -EINVAL; 1380 + } 1381 + break; 1382 + default: 1383 + DRM_ERROR("unknown voltage object table\n"); 1384 + return -EINVAL; 1385 + } 1386 + break; 1387 + default: 1388 + DRM_ERROR("unknown voltage object table\n"); 1389 + return -EINVAL; 1390 + } 1391 + 1392 + } 1393 + return 0; 1464 1394 } 1465 1395 1466 1396 bool
+15 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
··· 208 208 void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); 209 209 210 210 void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); 211 - 211 + int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, 212 + u16 voltage_id, u16 *voltage); 213 + int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, 214 + u16 *voltage, 215 + u16 leakage_idx); 216 + void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, 217 + u16 *vddc, u16 *vddci, u16 *mvdd); 218 + int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, 219 + u8 clock_type, 220 + u32 clock, 221 + bool strobe_mode, 222 + struct atom_clock_dividers *dividers); 223 + int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, 224 + u8 voltage_type, 225 + u8 *svd_gpio_id, u8 *svc_gpio_id); 212 226 #endif
+2
drivers/gpu/drm/amd/include/atombios.h
··· 494 494 union 495 495 { 496 496 ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter 497 + ULONG ulClockParams; //ULONG access for BE 497 498 ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter 498 499 }; 499 500 UCHAR ucRefDiv; //Output Parameter ··· 527 526 union 528 527 { 529 528 ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter 529 + ULONG ulClockParams; //ULONG access for BE 530 530 ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter 531 531 }; 532 532 UCHAR ucRefDiv; //Output Parameter