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

platform/x86/amd/pmf: Add support for CnQF

CnQF (a.k.a Cool and Quiet Framework) extends the static slider concept.
PMF dynamically manages system power limits and fan policy based on system
power trends which is representative of workload trend.

Static slider and CnQF controls are mutually exclusive for system power
budget adjustments. CnQF supports configurable number of modes which can
be unique for AC and DC. Every mode is representative of a system state
characterized by unique steady state and boost behavior.

OEMs can configure the different modes/system states and how the
transition to a mode happens. Whether to have CnQF manage system power
budget dynamically in AC or DC or both is also configurable. Mode changes
due to CnQF don't result in slider position change.

The default OEM values are obtained after evaluating the PMF ACPI function
idx 11 & 12 for AC and DC respectively. Whether to turn ON/OFF by default
is guided by a "flag" passed by the OEM BIOS.

Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Link: https://lore.kernel.org/r/20220922131202.56529-2-Shyam-sundar.S-k@amd.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Shyam Sundar S K and committed by
Hans de Goede
1738061c 9af48b26

+463 -2
+1 -1
drivers/platform/x86/amd/pmf/Makefile
··· 6 6 7 7 obj-$(CONFIG_AMD_PMF) += amd-pmf.o 8 8 amd-pmf-objs := core.o acpi.o sps.o \ 9 - auto-mode.o 9 + auto-mode.o cnqf.o
+10
drivers/platform/x86/amd/pmf/acpi.c
··· 233 233 return 0; 234 234 } 235 235 236 + int apmf_get_dyn_slider_def_ac(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data) 237 + { 238 + return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_AC, data, sizeof(*data)); 239 + } 240 + 241 + int apmf_get_dyn_slider_def_dc(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data) 242 + { 243 + return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_DC, data, sizeof(*data)); 244 + } 245 + 236 246 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev) 237 247 { 238 248 acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+335
drivers/platform/x86/amd/pmf/cnqf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * AMD Platform Management Framework Driver 4 + * 5 + * Copyright (c) 2022, Advanced Micro Devices, Inc. 6 + * All Rights Reserved. 7 + * 8 + * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 9 + */ 10 + 11 + #include <linux/workqueue.h> 12 + #include "pmf.h" 13 + 14 + static struct cnqf_config config_store; 15 + 16 + static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx, 17 + struct cnqf_config *table) 18 + { 19 + struct power_table_control *pc; 20 + 21 + pc = &config_store.mode_set[src][idx].power_control; 22 + 23 + amd_pmf_send_cmd(dev, SET_SPL, false, pc->spl, NULL); 24 + amd_pmf_send_cmd(dev, SET_FPPT, false, pc->fppt, NULL); 25 + amd_pmf_send_cmd(dev, SET_SPPT, false, pc->sppt, NULL); 26 + amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pc->sppt_apu_only, NULL); 27 + amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pc->stt_min, NULL); 28 + amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, pc->stt_skin_temp[STT_TEMP_APU], 29 + NULL); 30 + amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, pc->stt_skin_temp[STT_TEMP_HS2], 31 + NULL); 32 + 33 + if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX)) 34 + apmf_update_fan_idx(dev, 35 + config_store.mode_set[src][idx].fan_control.manual, 36 + config_store.mode_set[src][idx].fan_control.fan_id); 37 + 38 + return 0; 39 + } 40 + 41 + static void amd_pmf_update_power_threshold(int src) 42 + { 43 + struct cnqf_mode_settings *ts; 44 + struct cnqf_tran_params *tp; 45 + 46 + tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_QUIET]; 47 + ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 48 + tp->power_threshold = ts->power_floor - tp->power_delta; 49 + 50 + tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_TURBO]; 51 + ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 52 + tp->power_threshold = ts->power_floor - tp->power_delta; 53 + 54 + tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 55 + ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 56 + tp->power_threshold = ts->power_floor - tp->power_delta; 57 + 58 + tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 59 + ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 60 + tp->power_threshold = ts->power_floor - tp->power_delta; 61 + 62 + tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 63 + ts = &config_store.mode_set[src][CNQF_MODE_QUIET]; 64 + tp->power_threshold = ts->power_floor - tp->power_delta; 65 + 66 + tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 67 + ts = &config_store.mode_set[src][CNQF_MODE_TURBO]; 68 + tp->power_threshold = ts->power_floor - tp->power_delta; 69 + } 70 + 71 + static const char *state_as_str(unsigned int state) 72 + { 73 + switch (state) { 74 + case CNQF_MODE_QUIET: 75 + return "QUIET"; 76 + case CNQF_MODE_BALANCE: 77 + return "BALANCED"; 78 + case CNQF_MODE_TURBO: 79 + return "TURBO"; 80 + case CNQF_MODE_PERFORMANCE: 81 + return "PERFORMANCE"; 82 + default: 83 + return "Unknown CnQF mode"; 84 + } 85 + } 86 + 87 + static int amd_pmf_cnqf_get_power_source(struct amd_pmf_dev *dev) 88 + { 89 + if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) && 90 + is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 91 + return amd_pmf_get_power_source(); 92 + else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 93 + return POWER_SOURCE_DC; 94 + else 95 + return POWER_SOURCE_AC; 96 + } 97 + 98 + int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms) 99 + { 100 + struct cnqf_tran_params *tp; 101 + int src, i, j; 102 + u32 avg_power = 0; 103 + 104 + src = amd_pmf_cnqf_get_power_source(dev); 105 + 106 + if (dev->current_profile == PLATFORM_PROFILE_BALANCED) { 107 + amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 108 + } else { 109 + /* 110 + * Return from here if the platform_profile is not balanced 111 + * so that preference is given to user mode selection, rather 112 + * than enforcing CnQF to run all the time (if enabled) 113 + */ 114 + return -EINVAL; 115 + } 116 + 117 + for (i = 0; i < CNQF_TRANSITION_MAX; i++) { 118 + config_store.trans_param[src][i].timer += time_lapsed_ms; 119 + config_store.trans_param[src][i].total_power += socket_power; 120 + config_store.trans_param[src][i].count++; 121 + 122 + tp = &config_store.trans_param[src][i]; 123 + if (tp->timer >= tp->time_constant && tp->count) { 124 + avg_power = tp->total_power / tp->count; 125 + 126 + /* Reset the indices */ 127 + tp->timer = 0; 128 + tp->total_power = 0; 129 + tp->count = 0; 130 + 131 + if ((tp->shifting_up && avg_power >= tp->power_threshold) || 132 + (!tp->shifting_up && avg_power <= tp->power_threshold)) { 133 + tp->priority = true; 134 + } else { 135 + tp->priority = false; 136 + } 137 + } 138 + } 139 + 140 + dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n", 141 + avg_power, socket_power, state_as_str(config_store.current_mode)); 142 + 143 + for (j = 0; j < CNQF_TRANSITION_MAX; j++) { 144 + /* apply the highest priority */ 145 + if (config_store.trans_param[src][j].priority) { 146 + if (config_store.current_mode != 147 + config_store.trans_param[src][j].target_mode) { 148 + config_store.current_mode = 149 + config_store.trans_param[src][j].target_mode; 150 + dev_dbg(dev->dev, "Moving to Mode :%s\n", 151 + state_as_str(config_store.current_mode)); 152 + amd_pmf_set_cnqf(dev, src, 153 + config_store.current_mode, NULL); 154 + } 155 + break; 156 + } 157 + } 158 + return 0; 159 + } 160 + 161 + static void amd_pmf_update_trans_data(int idx, struct apmf_dyn_slider_output out) 162 + { 163 + struct cnqf_tran_params *tp; 164 + 165 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_QUIET]; 166 + tp->time_constant = out.t_balanced_to_quiet; 167 + tp->target_mode = CNQF_MODE_QUIET; 168 + tp->shifting_up = false; 169 + 170 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 171 + tp->time_constant = out.t_balanced_to_perf; 172 + tp->target_mode = CNQF_MODE_PERFORMANCE; 173 + tp->shifting_up = true; 174 + 175 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 176 + tp->time_constant = out.t_quiet_to_balanced; 177 + tp->target_mode = CNQF_MODE_BALANCE; 178 + tp->shifting_up = true; 179 + 180 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 181 + tp->time_constant = out.t_perf_to_balanced; 182 + tp->target_mode = CNQF_MODE_BALANCE; 183 + tp->shifting_up = false; 184 + 185 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 186 + tp->time_constant = out.t_turbo_to_perf; 187 + tp->target_mode = CNQF_MODE_PERFORMANCE; 188 + tp->shifting_up = false; 189 + 190 + tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_TURBO]; 191 + tp->time_constant = out.t_perf_to_turbo; 192 + tp->target_mode = CNQF_MODE_TURBO; 193 + tp->shifting_up = true; 194 + } 195 + 196 + static void amd_pmf_update_mode_set(int idx, struct apmf_dyn_slider_output out) 197 + { 198 + struct cnqf_mode_settings *ms; 199 + 200 + /* Quiet Mode */ 201 + ms = &config_store.mode_set[idx][CNQF_MODE_QUIET]; 202 + ms->power_floor = out.ps[APMF_CNQF_QUIET].pfloor; 203 + ms->power_control.fppt = out.ps[APMF_CNQF_QUIET].fppt; 204 + ms->power_control.sppt = out.ps[APMF_CNQF_QUIET].sppt; 205 + ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_QUIET].sppt_apu_only; 206 + ms->power_control.spl = out.ps[APMF_CNQF_QUIET].spl; 207 + ms->power_control.stt_min = out.ps[APMF_CNQF_QUIET].stt_min_limit; 208 + ms->power_control.stt_skin_temp[STT_TEMP_APU] = 209 + out.ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_APU]; 210 + ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 211 + out.ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_HS2]; 212 + ms->fan_control.fan_id = out.ps[APMF_CNQF_QUIET].fan_id; 213 + 214 + /* Balance Mode */ 215 + ms = &config_store.mode_set[idx][CNQF_MODE_BALANCE]; 216 + ms->power_floor = out.ps[APMF_CNQF_BALANCE].pfloor; 217 + ms->power_control.fppt = out.ps[APMF_CNQF_BALANCE].fppt; 218 + ms->power_control.sppt = out.ps[APMF_CNQF_BALANCE].sppt; 219 + ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_BALANCE].sppt_apu_only; 220 + ms->power_control.spl = out.ps[APMF_CNQF_BALANCE].spl; 221 + ms->power_control.stt_min = out.ps[APMF_CNQF_BALANCE].stt_min_limit; 222 + ms->power_control.stt_skin_temp[STT_TEMP_APU] = 223 + out.ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_APU]; 224 + ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 225 + out.ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_HS2]; 226 + ms->fan_control.fan_id = out.ps[APMF_CNQF_BALANCE].fan_id; 227 + 228 + /* Performance Mode */ 229 + ms = &config_store.mode_set[idx][CNQF_MODE_PERFORMANCE]; 230 + ms->power_floor = out.ps[APMF_CNQF_PERFORMANCE].pfloor; 231 + ms->power_control.fppt = out.ps[APMF_CNQF_PERFORMANCE].fppt; 232 + ms->power_control.sppt = out.ps[APMF_CNQF_PERFORMANCE].sppt; 233 + ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_PERFORMANCE].sppt_apu_only; 234 + ms->power_control.spl = out.ps[APMF_CNQF_PERFORMANCE].spl; 235 + ms->power_control.stt_min = out.ps[APMF_CNQF_PERFORMANCE].stt_min_limit; 236 + ms->power_control.stt_skin_temp[STT_TEMP_APU] = 237 + out.ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_APU]; 238 + ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 239 + out.ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_HS2]; 240 + ms->fan_control.fan_id = out.ps[APMF_CNQF_PERFORMANCE].fan_id; 241 + 242 + /* Turbo Mode */ 243 + ms = &config_store.mode_set[idx][CNQF_MODE_TURBO]; 244 + ms->power_floor = out.ps[APMF_CNQF_TURBO].pfloor; 245 + ms->power_control.fppt = out.ps[APMF_CNQF_TURBO].fppt; 246 + ms->power_control.sppt = out.ps[APMF_CNQF_TURBO].sppt; 247 + ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_TURBO].sppt_apu_only; 248 + ms->power_control.spl = out.ps[APMF_CNQF_TURBO].spl; 249 + ms->power_control.stt_min = out.ps[APMF_CNQF_TURBO].stt_min_limit; 250 + ms->power_control.stt_skin_temp[STT_TEMP_APU] = 251 + out.ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_APU]; 252 + ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 253 + out.ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_HS2]; 254 + ms->fan_control.fan_id = out.ps[APMF_CNQF_TURBO].fan_id; 255 + } 256 + 257 + static int amd_pmf_check_flags(struct amd_pmf_dev *dev) 258 + { 259 + struct apmf_dyn_slider_output out = {}; 260 + 261 + if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC)) 262 + apmf_get_dyn_slider_def_ac(dev, &out); 263 + else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 264 + apmf_get_dyn_slider_def_dc(dev, &out); 265 + 266 + return out.flags; 267 + } 268 + 269 + static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev) 270 + { 271 + struct apmf_dyn_slider_output out; 272 + int i, j, ret; 273 + 274 + for (i = 0; i < POWER_SOURCE_MAX; i++) { 275 + if (!is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC + i)) 276 + continue; 277 + 278 + if (i == POWER_SOURCE_AC) 279 + ret = apmf_get_dyn_slider_def_ac(dev, &out); 280 + else 281 + ret = apmf_get_dyn_slider_def_dc(dev, &out); 282 + if (ret) { 283 + dev_err(dev->dev, "APMF apmf_get_dyn_slider_def_dc failed :%d\n", ret); 284 + return ret; 285 + } 286 + 287 + amd_pmf_update_mode_set(i, out); 288 + amd_pmf_update_trans_data(i, out); 289 + amd_pmf_update_power_threshold(i); 290 + 291 + for (j = 0; j < CNQF_MODE_MAX; j++) { 292 + if (config_store.mode_set[i][j].fan_control.fan_id == FAN_INDEX_AUTO) 293 + config_store.mode_set[i][j].fan_control.manual = false; 294 + else 295 + config_store.mode_set[i][j].fan_control.manual = true; 296 + } 297 + } 298 + 299 + /* set to initial default values */ 300 + config_store.current_mode = CNQF_MODE_BALANCE; 301 + 302 + return 0; 303 + } 304 + 305 + void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev) 306 + { 307 + cancel_delayed_work_sync(&dev->work_buffer); 308 + } 309 + 310 + int amd_pmf_init_cnqf(struct amd_pmf_dev *dev) 311 + { 312 + int ret, src; 313 + 314 + /* 315 + * Note the caller of this function has already checked that both 316 + * APMF_FUNC_DYN_SLIDER_AC and APMF_FUNC_DYN_SLIDER_DC are supported. 317 + */ 318 + 319 + ret = amd_pmf_load_defaults_cnqf(dev); 320 + if (ret < 0) 321 + return ret; 322 + 323 + amd_pmf_init_metrics_table(dev); 324 + 325 + dev->cnqf_supported = true; 326 + dev->cnqf_enabled = amd_pmf_check_flags(dev); 327 + 328 + /* update the thermal for CnQF */ 329 + if (dev->cnqf_enabled && dev->current_profile == PLATFORM_PROFILE_BALANCED) { 330 + src = amd_pmf_cnqf_get_power_source(dev); 331 + amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 332 + } 333 + 334 + return 0; 335 + }
+18 -1
drivers/platform/x86/amd/pmf/core.c
··· 123 123 amd_pmf_trans_automode(dev, socket_power, time_elapsed_ms); 124 124 } 125 125 126 + if (dev->cnqf_enabled) { 127 + /* Apply the CnQF transition */ 128 + amd_pmf_trans_cnqf(dev, socket_power, time_elapsed_ms); 129 + } 130 + 126 131 dev->start_time = ktime_to_ms(ktime_get()); 127 132 schedule_delayed_work(&dev->work_buffer, msecs_to_jiffies(metrics_table_loop_ms)); 128 133 mutex_unlock(&dev->update_mutex); ··· 257 252 258 253 static void amd_pmf_init_features(struct amd_pmf_dev *dev) 259 254 { 255 + int ret; 256 + 260 257 /* Enable Static Slider */ 261 258 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) { 262 259 amd_pmf_init_sps(dev); ··· 269 262 if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { 270 263 amd_pmf_init_auto_mode(dev); 271 264 dev_dbg(dev->dev, "Auto Mode Init done\n"); 265 + } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) || 266 + is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) { 267 + /* Enable Cool n Quiet Framework (CnQF) */ 268 + ret = amd_pmf_init_cnqf(dev); 269 + if (ret) 270 + dev_warn(dev->dev, "CnQF Init failed\n"); 272 271 } 273 272 } 274 273 ··· 283 270 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) 284 271 amd_pmf_deinit_sps(dev); 285 272 286 - if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) 273 + if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { 287 274 amd_pmf_deinit_auto_mode(dev); 275 + } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) || 276 + is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) { 277 + amd_pmf_deinit_cnqf(dev); 278 + } 288 279 } 289 280 290 281 static const struct acpi_device_id amd_pmf_acpi_ids[] = {
+99
drivers/platform/x86/amd/pmf/pmf.h
··· 22 22 #define APMF_FUNC_AUTO_MODE 5 23 23 #define APMF_FUNC_SET_FAN_IDX 7 24 24 #define APMF_FUNC_STATIC_SLIDER_GRANULAR 9 25 + #define APMF_FUNC_DYN_SLIDER_AC 11 26 + #define APMF_FUNC_DYN_SLIDER_DC 12 25 27 26 28 /* Message Definitions */ 27 29 #define SET_SPL 0x03 /* SPL: Sustained Power Limit */ ··· 167 165 int socket_power_history_idx; 168 166 bool amt_enabled; 169 167 struct mutex update_mutex; /* protects race between ACPI handler and metrics thread */ 168 + bool cnqf_enabled; 169 + bool cnqf_supported; 170 170 }; 171 171 172 172 struct apmf_sps_prop_granular { ··· 298 294 u32 fan_id_quiet; 299 295 } __packed; 300 296 297 + /* CnQF Layer */ 298 + enum cnqf_trans_priority { 299 + CNQF_TRANSITION_TO_TURBO, /* Any other mode to Turbo Mode */ 300 + CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE, /* quiet/balance to Performance Mode */ 301 + CNQF_TRANSITION_FROM_QUIET_TO_BALANCE, /* Quiet Mode to Balance Mode */ 302 + CNQF_TRANSITION_TO_QUIET, /* Any other mode to Quiet Mode */ 303 + CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE, /* Performance/Turbo to Balance Mode */ 304 + CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE, /* Turbo mode to Performance Mode */ 305 + CNQF_TRANSITION_MAX, 306 + }; 307 + 308 + enum cnqf_mode { 309 + CNQF_MODE_QUIET, 310 + CNQF_MODE_BALANCE, 311 + CNQF_MODE_PERFORMANCE, 312 + CNQF_MODE_TURBO, 313 + CNQF_MODE_MAX, 314 + }; 315 + 316 + enum apmf_cnqf_pos { 317 + APMF_CNQF_TURBO, 318 + APMF_CNQF_PERFORMANCE, 319 + APMF_CNQF_BALANCE, 320 + APMF_CNQF_QUIET, 321 + APMF_CNQF_MAX, 322 + }; 323 + 324 + struct cnqf_mode_settings { 325 + struct power_table_control power_control; 326 + struct fan_table_control fan_control; 327 + u32 power_floor; 328 + }; 329 + 330 + struct cnqf_tran_params { 331 + u32 time_constant; /* minimum time required to switch to next mode */ 332 + u32 power_delta; /* minimum power required to switch to next mode */ 333 + u32 power_threshold; 334 + u32 timer; /* elapsed time. if timer > timethreshold, it will move to next mode */ 335 + u32 total_power; 336 + u32 count; 337 + bool priority; 338 + bool shifting_up; 339 + enum cnqf_mode target_mode; 340 + }; 341 + 342 + struct cnqf_power_delta { 343 + u32 to_turbo; 344 + u32 balance_to_perf; 345 + u32 quiet_to_balance; 346 + u32 to_quiet; 347 + u32 perf_to_balance; 348 + u32 turbo_to_perf; 349 + }; 350 + 351 + struct cnqf_config { 352 + struct cnqf_tran_params trans_param[POWER_SOURCE_MAX][CNQF_TRANSITION_MAX]; 353 + struct cnqf_mode_settings mode_set[POWER_SOURCE_MAX][CNQF_MODE_MAX]; 354 + struct power_table_control defaults; 355 + enum cnqf_mode current_mode; 356 + struct cnqf_power_delta power_delta[POWER_SOURCE_MAX]; 357 + u32 power_src; 358 + u32 avg_power; 359 + }; 360 + 361 + struct apmf_cnqf_power_set { 362 + u32 pfloor; 363 + u32 fppt; 364 + u32 sppt; 365 + u32 sppt_apu_only; 366 + u32 spl; 367 + u32 stt_min_limit; 368 + u8 stt_skintemp[STT_TEMP_COUNT]; 369 + u32 fan_id; 370 + } __packed; 371 + 372 + struct apmf_dyn_slider_output { 373 + u16 size; 374 + u16 flags; 375 + u32 t_perf_to_turbo; 376 + u32 t_balanced_to_perf; 377 + u32 t_quiet_to_balanced; 378 + u32 t_balanced_to_quiet; 379 + u32 t_perf_to_balanced; 380 + u32 t_turbo_to_perf; 381 + struct apmf_cnqf_power_set ps[APMF_CNQF_MAX]; 382 + } __packed; 383 + 301 384 /* Core Layer */ 302 385 int apmf_acpi_init(struct amd_pmf_dev *pmf_dev); 303 386 void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev); ··· 415 324 void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event); 416 325 int amd_pmf_reset_amt(struct amd_pmf_dev *dev); 417 326 void amd_pmf_handle_amt(struct amd_pmf_dev *dev); 327 + 328 + /* CnQF Layer */ 329 + int apmf_get_dyn_slider_def_ac(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data); 330 + int apmf_get_dyn_slider_def_dc(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_output *data); 331 + int amd_pmf_init_cnqf(struct amd_pmf_dev *dev); 332 + void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev); 333 + int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms); 334 + 418 335 #endif /* PMF_H */