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