Lines Matching +full:memcpy +full:- +full:channels
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
10 #include "sof-priv.h"
11 #include "sof-audio.h"
12 #include "ipc3-priv.h"
18 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp); in sof_ipc3_set_get_kcontrol_data()
19 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_set_get_kcontrol_data()
20 const struct sof_ipc_ops *iops = sdev->ipc->ops; in sof_ipc3_set_get_kcontrol_data()
27 list_for_each_entry(swidget, &sdev->widget_list, list) { in sof_ipc3_set_get_kcontrol_data()
28 if (swidget->comp_id == scontrol->comp_id) { in sof_ipc3_set_get_kcontrol_data()
35 dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__, in sof_ipc3_set_get_kcontrol_data()
36 scontrol->comp_id); in sof_ipc3_set_get_kcontrol_data()
37 return -EINVAL; in sof_ipc3_set_get_kcontrol_data()
41 mutex_lock(&swidget->setup_mutex); in sof_ipc3_set_get_kcontrol_data()
43 lockdep_assert_held(&swidget->setup_mutex); in sof_ipc3_set_get_kcontrol_data()
50 if (!swidget->use_count) in sof_ipc3_set_get_kcontrol_data()
59 if (cdata->cmd == SOF_CTRL_CMD_BINARY) { in sof_ipc3_set_get_kcontrol_data()
67 cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd; in sof_ipc3_set_get_kcontrol_data()
68 cdata->type = ctrl_type; in sof_ipc3_set_get_kcontrol_data()
69 cdata->comp_id = scontrol->comp_id; in sof_ipc3_set_get_kcontrol_data()
70 cdata->msg_index = 0; in sof_ipc3_set_get_kcontrol_data()
73 switch (cdata->type) { in sof_ipc3_set_get_kcontrol_data()
76 cdata->num_elems = scontrol->num_channels; in sof_ipc3_set_get_kcontrol_data()
78 msg_bytes = scontrol->num_channels * in sof_ipc3_set_get_kcontrol_data()
84 cdata->num_elems = cdata->data->size; in sof_ipc3_set_get_kcontrol_data()
86 msg_bytes = cdata->data->size; in sof_ipc3_set_get_kcontrol_data()
91 ret = -EINVAL; in sof_ipc3_set_get_kcontrol_data()
95 cdata->rhdr.hdr.size = msg_bytes; in sof_ipc3_set_get_kcontrol_data()
96 cdata->elems_remaining = 0; in sof_ipc3_set_get_kcontrol_data()
98 ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set); in sof_ipc3_set_get_kcontrol_data()
102 /* It is a set-data operation, and we have a backup that we can restore */ in sof_ipc3_set_get_kcontrol_data()
104 if (!scontrol->old_ipc_control_data) in sof_ipc3_set_get_kcontrol_data()
110 memcpy(scontrol->ipc_control_data, scontrol->old_ipc_control_data, in sof_ipc3_set_get_kcontrol_data()
111 scontrol->max_size); in sof_ipc3_set_get_kcontrol_data()
112 kfree(scontrol->old_ipc_control_data); in sof_ipc3_set_get_kcontrol_data()
113 scontrol->old_ipc_control_data = NULL; in sof_ipc3_set_get_kcontrol_data()
115 ret = iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set); in sof_ipc3_set_get_kcontrol_data()
122 mutex_unlock(&swidget->setup_mutex); in sof_ipc3_set_get_kcontrol_data()
129 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_refresh_control()
130 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_refresh_control()
133 if (!scontrol->comp_data_dirty) in sof_ipc3_refresh_control()
136 if (!pm_runtime_active(scomp->dev)) in sof_ipc3_refresh_control()
140 cdata->data->magic = SOF_ABI_MAGIC; in sof_ipc3_refresh_control()
141 cdata->data->abi = SOF_ABI_VERSION; in sof_ipc3_refresh_control()
144 scontrol->comp_data_dirty = false; in sof_ipc3_refresh_control()
147 dev_err(scomp->dev, "Failed to get control data: %d\n", ret); in sof_ipc3_refresh_control()
149 /* Set the flag to re-try next time to get the data */ in sof_ipc3_refresh_control()
150 scontrol->comp_data_dirty = true; in sof_ipc3_refresh_control()
157 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_volume_get()
158 unsigned int channels = scontrol->num_channels; in sof_ipc3_volume_get() local
164 for (i = 0; i < channels; i++) in sof_ipc3_volume_get()
165 ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value, in sof_ipc3_volume_get()
166 scontrol->volume_table, in sof_ipc3_volume_get()
167 scontrol->max + 1); in sof_ipc3_volume_get()
175 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_volume_put()
176 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_volume_put()
177 unsigned int channels = scontrol->num_channels; in sof_ipc3_volume_put() local
182 for (i = 0; i < channels; i++) { in sof_ipc3_volume_put()
183 u32 value = mixer_to_ipc(ucontrol->value.integer.value[i], in sof_ipc3_volume_put()
184 scontrol->volume_table, scontrol->max + 1); in sof_ipc3_volume_put()
186 change = change || (value != cdata->chanv[i].value); in sof_ipc3_volume_put()
187 cdata->chanv[i].channel = i; in sof_ipc3_volume_put()
188 cdata->chanv[i].value = value; in sof_ipc3_volume_put()
192 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_volume_put()
196 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", in sof_ipc3_volume_put()
197 scontrol->name); in sof_ipc3_volume_put()
208 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_switch_get()
209 unsigned int channels = scontrol->num_channels; in sof_ipc3_switch_get() local
215 for (i = 0; i < channels; i++) in sof_ipc3_switch_get()
216 ucontrol->value.integer.value[i] = cdata->chanv[i].value; in sof_ipc3_switch_get()
224 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_switch_put()
225 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_switch_put()
226 unsigned int channels = scontrol->num_channels; in sof_ipc3_switch_put() local
232 for (i = 0; i < channels; i++) { in sof_ipc3_switch_put()
233 value = ucontrol->value.integer.value[i]; in sof_ipc3_switch_put()
234 change = change || (value != cdata->chanv[i].value); in sof_ipc3_switch_put()
235 cdata->chanv[i].channel = i; in sof_ipc3_switch_put()
236 cdata->chanv[i].value = value; in sof_ipc3_switch_put()
240 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_switch_put()
244 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", in sof_ipc3_switch_put()
245 scontrol->name); in sof_ipc3_switch_put()
256 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_enum_get()
257 unsigned int channels = scontrol->num_channels; in sof_ipc3_enum_get() local
263 for (i = 0; i < channels; i++) in sof_ipc3_enum_get()
264 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; in sof_ipc3_enum_get()
272 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_enum_put()
273 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_enum_put()
274 unsigned int channels = scontrol->num_channels; in sof_ipc3_enum_put() local
280 for (i = 0; i < channels; i++) { in sof_ipc3_enum_put()
281 value = ucontrol->value.enumerated.item[i]; in sof_ipc3_enum_put()
282 change = change || (value != cdata->chanv[i].value); in sof_ipc3_enum_put()
283 cdata->chanv[i].channel = i; in sof_ipc3_enum_put()
284 cdata->chanv[i].value = value; in sof_ipc3_enum_put()
288 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_enum_put()
292 dev_err(scomp->dev, "Failed to set enum updates for %s\n", in sof_ipc3_enum_put()
293 scontrol->name); in sof_ipc3_enum_put()
304 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_get()
305 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_get()
306 struct sof_abi_hdr *data = cdata->data; in sof_ipc3_bytes_get()
311 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { in sof_ipc3_bytes_get()
312 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", in sof_ipc3_bytes_get()
313 scontrol->max_size); in sof_ipc3_bytes_get()
314 return -EINVAL; in sof_ipc3_bytes_get()
317 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_get()
318 if (data->size > scontrol->max_size - sizeof(*data)) { in sof_ipc3_bytes_get()
319 dev_err_ratelimited(scomp->dev, in sof_ipc3_bytes_get()
321 data->size, scontrol->max_size - sizeof(*data)); in sof_ipc3_bytes_get()
322 return -EINVAL; in sof_ipc3_bytes_get()
325 size = data->size + sizeof(*data); in sof_ipc3_bytes_get()
328 memcpy(ucontrol->value.bytes.data, data, size); in sof_ipc3_bytes_get()
336 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_put()
337 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_put()
338 struct sof_abi_hdr *data = cdata->data; in sof_ipc3_bytes_put()
341 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { in sof_ipc3_bytes_put()
342 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", in sof_ipc3_bytes_put()
343 scontrol->max_size); in sof_ipc3_bytes_put()
344 return -EINVAL; in sof_ipc3_bytes_put()
347 /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_put()
348 if (data->size > scontrol->max_size - sizeof(*data)) { in sof_ipc3_bytes_put()
349 dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", in sof_ipc3_bytes_put()
350 data->size, scontrol->max_size - sizeof(*data)); in sof_ipc3_bytes_put()
351 return -EINVAL; in sof_ipc3_bytes_put()
354 size = data->size + sizeof(*data); in sof_ipc3_bytes_put()
357 memcpy(data, ucontrol->value.bytes.data, size); in sof_ipc3_bytes_put()
360 if (pm_runtime_active(scomp->dev)) in sof_ipc3_bytes_put()
371 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_ext_put()
372 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_ext_put()
374 int ret = -EINVAL; in sof_ipc3_bytes_ext_put()
379 * length of data from tlvd->tlv. in sof_ipc3_bytes_ext_put()
382 return -EFAULT; in sof_ipc3_bytes_ext_put()
386 dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n", in sof_ipc3_bytes_ext_put()
388 return -EINVAL; in sof_ipc3_bytes_ext_put()
391 /* be->max is coming from topology */ in sof_ipc3_bytes_ext_put()
392 if (header.length > scontrol->max_size) { in sof_ipc3_bytes_ext_put()
393 dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n", in sof_ipc3_bytes_ext_put()
394 header.length, scontrol->max_size); in sof_ipc3_bytes_ext_put()
395 return -EINVAL; in sof_ipc3_bytes_ext_put()
399 if (header.numid != cdata->cmd) { in sof_ipc3_bytes_ext_put()
400 dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n", in sof_ipc3_bytes_ext_put()
402 return -EINVAL; in sof_ipc3_bytes_ext_put()
405 if (!scontrol->old_ipc_control_data) { in sof_ipc3_bytes_ext_put()
407 scontrol->old_ipc_control_data = kmemdup(scontrol->ipc_control_data, in sof_ipc3_bytes_ext_put()
408 scontrol->max_size, GFP_KERNEL); in sof_ipc3_bytes_ext_put()
409 if (!scontrol->old_ipc_control_data) in sof_ipc3_bytes_ext_put()
410 return -ENOMEM; in sof_ipc3_bytes_ext_put()
413 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) { in sof_ipc3_bytes_ext_put()
414 ret = -EFAULT; in sof_ipc3_bytes_ext_put()
418 if (cdata->data->magic != SOF_ABI_MAGIC) { in sof_ipc3_bytes_ext_put()
419 dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic); in sof_ipc3_bytes_ext_put()
423 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { in sof_ipc3_bytes_ext_put()
424 dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n", in sof_ipc3_bytes_ext_put()
425 cdata->data->abi); in sof_ipc3_bytes_ext_put()
429 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_ext_put()
430 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { in sof_ipc3_bytes_ext_put()
431 dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n"); in sof_ipc3_bytes_ext_put()
436 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_bytes_ext_put()
445 if (scontrol->old_ipc_control_data) { in sof_ipc3_bytes_ext_put()
446 memcpy(cdata->data, scontrol->old_ipc_control_data, scontrol->max_size); in sof_ipc3_bytes_ext_put()
447 kfree(scontrol->old_ipc_control_data); in sof_ipc3_bytes_ext_put()
448 scontrol->old_ipc_control_data = NULL; in sof_ipc3_bytes_ext_put()
458 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in _sof_ipc3_bytes_ext_get()
459 struct snd_soc_component *scomp = scontrol->scomp; in _sof_ipc3_bytes_ext_get()
468 return -ENOSPC; in _sof_ipc3_bytes_ext_get()
470 size -= sizeof(struct snd_ctl_tlv); in _sof_ipc3_bytes_ext_get()
473 cdata->data->magic = SOF_ABI_MAGIC; in _sof_ipc3_bytes_ext_get()
474 cdata->data->abi = SOF_ABI_VERSION; in _sof_ipc3_bytes_ext_get()
485 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { in _sof_ipc3_bytes_ext_get()
486 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", in _sof_ipc3_bytes_ext_get()
487 cdata->data->size, in _sof_ipc3_bytes_ext_get()
488 scontrol->max_size - sizeof(struct sof_abi_hdr)); in _sof_ipc3_bytes_ext_get()
489 return -EINVAL; in _sof_ipc3_bytes_ext_get()
492 data_size = cdata->data->size + sizeof(struct sof_abi_hdr); in _sof_ipc3_bytes_ext_get()
496 return -ENOSPC; in _sof_ipc3_bytes_ext_get()
498 header.numid = cdata->cmd; in _sof_ipc3_bytes_ext_get()
501 return -EFAULT; in _sof_ipc3_bytes_ext_get()
503 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) in _sof_ipc3_bytes_ext_get()
504 return -EFAULT; in _sof_ipc3_bytes_ext_get()
525 struct snd_soc_component *scomp = scontrol->scomp; in snd_sof_update_control()
529 local_cdata = scontrol->ipc_control_data; in snd_sof_update_control()
531 if (cdata->cmd == SOF_CTRL_CMD_BINARY) { in snd_sof_update_control()
532 if (cdata->num_elems != local_cdata->data->size) { in snd_sof_update_control()
533 dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n", in snd_sof_update_control()
534 cdata->num_elems, local_cdata->data->size); in snd_sof_update_control()
539 memcpy(local_cdata->data, cdata->data, cdata->num_elems); in snd_sof_update_control()
540 } else if (cdata->num_elems != scontrol->num_channels) { in snd_sof_update_control()
541 dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n", in snd_sof_update_control()
542 cdata->num_elems, scontrol->num_channels); in snd_sof_update_control()
545 for (i = 0; i < cdata->num_elems; i++) in snd_sof_update_control()
546 local_cdata->chanv[i].value = cdata->chanv[i].value; in snd_sof_update_control()
564 if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET || in sof_ipc3_control_update()
565 cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) { in sof_ipc3_control_update()
566 dev_err(sdev->dev, "Component data is not supported in control notification\n"); in sof_ipc3_control_update()
571 list_for_each_entry(swidget, &sdev->widget_list, list) { in sof_ipc3_control_update()
572 if (swidget->comp_id == cdata->comp_id) { in sof_ipc3_control_update()
582 switch (cdata->cmd) { in sof_ipc3_control_update()
594 dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__); in sof_ipc3_control_update()
598 widget = swidget->widget; in sof_ipc3_control_update()
599 for (i = 0; i < widget->num_kcontrols; i++) { in sof_ipc3_control_update()
601 if (widget->dobj.widget.kcontrol_type[i] == type && in sof_ipc3_control_update()
602 widget->kcontrol_news[i].index == cdata->index) { in sof_ipc3_control_update()
603 kc = widget->kcontrols[i]; in sof_ipc3_control_update()
611 switch (cdata->cmd) { in sof_ipc3_control_update()
614 sm = (struct soc_mixer_control *)kc->private_value; in sof_ipc3_control_update()
615 scontrol = sm->dobj.private; in sof_ipc3_control_update()
618 be = (struct soc_bytes_ext *)kc->private_value; in sof_ipc3_control_update()
619 scontrol = be->dobj.private; in sof_ipc3_control_update()
622 se = (struct soc_enum *)kc->private_value; in sof_ipc3_control_update()
623 scontrol = se->dobj.private; in sof_ipc3_control_update()
630 switch (cdata->type) { in sof_ipc3_control_update()
633 expected_size += cdata->num_elems * in sof_ipc3_control_update()
638 expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); in sof_ipc3_control_update()
644 if (cdata->rhdr.hdr.size != expected_size) { in sof_ipc3_control_update()
645 dev_err(sdev->dev, "Component notification size mismatch\n"); in sof_ipc3_control_update()
649 if (cdata->num_elems) in sof_ipc3_control_update()
657 scontrol->comp_data_dirty = true; in sof_ipc3_control_update()
659 snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); in sof_ipc3_control_update()
669 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) in sof_ipc3_widget_kcontrol_setup()
670 if (scontrol->comp_id == swidget->comp_id) { in sof_ipc3_widget_kcontrol_setup()
674 dev_err(sdev->dev, in sof_ipc3_widget_kcontrol_setup()
676 scontrol->comp_id, swidget->widget->name); in sof_ipc3_widget_kcontrol_setup()
686 if (swidget->dynamic_pipeline_widget) in sof_ipc3_widget_kcontrol_setup()
691 dev_warn(sdev->dev, in sof_ipc3_widget_kcontrol_setup()
693 scontrol->comp_id, swidget->widget->name); in sof_ipc3_widget_kcontrol_setup()
705 scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); in sof_ipc3_set_up_volume_table()
706 if (!scontrol->volume_table) in sof_ipc3_set_up_volume_table()
707 return -ENOMEM; in sof_ipc3_set_up_volume_table()
711 scontrol->volume_table[i] = vol_compute_gain(i, tlv); in sof_ipc3_set_up_volume_table()