Linux Audio

Check our new training course

Loading...
v6.2
  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/acpi.h>
 12#include <linux/workqueue.h>
 13#include "pmf.h"
 14
 15static struct auto_mode_mode_config config_store;
 16static const char *state_as_str(unsigned int state);
 17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 18static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
 19				 struct auto_mode_mode_config *table)
 20{
 21	struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
 22
 23	amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL);
 24	amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL);
 25	amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL);
 26	amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
 27	amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
 28	amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
 29			 pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
 30	amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
 31			 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
 32
 33	if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
 34		apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,
 35				    config_store.mode_set[idx].fan_control.fan_id);
 36}
 37
 38static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
 39{
 40	int i, total = 0;
 41
 42	if (pdev->socket_power_history_idx == -1) {
 43		for (i = 0; i < AVG_SAMPLE_SIZE; i++)
 44			pdev->socket_power_history[i] = socket_power;
 45	}
 46
 47	pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;
 48	pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;
 49
 50	for (i = 0; i < AVG_SAMPLE_SIZE; i++)
 51		total += pdev->socket_power_history[i];
 52
 53	return total / AVG_SAMPLE_SIZE;
 54}
 55
 56void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
 57{
 58	int avg_power = 0;
 59	bool update = false;
 60	int i, j;
 61
 62	/* Get the average moving average computed by auto mode algorithm */
 63	avg_power = amd_pmf_get_moving_avg(dev, socket_power);
 64
 65	for (i = 0; i < AUTO_TRANSITION_MAX; i++) {
 66		if ((config_store.transition[i].shifting_up && avg_power >=
 67		     config_store.transition[i].power_threshold) ||
 68		    (!config_store.transition[i].shifting_up && avg_power <=
 69		     config_store.transition[i].power_threshold)) {
 70			if (config_store.transition[i].timer <
 71			    config_store.transition[i].time_constant)
 72				config_store.transition[i].timer += time_elapsed_ms;
 73		} else {
 74			config_store.transition[i].timer = 0;
 75		}
 76
 77		if (config_store.transition[i].timer >=
 78		    config_store.transition[i].time_constant &&
 79		    !config_store.transition[i].applied) {
 80			config_store.transition[i].applied = true;
 81			update = true;
 82		} else if (config_store.transition[i].timer <=
 83			   config_store.transition[i].time_constant &&
 84			   config_store.transition[i].applied) {
 85			config_store.transition[i].applied = false;
 86			update = true;
 87		}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 88	}
 89
 90	dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
 91		state_as_str(config_store.current_mode));
 92
 
 
 
 
 
 
 
 
 93	if (update) {
 94		for (j = 0; j < AUTO_TRANSITION_MAX; j++) {
 95			/* Apply the mode with highest priority indentified */
 96			if (config_store.transition[j].applied) {
 97				if (config_store.current_mode !=
 98				    config_store.transition[j].target_mode) {
 99					config_store.current_mode =
100							config_store.transition[j].target_mode;
101					dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n",
102						state_as_str(config_store.current_mode));
103					amd_pmf_set_automode(dev, config_store.current_mode, NULL);
104				}
105				break;
106			}
107		}
108	}
109}
110
111void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)
112{
113	int mode = config_store.current_mode;
114
115	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
116				   is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;
117
118	if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) &&
119	    mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) {
120		mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode;
121		amd_pmf_set_automode(dev, mode, NULL);
122	}
123	dev_dbg(dev->dev, "updated CQL thermals\n");
124}
125
126static void amd_pmf_get_power_threshold(void)
127{
128	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold =
129				config_store.mode_set[AUTO_BALANCE].power_floor -
130				config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta;
131
132	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold =
133				config_store.mode_set[AUTO_BALANCE].power_floor -
134				config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta;
135
136	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold =
137			config_store.mode_set[AUTO_QUIET].power_floor -
138			config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta;
139
140	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =
141		config_store.mode_set[AUTO_PERFORMANCE].power_floor -
142		config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143}
144
145static const char *state_as_str(unsigned int state)
146{
147	switch (state) {
148	case AUTO_QUIET:
149		return "QUIET";
150	case AUTO_BALANCE:
151		return "BALANCED";
152	case AUTO_PERFORMANCE_ON_LAP:
153		return "ON_LAP";
154	case AUTO_PERFORMANCE:
155		return "PERFORMANCE";
156	default:
157		return "Unknown Auto Mode State";
158	}
159}
160
161static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
162{
163	struct apmf_auto_mode output;
164	struct power_table_control *pwr_ctrl;
165	int i;
166
167	apmf_get_auto_mode_def(dev, &output);
168	/* time constant */
169	config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant =
170								output.balanced_to_quiet;
171	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant =
172								output.balanced_to_perf;
173	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant =
174								output.quiet_to_balanced;
175	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant =
176								output.perf_to_balanced;
177
178	/* power floor */
179	config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet;
180	config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced;
181	config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf;
182	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf;
183
184	/* Power delta for mode change */
185	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta =
186								output.pd_balanced_to_quiet;
187	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta =
188								output.pd_balanced_to_perf;
189	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta =
190								output.pd_quiet_to_balanced;
191	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta =
192								output.pd_perf_to_balanced;
193
194	/* Power threshold */
195	amd_pmf_get_power_threshold();
196
197	/* skin temperature limits */
198	pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control;
199	pwr_ctrl->spl = output.spl_quiet;
200	pwr_ctrl->sppt = output.sppt_quiet;
201	pwr_ctrl->fppt = output.fppt_quiet;
202	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet;
203	pwr_ctrl->stt_min = output.stt_min_limit_quiet;
204	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet;
205	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet;
206
207	pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control;
208	pwr_ctrl->spl = output.spl_balanced;
209	pwr_ctrl->sppt = output.sppt_balanced;
210	pwr_ctrl->fppt = output.fppt_balanced;
211	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced;
212	pwr_ctrl->stt_min = output.stt_min_limit_balanced;
213	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced;
214	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced;
215
216	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control;
217	pwr_ctrl->spl = output.spl_perf;
218	pwr_ctrl->sppt = output.sppt_perf;
219	pwr_ctrl->fppt = output.fppt_perf;
220	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf;
221	pwr_ctrl->stt_min = output.stt_min_limit_perf;
222	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf;
223	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf;
224
225	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control;
226	pwr_ctrl->spl = output.spl_perf_on_lap;
227	pwr_ctrl->sppt = output.sppt_perf_on_lap;
228	pwr_ctrl->fppt = output.fppt_perf_on_lap;
229	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap;
230	pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap;
231	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap;
232	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap;
233
234	/* Fan ID */
235	config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet;
236	config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced;
237	config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf;
238	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id =
239									output.fan_id_perf;
240
241	config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;
242	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
243								AUTO_PERFORMANCE;
244	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =
245									AUTO_BALANCE;
246	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =
247									AUTO_BALANCE;
248
249	config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false;
250	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true;
251	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true;
252	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up =
253										false;
254
255	for (i = 0 ; i < AUTO_MODE_MAX ; i++) {
256		if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO)
257			config_store.mode_set[i].fan_control.manual = false;
258		else
259			config_store.mode_set[i].fan_control.manual = true;
260	}
261
262	/* set to initial default values */
263	config_store.current_mode = AUTO_BALANCE;
264	dev->socket_power_history_idx = -1;
 
 
265}
266
267int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
268{
269	/*
270	 * OEM BIOS implementation guide says that if the auto mode is enabled
271	 * the platform_profile registration shall be done by the OEM driver.
272	 * There could be cases where both static slider and auto mode BIOS
273	 * functions are enabled, in that case enable static slider updates
274	 * only if it advertised as supported.
275	 */
276
277	if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
278		dev_dbg(dev->dev, "resetting AMT thermals\n");
279		amd_pmf_set_sps_power_limits(dev);
280	}
281	return 0;
282}
283
284void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
285{
286	amd_pmf_set_automode(dev, config_store.current_mode, NULL);
287}
288
289void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
290{
291	cancel_delayed_work_sync(&dev->work_buffer);
292}
293
294void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
295{
296	amd_pmf_load_defaults_auto_mode(dev);
297	amd_pmf_init_metrics_table(dev);
298}
v6.8
  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/acpi.h>
 12#include <linux/workqueue.h>
 13#include "pmf.h"
 14
 15static struct auto_mode_mode_config config_store;
 16static const char *state_as_str(unsigned int state);
 17
 18#ifdef CONFIG_AMD_PMF_DEBUG
 19static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data)
 20{
 21	struct auto_mode_mode_settings *its_mode;
 22
 23	pr_debug("Auto Mode Data - BEGIN\n");
 24
 25	/* time constant */
 26	pr_debug("balanced_to_perf: %u ms\n",
 27		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant);
 28	pr_debug("perf_to_balanced: %u ms\n",
 29		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant);
 30	pr_debug("quiet_to_balanced: %u ms\n",
 31		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant);
 32	pr_debug("balanced_to_quiet: %u ms\n",
 33		 data->transition[AUTO_TRANSITION_TO_QUIET].time_constant);
 34
 35	/* power floor */
 36	pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor);
 37	pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor);
 38	pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor);
 39
 40	/* Power delta for mode change */
 41	pr_debug("pd_balanced_to_perf: %u mW\n",
 42		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
 43	pr_debug("pd_perf_to_balanced: %u mW\n",
 44		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
 45	pr_debug("pd_quiet_to_balanced: %u mW\n",
 46		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
 47	pr_debug("pd_balanced_to_quiet: %u mW\n",
 48		 data->transition[AUTO_TRANSITION_TO_QUIET].power_delta);
 49
 50	/* skin temperature limits */
 51	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
 52	pr_debug("stt_apu_perf_on_lap: %u C\n",
 53		 its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
 54	pr_debug("stt_hs2_perf_on_lap: %u C\n",
 55		 its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
 56	pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min);
 57
 58	its_mode = &data->mode_set[AUTO_PERFORMANCE];
 59	pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
 60	pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
 61	pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min);
 62
 63	its_mode = &data->mode_set[AUTO_BALANCE];
 64	pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
 65	pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
 66	pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min);
 67
 68	its_mode = &data->mode_set[AUTO_QUIET];
 69	pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
 70	pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
 71	pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min);
 72
 73	/* SPL based power limits */
 74	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
 75	pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt);
 76	pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt);
 77	pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl);
 78	pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only);
 79
 80	its_mode = &data->mode_set[AUTO_PERFORMANCE];
 81	pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt);
 82	pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt);
 83	pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl);
 84	pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only);
 85
 86	its_mode = &data->mode_set[AUTO_BALANCE];
 87	pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt);
 88	pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt);
 89	pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl);
 90	pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only);
 91
 92	its_mode = &data->mode_set[AUTO_QUIET];
 93	pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt);
 94	pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt);
 95	pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl);
 96	pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only);
 97
 98	/* Fan ID */
 99	pr_debug("fan_id_perf: %lu\n",
100		 data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id);
101	pr_debug("fan_id_balanced: %lu\n",
102		 data->mode_set[AUTO_BALANCE].fan_control.fan_id);
103	pr_debug("fan_id_quiet: %lu\n",
104		 data->mode_set[AUTO_QUIET].fan_control.fan_id);
105
106	pr_debug("Auto Mode Data - END\n");
107}
108#else
109static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}
110#endif
111
112static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
113				 struct auto_mode_mode_config *table)
114{
115	struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
116
117	amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL);
118	amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL);
119	amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL);
120	amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
121	amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
122	amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
123			 pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
124	amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
125			 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
126
127	if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
128		apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,
129				    config_store.mode_set[idx].fan_control.fan_id);
130}
131
132static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
133{
134	int i, total = 0;
135
136	if (pdev->socket_power_history_idx == -1) {
137		for (i = 0; i < AVG_SAMPLE_SIZE; i++)
138			pdev->socket_power_history[i] = socket_power;
139	}
140
141	pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;
142	pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;
143
144	for (i = 0; i < AVG_SAMPLE_SIZE; i++)
145		total += pdev->socket_power_history[i];
146
147	return total / AVG_SAMPLE_SIZE;
148}
149
150void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
151{
152	int avg_power = 0;
153	bool update = false;
154	int i, j;
155
156	/* Get the average moving average computed by auto mode algorithm */
157	avg_power = amd_pmf_get_moving_avg(dev, socket_power);
158
159	for (i = 0; i < AUTO_TRANSITION_MAX; i++) {
160		if ((config_store.transition[i].shifting_up && avg_power >=
161		     config_store.transition[i].power_threshold) ||
162		    (!config_store.transition[i].shifting_up && avg_power <=
163		     config_store.transition[i].power_threshold)) {
164			if (config_store.transition[i].timer <
165			    config_store.transition[i].time_constant)
166				config_store.transition[i].timer += time_elapsed_ms;
167		} else {
168			config_store.transition[i].timer = 0;
169		}
170
171		if (config_store.transition[i].timer >=
172		    config_store.transition[i].time_constant &&
173		    !config_store.transition[i].applied) {
174			config_store.transition[i].applied = true;
175			update = true;
176		} else if (config_store.transition[i].timer <=
177			   config_store.transition[i].time_constant &&
178			   config_store.transition[i].applied) {
179			config_store.transition[i].applied = false;
180			update = true;
181		}
182
183#ifdef CONFIG_AMD_PMF_DEBUG
184		dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power,
185			state_as_str(config_store.current_mode));
186
187		dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n",
188			time_elapsed_ms, config_store.transition[i].timer,
189			config_store.transition[i].time_constant);
190
191		dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n",
192			config_store.transition[i].shifting_up,
193			config_store.transition[i].power_threshold,
194			config_store.mode_set[i].power_floor,
195			config_store.transition[i].power_delta);
196#endif
197	}
198
199	dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
200		state_as_str(config_store.current_mode));
201
202#ifdef CONFIG_AMD_PMF_DEBUG
203	dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n",
204		config_store.transition[0].applied,
205		config_store.transition[1].applied,
206		config_store.transition[2].applied,
207		config_store.transition[3].applied);
208#endif
209
210	if (update) {
211		for (j = 0; j < AUTO_TRANSITION_MAX; j++) {
212			/* Apply the mode with highest priority indentified */
213			if (config_store.transition[j].applied) {
214				if (config_store.current_mode !=
215				    config_store.transition[j].target_mode) {
216					config_store.current_mode =
217							config_store.transition[j].target_mode;
218					dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n",
219						state_as_str(config_store.current_mode));
220					amd_pmf_set_automode(dev, config_store.current_mode, NULL);
221				}
222				break;
223			}
224		}
225	}
226}
227
228void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)
229{
230	int mode = config_store.current_mode;
231
232	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
233				   is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;
234
235	if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) &&
236	    mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) {
237		mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode;
238		amd_pmf_set_automode(dev, mode, NULL);
239	}
240	dev_dbg(dev->dev, "updated CQL thermals\n");
241}
242
243static void amd_pmf_get_power_threshold(void)
244{
245	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold =
246				config_store.mode_set[AUTO_BALANCE].power_floor -
247				config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta;
248
249	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold =
250				config_store.mode_set[AUTO_BALANCE].power_floor -
251				config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta;
252
253	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold =
254			config_store.mode_set[AUTO_QUIET].power_floor -
255			config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta;
256
257	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =
258		config_store.mode_set[AUTO_PERFORMANCE].power_floor -
259		config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;
260
261#ifdef CONFIG_AMD_PMF_DEBUG
262	pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n",
263		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold,
264		 config_store.mode_set[AUTO_BALANCE].power_floor,
265		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta);
266
267	pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n",
268		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold,
269		 config_store.mode_set[AUTO_BALANCE].power_floor,
270		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
271
272	pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
273		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE]
274		 .power_threshold,
275		 config_store.mode_set[AUTO_QUIET].power_floor,
276		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
277
278	pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
279		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]
280		 .power_threshold,
281		 config_store.mode_set[AUTO_PERFORMANCE].power_floor,
282		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
283#endif
284}
285
286static const char *state_as_str(unsigned int state)
287{
288	switch (state) {
289	case AUTO_QUIET:
290		return "QUIET";
291	case AUTO_BALANCE:
292		return "BALANCED";
293	case AUTO_PERFORMANCE_ON_LAP:
294		return "ON_LAP";
295	case AUTO_PERFORMANCE:
296		return "PERFORMANCE";
297	default:
298		return "Unknown Auto Mode State";
299	}
300}
301
302static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
303{
304	struct apmf_auto_mode output;
305	struct power_table_control *pwr_ctrl;
306	int i;
307
308	apmf_get_auto_mode_def(dev, &output);
309	/* time constant */
310	config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant =
311								output.balanced_to_quiet;
312	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant =
313								output.balanced_to_perf;
314	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant =
315								output.quiet_to_balanced;
316	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant =
317								output.perf_to_balanced;
318
319	/* power floor */
320	config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet;
321	config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced;
322	config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf;
323	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf;
324
325	/* Power delta for mode change */
326	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta =
327								output.pd_balanced_to_quiet;
328	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta =
329								output.pd_balanced_to_perf;
330	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta =
331								output.pd_quiet_to_balanced;
332	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta =
333								output.pd_perf_to_balanced;
334
335	/* Power threshold */
336	amd_pmf_get_power_threshold();
337
338	/* skin temperature limits */
339	pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control;
340	pwr_ctrl->spl = output.spl_quiet;
341	pwr_ctrl->sppt = output.sppt_quiet;
342	pwr_ctrl->fppt = output.fppt_quiet;
343	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet;
344	pwr_ctrl->stt_min = output.stt_min_limit_quiet;
345	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet;
346	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet;
347
348	pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control;
349	pwr_ctrl->spl = output.spl_balanced;
350	pwr_ctrl->sppt = output.sppt_balanced;
351	pwr_ctrl->fppt = output.fppt_balanced;
352	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced;
353	pwr_ctrl->stt_min = output.stt_min_limit_balanced;
354	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced;
355	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced;
356
357	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control;
358	pwr_ctrl->spl = output.spl_perf;
359	pwr_ctrl->sppt = output.sppt_perf;
360	pwr_ctrl->fppt = output.fppt_perf;
361	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf;
362	pwr_ctrl->stt_min = output.stt_min_limit_perf;
363	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf;
364	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf;
365
366	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control;
367	pwr_ctrl->spl = output.spl_perf_on_lap;
368	pwr_ctrl->sppt = output.sppt_perf_on_lap;
369	pwr_ctrl->fppt = output.fppt_perf_on_lap;
370	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap;
371	pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap;
372	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap;
373	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap;
374
375	/* Fan ID */
376	config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet;
377	config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced;
378	config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf;
379	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id =
380									output.fan_id_perf;
381
382	config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;
383	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
384								AUTO_PERFORMANCE;
385	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =
386									AUTO_BALANCE;
387	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =
388									AUTO_BALANCE;
389
390	config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false;
391	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true;
392	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true;
393	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up =
394										false;
395
396	for (i = 0 ; i < AUTO_MODE_MAX ; i++) {
397		if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO)
398			config_store.mode_set[i].fan_control.manual = false;
399		else
400			config_store.mode_set[i].fan_control.manual = true;
401	}
402
403	/* set to initial default values */
404	config_store.current_mode = AUTO_BALANCE;
405	dev->socket_power_history_idx = -1;
406
407	amd_pmf_dump_auto_mode_defaults(&config_store);
408}
409
410int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
411{
412	/*
413	 * OEM BIOS implementation guide says that if the auto mode is enabled
414	 * the platform_profile registration shall be done by the OEM driver.
415	 * There could be cases where both static slider and auto mode BIOS
416	 * functions are enabled, in that case enable static slider updates
417	 * only if it advertised as supported.
418	 */
419
420	if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
421		dev_dbg(dev->dev, "resetting AMT thermals\n");
422		amd_pmf_set_sps_power_limits(dev);
423	}
424	return 0;
425}
426
427void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
428{
429	amd_pmf_set_automode(dev, config_store.current_mode, NULL);
430}
431
432void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
433{
434	cancel_delayed_work_sync(&dev->work_buffer);
435}
436
437void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
438{
439	amd_pmf_load_defaults_auto_mode(dev);
440	amd_pmf_init_metrics_table(dev);
441}