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