Lines Matching +full:data +full:- +full:size

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"
17 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scontrol->scomp); in sof_ipc3_set_get_kcontrol_data()
18 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_set_get_kcontrol_data()
19 const struct sof_ipc_ops *iops = sdev->ipc->ops; in sof_ipc3_set_get_kcontrol_data()
25 list_for_each_entry(swidget, &sdev->widget_list, list) { in sof_ipc3_set_get_kcontrol_data()
26 if (swidget->comp_id == scontrol->comp_id) { in sof_ipc3_set_get_kcontrol_data()
33 dev_err(sdev->dev, "%s: can't find widget with id %d\n", __func__, in sof_ipc3_set_get_kcontrol_data()
34 scontrol->comp_id); in sof_ipc3_set_get_kcontrol_data()
35 return -EINVAL; in sof_ipc3_set_get_kcontrol_data()
43 if (!swidget->use_count) in sof_ipc3_set_get_kcontrol_data()
52 if (cdata->cmd == SOF_CTRL_CMD_BINARY) { in sof_ipc3_set_get_kcontrol_data()
60 cdata->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | ipc_cmd; in sof_ipc3_set_get_kcontrol_data()
61 cdata->type = ctrl_type; in sof_ipc3_set_get_kcontrol_data()
62 cdata->comp_id = scontrol->comp_id; in sof_ipc3_set_get_kcontrol_data()
63 cdata->msg_index = 0; in sof_ipc3_set_get_kcontrol_data()
65 /* calculate header and data size */ in sof_ipc3_set_get_kcontrol_data()
66 switch (cdata->type) { in sof_ipc3_set_get_kcontrol_data()
69 cdata->num_elems = scontrol->num_channels; in sof_ipc3_set_get_kcontrol_data()
71 msg_bytes = scontrol->num_channels * in sof_ipc3_set_get_kcontrol_data()
77 cdata->num_elems = cdata->data->size; in sof_ipc3_set_get_kcontrol_data()
79 msg_bytes = cdata->data->size; in sof_ipc3_set_get_kcontrol_data()
84 return -EINVAL; in sof_ipc3_set_get_kcontrol_data()
87 cdata->rhdr.hdr.size = msg_bytes; in sof_ipc3_set_get_kcontrol_data()
88 cdata->elems_remaining = 0; in sof_ipc3_set_get_kcontrol_data()
90 return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set); in sof_ipc3_set_get_kcontrol_data()
95 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in snd_sof_refresh_control()
96 struct snd_soc_component *scomp = scontrol->scomp; in snd_sof_refresh_control()
99 if (!scontrol->comp_data_dirty) in snd_sof_refresh_control()
102 if (!pm_runtime_active(scomp->dev)) in snd_sof_refresh_control()
106 cdata->data->magic = SOF_ABI_MAGIC; in snd_sof_refresh_control()
107 cdata->data->abi = SOF_ABI_VERSION; in snd_sof_refresh_control()
109 /* refresh the component data from DSP */ in snd_sof_refresh_control()
110 scontrol->comp_data_dirty = false; in snd_sof_refresh_control()
113 dev_err(scomp->dev, "Failed to get control data: %d\n", ret); in snd_sof_refresh_control()
115 /* Set the flag to re-try next time to get the data */ in snd_sof_refresh_control()
116 scontrol->comp_data_dirty = true; in snd_sof_refresh_control()
123 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_volume_get()
124 unsigned int channels = scontrol->num_channels; in sof_ipc3_volume_get()
131 ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value, in sof_ipc3_volume_get()
132 scontrol->volume_table, in sof_ipc3_volume_get()
133 scontrol->max + 1); in sof_ipc3_volume_get()
141 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_volume_put()
142 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_volume_put()
143 unsigned int channels = scontrol->num_channels; in sof_ipc3_volume_put()
149 u32 value = mixer_to_ipc(ucontrol->value.integer.value[i], in sof_ipc3_volume_put()
150 scontrol->volume_table, scontrol->max + 1); in sof_ipc3_volume_put()
152 change = change || (value != cdata->chanv[i].value); in sof_ipc3_volume_put()
153 cdata->chanv[i].channel = i; in sof_ipc3_volume_put()
154 cdata->chanv[i].value = value; in sof_ipc3_volume_put()
158 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_volume_put()
162 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", in sof_ipc3_volume_put()
163 scontrol->name); in sof_ipc3_volume_put()
174 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_switch_get()
175 unsigned int channels = scontrol->num_channels; in sof_ipc3_switch_get()
182 ucontrol->value.integer.value[i] = cdata->chanv[i].value; in sof_ipc3_switch_get()
190 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_switch_put()
191 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_switch_put()
192 unsigned int channels = scontrol->num_channels; in sof_ipc3_switch_put()
199 value = ucontrol->value.integer.value[i]; in sof_ipc3_switch_put()
200 change = change || (value != cdata->chanv[i].value); in sof_ipc3_switch_put()
201 cdata->chanv[i].channel = i; in sof_ipc3_switch_put()
202 cdata->chanv[i].value = value; in sof_ipc3_switch_put()
206 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_switch_put()
210 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", in sof_ipc3_switch_put()
211 scontrol->name); in sof_ipc3_switch_put()
222 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_enum_get()
223 unsigned int channels = scontrol->num_channels; in sof_ipc3_enum_get()
230 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; in sof_ipc3_enum_get()
238 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_enum_put()
239 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_enum_put()
240 unsigned int channels = scontrol->num_channels; in sof_ipc3_enum_put()
247 value = ucontrol->value.enumerated.item[i]; in sof_ipc3_enum_put()
248 change = change || (value != cdata->chanv[i].value); in sof_ipc3_enum_put()
249 cdata->chanv[i].channel = i; in sof_ipc3_enum_put()
250 cdata->chanv[i].value = value; in sof_ipc3_enum_put()
254 if (pm_runtime_active(scomp->dev)) { in sof_ipc3_enum_put()
258 dev_err(scomp->dev, "Failed to set enum updates for %s\n", in sof_ipc3_enum_put()
259 scontrol->name); in sof_ipc3_enum_put()
270 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_get()
271 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_get()
272 struct sof_abi_hdr *data = cdata->data; in sof_ipc3_bytes_get() local
273 size_t size; in sof_ipc3_bytes_get() local
277 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { in sof_ipc3_bytes_get()
278 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", in sof_ipc3_bytes_get()
279 scontrol->max_size); in sof_ipc3_bytes_get()
280 return -EINVAL; in sof_ipc3_bytes_get()
283 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_get()
284 if (data->size > scontrol->max_size - sizeof(*data)) { in sof_ipc3_bytes_get()
285 dev_err_ratelimited(scomp->dev, in sof_ipc3_bytes_get()
286 "%u bytes of control data is invalid, max is %zu\n", in sof_ipc3_bytes_get()
287 data->size, scontrol->max_size - sizeof(*data)); in sof_ipc3_bytes_get()
288 return -EINVAL; in sof_ipc3_bytes_get()
291 size = data->size + sizeof(*data); in sof_ipc3_bytes_get()
294 memcpy(ucontrol->value.bytes.data, data, size); in sof_ipc3_bytes_get()
302 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_put()
303 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_put()
304 struct sof_abi_hdr *data = cdata->data; in sof_ipc3_bytes_put() local
305 size_t size; in sof_ipc3_bytes_put() local
307 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { in sof_ipc3_bytes_put()
308 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", in sof_ipc3_bytes_put()
309 scontrol->max_size); in sof_ipc3_bytes_put()
310 return -EINVAL; in sof_ipc3_bytes_put()
313 /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_put()
314 if (data->size > scontrol->max_size - sizeof(*data)) { in sof_ipc3_bytes_put()
315 dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", in sof_ipc3_bytes_put()
316 data->size, scontrol->max_size - sizeof(*data)); in sof_ipc3_bytes_put()
317 return -EINVAL; in sof_ipc3_bytes_put()
320 size = data->size + sizeof(*data); in sof_ipc3_bytes_put()
323 memcpy(data, ucontrol->value.bytes.data, size); in sof_ipc3_bytes_put()
326 if (pm_runtime_active(scomp->dev)) in sof_ipc3_bytes_put()
333 const unsigned int __user *binary_data, unsigned int size) in sof_ipc3_bytes_ext_get() argument
336 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_ext_get()
337 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_ext_get()
344 * Decrement the limit by ext bytes header size to in sof_ipc3_bytes_ext_get()
347 if (size < sizeof(struct snd_ctl_tlv)) in sof_ipc3_bytes_ext_get()
348 return -ENOSPC; in sof_ipc3_bytes_ext_get()
350 size -= sizeof(struct snd_ctl_tlv); in sof_ipc3_bytes_ext_get()
353 cdata->data->magic = SOF_ABI_MAGIC; in sof_ipc3_bytes_ext_get()
354 cdata->data->abi = SOF_ABI_VERSION; in sof_ipc3_bytes_ext_get()
356 /* check data size doesn't exceed max coming from topology */ in sof_ipc3_bytes_ext_get()
357 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { in sof_ipc3_bytes_ext_get()
358 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", in sof_ipc3_bytes_ext_get()
359 cdata->data->size, in sof_ipc3_bytes_ext_get()
360 scontrol->max_size - sizeof(struct sof_abi_hdr)); in sof_ipc3_bytes_ext_get()
361 return -EINVAL; in sof_ipc3_bytes_ext_get()
364 data_size = cdata->data->size + sizeof(struct sof_abi_hdr); in sof_ipc3_bytes_ext_get()
366 /* make sure we don't exceed size provided by user space for data */ in sof_ipc3_bytes_ext_get()
367 if (data_size > size) in sof_ipc3_bytes_ext_get()
368 return -ENOSPC; in sof_ipc3_bytes_ext_get()
370 header.numid = cdata->cmd; in sof_ipc3_bytes_ext_get()
373 return -EFAULT; in sof_ipc3_bytes_ext_get()
375 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) in sof_ipc3_bytes_ext_get()
376 return -EFAULT; in sof_ipc3_bytes_ext_get()
383 unsigned int size) in sof_ipc3_bytes_ext_put() argument
386 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_ext_put()
387 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_ext_put()
391 * The beginning of bytes data contains a header from where in sof_ipc3_bytes_ext_put()
393 * length of data from tlvd->tlv. in sof_ipc3_bytes_ext_put()
396 return -EFAULT; in sof_ipc3_bytes_ext_put()
399 if (header.length + sizeof(struct snd_ctl_tlv) > size) { in sof_ipc3_bytes_ext_put()
400 dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n", in sof_ipc3_bytes_ext_put()
401 header.length, sizeof(struct snd_ctl_tlv), size); in sof_ipc3_bytes_ext_put()
402 return -EINVAL; in sof_ipc3_bytes_ext_put()
405 /* be->max is coming from topology */ in sof_ipc3_bytes_ext_put()
406 if (header.length > scontrol->max_size) { in sof_ipc3_bytes_ext_put()
407 dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n", in sof_ipc3_bytes_ext_put()
408 header.length, scontrol->max_size); in sof_ipc3_bytes_ext_put()
409 return -EINVAL; in sof_ipc3_bytes_ext_put()
413 if (header.numid != cdata->cmd) { in sof_ipc3_bytes_ext_put()
414 dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n", in sof_ipc3_bytes_ext_put()
416 return -EINVAL; in sof_ipc3_bytes_ext_put()
419 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) in sof_ipc3_bytes_ext_put()
420 return -EFAULT; in sof_ipc3_bytes_ext_put()
422 if (cdata->data->magic != SOF_ABI_MAGIC) { in sof_ipc3_bytes_ext_put()
423 dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic); in sof_ipc3_bytes_ext_put()
424 return -EINVAL; in sof_ipc3_bytes_ext_put()
427 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { in sof_ipc3_bytes_ext_put()
428 dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n", in sof_ipc3_bytes_ext_put()
429 cdata->data->abi); in sof_ipc3_bytes_ext_put()
430 return -EINVAL; in sof_ipc3_bytes_ext_put()
433 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ in sof_ipc3_bytes_ext_put()
434 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { in sof_ipc3_bytes_ext_put()
435 dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n"); in sof_ipc3_bytes_ext_put()
436 return -EINVAL; in sof_ipc3_bytes_ext_put()
440 if (pm_runtime_active(scomp->dev)) in sof_ipc3_bytes_ext_put()
448 unsigned int size) in sof_ipc3_bytes_ext_volatile_get() argument
451 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; in sof_ipc3_bytes_ext_volatile_get()
452 struct snd_soc_component *scomp = scontrol->scomp; in sof_ipc3_bytes_ext_volatile_get()
458 * Decrement the limit by ext bytes header size to in sof_ipc3_bytes_ext_volatile_get()
461 if (size < sizeof(struct snd_ctl_tlv)) in sof_ipc3_bytes_ext_volatile_get()
462 return -ENOSPC; in sof_ipc3_bytes_ext_volatile_get()
464 size -= sizeof(struct snd_ctl_tlv); in sof_ipc3_bytes_ext_volatile_get()
467 cdata->data->magic = SOF_ABI_MAGIC; in sof_ipc3_bytes_ext_volatile_get()
468 cdata->data->abi = SOF_ABI_VERSION; in sof_ipc3_bytes_ext_volatile_get()
470 /* get all the component data from DSP */ in sof_ipc3_bytes_ext_volatile_get()
475 /* check data size doesn't exceed max coming from topology */ in sof_ipc3_bytes_ext_volatile_get()
476 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { in sof_ipc3_bytes_ext_volatile_get()
477 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", in sof_ipc3_bytes_ext_volatile_get()
478 cdata->data->size, in sof_ipc3_bytes_ext_volatile_get()
479 scontrol->max_size - sizeof(struct sof_abi_hdr)); in sof_ipc3_bytes_ext_volatile_get()
480 return -EINVAL; in sof_ipc3_bytes_ext_volatile_get()
483 data_size = cdata->data->size + sizeof(struct sof_abi_hdr); in sof_ipc3_bytes_ext_volatile_get()
485 /* make sure we don't exceed size provided by user space for data */ in sof_ipc3_bytes_ext_volatile_get()
486 if (data_size > size) in sof_ipc3_bytes_ext_volatile_get()
487 return -ENOSPC; in sof_ipc3_bytes_ext_volatile_get()
489 header.numid = cdata->cmd; in sof_ipc3_bytes_ext_volatile_get()
492 return -EFAULT; in sof_ipc3_bytes_ext_volatile_get()
494 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) in sof_ipc3_bytes_ext_volatile_get()
495 return -EFAULT; in sof_ipc3_bytes_ext_volatile_get()
503 struct snd_soc_component *scomp = scontrol->scomp; in snd_sof_update_control()
507 local_cdata = scontrol->ipc_control_data; in snd_sof_update_control()
509 if (cdata->cmd == SOF_CTRL_CMD_BINARY) { in snd_sof_update_control()
510 if (cdata->num_elems != local_cdata->data->size) { in snd_sof_update_control()
511 dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n", in snd_sof_update_control()
512 cdata->num_elems, local_cdata->data->size); in snd_sof_update_control()
516 /* copy the new binary data */ in snd_sof_update_control()
517 memcpy(local_cdata->data, cdata->data, cdata->num_elems); in snd_sof_update_control()
518 } else if (cdata->num_elems != scontrol->num_channels) { in snd_sof_update_control()
519 dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n", in snd_sof_update_control()
520 cdata->num_elems, scontrol->num_channels); in snd_sof_update_control()
523 for (i = 0; i < cdata->num_elems; i++) in snd_sof_update_control()
524 local_cdata->chanv[i].value = cdata->chanv[i].value; in snd_sof_update_control()
542 if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET || in sof_ipc3_control_update()
543 cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) { in sof_ipc3_control_update()
544 dev_err(sdev->dev, "Component data is not supported in control notification\n"); in sof_ipc3_control_update()
549 list_for_each_entry(swidget, &sdev->widget_list, list) { in sof_ipc3_control_update()
550 if (swidget->comp_id == cdata->comp_id) { in sof_ipc3_control_update()
560 switch (cdata->cmd) { in sof_ipc3_control_update()
572 dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__); in sof_ipc3_control_update()
576 widget = swidget->widget; in sof_ipc3_control_update()
577 for (i = 0; i < widget->num_kcontrols; i++) { in sof_ipc3_control_update()
579 if (widget->dobj.widget.kcontrol_type[i] == type && in sof_ipc3_control_update()
580 widget->kcontrol_news[i].index == cdata->index) { in sof_ipc3_control_update()
581 kc = widget->kcontrols[i]; in sof_ipc3_control_update()
589 switch (cdata->cmd) { in sof_ipc3_control_update()
592 sm = (struct soc_mixer_control *)kc->private_value; in sof_ipc3_control_update()
593 scontrol = sm->dobj.private; in sof_ipc3_control_update()
596 be = (struct soc_bytes_ext *)kc->private_value; in sof_ipc3_control_update()
597 scontrol = be->dobj.private; in sof_ipc3_control_update()
600 se = (struct soc_enum *)kc->private_value; in sof_ipc3_control_update()
601 scontrol = se->dobj.private; in sof_ipc3_control_update()
608 switch (cdata->type) { in sof_ipc3_control_update()
611 expected_size += cdata->num_elems * in sof_ipc3_control_update()
616 expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); in sof_ipc3_control_update()
622 if (cdata->rhdr.hdr.size != expected_size) { in sof_ipc3_control_update()
623 dev_err(sdev->dev, "Component notification size mismatch\n"); in sof_ipc3_control_update()
627 if (cdata->num_elems) in sof_ipc3_control_update()
629 * The message includes the updated value/data, update the in sof_ipc3_control_update()
634 /* Mark the scontrol that the value/data is changed in SOF */ in sof_ipc3_control_update()
635 scontrol->comp_data_dirty = true; in sof_ipc3_control_update()
637 snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); in sof_ipc3_control_update()
647 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) in sof_ipc3_widget_kcontrol_setup()
648 if (scontrol->comp_id == swidget->comp_id) { in sof_ipc3_widget_kcontrol_setup()
649 /* set kcontrol data in DSP */ in sof_ipc3_widget_kcontrol_setup()
652 dev_err(sdev->dev, in sof_ipc3_widget_kcontrol_setup()
654 scontrol->comp_id, swidget->widget->name); in sof_ipc3_widget_kcontrol_setup()
659 * Read back the data from the DSP for static widgets. in sof_ipc3_widget_kcontrol_setup()
662 * the data size to match that in the DSP. in sof_ipc3_widget_kcontrol_setup()
664 if (swidget->dynamic_pipeline_widget) in sof_ipc3_widget_kcontrol_setup()
669 dev_warn(sdev->dev, in sof_ipc3_widget_kcontrol_setup()
671 scontrol->comp_id, swidget->widget->name); in sof_ipc3_widget_kcontrol_setup()
678 sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size) in sof_ipc3_set_up_volume_table() argument
683 scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); in sof_ipc3_set_up_volume_table()
684 if (!scontrol->volume_table) in sof_ipc3_set_up_volume_table()
685 return -ENOMEM; in sof_ipc3_set_up_volume_table()
688 for (i = 0; i < size ; i++) in sof_ipc3_set_up_volume_table()
689 scontrol->volume_table[i] = vol_compute_gain(i, tlv); in sof_ipc3_set_up_volume_table()