diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 161 | 
1 files changed, 126 insertions, 35 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 4bdda56fccee..f9ffe8ef0cd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -66,41 +66,6 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)  	}  } -void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev) -{ -	int i; - -	for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) -		adev->bios_scratch[i] = RREG32(adev->bios_scratch_reg_offset + i); -} - -void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev) -{ -	int i; - -	/* -	 * VBIOS will check ASIC_INIT_COMPLETE bit to decide if -	 * execute ASIC_Init posting via driver -	 */ -	adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK; - -	for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) -		WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); -} - -void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev, -						  bool hung) -{ -	u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3); - -	if (hung) -		tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; -	else -		tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; - -	WREG32(adev->bios_scratch_reg_offset + 3, tmp); -} -  int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)  {  	struct atom_context *ctx = adev->mode_info.atom_context; @@ -130,3 +95,129 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)  	ctx->scratch_size_bytes = usage_bytes;  	return 0;  } + +union igp_info { +	struct atom_integrated_system_info_v1_11 v11; +}; + +/* + * Return vram width from integrated system info table, if available, + * or 0 if not. + */ +int amdgpu_atomfirmware_get_vram_width(struct amdgpu_device *adev) +{ +	struct amdgpu_mode_info *mode_info = &adev->mode_info; +	int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, +						integratedsysteminfo); +	u16 data_offset, size; +	union igp_info *igp_info; +	u8 frev, crev; + +	/* get any igp specific overrides */ +	if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, &size, +				   &frev, &crev, &data_offset)) { +		igp_info = (union igp_info *) +			(mode_info->atom_context->bios + data_offset); +		switch (crev) { +		case 11: +			return igp_info->v11.umachannelnumber * 64; +		default: +			return 0; +		} +	} + +	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; +} |