|
@@ -128,3 +128,96 @@ int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev)
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+union firmware_info {
|
|
|
+ struct atom_firmware_info_v3_1 v31;
|
|
|
+};
|
|
|
+
|
|
|
+union smu_info {
|
|
|
+ struct atom_smu_info_v3_1 v31;
|
|
|
+};
|
|
|
+
|
|
|
+union umc_info {
|
|
|
+ struct atom_umc_info_v3_1 v31;
|
|
|
+};
|
|
|
+
|
|
|
+int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev)
|
|
|
+{
|
|
|
+ struct amdgpu_mode_info *mode_info = &adev->mode_info;
|
|
|
+ struct amdgpu_pll *spll = &adev->clock.spll;
|
|
|
+ struct amdgpu_pll *mpll = &adev->clock.mpll;
|
|
|
+ uint8_t frev, crev;
|
|
|
+ uint16_t data_offset;
|
|
|
+ int ret = -EINVAL, index;
|
|
|
+
|
|
|
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
|
|
+ firmwareinfo);
|
|
|
+ if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
|
|
|
+ &frev, &crev, &data_offset)) {
|
|
|
+ union firmware_info *firmware_info =
|
|
|
+ (union firmware_info *)(mode_info->atom_context->bios +
|
|
|
+ data_offset);
|
|
|
+
|
|
|
+ adev->clock.default_sclk =
|
|
|
+ le32_to_cpu(firmware_info->v31.bootup_sclk_in10khz);
|
|
|
+ adev->clock.default_mclk =
|
|
|
+ le32_to_cpu(firmware_info->v31.bootup_mclk_in10khz);
|
|
|
+
|
|
|
+ adev->pm.current_sclk = adev->clock.default_sclk;
|
|
|
+ adev->pm.current_mclk = adev->clock.default_mclk;
|
|
|
+
|
|
|
+ /* not technically a clock, but... */
|
|
|
+ adev->mode_info.firmware_flags =
|
|
|
+ le32_to_cpu(firmware_info->v31.firmware_capability);
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
|
|
+ smu_info);
|
|
|
+ if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
|
|
|
+ &frev, &crev, &data_offset)) {
|
|
|
+ union smu_info *smu_info =
|
|
|
+ (union smu_info *)(mode_info->atom_context->bios +
|
|
|
+ data_offset);
|
|
|
+
|
|
|
+ /* system clock */
|
|
|
+ spll->reference_freq = le32_to_cpu(smu_info->v31.core_refclk_10khz);
|
|
|
+
|
|
|
+ spll->reference_div = 0;
|
|
|
+ spll->min_post_div = 1;
|
|
|
+ spll->max_post_div = 1;
|
|
|
+ spll->min_ref_div = 2;
|
|
|
+ spll->max_ref_div = 0xff;
|
|
|
+ spll->min_feedback_div = 4;
|
|
|
+ spll->max_feedback_div = 0xff;
|
|
|
+ spll->best_vco = 0;
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
|
|
+ umc_info);
|
|
|
+ if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
|
|
|
+ &frev, &crev, &data_offset)) {
|
|
|
+ union umc_info *umc_info =
|
|
|
+ (union umc_info *)(mode_info->atom_context->bios +
|
|
|
+ data_offset);
|
|
|
+
|
|
|
+ /* memory clock */
|
|
|
+ mpll->reference_freq = le32_to_cpu(umc_info->v31.mem_refclk_10khz);
|
|
|
+
|
|
|
+ mpll->reference_div = 0;
|
|
|
+ mpll->min_post_div = 1;
|
|
|
+ mpll->max_post_div = 1;
|
|
|
+ mpll->min_ref_div = 2;
|
|
|
+ mpll->max_ref_div = 0xff;
|
|
|
+ mpll->min_feedback_div = 4;
|
|
|
+ mpll->max_feedback_div = 0xff;
|
|
|
+ mpll->best_vco = 0;
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|