Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * AMD Platform Management Framework (PMF) 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 "pmf.h"
 12
 13static struct amd_pmf_static_slider_granular config_store;
 14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 15static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
 16{
 17	struct apmf_static_slider_granular_output output;
 18	int i, j, idx = 0;
 19
 20	memset(&config_store, 0, sizeof(config_store));
 21	apmf_get_static_slider_granular(dev, &output);
 22
 23	for (i = 0; i < POWER_SOURCE_MAX; i++) {
 24		for (j = 0; j < POWER_MODE_MAX; j++) {
 25			config_store.prop[i][j].spl = output.prop[idx].spl;
 26			config_store.prop[i][j].sppt = output.prop[idx].sppt;
 27			config_store.prop[i][j].sppt_apu_only =
 28						output.prop[idx].sppt_apu_only;
 29			config_store.prop[i][j].fppt = output.prop[idx].fppt;
 30			config_store.prop[i][j].stt_min = output.prop[idx].stt_min;
 31			config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =
 32					output.prop[idx].stt_skin_temp[STT_TEMP_APU];
 33			config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =
 34					output.prop[idx].stt_skin_temp[STT_TEMP_HS2];
 35			config_store.prop[i][j].fan_id = output.prop[idx].fan_id;
 36			idx++;
 37		}
 38	}
 
 39}
 40
 41void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
 42			   struct amd_pmf_static_slider_granular *table)
 43{
 44	int src = amd_pmf_get_power_source();
 45
 46	if (op == SLIDER_OP_SET) {
 47		amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);
 48		amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);
 49		amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);
 50		amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
 51				 config_store.prop[src][idx].sppt_apu_only, NULL);
 52		amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
 53				 config_store.prop[src][idx].stt_min, NULL);
 54		amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
 55				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);
 56		amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
 57				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);
 58	} else if (op == SLIDER_OP_GET) {
 59		amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
 60		amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);
 61		amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);
 62		amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,
 63				 &table->prop[src][idx].sppt_apu_only);
 64		amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,
 65				 &table->prop[src][idx].stt_min);
 66		amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,
 67				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);
 68		amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,
 69				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);
 70	}
 71}
 72
 73int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf)
 74{
 75	int mode;
 76
 77	mode = amd_pmf_get_pprof_modes(pmf);
 78	if (mode < 0)
 79		return mode;
 80
 81	amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
 82
 83	return 0;
 84}
 85
 86bool is_pprof_balanced(struct amd_pmf_dev *pmf)
 87{
 88	return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
 89}
 90
 91static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
 92			       enum platform_profile_option *profile)
 93{
 94	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
 95
 96	*profile = pmf->current_profile;
 97	return 0;
 98}
 99
