diff options
author | Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com> | 2016-04-26 10:54:38 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-08-31 15:21:07 -0400 |
commit | 9139d731fdaa52b85543f2713d65ca860e0ce884 (patch) | |
tree | afa48d7ab93a8b78ca08c8d08db6b871dbf366b8 /drivers/gpu/drm/amd/amdgpu | |
parent | da69c161448d6a682b3761d9bc444161cbf25337 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 158 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 16 |
2 files changed, 173 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 1b621160b52e..59961db9c390 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | |||
@@ -978,6 +978,48 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, | |||
978 | return -EINVAL; | 978 | return -EINVAL; |
979 | 979 | ||
980 | switch (crev) { | 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 | case 4: | 1023 | case 4: |
982 | /* fusion */ | 1024 | /* fusion */ |
983 | args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ | 1025 | args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */ |
@@ -1122,6 +1164,32 @@ void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev, | |||
1122 | amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); | 1164 | amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); |
1123 | } | 1165 | } |
1124 | 1166 | ||
1167 | void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, | ||
1168 | u16 *vddc, u16 *vddci, u16 *mvdd) | ||
1169 | { | ||
1170 | struct amdgpu_mode_info *mode_info = &adev->mode_info; | ||
1171 | int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); | ||
1172 | u8 frev, crev; | ||
1173 | u16 data_offset; | ||
1174 | union firmware_info *firmware_info; | ||
1175 | |||
1176 | *vddc = 0; | ||
1177 | *vddci = 0; | ||
1178 | *mvdd = 0; | ||
1179 | |||
1180 | if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, | ||
1181 | &frev, &crev, &data_offset)) { | ||
1182 | firmware_info = | ||
1183 | (union firmware_info *)(mode_info->atom_context->bios + | ||
1184 | data_offset); | ||
1185 | *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); | ||
1186 | if ((frev == 2) && (crev >= 2)) { | ||
1187 | *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); | ||
1188 | *mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage); | ||
1189 | } | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1125 | union set_voltage { | 1193 | union set_voltage { |
1126 | struct _SET_VOLTAGE_PS_ALLOCATION alloc; | 1194 | struct _SET_VOLTAGE_PS_ALLOCATION alloc; |
1127 | struct _SET_VOLTAGE_PARAMETERS v1; | 1195 | struct _SET_VOLTAGE_PARAMETERS v1; |
@@ -1129,6 +1197,52 @@ union set_voltage { | |||
1129 | struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; | 1197 | struct _SET_VOLTAGE_PARAMETERS_V1_3 v3; |
1130 | }; | 1198 | }; |
1131 | 1199 | ||
1200 | int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, | ||
1201 | u16 voltage_id, u16 *voltage) | ||
1202 | { | ||
1203 | union set_voltage args; | ||
1204 | int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); | ||
1205 | u8 frev, crev; | ||
1206 | |||
1207 | if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) | ||
1208 | return -EINVAL; | ||
1209 | |||
1210 | switch (crev) { | ||
1211 | case 1: | ||
1212 | return -EINVAL; | ||
1213 | case 2: | ||
1214 | args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; | ||
1215 | args.v2.ucVoltageMode = 0; | ||
1216 | args.v2.usVoltageLevel = 0; | ||
1217 | |||
1218 | amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1219 | |||
1220 | *voltage = le16_to_cpu(args.v2.usVoltageLevel); | ||
1221 | break; | ||
1222 | case 3: | ||
1223 | args.v3.ucVoltageType = voltage_type; | ||
1224 | args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; | ||
1225 | args.v3.usVoltageLevel = cpu_to_le16(voltage_id); | ||
1226 | |||
1227 | amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); | ||
1228 | |||
1229 | *voltage = le16_to_cpu(args.v3.usVoltageLevel); | ||
1230 | break; | ||
1231 | default: | ||
1232 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
1233 | return -EINVAL; | ||
1234 | } | ||
1235 | |||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, | ||
1240 | u16 *voltage, | ||
1241 | u16 leakage_idx) | ||
1242 | { | ||
1243 | return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); | ||
1244 | } | ||
1245 | |||
1132 | void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, | 1246 | void amdgpu_atombios_set_voltage(struct amdgpu_device *adev, |
1133 | u16 voltage_level, | 1247 | u16 voltage_level, |
1134 | u8 voltage_type) | 1248 | u8 voltage_type) |
@@ -1349,6 +1463,50 @@ static ATOM_VOLTAGE_OBJECT_V3 *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOL | |||
1349 | return NULL; | 1463 | return NULL; |
1350 | } | 1464 | } |
1351 | 1465 | ||
1466 | int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, | ||
1467 | u8 voltage_type, | ||
1468 | u8 *svd_gpio_id, u8 *svc_gpio_id) | ||
1469 | { | ||
1470 | int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); | ||
1471 | u8 frev, crev; | ||
1472 | u16 data_offset, size; | ||
1473 | union voltage_object_info *voltage_info; | ||
1474 | union voltage_object *voltage_object = NULL; | ||
1475 | |||
1476 | if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size, | ||
1477 | &frev, &crev, &data_offset)) { | ||
1478 | voltage_info = (union voltage_object_info *) | ||
1479 | (adev->mode_info.atom_context->bios + data_offset); | ||
1480 | |||
1481 | switch (frev) { | ||
1482 | case 3: | ||
1483 | switch (crev) { | ||
1484 | case 1: | ||
1485 | voltage_object = (union voltage_object *) | ||
1486 | amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, | ||
1487 | voltage_type, | ||
1488 | VOLTAGE_OBJ_SVID2); | ||
1489 | if (voltage_object) { | ||
1490 | *svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId; | ||
1491 | *svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId; | ||
1492 | } else { | ||
1493 | return -EINVAL; | ||
1494 | } | ||
1495 | break; | ||
1496 | default: | ||
1497 | DRM_ERROR("unknown voltage object table\n"); | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1500 | break; | ||
1501 | default: | ||
1502 | DRM_ERROR("unknown voltage object table\n"); | ||
1503 | return -EINVAL; | ||
1504 | } | ||
1505 | |||
1506 | } | ||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1352 | bool | 1510 | bool |
1353 | amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev, | 1511 | amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev, |
1354 | u8 voltage_type, u8 voltage_mode) | 1512 | u8 voltage_type, u8 voltage_mode) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 15dd43ec38bb..17356151db38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | |||
@@ -208,5 +208,19 @@ void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev); | |||
208 | void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); | 208 | void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev); |
209 | 209 | ||
210 | void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); | 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 | #endif | 226 | #endif |