diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 93 | 
1 files changed, 93 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index a7d65f033883..f9ffe8ef0cd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -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; +} | 