100int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
101{
102	int mode;
103
104	switch (pmf->current_profile) {
105	case PLATFORM_PROFILE_PERFORMANCE:
106		mode = POWER_MODE_PERFORMANCE;
107		break;
108	case PLATFORM_PROFILE_BALANCED:
109		mode = POWER_MODE_BALANCED_POWER;
110		break;
111	case PLATFORM_PROFILE_LOW_POWER:
112		mode = POWER_MODE_POWER_SAVER;
113		break;
114	default:
115		dev_err(pmf->dev, "Unknown Platform Profile.\n");
116		return -EOPNOTSUPP;
117	}
118
119	return mode;
120}
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
123			       enum platform_profile_option profile)
124{
125	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
 
126
127	pmf->current_profile = profile;
128
129	return amd_pmf_set_sps_power_limits(pmf);
 
 
 
 
 
 
 
 
 
 
 
 
 
130}
131
132int amd_pmf_init_sps(struct amd_pmf_dev *dev)
133{
134	int err;
135
136	dev->current_profile = PLATFORM_PROFILE_BALANCED;
137	amd_pmf_load_defaults_sps(dev);
138
139	/* update SPS balanced power mode thermals */
140	amd_pmf_set_sps_power_limits(dev);
 
 
 
 
141
142	dev->pprof.profile_get = amd_pmf_profile_get;
143	dev->pprof.profile_set = amd_pmf_profile_set;
144
145	/* Setup supported modes */
146	set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
147	set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
148	set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
149
150	/* Create platform_profile structure and register */
151	err = platform_profile_register(&dev->pprof);
152	if (err)
153		dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
154			err);
155
156	return err;
157}
158
159void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
160{
161	platform_profile_remove();
162}
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * AMD Platform Management Framework (PMF) 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 "pmf.h"
 12
 13static struct amd_pmf_static_slider_granular config_store;
 14
 15#ifdef CONFIG_AMD_PMF_DEBUG
 16static const char *slider_as_str(unsigned int state)
 17{
 18	switch (state) {
 19	case POWER_MODE_PERFORMANCE:
 20		return "PERFORMANCE";
 21	case POWER_MODE_BALANCED_POWER:
 22		return "BALANCED_POWER";
 23	case POWER_MODE_POWER_SAVER:
 24		return "POWER_SAVER";
 25	default:
 26		return "Unknown Slider State";
 27	}
 28}
 29
 30const char *amd_pmf_source_as_str(unsigned int state)
 31{
 32	switch (state) {
 33	case POWER_SOURCE_AC:
 34		return "AC";
 35	case POWER_SOURCE_DC:
 36		return "DC";
 37	default:
 38		return "Unknown Power State";
 39	}
 40}
 41
 42static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data)
 43{
 44	int i, j;
 45
 46	pr_debug("Static Slider Data - BEGIN\n");
 47
 48	for (i = 0; i < POWER_SOURCE_MAX; i++) {
 49		for (j = 0; j < POWER_MODE_MAX; j++) {
 50			pr_debug("--- Source:%s Mode:%s ---\n", amd_pmf_source_as_str(i),
 51				 slider_as_str(j));
 52			pr_debug("SPL: %u mW\n", data->prop[i][j].spl);
 53			pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt);
 54			pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only);
 55			pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt);
 56			pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min);
 57			pr_debug("STT_SkinTempLimit_APU: %u C\n",
 58				 data->prop[i][j].stt_skin_temp[STT_TEMP_APU]);
 59			pr_debug("STT_SkinTempLimit_HS2: %u C\n",
 60				 data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]);
 61		}
 62	}
 63
 64	pr_debug("Static Slider Data - END\n");
 65}
 66#else
 67static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {}
 68#endif
 69
 70static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
 71{
 72	struct apmf_static_slider_granular_output output;
 73	int i, j, idx = 0;
 74
 75	memset(&config_store, 0, sizeof(config_store));
 76	apmf_get_static_slider_granular(dev, &output);
 77
 78	for (i = 0; i < POWER_SOURCE_MAX; i++) {
 79		for (j = 0; j < POWER_MODE_MAX; j++) {
 80			config_store.prop[i][j].spl = output.prop[idx].spl;
 81			config_store.prop[i][j].sppt = output.prop[idx].sppt;
 82			config_store.prop[i][j].sppt_apu_only =
 83						output.prop[idx].sppt_apu_only;
 84			config_store.prop[i][j].fppt = output.prop[idx].fppt;
 85			config_store.prop[i][j].stt_min = output.prop[idx].stt_min;
 86			config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =
 87					output.prop[idx].stt_skin_temp[STT_TEMP_APU];
 88			config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =
 89					output.prop[idx].stt_skin_temp[STT_TEMP_HS2];
 90			config_store.prop[i][j].fan_id = output.prop[idx].fan_id;
 91			idx++;
 92		}
 93	}
 94	amd_pmf_dump_sps_defaults(&config_store);
 95}
 96
 97void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
 98			   struct amd_pmf_static_slider_granular *table)
 99{
100	int src = amd_pmf_get_power_source();
101
102	if (op == SLIDER_OP_SET) {
103		amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);
104		amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);
105		amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);
106		amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
107				 config_store.prop[src][idx].sppt_apu_only, NULL);
108		amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
109				 config_store.prop[src][idx].stt_min, NULL);
110		amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
111				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);
112		amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
113				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);
114	} else if (op == SLIDER_OP_GET) {
115		amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
116		amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);
117		amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);
118		amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,
119				 &table->prop[src][idx].sppt_apu_only);
120		amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,
121				 &table->prop[src][idx].stt_min);
122		amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,
123				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);
124		amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,
125				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);
126	}
127}
128
129int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf)
130{
131	int mode;
132
133	mode = amd_pmf_get_pprof_modes(pmf);
134	if (mode < 0)
135		return mode;
136
137	amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
138
139	return 0;
140}
141
142bool is_pprof_balanced(struct amd_pmf_dev *pmf)
143{
144	return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
145}
146
147static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
148			       enum platform_profile_option *profile)
149{
150	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
151
152	*profile = pmf->current_profile;
153	return 0;
154}
155
156int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
157{
158	int mode;
159
160	switch (pmf->current_profile) {
161	case PLATFORM_PROFILE_PERFORMANCE:
162		mode = POWER_MODE_PERFORMANCE;
163		break;
164	case PLATFORM_PROFILE_BALANCED:
165		mode = POWER_MODE_BALANCED_POWER;
166		break;
167	case PLATFORM_PROFILE_LOW_POWER:
168		mode = POWER_MODE_POWER_SAVER;
169		break;
170	default:
171		dev_err(pmf->dev, "Unknown Platform Profile.\n");
172		return -EOPNOTSUPP;
173	}
174
175	return mode;
176}
177
178int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
179{
180	u8 flag = 0;
181	int mode;
182	int src;
183
184	mode = amd_pmf_get_pprof_modes(dev);
185	if (mode < 0)
186		return mode;
187
188	src = amd_pmf_get_power_source();
189
190	if (src == POWER_SOURCE_AC) {
191		switch (mode) {
192		case POWER_MODE_PERFORMANCE:
193			flag |= BIT(AC_BEST_PERF);
194			break;
195		case POWER_MODE_BALANCED_POWER:
196			flag |= BIT(AC_BETTER_PERF);
197			break;
198		case POWER_MODE_POWER_SAVER:
199			flag |= BIT(AC_BETTER_BATTERY);
200			break;
201		default:
202			dev_err(dev->dev, "unsupported platform profile\n");
203			return -EOPNOTSUPP;
204		}
205
206	} else if (src == POWER_SOURCE_DC) {
207		switch (mode) {
208		case POWER_MODE_PERFORMANCE:
209			flag |= BIT(DC_BEST_PERF);
210			break;
211		case POWER_MODE_BALANCED_POWER:
212			flag |= BIT(DC_BETTER_PERF);
213			break;
214		case POWER_MODE_POWER_SAVER:
215			flag |= BIT(DC_BATTERY_SAVER);
216			break;
217		default:
218			dev_err(dev->dev, "unsupported platform profile\n");
219			return -EOPNOTSUPP;
220		}
221	}
222
223	apmf_os_power_slider_update(dev, flag);
224
225	return 0;
226}
227
228static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
229			       enum platform_profile_option profile)
230{
231	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
232	int ret = 0;
233
234	pmf->current_profile = profile;
235
236	/* Notify EC about the slider position change */
237	if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
238		ret = amd_pmf_power_slider_update_event(pmf);
239		if (ret)
240			return ret;
241	}
242
243	if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
244		ret = amd_pmf_set_sps_power_limits(pmf);
245		if (ret)
246			return ret;
247	}
248
249	return 0;
250}
251
252int amd_pmf_init_sps(struct amd_pmf_dev *dev)
253{
254	int err;
255
256	dev->current_profile = PLATFORM_PROFILE_BALANCED;
 
257
258	if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
259		amd_pmf_load_defaults_sps(dev);
260
261		/* update SPS balanced power mode thermals */
262		amd_pmf_set_sps_power_limits(dev);
263	}
264
265	dev->pprof.profile_get = amd_pmf_profile_get;
266	dev->pprof.profile_set = amd_pmf_profile_set;
267
268	/* Setup supported modes */
269	set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
270	set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
271	set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
272
273	/* Create platform_profile structure and register */
274	err = platform_profile_register(&dev->pprof);
275	if (err)
276		dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
277			err);
278
279	return err;
280}
281
282void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
283{
284	platform_profile_remove();
285}