xref: /kernel/linux/linux-5.10/sound/soc/sof/control.c (revision 8c2ecf20)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license.  When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9//
10
11/* Mixer Controls */
12
13#include <linux/pm_runtime.h>
14#include <linux/leds.h>
15#include "sof-priv.h"
16#include "sof-audio.h"
17
18static void update_mute_led(struct snd_sof_control *scontrol,
19			    struct snd_kcontrol *kcontrol,
20			    struct snd_ctl_elem_value *ucontrol)
21{
22	int temp = 0;
23	int mask;
24	int i;
25
26	mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
27
28	for (i = 0; i < scontrol->num_channels; i++) {
29		if (ucontrol->value.integer.value[i]) {
30			temp |= mask;
31			break;
32		}
33	}
34
35	if (temp == scontrol->led_ctl.led_value)
36		return;
37
38	scontrol->led_ctl.led_value = temp;
39
40#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
41	if (!scontrol->led_ctl.direction)
42		ledtrig_audio_set(LED_AUDIO_MUTE, temp ? LED_OFF : LED_ON);
43	else
44		ledtrig_audio_set(LED_AUDIO_MICMUTE, temp ? LED_OFF : LED_ON);
45#endif
46}
47
48static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
49{
50	if (value >= size)
51		return volume_map[size - 1];
52
53	return volume_map[value];
54}
55
56static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
57{
58	int i;
59
60	for (i = 0; i < size; i++) {
61		if (volume_map[i] >= value)
62			return i;
63	}
64
65	return i - 1;
66}
67
68int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
69		       struct snd_ctl_elem_value *ucontrol)
70{
71	struct soc_mixer_control *sm =
72		(struct soc_mixer_control *)kcontrol->private_value;
73	struct snd_sof_control *scontrol = sm->dobj.private;
74	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
75	unsigned int i, channels = scontrol->num_channels;
76
77	/* read back each channel */
78	for (i = 0; i < channels; i++)
79		ucontrol->value.integer.value[i] =
80			ipc_to_mixer(cdata->chanv[i].value,
81				     scontrol->volume_table, sm->max + 1);
82
83	return 0;
84}
85
86int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
87		       struct snd_ctl_elem_value *ucontrol)
88{
89	struct soc_mixer_control *sm =
90		(struct soc_mixer_control *)kcontrol->private_value;
91	struct snd_sof_control *scontrol = sm->dobj.private;
92	struct snd_soc_component *scomp = scontrol->scomp;
93	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
94	unsigned int i, channels = scontrol->num_channels;
95	bool change = false;
96	u32 value;
97
98	/* update each channel */
99	for (i = 0; i < channels; i++) {
100		value = mixer_to_ipc(ucontrol->value.integer.value[i],
101				     scontrol->volume_table, sm->max + 1);
102		change = change || (value != cdata->chanv[i].value);
103		cdata->chanv[i].channel = i;
104		cdata->chanv[i].value = value;
105	}
106
107	/* notify DSP of mixer updates */
108	if (pm_runtime_active(scomp->dev))
109		snd_sof_ipc_set_get_comp_data(scontrol,
110					      SOF_IPC_COMP_SET_VALUE,
111					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
112					      SOF_CTRL_CMD_VOLUME,
113					      true);
114	return change;
115}
116
117int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
118		       struct snd_ctl_elem_value *ucontrol)
119{
120	struct soc_mixer_control *sm =
121		(struct soc_mixer_control *)kcontrol->private_value;
122	struct snd_sof_control *scontrol = sm->dobj.private;
123	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
124	unsigned int i, channels = scontrol->num_channels;
125
126	/* read back each channel */
127	for (i = 0; i < channels; i++)
128		ucontrol->value.integer.value[i] = cdata->chanv[i].value;
129
130	return 0;
131}
132
133int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
134		       struct snd_ctl_elem_value *ucontrol)
135{
136	struct soc_mixer_control *sm =
137		(struct soc_mixer_control *)kcontrol->private_value;
138	struct snd_sof_control *scontrol = sm->dobj.private;
139	struct snd_soc_component *scomp = scontrol->scomp;
140	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
141	unsigned int i, channels = scontrol->num_channels;
142	bool change = false;
143	u32 value;
144
145	/* update each channel */
146	for (i = 0; i < channels; i++) {
147		value = ucontrol->value.integer.value[i];
148		change = change || (value != cdata->chanv[i].value);
149		cdata->chanv[i].channel = i;
150		cdata->chanv[i].value = value;
151	}
152
153	if (scontrol->led_ctl.use_led)
154		update_mute_led(scontrol, kcontrol, ucontrol);
155
156	/* notify DSP of mixer updates */
157	if (pm_runtime_active(scomp->dev))
158		snd_sof_ipc_set_get_comp_data(scontrol,
159					      SOF_IPC_COMP_SET_VALUE,
160					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
161					      SOF_CTRL_CMD_SWITCH,
162					      true);
163
164	return change;
165}
166
167int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
168		     struct snd_ctl_elem_value *ucontrol)
169{
170	struct soc_enum *se =
171		(struct soc_enum *)kcontrol->private_value;
172	struct snd_sof_control *scontrol = se->dobj.private;
173	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
174	unsigned int i, channels = scontrol->num_channels;
175
176	/* read back each channel */
177	for (i = 0; i < channels; i++)
178		ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
179
180	return 0;
181}
182
183int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
184		     struct snd_ctl_elem_value *ucontrol)
185{
186	struct soc_enum *se =
187		(struct soc_enum *)kcontrol->private_value;
188	struct snd_sof_control *scontrol = se->dobj.private;
189	struct snd_soc_component *scomp = scontrol->scomp;
190	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
191	unsigned int i, channels = scontrol->num_channels;
192	bool change = false;
193	u32 value;
194
195	/* update each channel */
196	for (i = 0; i < channels; i++) {
197		value = ucontrol->value.enumerated.item[i];
198		change = change || (value != cdata->chanv[i].value);
199		cdata->chanv[i].channel = i;
200		cdata->chanv[i].value = value;
201	}
202
203	/* notify DSP of enum updates */
204	if (pm_runtime_active(scomp->dev))
205		snd_sof_ipc_set_get_comp_data(scontrol,
206					      SOF_IPC_COMP_SET_VALUE,
207					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
208					      SOF_CTRL_CMD_ENUM,
209					      true);
210
211	return change;
212}
213
214int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
215		      struct snd_ctl_elem_value *ucontrol)
216{
217	struct soc_bytes_ext *be =
218		(struct soc_bytes_ext *)kcontrol->private_value;
219	struct snd_sof_control *scontrol = be->dobj.private;
220	struct snd_soc_component *scomp = scontrol->scomp;
221	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
222	struct sof_abi_hdr *data = cdata->data;
223	size_t size;
224
225	if (be->max > sizeof(ucontrol->value.bytes.data)) {
226		dev_err_ratelimited(scomp->dev,
227				    "error: data max %d exceeds ucontrol data array size\n",
228				    be->max);
229		return -EINVAL;
230	}
231
232	/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
233	if (data->size > be->max - sizeof(*data)) {
234		dev_err_ratelimited(scomp->dev,
235				    "error: %u bytes of control data is invalid, max is %zu\n",
236				    data->size, be->max - sizeof(*data));
237		return -EINVAL;
238	}
239
240	size = data->size + sizeof(*data);
241
242	/* copy back to kcontrol */
243	memcpy(ucontrol->value.bytes.data, data, size);
244
245	return 0;
246}
247
248int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
249		      struct snd_ctl_elem_value *ucontrol)
250{
251	struct soc_bytes_ext *be =
252		(struct soc_bytes_ext *)kcontrol->private_value;
253	struct snd_sof_control *scontrol = be->dobj.private;
254	struct snd_soc_component *scomp = scontrol->scomp;
255	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
256	struct sof_abi_hdr *data = cdata->data;
257	size_t size;
258
259	if (be->max > sizeof(ucontrol->value.bytes.data)) {
260		dev_err_ratelimited(scomp->dev,
261				    "error: data max %d exceeds ucontrol data array size\n",
262				    be->max);
263		return -EINVAL;
264	}
265
266	/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
267	if (data->size > be->max - sizeof(*data)) {
268		dev_err_ratelimited(scomp->dev,
269				    "error: data size too big %u bytes max is %zu\n",
270				    data->size, be->max - sizeof(*data));
271		return -EINVAL;
272	}
273
274	size = data->size + sizeof(*data);
275
276	/* copy from kcontrol */
277	memcpy(data, ucontrol->value.bytes.data, size);
278
279	/* notify DSP of byte control updates */
280	if (pm_runtime_active(scomp->dev))
281		snd_sof_ipc_set_get_comp_data(scontrol,
282					      SOF_IPC_COMP_SET_DATA,
283					      SOF_CTRL_TYPE_DATA_SET,
284					      scontrol->cmd,
285					      true);
286
287	return 0;
288}
289
290int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
291			  const unsigned int __user *binary_data,
292			  unsigned int size)
293{
294	struct soc_bytes_ext *be =
295		(struct soc_bytes_ext *)kcontrol->private_value;
296	struct snd_sof_control *scontrol = be->dobj.private;
297	struct snd_soc_component *scomp = scontrol->scomp;
298	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
299	struct snd_ctl_tlv header;
300	const struct snd_ctl_tlv __user *tlvd =
301		(const struct snd_ctl_tlv __user *)binary_data;
302
303	/* make sure we have at least a header */
304	if (size < sizeof(struct snd_ctl_tlv))
305		return -EINVAL;
306
307	/*
308	 * The beginning of bytes data contains a header from where
309	 * the length (as bytes) is needed to know the correct copy
310	 * length of data from tlvd->tlv.
311	 */
312	if (copy_from_user(&header, tlvd, sizeof(const struct snd_ctl_tlv)))
313		return -EFAULT;
314
315	/* make sure TLV info is consistent */
316	if (header.length + sizeof(struct snd_ctl_tlv) > size) {
317		dev_err_ratelimited(scomp->dev, "error: inconsistent TLV, data %d + header %zu > %d\n",
318				    header.length, sizeof(struct snd_ctl_tlv), size);
319		return -EINVAL;
320	}
321
322	/* be->max is coming from topology */
323	if (header.length > be->max) {
324		dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n",
325				    header.length, be->max);
326		return -EINVAL;
327	}
328
329	/* Check that header id matches the command */
330	if (header.numid != scontrol->cmd) {
331		dev_err_ratelimited(scomp->dev,
332				    "error: incorrect numid %d\n",
333				    header.numid);
334		return -EINVAL;
335	}
336
337	if (copy_from_user(cdata->data, tlvd->tlv, header.length))
338		return -EFAULT;
339
340	if (cdata->data->magic != SOF_ABI_MAGIC) {
341		dev_err_ratelimited(scomp->dev,
342				    "error: Wrong ABI magic 0x%08x.\n",
343				    cdata->data->magic);
344		return -EINVAL;
345	}
346
347	if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
348		dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n",
349				    cdata->data->abi);
350		return -EINVAL;
351	}
352
353	/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
354	if (cdata->data->size > be->max - sizeof(const struct sof_abi_hdr)) {
355		dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
356		return -EINVAL;
357	}
358
359	/* notify DSP of byte control updates */
360	if (pm_runtime_active(scomp->dev))
361		snd_sof_ipc_set_get_comp_data(scontrol,
362					      SOF_IPC_COMP_SET_DATA,
363					      SOF_CTRL_TYPE_DATA_SET,
364					      scontrol->cmd,
365					      true);
366
367	return 0;
368}
369
370int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
371				   unsigned int size)
372{
373	struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
374	struct snd_sof_control *scontrol = be->dobj.private;
375	struct snd_soc_component *scomp = scontrol->scomp;
376	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
377	struct snd_ctl_tlv header;
378	struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
379	size_t data_size;
380	int ret;
381	int err;
382
383	/*
384	 * Decrement the limit by ext bytes header size to
385	 * ensure the user space buffer is not exceeded.
386	 */
387	if (size < sizeof(struct snd_ctl_tlv))
388		return -ENOSPC;
389	size -= sizeof(struct snd_ctl_tlv);
390
391	ret = pm_runtime_get_sync(scomp->dev);
392	if (ret < 0 && ret != -EACCES) {
393		dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to resume %d\n", ret);
394		pm_runtime_put_noidle(scomp->dev);
395		return ret;
396	}
397
398	/* set the ABI header values */
399	cdata->data->magic = SOF_ABI_MAGIC;
400	cdata->data->abi = SOF_ABI_VERSION;
401	/* get all the component data from DSP */
402	ret = snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_GET_DATA, SOF_CTRL_TYPE_DATA_GET,
403					    scontrol->cmd, false);
404	if (ret < 0)
405		goto out;
406
407	/* check data size doesn't exceed max coming from topology */
408	if (cdata->data->size > be->max - sizeof(const struct sof_abi_hdr)) {
409		dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
410				    cdata->data->size,
411				    be->max - sizeof(const struct sof_abi_hdr));
412		ret = -EINVAL;
413		goto out;
414	}
415
416	data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
417
418	/* make sure we don't exceed size provided by user space for data */
419	if (data_size > size) {
420		ret = -ENOSPC;
421		goto out;
422	}
423
424	header.numid = scontrol->cmd;
425	header.length = data_size;
426	if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) {
427		ret = -EFAULT;
428		goto out;
429	}
430
431	if (copy_to_user(tlvd->tlv, cdata->data, data_size))
432		ret = -EFAULT;
433out:
434	pm_runtime_mark_last_busy(scomp->dev);
435	err = pm_runtime_put_autosuspend(scomp->dev);
436	if (err < 0)
437		dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to idle %d\n", err);
438
439	return ret;
440}
441
442int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
443			  unsigned int __user *binary_data,
444			  unsigned int size)
445{
446	struct soc_bytes_ext *be =
447		(struct soc_bytes_ext *)kcontrol->private_value;
448	struct snd_sof_control *scontrol = be->dobj.private;
449	struct snd_soc_component *scomp = scontrol->scomp;
450	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
451	struct snd_ctl_tlv header;
452	struct snd_ctl_tlv __user *tlvd =
453		(struct snd_ctl_tlv __user *)binary_data;
454	size_t data_size;
455
456	/*
457	 * Decrement the limit by ext bytes header size to
458	 * ensure the user space buffer is not exceeded.
459	 */
460	if (size < sizeof(struct snd_ctl_tlv))
461		return -ENOSPC;
462	size -= sizeof(struct snd_ctl_tlv);
463
464	/* set the ABI header values */
465	cdata->data->magic = SOF_ABI_MAGIC;
466	cdata->data->abi = SOF_ABI_VERSION;
467
468	/* check data size doesn't exceed max coming from topology */
469	if (cdata->data->size > be->max - sizeof(const struct sof_abi_hdr)) {
470		dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
471				    cdata->data->size,
472				    be->max - sizeof(const struct sof_abi_hdr));
473		return -EINVAL;
474	}
475
476	data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
477
478	/* make sure we don't exceed size provided by user space for data */
479	if (data_size > size)
480		return -ENOSPC;
481
482	header.numid = scontrol->cmd;
483	header.length = data_size;
484	if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv)))
485		return -EFAULT;
486
487	if (copy_to_user(tlvd->tlv, cdata->data, data_size))
488		return -EFAULT;
489
490	return 0;
491}
492