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. All rights reserved. 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 100 unlock: 101 if (lock) 102 mutex_unlock(&swidget->setup_mutex); 103 104 return ret; 105 } 106 107 static void snd_sof_refresh_control(struct snd_sof_control *scontrol) 108 { 109 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 110 struct snd_soc_component *scomp = scontrol->scomp; 111 int ret; 112 113 if (!scontrol->comp_data_dirty) 114 return; 115 116 if (!pm_runtime_active(scomp->dev)) 117 return; 118 119 /* set the ABI header values */ 120 cdata->data->magic = SOF_ABI_MAGIC; 121 cdata->data->abi = SOF_ABI_VERSION; 122 123 /* refresh the component data from DSP */ 124 scontrol->comp_data_dirty = false; 125 ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); 126 if (ret < 0) { 127 dev_err(scomp->dev, "Failed to get control data: %d\n", ret); 128 129 /* Set the flag to re-try next time to get the data */ 130 scontrol->comp_data_dirty = true; 131 } 132 } 133 134 static int sof_ipc3_volume_get(struct snd_sof_control *scontrol, 135 struct snd_ctl_elem_value *ucontrol) 136 { 137 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 138 unsigned int channels = scontrol->num_channels; 139 unsigned int i; 140 141 snd_sof_refresh_control(scontrol); 142 143 /* read back each channel */ 144 for (i = 0; i < channels; i++) 145 ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value, 146 scontrol->volume_table, 147 scontrol->max + 1); 148 149 return 0; 150 } 151 152 static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol, 153 struct snd_ctl_elem_value *ucontrol) 154 { 155 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 156 struct snd_soc_component *scomp = scontrol->scomp; 157 unsigned int channels = scontrol->num_channels; 158 unsigned int i; 159 bool change = false; 160 161 /* update each channel */ 162 for (i = 0; i < channels; i++) { 163 u32 value = mixer_to_ipc(ucontrol->value.integer.value[i], 164 scontrol->volume_table, scontrol->max + 1); 165 166 change = change || (value != cdata->chanv[i].value); 167 cdata->chanv[i].channel = i; 168 cdata->chanv[i].value = value; 169 } 170 171 /* notify DSP of mixer updates */ 172 if (pm_runtime_active(scomp->dev)) { 173 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true); 174 175 if (ret < 0) { 176 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", 177 scontrol->name); 178 return false; 179 } 180 } 181 182 return change; 183 } 184 185 static int sof_ipc3_switch_get(struct snd_sof_control *scontrol, 186 struct snd_ctl_elem_value *ucontrol) 187 { 188 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 189 unsigned int channels = scontrol->num_channels; 190 unsigned int i; 191 192 snd_sof_refresh_control(scontrol); 193 194 /* read back each channel */ 195 for (i = 0; i < channels; i++) 196 ucontrol->value.integer.value[i] = cdata->chanv[i].value; 197 198 return 0; 199 } 200 201 static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol, 202 struct snd_ctl_elem_value *ucontrol) 203 { 204 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 205 struct snd_soc_component *scomp = scontrol->scomp; 206 unsigned int channels = scontrol->num_channels; 207 unsigned int i; 208 bool change = false; 209 u32 value; 210 211 /* update each channel */ 212 for (i = 0; i < channels; i++) { 213 value = ucontrol->value.integer.value[i]; 214 change = change || (value != cdata->chanv[i].value); 215 cdata->chanv[i].channel = i; 216 cdata->chanv[i].value = value; 217 } 218 219 /* notify DSP of mixer updates */ 220 if (pm_runtime_active(scomp->dev)) { 221 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true); 222 223 if (ret < 0) { 224 dev_err(scomp->dev, "Failed to set mixer updates for %s\n", 225 scontrol->name); 226 return false; 227 } 228 } 229 230 return change; 231 } 232 233 static int sof_ipc3_enum_get(struct snd_sof_control *scontrol, 234 struct snd_ctl_elem_value *ucontrol) 235 { 236 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 237 unsigned int channels = scontrol->num_channels; 238 unsigned int i; 239 240 snd_sof_refresh_control(scontrol); 241 242 /* read back each channel */ 243 for (i = 0; i < channels; i++) 244 ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; 245 246 return 0; 247 } 248 249 static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol, 250 struct snd_ctl_elem_value *ucontrol) 251 { 252 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 253 struct snd_soc_component *scomp = scontrol->scomp; 254 unsigned int channels = scontrol->num_channels; 255 unsigned int i; 256 bool change = false; 257 u32 value; 258 259 /* update each channel */ 260 for (i = 0; i < channels; i++) { 261 value = ucontrol->value.enumerated.item[i]; 262 change = change || (value != cdata->chanv[i].value); 263 cdata->chanv[i].channel = i; 264 cdata->chanv[i].value = value; 265 } 266 267 /* notify DSP of enum updates */ 268 if (pm_runtime_active(scomp->dev)) { 269 int ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, true); 270 271 if (ret < 0) { 272 dev_err(scomp->dev, "Failed to set enum updates for %s\n", 273 scontrol->name); 274 return false; 275 } 276 } 277 278 return change; 279 } 280 281 static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol, 282 struct snd_ctl_elem_value *ucontrol) 283 { 284 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 285 struct snd_soc_component *scomp = scontrol->scomp; 286 struct sof_abi_hdr *data = cdata->data; 287 size_t size; 288 289 snd_sof_refresh_control(scontrol); 290 291 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { 292 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", 293 scontrol->max_size); 294 return -EINVAL; 295 } 296 297 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ 298 if (data->size > scontrol->max_size - sizeof(*data)) { 299 dev_err_ratelimited(scomp->dev, 300 "%u bytes of control data is invalid, max is %zu\n", 301 data->size, scontrol->max_size - sizeof(*data)); 302 return -EINVAL; 303 } 304 305 size = data->size + sizeof(*data); 306 307 /* copy back to kcontrol */ 308 memcpy(ucontrol->value.bytes.data, data, size); 309 310 return 0; 311 } 312 313 static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, 314 struct snd_ctl_elem_value *ucontrol) 315 { 316 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 317 struct snd_soc_component *scomp = scontrol->scomp; 318 struct sof_abi_hdr *data = cdata->data; 319 size_t size; 320 321 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { 322 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", 323 scontrol->max_size); 324 return -EINVAL; 325 } 326 327 /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ 328 if (data->size > scontrol->max_size - sizeof(*data)) { 329 dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", 330 data->size, scontrol->max_size - sizeof(*data)); 331 return -EINVAL; 332 } 333 334 size = data->size + sizeof(*data); 335 336 /* copy from kcontrol */ 337 memcpy(data, ucontrol->value.bytes.data, size); 338 339 /* notify DSP of byte control updates */ 340 if (pm_runtime_active(scomp->dev)) 341 return sof_ipc3_set_get_kcontrol_data(scontrol, true, true); 342 343 return 0; 344 } 345 346 static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, 347 const unsigned int __user *binary_data, unsigned int size) 348 { 349 struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; 350 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 351 struct snd_soc_component *scomp = scontrol->scomp; 352 struct snd_ctl_tlv header; 353 size_t data_size; 354 355 snd_sof_refresh_control(scontrol); 356 357 /* 358 * Decrement the limit by ext bytes header size to 359 * ensure the user space buffer is not exceeded. 360 */ 361 if (size < sizeof(struct snd_ctl_tlv)) 362 return -ENOSPC; 363 364 size -= sizeof(struct snd_ctl_tlv); 365 366 /* set the ABI header values */ 367 cdata->data->magic = SOF_ABI_MAGIC; 368 cdata->data->abi = SOF_ABI_VERSION; 369 370 /* check data size doesn't exceed max coming from topology */ 371 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { 372 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", 373 cdata->data->size, 374 scontrol->max_size - sizeof(struct sof_abi_hdr)); 375 return -EINVAL; 376 } 377 378 data_size = cdata->data->size + sizeof(struct sof_abi_hdr); 379 380 /* make sure we don't exceed size provided by user space for data */ 381 if (data_size > size) 382 return -ENOSPC; 383 384 header.numid = cdata->cmd; 385 header.length = data_size; 386 if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) 387 return -EFAULT; 388 389 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 390 return -EFAULT; 391 392 return 0; 393 } 394 395 static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, 396 const unsigned int __user *binary_data, 397 unsigned int size) 398 { 399 const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data; 400 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 401 struct snd_soc_component *scomp = scontrol->scomp; 402 struct snd_ctl_tlv header; 403 404 /* 405 * The beginning of bytes data contains a header from where 406 * the length (as bytes) is needed to know the correct copy 407 * length of data from tlvd->tlv. 408 */ 409 if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) 410 return -EFAULT; 411 412 /* make sure TLV info is consistent */ 413 if (header.length + sizeof(struct snd_ctl_tlv) > size) { 414 dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n", 415 header.length, sizeof(struct snd_ctl_tlv), size); 416 return -EINVAL; 417 } 418 419 /* be->max is coming from topology */ 420 if (header.length > scontrol->max_size) { 421 dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n", 422 header.length, scontrol->max_size); 423 return -EINVAL; 424 } 425 426 /* Check that header id matches the command */ 427 if (header.numid != cdata->cmd) { 428 dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n", 429 header.numid); 430 return -EINVAL; 431 } 432 433 if (copy_from_user(cdata->data, tlvd->tlv, header.length)) 434 return -EFAULT; 435 436 if (cdata->data->magic != SOF_ABI_MAGIC) { 437 dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic); 438 return -EINVAL; 439 } 440 441 if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { 442 dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n", 443 cdata->data->abi); 444 return -EINVAL; 445 } 446 447 /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ 448 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { 449 dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n"); 450 return -EINVAL; 451 } 452 453 /* notify DSP of byte control updates */ 454 if (pm_runtime_active(scomp->dev)) 455 return sof_ipc3_set_get_kcontrol_data(scontrol, true, true); 456 457 return 0; 458 } 459 460 static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, 461 const unsigned int __user *binary_data, 462 unsigned int size) 463 { 464 struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; 465 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 466 struct snd_soc_component *scomp = scontrol->scomp; 467 struct snd_ctl_tlv header; 468 size_t data_size; 469 int ret; 470 471 /* 472 * Decrement the limit by ext bytes header size to 473 * ensure the user space buffer is not exceeded. 474 */ 475 if (size < sizeof(struct snd_ctl_tlv)) 476 return -ENOSPC; 477 478 size -= sizeof(struct snd_ctl_tlv); 479 480 /* set the ABI header values */ 481 cdata->data->magic = SOF_ABI_MAGIC; 482 cdata->data->abi = SOF_ABI_VERSION; 483 484 /* get all the component data from DSP */ 485 ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); 486 if (ret < 0) 487 return ret; 488 489 /* check data size doesn't exceed max coming from topology */ 490 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { 491 dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", 492 cdata->data->size, 493 scontrol->max_size - sizeof(struct sof_abi_hdr)); 494 return -EINVAL; 495 } 496 497 data_size = cdata->data->size + sizeof(struct sof_abi_hdr); 498 499 /* make sure we don't exceed size provided by user space for data */ 500 if (data_size > size) 501 return -ENOSPC; 502 503 header.numid = cdata->cmd; 504 header.length = data_size; 505 if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) 506 return -EFAULT; 507 508 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 509 return -EFAULT; 510 511 return ret; 512 } 513 514 static void snd_sof_update_control(struct snd_sof_control *scontrol, 515 struct sof_ipc_ctrl_data *cdata) 516 { 517 struct snd_soc_component *scomp = scontrol->scomp; 518 struct sof_ipc_ctrl_data *local_cdata; 519 int i; 520 521 local_cdata = scontrol->ipc_control_data; 522 523 if (cdata->cmd == SOF_CTRL_CMD_BINARY) { 524 if (cdata->num_elems != local_cdata->data->size) { 525 dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n", 526 cdata->num_elems, local_cdata->data->size); 527 return; 528 } 529 530 /* copy the new binary data */ 531 memcpy(local_cdata->data, cdata->data, cdata->num_elems); 532 } else if (cdata->num_elems != scontrol->num_channels) { 533 dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n", 534 cdata->num_elems, scontrol->num_channels); 535 } else { 536 /* copy the new values */ 537 for (i = 0; i < cdata->num_elems; i++) 538 local_cdata->chanv[i].value = cdata->chanv[i].value; 539 } 540 } 541 542 static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_message) 543 { 544 struct sof_ipc_ctrl_data *cdata = ipc_control_message; 545 struct snd_soc_dapm_widget *widget; 546 struct snd_sof_control *scontrol; 547 struct snd_sof_widget *swidget; 548 struct snd_kcontrol *kc = NULL; 549 struct soc_mixer_control *sm; 550 struct soc_bytes_ext *be; 551 size_t expected_size; 552 struct soc_enum *se; 553 bool found = false; 554 int i, type; 555 556 if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET || 557 cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) { 558 dev_err(sdev->dev, "Component data is not supported in control notification\n"); 559 return; 560 } 561 562 /* Find the swidget first */ 563 list_for_each_entry(swidget, &sdev->widget_list, list) { 564 if (swidget->comp_id == cdata->comp_id) { 565 found = true; 566 break; 567 } 568 } 569 570 if (!found) 571 return; 572 573 /* Translate SOF cmd to TPLG type */ 574 switch (cdata->cmd) { 575 case SOF_CTRL_CMD_VOLUME: 576 case SOF_CTRL_CMD_SWITCH: 577 type = SND_SOC_TPLG_TYPE_MIXER; 578 break; 579 case SOF_CTRL_CMD_BINARY: 580 type = SND_SOC_TPLG_TYPE_BYTES; 581 break; 582 case SOF_CTRL_CMD_ENUM: 583 type = SND_SOC_TPLG_TYPE_ENUM; 584 break; 585 default: 586 dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__); 587 return; 588 } 589 590 widget = swidget->widget; 591 for (i = 0; i < widget->num_kcontrols; i++) { 592 /* skip non matching types or non matching indexes within type */ 593 if (widget->dobj.widget.kcontrol_type[i] == type && 594 widget->kcontrol_news[i].index == cdata->index) { 595 kc = widget->kcontrols[i]; 596 break; 597 } 598 } 599 600 if (!kc) 601 return; 602 603 switch (cdata->cmd) { 604 case SOF_CTRL_CMD_VOLUME: 605 case SOF_CTRL_CMD_SWITCH: 606 sm = (struct soc_mixer_control *)kc->private_value; 607 scontrol = sm->dobj.private; 608 break; 609 case SOF_CTRL_CMD_BINARY: 610 be = (struct soc_bytes_ext *)kc->private_value; 611 scontrol = be->dobj.private; 612 break; 613 case SOF_CTRL_CMD_ENUM: 614 se = (struct soc_enum *)kc->private_value; 615 scontrol = se->dobj.private; 616 break; 617 default: 618 return; 619 } 620 621 expected_size = sizeof(struct sof_ipc_ctrl_data); 622 switch (cdata->type) { 623 case SOF_CTRL_TYPE_VALUE_CHAN_GET: 624 case SOF_CTRL_TYPE_VALUE_CHAN_SET: 625 expected_size += cdata->num_elems * 626 sizeof(struct sof_ipc_ctrl_value_chan); 627 break; 628 case SOF_CTRL_TYPE_DATA_GET: 629 case SOF_CTRL_TYPE_DATA_SET: 630 expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); 631 break; 632 default: 633 return; 634 } 635 636 if (cdata->rhdr.hdr.size != expected_size) { 637 dev_err(sdev->dev, "Component notification size mismatch\n"); 638 return; 639 } 640 641 if (cdata->num_elems) 642 /* 643 * The message includes the updated value/data, update the 644 * control's local cache using the received notification 645 */ 646 snd_sof_update_control(scontrol, cdata); 647 else 648 /* Mark the scontrol that the value/data is changed in SOF */ 649 scontrol->comp_data_dirty = true; 650 651 snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); 652 } 653 654 static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev, 655 struct snd_sof_widget *swidget) 656 { 657 struct snd_sof_control *scontrol; 658 int ret; 659 660 /* set up all controls for the widget */ 661 list_for_each_entry(scontrol, &sdev->kcontrol_list, list) 662 if (scontrol->comp_id == swidget->comp_id) { 663 /* set kcontrol data in DSP */ 664 ret = sof_ipc3_set_get_kcontrol_data(scontrol, true, false); 665 if (ret < 0) { 666 dev_err(sdev->dev, 667 "kcontrol %d set up failed for widget %s\n", 668 scontrol->comp_id, swidget->widget->name); 669 return ret; 670 } 671 672 /* 673 * Read back the data from the DSP for static widgets. 674 * This is particularly useful for binary kcontrols 675 * associated with static pipeline widgets to initialize 676 * the data size to match that in the DSP. 677 */ 678 if (swidget->dynamic_pipeline_widget) 679 continue; 680 681 ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, false); 682 if (ret < 0) 683 dev_warn(sdev->dev, 684 "kcontrol %d read failed for widget %s\n", 685 scontrol->comp_id, swidget->widget->name); 686 } 687 688 return 0; 689 } 690 691 static int 692 sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size) 693 { 694 int i; 695 696 /* init the volume table */ 697 scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL); 698 if (!scontrol->volume_table) 699 return -ENOMEM; 700 701 /* populate the volume table */ 702 for (i = 0; i < size ; i++) 703 scontrol->volume_table[i] = vol_compute_gain(i, tlv); 704 705 return 0; 706 } 707 708 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { 709 .volume_put = sof_ipc3_volume_put, 710 .volume_get = sof_ipc3_volume_get, 711 .switch_put = sof_ipc3_switch_put, 712 .switch_get = sof_ipc3_switch_get, 713 .enum_put = sof_ipc3_enum_put, 714 .enum_get = sof_ipc3_enum_get, 715 .bytes_put = sof_ipc3_bytes_put, 716 .bytes_get = sof_ipc3_bytes_get, 717 .bytes_ext_put = sof_ipc3_bytes_ext_put, 718 .bytes_ext_get = sof_ipc3_bytes_ext_get, 719 .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get, 720 .update = sof_ipc3_control_update, 721 .widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup, 722 .set_up_volume_table = sof_ipc3_set_up_volume_table, 723 }; 724