162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD Platform Management Framework Driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2022, Advanced Micro Devices, Inc. 662306a36Sopenharmony_ci * All Rights Reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/acpi.h> 1262306a36Sopenharmony_ci#include <linux/workqueue.h> 1362306a36Sopenharmony_ci#include "pmf.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic struct auto_mode_mode_config config_store; 1662306a36Sopenharmony_cistatic const char *state_as_str(unsigned int state); 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#ifdef CONFIG_AMD_PMF_DEBUG 1962306a36Sopenharmony_cistatic void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct auto_mode_mode_settings *its_mode; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci pr_debug("Auto Mode Data - BEGIN\n"); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci /* time constant */ 2662306a36Sopenharmony_ci pr_debug("balanced_to_perf: %u ms\n", 2762306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant); 2862306a36Sopenharmony_ci pr_debug("perf_to_balanced: %u ms\n", 2962306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant); 3062306a36Sopenharmony_ci pr_debug("quiet_to_balanced: %u ms\n", 3162306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant); 3262306a36Sopenharmony_ci pr_debug("balanced_to_quiet: %u ms\n", 3362306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_TO_QUIET].time_constant); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci /* power floor */ 3662306a36Sopenharmony_ci pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor); 3762306a36Sopenharmony_ci pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor); 3862306a36Sopenharmony_ci pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* Power delta for mode change */ 4162306a36Sopenharmony_ci pr_debug("pd_balanced_to_perf: %u mW\n", 4262306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); 4362306a36Sopenharmony_ci pr_debug("pd_perf_to_balanced: %u mW\n", 4462306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); 4562306a36Sopenharmony_ci pr_debug("pd_quiet_to_balanced: %u mW\n", 4662306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); 4762306a36Sopenharmony_ci pr_debug("pd_balanced_to_quiet: %u mW\n", 4862306a36Sopenharmony_ci data->transition[AUTO_TRANSITION_TO_QUIET].power_delta); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* skin temperature limits */ 5162306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; 5262306a36Sopenharmony_ci pr_debug("stt_apu_perf_on_lap: %u C\n", 5362306a36Sopenharmony_ci its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); 5462306a36Sopenharmony_ci pr_debug("stt_hs2_perf_on_lap: %u C\n", 5562306a36Sopenharmony_ci its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); 5662306a36Sopenharmony_ci pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_PERFORMANCE]; 5962306a36Sopenharmony_ci pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); 6062306a36Sopenharmony_ci pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); 6162306a36Sopenharmony_ci pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_BALANCE]; 6462306a36Sopenharmony_ci pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); 6562306a36Sopenharmony_ci pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); 6662306a36Sopenharmony_ci pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_QUIET]; 6962306a36Sopenharmony_ci pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]); 7062306a36Sopenharmony_ci pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]); 7162306a36Sopenharmony_ci pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* SPL based power limits */ 7462306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP]; 7562306a36Sopenharmony_ci pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt); 7662306a36Sopenharmony_ci pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt); 7762306a36Sopenharmony_ci pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl); 7862306a36Sopenharmony_ci pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_PERFORMANCE]; 8162306a36Sopenharmony_ci pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt); 8262306a36Sopenharmony_ci pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt); 8362306a36Sopenharmony_ci pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl); 8462306a36Sopenharmony_ci pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_BALANCE]; 8762306a36Sopenharmony_ci pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt); 8862306a36Sopenharmony_ci pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt); 8962306a36Sopenharmony_ci pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl); 9062306a36Sopenharmony_ci pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci its_mode = &data->mode_set[AUTO_QUIET]; 9362306a36Sopenharmony_ci pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt); 9462306a36Sopenharmony_ci pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt); 9562306a36Sopenharmony_ci pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl); 9662306a36Sopenharmony_ci pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* Fan ID */ 9962306a36Sopenharmony_ci pr_debug("fan_id_perf: %lu\n", 10062306a36Sopenharmony_ci data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id); 10162306a36Sopenharmony_ci pr_debug("fan_id_balanced: %lu\n", 10262306a36Sopenharmony_ci data->mode_set[AUTO_BALANCE].fan_control.fan_id); 10362306a36Sopenharmony_ci pr_debug("fan_id_quiet: %lu\n", 10462306a36Sopenharmony_ci data->mode_set[AUTO_QUIET].fan_control.fan_id); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci pr_debug("Auto Mode Data - END\n"); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci#else 10962306a36Sopenharmony_cistatic void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {} 11062306a36Sopenharmony_ci#endif 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx, 11362306a36Sopenharmony_ci struct auto_mode_mode_config *table) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL); 11862306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL); 11962306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL); 12062306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL); 12162306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL); 12262306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, 12362306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL); 12462306a36Sopenharmony_ci amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, 12562306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX)) 12862306a36Sopenharmony_ci apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual, 12962306a36Sopenharmony_ci config_store.mode_set[idx].fan_control.fan_id); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci int i, total = 0; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (pdev->socket_power_history_idx == -1) { 13762306a36Sopenharmony_ci for (i = 0; i < AVG_SAMPLE_SIZE; i++) 13862306a36Sopenharmony_ci pdev->socket_power_history[i] = socket_power; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE; 14262306a36Sopenharmony_ci pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci for (i = 0; i < AVG_SAMPLE_SIZE; i++) 14562306a36Sopenharmony_ci total += pdev->socket_power_history[i]; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci return total / AVG_SAMPLE_SIZE; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_civoid amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci int avg_power = 0; 15362306a36Sopenharmony_ci bool update = false; 15462306a36Sopenharmony_ci int i, j; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* Get the average moving average computed by auto mode algorithm */ 15762306a36Sopenharmony_ci avg_power = amd_pmf_get_moving_avg(dev, socket_power); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (i = 0; i < AUTO_TRANSITION_MAX; i++) { 16062306a36Sopenharmony_ci if ((config_store.transition[i].shifting_up && avg_power >= 16162306a36Sopenharmony_ci config_store.transition[i].power_threshold) || 16262306a36Sopenharmony_ci (!config_store.transition[i].shifting_up && avg_power <= 16362306a36Sopenharmony_ci config_store.transition[i].power_threshold)) { 16462306a36Sopenharmony_ci if (config_store.transition[i].timer < 16562306a36Sopenharmony_ci config_store.transition[i].time_constant) 16662306a36Sopenharmony_ci config_store.transition[i].timer += time_elapsed_ms; 16762306a36Sopenharmony_ci } else { 16862306a36Sopenharmony_ci config_store.transition[i].timer = 0; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (config_store.transition[i].timer >= 17262306a36Sopenharmony_ci config_store.transition[i].time_constant && 17362306a36Sopenharmony_ci !config_store.transition[i].applied) { 17462306a36Sopenharmony_ci config_store.transition[i].applied = true; 17562306a36Sopenharmony_ci update = true; 17662306a36Sopenharmony_ci } else if (config_store.transition[i].timer <= 17762306a36Sopenharmony_ci config_store.transition[i].time_constant && 17862306a36Sopenharmony_ci config_store.transition[i].applied) { 17962306a36Sopenharmony_ci config_store.transition[i].applied = false; 18062306a36Sopenharmony_ci update = true; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#ifdef CONFIG_AMD_PMF_DEBUG 18462306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power, 18562306a36Sopenharmony_ci state_as_str(config_store.current_mode)); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n", 18862306a36Sopenharmony_ci time_elapsed_ms, config_store.transition[i].timer, 18962306a36Sopenharmony_ci config_store.transition[i].time_constant); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n", 19262306a36Sopenharmony_ci config_store.transition[i].shifting_up, 19362306a36Sopenharmony_ci config_store.transition[i].power_threshold, 19462306a36Sopenharmony_ci config_store.mode_set[i].power_floor, 19562306a36Sopenharmony_ci config_store.transition[i].power_delta); 19662306a36Sopenharmony_ci#endif 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power, 20062306a36Sopenharmony_ci state_as_str(config_store.current_mode)); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#ifdef CONFIG_AMD_PMF_DEBUG 20362306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n", 20462306a36Sopenharmony_ci config_store.transition[0].applied, 20562306a36Sopenharmony_ci config_store.transition[1].applied, 20662306a36Sopenharmony_ci config_store.transition[2].applied, 20762306a36Sopenharmony_ci config_store.transition[3].applied); 20862306a36Sopenharmony_ci#endif 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (update) { 21162306a36Sopenharmony_ci for (j = 0; j < AUTO_TRANSITION_MAX; j++) { 21262306a36Sopenharmony_ci /* Apply the mode with highest priority indentified */ 21362306a36Sopenharmony_ci if (config_store.transition[j].applied) { 21462306a36Sopenharmony_ci if (config_store.current_mode != 21562306a36Sopenharmony_ci config_store.transition[j].target_mode) { 21662306a36Sopenharmony_ci config_store.current_mode = 21762306a36Sopenharmony_ci config_store.transition[j].target_mode; 21862306a36Sopenharmony_ci dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n", 21962306a36Sopenharmony_ci state_as_str(config_store.current_mode)); 22062306a36Sopenharmony_ci amd_pmf_set_automode(dev, config_store.current_mode, NULL); 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci break; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_civoid amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci int mode = config_store.current_mode; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode = 23362306a36Sopenharmony_ci is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) && 23662306a36Sopenharmony_ci mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) { 23762306a36Sopenharmony_ci mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode; 23862306a36Sopenharmony_ci amd_pmf_set_automode(dev, mode, NULL); 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci dev_dbg(dev->dev, "updated CQL thermals\n"); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void amd_pmf_get_power_threshold(void) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold = 24662306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].power_floor - 24762306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold = 25062306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].power_floor - 25162306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold = 25462306a36Sopenharmony_ci config_store.mode_set[AUTO_QUIET].power_floor - 25562306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold = 25862306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE].power_floor - 25962306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci#ifdef CONFIG_AMD_PMF_DEBUG 26262306a36Sopenharmony_ci pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n", 26362306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold, 26462306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].power_floor, 26562306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n", 26862306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold, 26962306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].power_floor, 27062306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", 27362306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE] 27462306a36Sopenharmony_ci .power_threshold, 27562306a36Sopenharmony_ci config_store.mode_set[AUTO_QUIET].power_floor, 27662306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n", 27962306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE] 28062306a36Sopenharmony_ci .power_threshold, 28162306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE].power_floor, 28262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta); 28362306a36Sopenharmony_ci#endif 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cistatic const char *state_as_str(unsigned int state) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci switch (state) { 28962306a36Sopenharmony_ci case AUTO_QUIET: 29062306a36Sopenharmony_ci return "QUIET"; 29162306a36Sopenharmony_ci case AUTO_BALANCE: 29262306a36Sopenharmony_ci return "BALANCED"; 29362306a36Sopenharmony_ci case AUTO_PERFORMANCE_ON_LAP: 29462306a36Sopenharmony_ci return "ON_LAP"; 29562306a36Sopenharmony_ci case AUTO_PERFORMANCE: 29662306a36Sopenharmony_ci return "PERFORMANCE"; 29762306a36Sopenharmony_ci default: 29862306a36Sopenharmony_ci return "Unknown Auto Mode State"; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci struct apmf_auto_mode output; 30562306a36Sopenharmony_ci struct power_table_control *pwr_ctrl; 30662306a36Sopenharmony_ci int i; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci apmf_get_auto_mode_def(dev, &output); 30962306a36Sopenharmony_ci /* time constant */ 31062306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant = 31162306a36Sopenharmony_ci output.balanced_to_quiet; 31262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant = 31362306a36Sopenharmony_ci output.balanced_to_perf; 31462306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant = 31562306a36Sopenharmony_ci output.quiet_to_balanced; 31662306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant = 31762306a36Sopenharmony_ci output.perf_to_balanced; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* power floor */ 32062306a36Sopenharmony_ci config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet; 32162306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced; 32262306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf; 32362306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* Power delta for mode change */ 32662306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta = 32762306a36Sopenharmony_ci output.pd_balanced_to_quiet; 32862306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta = 32962306a36Sopenharmony_ci output.pd_balanced_to_perf; 33062306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta = 33162306a36Sopenharmony_ci output.pd_quiet_to_balanced; 33262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta = 33362306a36Sopenharmony_ci output.pd_perf_to_balanced; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* Power threshold */ 33662306a36Sopenharmony_ci amd_pmf_get_power_threshold(); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* skin temperature limits */ 33962306a36Sopenharmony_ci pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control; 34062306a36Sopenharmony_ci pwr_ctrl->spl = output.spl_quiet; 34162306a36Sopenharmony_ci pwr_ctrl->sppt = output.sppt_quiet; 34262306a36Sopenharmony_ci pwr_ctrl->fppt = output.fppt_quiet; 34362306a36Sopenharmony_ci pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet; 34462306a36Sopenharmony_ci pwr_ctrl->stt_min = output.stt_min_limit_quiet; 34562306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet; 34662306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control; 34962306a36Sopenharmony_ci pwr_ctrl->spl = output.spl_balanced; 35062306a36Sopenharmony_ci pwr_ctrl->sppt = output.sppt_balanced; 35162306a36Sopenharmony_ci pwr_ctrl->fppt = output.fppt_balanced; 35262306a36Sopenharmony_ci pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced; 35362306a36Sopenharmony_ci pwr_ctrl->stt_min = output.stt_min_limit_balanced; 35462306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced; 35562306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control; 35862306a36Sopenharmony_ci pwr_ctrl->spl = output.spl_perf; 35962306a36Sopenharmony_ci pwr_ctrl->sppt = output.sppt_perf; 36062306a36Sopenharmony_ci pwr_ctrl->fppt = output.fppt_perf; 36162306a36Sopenharmony_ci pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf; 36262306a36Sopenharmony_ci pwr_ctrl->stt_min = output.stt_min_limit_perf; 36362306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf; 36462306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control; 36762306a36Sopenharmony_ci pwr_ctrl->spl = output.spl_perf_on_lap; 36862306a36Sopenharmony_ci pwr_ctrl->sppt = output.sppt_perf_on_lap; 36962306a36Sopenharmony_ci pwr_ctrl->fppt = output.fppt_perf_on_lap; 37062306a36Sopenharmony_ci pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap; 37162306a36Sopenharmony_ci pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap; 37262306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap; 37362306a36Sopenharmony_ci pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Fan ID */ 37662306a36Sopenharmony_ci config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet; 37762306a36Sopenharmony_ci config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced; 37862306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf; 37962306a36Sopenharmony_ci config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id = 38062306a36Sopenharmony_ci output.fan_id_perf; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET; 38362306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode = 38462306a36Sopenharmony_ci AUTO_PERFORMANCE; 38562306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode = 38662306a36Sopenharmony_ci AUTO_BALANCE; 38762306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode = 38862306a36Sopenharmony_ci AUTO_BALANCE; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false; 39162306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true; 39262306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true; 39362306a36Sopenharmony_ci config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up = 39462306a36Sopenharmony_ci false; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci for (i = 0 ; i < AUTO_MODE_MAX ; i++) { 39762306a36Sopenharmony_ci if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO) 39862306a36Sopenharmony_ci config_store.mode_set[i].fan_control.manual = false; 39962306a36Sopenharmony_ci else 40062306a36Sopenharmony_ci config_store.mode_set[i].fan_control.manual = true; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci /* set to initial default values */ 40462306a36Sopenharmony_ci config_store.current_mode = AUTO_BALANCE; 40562306a36Sopenharmony_ci dev->socket_power_history_idx = -1; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci amd_pmf_dump_auto_mode_defaults(&config_store); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ciint amd_pmf_reset_amt(struct amd_pmf_dev *dev) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci /* 41362306a36Sopenharmony_ci * OEM BIOS implementation guide says that if the auto mode is enabled 41462306a36Sopenharmony_ci * the platform_profile registration shall be done by the OEM driver. 41562306a36Sopenharmony_ci * There could be cases where both static slider and auto mode BIOS 41662306a36Sopenharmony_ci * functions are enabled, in that case enable static slider updates 41762306a36Sopenharmony_ci * only if it advertised as supported. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) { 42162306a36Sopenharmony_ci dev_dbg(dev->dev, "resetting AMT thermals\n"); 42262306a36Sopenharmony_ci amd_pmf_set_sps_power_limits(dev); 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci return 0; 42562306a36Sopenharmony_ci} 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_civoid amd_pmf_handle_amt(struct amd_pmf_dev *dev) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci amd_pmf_set_automode(dev, config_store.current_mode, NULL); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_civoid amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci cancel_delayed_work_sync(&dev->work_buffer); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_civoid amd_pmf_init_auto_mode(struct amd_pmf_dev *dev) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci amd_pmf_load_defaults_auto_mode(dev); 44062306a36Sopenharmony_ci amd_pmf_init_metrics_table(dev); 44162306a36Sopenharmony_ci} 442