xref: /linux/sound/soc/sof/control.c (revision 6fdcba32711044c35c0e1b094cbd8f3f0b4472c9)
1 // SPDX-License-Identifier: (GPL-2.0 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 
17 static void update_mute_led(struct snd_sof_control *scontrol,
18 			    struct snd_kcontrol *kcontrol,
19 			    struct snd_ctl_elem_value *ucontrol)
20 {
21 	unsigned int temp = 0;
22 	unsigned int mask;
23 	int i;
24 
25 	mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
26 
27 	for (i = 0; i < scontrol->num_channels; i++) {
28 		if (ucontrol->value.integer.value[i]) {
29 			temp |= mask;
30 			break;
31 		}
32 	}
33 
34 	if (temp == scontrol->led_ctl.led_value)
35 		return;
36 
37 	scontrol->led_ctl.led_value = temp;
38 
39 #if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
40 	if (!scontrol->led_ctl.direction)
41 		ledtrig_audio_set(LED_AUDIO_MUTE, temp ? LED_OFF : LED_ON);
42 	else
43 		ledtrig_audio_set(LED_AUDIO_MICMUTE, temp ? LED_OFF : LED_ON);
44 #endif
45 }
46 
47 static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
48 {
49 	if (value >= size)
50 		return volume_map[size - 1];
51 
52 	return volume_map[value];
53 }
54 
55 static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
56 {
57 	int i;
58 
59 	for (i = 0; i < size; i++) {
60 		if (volume_map[i] >= value)
61 			return i;
62 	}
63 
64 	return i - 1;
65 }
66 
67 int snd_sof_volume_get(struct snd_kcontrol *kcontrol,
68 		       struct snd_ctl_elem_value *ucontrol)
69 {
70 	struct soc_mixer_control *sm =
71 		(struct soc_mixer_control *)kcontrol->private_value;
72 	struct snd_sof_control *scontrol = sm->dobj.private;
73 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
74 	unsigned int i, channels = scontrol->num_channels;
75 
76 	/* read back each channel */
77 	for (i = 0; i < channels; i++)
78 		ucontrol->value.integer.value[i] =
79 			ipc_to_mixer(cdata->chanv[i].value,
80 				     scontrol->volume_table, sm->max + 1);
81 
82 	return 0;
83 }
84 
85 int snd_sof_volume_put(struct snd_kcontrol *kcontrol,
86 		       struct snd_ctl_elem_value *ucontrol)
87 {
88 	struct soc_mixer_control *sm =
89 		(struct soc_mixer_control *)kcontrol->private_value;
90 	struct snd_sof_control *scontrol = sm->dobj.private;
91 	struct snd_sof_dev *sdev = scontrol->sdev;
92 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
93 	unsigned int i, channels = scontrol->num_channels;
94 	bool change = false;
95 	u32 value;
96 
97 	/* update each channel */
98 	for (i = 0; i < channels; i++) {
99 		value = mixer_to_ipc(ucontrol->value.integer.value[i],
100 				     scontrol->volume_table, sm->max + 1);
101 		change = change || (value != cdata->chanv[i].value);
102 		cdata->chanv[i].channel = i;
103 		cdata->chanv[i].value = value;
104 	}
105 
106 	/* notify DSP of mixer updates */
107 	if (pm_runtime_active(sdev->dev))
108 		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
109 					      SOF_IPC_COMP_SET_VALUE,
110 					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
111 					      SOF_CTRL_CMD_VOLUME,
112 					      true);
113 	return change;
114 }
115 
116 int snd_sof_switch_get(struct snd_kcontrol *kcontrol,
117 		       struct snd_ctl_elem_value *ucontrol)
118 {
119 	struct soc_mixer_control *sm =
120 		(struct soc_mixer_control *)kcontrol->private_value;
121 	struct snd_sof_control *scontrol = sm->dobj.private;
122 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
123 	unsigned int i, channels = scontrol->num_channels;
124 
125 	/* read back each channel */
126 	for (i = 0; i < channels; i++)
127 		ucontrol->value.integer.value[i] = cdata->chanv[i].value;
128 
129 	return 0;
130 }
131 
132 int snd_sof_switch_put(struct snd_kcontrol *kcontrol,
133 		       struct snd_ctl_elem_value *ucontrol)
134 {
135 	struct soc_mixer_control *sm =
136 		(struct soc_mixer_control *)kcontrol->private_value;
137 	struct snd_sof_control *scontrol = sm->dobj.private;
138 	struct snd_sof_dev *sdev = scontrol->sdev;
139 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
140 	unsigned int i, channels = scontrol->num_channels;
141 	bool change = false;
142 	u32 value;
143 
144 	/* update each channel */
145 	for (i = 0; i < channels; i++) {
146 		value = ucontrol->value.integer.value[i];
147 		change = change || (value != cdata->chanv[i].value);
148 		cdata->chanv[i].channel = i;
149 		cdata->chanv[i].value = value;
150 	}
151 
152 	if (scontrol->led_ctl.use_led)
153 		update_mute_led(scontrol, kcontrol, ucontrol);
154 
155 	/* notify DSP of mixer updates */
156 	if (pm_runtime_active(sdev->dev))
157 		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
158 					      SOF_IPC_COMP_SET_VALUE,
159 					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
160 					      SOF_CTRL_CMD_SWITCH,
161 					      true);
162 
163 	return change;
164 }
165 
166 int snd_sof_enum_get(struct snd_kcontrol *kcontrol,
167 		     struct snd_ctl_elem_value *ucontrol)
168 {
169 	struct soc_enum *se =
170 		(struct soc_enum *)kcontrol->private_value;
171 	struct snd_sof_control *scontrol = se->dobj.private;
172 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
173 	unsigned int i, channels = scontrol->num_channels;
174 
175 	/* read back each channel */
176 	for (i = 0; i < channels; i++)
177 		ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
178 
179 	return 0;
180 }
181 
182 int snd_sof_enum_put(struct snd_kcontrol *kcontrol,
183 		     struct snd_ctl_elem_value *ucontrol)
184 {
185 	struct soc_enum *se =
186 		(struct soc_enum *)kcontrol->private_value;
187 	struct snd_sof_control *scontrol = se->dobj.private;
188 	struct snd_sof_dev *sdev = scontrol->sdev;
189 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
190 	unsigned int i, channels = scontrol->num_channels;
191 	bool change = false;
192 	u32 value;
193 
194 	/* update each channel */
195 	for (i = 0; i < channels; i++) {
196 		value = ucontrol->value.enumerated.item[i];
197 		change = change || (value != cdata->chanv[i].value);
198 		cdata->chanv[i].channel = i;
199 		cdata->chanv[i].value = value;
200 	}
201 
202 	/* notify DSP of enum updates */
203 	if (pm_runtime_active(sdev->dev))
204 		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
205 					      SOF_IPC_COMP_SET_VALUE,
206 					      SOF_CTRL_TYPE_VALUE_CHAN_GET,
207 					      SOF_CTRL_CMD_ENUM,
208 					      true);
209 
210 	return change;
211 }
212 
213 int snd_sof_bytes_get(struct snd_kcontrol *kcontrol,
214 		      struct snd_ctl_elem_value *ucontrol)
215 {
216 	struct soc_bytes_ext *be =
217 		(struct soc_bytes_ext *)kcontrol->private_value;
218 	struct snd_sof_control *scontrol = be->dobj.private;
219 	struct snd_sof_dev *sdev = scontrol->sdev;
220 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
221 	struct sof_abi_hdr *data = cdata->data;
222 	size_t size;
223 	int ret = 0;
224 
225 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
226 		dev_err_ratelimited(sdev->dev,
227 				    "error: data max %d exceeds ucontrol data array size\n",
228 				    be->max);
229 		return -EINVAL;
230 	}
231 
232 	size = data->size + sizeof(*data);
233 	if (size > be->max) {
234 		dev_err_ratelimited(sdev->dev,
235 				    "error: DSP sent %zu bytes max is %d\n",
236 				    size, be->max);
237 		ret = -EINVAL;
238 		goto out;
239 	}
240 
241 	/* copy back to kcontrol */
242 	memcpy(ucontrol->value.bytes.data, data, size);
243 
244 out:
245 	return ret;
246 }
247 
248 int 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_sof_dev *sdev = scontrol->sdev;
255 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
256 	struct sof_abi_hdr *data = cdata->data;
257 	size_t size = data->size + sizeof(*data);
258 
259 	if (be->max > sizeof(ucontrol->value.bytes.data)) {
260 		dev_err_ratelimited(sdev->dev,
261 				    "error: data max %d exceeds ucontrol data array size\n",
262 				    be->max);
263 		return -EINVAL;
264 	}
265 
266 	if (size > be->max) {
267 		dev_err_ratelimited(sdev->dev,
268 				    "error: size too big %zu bytes max is %d\n",
269 				    size, be->max);
270 		return -EINVAL;
271 	}
272 
273 	/* copy from kcontrol */
274 	memcpy(data, ucontrol->value.bytes.data, size);
275 
276 	/* notify DSP of byte control updates */
277 	if (pm_runtime_active(sdev->dev))
278 		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
279 					      SOF_IPC_COMP_SET_DATA,
280 					      SOF_CTRL_TYPE_DATA_SET,
281 					      scontrol->cmd,
282 					      true);
283 
284 	return 0;
285 }
286 
287 int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol,
288 			  const unsigned int __user *binary_data,
289 			  unsigned int size)
290 {
291 	struct soc_bytes_ext *be =
292 		(struct soc_bytes_ext *)kcontrol->private_value;
293 	struct snd_sof_control *scontrol = be->dobj.private;
294 	struct snd_sof_dev *sdev = scontrol->sdev;
295 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
296 	struct snd_ctl_tlv header;
297 	const struct snd_ctl_tlv __user *tlvd =
298 		(const struct snd_ctl_tlv __user *)binary_data;
299 
300 	/*
301 	 * The beginning of bytes data contains a header from where
302 	 * the length (as bytes) is needed to know the correct copy
303 	 * length of data from tlvd->tlv.
304 	 */
305 	if (copy_from_user(&header, tlvd, sizeof(const struct snd_ctl_tlv)))
306 		return -EFAULT;
307 
308 	/* be->max is coming from topology */
309 	if (header.length > be->max) {
310 		dev_err_ratelimited(sdev->dev, "error: Bytes data size %d exceeds max %d.\n",
311 				    header.length, be->max);
312 		return -EINVAL;
313 	}
314 
315 	/* Check that header id matches the command */
316 	if (header.numid != scontrol->cmd) {
317 		dev_err_ratelimited(sdev->dev,
318 				    "error: incorrect numid %d\n",
319 				    header.numid);
320 		return -EINVAL;
321 	}
322 
323 	if (copy_from_user(cdata->data, tlvd->tlv, header.length))
324 		return -EFAULT;
325 
326 	if (cdata->data->magic != SOF_ABI_MAGIC) {
327 		dev_err_ratelimited(sdev->dev,
328 				    "error: Wrong ABI magic 0x%08x.\n",
329 				    cdata->data->magic);
330 		return -EINVAL;
331 	}
332 
333 	if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
334 		dev_err_ratelimited(sdev->dev, "error: Incompatible ABI version 0x%08x.\n",
335 				    cdata->data->abi);
336 		return -EINVAL;
337 	}
338 
339 	if (cdata->data->size + sizeof(const struct sof_abi_hdr) > be->max) {
340 		dev_err_ratelimited(sdev->dev, "error: Mismatch in ABI data size (truncated?).\n");
341 		return -EINVAL;
342 	}
343 
344 	/* notify DSP of byte control updates */
345 	if (pm_runtime_active(sdev->dev))
346 		snd_sof_ipc_set_get_comp_data(sdev->ipc, scontrol,
347 					      SOF_IPC_COMP_SET_DATA,
348 					      SOF_CTRL_TYPE_DATA_SET,
349 					      scontrol->cmd,
350 					      true);
351 
352 	return 0;
353 }
354 
355 int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol,
356 			  unsigned int __user *binary_data,
357 			  unsigned int size)
358 {
359 	struct soc_bytes_ext *be =
360 		(struct soc_bytes_ext *)kcontrol->private_value;
361 	struct snd_sof_control *scontrol = be->dobj.private;
362 	struct snd_sof_dev *sdev = scontrol->sdev;
363 	struct sof_ipc_ctrl_data *cdata = scontrol->control_data;
364 	struct snd_ctl_tlv header;
365 	struct snd_ctl_tlv __user *tlvd =
366 		(struct snd_ctl_tlv __user *)binary_data;
367 	int data_size;
368 	int ret = 0;
369 
370 	/*
371 	 * Decrement the limit by ext bytes header size to
372 	 * ensure the user space buffer is not exceeded.
373 	 */
374 	size -= sizeof(const struct snd_ctl_tlv);
375 
376 	/* set the ABI header values */
377 	cdata->data->magic = SOF_ABI_MAGIC;
378 	cdata->data->abi = SOF_ABI_VERSION;
379 
380 	/* Prevent read of other kernel data or possibly corrupt response */
381 	data_size = cdata->data->size + sizeof(const struct sof_abi_hdr);
382 
383 	/* check data size doesn't exceed max coming from topology */
384 	if (data_size > be->max) {
385 		dev_err_ratelimited(sdev->dev, "error: user data size %d exceeds max size %d.\n",
386 				    data_size, be->max);
387 		ret = -EINVAL;
388 		goto out;
389 	}
390 
391 	header.numid = scontrol->cmd;
392 	header.length = data_size;
393 	if (copy_to_user(tlvd, &header, sizeof(const struct snd_ctl_tlv))) {
394 		ret = -EFAULT;
395 		goto out;
396 	}
397 
398 	if (copy_to_user(tlvd->tlv, cdata->data, data_size))
399 		ret = -EFAULT;
400 
401 out:
402 	return ret;
403 }
404