xref: /linux/sound/soc/sof/ipc3-control.c (revision c5e90e8844692deb7bbcd029e8b92b3a20441903)
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) 2021 Intel Corporation
7 //
8 //
9 
10 #include "sof-priv.h"
11 #include "sof-audio.h"
12 #include "ipc3-priv.h"
13 
14 /* IPC set()/get() for kcontrols. */
15 static int sof_ipc3_set_get_kcontrol_data(struct snd_sof_control *scontrol,
16 					  bool set, bool lock)
17 {
18 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp);
19 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
20 	const struct sof_ipc_ops *iops = sdev->ipc->ops;
21 	enum sof_ipc_ctrl_type ctrl_type;
22 	struct snd_sof_widget *swidget;
23 	bool widget_found = false;
24 	u32 ipc_cmd, msg_bytes;
25 	int ret = 0;
26 
27 	list_for_each_entry(swidget, &sdev->widget_list, list) {
28 		if (swidget->comp_id == scontrol->comp_id) {
29 			widget_found = true;
30 			break;
31 		}
32 	}
33 
34 	if (!widget_found) {
35 		dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__,
36 			scontrol->comp_id);
37 		return -EINVAL;
38 	}
39 
40 	if (lock)
41 		mutex_lock(&swidget->setup_mutex);
42 	else
43 		lockdep_assert_held(&swidget->setup_mutex);
44 
45 	/*
46 	 * Volatile controls should always be part of static pipelines and the
47 	 * widget use_count would always be > 0 in this case. For the others,
48 	 * just return the cached value if the widget is not set up.
49 	 */
50 	if (!swidget->use_count)
51 		goto unlock;
52 
53 	/*
54 	 * Select the IPC cmd and the ctrl_type based on the ctrl_cmd and the
55 	 * direction
56 	 * Note: SOF_CTRL_TYPE_VALUE_COMP_* is not used and supported currently
57 	 *	 for ctrl_type
58 	 */
59 	if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
60 		ipc_cmd = set ? SOF_IPC_COMP_SET_DATA : SOF_IPC_COMP_GET_DATA;
61 		ctrl_type = set ? SOF_CTRL_TYPE_DATA_SET : SOF_CTRL_TYPE_DATA_GET;
62 	} else {
63 		ipc_cmd = set ? SOF_IPC_COMP_SET_VALUE : SOF_IPC_COMP_GET_VALUE;
64 		ctrl_type = set ? SOF_CTRL_TYPE_VALUE_CHAN_SET : SOF_CTRL_TYPE_VALUE_CHAN_GET;
65 	}
66 
67 	cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd;
68 	cdata->type = ctrl_type;
69 	cdata->comp_id = scontrol->comp_id;
70 	cdata->msg_index = 0;
71 
72 	/* calculate header and data size */
73 	switch (cdata->type) {
74 	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
75 	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
76 		cdata->num_elems = scontrol->num_channels;
77 
78 		msg_bytes = scontrol->num_channels *
79 			    sizeof(struct sof_ipc_ctrl_value_chan);
80 		msg_bytes += sizeof(struct sof_ipc_ctrl_data);
81 		break;
82 	case SOF_CTRL_TYPE_DATA_GET:
83 	case SOF_CTRL_TYPE_DATA_SET:
84 		cdata->num_elems = cdata->data->size;
85 
86 		msg_bytes = cdata->data->size;
87 		msg_bytes += sizeof(struct sof_ipc_ctrl_data) +
88 			     sizeof(struct sof_abi_hdr);
89 		break;
90 	default:
91 		ret = -EINVAL;
92 		goto unlock;
93 	}
94 
95 	cdata->rhdr.hdr.size = msg_bytes;
96 	cdata->elems_remaining = 0;
97 
98 	ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
99 	if (!set)
100 		goto unlock;
101 
102 	/* It is a set-data operation, and we have a backup that we can restore */
103 	if (ret < 0) {
104 		if (!scontrol->old_ipc_control_data)
105 			goto unlock;
106 		/*
107 		 * Current ipc_control_data is not valid, we use the last known good
108 		 * configuration
109 		 */
110 		memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data,
111 		       scontrol->max_size);
112 		kfree(scontrol->old_ipc_control_data);
113 		scontrol->old_ipc_control_data = NULL;
114 		/* Send the last known good configuration to firmware */
115 		ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
116 		if (ret < 0)
117 			goto unlock;
118 	}
119 
120 unlock:
121 	if (lock)
122 		mutex_unlock(&swidget->setup_mutex);
123 
124 	return ret;
125 }
126 
127 static void sof_ipc3_refresh_control(struct snd_sof_control *scontrol)
128 {
129 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
130 	struct snd_soc_component *scomp = scontrol->scomp;
131 	int ret;
132 
133 	if (!scontrol->comp_data_dirty)
134 		return;
135 
136 	if (!pm_runtime_active(scomp->dev))
137 		return;
138 
139 	/* set the ABI header values */
140 	cdata->data->magic = SOF_ABI_MAGIC;
141 	cdata->data->abi = SOF_ABI_VERSION;
142 
143 	/* refresh the component data from DSP */
144 	scontrol->comp_data_dirty = false;
145 	ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true);
146 	if (ret < 0) {
147 		dev_err(scomp->dev, "Failed to get control data: %d\n", ret);
148 
149 		/* Set the flag to re-try next time to get the data */
150 		scontrol->comp_data_dirty = true;
151 	}
152 }
153 
154 static int sof_ipc3_volume_get(struct snd_sof_control *scontrol,
155 			       struct snd_ctl_elem_value *ucontrol)
156 {
157 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
158 	unsigned int channels = scontrol->num_channels;
159 	unsigned int i;
160 
161 	sof_ipc3_refresh_control(scontrol);
162 
163 	/* read back each channel */
164 	for (i = 0; i < channels; i++)
165 		ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value,
166 								scontrol->volume_table,
167 								scontrol->max + 1);
168 
169 	return 0;
170 }
171 
172 static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol,
173 				struct snd_ctl_elem_value *ucontrol)
174 {
175 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
176 	struct snd_soc_component *scomp = scontrol->scomp;
177 	unsigned int channels = scontrol->num_channels;
178 	unsigned int i;
179 	bool change = false;
180 
181 	/* update each channel */
182 	for (i = 0; i < channels; i++) {
183 		u32 value = mixer_to_ipc(ucontrol->value.integer.value[i],
184 					 scontrol->volume_table, scontrol->max + 1);
185 
186 		change = change || (value != cdata->chanv[i].value);
187 		cdata->chanv[i].channel = i;
188 		cdata->chanv[i].value = value;
189 	}
190 
191 	/* notify DSP of mixer updates */
192 	if (pm_runtime_active(scomp->dev)) {
193 		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
194 
195 		if (ret < 0) {
196 			dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
197 				scontrol->name);
198 			return false;
199 		}
200 	}
201 
202 	return change;
203 }
204 
205 static int sof_ipc3_switch_get(struct snd_sof_control *scontrol,
206 			       struct snd_ctl_elem_value *ucontrol)
207 {
208 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
209 	unsigned int channels = scontrol->num_channels;
210 	unsigned int i;
211 
212 	sof_ipc3_refresh_control(scontrol);
213 
214 	/* read back each channel */
215 	for (i = 0; i < channels; i++)
216 		ucontrol->value.integer.value[i] = cdata->chanv[i].value;
217 
218 	return 0;
219 }
220 
221 static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol,
222 				struct snd_ctl_elem_value *ucontrol)
223 {
224 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
225 	struct snd_soc_component *scomp = scontrol->scomp;
226 	unsigned int channels = scontrol->num_channels;
227 	unsigned int i;
228 	bool change = false;
229 	u32 value;
230 
231 	/* update each channel */
232 	for (i = 0; i < channels; i++) {
233 		value = ucontrol->value.integer.value[i];
234 		change = change || (value != cdata->chanv[i].value);
235 		cdata->chanv[i].channel = i;
236 		cdata->chanv[i].value = value;
237 	}
238 
239 	/* notify DSP of mixer updates */
240 	if (pm_runtime_active(scomp->dev)) {
241 		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
242 
243 		if (ret < 0) {
244 			dev_err(scomp->dev, "Failed to set mixer updates for %s\n",
245 				scontrol->name);
246 			return false;
247 		}
248 	}
249 
250 	return change;
251 }
252 
253 static int sof_ipc3_enum_get(struct snd_sof_control *scontrol,
254 			     struct snd_ctl_elem_value *ucontrol)
255 {
256 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
257 	unsigned int channels = scontrol->num_channels;
258 	unsigned int i;
259 
260 	sof_ipc3_refresh_control(scontrol);
261 
262 	/* read back each channel */
263 	for (i = 0; i < channels; i++)
264 		ucontrol->value.enumerated.item[i] = cdata->chanv[i].value;
265 
266 	return 0;
267 }
268 
269 static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol,
270 			      struct snd_ctl_elem_value *ucontrol)
271 {
272 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
273 	struct snd_soc_component *scomp = scontrol->scomp;
274 	unsigned int channels = scontrol->num_channels;
275 	unsigned int i;
276 	bool change = false;
277 	u32 value;
278 
279 	/* update each channel */
280 	for (i = 0; i < channels; i++) {
281 		value = ucontrol->value.enumerated.item[i];
282 		change = change || (value != cdata->chanv[i].value);
283 		cdata->chanv[i].channel = i;
284 		cdata->chanv[i].value = value;
285 	}
286 
287 	/* notify DSP of enum updates */
288 	if (pm_runtime_active(scomp->dev)) {
289 		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
290 
291 		if (ret < 0) {
292 			dev_err(scomp->dev, "Failed to set enum updates for %s\n",
293 				scontrol->name);
294 			return false;
295 		}
296 	}
297 
298 	return change;
299 }
300 
301 static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol,
302 			      struct snd_ctl_elem_value *ucontrol)
303 {
304 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
305 	struct snd_soc_component *scomp = scontrol->scomp;
306 	struct sof_abi_hdr *data = cdata->data;
307 	size_t size;
308 
309 	sof_ipc3_refresh_control(scontrol);
310 
311 	if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
312 		dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
313 				    scontrol->max_size);
314 		return -EINVAL;
315 	}
316 
317 	/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
318 	if (data->size > scontrol->max_size - sizeof(*cdata) -
319 				    sizeof(*data)) {
320 		dev_err_ratelimited(scomp->dev,
321 				    "%u bytes of control data is invalid, max is %zu\n",
322 				    data->size,
323 				    scontrol->max_size - sizeof(*cdata) -
324 				    sizeof(*data));
325 		return -EINVAL;
326 	}
327 
328 	size = data->size + sizeof(*data);
329 
330 	/* copy back to kcontrol */
331 	memcpy(ucontrol->value.bytes.data, data, size);
332 
333 	return 0;
334 }
335 
336 static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
337 			      struct snd_ctl_elem_value *ucontrol)
338 {
339 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
340 	struct snd_soc_component *scomp = scontrol->scomp;
341 	struct sof_abi_hdr *data = cdata->data;
342 	const struct sof_abi_hdr *new_hdr =
343 		(const struct sof_abi_hdr *)ucontrol->value.bytes.data;
344 	size_t size;
345 
346 	if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
347 		dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n",
348 				    scontrol->max_size);
349 		return -EINVAL;
350 	}
351 
352 	/* Validate the new data's size, not the old one */
353 	if (new_hdr->size > scontrol->max_size - sizeof(*cdata) -
354 				    sizeof(*new_hdr)) {
355 		dev_err_ratelimited(scomp->dev,
356 				    "data size too big %u bytes max is %zu\n",
357 				    new_hdr->size,
358 				    scontrol->max_size - sizeof(*cdata) -
359 				    sizeof(*new_hdr));
360 		return -EINVAL;
361 	}
362 
363 	size = new_hdr->size + sizeof(*new_hdr);
364 
365 	/* copy from kcontrol */
366 	memcpy(data, ucontrol->value.bytes.data, size);
367 
368 	/* notify DSP of byte control updates */
369 	if (pm_runtime_active(scomp->dev))
370 		return sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
371 
372 	return 0;
373 }
374 
375 static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
376 				  const unsigned int __user *binary_data,
377 				  unsigned int size)
378 {
379 	const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data;
380 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
381 	struct snd_soc_component *scomp = scontrol->scomp;
382 	struct snd_ctl_tlv header;
383 	int ret = -EINVAL;
384 
385 	/*
386 	 * The beginning of bytes data contains a header from where
387 	 * the length (as bytes) is needed to know the correct copy
388 	 * length of data from tlvd->tlv.
389 	 */
390 	if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv)))
391 		return -EFAULT;
392 
393 	/* make sure TLV info is consistent */
394 	if (header.length + sizeof(struct snd_ctl_tlv) > size) {
395 		dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n",
396 				    header.length, sizeof(struct snd_ctl_tlv), size);
397 		return -EINVAL;
398 	}
399 
400 	/* be->max is coming from topology */
401 	if (header.length > scontrol->max_size - sizeof(*cdata)) {
402 		dev_err_ratelimited(scomp->dev, "Bytes data size %u exceeds max %zu\n",
403 				    header.length, scontrol->max_size - sizeof(*cdata));
404 		return -EINVAL;
405 	}
406 
407 	/* Ensure the data is large enough to contain the ABI header */
408 	if (header.length < sizeof(struct sof_abi_hdr)) {
409 		dev_err_ratelimited(scomp->dev,
410 				    "Bytes data size %u less than ABI header %zu\n",
411 				    header.length, sizeof(struct sof_abi_hdr));
412 		return -EINVAL;
413 	}
414 
415 	/* Check that header id matches the command */
416 	if (header.numid != cdata->cmd) {
417 		dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n",
418 				    header.numid);
419 		return -EINVAL;
420 	}
421 
422 	if (!scontrol->old_ipc_control_data) {
423 		/* Create a backup of the current, valid bytes control */
424 		scontrol->old_ipc_control_data = kmemdup(scontrol->ipc_control_data,
425 							 scontrol->max_size, GFP_KERNEL);
426 		if (!scontrol->old_ipc_control_data)
427 			return -ENOMEM;
428 	}
429 
430 	if (copy_from_user(cdata->data, tlvd->tlv, header.length)) {
431 		ret = -EFAULT;
432 		goto err_restore;
433 	}
434 
435 	if (cdata->data->magic != SOF_ABI_MAGIC) {
436 		dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic);
437 		goto err_restore;
438 	}
439 
440 	if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) {
441 		dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n",
442 				    cdata->data->abi);
443 		goto err_restore;
444 	}
445 
446 	/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
447 	if (cdata->data->size > scontrol->max_size - sizeof(*cdata) - sizeof(struct sof_abi_hdr)) {
448 		dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n");
449 		goto err_restore;
450 	}
451 
452 	/* notify DSP of byte control updates */
453 	if (pm_runtime_active(scomp->dev)) {
454 		/* Actually send the data to the DSP; this is an opportunity to validate the data */
455 		return sof_ipc3_set_get_kcontrol_data(scontrol, true, true);
456 	}
457 
458 	return 0;
459 
460 err_restore:
461 	/* If we have an issue, we restore the old, valid bytes control data */
462 	if (scontrol->old_ipc_control_data) {
463 		memcpy(cdata, scontrol->old_ipc_control_data, scontrol->max_size);
464 		kfree(scontrol->old_ipc_control_data);
465 		scontrol->old_ipc_control_data = NULL;
466 	}
467 	return ret;
468 }
469 
470 static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
471 				   const unsigned int __user *binary_data,
472 				   unsigned int size, bool from_dsp)
473 {
474 	struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data;
475 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
476 	struct snd_soc_component *scomp = scontrol->scomp;
477 	struct snd_ctl_tlv header;
478 	size_t data_size;
479 
480 	/*
481 	 * Decrement the limit by ext bytes header size to
482 	 * ensure the user space buffer is not exceeded.
483 	 */
484 	if (size < sizeof(struct snd_ctl_tlv))
485 		return -ENOSPC;
486 
487 	size -= sizeof(struct snd_ctl_tlv);
488 
489 	/* set the ABI header values */
490 	cdata->data->magic = SOF_ABI_MAGIC;
491 	cdata->data->abi = SOF_ABI_VERSION;
492 
493 	/* get all the component data from DSP */
494 	if (from_dsp) {
495 		int ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true);
496 
497 		if (ret < 0)
498 			return ret;
499 	}
500 
501 	/* check data size doesn't exceed max coming from topology */
502 	if (cdata->data->size > scontrol->max_size - sizeof(*cdata) -
503 				sizeof(struct sof_abi_hdr)) {
504 		dev_err_ratelimited(scomp->dev,
505 				    "User data size %u exceeds max size %zu\n",
506 				    cdata->data->size,
507 				    scontrol->max_size - sizeof(*cdata) -
508 				    sizeof(struct sof_abi_hdr));
509 		return -EINVAL;
510 	}
511 
512 	data_size = cdata->data->size + sizeof(struct sof_abi_hdr);
513 
514 	/* make sure we don't exceed size provided by user space for data */
515 	if (data_size > size)
516 		return -ENOSPC;
517 
518 	header.numid = cdata->cmd;
519 	header.length = data_size;
520 	if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
521 		return -EFAULT;
522 
523 	if (copy_to_user(tlvd->tlv, cdata->data, data_size))
524 		return -EFAULT;
525 
526 	return 0;
527 }
528 
529 static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
530 				  const unsigned int __user *binary_data, unsigned int size)
531 {
532 	return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, false);
533 }
534 
535 static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol,
536 					   const unsigned int __user *binary_data,
537 					   unsigned int size)
538 {
539 	return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, true);
540 }
541 
542 static void snd_sof_update_control(struct snd_sof_control *scontrol,
543 				   struct sof_ipc_ctrl_data *cdata)
544 {
545 	struct snd_soc_component *scomp = scontrol->scomp;
546 	struct sof_ipc_ctrl_data *local_cdata;
547 	int i;
548 
549 	local_cdata = scontrol->ipc_control_data;
550 
551 	if (cdata->cmd == SOF_CTRL_CMD_BINARY) {
552 		if (cdata->num_elems != local_cdata->data->size) {
553 			dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n",
554 				cdata->num_elems, local_cdata->data->size);
555 			return;
556 		}
557 
558 		/* Verify the size fits within the allocation */
559 		if (cdata->num_elems > scontrol->max_size - sizeof(*local_cdata) -
560 					sizeof(*local_cdata->data)) {
561 			dev_err(scomp->dev,
562 				"cdata binary size %u exceeds buffer\n",
563 				cdata->num_elems);
564 			return;
565 		}
566 
567 		/* copy the new binary data */
568 		memcpy(local_cdata->data, cdata->data, cdata->num_elems);
569 	} else if (cdata->num_elems != scontrol->num_channels) {
570 		dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n",
571 			cdata->num_elems, scontrol->num_channels);
572 	} else {
573 		/* copy the new values */
574 		for (i = 0; i < cdata->num_elems; i++)
575 			local_cdata->chanv[i].value = cdata->chanv[i].value;
576 	}
577 }
578 
579 static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_message)
580 {
581 	struct sof_ipc_ctrl_data *cdata = ipc_control_message;
582 	struct snd_soc_dapm_widget *widget;
583 	struct snd_sof_control *scontrol;
584 	struct snd_sof_widget *swidget;
585 	struct snd_kcontrol *kc = NULL;
586 	struct soc_mixer_control *sm;
587 	struct soc_bytes_ext *be;
588 	size_t expected_size;
589 	struct soc_enum *se;
590 	bool found = false;
591 	int i, type;
592 
593 	if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET ||
594 	    cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) {
595 		dev_err(sdev->dev, "Component data is not supported in control notification\n");
596 		return;
597 	}
598 
599 	/* Find the swidget first */
600 	list_for_each_entry(swidget, &sdev->widget_list, list) {
601 		if (swidget->comp_id == cdata->comp_id) {
602 			found = true;
603 			break;
604 		}
605 	}
606 
607 	if (!found)
608 		return;
609 
610 	/* Translate SOF cmd to TPLG type */
611 	switch (cdata->cmd) {
612 	case SOF_CTRL_CMD_VOLUME:
613 	case SOF_CTRL_CMD_SWITCH:
614 		type = SND_SOC_TPLG_TYPE_MIXER;
615 		break;
616 	case SOF_CTRL_CMD_BINARY:
617 		type = SND_SOC_TPLG_TYPE_BYTES;
618 		break;
619 	case SOF_CTRL_CMD_ENUM:
620 		type = SND_SOC_TPLG_TYPE_ENUM;
621 		break;
622 	default:
623 		dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__);
624 		return;
625 	}
626 
627 	widget = swidget->widget;
628 	for (i = 0; i < widget->num_kcontrols; i++) {
629 		/* skip non matching types or non matching indexes within type */
630 		if (widget->dobj.widget.kcontrol_type[i] == type &&
631 		    widget->kcontrol_news[i].index == cdata->index) {
632 			kc = widget->kcontrols[i];
633 			break;
634 		}
635 	}
636 
637 	if (!kc)
638 		return;
639 
640 	switch (cdata->cmd) {
641 	case SOF_CTRL_CMD_VOLUME:
642 	case SOF_CTRL_CMD_SWITCH:
643 		sm = (struct soc_mixer_control *)kc->private_value;
644 		scontrol = sm->dobj.private;
645 		break;
646 	case SOF_CTRL_CMD_BINARY:
647 		be = (struct soc_bytes_ext *)kc->private_value;
648 		scontrol = be->dobj.private;
649 		break;
650 	case SOF_CTRL_CMD_ENUM:
651 		se = (struct soc_enum *)kc->private_value;
652 		scontrol = se->dobj.private;
653 		break;
654 	default:
655 		return;
656 	}
657 
658 	switch (cdata->type) {
659 	case SOF_CTRL_TYPE_VALUE_CHAN_GET:
660 	case SOF_CTRL_TYPE_VALUE_CHAN_SET:
661 		if (check_mul_overflow((size_t)cdata->num_elems,
662 				       sizeof(struct sof_ipc_ctrl_value_chan),
663 				       &expected_size))
664 			return;
665 		if (check_add_overflow(expected_size,
666 				       sizeof(struct sof_ipc_ctrl_data),
667 				       &expected_size))
668 			return;
669 		break;
670 	case SOF_CTRL_TYPE_DATA_GET:
671 	case SOF_CTRL_TYPE_DATA_SET:
672 		if (check_add_overflow((size_t)cdata->num_elems,
673 				       sizeof(struct sof_abi_hdr),
674 				       &expected_size))
675 			return;
676 		if (check_add_overflow(expected_size,
677 				       sizeof(struct sof_ipc_ctrl_data),
678 				       &expected_size))
679 			return;
680 		break;
681 	default:
682 		return;
683 	}
684 
685 	if (cdata->rhdr.hdr.size != expected_size) {
686 		dev_err(sdev->dev, "Component notification size mismatch\n");
687 		return;
688 	}
689 
690 	if (cdata->num_elems)
691 		/*
692 		 * The message includes the updated value/data, update the
693 		 * control's local cache using the received notification
694 		 */
695 		snd_sof_update_control(scontrol, cdata);
696 	else
697 		/* Mark the scontrol that the value/data is changed in SOF */
698 		scontrol->comp_data_dirty = true;
699 
700 	snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0);
701 }
702 
703 static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
704 					  struct snd_sof_widget *swidget)
705 {
706 	struct snd_sof_control *scontrol;
707 	int ret;
708 
709 	/* set up all controls for the widget */
710 	list_for_each_entry(scontrol, &sdev->kcontrol_list, list)
711 		if (scontrol->comp_id == swidget->comp_id) {
712 			/* set kcontrol data in DSP */
713 			ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, false);
714 			if (ret < 0) {
715 				dev_err(sdev->dev,
716 					"kcontrol %d set up failed for widget %s\n",
717 					scontrol->comp_id, swidget->widget->name);
718 				return ret;
719 			}
720 
721 			/*
722 			 * Read back the data from the DSP for static widgets.
723 			 * This is particularly useful for binary kcontrols
724 			 * associated with static pipeline widgets to initialize
725 			 * the data size to match that in the DSP.
726 			 */
727 			if (swidget->dynamic_pipeline_widget)
728 				continue;
729 
730 			ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, false);
731 			if (ret < 0)
732 				dev_warn(sdev->dev,
733 					 "kcontrol %d read failed for widget %s\n",
734 					 scontrol->comp_id, swidget->widget->name);
735 		}
736 
737 	return 0;
738 }
739 
740 static int
741 sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size)
742 {
743 	int i;
744 
745 	/* init the volume table */
746 	scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
747 	if (!scontrol->volume_table)
748 		return -ENOMEM;
749 
750 	/* populate the volume table */
751 	for (i = 0; i < size ; i++)
752 		scontrol->volume_table[i] = vol_compute_gain(i, tlv);
753 
754 	return 0;
755 }
756 
757 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
758 	.volume_put = sof_ipc3_volume_put,
759 	.volume_get = sof_ipc3_volume_get,
760 	.switch_put = sof_ipc3_switch_put,
761 	.switch_get = sof_ipc3_switch_get,
762 	.enum_put = sof_ipc3_enum_put,
763 	.enum_get = sof_ipc3_enum_get,
764 	.bytes_put = sof_ipc3_bytes_put,
765 	.bytes_get = sof_ipc3_bytes_get,
766 	.bytes_ext_put = sof_ipc3_bytes_ext_put,
767 	.bytes_ext_get = sof_ipc3_bytes_ext_get,
768 	.bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
769 	.update = sof_ipc3_control_update,
770 	.widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
771 	.set_up_volume_table = sof_ipc3_set_up_volume_table,
772 };
773