diff options
| author | Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com> | 2016-04-26 20:24:38 +0530 | 
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2016-08-31 15:21:07 -0400 | 
| commit | 9139d731fdaa52b85543f2713d65ca860e0ce884 (patch) | |
| tree | afa48d7ab93a8b78ca08c8d08db6b871dbf366b8 | |
| 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>
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 158 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/include/atombios.h | 2 | 
3 files changed, 175 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,  		return -EINVAL;  	switch (crev) { +	case 2: +	case 3: +	case 5: +		/* r6xx, r7xx, evergreen, ni, si. +		 * TODO: add support for asic_type <= CHIP_RV770*/ +		if (clock_type == COMPUTE_ENGINE_PLL_PARAM) { +			args.v3.ulClockParams = cpu_to_le32((clock_type << 24) | clock); + +			amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + +			dividers->post_div = args.v3.ucPostDiv; +			dividers->enable_post_div = (args.v3.ucCntlFlag & +						     ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; +			dividers->enable_dithen = (args.v3.ucCntlFlag & +						   ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; +			dividers->whole_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv); +			dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac); +			dividers->ref_div = args.v3.ucRefDiv; +			dividers->vco_mode = (args.v3.ucCntlFlag & +					      ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; +		} else { +			/* for SI we use ComputeMemoryClockParam for memory plls */ +			if (adev->asic_type >= CHIP_TAHITI) +				return -EINVAL; +			args.v5.ulClockParams = cpu_to_le32((clock_type << 24) | clock); +			if (strobe_mode) +				args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN; + +			amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + +			dividers->post_div = args.v5.ucPostDiv; +			dividers->enable_post_div = (args.v5.ucCntlFlag & +						     ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false; +			dividers->enable_dithen = (args.v5.ucCntlFlag & +						   ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true; +			dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv); +			dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac); +			dividers->ref_div = args.v5.ucRefDiv; +			dividers->vco_mode = (args.v5.ucCntlFlag & +					      ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0; +		} +		break;  	case 4:  		/* fusion */  		args.v4.ulClock = cpu_to_le32(clock);	/* 10 khz */ @@ -1122,6 +1164,32 @@ void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,  	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);  } +void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, +					  u16 *vddc, u16 *vddci, u16 *mvdd) +{ +	struct amdgpu_mode_info *mode_info = &adev->mode_info; +	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); +	u8 frev, crev; +	u16 data_offset; +	union firmware_info *firmware_info; + +	*vddc = 0; +	*vddci = 0; +	*mvdd = 0; + +	if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, +				   &frev, &crev, &data_offset)) { +		firmware_info = +			(union firmware_info *)(mode_info->atom_context->bios + +						data_offset); +		*vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); +		if ((frev == 2) && (crev >= 2)) { +			*vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); +			*mvdd = le16_to_cpu(firmware_info->info_22.usBootUpMVDDCVoltage); +		} +	} +} +  union set_voltage {  	struct _SET_VOLTAGE_PS_ALLOCATION alloc;  	struct _SET_VOLTAGE_PARAMETERS v1; @@ -1129,6 +1197,52 @@ union set_voltage {  	struct _SET_VOLTAGE_PARAMETERS_V1_3 v3;  }; +int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, +			     u16 voltage_id, u16 *voltage) +{ +	union set_voltage args; +	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); +	u8 frev, crev; + +	if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev)) +		return -EINVAL; + +	switch (crev) { +	case 1: +		return -EINVAL; +	case 2: +		args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; +		args.v2.ucVoltageMode = 0; +		args.v2.usVoltageLevel = 0; + +		amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + +		*voltage = le16_to_cpu(args.v2.usVoltageLevel); +		break; +	case 3: +		args.v3.ucVoltageType = voltage_type; +		args.v3.ucVoltageMode = ATOM_GET_VOLTAGE_LEVEL; +		args.v3.usVoltageLevel = cpu_to_le16(voltage_id); + +		amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args); + +		*voltage = le16_to_cpu(args.v3.usVoltageLevel); +		break; +	default: +		DRM_ERROR("Unknown table version %d, %d\n", frev, crev); +		return -EINVAL; +	} + +	return 0; +} + +int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, +						      u16 *voltage, +						      u16 leakage_idx) +{ +	return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage); +} +  void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,  				 u16 voltage_level,  				 u8 voltage_type) @@ -1349,6 +1463,50 @@ static ATOM_VOLTAGE_OBJECT_V3 *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOL  	return NULL;  } +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, +			      u8 voltage_type, +			      u8 *svd_gpio_id, u8 *svc_gpio_id) +{ +	int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); +	u8 frev, crev; +	u16 data_offset, size; +	union voltage_object_info *voltage_info; +	union voltage_object *voltage_object = NULL; + +	if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size, +				   &frev, &crev, &data_offset)) { +		voltage_info = (union voltage_object_info *) +			(adev->mode_info.atom_context->bios + data_offset); + +		switch (frev) { +		case 3: +			switch (crev) { +			case 1: +				voltage_object = (union voltage_object *) +					amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, +								      voltage_type, +								      VOLTAGE_OBJ_SVID2); +				if (voltage_object) { +					*svd_gpio_id = voltage_object->v3.asSVID2Obj.ucSVDGpioId; +					*svc_gpio_id = voltage_object->v3.asSVID2Obj.ucSVCGpioId; +				} else { +					return -EINVAL; +				} +				break; +			default: +				DRM_ERROR("unknown voltage object table\n"); +				return -EINVAL; +			} +			break; +		default: +			DRM_ERROR("unknown voltage object table\n"); +			return -EINVAL; +		} + +	} +	return 0; +} +  bool  amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev,  				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);  void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev);  void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); - +int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, +			     u16 voltage_id, u16 *voltage); +int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, +						      u16 *voltage, +						      u16 leakage_idx); +void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, +					  u16 *vddc, u16 *vddci, u16 *mvdd); +int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, +				       u8 clock_type, +				       u32 clock, +				       bool strobe_mode, +				       struct atom_clock_dividers *dividers); +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, +			      u8 voltage_type, +			      u8 *svd_gpio_id, u8 *svc_gpio_id);  #endif diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 3493da5c8f0e..4a4d3797a6d3 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -494,6 +494,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3    union    {      ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter +    ULONG ulClockParams;                      //ULONG access for BE      ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter    };    UCHAR   ucRefDiv;                           //Output Parameter @@ -526,6 +527,7 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5    union    {      ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter +    ULONG ulClockParams;                      //ULONG access for BE      ATOM_S_MPLL_FB_DIVIDER   ulFbDiv;         //Output Parameter    };    UCHAR   ucRefDiv;                           //Output Parameter | 
