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

drm/radeon/dpm: add pre/post_set_power_state callback (BTC)

This properly implemented dynamic state adjustment by
using a working copy of the requested and current
power states.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

+83 -13
+71 -10
drivers/gpu/drm/radeon/btc_dpm.c
··· 2062 2062 static void btc_apply_state_adjust_rules(struct radeon_device *rdev, 2063 2063 struct radeon_ps *rps) 2064 2064 { 2065 - struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2066 2065 struct rv7xx_ps *ps = rv770_get_ps(rps); 2067 2066 struct radeon_clock_and_voltage_limits *max_limits; 2068 2067 bool disable_mclk_switching; 2069 2068 u32 mclk, sclk; 2070 2069 u16 vddc, vddci; 2071 - 2072 - /* point to the hw copy since this function will modify the ps */ 2073 - eg_pi->hw_ps = *ps; 2074 - rdev->pm.dpm.hw_ps.ps_priv = &eg_pi->hw_ps; 2075 - ps = &eg_pi->hw_ps; 2076 2070 2077 2071 if (rdev->pm.dpm.new_active_crtc_count > 1) 2078 2072 disable_mclk_switching = true; ··· 2216 2222 ps->high.flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2; 2217 2223 } 2218 2224 2225 + static void btc_update_current_ps(struct radeon_device *rdev, 2226 + struct radeon_ps *rps) 2227 + { 2228 + struct rv7xx_ps *new_ps = rv770_get_ps(rps); 2229 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2230 + 2231 + eg_pi->current_rps = *rps; 2232 + eg_pi->current_ps = *new_ps; 2233 + eg_pi->current_rps.ps_priv = &eg_pi->current_ps; 2234 + } 2235 + 2236 + static void btc_update_requested_ps(struct radeon_device *rdev, 2237 + struct radeon_ps *rps) 2238 + { 2239 + struct rv7xx_ps *new_ps = rv770_get_ps(rps); 2240 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2241 + 2242 + eg_pi->requested_rps = *rps; 2243 + eg_pi->requested_ps = *new_ps; 2244 + eg_pi->requested_rps.ps_priv = &eg_pi->requested_ps; 2245 + } 2246 + 2219 2247 void btc_dpm_reset_asic(struct radeon_device *rdev) 2220 2248 { 2221 2249 rv770_restrict_performance_levels_before_switch(rdev); ··· 2246 2230 rv770_set_boot_state(rdev); 2247 2231 } 2248 2232 2233 + int btc_dpm_pre_set_power_state(struct radeon_device *rdev) 2234 + { 2235 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2236 + struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 2237 + struct radeon_ps *new_ps = &requested_ps; 2238 + 2239 + btc_update_requested_ps(rdev, new_ps); 2240 + 2241 + btc_apply_state_adjust_rules(rdev, &eg_pi->requested_rps); 2242 + 2243 + return 0; 2244 + } 2245 + 2249 2246 int btc_dpm_set_power_state(struct radeon_device *rdev) 2250 2247 { 2251 2248 struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2252 - struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps; 2253 - struct radeon_ps *old_ps = rdev->pm.dpm.current_ps; 2254 - 2255 - btc_apply_state_adjust_rules(rdev, new_ps); 2249 + struct radeon_ps *new_ps = &eg_pi->requested_rps; 2250 + struct radeon_ps *old_ps = &eg_pi->current_rps; 2256 2251 2257 2252 btc_disable_ulv(rdev); 2258 2253 btc_set_boot_state_timing(rdev); ··· 2299 2272 #endif 2300 2273 2301 2274 return 0; 2275 + } 2276 + 2277 + void btc_dpm_post_set_power_state(struct radeon_device *rdev) 2278 + { 2279 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2280 + struct radeon_ps *new_ps = &eg_pi->requested_rps; 2281 + 2282 + btc_update_current_ps(rdev, new_ps); 2302 2283 } 2303 2284 2304 2285 int btc_dpm_enable(struct radeon_device *rdev) ··· 2404 2369 2405 2370 btc_init_stutter_mode(rdev); 2406 2371 2372 + btc_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 2373 + 2407 2374 return 0; 2408 2375 }; 2409 2376 ··· 2444 2407 btc_reset_to_default(rdev); 2445 2408 btc_stop_smc(rdev); 2446 2409 cypress_enable_spread_spectrum(rdev, false); 2410 + 2411 + btc_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 2447 2412 } 2448 2413 2449 2414 void btc_dpm_setup_asic(struct radeon_device *rdev) ··· 2629 2590 kfree(rdev->pm.dpm.ps); 2630 2591 kfree(rdev->pm.dpm.priv); 2631 2592 r600_free_extended_power_table(rdev); 2593 + } 2594 + 2595 + u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low) 2596 + { 2597 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2598 + struct rv7xx_ps *requested_state = rv770_get_ps(&eg_pi->requested_rps); 2599 + 2600 + if (low) 2601 + return requested_state->low.sclk; 2602 + else 2603 + return requested_state->high.sclk; 2604 + } 2605 + 2606 + u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low) 2607 + { 2608 + struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev); 2609 + struct rv7xx_ps *requested_state = rv770_get_ps(&eg_pi->requested_rps); 2610 + 2611 + if (low) 2612 + return requested_state->low.mclk; 2613 + else 2614 + return requested_state->high.mclk; 2632 2615 }
+4 -1
drivers/gpu/drm/radeon/cypress_dpm.h
··· 88 88 struct at ats[2]; 89 89 /* smc offsets */ 90 90 u16 mc_reg_table_start; 91 - struct rv7xx_ps hw_ps; 91 + struct radeon_ps current_rps; 92 + struct rv7xx_ps current_ps; 93 + struct radeon_ps requested_rps; 94 + struct rv7xx_ps requested_ps; 92 95 }; 93 96 94 97 #define CYPRESS_HASI_DFLT 400000
+4 -2
drivers/gpu/drm/radeon/radeon_asic.c
··· 1749 1749 .setup_asic = &btc_dpm_setup_asic, 1750 1750 .enable = &btc_dpm_enable, 1751 1751 .disable = &btc_dpm_disable, 1752 + .pre_set_power_state = &btc_dpm_pre_set_power_state, 1752 1753 .set_power_state = &btc_dpm_set_power_state, 1754 + .post_set_power_state = &btc_dpm_post_set_power_state, 1753 1755 .display_configuration_changed = &cypress_dpm_display_configuration_changed, 1754 1756 .fini = &btc_dpm_fini, 1755 - .get_sclk = &rv770_dpm_get_sclk, 1756 - .get_mclk = &rv770_dpm_get_mclk, 1757 + .get_sclk = &btc_dpm_get_sclk, 1758 + .get_mclk = &btc_dpm_get_mclk, 1757 1759 .print_power_state = &rv770_dpm_print_power_state, 1758 1760 }, 1759 1761 .pflip = {
+4
drivers/gpu/drm/radeon/radeon_asic.h
··· 542 542 void btc_dpm_setup_asic(struct radeon_device *rdev); 543 543 int btc_dpm_enable(struct radeon_device *rdev); 544 544 void btc_dpm_disable(struct radeon_device *rdev); 545 + int btc_dpm_pre_set_power_state(struct radeon_device *rdev); 545 546 int btc_dpm_set_power_state(struct radeon_device *rdev); 547 + void btc_dpm_post_set_power_state(struct radeon_device *rdev); 546 548 void btc_dpm_fini(struct radeon_device *rdev); 549 + u32 btc_dpm_get_sclk(struct radeon_device *rdev, bool low); 550 + u32 btc_dpm_get_mclk(struct radeon_device *rdev, bool low); 547 551 int sumo_dpm_init(struct radeon_device *rdev); 548 552 int sumo_dpm_enable(struct radeon_device *rdev); 549 553 void sumo_dpm_disable(struct radeon_device *rdev);