[AMD Official Use Only] > -----Original Message----- > From: Lazar, Lijo <Lijo.Lazar@xxxxxxx> > Sent: Wednesday, December 1, 2021 12:19 PM > To: Quan, Evan <Evan.Quan@xxxxxxx>; amd-gfx@xxxxxxxxxxxxxxxxxxxxx > Cc: Deucher, Alexander <Alexander.Deucher@xxxxxxx>; Koenig, Christian > <Christian.Koenig@xxxxxxx>; Feng, Kenneth <Kenneth.Feng@xxxxxxx> > Subject: Re: [PATCH V2 07/17] drm/amd/pm: create a new holder for those > APIs used only by legacy ASICs(si/kv) > > > > On 12/1/2021 8:43 AM, Quan, Evan wrote: > > [AMD Official Use Only] > > > > > > > >> -----Original Message----- > >> From: Lazar, Lijo <Lijo.Lazar@xxxxxxx> > >> Sent: Tuesday, November 30, 2021 9:21 PM > >> To: Quan, Evan <Evan.Quan@xxxxxxx>; amd-gfx@xxxxxxxxxxxxxxxxxxxxx > >> Cc: Deucher, Alexander <Alexander.Deucher@xxxxxxx>; Koenig, > Christian > >> <Christian.Koenig@xxxxxxx>; Feng, Kenneth <Kenneth.Feng@xxxxxxx> > >> Subject: Re: [PATCH V2 07/17] drm/amd/pm: create a new holder for > those > >> APIs used only by legacy ASICs(si/kv) > >> > >> > >> > >> On 11/30/2021 1:12 PM, Evan Quan wrote: > >>> Those APIs are used only by legacy ASICs(si/kv). They cannot be > >>> shared by other ASICs. So, we create a new holder for them. > >>> > >>> Signed-off-by: Evan Quan <evan.quan@xxxxxxx> > >>> Change-Id: I555dfa37e783a267b1d3b3a7db5c87fcc3f1556f > >>> -- > >>> v1->v2: > >>> - move other APIs used by si/kv in amdgpu_atombios.c to the new > >>> holder also(Alex) > >>> --- > >>> drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 421 ----- > >>> drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 30 - > >>> .../gpu/drm/amd/include/kgd_pp_interface.h | 1 + > >>> drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 1008 +----------- > >>> drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 15 - > >>> drivers/gpu/drm/amd/pm/powerplay/Makefile | 2 +- > >>> drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 2 + > >>> drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c | 1453 > >> +++++++++++++++++ > >>> drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h | 70 + > >>> drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 2 + > >>> 10 files changed, 1534 insertions(+), 1470 deletions(-) > >>> create mode 100644 > drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c > >>> create mode 100644 > drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h > >>> > >>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > >>> index 12a6b1c99c93..f2e447212e62 100644 > >>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > >>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c > >>> @@ -1083,427 +1083,6 @@ int > >> amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, > >>> return 0; > >>> } > >>> > >>> -int amdgpu_atombios_get_memory_pll_dividers(struct > amdgpu_device > >> *adev, > >>> - u32 clock, > >>> - bool strobe_mode, > >>> - struct atom_mpll_param > >> *mpll_param) > >>> -{ > >>> - COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 args; > >>> - int index = GetIndexIntoMasterTable(COMMAND, > >> ComputeMemoryClockParam); > >>> - u8 frev, crev; > >>> - > >>> - memset(&args, 0, sizeof(args)); > >>> - memset(mpll_param, 0, sizeof(struct atom_mpll_param)); > >>> - > >>> - if (!amdgpu_atom_parse_cmd_header(adev- > >>> mode_info.atom_context, index, &frev, &crev)) > >>> - return -EINVAL; > >>> - > >>> - switch (frev) { > >>> - case 2: > >>> - switch (crev) { > >>> - case 1: > >>> - /* SI */ > >>> - args.ulClock = cpu_to_le32(clock); /* 10 khz */ > >>> - args.ucInputFlag = 0; > >>> - if (strobe_mode) > >>> - args.ucInputFlag |= > >> MPLL_INPUT_FLAG_STROBE_MODE_EN; > >>> - > >>> - amdgpu_atom_execute_table(adev- > >>> mode_info.atom_context, index, (uint32_t *)&args); > >>> - > >>> - mpll_param->clkfrac = > >> le16_to_cpu(args.ulFbDiv.usFbDivFrac); > >>> - mpll_param->clkf = > >> le16_to_cpu(args.ulFbDiv.usFbDiv); > >>> - mpll_param->post_div = args.ucPostDiv; > >>> - mpll_param->dll_speed = args.ucDllSpeed; > >>> - mpll_param->bwcntl = args.ucBWCntl; > >>> - mpll_param->vco_mode = > >>> - (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_VCO_MODE_MASK); > >>> - mpll_param->yclk_sel = > >>> - (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0; > >>> - mpll_param->qdr = > >>> - (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0; > >>> - mpll_param->half_rate = > >>> - (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0; > >>> - break; > >>> - default: > >>> - return -EINVAL; > >>> - } > >>> - break; > >>> - default: > >>> - return -EINVAL; > >>> - } > >>> - return 0; > >>> -} > >>> - > >>> -void amdgpu_atombios_set_engine_dram_timings(struct > amdgpu_device > >> *adev, > >>> - u32 eng_clock, u32 mem_clock) > >>> -{ > >>> - SET_ENGINE_CLOCK_PS_ALLOCATION args; > >>> - int index = GetIndexIntoMasterTable(COMMAND, > >> DynamicMemorySettings); > >>> - u32 tmp; > >>> - > >>> - memset(&args, 0, sizeof(args)); > >>> - > >>> - tmp = eng_clock & SET_CLOCK_FREQ_MASK; > >>> - tmp |= (COMPUTE_ENGINE_PLL_PARAM << 24); > >>> - > >>> - args.ulTargetEngineClock = cpu_to_le32(tmp); > >>> - if (mem_clock) > >>> - args.sReserved.ulClock = cpu_to_le32(mem_clock & > >> SET_CLOCK_FREQ_MASK); > >>> - > >>> - 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; > >>> - struct _SET_VOLTAGE_PARAMETERS_V2 v2; > >>> - 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); > >>> -} > >>> - > >>> -union voltage_object_info { > >>> - struct _ATOM_VOLTAGE_OBJECT_INFO v1; > >>> - struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; > >>> - struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3; > >>> -}; > >>> - > >>> -union voltage_object { > >>> - struct _ATOM_VOLTAGE_OBJECT v1; > >>> - struct _ATOM_VOLTAGE_OBJECT_V2 v2; > >>> - union _ATOM_VOLTAGE_OBJECT_V3 v3; > >>> -}; > >>> - > >>> - > >>> -static ATOM_VOLTAGE_OBJECT_V3 > >> > *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOLTAGE_OBJECT_I > >> NFO_V3_1 *v3, > >>> - u8 > >> voltage_type, u8 voltage_mode) > >>> -{ > >>> - u32 size = le16_to_cpu(v3->sHeader.usStructureSize); > >>> - u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, > >> asVoltageObj[0]); > >>> - u8 *start = (u8 *)v3; > >>> - > >>> - while (offset < size) { > >>> - ATOM_VOLTAGE_OBJECT_V3 *vo = > >> (ATOM_VOLTAGE_OBJECT_V3 *)(start + offset); > >>> - if ((vo->asGpioVoltageObj.sHeader.ucVoltageType == > >> voltage_type) && > >>> - (vo->asGpioVoltageObj.sHeader.ucVoltageMode == > >> voltage_mode)) > >>> - return vo; > >>> - offset += le16_to_cpu(vo- > >>> asGpioVoltageObj.sHeader.usSize); > >>> - } > >>> - 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) > >>> -{ > >>> - int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); > >>> - u8 frev, crev; > >>> - u16 data_offset, size; > >>> - union voltage_object_info *voltage_info; > >>> - > >>> - 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: > >>> - if > >> (amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, > >>> - > >> voltage_type, voltage_mode)) > >>> - return true; > >>> - break; > >>> - default: > >>> - DRM_ERROR("unknown voltage object > >> table\n"); > >>> - return false; > >>> - } > >>> - break; > >>> - default: > >>> - DRM_ERROR("unknown voltage object table\n"); > >>> - return false; > >>> - } > >>> - > >>> - } > >>> - return false; > >>> -} > >>> - > >>> -int amdgpu_atombios_get_voltage_table(struct amdgpu_device *adev, > >>> - u8 voltage_type, u8 voltage_mode, > >>> - struct atom_voltage_table *voltage_table) > >>> -{ > >>> - int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); > >>> - u8 frev, crev; > >>> - u16 data_offset, size; > >>> - int i; > >>> - 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_mode); > >>> - if (voltage_object) { > >>> - ATOM_GPIO_VOLTAGE_OBJECT_V3 > >> *gpio = > >>> - &voltage_object- > >>> v3.asGpioVoltageObj; > >>> - VOLTAGE_LUT_ENTRY_V2 *lut; > >>> - if (gpio->ucGpioEntryNum > > >> MAX_VOLTAGE_ENTRIES) > >>> - return -EINVAL; > >>> - lut = &gpio->asVolGpioLut[0]; > >>> - for (i = 0; i < gpio->ucGpioEntryNum; > >> i++) { > >>> - voltage_table- > >>> entries[i].value = > >>> - le16_to_cpu(lut- > >>> usVoltageValue); > >>> - voltage_table- > >>> entries[i].smio_low = > >>> - le32_to_cpu(lut- > >>> ulVoltageId); > >>> - lut = > >> (VOLTAGE_LUT_ENTRY_V2 *) > >>> - ((u8 *)lut + > >> sizeof(VOLTAGE_LUT_ENTRY_V2)); > >>> - } > >>> - voltage_table->mask_low = > >> le32_to_cpu(gpio->ulGpioMaskVal); > >>> - voltage_table->count = gpio- > >>> ucGpioEntryNum; > >>> - voltage_table->phase_delay = gpio- > >>> ucPhaseDelay; > >>> - return 0; > >>> - } > >>> - break; > >>> - default: > >>> - DRM_ERROR("unknown voltage object > >> table\n"); > >>> - return -EINVAL; > >>> - } > >>> - break; > >>> - default: > >>> - DRM_ERROR("unknown voltage object table\n"); > >>> - return -EINVAL; > >>> - } > >>> - } > >>> - return -EINVAL; > >>> -} > >>> - > >>> -union vram_info { > >>> - struct _ATOM_VRAM_INFO_V3 v1_3; > >>> - struct _ATOM_VRAM_INFO_V4 v1_4; > >>> - struct _ATOM_VRAM_INFO_HEADER_V2_1 v2_1; > >>> -}; > >>> - > >>> -#define MEM_ID_MASK 0xff000000 > >>> -#define MEM_ID_SHIFT 24 > >>> -#define CLOCK_RANGE_MASK 0x00ffffff > >>> -#define CLOCK_RANGE_SHIFT 0 > >>> -#define LOW_NIBBLE_MASK 0xf > >>> -#define DATA_EQU_PREV 0 > >>> -#define DATA_FROM_TABLE 4 > >>> - > >>> -int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev, > >>> - u8 module_index, > >>> - struct atom_mc_reg_table *reg_table) > >>> -{ > >>> - int index = GetIndexIntoMasterTable(DATA, VRAM_Info); > >>> - u8 frev, crev, num_entries, t_mem_id, num_ranges = 0; > >>> - u32 i = 0, j; > >>> - u16 data_offset, size; > >>> - union vram_info *vram_info; > >>> - > >>> - memset(reg_table, 0, sizeof(struct atom_mc_reg_table)); > >>> - > >>> - if (amdgpu_atom_parse_data_header(adev- > >>> mode_info.atom_context, index, &size, > >>> - &frev, &crev, &data_offset)) { > >>> - vram_info = (union vram_info *) > >>> - (adev->mode_info.atom_context->bios + > >> data_offset); > >>> - switch (frev) { > >>> - case 1: > >>> - DRM_ERROR("old table version %d, %d\n", frev, > >> crev); > >>> - return -EINVAL; > >>> - case 2: > >>> - switch (crev) { > >>> - case 1: > >>> - if (module_index < vram_info- > >>> v2_1.ucNumOfVRAMModule) { > >>> - ATOM_INIT_REG_BLOCK *reg_block > >> = > >>> - (ATOM_INIT_REG_BLOCK *) > >>> - ((u8 *)vram_info + > >> le16_to_cpu(vram_info->v2_1.usMemClkPatchTblOffset)); > >>> - > >> ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = > >>> - > >> (ATOM_MEMORY_SETTING_DATA_BLOCK *) > >>> - ((u8 *)reg_block + (2 * > >> sizeof(u16)) + > >>> - le16_to_cpu(reg_block- > >>> usRegIndexTblSize)); > >>> - ATOM_INIT_REG_INDEX_FORMAT > >> *format = ®_block->asRegIndexBuf[0]; > >>> - num_entries = > >> (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) / > >>> - > >> sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1; > >>> - if (num_entries > > >> VBIOS_MC_REGISTER_ARRAY_SIZE) > >>> - return -EINVAL; > >>> - while (i < num_entries) { > >>> - if (format- > >>> ucPreRegDataLength & ACCESS_PLACEHOLDER) > >>> - break; > >>> - reg_table- > >>> mc_reg_address[i].s1 = > >>> - > >> (u16)(le16_to_cpu(format->usRegIndex)); > >>> - reg_table- > >>> mc_reg_address[i].pre_reg_data = > >>> - (u8)(format- > >>> ucPreRegDataLength); > >>> - i++; > >>> - format = > >> (ATOM_INIT_REG_INDEX_FORMAT *) > >>> - ((u8 *)format + > >> sizeof(ATOM_INIT_REG_INDEX_FORMAT)); > >>> - } > >>> - reg_table->last = i; > >>> - while ((le32_to_cpu(*(u32 > >> *)reg_data) != END_OF_REG_DATA_BLOCK) && > >>> - (num_ranges < > >> VBIOS_MAX_AC_TIMING_ENTRIES)) { > >>> - t_mem_id = > >> (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK) > >>> - >> > >> MEM_ID_SHIFT); > >>> - if (module_index == > >> t_mem_id) { > >>> - reg_table- > >>> mc_reg_table_entry[num_ranges].mclk_max = > >>> - > >> (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK) > >>> - >> > >> CLOCK_RANGE_SHIFT); > >>> - for (i = 0, j = 1; i < > >> reg_table->last; i++) { > >>> - if ((reg_table- > >>> mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == > >> DATA_FROM_TABLE) { > >>> - > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = > >>> - > >> (u32)le32_to_cpu(*((u32 *)reg_data + j)); > >>> - j++; > >>> - } else if > >> ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == > >> DATA_EQU_PREV) { > >>> - > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = > >>> - > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1]; > >>> - } > >>> - } > >>> - num_ranges++; > >>> - } > >>> - reg_data = > >> (ATOM_MEMORY_SETTING_DATA_BLOCK *) > >>> - ((u8 *)reg_data + > >> le16_to_cpu(reg_block->usRegDataBlkSize)); > >>> - } > >>> - if (le32_to_cpu(*(u32 *)reg_data) != > >> END_OF_REG_DATA_BLOCK) > >>> - return -EINVAL; > >>> - reg_table->num_entries = > >> num_ranges; > >>> - } else > >>> - return -EINVAL; > >>> - break; > >>> - default: > >>> - DRM_ERROR("Unknown table > >> version %d, %d\n", frev, crev); > >>> - return -EINVAL; > >>> - } > >>> - break; > >>> - default: > >>> - DRM_ERROR("Unknown table version %d, %d\n", > >> frev, crev); > >>> - return -EINVAL; > >>> - } > >>> - return 0; > >>> - } > >>> - return -EINVAL; > >>> -} > >>> - > >>> bool amdgpu_atombios_has_gpu_virtualization_table(struct > >> amdgpu_device *adev) > >>> { > >>> int index = GetIndexIntoMasterTable(DATA, GPUVirtualizationInfo); > >>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h > >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h > >>> index 27e74b1fc260..cb5649298dcb 100644 > >>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h > >>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h > >>> @@ -160,26 +160,6 @@ int > amdgpu_atombios_get_clock_dividers(struct > >> amdgpu_device *adev, > >>> bool strobe_mode, > >>> struct atom_clock_dividers *dividers); > >>> > >>> -int amdgpu_atombios_get_memory_pll_dividers(struct > amdgpu_device > >> *adev, > >>> - u32 clock, > >>> - bool strobe_mode, > >>> - struct atom_mpll_param > >> *mpll_param); > >>> - > >>> -void amdgpu_atombios_set_engine_dram_timings(struct > amdgpu_device > >> *adev, > >>> - u32 eng_clock, u32 mem_clock); > >>> - > >>> -bool > >>> -amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev, > >>> - u8 voltage_type, u8 voltage_mode); > >>> - > >>> -int amdgpu_atombios_get_voltage_table(struct amdgpu_device *adev, > >>> - u8 voltage_type, u8 voltage_mode, > >>> - struct atom_voltage_table > >> *voltage_table); > >>> - > >>> -int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev, > >>> - u8 module_index, > >>> - struct atom_mc_reg_table *reg_table); > >>> - > >>> bool amdgpu_atombios_has_gpu_virtualization_table(struct > >> amdgpu_device *adev); > >>> > >>> void amdgpu_atombios_scratch_regs_lock(struct amdgpu_device > *adev, > >> bool lock); > >>> @@ -190,21 +170,11 @@ void > >> amdgpu_atombios_scratch_regs_set_backlight_level(struct > amdgpu_device > >> *adev > >>> bool amdgpu_atombios_scratch_need_asic_init(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); > >>> > >>> int amdgpu_atombios_get_data_table(struct amdgpu_device *adev, > >>> uint32_t table, > >> > >> > >> Whether used in legacy or new logic, atombios table parsing/execution > >> should be kept as separate logic. These shouldn't be moved along with > dpm. > > [Quan, Evan] Are you suggesting another place holder for those atombios > APIs? Like legacy_atombios.c? > > What I meant is no need to move them, keep it in the same file. We also > have atomfirmware, splitting this and adding another legacy_atombios is > not required. [Quan, Evan] Hmm, that seems contrary to Alex' suggestions. Although I'm fine with either. I kind of prefer Alex's suggestions. That is if they are destined to be dropped(together with SI/KV support), we should get them separated now. BR Evan > > >> > >> > >>> diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h > >> b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > >>> index 2e295facd086..cdf724dcf832 100644 > >>> --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h > >>> +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h > >>> @@ -404,6 +404,7 @@ struct amd_pm_funcs { > >>> int (*get_dpm_clock_table)(void *handle, > >>> struct dpm_clocks *clock_table); > >>> int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t > >> *size); > >>> + int (*change_power_state)(void *handle); > >>> }; > >>> > >>> struct metrics_table_header { > >>> diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c > >> b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c > >>> index ecaf0081bc31..c6801d10cde6 100644 > >>> --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c > >>> +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c > >>> @@ -34,113 +34,9 @@ > >>> > >>> #define WIDTH_4K 3840 > >>> > >>> -#define amdgpu_dpm_pre_set_power_state(adev) \ > >>> - ((adev)->powerplay.pp_funcs- > >>> pre_set_power_state((adev)->powerplay.pp_handle)) > >>> - > >>> -#define amdgpu_dpm_post_set_power_state(adev) \ > >>> - ((adev)->powerplay.pp_funcs- > >>> post_set_power_state((adev)->powerplay.pp_handle)) > >>> - > >>> -#define amdgpu_dpm_display_configuration_changed(adev) \ > >>> - ((adev)->powerplay.pp_funcs- > >>> display_configuration_changed((adev)->powerplay.pp_handle)) > >>> - > >>> -#define amdgpu_dpm_print_power_state(adev, ps) \ > >>> - ((adev)->powerplay.pp_funcs->print_power_state((adev)- > >>> powerplay.pp_handle, (ps))) > >>> - > >>> -#define amdgpu_dpm_vblank_too_short(adev) \ > >>> - ((adev)->powerplay.pp_funcs->vblank_too_short((adev)- > >>> powerplay.pp_handle)) > >>> - > >>> #define amdgpu_dpm_enable_bapm(adev, e) \ > >>> ((adev)->powerplay.pp_funcs->enable_bapm((adev)- > >>> powerplay.pp_handle, (e))) > >>> > >>> -#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ > >>> - ((adev)->powerplay.pp_funcs->check_state_equal((adev)- > >>> powerplay.pp_handle, (cps), (rps), (equal))) > >>> - > >>> -void amdgpu_dpm_print_class_info(u32 class, u32 class2) > >>> -{ > >>> - const char *s; > >>> - > >>> - switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { > >>> - case ATOM_PPLIB_CLASSIFICATION_UI_NONE: > >>> - default: > >>> - s = "none"; > >>> - break; > >>> - case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: > >>> - s = "battery"; > >>> - break; > >>> - case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: > >>> - s = "balanced"; > >>> - break; > >>> - case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: > >>> - s = "performance"; > >>> - break; > >>> - } > >>> - printk("\tui class: %s\n", s); > >>> - printk("\tinternal class:"); > >>> - if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && > >>> - (class2 == 0)) > >>> - pr_cont(" none"); > >>> - else { > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) > >>> - pr_cont(" boot"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) > >>> - pr_cont(" thermal"); > >>> - if (class & > >> ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) > >>> - pr_cont(" limited_pwr"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_REST) > >>> - pr_cont(" rest"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) > >>> - pr_cont(" forced"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) > >>> - pr_cont(" 3d_perf"); > >>> - if (class & > >> ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) > >>> - pr_cont(" ovrdrv"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) > >>> - pr_cont(" uvd"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) > >>> - pr_cont(" 3d_low"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) > >>> - pr_cont(" acpi"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) > >>> - pr_cont(" uvd_hd2"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) > >>> - pr_cont(" uvd_hd"); > >>> - if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) > >>> - pr_cont(" uvd_sd"); > >>> - if (class2 & > >> ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) > >>> - pr_cont(" limited_pwr2"); > >>> - if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) > >>> - pr_cont(" ulv"); > >>> - if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) > >>> - pr_cont(" uvd_mvc"); > >>> - } > >>> - pr_cont("\n"); > >>> -} > >>> - > >>> -void amdgpu_dpm_print_cap_info(u32 caps) > >>> -{ > >>> - printk("\tcaps:"); > >>> - if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) > >>> - pr_cont(" single_disp"); > >>> - if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) > >>> - pr_cont(" video"); > >>> - if (caps & ATOM_PPLIB_DISALLOW_ON_DC) > >>> - pr_cont(" no_dc"); > >>> - pr_cont("\n"); > >>> -} > >>> - > >>> -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, > >>> - struct amdgpu_ps *rps) > >>> -{ > >>> - printk("\tstatus:"); > >>> - if (rps == adev->pm.dpm.current_ps) > >>> - pr_cont(" c"); > >>> - if (rps == adev->pm.dpm.requested_ps) > >>> - pr_cont(" r"); > >>> - if (rps == adev->pm.dpm.boot_ps) > >>> - pr_cont(" b"); > >>> - pr_cont("\n"); > >>> -} > >>> - > >>> static void amdgpu_dpm_get_active_displays(struct amdgpu_device > >> *adev) > >>> { > >>> struct drm_device *ddev = adev_to_drm(adev); > >>> @@ -161,7 +57,6 @@ static void > amdgpu_dpm_get_active_displays(struct > >> amdgpu_device *adev) > >>> } > >>> } > >>> > >>> - > >>> u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) > >>> { > >>> struct drm_device *dev = adev_to_drm(adev); > >>> @@ -209,679 +104,6 @@ static u32 amdgpu_dpm_get_vrefresh(struct > >> amdgpu_device *adev) > >>> return vrefresh; > >>> } > >>> > >>> -union power_info { > >>> - struct _ATOM_POWERPLAY_INFO info; > >>> - struct _ATOM_POWERPLAY_INFO_V2 info_2; > >>> - struct _ATOM_POWERPLAY_INFO_V3 info_3; > >>> - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; > >>> - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; > >>> - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; > >>> - struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; > >>> - struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; > >>> -}; > >>> - > >>> -union fan_info { > >>> - struct _ATOM_PPLIB_FANTABLE fan; > >>> - struct _ATOM_PPLIB_FANTABLE2 fan2; > >>> - struct _ATOM_PPLIB_FANTABLE3 fan3; > >>> -}; > >>> - > >>> -static int amdgpu_parse_clk_voltage_dep_table(struct > >> amdgpu_clock_voltage_dependency_table *amdgpu_table, > >>> - > >> ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) > >>> -{ > >>> - u32 size = atom_table->ucNumEntries * > >>> - sizeof(struct amdgpu_clock_voltage_dependency_entry); > >>> - int i; > >>> - ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; > >>> - > >>> - amdgpu_table->entries = kzalloc(size, GFP_KERNEL); > >>> - if (!amdgpu_table->entries) > >>> - return -ENOMEM; > >>> - > >>> - entry = &atom_table->entries[0]; > >>> - for (i = 0; i < atom_table->ucNumEntries; i++) { > >>> - amdgpu_table->entries[i].clk = le16_to_cpu(entry- > >>> usClockLow) | > >>> - (entry->ucClockHigh << 16); > >>> - amdgpu_table->entries[i].v = le16_to_cpu(entry- > >>> usVoltage); > >>> - entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record > >> *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); > >>> - } > >>> - amdgpu_table->count = atom_table->ucNumEntries; > >>> - > >>> - return 0; > >>> -} > >>> - > >>> -int amdgpu_get_platform_caps(struct amdgpu_device *adev) > >>> -{ > >>> - struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> - union power_info *power_info; > >>> - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> - u16 data_offset; > >>> - u8 frev, crev; > >>> - > >>> - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> - &frev, &crev, &data_offset)) > >>> - return -EINVAL; > >>> - power_info = (union power_info *)(mode_info->atom_context- > >>> bios + data_offset); > >>> - > >>> - adev->pm.dpm.platform_caps = le32_to_cpu(power_info- > >>> pplib.ulPlatformCaps); > >>> - adev->pm.dpm.backbias_response_time = > >> le16_to_cpu(power_info->pplib.usBackbiasTime); > >>> - adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info- > >>> pplib.usVoltageTime); > >>> - > >>> - return 0; > >>> -} > >>> - > >>> -/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 > >>> -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 > >>> - > >>> -int amdgpu_parse_extended_power_table(struct amdgpu_device > *adev) > >>> -{ > >>> - struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> - union power_info *power_info; > >>> - union fan_info *fan_info; > >>> - ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; > >>> - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> - u16 data_offset; > >>> - u8 frev, crev; > >>> - int ret, i; > >>> - > >>> - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> - &frev, &crev, &data_offset)) > >>> - return -EINVAL; > >>> - power_info = (union power_info *)(mode_info->atom_context- > >>> bios + data_offset); > >>> - > >>> - /* fan table */ > >>> - if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { > >>> - if (power_info->pplib3.usFanTableOffset) { > >>> - fan_info = (union fan_info *)(mode_info- > >>> atom_context->bios + data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib3.usFanTableOffset)); > >>> - adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; > >>> - adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info- > >>> fan.usTMin); > >>> - adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info- > >>> fan.usTMed); > >>> - adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info- > >>> fan.usTHigh); > >>> - adev->pm.dpm.fan.pwm_min = > >> le16_to_cpu(fan_info->fan.usPWMMin); > >>> - adev->pm.dpm.fan.pwm_med = > >> le16_to_cpu(fan_info->fan.usPWMMed); > >>> - adev->pm.dpm.fan.pwm_high = > >> le16_to_cpu(fan_info->fan.usPWMHigh); > >>> - if (fan_info->fan.ucFanTableFormat >= 2) > >>> - adev->pm.dpm.fan.t_max = > >> le16_to_cpu(fan_info->fan2.usTMax); > >>> - else > >>> - adev->pm.dpm.fan.t_max = 10900; > >>> - adev->pm.dpm.fan.cycle_delay = 100000; > >>> - if (fan_info->fan.ucFanTableFormat >= 3) { > >>> - adev->pm.dpm.fan.control_mode = > >> fan_info->fan3.ucFanControlMode; > >>> - adev->pm.dpm.fan.default_max_fan_pwm > >> = > >>> - le16_to_cpu(fan_info- > >>> fan3.usFanPWMMax); > >>> - adev- > >>> pm.dpm.fan.default_fan_output_sensitivity = 4836; > >>> - adev->pm.dpm.fan.fan_output_sensitivity = > >>> - le16_to_cpu(fan_info- > >>> fan3.usFanOutputSensitivity); > >>> - } > >>> - adev->pm.dpm.fan.ucode_fan_control = true; > >>> - } > >>> - } > >>> - > >>> - /* clock dependancy tables, shedding tables */ > >>> - if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { > >>> - if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { > >>> - dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usVddcDependencyOnSCLKOffset)); > >>> - ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddc_dependency_on_sclk, > >>> - dep_table); > >>> - if (ret) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return ret; > >>> - } > >>> - } > >>> - if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { > >>> - dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usVddciDependencyOnMCLKOffset)); > >>> - ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddci_dependency_on_mclk, > >>> - dep_table); > >>> - if (ret) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return ret; > >>> - } > >>> - } > >>> - if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { > >>> - dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usVddcDependencyOnMCLKOffset)); > >>> - ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddc_dependency_on_mclk, > >>> - dep_table); > >>> - if (ret) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return ret; > >>> - } > >>> - } > >>> - if (power_info->pplib4.usMvddDependencyOnMCLKOffset) > >> { > >>> - dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usMvddDependencyOnMCLKOffset)); > >>> - ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.mvdd_dependency_on_mclk, > >>> - dep_table); > >>> - if (ret) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return ret; > >>> - } > >>> - } > >>> - if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { > >>> - ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = > >>> - (ATOM_PPLIB_Clock_Voltage_Limit_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usMaxClockVoltageOnDCOffset)); > >>> - if (clk_v->ucNumEntries) { > >>> - adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = > >>> - le16_to_cpu(clk_v- > >>> entries[0].usSclkLow) | > >>> - (clk_v->entries[0].ucSclkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = > >>> - le16_to_cpu(clk_v- > >>> entries[0].usMclkLow) | > >>> - (clk_v->entries[0].ucMclkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = > >>> - le16_to_cpu(clk_v- > >>> entries[0].usVddc); > >>> - adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = > >>> - le16_to_cpu(clk_v- > >>> entries[0].usVddci); > >>> - } > >>> - } > >>> - if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) > >> { > >>> - ATOM_PPLIB_PhaseSheddingLimits_Table *psl = > >>> - (ATOM_PPLIB_PhaseSheddingLimits_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib4.usVddcPhaseShedLimitsTableOffset)); > >>> - ATOM_PPLIB_PhaseSheddingLimits_Record *entry; > >>> - > >>> - adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries = > >>> - kcalloc(psl->ucNumEntries, > >>> - sizeof(struct > >> amdgpu_phase_shedding_limits_entry), > >>> - GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - > >>> - entry = &psl->entries[0]; > >>> - for (i = 0; i < psl->ucNumEntries; i++) { > >>> - adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = > >>> - le16_to_cpu(entry->usSclkLow) | > >> (entry->ucSclkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = > >>> - le16_to_cpu(entry->usMclkLow) | > >> (entry->ucMclkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = > >>> - le16_to_cpu(entry->usVoltage); > >>> - entry = > >> (ATOM_PPLIB_PhaseSheddingLimits_Record *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); > >>> - } > >>> - adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.count = > >>> - psl->ucNumEntries; > >>> - } > >>> - } > >>> - > >>> - /* cac data */ > >>> - if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { > >>> - adev->pm.dpm.tdp_limit = le32_to_cpu(power_info- > >>> pplib5.ulTDPLimit); > >>> - adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info- > >>> pplib5.ulNearTDPLimit); > >>> - adev->pm.dpm.near_tdp_limit_adjusted = adev- > >>> pm.dpm.near_tdp_limit; > >>> - adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info- > >>> pplib5.usTDPODLimit); > >>> - if (adev->pm.dpm.tdp_od_limit) > >>> - adev->pm.dpm.power_control = true; > >>> - else > >>> - adev->pm.dpm.power_control = false; > >>> - adev->pm.dpm.tdp_adjustment = 0; > >>> - adev->pm.dpm.sq_ramping_threshold = > >> le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); > >>> - adev->pm.dpm.cac_leakage = le32_to_cpu(power_info- > >>> pplib5.ulCACLeakage); > >>> - adev->pm.dpm.load_line_slope = le16_to_cpu(power_info- > >>> pplib5.usLoadLineSlope); > >>> - if (power_info->pplib5.usCACLeakageTableOffset) { > >>> - ATOM_PPLIB_CAC_Leakage_Table *cac_table = > >>> - (ATOM_PPLIB_CAC_Leakage_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib5.usCACLeakageTableOffset)); > >>> - ATOM_PPLIB_CAC_Leakage_Record *entry; > >>> - u32 size = cac_table->ucNumEntries * sizeof(struct > >> amdgpu_cac_leakage_table); > >>> - adev->pm.dpm.dyn_state.cac_leakage_table.entries > >> = kzalloc(size, GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - entry = &cac_table->entries[0]; > >>> - for (i = 0; i < cac_table->ucNumEntries; i++) { > >>> - if (adev->pm.dpm.platform_caps & > >> ATOM_PP_PLATFORM_CAP_EVV) { > >>> - adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = > >>> - le16_to_cpu(entry- > >>> usVddc1); > >>> - adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = > >>> - le16_to_cpu(entry- > >>> usVddc2); > >>> - adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = > >>> - le16_to_cpu(entry- > >>> usVddc3); > >>> - } else { > >>> - adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = > >>> - le16_to_cpu(entry->usVddc); > >>> - adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = > >>> - le32_to_cpu(entry- > >>> ulLeakageValue); > >>> - } > >>> - entry = (ATOM_PPLIB_CAC_Leakage_Record > >> *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_CAC_Leakage_Record)); > >>> - } > >>> - adev->pm.dpm.dyn_state.cac_leakage_table.count > >> = cac_table->ucNumEntries; > >>> - } > >>> - } > >>> - > >>> - /* ext tables */ > >>> - if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { > >>> - ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = > >> (ATOM_PPLIB_EXTENDEDHEADER *) > >>> - (mode_info->atom_context->bios + data_offset + > >>> - le16_to_cpu(power_info- > >>> pplib3.usExtendendedHeaderOffset)); > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && > >>> - ext_hdr->usVCETableOffset) { > >>> - VCEClockInfoArray *array = (VCEClockInfoArray *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1); > >>> - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table > >> *limits = > >>> - > >> (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1 + > >>> - 1 + array->ucNumEntries * > >> sizeof(VCEClockInfo)); > >>> - ATOM_PPLIB_VCE_State_Table *states = > >>> - (ATOM_PPLIB_VCE_State_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1 + > >>> - 1 + (array->ucNumEntries * sizeof > >> (VCEClockInfo)) + > >>> - 1 + (limits->numEntries * > >> sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); > >>> - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record > >> *entry; > >>> - ATOM_PPLIB_VCE_State_Record *state_entry; > >>> - VCEClockInfo *vce_clk; > >>> - u32 size = limits->numEntries * > >>> - sizeof(struct > >> amdgpu_vce_clock_voltage_dependency_entry); > >>> - adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = > >>> - kzalloc(size, GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = > >>> - limits->numEntries; > >>> - entry = &limits->entries[0]; > >>> - state_entry = &states->entries[0]; > >>> - for (i = 0; i < limits->numEntries; i++) { > >>> - vce_clk = (VCEClockInfo *) > >>> - ((u8 *)&array->entries[0] + > >>> - (entry->ucVCEClockInfoIndex * > >> sizeof(VCEClockInfo))); > >>> - adev- > >>> > pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk > >> = > >>> - le16_to_cpu(vce_clk->usEVClkLow) | > >> (vce_clk->ucEVClkHigh << 16); > >>> - adev- > >>> > pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk > >> = > >>> - le16_to_cpu(vce_clk->usECClkLow) | > >> (vce_clk->ucECClkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = > >>> - le16_to_cpu(entry->usVoltage); > >>> - entry = > >> (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); > >>> - } > >>> - adev->pm.dpm.num_of_vce_states = > >>> - states->numEntries > > >> AMD_MAX_VCE_LEVELS ? > >>> - AMD_MAX_VCE_LEVELS : states- > >>> numEntries; > >>> - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) > >> { > >>> - vce_clk = (VCEClockInfo *) > >>> - ((u8 *)&array->entries[0] + > >>> - (state_entry->ucVCEClockInfoIndex > >> * sizeof(VCEClockInfo))); > >>> - adev->pm.dpm.vce_states[i].evclk = > >>> - le16_to_cpu(vce_clk->usEVClkLow) | > >> (vce_clk->ucEVClkHigh << 16); > >>> - adev->pm.dpm.vce_states[i].ecclk = > >>> - le16_to_cpu(vce_clk->usECClkLow) | > >> (vce_clk->ucECClkHigh << 16); > >>> - adev->pm.dpm.vce_states[i].clk_idx = > >>> - state_entry->ucClockInfoIndex & > >> 0x3f; > >>> - adev->pm.dpm.vce_states[i].pstate = > >>> - (state_entry->ucClockInfoIndex & > >> 0xc0) >> 6; > >>> - state_entry = > >> (ATOM_PPLIB_VCE_State_Record *) > >>> - ((u8 *)state_entry + > >> sizeof(ATOM_PPLIB_VCE_State_Record)); > >>> - } > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && > >>> - ext_hdr->usUVDTableOffset) { > >>> - UVDClockInfoArray *array = (UVDClockInfoArray *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usUVDTableOffset) + > >> 1); > >>> - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table > >> *limits = > >>> - > >> (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usUVDTableOffset) + > >> 1 + > >>> - 1 + (array->ucNumEntries * sizeof > >> (UVDClockInfo))); > >>> - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record > >> *entry; > >>> - u32 size = limits->numEntries * > >>> - sizeof(struct > >> amdgpu_uvd_clock_voltage_dependency_entry); > >>> - adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = > >>> - kzalloc(size, GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = > >>> - limits->numEntries; > >>> - entry = &limits->entries[0]; > >>> - for (i = 0; i < limits->numEntries; i++) { > >>> - UVDClockInfo *uvd_clk = (UVDClockInfo *) > >>> - ((u8 *)&array->entries[0] + > >>> - (entry->ucUVDClockInfoIndex * > >> sizeof(UVDClockInfo))); > >>> - adev- > >>> > pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = > >>> - le16_to_cpu(uvd_clk->usVClkLow) | > >> (uvd_clk->ucVClkHigh << 16); > >>> - adev- > >>> > pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = > >>> - le16_to_cpu(uvd_clk->usDClkLow) | > >> (uvd_clk->ucDClkHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = > >>> - le16_to_cpu(entry->usVoltage); > >>> - entry = > >> (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); > >>> - } > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && > >>> - ext_hdr->usSAMUTableOffset) { > >>> - ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = > >>> - (ATOM_PPLIB_SAMClk_Voltage_Limit_Table > >> *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usSAMUTableOffset) > >> + 1); > >>> - ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; > >>> - u32 size = limits->numEntries * > >>> - sizeof(struct > >> amdgpu_clock_voltage_dependency_entry); > >>> - adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = > >>> - kzalloc(size, GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = > >>> - limits->numEntries; > >>> - entry = &limits->entries[0]; > >>> - for (i = 0; i < limits->numEntries; i++) { > >>> - adev- > >>> > pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = > >>> - le16_to_cpu(entry->usSAMClockLow) > >> | (entry->ucSAMClockHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v > = > >>> - le16_to_cpu(entry->usVoltage); > >>> - entry = > >> (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); > >>> - } > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && > >>> - ext_hdr->usPPMTableOffset) { > >>> - ATOM_PPLIB_PPM_Table *ppm = > >> (ATOM_PPLIB_PPM_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usPPMTableOffset)); > >>> - adev->pm.dpm.dyn_state.ppm_table = > >>> - kzalloc(sizeof(struct amdgpu_ppm_table), > >> GFP_KERNEL); > >>> - if (!adev->pm.dpm.dyn_state.ppm_table) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - adev->pm.dpm.dyn_state.ppm_table->ppm_design > >> = ppm->ucPpmDesign; > >>> - adev->pm.dpm.dyn_state.ppm_table- > >>> cpu_core_number = > >>> - le16_to_cpu(ppm->usCpuCoreNumber); > >>> - adev->pm.dpm.dyn_state.ppm_table- > >>> platform_tdp = > >>> - le32_to_cpu(ppm->ulPlatformTDP); > >>> - adev->pm.dpm.dyn_state.ppm_table- > >>> small_ac_platform_tdp = > >>> - le32_to_cpu(ppm->ulSmallACPlatformTDP); > >>> - adev->pm.dpm.dyn_state.ppm_table->platform_tdc > >> = > >>> - le32_to_cpu(ppm->ulPlatformTDC); > >>> - adev->pm.dpm.dyn_state.ppm_table- > >>> small_ac_platform_tdc = > >>> - le32_to_cpu(ppm->ulSmallACPlatformTDC); > >>> - adev->pm.dpm.dyn_state.ppm_table->apu_tdp = > >>> - le32_to_cpu(ppm->ulApuTDP); > >>> - adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = > >>> - le32_to_cpu(ppm->ulDGpuTDP); > >>> - adev->pm.dpm.dyn_state.ppm_table- > >>> dgpu_ulv_power = > >>> - le32_to_cpu(ppm->ulDGpuUlvPower); > >>> - adev->pm.dpm.dyn_state.ppm_table->tj_max = > >>> - le32_to_cpu(ppm->ulTjmax); > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && > >>> - ext_hdr->usACPTableOffset) { > >>> - ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = > >>> - (ATOM_PPLIB_ACPClk_Voltage_Limit_Table > >> *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr->usACPTableOffset) + > >> 1); > >>> - ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; > >>> - u32 size = limits->numEntries * > >>> - sizeof(struct > >> amdgpu_clock_voltage_dependency_entry); > >>> - adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = > >>> - kzalloc(size, GFP_KERNEL); > >>> - if (!adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = > >>> - limits->numEntries; > >>> - entry = &limits->entries[0]; > >>> - for (i = 0; i < limits->numEntries; i++) { > >>> - adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk > = > >>> - le16_to_cpu(entry->usACPClockLow) > >> | (entry->ucACPClockHigh << 16); > >>> - adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = > >>> - le16_to_cpu(entry->usVoltage); > >>> - entry = > >> (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) > >>> - ((u8 *)entry + > >> sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); > >>> - } > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && > >>> - ext_hdr->usPowerTuneTableOffset) { > >>> - u8 rev = *(u8 *)(mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> - ATOM_PowerTune_Table *pt; > >>> - adev->pm.dpm.dyn_state.cac_tdp_table = > >>> - kzalloc(sizeof(struct amdgpu_cac_tdp_table), > >> GFP_KERNEL); > >>> - if (!adev->pm.dpm.dyn_state.cac_tdp_table) { > >>> - > >> amdgpu_free_extended_power_table(adev); > >>> - return -ENOMEM; > >>> - } > >>> - if (rev > 0) { > >>> - ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = > >> (ATOM_PPLIB_POWERTUNE_Table_V1 *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> maximum_power_delivery_limit = > >>> - ppt->usMaximumPowerDeliveryLimit; > >>> - pt = &ppt->power_tune_table; > >>> - } else { > >>> - ATOM_PPLIB_POWERTUNE_Table *ppt = > >> (ATOM_PPLIB_POWERTUNE_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> maximum_power_delivery_limit = 255; > >>> - pt = &ppt->power_tune_table; > >>> - } > >>> - adev->pm.dpm.dyn_state.cac_tdp_table->tdp = > >> le16_to_cpu(pt->usTDP); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> configurable_tdp = > >>> - le16_to_cpu(pt->usConfigurableTDP); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table->tdc = > >> le16_to_cpu(pt->usTDC); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> battery_power_limit = > >>> - le16_to_cpu(pt->usBatteryPowerLimit); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> small_power_limit = > >>> - le16_to_cpu(pt->usSmallPowerLimit); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> low_cac_leakage = > >>> - le16_to_cpu(pt->usLowCACLeakage); > >>> - adev->pm.dpm.dyn_state.cac_tdp_table- > >>> high_cac_leakage = > >>> - le16_to_cpu(pt->usHighCACLeakage); > >>> - } > >>> - if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && > >>> - ext_hdr->usSclkVddgfxTableOffset) { > >>> - dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> - (mode_info->atom_context->bios + > >> data_offset + > >>> - le16_to_cpu(ext_hdr- > >>> usSclkVddgfxTableOffset)); > >>> - ret = amdgpu_parse_clk_voltage_dep_table( > >>> - &adev- > >>> pm.dpm.dyn_state.vddgfx_dependency_on_sclk, > >>> - dep_table); > >>> - if (ret) { > >>> - kfree(adev- > >>> pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); > >>> - return ret; > >>> - } > >>> - } > >>> - } > >>> - > >>> - return 0; > >>> -} > >>> - > >>> -void amdgpu_free_extended_power_table(struct amdgpu_device > *adev) > >>> -{ > >>> - struct amdgpu_dpm_dynamic_state *dyn_state = &adev- > >>> pm.dpm.dyn_state; > >>> - > >>> - kfree(dyn_state->vddc_dependency_on_sclk.entries); > >>> - kfree(dyn_state->vddci_dependency_on_mclk.entries); > >>> - kfree(dyn_state->vddc_dependency_on_mclk.entries); > >>> - kfree(dyn_state->mvdd_dependency_on_mclk.entries); > >>> - kfree(dyn_state->cac_leakage_table.entries); > >>> - kfree(dyn_state->phase_shedding_limits_table.entries); > >>> - kfree(dyn_state->ppm_table); > >>> - kfree(dyn_state->cac_tdp_table); > >>> - kfree(dyn_state->vce_clock_voltage_dependency_table.entries); > >>> - kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); > >>> - kfree(dyn_state->samu_clock_voltage_dependency_table.entries); > >>> - kfree(dyn_state->acp_clock_voltage_dependency_table.entries); > >>> - kfree(dyn_state->vddgfx_dependency_on_sclk.entries); > >>> -} > >>> - > >>> -static const char *pp_lib_thermal_controller_names[] = { > >>> - "NONE", > >>> - "lm63", > >>> - "adm1032", > >>> - "adm1030", > >>> - "max6649", > >>> - "lm64", > >>> - "f75375", > >>> - "RV6xx", > >>> - "RV770", > >>> - "adt7473", > >>> - "NONE", > >>> - "External GPIO", > >>> - "Evergreen", > >>> - "emc2103", > >>> - "Sumo", > >>> - "Northern Islands", > >>> - "Southern Islands", > >>> - "lm96163", > >>> - "Sea Islands", > >>> - "Kaveri/Kabini", > >>> -}; > >>> - > >>> -void amdgpu_add_thermal_controller(struct amdgpu_device *adev) > >>> -{ > >>> - struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> - ATOM_PPLIB_POWERPLAYTABLE *power_table; > >>> - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> - ATOM_PPLIB_THERMALCONTROLLER *controller; > >>> - struct amdgpu_i2c_bus_rec i2c_bus; > >>> - u16 data_offset; > >>> - u8 frev, crev; > >>> - > >>> - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> - &frev, &crev, &data_offset)) > >>> - return; > >>> - power_table = (ATOM_PPLIB_POWERPLAYTABLE *) > >>> - (mode_info->atom_context->bios + data_offset); > >>> - controller = &power_table->sThermalController; > >>> - > >>> - /* add the i2c bus for thermal/fan chip */ > >>> - if (controller->ucType > 0) { > >>> - if (controller->ucFanParameters & > >> ATOM_PP_FANPARAMETERS_NOFAN) > >>> - adev->pm.no_fan = true; > >>> - adev->pm.fan_pulses_per_revolution = > >>> - controller->ucFanParameters & > >> > ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_M > >> ASK; > >>> - if (adev->pm.fan_pulses_per_revolution) { > >>> - adev->pm.fan_min_rpm = controller->ucFanMinRPM; > >>> - adev->pm.fan_max_rpm = controller- > >>> ucFanMaxRPM; > >>> - } > >>> - if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_RV6xx) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_RV6XX; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_RV770) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_RV770; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_EVERGREEN) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_EVERGREEN; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_SUMO) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_SUMO; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_NISLANDS) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = THERMAL_TYPE_NI; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_SISLANDS) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = THERMAL_TYPE_SI; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_CISLANDS) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = THERMAL_TYPE_CI; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_KAVERI) { > >>> - DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = THERMAL_TYPE_KV; > >>> - } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { > >>> - DRM_INFO("External GPIO thermal controller %s fan > >> control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_EXTERNAL_GPIO; > >>> - } else if (controller->ucType == > >>> - > >> ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { > >>> - DRM_INFO("ADT7473 with internal thermal > >> controller %s fan control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_ADT7473_WITH_INTERNAL; > >>> - } else if (controller->ucType == > >>> - > >> ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { > >>> - DRM_INFO("EMC2103 with internal thermal > >> controller %s fan control\n", > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_EMC2103_WITH_INTERNAL; > >>> - } else if (controller->ucType < > >> ARRAY_SIZE(pp_lib_thermal_controller_names)) { > >>> - DRM_INFO("Possible %s thermal controller at > >> 0x%02x %s fan control\n", > >>> - > >> pp_lib_thermal_controller_names[controller->ucType], > >>> - controller->ucI2cAddress >> 1, > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - adev->pm.int_thermal_type = > >> THERMAL_TYPE_EXTERNAL; > >>> - i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, > >> controller->ucI2cLine); > >>> - adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, > >> &i2c_bus); > >>> - if (adev->pm.i2c_bus) { > >>> - struct i2c_board_info info = { }; > >>> - const char *name = > >> pp_lib_thermal_controller_names[controller->ucType]; > >>> - info.addr = controller->ucI2cAddress >> 1; > >>> - strlcpy(info.type, name, sizeof(info.type)); > >>> - i2c_new_client_device(&adev->pm.i2c_bus- > >>> adapter, &info); > >>> - } > >>> - } else { > >>> - DRM_INFO("Unknown thermal controller type %d at > >> 0x%02x %s fan control\n", > >>> - controller->ucType, > >>> - controller->ucI2cAddress >> 1, > >>> - (controller->ucFanParameters & > >>> - ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> - } > >>> - } > >>> -} > >>> - > >>> -struct amd_vce_state* > >>> -amdgpu_get_vce_clock_state(void *handle, u32 idx) > >>> -{ > >>> - struct amdgpu_device *adev = (struct amdgpu_device *)handle; > >>> - > >>> - if (idx < adev->pm.dpm.num_of_vce_states) > >>> - return &adev->pm.dpm.vce_states[idx]; > >>> - > >>> - return NULL; > >>> -} > >>> - > >>> int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) > >>> { > >>> const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; > >>> @@ -1243,211 +465,6 @@ void > >> amdgpu_dpm_thermal_work_handler(struct work_struct *work) > >>> amdgpu_pm_compute_clocks(adev); > >>> } > >>> > >>> -static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct > >> amdgpu_device *adev, > >>> - enum > >> amd_pm_state_type dpm_state) > >>> -{ > >>> - int i; > >>> - struct amdgpu_ps *ps; > >>> - u32 ui_class; > >>> - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? > >>> - true : false; > >>> - > >>> - /* check if the vblank period is too short to adjust the mclk */ > >>> - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) > >> { > >>> - if (amdgpu_dpm_vblank_too_short(adev)) > >>> - single_display = false; > >>> - } > >>> - > >>> - /* certain older asics have a separare 3D performance state, > >>> - * so try that first if the user selected performance > >>> - */ > >>> - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) > >>> - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; > >>> - /* balanced states don't exist at the moment */ > >>> - if (dpm_state == POWER_STATE_TYPE_BALANCED) > >>> - dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> - > >>> -restart_search: > >>> - /* Pick the best power state based on current conditions */ > >>> - for (i = 0; i < adev->pm.dpm.num_ps; i++) { > >>> - ps = &adev->pm.dpm.ps[i]; > >>> - ui_class = ps->class & > >> ATOM_PPLIB_CLASSIFICATION_UI_MASK; > >>> - switch (dpm_state) { > >>> - /* user states */ > >>> - case POWER_STATE_TYPE_BATTERY: > >>> - if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { > >>> - if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> - if (single_display) > >>> - return ps; > >>> - } else > >>> - return ps; > >>> - } > >>> - break; > >>> - case POWER_STATE_TYPE_BALANCED: > >>> - if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { > >>> - if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> - if (single_display) > >>> - return ps; > >>> - } else > >>> - return ps; > >>> - } > >>> - break; > >>> - case POWER_STATE_TYPE_PERFORMANCE: > >>> - if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { > >>> - if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> - if (single_display) > >>> - return ps; > >>> - } else > >>> - return ps; > >>> - } > >>> - break; > >>> - /* internal states */ > >>> - case POWER_STATE_TYPE_INTERNAL_UVD: > >>> - if (adev->pm.dpm.uvd_ps) > >>> - return adev->pm.dpm.uvd_ps; > >>> - else > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_SD: > >>> - if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_SDSTATE) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_HD: > >>> - if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_HDSTATE) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: > >>> - if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_HD2STATE) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: > >>> - if (ps->class2 & > >> ATOM_PPLIB_CLASSIFICATION2_MVC) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_BOOT: > >>> - return adev->pm.dpm.boot_ps; > >>> - case POWER_STATE_TYPE_INTERNAL_THERMAL: > >>> - if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_THERMAL) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_ACPI: > >>> - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_ULV: > >>> - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) > >>> - return ps; > >>> - break; > >>> - case POWER_STATE_TYPE_INTERNAL_3DPERF: > >>> - if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) > >>> - return ps; > >>> - break; > >>> - default: > >>> - break; > >>> - } > >>> - } > >>> - /* use a fallback state if we didn't match */ > >>> - switch (dpm_state) { > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_SD: > >>> - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; > >>> - goto restart_search; > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_HD: > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: > >>> - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: > >>> - if (adev->pm.dpm.uvd_ps) { > >>> - return adev->pm.dpm.uvd_ps; > >>> - } else { > >>> - dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> - goto restart_search; > >>> - } > >>> - case POWER_STATE_TYPE_INTERNAL_THERMAL: > >>> - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; > >>> - goto restart_search; > >>> - case POWER_STATE_TYPE_INTERNAL_ACPI: > >>> - dpm_state = POWER_STATE_TYPE_BATTERY; > >>> - goto restart_search; > >>> - case POWER_STATE_TYPE_BATTERY: > >>> - case POWER_STATE_TYPE_BALANCED: > >>> - case POWER_STATE_TYPE_INTERNAL_3DPERF: > >>> - dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> - goto restart_search; > >>> - default: > >>> - break; > >>> - } > >>> - > >>> - return NULL; > >>> -} > >>> - > >>> -static void amdgpu_dpm_change_power_state_locked(struct > >> amdgpu_device *adev) > >>> -{ > >>> - struct amdgpu_ps *ps; > >>> - enum amd_pm_state_type dpm_state; > >>> - int ret; > >>> - bool equal = false; > >>> - > >>> - /* if dpm init failed */ > >>> - if (!adev->pm.dpm_enabled) > >>> - return; > >>> - > >>> - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { > >>> - /* add other state override checks here */ > >>> - if ((!adev->pm.dpm.thermal_active) && > >>> - (!adev->pm.dpm.uvd_active)) > >>> - adev->pm.dpm.state = adev->pm.dpm.user_state; > >>> - } > >>> - dpm_state = adev->pm.dpm.state; > >>> - > >>> - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); > >>> - if (ps) > >>> - adev->pm.dpm.requested_ps = ps; > >>> - else > >>> - return; > >>> - > >>> - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs- > >>> print_power_state) { > >>> - printk("switching from power state:\n"); > >>> - amdgpu_dpm_print_power_state(adev, adev- > >>> pm.dpm.current_ps); > >>> - printk("switching to power state:\n"); > >>> - amdgpu_dpm_print_power_state(adev, adev- > >>> pm.dpm.requested_ps); > >>> - } > >>> - > >>> - /* update whether vce is active */ > >>> - ps->vce_active = adev->pm.dpm.vce_active; > >>> - if (adev->powerplay.pp_funcs->display_configuration_changed) > >>> - amdgpu_dpm_display_configuration_changed(adev); > >>> - > >>> - ret = amdgpu_dpm_pre_set_power_state(adev); > >>> - if (ret) > >>> - return; > >>> - > >>> - if (adev->powerplay.pp_funcs->check_state_equal) { > >>> - if (0 != amdgpu_dpm_check_state_equal(adev, adev- > >>> pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) > >>> - equal = false; > >>> - } > >>> - > >>> - if (equal) > >>> - return; > >>> - > >>> - if (adev->powerplay.pp_funcs->set_power_state) > >>> - adev->powerplay.pp_funcs->set_power_state(adev- > >>> powerplay.pp_handle); > >>> - > >>> - amdgpu_dpm_post_set_power_state(adev); > >>> - > >>> - adev->pm.dpm.current_active_crtcs = adev- > >>> pm.dpm.new_active_crtcs; > >>> - adev->pm.dpm.current_active_crtc_count = adev- > >>> pm.dpm.new_active_crtc_count; > >>> - > >>> - if (adev->powerplay.pp_funcs->force_performance_level) { > >>> - if (adev->pm.dpm.thermal_active) { > >>> - enum amd_dpm_forced_level level = adev- > >>> pm.dpm.forced_level; > >>> - /* force low perf level for thermal */ > >>> - amdgpu_dpm_force_performance_level(adev, > >> AMD_DPM_FORCED_LEVEL_LOW); > >>> - /* save the user's level */ > >>> - adev->pm.dpm.forced_level = level; > >>> - } else { > >>> - /* otherwise, user selected level */ > >>> - amdgpu_dpm_force_performance_level(adev, > >> adev->pm.dpm.forced_level); > >>> - } > >>> - } > >>> -} > >>> - > >>> void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) > >>> { > >> > >> Rename to amdgpu_dpm_compute_clocks? > > [Quan, Evan] Sure, I can do that. > >> > >>> int i = 0; > >>> @@ -1464,9 +481,12 @@ void amdgpu_pm_compute_clocks(struct > >> amdgpu_device *adev) > >>> amdgpu_fence_wait_empty(ring); > >>> } > >>> > >>> - if (adev->powerplay.pp_funcs->dispatch_tasks) { > >>> + if ((adev->family == AMDGPU_FAMILY_SI) || > >>> + (adev->family == AMDGPU_FAMILY_KV)) { > >>> + amdgpu_dpm_get_active_displays(adev); > >>> + adev->powerplay.pp_funcs->change_power_state(adev- > >>> powerplay.pp_handle); > >> > >> It would be clearer if the newly added logic in this function is in > >> another patch. This does more than what the patch subject says. > > [Quan, Evan] Actually there are no new logic added. These are for "!adev- > >powerplay.pp_funcs->dispatch_tasks". > > Considering there are actually only SI and KV which do not have - > >dispatch_tasks() implemented. > > So, I used "((adev->family == AMDGPU_FAMILY_SI) ||(adev->family == > AMDGPU_FAMILY_KV))" here. > > Maybe i should stick with "!adev->powerplay.pp_funcs->dispatch_tasks"? > > This change also adds a new callback change_power_state(). I interpreted > it as something different from what the patch subject says. > > >> > >>> + } else { > >>> if (!amdgpu_device_has_dc_support(adev)) { > >>> - mutex_lock(&adev->pm.mutex); > >>> amdgpu_dpm_get_active_displays(adev); > >>> adev->pm.pm_display_cfg.num_display = adev- > >>> pm.dpm.new_active_crtc_count; > >>> adev->pm.pm_display_cfg.vrefresh = > >> amdgpu_dpm_get_vrefresh(adev); > >>> @@ -1480,14 +500,8 @@ void amdgpu_pm_compute_clocks(struct > >> amdgpu_device *adev) > >>> adev->powerplay.pp_funcs- > >>> display_configuration_change( > >>> adev- > >>> powerplay.pp_handle, > >>> &adev- > >>> pm.pm_display_cfg); > >>> - mutex_unlock(&adev->pm.mutex); > >>> } > >>> amdgpu_dpm_dispatch_task(adev, > >> AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); > >>> - } else { > >>> - mutex_lock(&adev->pm.mutex); > >>> - amdgpu_dpm_get_active_displays(adev); > >>> - amdgpu_dpm_change_power_state_locked(adev); > >>> - mutex_unlock(&adev->pm.mutex); > >>> } > >>> } > >>> > >>> @@ -1550,18 +564,6 @@ void amdgpu_dpm_enable_vce(struct > >> amdgpu_device *adev, bool enable) > >>> } > >>> } > >>> > >>> -void amdgpu_pm_print_power_states(struct amdgpu_device *adev) > >>> -{ > >>> - int i; > >>> - > >>> - if (adev->powerplay.pp_funcs->print_power_state == NULL) > >>> - return; > >>> - > >>> - for (i = 0; i < adev->pm.dpm.num_ps; i++) > >>> - amdgpu_dpm_print_power_state(adev, &adev- > >>> pm.dpm.ps[i]); > >>> - > >>> -} > >>> - > >>> void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool > >> enable) > >>> { > >>> int ret = 0; > >>> diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h > >> b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h > >>> index 01120b302590..295d2902aef7 100644 > >>> --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h > >>> +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h > >>> @@ -366,24 +366,10 @@ enum amdgpu_display_gap > >>> AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, > >>> }; > >>> > >>> -void amdgpu_dpm_print_class_info(u32 class, u32 class2); > >>> -void amdgpu_dpm_print_cap_info(u32 caps); > >>> -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, > >>> - struct amdgpu_ps *rps); > >>> u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); > >>> int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum > >> amd_pp_sensors sensor, > >>> void *data, uint32_t *size); > >>> > >>> -int amdgpu_get_platform_caps(struct amdgpu_device *adev); > >>> - > >>> -int amdgpu_parse_extended_power_table(struct amdgpu_device > *adev); > >>> -void amdgpu_free_extended_power_table(struct amdgpu_device > >> *adev); > >>> - > >>> -void amdgpu_add_thermal_controller(struct amdgpu_device *adev); > >>> - > >>> -struct amd_vce_state* > >>> -amdgpu_get_vce_clock_state(void *handle, u32 idx); > >>> - > >>> int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device > >> *adev, > >>> uint32_t block_type, bool gate); > >>> > >>> @@ -438,7 +424,6 @@ void amdgpu_pm_compute_clocks(struct > >> amdgpu_device *adev); > >>> void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool > >> enable); > >>> void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool > >> enable); > >>> void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool > >> enable); > >>> -void amdgpu_pm_print_power_states(struct amdgpu_device *adev); > >>> int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, > >> uint32_t *smu_version); > >>> int amdgpu_dpm_set_light_sbr(struct amdgpu_device *adev, bool > >> enable); > >>> int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device > >> *adev, uint32_t size); > >>> diff --git a/drivers/gpu/drm/amd/pm/powerplay/Makefile > >> b/drivers/gpu/drm/amd/pm/powerplay/Makefile > >>> index 0fb114adc79f..614d8b6a58ad 100644 > >>> --- a/drivers/gpu/drm/amd/pm/powerplay/Makefile > >>> +++ b/drivers/gpu/drm/amd/pm/powerplay/Makefile > >>> @@ -28,7 +28,7 @@ AMD_POWERPLAY = $(addsuffix > >> /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/ > >>> > >>> include $(AMD_POWERPLAY) > >>> > >>> -POWER_MGR-y = amd_powerplay.o > >>> +POWER_MGR-y = amd_powerplay.o legacy_dpm.o > >>> > >>> POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o > >>> > >>> diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c > >> b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c > >>> index 380a5336c74f..90f4c65659e2 100644 > >>> --- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c > >>> +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c > >>> @@ -36,6 +36,7 @@ > >>> > >>> #include "gca/gfx_7_2_d.h" > >>> #include "gca/gfx_7_2_sh_mask.h" > >>> +#include "legacy_dpm.h" > >>> > >>> #define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 > >>> #define KV_MINIMUM_ENGINE_CLOCK 800 > >>> @@ -3389,6 +3390,7 @@ static const struct amd_pm_funcs > kv_dpm_funcs > >> = { > >>> .get_vce_clock_state = amdgpu_get_vce_clock_state, > >>> .check_state_equal = kv_check_state_equal, > >>> .read_sensor = &kv_dpm_read_sensor, > >>> + .change_power_state = amdgpu_dpm_change_power_state_locked, > >>> }; > >>> > >>> static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { > >>> diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c > >> b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c > >> > >> This could get confused with all APIs that support legacy dpms. This > >> file has only a subset of APIs to support legacy dpm. Needs a better > >> name - powerplay_ctrl/powerplay_util ? > > [Quan, Evan] The "legacy_dpm" refers for those logics used only by > si/kv(si_dpm.c, kv_dpm.c). > > Considering these logics are not used at default(radeon driver instead of > amdgpu driver is used to support those legacy ASICs at default). > > We might drop support for them from our amdgpu driver. So, I gather all > those APIs and put them in a new holder. > > Maybe you wrongly treat it as a new holder for powerplay APIs(used by > VI/AI)? > > As it got moved under powerplay, I thought they were also used in AI/VI > powerplay. Otherwise, move si/kv along with this out of powerplay and > keep them separate. > > Thanks, > Lijo > > > > > BR > > Evan > >> > >> Thanks, > >> Lijo > >> > >>> new file mode 100644 > >>> index 000000000000..9427c1026e1d > >>> --- /dev/null > >>> +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c > >>> @@ -0,0 +1,1453 @@ > >>> +/* > >>> + * Copyright 2021 Advanced Micro Devices, Inc. > >>> + * > >>> + * Permission is hereby granted, free of charge, to any person obtaining > a > >>> + * copy of this software and associated documentation files (the > >> "Software"), > >>> + * to deal in the Software without restriction, including without > limitation > >>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > >>> + * and/or sell copies of the Software, and to permit persons to whom > the > >>> + * Software is furnished to do so, subject to the following conditions: > >>> + * > >>> + * The above copyright notice and this permission notice shall be > included > >> in > >>> + * all copies or substantial portions of the Software. > >>> + * > >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > >> KIND, EXPRESS OR > >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > >> MERCHANTABILITY, > >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > >> NO EVENT SHALL > >>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > >> DAMAGES OR > >>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > >> OTHERWISE, > >>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE > OR > >> THE USE OR > >>> + * OTHER DEALINGS IN THE SOFTWARE. > >>> + */ > >>> + > >>> +#include "amdgpu.h" > >>> +#include "amdgpu_atombios.h" > >>> +#include "amdgpu_i2c.h" > >>> +#include "atom.h" > >>> +#include "amd_pcie.h" > >>> +#include "legacy_dpm.h" > >>> + > >>> +#define amdgpu_dpm_pre_set_power_state(adev) \ > >>> + ((adev)->powerplay.pp_funcs- > >>> pre_set_power_state((adev)->powerplay.pp_handle)) > >>> + > >>> +#define amdgpu_dpm_post_set_power_state(adev) \ > >>> + ((adev)->powerplay.pp_funcs- > >>> post_set_power_state((adev)->powerplay.pp_handle)) > >>> + > >>> +#define amdgpu_dpm_display_configuration_changed(adev) \ > >>> + ((adev)->powerplay.pp_funcs- > >>> display_configuration_changed((adev)->powerplay.pp_handle)) > >>> + > >>> +#define amdgpu_dpm_print_power_state(adev, ps) \ > >>> + ((adev)->powerplay.pp_funcs->print_power_state((adev)- > >>> powerplay.pp_handle, (ps))) > >>> + > >>> +#define amdgpu_dpm_vblank_too_short(adev) \ > >>> + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)- > >>> powerplay.pp_handle)) > >>> + > >>> +#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ > >>> + ((adev)->powerplay.pp_funcs->check_state_equal((adev)- > >>> powerplay.pp_handle, (cps), (rps), (equal))) > >>> + > >>> +int amdgpu_atombios_get_memory_pll_dividers(struct > amdgpu_device > >> *adev, > >>> + u32 clock, > >>> + bool strobe_mode, > >>> + struct atom_mpll_param > >> *mpll_param) > >>> +{ > >>> + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 args; > >>> + int index = GetIndexIntoMasterTable(COMMAND, > >> ComputeMemoryClockParam); > >>> + u8 frev, crev; > >>> + > >>> + memset(&args, 0, sizeof(args)); > >>> + memset(mpll_param, 0, sizeof(struct atom_mpll_param)); > >>> + > >>> + if (!amdgpu_atom_parse_cmd_header(adev- > >>> mode_info.atom_context, index, &frev, &crev)) > >>> + return -EINVAL; > >>> + > >>> + switch (frev) { > >>> + case 2: > >>> + switch (crev) { > >>> + case 1: > >>> + /* SI */ > >>> + args.ulClock = cpu_to_le32(clock); /* 10 khz */ > >>> + args.ucInputFlag = 0; > >>> + if (strobe_mode) > >>> + args.ucInputFlag |= > >> MPLL_INPUT_FLAG_STROBE_MODE_EN; > >>> + > >>> + amdgpu_atom_execute_table(adev- > >>> mode_info.atom_context, index, (uint32_t *)&args); > >>> + > >>> + mpll_param->clkfrac = > >> le16_to_cpu(args.ulFbDiv.usFbDivFrac); > >>> + mpll_param->clkf = > >> le16_to_cpu(args.ulFbDiv.usFbDiv); > >>> + mpll_param->post_div = args.ucPostDiv; > >>> + mpll_param->dll_speed = args.ucDllSpeed; > >>> + mpll_param->bwcntl = args.ucBWCntl; > >>> + mpll_param->vco_mode = > >>> + (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_VCO_MODE_MASK); > >>> + mpll_param->yclk_sel = > >>> + (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0; > >>> + mpll_param->qdr = > >>> + (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0; > >>> + mpll_param->half_rate = > >>> + (args.ucPllCntlFlag & > >> MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0; > >>> + break; > >>> + default: > >>> + return -EINVAL; > >>> + } > >>> + break; > >>> + default: > >>> + return -EINVAL; > >>> + } > >>> + return 0; > >>> +} > >>> + > >>> +void amdgpu_atombios_set_engine_dram_timings(struct > >> amdgpu_device *adev, > >>> + u32 eng_clock, u32 mem_clock) > >>> +{ > >>> + SET_ENGINE_CLOCK_PS_ALLOCATION args; > >>> + int index = GetIndexIntoMasterTable(COMMAND, > >> DynamicMemorySettings); > >>> + u32 tmp; > >>> + > >>> + memset(&args, 0, sizeof(args)); > >>> + > >>> + tmp = eng_clock & SET_CLOCK_FREQ_MASK; > >>> + tmp |= (COMPUTE_ENGINE_PLL_PARAM << 24); > >>> + > >>> + args.ulTargetEngineClock = cpu_to_le32(tmp); > >>> + if (mem_clock) > >>> + args.sReserved.ulClock = cpu_to_le32(mem_clock & > >> SET_CLOCK_FREQ_MASK); > >>> + > >>> + amdgpu_atom_execute_table(adev->mode_info.atom_context, > >> index, (uint32_t *)&args); > >>> +} > >>> + > >>> +union firmware_info { > >>> + ATOM_FIRMWARE_INFO info; > >>> + ATOM_FIRMWARE_INFO_V1_2 info_12; > >>> + ATOM_FIRMWARE_INFO_V1_3 info_13; > >>> + ATOM_FIRMWARE_INFO_V1_4 info_14; > >>> + ATOM_FIRMWARE_INFO_V2_1 info_21; > >>> + ATOM_FIRMWARE_INFO_V2_2 info_22; > >>> +}; > >>> + > >>> +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; > >>> + struct _SET_VOLTAGE_PARAMETERS_V2 v2; > >>> + 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); > >>> +} > >>> + > >>> +union voltage_object_info { > >>> + struct _ATOM_VOLTAGE_OBJECT_INFO v1; > >>> + struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; > >>> + struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3; > >>> +}; > >>> + > >>> +union voltage_object { > >>> + struct _ATOM_VOLTAGE_OBJECT v1; > >>> + struct _ATOM_VOLTAGE_OBJECT_V2 v2; > >>> + union _ATOM_VOLTAGE_OBJECT_V3 v3; > >>> +}; > >>> + > >>> +static ATOM_VOLTAGE_OBJECT_V3 > >> > *amdgpu_atombios_lookup_voltage_object_v3(ATOM_VOLTAGE_OBJECT_I > >> NFO_V3_1 *v3, > >>> + u8 > >> voltage_type, u8 voltage_mode) > >>> +{ > >>> + u32 size = le16_to_cpu(v3->sHeader.usStructureSize); > >>> + u32 offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, > >> asVoltageObj[0]); > >>> + u8 *start = (u8 *)v3; > >>> + > >>> + while (offset < size) { > >>> + ATOM_VOLTAGE_OBJECT_V3 *vo = > >> (ATOM_VOLTAGE_OBJECT_V3 *)(start + offset); > >>> + if ((vo->asGpioVoltageObj.sHeader.ucVoltageType == > >> voltage_type) && > >>> + (vo->asGpioVoltageObj.sHeader.ucVoltageMode == > >> voltage_mode)) > >>> + return vo; > >>> + offset += le16_to_cpu(vo- > >>> asGpioVoltageObj.sHeader.usSize); > >>> + } > >>> + 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) > >>> +{ > >>> + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); > >>> + u8 frev, crev; > >>> + u16 data_offset, size; > >>> + union voltage_object_info *voltage_info; > >>> + > >>> + 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: > >>> + if > >> (amdgpu_atombios_lookup_voltage_object_v3(&voltage_info->v3, > >>> + > >> voltage_type, voltage_mode)) > >>> + return true; > >>> + break; > >>> + default: > >>> + DRM_ERROR("unknown voltage object > >> table\n"); > >>> + return false; > >>> + } > >>> + break; > >>> + default: > >>> + DRM_ERROR("unknown voltage object table\n"); > >>> + return false; > >>> + } > >>> + > >>> + } > >>> + return false; > >>> +} > >>> + > >>> +int amdgpu_atombios_get_voltage_table(struct amdgpu_device > *adev, > >>> + u8 voltage_type, u8 voltage_mode, > >>> + struct atom_voltage_table *voltage_table) > >>> +{ > >>> + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); > >>> + u8 frev, crev; > >>> + u16 data_offset, size; > >>> + int i; > >>> + 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_mode); > >>> + if (voltage_object) { > >>> + ATOM_GPIO_VOLTAGE_OBJECT_V3 > >> *gpio = > >>> + &voltage_object- > >>> v3.asGpioVoltageObj; > >>> + VOLTAGE_LUT_ENTRY_V2 *lut; > >>> + if (gpio->ucGpioEntryNum > > >> MAX_VOLTAGE_ENTRIES) > >>> + return -EINVAL; > >>> + lut = &gpio->asVolGpioLut[0]; > >>> + for (i = 0; i < gpio->ucGpioEntryNum; > >> i++) { > >>> + voltage_table- > >>> entries[i].value = > >>> + le16_to_cpu(lut- > >>> usVoltageValue); > >>> + voltage_table- > >>> entries[i].smio_low = > >>> + le32_to_cpu(lut- > >>> ulVoltageId); > >>> + lut = > >> (VOLTAGE_LUT_ENTRY_V2 *) > >>> + ((u8 *)lut + > >> sizeof(VOLTAGE_LUT_ENTRY_V2)); > >>> + } > >>> + voltage_table->mask_low = > >> le32_to_cpu(gpio->ulGpioMaskVal); > >>> + voltage_table->count = gpio- > >>> ucGpioEntryNum; > >>> + voltage_table->phase_delay = gpio- > >>> ucPhaseDelay; > >>> + return 0; > >>> + } > >>> + break; > >>> + default: > >>> + DRM_ERROR("unknown voltage object > >> table\n"); > >>> + return -EINVAL; > >>> + } > >>> + break; > >>> + default: > >>> + DRM_ERROR("unknown voltage object table\n"); > >>> + return -EINVAL; > >>> + } > >>> + } > >>> + return -EINVAL; > >>> +} > >>> + > >>> +union vram_info { > >>> + struct _ATOM_VRAM_INFO_V3 v1_3; > >>> + struct _ATOM_VRAM_INFO_V4 v1_4; > >>> + struct _ATOM_VRAM_INFO_HEADER_V2_1 v2_1; > >>> +}; > >>> + > >>> +#define MEM_ID_MASK 0xff000000 > >>> +#define MEM_ID_SHIFT 24 > >>> +#define CLOCK_RANGE_MASK 0x00ffffff > >>> +#define CLOCK_RANGE_SHIFT 0 > >>> +#define LOW_NIBBLE_MASK 0xf > >>> +#define DATA_EQU_PREV 0 > >>> +#define DATA_FROM_TABLE 4 > >>> + > >>> +int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device > *adev, > >>> + u8 module_index, > >>> + struct atom_mc_reg_table *reg_table) > >>> +{ > >>> + int index = GetIndexIntoMasterTable(DATA, VRAM_Info); > >>> + u8 frev, crev, num_entries, t_mem_id, num_ranges = 0; > >>> + u32 i = 0, j; > >>> + u16 data_offset, size; > >>> + union vram_info *vram_info; > >>> + > >>> + memset(reg_table, 0, sizeof(struct atom_mc_reg_table)); > >>> + > >>> + if (amdgpu_atom_parse_data_header(adev- > >>> mode_info.atom_context, index, &size, > >>> + &frev, &crev, &data_offset)) { > >>> + vram_info = (union vram_info *) > >>> + (adev->mode_info.atom_context->bios + > >> data_offset); > >>> + switch (frev) { > >>> + case 1: > >>> + DRM_ERROR("old table version %d, %d\n", frev, > >> crev); > >>> + return -EINVAL; > >>> + case 2: > >>> + switch (crev) { > >>> + case 1: > >>> + if (module_index < vram_info- > >>> v2_1.ucNumOfVRAMModule) { > >>> + ATOM_INIT_REG_BLOCK *reg_block > >> = > >>> + (ATOM_INIT_REG_BLOCK *) > >>> + ((u8 *)vram_info + > >> le16_to_cpu(vram_info->v2_1.usMemClkPatchTblOffset)); > >>> + > >> ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = > >>> + > >> (ATOM_MEMORY_SETTING_DATA_BLOCK *) > >>> + ((u8 *)reg_block + (2 * > >> sizeof(u16)) + > >>> + le16_to_cpu(reg_block- > >>> usRegIndexTblSize)); > >>> + ATOM_INIT_REG_INDEX_FORMAT > >> *format = ®_block->asRegIndexBuf[0]; > >>> + num_entries = > >> (u8)((le16_to_cpu(reg_block->usRegIndexTblSize)) / > >>> + > >> sizeof(ATOM_INIT_REG_INDEX_FORMAT)) - 1; > >>> + if (num_entries > > >> VBIOS_MC_REGISTER_ARRAY_SIZE) > >>> + return -EINVAL; > >>> + while (i < num_entries) { > >>> + if (format- > >>> ucPreRegDataLength & ACCESS_PLACEHOLDER) > >>> + break; > >>> + reg_table- > >>> mc_reg_address[i].s1 = > >>> + > >> (u16)(le16_to_cpu(format->usRegIndex)); > >>> + reg_table- > >>> mc_reg_address[i].pre_reg_data = > >>> + (u8)(format- > >>> ucPreRegDataLength); > >>> + i++; > >>> + format = > >> (ATOM_INIT_REG_INDEX_FORMAT *) > >>> + ((u8 *)format + > >> sizeof(ATOM_INIT_REG_INDEX_FORMAT)); > >>> + } > >>> + reg_table->last = i; > >>> + while ((le32_to_cpu(*(u32 > >> *)reg_data) != END_OF_REG_DATA_BLOCK) && > >>> + (num_ranges < > >> VBIOS_MAX_AC_TIMING_ENTRIES)) { > >>> + t_mem_id = > >> (u8)((le32_to_cpu(*(u32 *)reg_data) & MEM_ID_MASK) > >>> + >> > >> MEM_ID_SHIFT); > >>> + if (module_index == > >> t_mem_id) { > >>> + reg_table- > >>> mc_reg_table_entry[num_ranges].mclk_max = > >>> + > >> (u32)((le32_to_cpu(*(u32 *)reg_data) & CLOCK_RANGE_MASK) > >>> + >> > >> CLOCK_RANGE_SHIFT); > >>> + for (i = 0, j = 1; i < > >> reg_table->last; i++) { > >>> + if ((reg_table- > >>> mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == > >> DATA_FROM_TABLE) { > >>> + > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = > >>> + > >> (u32)le32_to_cpu(*((u32 *)reg_data + j)); > >>> + j++; > >>> + } else if > >> ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == > >> DATA_EQU_PREV) { > >>> + > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i] = > >>> + > >> reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1]; > >>> + } > >>> + } > >>> + num_ranges++; > >>> + } > >>> + reg_data = > >> (ATOM_MEMORY_SETTING_DATA_BLOCK *) > >>> + ((u8 *)reg_data + > >> le16_to_cpu(reg_block->usRegDataBlkSize)); > >>> + } > >>> + if (le32_to_cpu(*(u32 *)reg_data) != > >> END_OF_REG_DATA_BLOCK) > >>> + return -EINVAL; > >>> + reg_table->num_entries = > >> num_ranges; > >>> + } else > >>> + return -EINVAL; > >>> + break; > >>> + default: > >>> + DRM_ERROR("Unknown table > >> version %d, %d\n", frev, crev); > >>> + return -EINVAL; > >>> + } > >>> + break; > >>> + default: > >>> + DRM_ERROR("Unknown table version %d, %d\n", > >> frev, crev); > >>> + return -EINVAL; > >>> + } > >>> + return 0; > >>> + } > >>> + return -EINVAL; > >>> +} > >>> + > >>> +void amdgpu_dpm_print_class_info(u32 class, u32 class2) > >>> +{ > >>> + const char *s; > >>> + > >>> + switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { > >>> + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: > >>> + default: > >>> + s = "none"; > >>> + break; > >>> + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: > >>> + s = "battery"; > >>> + break; > >>> + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: > >>> + s = "balanced"; > >>> + break; > >>> + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: > >>> + s = "performance"; > >>> + break; > >>> + } > >>> + printk("\tui class: %s\n", s); > >>> + printk("\tinternal class:"); > >>> + if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && > >>> + (class2 == 0)) > >>> + pr_cont(" none"); > >>> + else { > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) > >>> + pr_cont(" boot"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) > >>> + pr_cont(" thermal"); > >>> + if (class & > >> ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) > >>> + pr_cont(" limited_pwr"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_REST) > >>> + pr_cont(" rest"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) > >>> + pr_cont(" forced"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) > >>> + pr_cont(" 3d_perf"); > >>> + if (class & > >> ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) > >>> + pr_cont(" ovrdrv"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) > >>> + pr_cont(" uvd"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) > >>> + pr_cont(" 3d_low"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) > >>> + pr_cont(" acpi"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) > >>> + pr_cont(" uvd_hd2"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) > >>> + pr_cont(" uvd_hd"); > >>> + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) > >>> + pr_cont(" uvd_sd"); > >>> + if (class2 & > >> ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) > >>> + pr_cont(" limited_pwr2"); > >>> + if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) > >>> + pr_cont(" ulv"); > >>> + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) > >>> + pr_cont(" uvd_mvc"); > >>> + } > >>> + pr_cont("\n"); > >>> +} > >>> + > >>> +void amdgpu_dpm_print_cap_info(u32 caps) > >>> +{ > >>> + printk("\tcaps:"); > >>> + if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) > >>> + pr_cont(" single_disp"); > >>> + if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) > >>> + pr_cont(" video"); > >>> + if (caps & ATOM_PPLIB_DISALLOW_ON_DC) > >>> + pr_cont(" no_dc"); > >>> + pr_cont("\n"); > >>> +} > >>> + > >>> +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, > >>> + struct amdgpu_ps *rps) > >>> +{ > >>> + printk("\tstatus:"); > >>> + if (rps == adev->pm.dpm.current_ps) > >>> + pr_cont(" c"); > >>> + if (rps == adev->pm.dpm.requested_ps) > >>> + pr_cont(" r"); > >>> + if (rps == adev->pm.dpm.boot_ps) > >>> + pr_cont(" b"); > >>> + pr_cont("\n"); > >>> +} > >>> + > >>> +void amdgpu_pm_print_power_states(struct amdgpu_device *adev) > >>> +{ > >>> + int i; > >>> + > >>> + if (adev->powerplay.pp_funcs->print_power_state == NULL) > >>> + return; > >>> + > >>> + for (i = 0; i < adev->pm.dpm.num_ps; i++) > >>> + amdgpu_dpm_print_power_state(adev, &adev- > >>> pm.dpm.ps[i]); > >>> + > >>> +} > >>> + > >>> +union power_info { > >>> + struct _ATOM_POWERPLAY_INFO info; > >>> + struct _ATOM_POWERPLAY_INFO_V2 info_2; > >>> + struct _ATOM_POWERPLAY_INFO_V3 info_3; > >>> + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; > >>> + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; > >>> + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; > >>> + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; > >>> + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; > >>> +}; > >>> + > >>> +int amdgpu_get_platform_caps(struct amdgpu_device *adev) > >>> +{ > >>> + struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> + union power_info *power_info; > >>> + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> + u16 data_offset; > >>> + u8 frev, crev; > >>> + > >>> + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> + &frev, &crev, &data_offset)) > >>> + return -EINVAL; > >>> + power_info = (union power_info *)(mode_info->atom_context- > >>> bios + data_offset); > >>> + > >>> + adev->pm.dpm.platform_caps = le32_to_cpu(power_info- > >>> pplib.ulPlatformCaps); > >>> + adev->pm.dpm.backbias_response_time = > >> le16_to_cpu(power_info->pplib.usBackbiasTime); > >>> + adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info- > >>> pplib.usVoltageTime); > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +union fan_info { > >>> + struct _ATOM_PPLIB_FANTABLE fan; > >>> + struct _ATOM_PPLIB_FANTABLE2 fan2; > >>> + struct _ATOM_PPLIB_FANTABLE3 fan3; > >>> +}; > >>> + > >>> +static int amdgpu_parse_clk_voltage_dep_table(struct > >> amdgpu_clock_voltage_dependency_table *amdgpu_table, > >>> + > >> ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) > >>> +{ > >>> + u32 size = atom_table->ucNumEntries * > >>> + sizeof(struct amdgpu_clock_voltage_dependency_entry); > >>> + int i; > >>> + ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; > >>> + > >>> + amdgpu_table->entries = kzalloc(size, GFP_KERNEL); > >>> + if (!amdgpu_table->entries) > >>> + return -ENOMEM; > >>> + > >>> + entry = &atom_table->entries[0]; > >>> + for (i = 0; i < atom_table->ucNumEntries; i++) { > >>> + amdgpu_table->entries[i].clk = le16_to_cpu(entry- > >>> usClockLow) | > >>> + (entry->ucClockHigh << 16); > >>> + amdgpu_table->entries[i].v = le16_to_cpu(entry- > >>> usVoltage); > >>> + entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record > >> *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); > >>> + } > >>> + amdgpu_table->count = atom_table->ucNumEntries; > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 > >>> +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 > >>> + > >>> +int amdgpu_parse_extended_power_table(struct amdgpu_device > *adev) > >>> +{ > >>> + struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> + union power_info *power_info; > >>> + union fan_info *fan_info; > >>> + ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; > >>> + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> + u16 data_offset; > >>> + u8 frev, crev; > >>> + int ret, i; > >>> + > >>> + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> + &frev, &crev, &data_offset)) > >>> + return -EINVAL; > >>> + power_info = (union power_info *)(mode_info->atom_context- > >>> bios + data_offset); > >>> + > >>> + /* fan table */ > >>> + if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { > >>> + if (power_info->pplib3.usFanTableOffset) { > >>> + fan_info = (union fan_info *)(mode_info- > >>> atom_context->bios + data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib3.usFanTableOffset)); > >>> + adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; > >>> + adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info- > >>> fan.usTMin); > >>> + adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info- > >>> fan.usTMed); > >>> + adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info- > >>> fan.usTHigh); > >>> + adev->pm.dpm.fan.pwm_min = > >> le16_to_cpu(fan_info->fan.usPWMMin); > >>> + adev->pm.dpm.fan.pwm_med = > >> le16_to_cpu(fan_info->fan.usPWMMed); > >>> + adev->pm.dpm.fan.pwm_high = > >> le16_to_cpu(fan_info->fan.usPWMHigh); > >>> + if (fan_info->fan.ucFanTableFormat >= 2) > >>> + adev->pm.dpm.fan.t_max = > >> le16_to_cpu(fan_info->fan2.usTMax); > >>> + else > >>> + adev->pm.dpm.fan.t_max = 10900; > >>> + adev->pm.dpm.fan.cycle_delay = 100000; > >>> + if (fan_info->fan.ucFanTableFormat >= 3) { > >>> + adev->pm.dpm.fan.control_mode = > >> fan_info->fan3.ucFanControlMode; > >>> + adev->pm.dpm.fan.default_max_fan_pwm > >> = > >>> + le16_to_cpu(fan_info- > >>> fan3.usFanPWMMax); > >>> + adev- > >>> pm.dpm.fan.default_fan_output_sensitivity = 4836; > >>> + adev->pm.dpm.fan.fan_output_sensitivity = > >>> + le16_to_cpu(fan_info- > >>> fan3.usFanOutputSensitivity); > >>> + } > >>> + adev->pm.dpm.fan.ucode_fan_control = true; > >>> + } > >>> + } > >>> + > >>> + /* clock dependancy tables, shedding tables */ > >>> + if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { > >>> + if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { > >>> + dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usVddcDependencyOnSCLKOffset)); > >>> + ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddc_dependency_on_sclk, > >>> + dep_table); > >>> + if (ret) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return ret; > >>> + } > >>> + } > >>> + if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { > >>> + dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usVddciDependencyOnMCLKOffset)); > >>> + ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddci_dependency_on_mclk, > >>> + dep_table); > >>> + if (ret) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return ret; > >>> + } > >>> + } > >>> + if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { > >>> + dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usVddcDependencyOnMCLKOffset)); > >>> + ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.vddc_dependency_on_mclk, > >>> + dep_table); > >>> + if (ret) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return ret; > >>> + } > >>> + } > >>> + if (power_info->pplib4.usMvddDependencyOnMCLKOffset) > >> { > >>> + dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usMvddDependencyOnMCLKOffset)); > >>> + ret = amdgpu_parse_clk_voltage_dep_table(&adev- > >>> pm.dpm.dyn_state.mvdd_dependency_on_mclk, > >>> + dep_table); > >>> + if (ret) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return ret; > >>> + } > >>> + } > >>> + if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { > >>> + ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = > >>> + (ATOM_PPLIB_Clock_Voltage_Limit_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usMaxClockVoltageOnDCOffset)); > >>> + if (clk_v->ucNumEntries) { > >>> + adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = > >>> + le16_to_cpu(clk_v- > >>> entries[0].usSclkLow) | > >>> + (clk_v->entries[0].ucSclkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = > >>> + le16_to_cpu(clk_v- > >>> entries[0].usMclkLow) | > >>> + (clk_v->entries[0].ucMclkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = > >>> + le16_to_cpu(clk_v- > >>> entries[0].usVddc); > >>> + adev- > >>> pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = > >>> + le16_to_cpu(clk_v- > >>> entries[0].usVddci); > >>> + } > >>> + } > >>> + if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) > >> { > >>> + ATOM_PPLIB_PhaseSheddingLimits_Table *psl = > >>> + (ATOM_PPLIB_PhaseSheddingLimits_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib4.usVddcPhaseShedLimitsTableOffset)); > >>> + ATOM_PPLIB_PhaseSheddingLimits_Record *entry; > >>> + > >>> + adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries = > >>> + kcalloc(psl->ucNumEntries, > >>> + sizeof(struct > >> amdgpu_phase_shedding_limits_entry), > >>> + GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + > >>> + entry = &psl->entries[0]; > >>> + for (i = 0; i < psl->ucNumEntries; i++) { > >>> + adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = > >>> + le16_to_cpu(entry->usSclkLow) | > >> (entry->ucSclkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = > >>> + le16_to_cpu(entry->usMclkLow) | > >> (entry->ucMclkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = > >>> + le16_to_cpu(entry->usVoltage); > >>> + entry = > >> (ATOM_PPLIB_PhaseSheddingLimits_Record *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); > >>> + } > >>> + adev- > >>> pm.dpm.dyn_state.phase_shedding_limits_table.count = > >>> + psl->ucNumEntries; > >>> + } > >>> + } > >>> + > >>> + /* cac data */ > >>> + if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { > >>> + adev->pm.dpm.tdp_limit = le32_to_cpu(power_info- > >>> pplib5.ulTDPLimit); > >>> + adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info- > >>> pplib5.ulNearTDPLimit); > >>> + adev->pm.dpm.near_tdp_limit_adjusted = adev- > >>> pm.dpm.near_tdp_limit; > >>> + adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info- > >>> pplib5.usTDPODLimit); > >>> + if (adev->pm.dpm.tdp_od_limit) > >>> + adev->pm.dpm.power_control = true; > >>> + else > >>> + adev->pm.dpm.power_control = false; > >>> + adev->pm.dpm.tdp_adjustment = 0; > >>> + adev->pm.dpm.sq_ramping_threshold = > >> le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); > >>> + adev->pm.dpm.cac_leakage = le32_to_cpu(power_info- > >>> pplib5.ulCACLeakage); > >>> + adev->pm.dpm.load_line_slope = le16_to_cpu(power_info- > >>> pplib5.usLoadLineSlope); > >>> + if (power_info->pplib5.usCACLeakageTableOffset) { > >>> + ATOM_PPLIB_CAC_Leakage_Table *cac_table = > >>> + (ATOM_PPLIB_CAC_Leakage_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib5.usCACLeakageTableOffset)); > >>> + ATOM_PPLIB_CAC_Leakage_Record *entry; > >>> + u32 size = cac_table->ucNumEntries * sizeof(struct > >> amdgpu_cac_leakage_table); > >>> + adev->pm.dpm.dyn_state.cac_leakage_table.entries > >> = kzalloc(size, GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + entry = &cac_table->entries[0]; > >>> + for (i = 0; i < cac_table->ucNumEntries; i++) { > >>> + if (adev->pm.dpm.platform_caps & > >> ATOM_PP_PLATFORM_CAP_EVV) { > >>> + adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = > >>> + le16_to_cpu(entry- > >>> usVddc1); > >>> + adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = > >>> + le16_to_cpu(entry- > >>> usVddc2); > >>> + adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = > >>> + le16_to_cpu(entry- > >>> usVddc3); > >>> + } else { > >>> + adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = > >>> + le16_to_cpu(entry->usVddc); > >>> + adev- > >>> pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = > >>> + le32_to_cpu(entry- > >>> ulLeakageValue); > >>> + } > >>> + entry = (ATOM_PPLIB_CAC_Leakage_Record > >> *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_CAC_Leakage_Record)); > >>> + } > >>> + adev->pm.dpm.dyn_state.cac_leakage_table.count > >> = cac_table->ucNumEntries; > >>> + } > >>> + } > >>> + > >>> + /* ext tables */ > >>> + if (le16_to_cpu(power_info->pplib.usTableSize) >= > >>> + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { > >>> + ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = > >> (ATOM_PPLIB_EXTENDEDHEADER *) > >>> + (mode_info->atom_context->bios + data_offset + > >>> + le16_to_cpu(power_info- > >>> pplib3.usExtendendedHeaderOffset)); > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && > >>> + ext_hdr->usVCETableOffset) { > >>> + VCEClockInfoArray *array = (VCEClockInfoArray *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1); > >>> + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table > >> *limits = > >>> + > >> (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1 + > >>> + 1 + array->ucNumEntries * > >> sizeof(VCEClockInfo)); > >>> + ATOM_PPLIB_VCE_State_Table *states = > >>> + (ATOM_PPLIB_VCE_State_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usVCETableOffset) + > >> 1 + > >>> + 1 + (array->ucNumEntries * sizeof > >> (VCEClockInfo)) + > >>> + 1 + (limits->numEntries * > >> sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); > >>> + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record > >> *entry; > >>> + ATOM_PPLIB_VCE_State_Record *state_entry; > >>> + VCEClockInfo *vce_clk; > >>> + u32 size = limits->numEntries * > >>> + sizeof(struct > >> amdgpu_vce_clock_voltage_dependency_entry); > >>> + adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = > >>> + kzalloc(size, GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = > >>> + limits->numEntries; > >>> + entry = &limits->entries[0]; > >>> + state_entry = &states->entries[0]; > >>> + for (i = 0; i < limits->numEntries; i++) { > >>> + vce_clk = (VCEClockInfo *) > >>> + ((u8 *)&array->entries[0] + > >>> + (entry->ucVCEClockInfoIndex * > >> sizeof(VCEClockInfo))); > >>> + adev- > >>> > pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk > >> = > >>> + le16_to_cpu(vce_clk->usEVClkLow) | > >> (vce_clk->ucEVClkHigh << 16); > >>> + adev- > >>> > pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk > >> = > >>> + le16_to_cpu(vce_clk->usECClkLow) | > >> (vce_clk->ucECClkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = > >>> + le16_to_cpu(entry->usVoltage); > >>> + entry = > >> (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); > >>> + } > >>> + adev->pm.dpm.num_of_vce_states = > >>> + states->numEntries > > >> AMD_MAX_VCE_LEVELS ? > >>> + AMD_MAX_VCE_LEVELS : states- > >>> numEntries; > >>> + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) > >> { > >>> + vce_clk = (VCEClockInfo *) > >>> + ((u8 *)&array->entries[0] + > >>> + (state_entry->ucVCEClockInfoIndex > >> * sizeof(VCEClockInfo))); > >>> + adev->pm.dpm.vce_states[i].evclk = > >>> + le16_to_cpu(vce_clk->usEVClkLow) | > >> (vce_clk->ucEVClkHigh << 16); > >>> + adev->pm.dpm.vce_states[i].ecclk = > >>> + le16_to_cpu(vce_clk->usECClkLow) | > >> (vce_clk->ucECClkHigh << 16); > >>> + adev->pm.dpm.vce_states[i].clk_idx = > >>> + state_entry->ucClockInfoIndex & > >> 0x3f; > >>> + adev->pm.dpm.vce_states[i].pstate = > >>> + (state_entry->ucClockInfoIndex & > >> 0xc0) >> 6; > >>> + state_entry = > >> (ATOM_PPLIB_VCE_State_Record *) > >>> + ((u8 *)state_entry + > >> sizeof(ATOM_PPLIB_VCE_State_Record)); > >>> + } > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && > >>> + ext_hdr->usUVDTableOffset) { > >>> + UVDClockInfoArray *array = (UVDClockInfoArray *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usUVDTableOffset) + > >> 1); > >>> + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table > >> *limits = > >>> + > >> (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usUVDTableOffset) + > >> 1 + > >>> + 1 + (array->ucNumEntries * sizeof > >> (UVDClockInfo))); > >>> + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record > >> *entry; > >>> + u32 size = limits->numEntries * > >>> + sizeof(struct > >> amdgpu_uvd_clock_voltage_dependency_entry); > >>> + adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = > >>> + kzalloc(size, GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = > >>> + limits->numEntries; > >>> + entry = &limits->entries[0]; > >>> + for (i = 0; i < limits->numEntries; i++) { > >>> + UVDClockInfo *uvd_clk = (UVDClockInfo *) > >>> + ((u8 *)&array->entries[0] + > >>> + (entry->ucUVDClockInfoIndex * > >> sizeof(UVDClockInfo))); > >>> + adev- > >>> > pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = > >>> + le16_to_cpu(uvd_clk->usVClkLow) | > >> (uvd_clk->ucVClkHigh << 16); > >>> + adev- > >>> > pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = > >>> + le16_to_cpu(uvd_clk->usDClkLow) | > >> (uvd_clk->ucDClkHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = > >>> + le16_to_cpu(entry->usVoltage); > >>> + entry = > >> (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); > >>> + } > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && > >>> + ext_hdr->usSAMUTableOffset) { > >>> + ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = > >>> + (ATOM_PPLIB_SAMClk_Voltage_Limit_Table > >> *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usSAMUTableOffset) > >> + 1); > >>> + ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; > >>> + u32 size = limits->numEntries * > >>> + sizeof(struct > >> amdgpu_clock_voltage_dependency_entry); > >>> + adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = > >>> + kzalloc(size, GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = > >>> + limits->numEntries; > >>> + entry = &limits->entries[0]; > >>> + for (i = 0; i < limits->numEntries; i++) { > >>> + adev- > >>> > pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = > >>> + le16_to_cpu(entry->usSAMClockLow) > >> | (entry->ucSAMClockHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v > = > >>> + le16_to_cpu(entry->usVoltage); > >>> + entry = > >> (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); > >>> + } > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && > >>> + ext_hdr->usPPMTableOffset) { > >>> + ATOM_PPLIB_PPM_Table *ppm = > >> (ATOM_PPLIB_PPM_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usPPMTableOffset)); > >>> + adev->pm.dpm.dyn_state.ppm_table = > >>> + kzalloc(sizeof(struct amdgpu_ppm_table), > >> GFP_KERNEL); > >>> + if (!adev->pm.dpm.dyn_state.ppm_table) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + adev->pm.dpm.dyn_state.ppm_table->ppm_design > >> = ppm->ucPpmDesign; > >>> + adev->pm.dpm.dyn_state.ppm_table- > >>> cpu_core_number = > >>> + le16_to_cpu(ppm->usCpuCoreNumber); > >>> + adev->pm.dpm.dyn_state.ppm_table- > >>> platform_tdp = > >>> + le32_to_cpu(ppm->ulPlatformTDP); > >>> + adev->pm.dpm.dyn_state.ppm_table- > >>> small_ac_platform_tdp = > >>> + le32_to_cpu(ppm->ulSmallACPlatformTDP); > >>> + adev->pm.dpm.dyn_state.ppm_table->platform_tdc > >> = > >>> + le32_to_cpu(ppm->ulPlatformTDC); > >>> + adev->pm.dpm.dyn_state.ppm_table- > >>> small_ac_platform_tdc = > >>> + le32_to_cpu(ppm->ulSmallACPlatformTDC); > >>> + adev->pm.dpm.dyn_state.ppm_table->apu_tdp = > >>> + le32_to_cpu(ppm->ulApuTDP); > >>> + adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = > >>> + le32_to_cpu(ppm->ulDGpuTDP); > >>> + adev->pm.dpm.dyn_state.ppm_table- > >>> dgpu_ulv_power = > >>> + le32_to_cpu(ppm->ulDGpuUlvPower); > >>> + adev->pm.dpm.dyn_state.ppm_table->tj_max = > >>> + le32_to_cpu(ppm->ulTjmax); > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && > >>> + ext_hdr->usACPTableOffset) { > >>> + ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = > >>> + (ATOM_PPLIB_ACPClk_Voltage_Limit_Table > >> *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr->usACPTableOffset) + > >> 1); > >>> + ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; > >>> + u32 size = limits->numEntries * > >>> + sizeof(struct > >> amdgpu_clock_voltage_dependency_entry); > >>> + adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = > >>> + kzalloc(size, GFP_KERNEL); > >>> + if (!adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = > >>> + limits->numEntries; > >>> + entry = &limits->entries[0]; > >>> + for (i = 0; i < limits->numEntries; i++) { > >>> + adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk > = > >>> + le16_to_cpu(entry->usACPClockLow) > >> | (entry->ucACPClockHigh << 16); > >>> + adev- > >>> pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = > >>> + le16_to_cpu(entry->usVoltage); > >>> + entry = > >> (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) > >>> + ((u8 *)entry + > >> sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); > >>> + } > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && > >>> + ext_hdr->usPowerTuneTableOffset) { > >>> + u8 rev = *(u8 *)(mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> + ATOM_PowerTune_Table *pt; > >>> + adev->pm.dpm.dyn_state.cac_tdp_table = > >>> + kzalloc(sizeof(struct amdgpu_cac_tdp_table), > >> GFP_KERNEL); > >>> + if (!adev->pm.dpm.dyn_state.cac_tdp_table) { > >>> + > >> amdgpu_free_extended_power_table(adev); > >>> + return -ENOMEM; > >>> + } > >>> + if (rev > 0) { > >>> + ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = > >> (ATOM_PPLIB_POWERTUNE_Table_V1 *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> maximum_power_delivery_limit = > >>> + ppt->usMaximumPowerDeliveryLimit; > >>> + pt = &ppt->power_tune_table; > >>> + } else { > >>> + ATOM_PPLIB_POWERTUNE_Table *ppt = > >> (ATOM_PPLIB_POWERTUNE_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr- > >>> usPowerTuneTableOffset)); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> maximum_power_delivery_limit = 255; > >>> + pt = &ppt->power_tune_table; > >>> + } > >>> + adev->pm.dpm.dyn_state.cac_tdp_table->tdp = > >> le16_to_cpu(pt->usTDP); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> configurable_tdp = > >>> + le16_to_cpu(pt->usConfigurableTDP); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table->tdc = > >> le16_to_cpu(pt->usTDC); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> battery_power_limit = > >>> + le16_to_cpu(pt->usBatteryPowerLimit); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> small_power_limit = > >>> + le16_to_cpu(pt->usSmallPowerLimit); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> low_cac_leakage = > >>> + le16_to_cpu(pt->usLowCACLeakage); > >>> + adev->pm.dpm.dyn_state.cac_tdp_table- > >>> high_cac_leakage = > >>> + le16_to_cpu(pt->usHighCACLeakage); > >>> + } > >>> + if ((le16_to_cpu(ext_hdr->usSize) >= > >> SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && > >>> + ext_hdr->usSclkVddgfxTableOffset) { > >>> + dep_table = > >> (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) > >>> + (mode_info->atom_context->bios + > >> data_offset + > >>> + le16_to_cpu(ext_hdr- > >>> usSclkVddgfxTableOffset)); > >>> + ret = amdgpu_parse_clk_voltage_dep_table( > >>> + &adev- > >>> pm.dpm.dyn_state.vddgfx_dependency_on_sclk, > >>> + dep_table); > >>> + if (ret) { > >>> + kfree(adev- > >>> pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); > >>> + return ret; > >>> + } > >>> + } > >>> + } > >>> + > >>> + return 0; > >>> +} > >>> + > >>> +void amdgpu_free_extended_power_table(struct amdgpu_device > *adev) > >>> +{ > >>> + struct amdgpu_dpm_dynamic_state *dyn_state = &adev- > >>> pm.dpm.dyn_state; > >>> + > >>> + kfree(dyn_state->vddc_dependency_on_sclk.entries); > >>> + kfree(dyn_state->vddci_dependency_on_mclk.entries); > >>> + kfree(dyn_state->vddc_dependency_on_mclk.entries); > >>> + kfree(dyn_state->mvdd_dependency_on_mclk.entries); > >>> + kfree(dyn_state->cac_leakage_table.entries); > >>> + kfree(dyn_state->phase_shedding_limits_table.entries); > >>> + kfree(dyn_state->ppm_table); > >>> + kfree(dyn_state->cac_tdp_table); > >>> + kfree(dyn_state->vce_clock_voltage_dependency_table.entries); > >>> + kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); > >>> + kfree(dyn_state->samu_clock_voltage_dependency_table.entries); > >>> + kfree(dyn_state->acp_clock_voltage_dependency_table.entries); > >>> + kfree(dyn_state->vddgfx_dependency_on_sclk.entries); > >>> +} > >>> + > >>> +static const char *pp_lib_thermal_controller_names[] = { > >>> + "NONE", > >>> + "lm63", > >>> + "adm1032", > >>> + "adm1030", > >>> + "max6649", > >>> + "lm64", > >>> + "f75375", > >>> + "RV6xx", > >>> + "RV770", > >>> + "adt7473", > >>> + "NONE", > >>> + "External GPIO", > >>> + "Evergreen", > >>> + "emc2103", > >>> + "Sumo", > >>> + "Northern Islands", > >>> + "Southern Islands", > >>> + "lm96163", > >>> + "Sea Islands", > >>> + "Kaveri/Kabini", > >>> +}; > >>> + > >>> +void amdgpu_add_thermal_controller(struct amdgpu_device *adev) > >>> +{ > >>> + struct amdgpu_mode_info *mode_info = &adev->mode_info; > >>> + ATOM_PPLIB_POWERPLAYTABLE *power_table; > >>> + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); > >>> + ATOM_PPLIB_THERMALCONTROLLER *controller; > >>> + struct amdgpu_i2c_bus_rec i2c_bus; > >>> + u16 data_offset; > >>> + u8 frev, crev; > >>> + > >>> + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, > >> index, NULL, > >>> + &frev, &crev, &data_offset)) > >>> + return; > >>> + power_table = (ATOM_PPLIB_POWERPLAYTABLE *) > >>> + (mode_info->atom_context->bios + data_offset); > >>> + controller = &power_table->sThermalController; > >>> + > >>> + /* add the i2c bus for thermal/fan chip */ > >>> + if (controller->ucType > 0) { > >>> + if (controller->ucFanParameters & > >> ATOM_PP_FANPARAMETERS_NOFAN) > >>> + adev->pm.no_fan = true; > >>> + adev->pm.fan_pulses_per_revolution = > >>> + controller->ucFanParameters & > >> > ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_M > >> ASK; > >>> + if (adev->pm.fan_pulses_per_revolution) { > >>> + adev->pm.fan_min_rpm = controller->ucFanMinRPM; > >>> + adev->pm.fan_max_rpm = controller- > >>> ucFanMaxRPM; > >>> + } > >>> + if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_RV6xx) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_RV6XX; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_RV770) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_RV770; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_EVERGREEN) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_EVERGREEN; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_SUMO) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_SUMO; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_NISLANDS) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = THERMAL_TYPE_NI; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_SISLANDS) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = THERMAL_TYPE_SI; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_CISLANDS) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = THERMAL_TYPE_CI; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_KAVERI) { > >>> + DRM_INFO("Internal thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = THERMAL_TYPE_KV; > >>> + } else if (controller->ucType == > >> ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { > >>> + DRM_INFO("External GPIO thermal controller %s fan > >> control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_EXTERNAL_GPIO; > >>> + } else if (controller->ucType == > >>> + > >> ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { > >>> + DRM_INFO("ADT7473 with internal thermal > >> controller %s fan control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_ADT7473_WITH_INTERNAL; > >>> + } else if (controller->ucType == > >>> + > >> ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { > >>> + DRM_INFO("EMC2103 with internal thermal > >> controller %s fan control\n", > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_EMC2103_WITH_INTERNAL; > >>> + } else if (controller->ucType < > >> ARRAY_SIZE(pp_lib_thermal_controller_names)) { > >>> + DRM_INFO("Possible %s thermal controller at > >> 0x%02x %s fan control\n", > >>> + > >> pp_lib_thermal_controller_names[controller->ucType], > >>> + controller->ucI2cAddress >> 1, > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + adev->pm.int_thermal_type = > >> THERMAL_TYPE_EXTERNAL; > >>> + i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, > >> controller->ucI2cLine); > >>> + adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, > >> &i2c_bus); > >>> + if (adev->pm.i2c_bus) { > >>> + struct i2c_board_info info = { }; > >>> + const char *name = > >> pp_lib_thermal_controller_names[controller->ucType]; > >>> + info.addr = controller->ucI2cAddress >> 1; > >>> + strlcpy(info.type, name, sizeof(info.type)); > >>> + i2c_new_client_device(&adev->pm.i2c_bus- > >>> adapter, &info); > >>> + } > >>> + } else { > >>> + DRM_INFO("Unknown thermal controller type %d at > >> 0x%02x %s fan control\n", > >>> + controller->ucType, > >>> + controller->ucI2cAddress >> 1, > >>> + (controller->ucFanParameters & > >>> + ATOM_PP_FANPARAMETERS_NOFAN) ? > >> "without" : "with"); > >>> + } > >>> + } > >>> +} > >>> + > >>> +struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, > u32 > >> idx) > >>> +{ > >>> + struct amdgpu_device *adev = (struct amdgpu_device *)handle; > >>> + > >>> + if (idx < adev->pm.dpm.num_of_vce_states) > >>> + return &adev->pm.dpm.vce_states[idx]; > >>> + > >>> + return NULL; > >>> +} > >>> + > >>> +static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct > >> amdgpu_device *adev, > >>> + enum > >> amd_pm_state_type dpm_state) > >>> +{ > >>> + int i; > >>> + struct amdgpu_ps *ps; > >>> + u32 ui_class; > >>> + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? > >>> + true : false; > >>> + > >>> + /* check if the vblank period is too short to adjust the mclk */ > >>> + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) > >> { > >>> + if (amdgpu_dpm_vblank_too_short(adev)) > >>> + single_display = false; > >>> + } > >>> + > >>> + /* certain older asics have a separare 3D performance state, > >>> + * so try that first if the user selected performance > >>> + */ > >>> + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) > >>> + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; > >>> + /* balanced states don't exist at the moment */ > >>> + if (dpm_state == POWER_STATE_TYPE_BALANCED) > >>> + dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> + > >>> +restart_search: > >>> + /* Pick the best power state based on current conditions */ > >>> + for (i = 0; i < adev->pm.dpm.num_ps; i++) { > >>> + ps = &adev->pm.dpm.ps[i]; > >>> + ui_class = ps->class & > >> ATOM_PPLIB_CLASSIFICATION_UI_MASK; > >>> + switch (dpm_state) { > >>> + /* user states */ > >>> + case POWER_STATE_TYPE_BATTERY: > >>> + if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { > >>> + if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> + if (single_display) > >>> + return ps; > >>> + } else > >>> + return ps; > >>> + } > >>> + break; > >>> + case POWER_STATE_TYPE_BALANCED: > >>> + if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { > >>> + if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> + if (single_display) > >>> + return ps; > >>> + } else > >>> + return ps; > >>> + } > >>> + break; > >>> + case POWER_STATE_TYPE_PERFORMANCE: > >>> + if (ui_class == > >> ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { > >>> + if (ps->caps & > >> ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { > >>> + if (single_display) > >>> + return ps; > >>> + } else > >>> + return ps; > >>> + } > >>> + break; > >>> + /* internal states */ > >>> + case POWER_STATE_TYPE_INTERNAL_UVD: > >>> + if (adev->pm.dpm.uvd_ps) > >>> + return adev->pm.dpm.uvd_ps; > >>> + else > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_SD: > >>> + if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_SDSTATE) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_HD: > >>> + if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_HDSTATE) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: > >>> + if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_HD2STATE) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: > >>> + if (ps->class2 & > >> ATOM_PPLIB_CLASSIFICATION2_MVC) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_BOOT: > >>> + return adev->pm.dpm.boot_ps; > >>> + case POWER_STATE_TYPE_INTERNAL_THERMAL: > >>> + if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_THERMAL) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_ACPI: > >>> + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_ULV: > >>> + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) > >>> + return ps; > >>> + break; > >>> + case POWER_STATE_TYPE_INTERNAL_3DPERF: > >>> + if (ps->class & > >> ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) > >>> + return ps; > >>> + break; > >>> + default: > >>> + break; > >>> + } > >>> + } > >>> + /* use a fallback state if we didn't match */ > >>> + switch (dpm_state) { > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_SD: > >>> + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; > >>> + goto restart_search; > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_HD: > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: > >>> + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: > >>> + if (adev->pm.dpm.uvd_ps) { > >>> + return adev->pm.dpm.uvd_ps; > >>> + } else { > >>> + dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> + goto restart_search; > >>> + } > >>> + case POWER_STATE_TYPE_INTERNAL_THERMAL: > >>> + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; > >>> + goto restart_search; > >>> + case POWER_STATE_TYPE_INTERNAL_ACPI: > >>> + dpm_state = POWER_STATE_TYPE_BATTERY; > >>> + goto restart_search; > >>> + case POWER_STATE_TYPE_BATTERY: > >>> + case POWER_STATE_TYPE_BALANCED: > >>> + case POWER_STATE_TYPE_INTERNAL_3DPERF: > >>> + dpm_state = POWER_STATE_TYPE_PERFORMANCE; > >>> + goto restart_search; > >>> + default: > >>> + break; > >>> + } > >>> + > >>> + return NULL; > >>> +} > >>> + > >>> +int amdgpu_dpm_change_power_state_locked(void *handle) > >>> +{ > >>> + struct amdgpu_device *adev = (struct amdgpu_device *)handle; > >>> + struct amdgpu_ps *ps; > >>> + enum amd_pm_state_type dpm_state; > >>> + int ret; > >>> + bool equal = false; > >>> + > >>> + /* if dpm init failed */ > >>> + if (!adev->pm.dpm_enabled) > >>> + return 0; > >>> + > >>> + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { > >>> + /* add other state override checks here */ > >>> + if ((!adev->pm.dpm.thermal_active) && > >>> + (!adev->pm.dpm.uvd_active)) > >>> + adev->pm.dpm.state = adev->pm.dpm.user_state; > >>> + } > >>> + dpm_state = adev->pm.dpm.state; > >>> + > >>> + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); > >>> + if (ps) > >>> + adev->pm.dpm.requested_ps = ps; > >>> + else > >>> + return -EINVAL; > >>> + > >>> + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs- > >>> print_power_state) { > >>> + printk("switching from power state:\n"); > >>> + amdgpu_dpm_print_power_state(adev, adev- > >>> pm.dpm.current_ps); > >>> + printk("switching to power state:\n"); > >>> + amdgpu_dpm_print_power_state(adev, adev- > >>> pm.dpm.requested_ps); > >>> + } > >>> + > >>> + /* update whether vce is active */ > >>> + ps->vce_active = adev->pm.dpm.vce_active; > >>> + if (adev->powerplay.pp_funcs->display_configuration_changed) > >>> + amdgpu_dpm_display_configuration_changed(adev); > >>> + > >>> + ret = amdgpu_dpm_pre_set_power_state(adev); > >>> + if (ret) > >>> + return ret; > >>> + > >>> + if (adev->powerplay.pp_funcs->check_state_equal) { > >>> + if (0 != amdgpu_dpm_check_state_equal(adev, adev- > >>> pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) > >>> + equal = false; > >>> + } > >>> + > >>> + if (equal) > >>> + return 0; > >>> + > >>> + if (adev->powerplay.pp_funcs->set_power_state) > >>> + adev->powerplay.pp_funcs->set_power_state(adev- > >>> powerplay.pp_handle); > >>> + > >>> + amdgpu_dpm_post_set_power_state(adev); > >>> + > >>> + adev->pm.dpm.current_active_crtcs = adev- > >>> pm.dpm.new_active_crtcs; > >>> + adev->pm.dpm.current_active_crtc_count = adev- > >>> pm.dpm.new_active_crtc_count; > >>> + > >>> + if (adev->powerplay.pp_funcs->force_performance_level) { > >>> + if (adev->pm.dpm.thermal_active) { > >>> + enum amd_dpm_forced_level level = adev- > >>> pm.dpm.forced_level; > >>> + /* force low perf level for thermal */ > >>> + amdgpu_dpm_force_performance_level(adev, > >> AMD_DPM_FORCED_LEVEL_LOW); > >>> + /* save the user's level */ > >>> + adev->pm.dpm.forced_level = level; > >>> + } else { > >>> + /* otherwise, user selected level */ > >>> + amdgpu_dpm_force_performance_level(adev, > >> adev->pm.dpm.forced_level); > >>> + } > >>> + } > >>> + > >>> + return 0; > >>> +} > >>> diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h > >> b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h > >>> new file mode 100644 > >>> index 000000000000..4adc765c8824 > >>> --- /dev/null > >>> +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h > >>> @@ -0,0 +1,70 @@ > >>> +/* > >>> + * Copyright 2021 Advanced Micro Devices, Inc. > >>> + * > >>> + * Permission is hereby granted, free of charge, to any person obtaining > a > >>> + * copy of this software and associated documentation files (the > >> "Software"), > >>> + * to deal in the Software without restriction, including without > limitation > >>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > >>> + * and/or sell copies of the Software, and to permit persons to whom > the > >>> + * Software is furnished to do so, subject to the following conditions: > >>> + * > >>> + * The above copyright notice and this permission notice shall be > included > >> in > >>> + * all copies or substantial portions of the Software. > >>> + * > >>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY > >> KIND, EXPRESS OR > >>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > >> MERCHANTABILITY, > >>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN > >> NO EVENT SHALL > >>> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, > >> DAMAGES OR > >>> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR > >> OTHERWISE, > >>> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE > OR > >> THE USE OR > >>> + * OTHER DEALINGS IN THE SOFTWARE. > >>> + * > >>> + */ > >>> +#ifndef __LEGACY_DPM_H__ > >>> +#define __LEGACY_DPM_H__ > >>> + > >>> +int amdgpu_atombios_get_memory_pll_dividers(struct > amdgpu_device > >> *adev, > >>> + u32 clock, > >>> + bool strobe_mode, > >>> + struct atom_mpll_param > >> *mpll_param); > >>> + > >>> +void amdgpu_atombios_set_engine_dram_timings(struct > >> amdgpu_device *adev, > >>> + u32 eng_clock, u32 mem_clock); > >>> + > >>> +void amdgpu_atombios_get_default_voltages(struct amdgpu_device > >> *adev, > >>> + u16 *vddc, u16 *vddci, u16 *mvdd); > >>> + > >>> +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); > >>> + > >>> +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, > >>> + u8 voltage_type, > >>> + u8 *svd_gpio_id, u8 *svc_gpio_id); > >>> + > >>> +bool > >>> +amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev, > >>> + u8 voltage_type, u8 voltage_mode); > >>> +int amdgpu_atombios_get_voltage_table(struct amdgpu_device > *adev, > >>> + u8 voltage_type, u8 voltage_mode, > >>> + struct atom_voltage_table > >> *voltage_table); > >>> + > >>> +int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device > *adev, > >>> + u8 module_index, > >>> + struct atom_mc_reg_table *reg_table); > >>> + > >>> +void amdgpu_dpm_print_class_info(u32 class, u32 class2); > >>> +void amdgpu_dpm_print_cap_info(u32 caps); > >>> +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, > >>> + struct amdgpu_ps *rps); > >>> +int amdgpu_get_platform_caps(struct amdgpu_device *adev); > >>> +int amdgpu_parse_extended_power_table(struct amdgpu_device > >> *adev); > >>> +void amdgpu_free_extended_power_table(struct amdgpu_device > >> *adev); > >>> +void amdgpu_add_thermal_controller(struct amdgpu_device *adev); > >>> +struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, > u32 > >> idx); > >>> +int amdgpu_dpm_change_power_state_locked(void *handle); > >>> +void amdgpu_pm_print_power_states(struct amdgpu_device *adev); > >>> +#endif > >>> diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c > >> b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c > >>> index 4f84d8b893f1..a2881c90d187 100644 > >>> --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c > >>> +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c > >>> @@ -37,6 +37,7 @@ > >>> #include <linux/math64.h> > >>> #include <linux/seq_file.h> > >>> #include <linux/firmware.h> > >>> +#include <legacy_dpm.h> > >>> > >>> #define MC_CG_ARB_FREQ_F0 0x0a > >>> #define MC_CG_ARB_FREQ_F1 0x0b > >>> @@ -8101,6 +8102,7 @@ static const struct amd_pm_funcs > si_dpm_funcs > >> = { > >>> .check_state_equal = &si_check_state_equal, > >>> .get_vce_clock_state = amdgpu_get_vce_clock_state, > >>> .read_sensor = &si_dpm_read_sensor, > >>> + .change_power_state = amdgpu_dpm_change_power_state_locked, > >>> }; > >>> > >>> static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { > >>>