Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/pm: create a new holder for those APIs used only by legacy ASICs(si/kv)

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@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Evan Quan and committed by
Alex Deucher
84176663 28a31774

+1091 -1034
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
··· 2532 2532 break; 2533 2533 } 2534 2534 /* adjust pm to dpms */ 2535 - amdgpu_pm_compute_clocks(adev); 2535 + amdgpu_dpm_compute_clocks(adev); 2536 2536 } 2537 2537 2538 2538 static void dce_v10_0_crtc_prepare(struct drm_crtc *crtc)
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
··· 2608 2608 break; 2609 2609 } 2610 2610 /* adjust pm to dpms */ 2611 - amdgpu_pm_compute_clocks(adev); 2611 + amdgpu_dpm_compute_clocks(adev); 2612 2612 } 2613 2613 2614 2614 static void dce_v11_0_crtc_prepare(struct drm_crtc *crtc)
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
··· 2424 2424 break; 2425 2425 } 2426 2426 /* adjust pm to dpms */ 2427 - amdgpu_pm_compute_clocks(adev); 2427 + amdgpu_dpm_compute_clocks(adev); 2428 2428 } 2429 2429 2430 2430 static void dce_v6_0_crtc_prepare(struct drm_crtc *crtc)
+1 -1
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
··· 2433 2433 break; 2434 2434 } 2435 2435 /* adjust pm to dpms */ 2436 - amdgpu_pm_compute_clocks(adev); 2436 + amdgpu_dpm_compute_clocks(adev); 2437 2437 } 2438 2438 2439 2439 static void dce_v8_0_crtc_prepare(struct drm_crtc *crtc)
+1 -1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
··· 101 101 102 102 amdgpu_dpm_display_configuration_change(adev, &adev->pm.pm_display_cfg); 103 103 104 - amdgpu_pm_compute_clocks(adev); 104 + amdgpu_dpm_compute_clocks(adev); 105 105 } 106 106 107 107 return true;
+1
drivers/gpu/drm/amd/include/kgd_pp_interface.h
··· 404 404 int (*get_dpm_clock_table)(void *handle, 405 405 struct dpm_clocks *clock_table); 406 406 int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t *size); 407 + int (*change_power_state)(void *handle); 407 408 }; 408 409 409 410 struct metrics_table_header {
+14 -1008
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
··· 34 34 35 35 #define WIDTH_4K 3840 36 36 37 - #define amdgpu_dpm_pre_set_power_state(adev) \ 38 - ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) 39 - 40 - #define amdgpu_dpm_post_set_power_state(adev) \ 41 - ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) 42 - 43 - #define amdgpu_dpm_display_configuration_changed(adev) \ 44 - ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) 45 - 46 - #define amdgpu_dpm_print_power_state(adev, ps) \ 47 - ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) 48 - 49 - #define amdgpu_dpm_vblank_too_short(adev) \ 50 - ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) 51 - 52 37 #define amdgpu_dpm_enable_bapm(adev, e) \ 53 38 ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) 54 - 55 - #define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ 56 - ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) 57 - 58 - void amdgpu_dpm_print_class_info(u32 class, u32 class2) 59 - { 60 - const char *s; 61 - 62 - switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 63 - case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 64 - default: 65 - s = "none"; 66 - break; 67 - case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 68 - s = "battery"; 69 - break; 70 - case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 71 - s = "balanced"; 72 - break; 73 - case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 74 - s = "performance"; 75 - break; 76 - } 77 - printk("\tui class: %s\n", s); 78 - printk("\tinternal class:"); 79 - if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && 80 - (class2 == 0)) 81 - pr_cont(" none"); 82 - else { 83 - if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) 84 - pr_cont(" boot"); 85 - if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 86 - pr_cont(" thermal"); 87 - if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 88 - pr_cont(" limited_pwr"); 89 - if (class & ATOM_PPLIB_CLASSIFICATION_REST) 90 - pr_cont(" rest"); 91 - if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) 92 - pr_cont(" forced"); 93 - if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 94 - pr_cont(" 3d_perf"); 95 - if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 96 - pr_cont(" ovrdrv"); 97 - if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 98 - pr_cont(" uvd"); 99 - if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) 100 - pr_cont(" 3d_low"); 101 - if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) 102 - pr_cont(" acpi"); 103 - if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 104 - pr_cont(" uvd_hd2"); 105 - if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 106 - pr_cont(" uvd_hd"); 107 - if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 108 - pr_cont(" uvd_sd"); 109 - if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 110 - pr_cont(" limited_pwr2"); 111 - if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 112 - pr_cont(" ulv"); 113 - if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 114 - pr_cont(" uvd_mvc"); 115 - } 116 - pr_cont("\n"); 117 - } 118 - 119 - void amdgpu_dpm_print_cap_info(u32 caps) 120 - { 121 - printk("\tcaps:"); 122 - if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 123 - pr_cont(" single_disp"); 124 - if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) 125 - pr_cont(" video"); 126 - if (caps & ATOM_PPLIB_DISALLOW_ON_DC) 127 - pr_cont(" no_dc"); 128 - pr_cont("\n"); 129 - } 130 - 131 - void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, 132 - struct amdgpu_ps *rps) 133 - { 134 - printk("\tstatus:"); 135 - if (rps == adev->pm.dpm.current_ps) 136 - pr_cont(" c"); 137 - if (rps == adev->pm.dpm.requested_ps) 138 - pr_cont(" r"); 139 - if (rps == adev->pm.dpm.boot_ps) 140 - pr_cont(" b"); 141 - pr_cont("\n"); 142 - } 143 39 144 40 static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) 145 41 { ··· 56 160 } 57 161 } 58 162 } 59 - 60 163 61 164 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) 62 165 { ··· 102 207 } 103 208 104 209 return vrefresh; 105 - } 106 - 107 - union power_info { 108 - struct _ATOM_POWERPLAY_INFO info; 109 - struct _ATOM_POWERPLAY_INFO_V2 info_2; 110 - struct _ATOM_POWERPLAY_INFO_V3 info_3; 111 - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 112 - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 113 - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 114 - struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 115 - struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 116 - }; 117 - 118 - union fan_info { 119 - struct _ATOM_PPLIB_FANTABLE fan; 120 - struct _ATOM_PPLIB_FANTABLE2 fan2; 121 - struct _ATOM_PPLIB_FANTABLE3 fan3; 122 - }; 123 - 124 - static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, 125 - ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) 126 - { 127 - u32 size = atom_table->ucNumEntries * 128 - sizeof(struct amdgpu_clock_voltage_dependency_entry); 129 - int i; 130 - ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; 131 - 132 - amdgpu_table->entries = kzalloc(size, GFP_KERNEL); 133 - if (!amdgpu_table->entries) 134 - return -ENOMEM; 135 - 136 - entry = &atom_table->entries[0]; 137 - for (i = 0; i < atom_table->ucNumEntries; i++) { 138 - amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | 139 - (entry->ucClockHigh << 16); 140 - amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); 141 - entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) 142 - ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); 143 - } 144 - amdgpu_table->count = atom_table->ucNumEntries; 145 - 146 - return 0; 147 - } 148 - 149 - int amdgpu_get_platform_caps(struct amdgpu_device *adev) 150 - { 151 - struct amdgpu_mode_info *mode_info = &adev->mode_info; 152 - union power_info *power_info; 153 - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 154 - u16 data_offset; 155 - u8 frev, crev; 156 - 157 - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 158 - &frev, &crev, &data_offset)) 159 - return -EINVAL; 160 - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 161 - 162 - adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 163 - adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 164 - adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 165 - 166 - return 0; 167 - } 168 - 169 - /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ 170 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 171 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 172 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 173 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 174 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 175 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 176 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 177 - #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 178 - 179 - int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) 180 - { 181 - struct amdgpu_mode_info *mode_info = &adev->mode_info; 182 - union power_info *power_info; 183 - union fan_info *fan_info; 184 - ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; 185 - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 186 - u16 data_offset; 187 - u8 frev, crev; 188 - int ret, i; 189 - 190 - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 191 - &frev, &crev, &data_offset)) 192 - return -EINVAL; 193 - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 194 - 195 - /* fan table */ 196 - if (le16_to_cpu(power_info->pplib.usTableSize) >= 197 - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 198 - if (power_info->pplib3.usFanTableOffset) { 199 - fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + 200 - le16_to_cpu(power_info->pplib3.usFanTableOffset)); 201 - adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; 202 - adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); 203 - adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); 204 - adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); 205 - adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); 206 - adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); 207 - adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); 208 - if (fan_info->fan.ucFanTableFormat >= 2) 209 - adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); 210 - else 211 - adev->pm.dpm.fan.t_max = 10900; 212 - adev->pm.dpm.fan.cycle_delay = 100000; 213 - if (fan_info->fan.ucFanTableFormat >= 3) { 214 - adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 215 - adev->pm.dpm.fan.default_max_fan_pwm = 216 - le16_to_cpu(fan_info->fan3.usFanPWMMax); 217 - adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 218 - adev->pm.dpm.fan.fan_output_sensitivity = 219 - le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 220 - } 221 - adev->pm.dpm.fan.ucode_fan_control = true; 222 - } 223 - } 224 - 225 - /* clock dependancy tables, shedding tables */ 226 - if (le16_to_cpu(power_info->pplib.usTableSize) >= 227 - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { 228 - if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { 229 - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 230 - (mode_info->atom_context->bios + data_offset + 231 - le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 232 - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 233 - dep_table); 234 - if (ret) { 235 - amdgpu_free_extended_power_table(adev); 236 - return ret; 237 - } 238 - } 239 - if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 240 - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 241 - (mode_info->atom_context->bios + data_offset + 242 - le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 243 - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 244 - dep_table); 245 - if (ret) { 246 - amdgpu_free_extended_power_table(adev); 247 - return ret; 248 - } 249 - } 250 - if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 251 - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 252 - (mode_info->atom_context->bios + data_offset + 253 - le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 254 - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 255 - dep_table); 256 - if (ret) { 257 - amdgpu_free_extended_power_table(adev); 258 - return ret; 259 - } 260 - } 261 - if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 262 - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 263 - (mode_info->atom_context->bios + data_offset + 264 - le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 265 - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 266 - dep_table); 267 - if (ret) { 268 - amdgpu_free_extended_power_table(adev); 269 - return ret; 270 - } 271 - } 272 - if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 273 - ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = 274 - (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 275 - (mode_info->atom_context->bios + data_offset + 276 - le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); 277 - if (clk_v->ucNumEntries) { 278 - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = 279 - le16_to_cpu(clk_v->entries[0].usSclkLow) | 280 - (clk_v->entries[0].ucSclkHigh << 16); 281 - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = 282 - le16_to_cpu(clk_v->entries[0].usMclkLow) | 283 - (clk_v->entries[0].ucMclkHigh << 16); 284 - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = 285 - le16_to_cpu(clk_v->entries[0].usVddc); 286 - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = 287 - le16_to_cpu(clk_v->entries[0].usVddci); 288 - } 289 - } 290 - if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { 291 - ATOM_PPLIB_PhaseSheddingLimits_Table *psl = 292 - (ATOM_PPLIB_PhaseSheddingLimits_Table *) 293 - (mode_info->atom_context->bios + data_offset + 294 - le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); 295 - ATOM_PPLIB_PhaseSheddingLimits_Record *entry; 296 - 297 - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = 298 - kcalloc(psl->ucNumEntries, 299 - sizeof(struct amdgpu_phase_shedding_limits_entry), 300 - GFP_KERNEL); 301 - if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 302 - amdgpu_free_extended_power_table(adev); 303 - return -ENOMEM; 304 - } 305 - 306 - entry = &psl->entries[0]; 307 - for (i = 0; i < psl->ucNumEntries; i++) { 308 - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = 309 - le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); 310 - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = 311 - le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); 312 - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = 313 - le16_to_cpu(entry->usVoltage); 314 - entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) 315 - ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); 316 - } 317 - adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = 318 - psl->ucNumEntries; 319 - } 320 - } 321 - 322 - /* cac data */ 323 - if (le16_to_cpu(power_info->pplib.usTableSize) >= 324 - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { 325 - adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); 326 - adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); 327 - adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; 328 - adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); 329 - if (adev->pm.dpm.tdp_od_limit) 330 - adev->pm.dpm.power_control = true; 331 - else 332 - adev->pm.dpm.power_control = false; 333 - adev->pm.dpm.tdp_adjustment = 0; 334 - adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); 335 - adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); 336 - adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); 337 - if (power_info->pplib5.usCACLeakageTableOffset) { 338 - ATOM_PPLIB_CAC_Leakage_Table *cac_table = 339 - (ATOM_PPLIB_CAC_Leakage_Table *) 340 - (mode_info->atom_context->bios + data_offset + 341 - le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); 342 - ATOM_PPLIB_CAC_Leakage_Record *entry; 343 - u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); 344 - adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 345 - if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { 346 - amdgpu_free_extended_power_table(adev); 347 - return -ENOMEM; 348 - } 349 - entry = &cac_table->entries[0]; 350 - for (i = 0; i < cac_table->ucNumEntries; i++) { 351 - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { 352 - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = 353 - le16_to_cpu(entry->usVddc1); 354 - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = 355 - le16_to_cpu(entry->usVddc2); 356 - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = 357 - le16_to_cpu(entry->usVddc3); 358 - } else { 359 - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = 360 - le16_to_cpu(entry->usVddc); 361 - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = 362 - le32_to_cpu(entry->ulLeakageValue); 363 - } 364 - entry = (ATOM_PPLIB_CAC_Leakage_Record *) 365 - ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); 366 - } 367 - adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; 368 - } 369 - } 370 - 371 - /* ext tables */ 372 - if (le16_to_cpu(power_info->pplib.usTableSize) >= 373 - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 374 - ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) 375 - (mode_info->atom_context->bios + data_offset + 376 - le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); 377 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && 378 - ext_hdr->usVCETableOffset) { 379 - VCEClockInfoArray *array = (VCEClockInfoArray *) 380 - (mode_info->atom_context->bios + data_offset + 381 - le16_to_cpu(ext_hdr->usVCETableOffset) + 1); 382 - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = 383 - (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 384 - (mode_info->atom_context->bios + data_offset + 385 - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 386 - 1 + array->ucNumEntries * sizeof(VCEClockInfo)); 387 - ATOM_PPLIB_VCE_State_Table *states = 388 - (ATOM_PPLIB_VCE_State_Table *) 389 - (mode_info->atom_context->bios + data_offset + 390 - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 391 - 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + 392 - 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); 393 - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; 394 - ATOM_PPLIB_VCE_State_Record *state_entry; 395 - VCEClockInfo *vce_clk; 396 - u32 size = limits->numEntries * 397 - sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); 398 - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 399 - kzalloc(size, GFP_KERNEL); 400 - if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 401 - amdgpu_free_extended_power_table(adev); 402 - return -ENOMEM; 403 - } 404 - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 405 - limits->numEntries; 406 - entry = &limits->entries[0]; 407 - state_entry = &states->entries[0]; 408 - for (i = 0; i < limits->numEntries; i++) { 409 - vce_clk = (VCEClockInfo *) 410 - ((u8 *)&array->entries[0] + 411 - (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 412 - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = 413 - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 414 - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = 415 - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 416 - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = 417 - le16_to_cpu(entry->usVoltage); 418 - entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) 419 - ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); 420 - } 421 - adev->pm.dpm.num_of_vce_states = 422 - states->numEntries > AMD_MAX_VCE_LEVELS ? 423 - AMD_MAX_VCE_LEVELS : states->numEntries; 424 - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { 425 - vce_clk = (VCEClockInfo *) 426 - ((u8 *)&array->entries[0] + 427 - (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 428 - adev->pm.dpm.vce_states[i].evclk = 429 - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 430 - adev->pm.dpm.vce_states[i].ecclk = 431 - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 432 - adev->pm.dpm.vce_states[i].clk_idx = 433 - state_entry->ucClockInfoIndex & 0x3f; 434 - adev->pm.dpm.vce_states[i].pstate = 435 - (state_entry->ucClockInfoIndex & 0xc0) >> 6; 436 - state_entry = (ATOM_PPLIB_VCE_State_Record *) 437 - ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); 438 - } 439 - } 440 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && 441 - ext_hdr->usUVDTableOffset) { 442 - UVDClockInfoArray *array = (UVDClockInfoArray *) 443 - (mode_info->atom_context->bios + data_offset + 444 - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); 445 - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = 446 - (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 447 - (mode_info->atom_context->bios + data_offset + 448 - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + 449 - 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); 450 - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; 451 - u32 size = limits->numEntries * 452 - sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); 453 - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 454 - kzalloc(size, GFP_KERNEL); 455 - if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 456 - amdgpu_free_extended_power_table(adev); 457 - return -ENOMEM; 458 - } 459 - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 460 - limits->numEntries; 461 - entry = &limits->entries[0]; 462 - for (i = 0; i < limits->numEntries; i++) { 463 - UVDClockInfo *uvd_clk = (UVDClockInfo *) 464 - ((u8 *)&array->entries[0] + 465 - (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); 466 - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = 467 - le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); 468 - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = 469 - le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); 470 - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = 471 - le16_to_cpu(entry->usVoltage); 472 - entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) 473 - ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); 474 - } 475 - } 476 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && 477 - ext_hdr->usSAMUTableOffset) { 478 - ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = 479 - (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 480 - (mode_info->atom_context->bios + data_offset + 481 - le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); 482 - ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; 483 - u32 size = limits->numEntries * 484 - sizeof(struct amdgpu_clock_voltage_dependency_entry); 485 - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 486 - kzalloc(size, GFP_KERNEL); 487 - if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 488 - amdgpu_free_extended_power_table(adev); 489 - return -ENOMEM; 490 - } 491 - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 492 - limits->numEntries; 493 - entry = &limits->entries[0]; 494 - for (i = 0; i < limits->numEntries; i++) { 495 - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = 496 - le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); 497 - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = 498 - le16_to_cpu(entry->usVoltage); 499 - entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) 500 - ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); 501 - } 502 - } 503 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && 504 - ext_hdr->usPPMTableOffset) { 505 - ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) 506 - (mode_info->atom_context->bios + data_offset + 507 - le16_to_cpu(ext_hdr->usPPMTableOffset)); 508 - adev->pm.dpm.dyn_state.ppm_table = 509 - kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); 510 - if (!adev->pm.dpm.dyn_state.ppm_table) { 511 - amdgpu_free_extended_power_table(adev); 512 - return -ENOMEM; 513 - } 514 - adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 515 - adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 516 - le16_to_cpu(ppm->usCpuCoreNumber); 517 - adev->pm.dpm.dyn_state.ppm_table->platform_tdp = 518 - le32_to_cpu(ppm->ulPlatformTDP); 519 - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = 520 - le32_to_cpu(ppm->ulSmallACPlatformTDP); 521 - adev->pm.dpm.dyn_state.ppm_table->platform_tdc = 522 - le32_to_cpu(ppm->ulPlatformTDC); 523 - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = 524 - le32_to_cpu(ppm->ulSmallACPlatformTDC); 525 - adev->pm.dpm.dyn_state.ppm_table->apu_tdp = 526 - le32_to_cpu(ppm->ulApuTDP); 527 - adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = 528 - le32_to_cpu(ppm->ulDGpuTDP); 529 - adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = 530 - le32_to_cpu(ppm->ulDGpuUlvPower); 531 - adev->pm.dpm.dyn_state.ppm_table->tj_max = 532 - le32_to_cpu(ppm->ulTjmax); 533 - } 534 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && 535 - ext_hdr->usACPTableOffset) { 536 - ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = 537 - (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 538 - (mode_info->atom_context->bios + data_offset + 539 - le16_to_cpu(ext_hdr->usACPTableOffset) + 1); 540 - ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; 541 - u32 size = limits->numEntries * 542 - sizeof(struct amdgpu_clock_voltage_dependency_entry); 543 - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 544 - kzalloc(size, GFP_KERNEL); 545 - if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 546 - amdgpu_free_extended_power_table(adev); 547 - return -ENOMEM; 548 - } 549 - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 550 - limits->numEntries; 551 - entry = &limits->entries[0]; 552 - for (i = 0; i < limits->numEntries; i++) { 553 - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = 554 - le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); 555 - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = 556 - le16_to_cpu(entry->usVoltage); 557 - entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) 558 - ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); 559 - } 560 - } 561 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && 562 - ext_hdr->usPowerTuneTableOffset) { 563 - u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + 564 - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 565 - ATOM_PowerTune_Table *pt; 566 - adev->pm.dpm.dyn_state.cac_tdp_table = 567 - kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); 568 - if (!adev->pm.dpm.dyn_state.cac_tdp_table) { 569 - amdgpu_free_extended_power_table(adev); 570 - return -ENOMEM; 571 - } 572 - if (rev > 0) { 573 - ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 574 - (mode_info->atom_context->bios + data_offset + 575 - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 576 - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 577 - ppt->usMaximumPowerDeliveryLimit; 578 - pt = &ppt->power_tune_table; 579 - } else { 580 - ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) 581 - (mode_info->atom_context->bios + data_offset + 582 - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 583 - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; 584 - pt = &ppt->power_tune_table; 585 - } 586 - adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); 587 - adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = 588 - le16_to_cpu(pt->usConfigurableTDP); 589 - adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); 590 - adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = 591 - le16_to_cpu(pt->usBatteryPowerLimit); 592 - adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = 593 - le16_to_cpu(pt->usSmallPowerLimit); 594 - adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = 595 - le16_to_cpu(pt->usLowCACLeakage); 596 - adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = 597 - le16_to_cpu(pt->usHighCACLeakage); 598 - } 599 - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && 600 - ext_hdr->usSclkVddgfxTableOffset) { 601 - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 602 - (mode_info->atom_context->bios + data_offset + 603 - le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); 604 - ret = amdgpu_parse_clk_voltage_dep_table( 605 - &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, 606 - dep_table); 607 - if (ret) { 608 - kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); 609 - return ret; 610 - } 611 - } 612 - } 613 - 614 - return 0; 615 - } 616 - 617 - void amdgpu_free_extended_power_table(struct amdgpu_device *adev) 618 - { 619 - struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; 620 - 621 - kfree(dyn_state->vddc_dependency_on_sclk.entries); 622 - kfree(dyn_state->vddci_dependency_on_mclk.entries); 623 - kfree(dyn_state->vddc_dependency_on_mclk.entries); 624 - kfree(dyn_state->mvdd_dependency_on_mclk.entries); 625 - kfree(dyn_state->cac_leakage_table.entries); 626 - kfree(dyn_state->phase_shedding_limits_table.entries); 627 - kfree(dyn_state->ppm_table); 628 - kfree(dyn_state->cac_tdp_table); 629 - kfree(dyn_state->vce_clock_voltage_dependency_table.entries); 630 - kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); 631 - kfree(dyn_state->samu_clock_voltage_dependency_table.entries); 632 - kfree(dyn_state->acp_clock_voltage_dependency_table.entries); 633 - kfree(dyn_state->vddgfx_dependency_on_sclk.entries); 634 - } 635 - 636 - static const char *pp_lib_thermal_controller_names[] = { 637 - "NONE", 638 - "lm63", 639 - "adm1032", 640 - "adm1030", 641 - "max6649", 642 - "lm64", 643 - "f75375", 644 - "RV6xx", 645 - "RV770", 646 - "adt7473", 647 - "NONE", 648 - "External GPIO", 649 - "Evergreen", 650 - "emc2103", 651 - "Sumo", 652 - "Northern Islands", 653 - "Southern Islands", 654 - "lm96163", 655 - "Sea Islands", 656 - "Kaveri/Kabini", 657 - }; 658 - 659 - void amdgpu_add_thermal_controller(struct amdgpu_device *adev) 660 - { 661 - struct amdgpu_mode_info *mode_info = &adev->mode_info; 662 - ATOM_PPLIB_POWERPLAYTABLE *power_table; 663 - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 664 - ATOM_PPLIB_THERMALCONTROLLER *controller; 665 - struct amdgpu_i2c_bus_rec i2c_bus; 666 - u16 data_offset; 667 - u8 frev, crev; 668 - 669 - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 670 - &frev, &crev, &data_offset)) 671 - return; 672 - power_table = (ATOM_PPLIB_POWERPLAYTABLE *) 673 - (mode_info->atom_context->bios + data_offset); 674 - controller = &power_table->sThermalController; 675 - 676 - /* add the i2c bus for thermal/fan chip */ 677 - if (controller->ucType > 0) { 678 - if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) 679 - adev->pm.no_fan = true; 680 - adev->pm.fan_pulses_per_revolution = 681 - controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 682 - if (adev->pm.fan_pulses_per_revolution) { 683 - adev->pm.fan_min_rpm = controller->ucFanMinRPM; 684 - adev->pm.fan_max_rpm = controller->ucFanMaxRPM; 685 - } 686 - if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { 687 - DRM_INFO("Internal thermal controller %s fan control\n", 688 - (controller->ucFanParameters & 689 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 690 - adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; 691 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { 692 - DRM_INFO("Internal thermal controller %s fan control\n", 693 - (controller->ucFanParameters & 694 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 695 - adev->pm.int_thermal_type = THERMAL_TYPE_RV770; 696 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { 697 - DRM_INFO("Internal thermal controller %s fan control\n", 698 - (controller->ucFanParameters & 699 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 700 - adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; 701 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { 702 - DRM_INFO("Internal thermal controller %s fan control\n", 703 - (controller->ucFanParameters & 704 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 705 - adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; 706 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { 707 - DRM_INFO("Internal thermal controller %s fan control\n", 708 - (controller->ucFanParameters & 709 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 710 - adev->pm.int_thermal_type = THERMAL_TYPE_NI; 711 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { 712 - DRM_INFO("Internal thermal controller %s fan control\n", 713 - (controller->ucFanParameters & 714 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 715 - adev->pm.int_thermal_type = THERMAL_TYPE_SI; 716 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { 717 - DRM_INFO("Internal thermal controller %s fan control\n", 718 - (controller->ucFanParameters & 719 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 720 - adev->pm.int_thermal_type = THERMAL_TYPE_CI; 721 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { 722 - DRM_INFO("Internal thermal controller %s fan control\n", 723 - (controller->ucFanParameters & 724 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 725 - adev->pm.int_thermal_type = THERMAL_TYPE_KV; 726 - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { 727 - DRM_INFO("External GPIO thermal controller %s fan control\n", 728 - (controller->ucFanParameters & 729 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 730 - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; 731 - } else if (controller->ucType == 732 - ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { 733 - DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", 734 - (controller->ucFanParameters & 735 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 736 - adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; 737 - } else if (controller->ucType == 738 - ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { 739 - DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", 740 - (controller->ucFanParameters & 741 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 742 - adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; 743 - } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { 744 - DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", 745 - pp_lib_thermal_controller_names[controller->ucType], 746 - controller->ucI2cAddress >> 1, 747 - (controller->ucFanParameters & 748 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 749 - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; 750 - i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); 751 - adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); 752 - if (adev->pm.i2c_bus) { 753 - struct i2c_board_info info = { }; 754 - const char *name = pp_lib_thermal_controller_names[controller->ucType]; 755 - info.addr = controller->ucI2cAddress >> 1; 756 - strlcpy(info.type, name, sizeof(info.type)); 757 - i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); 758 - } 759 - } else { 760 - DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", 761 - controller->ucType, 762 - controller->ucI2cAddress >> 1, 763 - (controller->ucFanParameters & 764 - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 765 - } 766 - } 767 - } 768 - 769 - struct amd_vce_state* 770 - amdgpu_get_vce_clock_state(void *handle, u32 idx) 771 - { 772 - struct amdgpu_device *adev = (struct amdgpu_device *)handle; 773 - 774 - if (idx < adev->pm.dpm.num_of_vce_states) 775 - return &adev->pm.dpm.vce_states[idx]; 776 - 777 - return NULL; 778 210 } 779 211 780 212 int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) ··· 462 1240 adev->pm.dpm.state = dpm_state; 463 1241 mutex_unlock(&adev->pm.mutex); 464 1242 465 - amdgpu_pm_compute_clocks(adev); 1243 + amdgpu_dpm_compute_clocks(adev); 466 1244 } 467 1245 468 - static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, 469 - enum amd_pm_state_type dpm_state) 470 - { 471 - int i; 472 - struct amdgpu_ps *ps; 473 - u32 ui_class; 474 - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? 475 - true : false; 476 - 477 - /* check if the vblank period is too short to adjust the mclk */ 478 - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { 479 - if (amdgpu_dpm_vblank_too_short(adev)) 480 - single_display = false; 481 - } 482 - 483 - /* certain older asics have a separare 3D performance state, 484 - * so try that first if the user selected performance 485 - */ 486 - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) 487 - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; 488 - /* balanced states don't exist at the moment */ 489 - if (dpm_state == POWER_STATE_TYPE_BALANCED) 490 - dpm_state = POWER_STATE_TYPE_PERFORMANCE; 491 - 492 - restart_search: 493 - /* Pick the best power state based on current conditions */ 494 - for (i = 0; i < adev->pm.dpm.num_ps; i++) { 495 - ps = &adev->pm.dpm.ps[i]; 496 - ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; 497 - switch (dpm_state) { 498 - /* user states */ 499 - case POWER_STATE_TYPE_BATTERY: 500 - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { 501 - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 502 - if (single_display) 503 - return ps; 504 - } else 505 - return ps; 506 - } 507 - break; 508 - case POWER_STATE_TYPE_BALANCED: 509 - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { 510 - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 511 - if (single_display) 512 - return ps; 513 - } else 514 - return ps; 515 - } 516 - break; 517 - case POWER_STATE_TYPE_PERFORMANCE: 518 - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { 519 - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 520 - if (single_display) 521 - return ps; 522 - } else 523 - return ps; 524 - } 525 - break; 526 - /* internal states */ 527 - case POWER_STATE_TYPE_INTERNAL_UVD: 528 - if (adev->pm.dpm.uvd_ps) 529 - return adev->pm.dpm.uvd_ps; 530 - else 531 - break; 532 - case POWER_STATE_TYPE_INTERNAL_UVD_SD: 533 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 534 - return ps; 535 - break; 536 - case POWER_STATE_TYPE_INTERNAL_UVD_HD: 537 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 538 - return ps; 539 - break; 540 - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 541 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 542 - return ps; 543 - break; 544 - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 545 - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 546 - return ps; 547 - break; 548 - case POWER_STATE_TYPE_INTERNAL_BOOT: 549 - return adev->pm.dpm.boot_ps; 550 - case POWER_STATE_TYPE_INTERNAL_THERMAL: 551 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 552 - return ps; 553 - break; 554 - case POWER_STATE_TYPE_INTERNAL_ACPI: 555 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) 556 - return ps; 557 - break; 558 - case POWER_STATE_TYPE_INTERNAL_ULV: 559 - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 560 - return ps; 561 - break; 562 - case POWER_STATE_TYPE_INTERNAL_3DPERF: 563 - if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 564 - return ps; 565 - break; 566 - default: 567 - break; 568 - } 569 - } 570 - /* use a fallback state if we didn't match */ 571 - switch (dpm_state) { 572 - case POWER_STATE_TYPE_INTERNAL_UVD_SD: 573 - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; 574 - goto restart_search; 575 - case POWER_STATE_TYPE_INTERNAL_UVD_HD: 576 - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 577 - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 578 - if (adev->pm.dpm.uvd_ps) { 579 - return adev->pm.dpm.uvd_ps; 580 - } else { 581 - dpm_state = POWER_STATE_TYPE_PERFORMANCE; 582 - goto restart_search; 583 - } 584 - case POWER_STATE_TYPE_INTERNAL_THERMAL: 585 - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; 586 - goto restart_search; 587 - case POWER_STATE_TYPE_INTERNAL_ACPI: 588 - dpm_state = POWER_STATE_TYPE_BATTERY; 589 - goto restart_search; 590 - case POWER_STATE_TYPE_BATTERY: 591 - case POWER_STATE_TYPE_BALANCED: 592 - case POWER_STATE_TYPE_INTERNAL_3DPERF: 593 - dpm_state = POWER_STATE_TYPE_PERFORMANCE; 594 - goto restart_search; 595 - default: 596 - break; 597 - } 598 - 599 - return NULL; 600 - } 601 - 602 - static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) 603 - { 604 - struct amdgpu_ps *ps; 605 - enum amd_pm_state_type dpm_state; 606 - int ret; 607 - bool equal = false; 608 - 609 - /* if dpm init failed */ 610 - if (!adev->pm.dpm_enabled) 611 - return; 612 - 613 - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { 614 - /* add other state override checks here */ 615 - if ((!adev->pm.dpm.thermal_active) && 616 - (!adev->pm.dpm.uvd_active)) 617 - adev->pm.dpm.state = adev->pm.dpm.user_state; 618 - } 619 - dpm_state = adev->pm.dpm.state; 620 - 621 - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); 622 - if (ps) 623 - adev->pm.dpm.requested_ps = ps; 624 - else 625 - return; 626 - 627 - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { 628 - printk("switching from power state:\n"); 629 - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); 630 - printk("switching to power state:\n"); 631 - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); 632 - } 633 - 634 - /* update whether vce is active */ 635 - ps->vce_active = adev->pm.dpm.vce_active; 636 - if (adev->powerplay.pp_funcs->display_configuration_changed) 637 - amdgpu_dpm_display_configuration_changed(adev); 638 - 639 - ret = amdgpu_dpm_pre_set_power_state(adev); 640 - if (ret) 641 - return; 642 - 643 - if (adev->powerplay.pp_funcs->check_state_equal) { 644 - if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) 645 - equal = false; 646 - } 647 - 648 - if (equal) 649 - return; 650 - 651 - if (adev->powerplay.pp_funcs->set_power_state) 652 - adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); 653 - 654 - amdgpu_dpm_post_set_power_state(adev); 655 - 656 - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; 657 - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; 658 - 659 - if (adev->powerplay.pp_funcs->force_performance_level) { 660 - if (adev->pm.dpm.thermal_active) { 661 - enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; 662 - /* force low perf level for thermal */ 663 - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); 664 - /* save the user's level */ 665 - adev->pm.dpm.forced_level = level; 666 - } else { 667 - /* otherwise, user selected level */ 668 - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); 669 - } 670 - } 671 - } 672 - 673 - void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) 1246 + void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) 674 1247 { 675 1248 int i = 0; 676 1249 ··· 481 1464 amdgpu_fence_wait_empty(ring); 482 1465 } 483 1466 484 - if (adev->powerplay.pp_funcs->dispatch_tasks) { 1467 + if ((adev->family == AMDGPU_FAMILY_SI) || 1468 + (adev->family == AMDGPU_FAMILY_KV)) { 1469 + mutex_lock(&adev->pm.mutex); 1470 + amdgpu_dpm_get_active_displays(adev); 1471 + adev->powerplay.pp_funcs->change_power_state(adev->powerplay.pp_handle); 1472 + mutex_unlock(&adev->pm.mutex); 1473 + } else { 485 1474 if (!amdgpu_device_has_dc_support(adev)) { 486 1475 mutex_lock(&adev->pm.mutex); 487 1476 amdgpu_dpm_get_active_displays(adev); ··· 506 1483 mutex_unlock(&adev->pm.mutex); 507 1484 } 508 1485 amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); 509 - } else { 510 - mutex_lock(&adev->pm.mutex); 511 - amdgpu_dpm_get_active_displays(adev); 512 - amdgpu_dpm_change_power_state_locked(adev); 513 - mutex_unlock(&adev->pm.mutex); 514 1486 } 515 1487 } 516 1488 ··· 523 1505 } 524 1506 mutex_unlock(&adev->pm.mutex); 525 1507 526 - amdgpu_pm_compute_clocks(adev); 1508 + amdgpu_dpm_compute_clocks(adev); 527 1509 } else { 528 1510 ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); 529 1511 if (ret) ··· 559 1541 } 560 1542 mutex_unlock(&adev->pm.mutex); 561 1543 562 - amdgpu_pm_compute_clocks(adev); 1544 + amdgpu_dpm_compute_clocks(adev); 563 1545 } else { 564 1546 ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); 565 1547 if (ret) 566 1548 DRM_ERROR("Dpm %s vce failed, ret = %d. \n", 567 1549 enable ? "enable" : "disable", ret); 568 1550 } 569 - } 570 - 571 - void amdgpu_pm_print_power_states(struct amdgpu_device *adev) 572 - { 573 - int i; 574 - 575 - if (adev->powerplay.pp_funcs->print_power_state == NULL) 576 - return; 577 - 578 - for (i = 0; i < adev->pm.dpm.num_ps; i++) 579 - amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); 580 - 581 1551 } 582 1552 583 1553 void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) ··· 733 1727 if (amdgpu_dpm_dispatch_task(adev, 734 1728 AMD_PP_TASK_ENABLE_USER_STATE, 735 1729 &state) == -EOPNOTSUPP) 736 - amdgpu_pm_compute_clocks(adev); 1730 + amdgpu_dpm_compute_clocks(adev); 737 1731 } 738 1732 739 1733 enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) ··· 908 1902 AMD_PP_TASK_READJUST_POWER_STATE, 909 1903 NULL) == -EOPNOTSUPP) { 910 1904 adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 911 - amdgpu_pm_compute_clocks(adev); 1905 + amdgpu_dpm_compute_clocks(adev); 912 1906 } 913 1907 914 1908 return 0; ··· 938 1932 AMD_PP_TASK_READJUST_POWER_STATE, 939 1933 NULL) == -EOPNOTSUPP) { 940 1934 adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; 941 - amdgpu_pm_compute_clocks(adev); 1935 + amdgpu_dpm_compute_clocks(adev); 942 1936 } 943 1937 944 1938 return 0;
+1 -16
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
··· 374 374 AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, 375 375 }; 376 376 377 - void amdgpu_dpm_print_class_info(u32 class, u32 class2); 378 - void amdgpu_dpm_print_cap_info(u32 caps); 379 - void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, 380 - struct amdgpu_ps *rps); 381 377 u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); 382 378 int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, 383 379 void *data, uint32_t *size); 384 - 385 - int amdgpu_get_platform_caps(struct amdgpu_device *adev); 386 - 387 - int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); 388 - void amdgpu_free_extended_power_table(struct amdgpu_device *adev); 389 - 390 - void amdgpu_add_thermal_controller(struct amdgpu_device *adev); 391 - 392 - struct amd_vce_state* 393 - amdgpu_get_vce_clock_state(void *handle, u32 idx); 394 380 395 381 int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, 396 382 uint32_t block_type, bool gate); ··· 428 442 429 443 void amdgpu_dpm_thermal_work_handler(struct work_struct *work); 430 444 431 - void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); 445 + void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev); 432 446 void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); 433 447 void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); 434 448 void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); 435 - void amdgpu_pm_print_power_states(struct amdgpu_device *adev); 436 449 int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); 437 450 int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable); 438 451 int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size);
+1 -1
drivers/gpu/drm/amd/pm/powerplay/Makefile
··· 28 28 29 29 include $(AMD_POWERPLAY) 30 30 31 - POWER_MGR-y = amd_powerplay.o 31 + POWER_MGR-y = amd_powerplay.o legacy_dpm.o 32 32 33 33 POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o 34 34
+4 -2
drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c
··· 36 36 37 37 #include "gca/gfx_7_2_d.h" 38 38 #include "gca/gfx_7_2_sh_mask.h" 39 + #include "legacy_dpm.h" 39 40 40 41 #define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 41 42 #define KV_MINIMUM_ENGINE_CLOCK 800 ··· 3088 3087 else 3089 3088 adev->pm.dpm_enabled = true; 3090 3089 mutex_unlock(&adev->pm.mutex); 3091 - amdgpu_pm_compute_clocks(adev); 3090 + amdgpu_dpm_compute_clocks(adev); 3092 3091 return ret; 3093 3092 } 3094 3093 ··· 3136 3135 adev->pm.dpm_enabled = true; 3137 3136 mutex_unlock(&adev->pm.mutex); 3138 3137 if (adev->pm.dpm_enabled) 3139 - amdgpu_pm_compute_clocks(adev); 3138 + amdgpu_dpm_compute_clocks(adev); 3140 3139 } 3141 3140 return 0; 3142 3141 } ··· 3390 3389 .get_vce_clock_state = amdgpu_get_vce_clock_state, 3391 3390 .check_state_equal = kv_check_state_equal, 3392 3391 .read_sensor = &kv_dpm_read_sensor, 3392 + .change_power_state = amdgpu_dpm_change_power_state_locked, 3393 3393 }; 3394 3394 3395 3395 static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = {
+1024
drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c
··· 1 + /* 2 + * Copyright 2021 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #include "amdgpu.h" 24 + #include "amdgpu_i2c.h" 25 + #include "amdgpu_atombios.h" 26 + #include "atom.h" 27 + #include "amd_pcie.h" 28 + #include "legacy_dpm.h" 29 + 30 + #define amdgpu_dpm_pre_set_power_state(adev) \ 31 + ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) 32 + 33 + #define amdgpu_dpm_post_set_power_state(adev) \ 34 + ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) 35 + 36 + #define amdgpu_dpm_display_configuration_changed(adev) \ 37 + ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) 38 + 39 + #define amdgpu_dpm_print_power_state(adev, ps) \ 40 + ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) 41 + 42 + #define amdgpu_dpm_vblank_too_short(adev) \ 43 + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) 44 + 45 + #define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ 46 + ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) 47 + 48 + void amdgpu_dpm_print_class_info(u32 class, u32 class2) 49 + { 50 + const char *s; 51 + 52 + switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 53 + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 54 + default: 55 + s = "none"; 56 + break; 57 + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 58 + s = "battery"; 59 + break; 60 + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 61 + s = "balanced"; 62 + break; 63 + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 64 + s = "performance"; 65 + break; 66 + } 67 + printk("\tui class: %s\n", s); 68 + printk("\tinternal class:"); 69 + if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && 70 + (class2 == 0)) 71 + pr_cont(" none"); 72 + else { 73 + if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) 74 + pr_cont(" boot"); 75 + if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 76 + pr_cont(" thermal"); 77 + if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 78 + pr_cont(" limited_pwr"); 79 + if (class & ATOM_PPLIB_CLASSIFICATION_REST) 80 + pr_cont(" rest"); 81 + if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) 82 + pr_cont(" forced"); 83 + if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 84 + pr_cont(" 3d_perf"); 85 + if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 86 + pr_cont(" ovrdrv"); 87 + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 88 + pr_cont(" uvd"); 89 + if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) 90 + pr_cont(" 3d_low"); 91 + if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) 92 + pr_cont(" acpi"); 93 + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 94 + pr_cont(" uvd_hd2"); 95 + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 96 + pr_cont(" uvd_hd"); 97 + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 98 + pr_cont(" uvd_sd"); 99 + if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 100 + pr_cont(" limited_pwr2"); 101 + if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 102 + pr_cont(" ulv"); 103 + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 104 + pr_cont(" uvd_mvc"); 105 + } 106 + pr_cont("\n"); 107 + } 108 + 109 + void amdgpu_dpm_print_cap_info(u32 caps) 110 + { 111 + printk("\tcaps:"); 112 + if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 113 + pr_cont(" single_disp"); 114 + if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) 115 + pr_cont(" video"); 116 + if (caps & ATOM_PPLIB_DISALLOW_ON_DC) 117 + pr_cont(" no_dc"); 118 + pr_cont("\n"); 119 + } 120 + 121 + void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, 122 + struct amdgpu_ps *rps) 123 + { 124 + printk("\tstatus:"); 125 + if (rps == adev->pm.dpm.current_ps) 126 + pr_cont(" c"); 127 + if (rps == adev->pm.dpm.requested_ps) 128 + pr_cont(" r"); 129 + if (rps == adev->pm.dpm.boot_ps) 130 + pr_cont(" b"); 131 + pr_cont("\n"); 132 + } 133 + 134 + void amdgpu_pm_print_power_states(struct amdgpu_device *adev) 135 + { 136 + int i; 137 + 138 + if (adev->powerplay.pp_funcs->print_power_state == NULL) 139 + return; 140 + 141 + for (i = 0; i < adev->pm.dpm.num_ps; i++) 142 + amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); 143 + 144 + } 145 + 146 + union power_info { 147 + struct _ATOM_POWERPLAY_INFO info; 148 + struct _ATOM_POWERPLAY_INFO_V2 info_2; 149 + struct _ATOM_POWERPLAY_INFO_V3 info_3; 150 + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 151 + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 152 + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 153 + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 154 + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 155 + }; 156 + 157 + int amdgpu_get_platform_caps(struct amdgpu_device *adev) 158 + { 159 + struct amdgpu_mode_info *mode_info = &adev->mode_info; 160 + union power_info *power_info; 161 + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 162 + u16 data_offset; 163 + u8 frev, crev; 164 + 165 + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 166 + &frev, &crev, &data_offset)) 167 + return -EINVAL; 168 + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 169 + 170 + adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 171 + adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 172 + adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 173 + 174 + return 0; 175 + } 176 + 177 + union fan_info { 178 + struct _ATOM_PPLIB_FANTABLE fan; 179 + struct _ATOM_PPLIB_FANTABLE2 fan2; 180 + struct _ATOM_PPLIB_FANTABLE3 fan3; 181 + }; 182 + 183 + static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, 184 + ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) 185 + { 186 + u32 size = atom_table->ucNumEntries * 187 + sizeof(struct amdgpu_clock_voltage_dependency_entry); 188 + int i; 189 + ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; 190 + 191 + amdgpu_table->entries = kzalloc(size, GFP_KERNEL); 192 + if (!amdgpu_table->entries) 193 + return -ENOMEM; 194 + 195 + entry = &atom_table->entries[0]; 196 + for (i = 0; i < atom_table->ucNumEntries; i++) { 197 + amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | 198 + (entry->ucClockHigh << 16); 199 + amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); 200 + entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) 201 + ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); 202 + } 203 + amdgpu_table->count = atom_table->ucNumEntries; 204 + 205 + return 0; 206 + } 207 + 208 + /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ 209 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 210 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 211 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 212 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 213 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 214 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 215 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 216 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 217 + 218 + int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) 219 + { 220 + struct amdgpu_mode_info *mode_info = &adev->mode_info; 221 + union power_info *power_info; 222 + union fan_info *fan_info; 223 + ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; 224 + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 225 + u16 data_offset; 226 + u8 frev, crev; 227 + int ret, i; 228 + 229 + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 230 + &frev, &crev, &data_offset)) 231 + return -EINVAL; 232 + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 233 + 234 + /* fan table */ 235 + if (le16_to_cpu(power_info->pplib.usTableSize) >= 236 + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 237 + if (power_info->pplib3.usFanTableOffset) { 238 + fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + 239 + le16_to_cpu(power_info->pplib3.usFanTableOffset)); 240 + adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; 241 + adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); 242 + adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); 243 + adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); 244 + adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); 245 + adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); 246 + adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); 247 + if (fan_info->fan.ucFanTableFormat >= 2) 248 + adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); 249 + else 250 + adev->pm.dpm.fan.t_max = 10900; 251 + adev->pm.dpm.fan.cycle_delay = 100000; 252 + if (fan_info->fan.ucFanTableFormat >= 3) { 253 + adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 254 + adev->pm.dpm.fan.default_max_fan_pwm = 255 + le16_to_cpu(fan_info->fan3.usFanPWMMax); 256 + adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 257 + adev->pm.dpm.fan.fan_output_sensitivity = 258 + le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 259 + } 260 + adev->pm.dpm.fan.ucode_fan_control = true; 261 + } 262 + } 263 + 264 + /* clock dependancy tables, shedding tables */ 265 + if (le16_to_cpu(power_info->pplib.usTableSize) >= 266 + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { 267 + if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { 268 + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 269 + (mode_info->atom_context->bios + data_offset + 270 + le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 271 + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 272 + dep_table); 273 + if (ret) { 274 + amdgpu_free_extended_power_table(adev); 275 + return ret; 276 + } 277 + } 278 + if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 279 + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 280 + (mode_info->atom_context->bios + data_offset + 281 + le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 282 + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 283 + dep_table); 284 + if (ret) { 285 + amdgpu_free_extended_power_table(adev); 286 + return ret; 287 + } 288 + } 289 + if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 290 + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 291 + (mode_info->atom_context->bios + data_offset + 292 + le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 293 + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 294 + dep_table); 295 + if (ret) { 296 + amdgpu_free_extended_power_table(adev); 297 + return ret; 298 + } 299 + } 300 + if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 301 + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 302 + (mode_info->atom_context->bios + data_offset + 303 + le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 304 + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 305 + dep_table); 306 + if (ret) { 307 + amdgpu_free_extended_power_table(adev); 308 + return ret; 309 + } 310 + } 311 + if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 312 + ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = 313 + (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 314 + (mode_info->atom_context->bios + data_offset + 315 + le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); 316 + if (clk_v->ucNumEntries) { 317 + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = 318 + le16_to_cpu(clk_v->entries[0].usSclkLow) | 319 + (clk_v->entries[0].ucSclkHigh << 16); 320 + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = 321 + le16_to_cpu(clk_v->entries[0].usMclkLow) | 322 + (clk_v->entries[0].ucMclkHigh << 16); 323 + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = 324 + le16_to_cpu(clk_v->entries[0].usVddc); 325 + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = 326 + le16_to_cpu(clk_v->entries[0].usVddci); 327 + } 328 + } 329 + if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { 330 + ATOM_PPLIB_PhaseSheddingLimits_Table *psl = 331 + (ATOM_PPLIB_PhaseSheddingLimits_Table *) 332 + (mode_info->atom_context->bios + data_offset + 333 + le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); 334 + ATOM_PPLIB_PhaseSheddingLimits_Record *entry; 335 + 336 + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = 337 + kcalloc(psl->ucNumEntries, 338 + sizeof(struct amdgpu_phase_shedding_limits_entry), 339 + GFP_KERNEL); 340 + if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 341 + amdgpu_free_extended_power_table(adev); 342 + return -ENOMEM; 343 + } 344 + 345 + entry = &psl->entries[0]; 346 + for (i = 0; i < psl->ucNumEntries; i++) { 347 + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = 348 + le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); 349 + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = 350 + le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); 351 + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = 352 + le16_to_cpu(entry->usVoltage); 353 + entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) 354 + ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); 355 + } 356 + adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = 357 + psl->ucNumEntries; 358 + } 359 + } 360 + 361 + /* cac data */ 362 + if (le16_to_cpu(power_info->pplib.usTableSize) >= 363 + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { 364 + adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); 365 + adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); 366 + adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; 367 + adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); 368 + if (adev->pm.dpm.tdp_od_limit) 369 + adev->pm.dpm.power_control = true; 370 + else 371 + adev->pm.dpm.power_control = false; 372 + adev->pm.dpm.tdp_adjustment = 0; 373 + adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); 374 + adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); 375 + adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); 376 + if (power_info->pplib5.usCACLeakageTableOffset) { 377 + ATOM_PPLIB_CAC_Leakage_Table *cac_table = 378 + (ATOM_PPLIB_CAC_Leakage_Table *) 379 + (mode_info->atom_context->bios + data_offset + 380 + le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); 381 + ATOM_PPLIB_CAC_Leakage_Record *entry; 382 + u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); 383 + adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 384 + if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { 385 + amdgpu_free_extended_power_table(adev); 386 + return -ENOMEM; 387 + } 388 + entry = &cac_table->entries[0]; 389 + for (i = 0; i < cac_table->ucNumEntries; i++) { 390 + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { 391 + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = 392 + le16_to_cpu(entry->usVddc1); 393 + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = 394 + le16_to_cpu(entry->usVddc2); 395 + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = 396 + le16_to_cpu(entry->usVddc3); 397 + } else { 398 + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = 399 + le16_to_cpu(entry->usVddc); 400 + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = 401 + le32_to_cpu(entry->ulLeakageValue); 402 + } 403 + entry = (ATOM_PPLIB_CAC_Leakage_Record *) 404 + ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); 405 + } 406 + adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; 407 + } 408 + } 409 + 410 + /* ext tables */ 411 + if (le16_to_cpu(power_info->pplib.usTableSize) >= 412 + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 413 + ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) 414 + (mode_info->atom_context->bios + data_offset + 415 + le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); 416 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && 417 + ext_hdr->usVCETableOffset) { 418 + VCEClockInfoArray *array = (VCEClockInfoArray *) 419 + (mode_info->atom_context->bios + data_offset + 420 + le16_to_cpu(ext_hdr->usVCETableOffset) + 1); 421 + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = 422 + (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 423 + (mode_info->atom_context->bios + data_offset + 424 + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 425 + 1 + array->ucNumEntries * sizeof(VCEClockInfo)); 426 + ATOM_PPLIB_VCE_State_Table *states = 427 + (ATOM_PPLIB_VCE_State_Table *) 428 + (mode_info->atom_context->bios + data_offset + 429 + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 430 + 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + 431 + 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); 432 + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; 433 + ATOM_PPLIB_VCE_State_Record *state_entry; 434 + VCEClockInfo *vce_clk; 435 + u32 size = limits->numEntries * 436 + sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); 437 + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 438 + kzalloc(size, GFP_KERNEL); 439 + if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 440 + amdgpu_free_extended_power_table(adev); 441 + return -ENOMEM; 442 + } 443 + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 444 + limits->numEntries; 445 + entry = &limits->entries[0]; 446 + state_entry = &states->entries[0]; 447 + for (i = 0; i < limits->numEntries; i++) { 448 + vce_clk = (VCEClockInfo *) 449 + ((u8 *)&array->entries[0] + 450 + (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 451 + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = 452 + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 453 + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = 454 + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 455 + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = 456 + le16_to_cpu(entry->usVoltage); 457 + entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) 458 + ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); 459 + } 460 + adev->pm.dpm.num_of_vce_states = 461 + states->numEntries > AMD_MAX_VCE_LEVELS ? 462 + AMD_MAX_VCE_LEVELS : states->numEntries; 463 + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { 464 + vce_clk = (VCEClockInfo *) 465 + ((u8 *)&array->entries[0] + 466 + (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 467 + adev->pm.dpm.vce_states[i].evclk = 468 + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 469 + adev->pm.dpm.vce_states[i].ecclk = 470 + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 471 + adev->pm.dpm.vce_states[i].clk_idx = 472 + state_entry->ucClockInfoIndex & 0x3f; 473 + adev->pm.dpm.vce_states[i].pstate = 474 + (state_entry->ucClockInfoIndex & 0xc0) >> 6; 475 + state_entry = (ATOM_PPLIB_VCE_State_Record *) 476 + ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); 477 + } 478 + } 479 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && 480 + ext_hdr->usUVDTableOffset) { 481 + UVDClockInfoArray *array = (UVDClockInfoArray *) 482 + (mode_info->atom_context->bios + data_offset + 483 + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); 484 + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = 485 + (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 486 + (mode_info->atom_context->bios + data_offset + 487 + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + 488 + 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); 489 + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; 490 + u32 size = limits->numEntries * 491 + sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); 492 + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 493 + kzalloc(size, GFP_KERNEL); 494 + if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 495 + amdgpu_free_extended_power_table(adev); 496 + return -ENOMEM; 497 + } 498 + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 499 + limits->numEntries; 500 + entry = &limits->entries[0]; 501 + for (i = 0; i < limits->numEntries; i++) { 502 + UVDClockInfo *uvd_clk = (UVDClockInfo *) 503 + ((u8 *)&array->entries[0] + 504 + (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); 505 + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = 506 + le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); 507 + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = 508 + le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); 509 + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = 510 + le16_to_cpu(entry->usVoltage); 511 + entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) 512 + ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); 513 + } 514 + } 515 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && 516 + ext_hdr->usSAMUTableOffset) { 517 + ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = 518 + (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 519 + (mode_info->atom_context->bios + data_offset + 520 + le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); 521 + ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; 522 + u32 size = limits->numEntries * 523 + sizeof(struct amdgpu_clock_voltage_dependency_entry); 524 + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 525 + kzalloc(size, GFP_KERNEL); 526 + if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 527 + amdgpu_free_extended_power_table(adev); 528 + return -ENOMEM; 529 + } 530 + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 531 + limits->numEntries; 532 + entry = &limits->entries[0]; 533 + for (i = 0; i < limits->numEntries; i++) { 534 + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = 535 + le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); 536 + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = 537 + le16_to_cpu(entry->usVoltage); 538 + entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) 539 + ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); 540 + } 541 + } 542 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && 543 + ext_hdr->usPPMTableOffset) { 544 + ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) 545 + (mode_info->atom_context->bios + data_offset + 546 + le16_to_cpu(ext_hdr->usPPMTableOffset)); 547 + adev->pm.dpm.dyn_state.ppm_table = 548 + kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); 549 + if (!adev->pm.dpm.dyn_state.ppm_table) { 550 + amdgpu_free_extended_power_table(adev); 551 + return -ENOMEM; 552 + } 553 + adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 554 + adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 555 + le16_to_cpu(ppm->usCpuCoreNumber); 556 + adev->pm.dpm.dyn_state.ppm_table->platform_tdp = 557 + le32_to_cpu(ppm->ulPlatformTDP); 558 + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = 559 + le32_to_cpu(ppm->ulSmallACPlatformTDP); 560 + adev->pm.dpm.dyn_state.ppm_table->platform_tdc = 561 + le32_to_cpu(ppm->ulPlatformTDC); 562 + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = 563 + le32_to_cpu(ppm->ulSmallACPlatformTDC); 564 + adev->pm.dpm.dyn_state.ppm_table->apu_tdp = 565 + le32_to_cpu(ppm->ulApuTDP); 566 + adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = 567 + le32_to_cpu(ppm->ulDGpuTDP); 568 + adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = 569 + le32_to_cpu(ppm->ulDGpuUlvPower); 570 + adev->pm.dpm.dyn_state.ppm_table->tj_max = 571 + le32_to_cpu(ppm->ulTjmax); 572 + } 573 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && 574 + ext_hdr->usACPTableOffset) { 575 + ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = 576 + (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 577 + (mode_info->atom_context->bios + data_offset + 578 + le16_to_cpu(ext_hdr->usACPTableOffset) + 1); 579 + ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; 580 + u32 size = limits->numEntries * 581 + sizeof(struct amdgpu_clock_voltage_dependency_entry); 582 + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 583 + kzalloc(size, GFP_KERNEL); 584 + if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 585 + amdgpu_free_extended_power_table(adev); 586 + return -ENOMEM; 587 + } 588 + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 589 + limits->numEntries; 590 + entry = &limits->entries[0]; 591 + for (i = 0; i < limits->numEntries; i++) { 592 + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = 593 + le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); 594 + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = 595 + le16_to_cpu(entry->usVoltage); 596 + entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) 597 + ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); 598 + } 599 + } 600 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && 601 + ext_hdr->usPowerTuneTableOffset) { 602 + u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + 603 + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 604 + ATOM_PowerTune_Table *pt; 605 + adev->pm.dpm.dyn_state.cac_tdp_table = 606 + kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); 607 + if (!adev->pm.dpm.dyn_state.cac_tdp_table) { 608 + amdgpu_free_extended_power_table(adev); 609 + return -ENOMEM; 610 + } 611 + if (rev > 0) { 612 + ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 613 + (mode_info->atom_context->bios + data_offset + 614 + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 615 + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 616 + ppt->usMaximumPowerDeliveryLimit; 617 + pt = &ppt->power_tune_table; 618 + } else { 619 + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) 620 + (mode_info->atom_context->bios + data_offset + 621 + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 622 + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; 623 + pt = &ppt->power_tune_table; 624 + } 625 + adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); 626 + adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = 627 + le16_to_cpu(pt->usConfigurableTDP); 628 + adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); 629 + adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = 630 + le16_to_cpu(pt->usBatteryPowerLimit); 631 + adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = 632 + le16_to_cpu(pt->usSmallPowerLimit); 633 + adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = 634 + le16_to_cpu(pt->usLowCACLeakage); 635 + adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = 636 + le16_to_cpu(pt->usHighCACLeakage); 637 + } 638 + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && 639 + ext_hdr->usSclkVddgfxTableOffset) { 640 + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 641 + (mode_info->atom_context->bios + data_offset + 642 + le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); 643 + ret = amdgpu_parse_clk_voltage_dep_table( 644 + &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, 645 + dep_table); 646 + if (ret) { 647 + kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); 648 + return ret; 649 + } 650 + } 651 + } 652 + 653 + return 0; 654 + } 655 + 656 + void amdgpu_free_extended_power_table(struct amdgpu_device *adev) 657 + { 658 + struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; 659 + 660 + kfree(dyn_state->vddc_dependency_on_sclk.entries); 661 + kfree(dyn_state->vddci_dependency_on_mclk.entries); 662 + kfree(dyn_state->vddc_dependency_on_mclk.entries); 663 + kfree(dyn_state->mvdd_dependency_on_mclk.entries); 664 + kfree(dyn_state->cac_leakage_table.entries); 665 + kfree(dyn_state->phase_shedding_limits_table.entries); 666 + kfree(dyn_state->ppm_table); 667 + kfree(dyn_state->cac_tdp_table); 668 + kfree(dyn_state->vce_clock_voltage_dependency_table.entries); 669 + kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); 670 + kfree(dyn_state->samu_clock_voltage_dependency_table.entries); 671 + kfree(dyn_state->acp_clock_voltage_dependency_table.entries); 672 + kfree(dyn_state->vddgfx_dependency_on_sclk.entries); 673 + } 674 + 675 + static const char *pp_lib_thermal_controller_names[] = { 676 + "NONE", 677 + "lm63", 678 + "adm1032", 679 + "adm1030", 680 + "max6649", 681 + "lm64", 682 + "f75375", 683 + "RV6xx", 684 + "RV770", 685 + "adt7473", 686 + "NONE", 687 + "External GPIO", 688 + "Evergreen", 689 + "emc2103", 690 + "Sumo", 691 + "Northern Islands", 692 + "Southern Islands", 693 + "lm96163", 694 + "Sea Islands", 695 + "Kaveri/Kabini", 696 + }; 697 + 698 + void amdgpu_add_thermal_controller(struct amdgpu_device *adev) 699 + { 700 + struct amdgpu_mode_info *mode_info = &adev->mode_info; 701 + ATOM_PPLIB_POWERPLAYTABLE *power_table; 702 + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 703 + ATOM_PPLIB_THERMALCONTROLLER *controller; 704 + struct amdgpu_i2c_bus_rec i2c_bus; 705 + u16 data_offset; 706 + u8 frev, crev; 707 + 708 + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 709 + &frev, &crev, &data_offset)) 710 + return; 711 + power_table = (ATOM_PPLIB_POWERPLAYTABLE *) 712 + (mode_info->atom_context->bios + data_offset); 713 + controller = &power_table->sThermalController; 714 + 715 + /* add the i2c bus for thermal/fan chip */ 716 + if (controller->ucType > 0) { 717 + if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) 718 + adev->pm.no_fan = true; 719 + adev->pm.fan_pulses_per_revolution = 720 + controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 721 + if (adev->pm.fan_pulses_per_revolution) { 722 + adev->pm.fan_min_rpm = controller->ucFanMinRPM; 723 + adev->pm.fan_max_rpm = controller->ucFanMaxRPM; 724 + } 725 + if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { 726 + DRM_INFO("Internal thermal controller %s fan control\n", 727 + (controller->ucFanParameters & 728 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 729 + adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; 730 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { 731 + DRM_INFO("Internal thermal controller %s fan control\n", 732 + (controller->ucFanParameters & 733 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 734 + adev->pm.int_thermal_type = THERMAL_TYPE_RV770; 735 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { 736 + DRM_INFO("Internal thermal controller %s fan control\n", 737 + (controller->ucFanParameters & 738 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 739 + adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; 740 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { 741 + DRM_INFO("Internal thermal controller %s fan control\n", 742 + (controller->ucFanParameters & 743 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 744 + adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; 745 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { 746 + DRM_INFO("Internal thermal controller %s fan control\n", 747 + (controller->ucFanParameters & 748 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 749 + adev->pm.int_thermal_type = THERMAL_TYPE_NI; 750 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { 751 + DRM_INFO("Internal thermal controller %s fan control\n", 752 + (controller->ucFanParameters & 753 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 754 + adev->pm.int_thermal_type = THERMAL_TYPE_SI; 755 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { 756 + DRM_INFO("Internal thermal controller %s fan control\n", 757 + (controller->ucFanParameters & 758 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 759 + adev->pm.int_thermal_type = THERMAL_TYPE_CI; 760 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { 761 + DRM_INFO("Internal thermal controller %s fan control\n", 762 + (controller->ucFanParameters & 763 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 764 + adev->pm.int_thermal_type = THERMAL_TYPE_KV; 765 + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { 766 + DRM_INFO("External GPIO thermal controller %s fan control\n", 767 + (controller->ucFanParameters & 768 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 769 + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; 770 + } else if (controller->ucType == 771 + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { 772 + DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", 773 + (controller->ucFanParameters & 774 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 775 + adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; 776 + } else if (controller->ucType == 777 + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { 778 + DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", 779 + (controller->ucFanParameters & 780 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 781 + adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; 782 + } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { 783 + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", 784 + pp_lib_thermal_controller_names[controller->ucType], 785 + controller->ucI2cAddress >> 1, 786 + (controller->ucFanParameters & 787 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 788 + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; 789 + i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); 790 + adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); 791 + if (adev->pm.i2c_bus) { 792 + struct i2c_board_info info = { }; 793 + const char *name = pp_lib_thermal_controller_names[controller->ucType]; 794 + info.addr = controller->ucI2cAddress >> 1; 795 + strlcpy(info.type, name, sizeof(info.type)); 796 + i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); 797 + } 798 + } else { 799 + DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", 800 + controller->ucType, 801 + controller->ucI2cAddress >> 1, 802 + (controller->ucFanParameters & 803 + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 804 + } 805 + } 806 + } 807 + 808 + struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx) 809 + { 810 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 811 + 812 + if (idx < adev->pm.dpm.num_of_vce_states) 813 + return &adev->pm.dpm.vce_states[idx]; 814 + 815 + return NULL; 816 + } 817 + 818 + static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, 819 + enum amd_pm_state_type dpm_state) 820 + { 821 + int i; 822 + struct amdgpu_ps *ps; 823 + u32 ui_class; 824 + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? 825 + true : false; 826 + 827 + /* check if the vblank period is too short to adjust the mclk */ 828 + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { 829 + if (amdgpu_dpm_vblank_too_short(adev)) 830 + single_display = false; 831 + } 832 + 833 + /* certain older asics have a separare 3D performance state, 834 + * so try that first if the user selected performance 835 + */ 836 + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) 837 + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; 838 + /* balanced states don't exist at the moment */ 839 + if (dpm_state == POWER_STATE_TYPE_BALANCED) 840 + dpm_state = POWER_STATE_TYPE_PERFORMANCE; 841 + 842 + restart_search: 843 + /* Pick the best power state based on current conditions */ 844 + for (i = 0; i < adev->pm.dpm.num_ps; i++) { 845 + ps = &adev->pm.dpm.ps[i]; 846 + ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; 847 + switch (dpm_state) { 848 + /* user states */ 849 + case POWER_STATE_TYPE_BATTERY: 850 + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { 851 + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 852 + if (single_display) 853 + return ps; 854 + } else 855 + return ps; 856 + } 857 + break; 858 + case POWER_STATE_TYPE_BALANCED: 859 + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { 860 + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 861 + if (single_display) 862 + return ps; 863 + } else 864 + return ps; 865 + } 866 + break; 867 + case POWER_STATE_TYPE_PERFORMANCE: 868 + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { 869 + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 870 + if (single_display) 871 + return ps; 872 + } else 873 + return ps; 874 + } 875 + break; 876 + /* internal states */ 877 + case POWER_STATE_TYPE_INTERNAL_UVD: 878 + if (adev->pm.dpm.uvd_ps) 879 + return adev->pm.dpm.uvd_ps; 880 + else 881 + break; 882 + case POWER_STATE_TYPE_INTERNAL_UVD_SD: 883 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 884 + return ps; 885 + break; 886 + case POWER_STATE_TYPE_INTERNAL_UVD_HD: 887 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 888 + return ps; 889 + break; 890 + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 891 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 892 + return ps; 893 + break; 894 + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 895 + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 896 + return ps; 897 + break; 898 + case POWER_STATE_TYPE_INTERNAL_BOOT: 899 + return adev->pm.dpm.boot_ps; 900 + case POWER_STATE_TYPE_INTERNAL_THERMAL: 901 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 902 + return ps; 903 + break; 904 + case POWER_STATE_TYPE_INTERNAL_ACPI: 905 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) 906 + return ps; 907 + break; 908 + case POWER_STATE_TYPE_INTERNAL_ULV: 909 + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 910 + return ps; 911 + break; 912 + case POWER_STATE_TYPE_INTERNAL_3DPERF: 913 + if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 914 + return ps; 915 + break; 916 + default: 917 + break; 918 + } 919 + } 920 + /* use a fallback state if we didn't match */ 921 + switch (dpm_state) { 922 + case POWER_STATE_TYPE_INTERNAL_UVD_SD: 923 + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; 924 + goto restart_search; 925 + case POWER_STATE_TYPE_INTERNAL_UVD_HD: 926 + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 927 + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 928 + if (adev->pm.dpm.uvd_ps) { 929 + return adev->pm.dpm.uvd_ps; 930 + } else { 931 + dpm_state = POWER_STATE_TYPE_PERFORMANCE; 932 + goto restart_search; 933 + } 934 + case POWER_STATE_TYPE_INTERNAL_THERMAL: 935 + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; 936 + goto restart_search; 937 + case POWER_STATE_TYPE_INTERNAL_ACPI: 938 + dpm_state = POWER_STATE_TYPE_BATTERY; 939 + goto restart_search; 940 + case POWER_STATE_TYPE_BATTERY: 941 + case POWER_STATE_TYPE_BALANCED: 942 + case POWER_STATE_TYPE_INTERNAL_3DPERF: 943 + dpm_state = POWER_STATE_TYPE_PERFORMANCE; 944 + goto restart_search; 945 + default: 946 + break; 947 + } 948 + 949 + return NULL; 950 + } 951 + 952 + int amdgpu_dpm_change_power_state_locked(void *handle) 953 + { 954 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 955 + struct amdgpu_ps *ps; 956 + enum amd_pm_state_type dpm_state; 957 + int ret; 958 + bool equal = false; 959 + 960 + /* if dpm init failed */ 961 + if (!adev->pm.dpm_enabled) 962 + return 0; 963 + 964 + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { 965 + /* add other state override checks here */ 966 + if ((!adev->pm.dpm.thermal_active) && 967 + (!adev->pm.dpm.uvd_active)) 968 + adev->pm.dpm.state = adev->pm.dpm.user_state; 969 + } 970 + dpm_state = adev->pm.dpm.state; 971 + 972 + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); 973 + if (ps) 974 + adev->pm.dpm.requested_ps = ps; 975 + else 976 + return -EINVAL; 977 + 978 + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { 979 + printk("switching from power state:\n"); 980 + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); 981 + printk("switching to power state:\n"); 982 + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); 983 + } 984 + 985 + /* update whether vce is active */ 986 + ps->vce_active = adev->pm.dpm.vce_active; 987 + if (adev->powerplay.pp_funcs->display_configuration_changed) 988 + amdgpu_dpm_display_configuration_changed(adev); 989 + 990 + ret = amdgpu_dpm_pre_set_power_state(adev); 991 + if (ret) 992 + return ret; 993 + 994 + if (adev->powerplay.pp_funcs->check_state_equal) { 995 + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) 996 + equal = false; 997 + } 998 + 999 + if (equal) 1000 + return 0; 1001 + 1002 + if (adev->powerplay.pp_funcs->set_power_state) 1003 + adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); 1004 + 1005 + amdgpu_dpm_post_set_power_state(adev); 1006 + 1007 + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; 1008 + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; 1009 + 1010 + if (adev->powerplay.pp_funcs->force_performance_level) { 1011 + if (adev->pm.dpm.thermal_active) { 1012 + enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; 1013 + /* force low perf level for thermal */ 1014 + amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); 1015 + /* save the user's level */ 1016 + adev->pm.dpm.forced_level = level; 1017 + } else { 1018 + /* otherwise, user selected level */ 1019 + amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); 1020 + } 1021 + } 1022 + 1023 + return 0; 1024 + }
+37
drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h
··· 1 + /* 2 + * Copyright 2021 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #ifndef __LEGACY_DPM_H__ 24 + #define __LEGACY_DPM_H__ 25 + 26 + void amdgpu_dpm_print_class_info(u32 class, u32 class2); 27 + void amdgpu_dpm_print_cap_info(u32 caps); 28 + void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, 29 + struct amdgpu_ps *rps); 30 + int amdgpu_get_platform_caps(struct amdgpu_device *adev); 31 + int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); 32 + void amdgpu_free_extended_power_table(struct amdgpu_device *adev); 33 + void amdgpu_add_thermal_controller(struct amdgpu_device *adev); 34 + struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx); 35 + int amdgpu_dpm_change_power_state_locked(void *handle); 36 + void amdgpu_pm_print_power_states(struct amdgpu_device *adev); 37 + #endif
+4 -2
drivers/gpu/drm/amd/pm/powerplay/si_dpm.c
··· 37 37 #include <linux/math64.h> 38 38 #include <linux/seq_file.h> 39 39 #include <linux/firmware.h> 40 + #include <legacy_dpm.h> 40 41 41 42 #define MC_CG_ARB_FREQ_F0 0x0a 42 43 #define MC_CG_ARB_FREQ_F1 0x0b ··· 7801 7800 else 7802 7801 adev->pm.dpm_enabled = true; 7803 7802 mutex_unlock(&adev->pm.mutex); 7804 - amdgpu_pm_compute_clocks(adev); 7803 + amdgpu_dpm_compute_clocks(adev); 7805 7804 return ret; 7806 7805 } 7807 7806 ··· 7849 7848 adev->pm.dpm_enabled = true; 7850 7849 mutex_unlock(&adev->pm.mutex); 7851 7850 if (adev->pm.dpm_enabled) 7852 - amdgpu_pm_compute_clocks(adev); 7851 + amdgpu_dpm_compute_clocks(adev); 7853 7852 } 7854 7853 return 0; 7855 7854 } ··· 8102 8101 .check_state_equal = &si_check_state_equal, 8103 8102 .get_vce_clock_state = amdgpu_get_vce_clock_state, 8104 8103 .read_sensor = &si_dpm_read_sensor, 8104 + .change_power_state = amdgpu_dpm_change_power_state_locked, 8105 8105 }; 8106 8106 8107 8107 static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = {