Merge tag 'powerpc-5.11-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux/fpc-iii.git] / sound / soc / sof / control.c
bloba5dd728c580a9374ef10b1a754900ccd39380dc8
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 //
11 /* Mixer Controls */
13 #include <linux/pm_runtime.h>
14 #include <linux/leds.h>
15 #include "sof-priv.h"
16 #include "sof-audio.h"
18 static void update_mute_led(struct snd_sof_control *scontrol,
19 struct snd_kcontrol *kcontrol,
20 struct snd_ctl_elem_value *ucontrol)
22 int temp = 0;
23 int mask;
24 int i;
26 mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
28 for (i = 0; i < scontrol->num_channels; i++) {
29 if (ucontrol->value.integer.value[i]) {
30 temp |= mask;
31 break;
35 if (temp == scontrol->led_ctl.led_value)
36 return;
38 scontrol->led_ctl.led_value = temp;
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
48 static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
50 if (value >= size)
51 return volume_map[size - 1];
53 return volume_map[value];
56 static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
58 int i;
60 for (i = 0; i < size; i++) {
61 if (volume_map[i] >= value)
62 return i;
65 return i - 1;
68 int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
69 struct snd_ctl_elem_value *ucontrol)
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;
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);
83 return 0;
86 int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
87 struct snd_ctl_elem_value *ucontrol)
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;
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;
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;
117 int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
119 struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value;
120 struct snd_sof_control *scontrol = sm->dobj.private;
121 unsigned int channels = scontrol->num_channels;
122 int platform_max;
124 if (!sm->platform_max)
125 sm->platform_max = sm->max;
126 platform_max = sm->platform_max;
128 if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
129 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
130 else
131 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
133 uinfo->count = channels;
134 uinfo->value.integer.min = 0;
135 uinfo->value.integer.max = platform_max - sm->min;
136 return 0;
139 int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
140 struct snd_ctl_elem_value *ucontrol)
142 struct soc_mixer_control *sm =
143 (struct soc_mixer_control *)kcontrol->private_value;
144 struct snd_sof_control *scontrol = sm->dobj.private;
145 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
146 unsigned int i, channels = scontrol->num_channels;
148 /* read back each channel */
149 for (i = 0; i < channels; i++)
150 ucontrol->value.integer.value[i] = cdata->chanv[i].value;
152 return 0;
155 int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
156 struct snd_ctl_elem_value *ucontrol)
158 struct soc_mixer_control *sm =
159 (struct soc_mixer_control *)kcontrol->private_value;
160 struct snd_sof_control *scontrol = sm->dobj.private;
161 struct snd_soc_component *scomp = scontrol->scomp;
162 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
163 unsigned int i, channels = scontrol->num_channels;
164 bool change = false;
165 u32 value;
167 /* update each channel */
168 for (i = 0; i < channels; i++) {
169 value = ucontrol->value.integer.value[i];
170 change = change || (value != cdata->chanv[i].value);
171 cdata->chanv[i].channel = i;
172 cdata->chanv[i].value = value;
175 if (scontrol->led_ctl.use_led)
176 update_mute_led(scontrol, kcontrol, ucontrol);
178 /* notify DSP of mixer updates */
179 if (pm_runtime_active(scomp->dev))
180 snd_sof_ipc_set_get_comp_data(scontrol,
181 SOF_IPC_COMP_SET_VALUE,
182 SOF_CTRL_TYPE_VALUE_CHAN_GET,
183 SOF_CTRL_CMD_SWITCH,
184 true);
186 return change;
189 int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
190 struct snd_ctl_elem_value *ucontrol)
192 struct soc_enum *se =
193 (struct soc_enum *)kcontrol->private_value;
194 struct snd_sof_control *scontrol = se->dobj.private;
195 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
196 unsigned int i, channels = scontrol->num_channels;
198 /* read back each channel */
199 for (i = 0; i < channels; i++)
200 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
202 return 0;
205 int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
206 struct snd_ctl_elem_value *ucontrol)
208 struct soc_enum *se =
209 (struct soc_enum *)kcontrol->private_value;
210 struct snd_sof_control *scontrol = se->dobj.private;
211 struct snd_soc_component *scomp = scontrol->scomp;
212 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
213 unsigned int i, channels = scontrol->num_channels;
214 bool change = false;
215 u32 value;
217 /* update each channel */
218 for (i = 0; i < channels; i++) {
219 value = ucontrol->value.enumerated.item[i];
220 change = change || (value != cdata->chanv[i].value);
221 cdata->chanv[i].channel = i;
222 cdata->chanv[i].value = value;
225 /* notify DSP of enum updates */
226 if (pm_runtime_active(scomp->dev))
227 snd_sof_ipc_set_get_comp_data(scontrol,
228 SOF_IPC_COMP_SET_VALUE,
229 SOF_CTRL_TYPE_VALUE_CHAN_GET,
230 SOF_CTRL_CMD_ENUM,
231 true);
233 return change;
236 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
237 struct snd_ctl_elem_value *ucontrol)
239 struct soc_bytes_ext *be =
240 (struct soc_bytes_ext *)kcontrol->private_value;
241 struct snd_sof_control *scontrol = be->dobj.private;
242 struct snd_soc_component *scomp = scontrol->scomp;
243 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
244 struct sof_abi_hdr *data = cdata->data;
245 size_t size;
247 if (be->max > sizeof(ucontrol->value.bytes.data)) {
248 dev_err_ratelimited(scomp->dev,
249 "error: data max %d exceeds ucontrol data array size\n",
250 be->max);
251 return -EINVAL;
254 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
255 if (data->size > be->max - sizeof(*data)) {
256 dev_err_ratelimited(scomp->dev,
257 "error: %u bytes of control data is invalid, max is %zu\n",
258 data->size, be->max - sizeof(*data));
259 return -EINVAL;
262 size = data->size + sizeof(*data);
264 /* copy back to kcontrol */
265 memcpy(ucontrol->value.bytes.data, data, size);
267 return 0;
270 int snd_sof_bytes_put(struct snd_kcontrol *kcontrol,
271 struct snd_ctl_elem_value *ucontrol)
273 struct soc_bytes_ext *be =
274 (struct soc_bytes_ext *)kcontrol->private_value;
275 struct snd_sof_control *scontrol = be->dobj.private;
276 struct snd_soc_component *scomp = scontrol->scomp;
277 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
278 struct sof_abi_hdr *data = cdata->data;
279 size_t size;
281 if (be->max > sizeof(ucontrol->value.bytes.data)) {
282 dev_err_ratelimited(scomp->dev,
283 "error: data max %d exceeds ucontrol data array size\n",
284 be->max);
285 return -EINVAL;
288 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
289 if (data->size > be->max - sizeof(*data)) {
290 dev_err_ratelimited(scomp->dev,
291 "error: data size too big %u bytes max is %zu\n",
292 data->size, be->max - sizeof(*data));
293 return -EINVAL;
296 size = data->size + sizeof(*data);
298 /* copy from kcontrol */
299 memcpy(data, ucontrol->value.bytes.data, size);
301 /* notify DSP of byte control updates */
302 if (pm_runtime_active(scomp->dev))
303 snd_sof_ipc_set_get_comp_data(scontrol,
304 SOF_IPC_COMP_SET_DATA,
305 SOF_CTRL_TYPE_DATA_SET,
306 scontrol->cmd,
307 true);
309 return 0;
312 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
313 const unsigned int __user *binary_data,
314 unsigned int size)
316 struct soc_bytes_ext *be =
317 (struct soc_bytes_ext *)kcontrol->private_value;
318 struct snd_sof_control *scontrol = be->dobj.private;
319 struct snd_soc_component *scomp = scontrol->scomp;
320 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
321 struct snd_ctl_tlv header;
322 const struct snd_ctl_tlv __user *tlvd =
323 (const struct snd_ctl_tlv __user *)binary_data;
325 /* make sure we have at least a header */
326 if (size < sizeof(struct snd_ctl_tlv))
327 return -EINVAL;
330 * The beginning of bytes data contains a header from where
331 * the length (as bytes) is needed to know the correct copy
332 * length of data from tlvd->tlv.
334 if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv)))
335 return -EFAULT;
337 /* make sure TLV info is consistent */
338 if (header.length + sizeof(struct snd_ctl_tlv) > size) {
339 dev_err_ratelimited(scomp->dev, "error: inconsistent TLV, data %d + header %zu > %d\n",
340 header.length, sizeof(struct snd_ctl_tlv), size);
341 return -EINVAL;
344 /* be->max is coming from topology */
345 if (header.length > be->max) {
346 dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n",
347 header.length, be->max);
348 return -EINVAL;
351 /* Check that header id matches the command */
352 if (header.numid != scontrol->cmd) {
353 dev_err_ratelimited(scomp->dev,
354 "error: incorrect numid %d\n",
355 header.numid);
356 return -EINVAL;
359 if (copy_from_user(cdata->data, tlvd->tlv, header.length))
360 return -EFAULT;
362 if (cdata->data->magic != SOF_ABI_MAGIC) {
363 dev_err_ratelimited(scomp->dev,
364 "error: Wrong ABI magic 0x%08x.\n",
365 cdata->data->magic);
366 return -EINVAL;
369 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
370 dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n",
371 cdata->data->abi);
372 return -EINVAL;
375 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
376 if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
377 dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n");
378 return -EINVAL;
381 /* notify DSP of byte control updates */
382 if (pm_runtime_active(scomp->dev))
383 snd_sof_ipc_set_get_comp_data(scontrol,
384 SOF_IPC_COMP_SET_DATA,
385 SOF_CTRL_TYPE_DATA_SET,
386 scontrol->cmd,
387 true);
389 return 0;
392 int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data,
393 unsigned int size)
395 struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value;
396 struct snd_sof_control *scontrol = be->dobj.private;
397 struct snd_soc_component *scomp = scontrol->scomp;
398 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
399 struct snd_ctl_tlv header;
400 struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
401 size_t data_size;
402 int ret;
403 int err;
406 * Decrement the limit by ext bytes header size to
407 * ensure the user space buffer is not exceeded.
409 if (size < sizeof(struct snd_ctl_tlv))
410 return -ENOSPC;
411 size -= sizeof(struct snd_ctl_tlv);
413 ret = pm_runtime_get_sync(scomp->dev);
414 if (ret < 0 && ret != -EACCES) {
415 dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to resume %d\n", ret);
416 pm_runtime_put_noidle(scomp->dev);
417 return ret;
420 /* set the ABI header values */
421 cdata->data->magic = SOF_ABI_MAGIC;
422 cdata->data->abi = SOF_ABI_VERSION;
423 /* get all the component data from DSP */
424 ret = snd_sof_ipc_set_get_comp_data(scontrol, SOF_IPC_COMP_GET_DATA, SOF_CTRL_TYPE_DATA_GET,
425 scontrol->cmd, false);
426 if (ret < 0)
427 goto out;
429 /* check data size doesn't exceed max coming from topology */
430 if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
431 dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
432 cdata->data->size,
433 be->max - sizeof(struct sof_abi_hdr));
434 ret = -EINVAL;
435 goto out;
438 data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
440 /* make sure we don't exceed size provided by user space for data */
441 if (data_size > size) {
442 ret = -ENOSPC;
443 goto out;
446 header.numid = scontrol->cmd;
447 header.length = data_size;
448 if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) {
449 ret = -EFAULT;
450 goto out;
453 if (copy_to_user(tlvd->tlv, cdata->data, data_size))
454 ret = -EFAULT;
455 out:
456 pm_runtime_mark_last_busy(scomp->dev);
457 err = pm_runtime_put_autosuspend(scomp->dev);
458 if (err < 0)
459 dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to idle %d\n", err);
461 return ret;
464 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
465 unsigned int __user *binary_data,
466 unsigned int size)
468 struct soc_bytes_ext *be =
469 (struct soc_bytes_ext *)kcontrol->private_value;
470 struct snd_sof_control *scontrol = be->dobj.private;
471 struct snd_soc_component *scomp = scontrol->scomp;
472 struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
473 struct snd_ctl_tlv header;
474 struct snd_ctl_tlv __user *tlvd =
475 (struct snd_ctl_tlv __user *)binary_data;
476 size_t data_size;
479 * Decrement the limit by ext bytes header size to
480 * ensure the user space buffer is not exceeded.
482 if (size < sizeof(struct snd_ctl_tlv))
483 return -ENOSPC;
484 size -= sizeof(struct snd_ctl_tlv);
486 /* set the ABI header values */
487 cdata->data->magic = SOF_ABI_MAGIC;
488 cdata->data->abi = SOF_ABI_VERSION;
490 /* check data size doesn't exceed max coming from topology */
491 if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) {
492 dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n",
493 cdata->data->size,
494 be->max - sizeof(struct sof_abi_hdr));
495 return -EINVAL;
498 data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
500 /* make sure we don't exceed size provided by user space for data */
501 if (data_size > size)
502 return -ENOSPC;
504 header.numid = scontrol->cmd;
505 header.length = data_size;
506 if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
507 return -EFAULT;
509 if (copy_to_user(tlvd->tlv, cdata->data, data_size))
510 return -EFAULT;
512 return 0;