Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: ipc4: Add support for bytes control

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

This series will add support for bytes control and topology types.
With IPC4 only the binary payload is sent to the firmware via LARGE_CONFIG
message (which does similar multi-part message handling as the IPC3 control
message did).

The bytes payload itself is not checked by the kernel but user space expected to
wrap it in sof_abi_hdr struct in order to get the target information of the
binary data.

The SOF firmware and sof-ctl have been updated to support blobs used in IPC4
setups.

+368 -78
+2
include/uapi/sound/sof/abi.h
··· 60 60 61 61 /* SOF ABI magic number "SOF\0". */ 62 62 #define SOF_ABI_MAGIC 0x00464F53 63 + /* SOF IPC4 ABI magic number "SOF4". */ 64 + #define SOF_IPC4_ABI_MAGIC 0x34464F53 63 65 64 66 #endif
+19 -8
include/uapi/sound/sof/header.h
··· 11 11 12 12 #include <linux/types.h> 13 13 14 - /* 15 - * Header for all non IPC ABI data. 14 + /** 15 + * struct sof_abi_hdr - Header for all non IPC ABI data. 16 + * @magic: Magic number for validation 17 + * for IPC3 data: 0x00464F53 ('S', 'O', 'F', '\0') 18 + * for IPC4 data: 0x34464F53 ('S', 'O', 'F', '4') 19 + * @type: module specific parameter 20 + * for IPC3: Component specific type 21 + * for IPC4: parameter ID (param_id) of the data 22 + * @size: The size in bytes of the data, excluding this struct 23 + * @abi: SOF ABI version. The version is valid in scope of the 'magic', IPC3 and 24 + * IPC4 ABI version numbers have no relationship. 25 + * @reserved: Reserved for future use 26 + * @data: Component data - opaque to core 16 27 * 17 28 * Identifies data type, size and ABI. 18 29 * Used by any bespoke component data structures or binary blobs. 19 30 */ 20 31 struct sof_abi_hdr { 21 - __u32 magic; /**< 'S', 'O', 'F', '\0' */ 22 - __u32 type; /**< component specific type */ 23 - __u32 size; /**< size in bytes of data excl. this struct */ 24 - __u32 abi; /**< SOF ABI version */ 25 - __u32 reserved[4]; /**< reserved for future use */ 26 - __u32 data[]; /**< Component data - opaque to core */ 32 + __u32 magic; 33 + __u32 type; 34 + __u32 size; 35 + __u32 abi; 36 + __u32 reserved[4]; 37 + __u32 data[]; 27 38 } __packed; 28 39 29 40 #define SOF_MANIFEST_DATA_TYPE_NHLT 1
+28 -62
sound/soc/sof/ipc3-control.c
··· 104 104 return ret; 105 105 } 106 106 107 - static void snd_sof_refresh_control(struct snd_sof_control *scontrol) 107 + static void sof_ipc3_refresh_control(struct snd_sof_control *scontrol) 108 108 { 109 109 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 110 110 struct snd_soc_component *scomp = scontrol->scomp; ··· 138 138 unsigned int channels = scontrol->num_channels; 139 139 unsigned int i; 140 140 141 - snd_sof_refresh_control(scontrol); 141 + sof_ipc3_refresh_control(scontrol); 142 142 143 143 /* read back each channel */ 144 144 for (i = 0; i < channels; i++) ··· 189 189 unsigned int channels = scontrol->num_channels; 190 190 unsigned int i; 191 191 192 - snd_sof_refresh_control(scontrol); 192 + sof_ipc3_refresh_control(scontrol); 193 193 194 194 /* read back each channel */ 195 195 for (i = 0; i < channels; i++) ··· 237 237 unsigned int channels = scontrol->num_channels; 238 238 unsigned int i; 239 239 240 - snd_sof_refresh_control(scontrol); 240 + sof_ipc3_refresh_control(scontrol); 241 241 242 242 /* read back each channel */ 243 243 for (i = 0; i < channels; i++) ··· 286 286 struct sof_abi_hdr *data = cdata->data; 287 287 size_t size; 288 288 289 - snd_sof_refresh_control(scontrol); 289 + sof_ipc3_refresh_control(scontrol); 290 290 291 291 if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { 292 292 dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", ··· 339 339 /* notify DSP of byte control updates */ 340 340 if (pm_runtime_active(scomp->dev)) 341 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 342 392 343 return 0; 393 344 } ··· 408 457 return 0; 409 458 } 410 459 411 - static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, 412 - const unsigned int __user *binary_data, 413 - unsigned int size) 460 + static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, 461 + const unsigned int __user *binary_data, 462 + unsigned int size, bool from_dsp) 414 463 { 415 464 struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; 416 465 struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; 417 466 struct snd_soc_component *scomp = scontrol->scomp; 418 467 struct snd_ctl_tlv header; 419 468 size_t data_size; 420 - int ret; 421 469 422 470 /* 423 471 * Decrement the limit by ext bytes header size to ··· 432 482 cdata->data->abi = SOF_ABI_VERSION; 433 483 434 484 /* get all the component data from DSP */ 435 - ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); 436 - if (ret < 0) 437 - return ret; 485 + if (from_dsp) { 486 + int ret = sof_ipc3_set_get_kcontrol_data(scontrol, false, true); 487 + 488 + if (ret < 0) 489 + return ret; 490 + } 438 491 439 492 /* check data size doesn't exceed max coming from topology */ 440 493 if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { ··· 461 508 if (copy_to_user(tlvd->tlv, cdata->data, data_size)) 462 509 return -EFAULT; 463 510 464 - return ret; 511 + return 0; 512 + } 513 + 514 + static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, 515 + const unsigned int __user *binary_data, unsigned int size) 516 + { 517 + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, false); 518 + } 519 + 520 + static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, 521 + const unsigned int __user *binary_data, 522 + unsigned int size) 523 + { 524 + return _sof_ipc3_bytes_ext_get(scontrol, binary_data, size, true); 465 525 } 466 526 467 527 static void snd_sof_update_control(struct snd_sof_control *scontrol,
+252 -8
sound/soc/sof/ipc4-control.c
··· 181 181 return 0; 182 182 } 183 183 184 + static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, 185 + struct snd_sof_control *scontrol, 186 + bool set, bool lock) 187 + { 188 + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 189 + struct sof_abi_hdr *data = cdata->data; 190 + struct sof_ipc4_msg *msg = &cdata->msg; 191 + int ret = 0; 192 + 193 + /* Send the new data to the firmware only if it is powered up */ 194 + if (set && !pm_runtime_active(sdev->dev)) 195 + return 0; 196 + 197 + msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); 198 + 199 + msg->data_ptr = data->data; 200 + msg->data_size = data->size; 201 + 202 + ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); 203 + if (ret < 0) 204 + dev_err(sdev->dev, "Failed to %s for %s\n", 205 + set ? "set bytes update" : "get bytes", 206 + scontrol->name); 207 + 208 + msg->data_ptr = NULL; 209 + msg->data_size = 0; 210 + 211 + return ret; 212 + } 213 + 214 + static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, 215 + struct snd_ctl_elem_value *ucontrol) 216 + { 217 + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 218 + struct snd_soc_component *scomp = scontrol->scomp; 219 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 220 + struct sof_abi_hdr *data = cdata->data; 221 + size_t size; 222 + 223 + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { 224 + dev_err_ratelimited(scomp->dev, 225 + "data max %zu exceeds ucontrol data array size\n", 226 + scontrol->max_size); 227 + return -EINVAL; 228 + } 229 + 230 + /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ 231 + if (data->size > scontrol->max_size - sizeof(*data)) { 232 + dev_err_ratelimited(scomp->dev, 233 + "data size too big %u bytes max is %zu\n", 234 + data->size, scontrol->max_size - sizeof(*data)); 235 + return -EINVAL; 236 + } 237 + 238 + size = data->size + sizeof(*data); 239 + 240 + /* copy from kcontrol */ 241 + memcpy(data, ucontrol->value.bytes.data, size); 242 + 243 + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); 244 + 245 + return 0; 246 + } 247 + 248 + static int sof_ipc4_bytes_get(struct snd_sof_control *scontrol, 249 + struct snd_ctl_elem_value *ucontrol) 250 + { 251 + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 252 + struct snd_soc_component *scomp = scontrol->scomp; 253 + struct sof_abi_hdr *data = cdata->data; 254 + size_t size; 255 + 256 + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { 257 + dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", 258 + scontrol->max_size); 259 + return -EINVAL; 260 + } 261 + 262 + if (data->size > scontrol->max_size - sizeof(*data)) { 263 + dev_err_ratelimited(scomp->dev, 264 + "%u bytes of control data is invalid, max is %zu\n", 265 + data->size, scontrol->max_size - sizeof(*data)); 266 + return -EINVAL; 267 + } 268 + 269 + size = data->size + sizeof(*data); 270 + 271 + /* copy back to kcontrol */ 272 + memcpy(ucontrol->value.bytes.data, data, size); 273 + 274 + return 0; 275 + } 276 + 277 + static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol, 278 + const unsigned int __user *binary_data, 279 + unsigned int size) 280 + { 281 + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; 282 + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 283 + struct snd_soc_component *scomp = scontrol->scomp; 284 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 285 + struct sof_abi_hdr *data = cdata->data; 286 + struct sof_abi_hdr abi_hdr; 287 + struct snd_ctl_tlv header; 288 + 289 + /* 290 + * The beginning of bytes data contains a header from where 291 + * the length (as bytes) is needed to know the correct copy 292 + * length of data from tlvd->tlv. 293 + */ 294 + if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) 295 + return -EFAULT; 296 + 297 + /* make sure TLV info is consistent */ 298 + if (header.length + sizeof(struct snd_ctl_tlv) > size) { 299 + dev_err_ratelimited(scomp->dev, 300 + "Inconsistent TLV, data %d + header %zu > %d\n", 301 + header.length, sizeof(struct snd_ctl_tlv), size); 302 + return -EINVAL; 303 + } 304 + 305 + /* be->max is coming from topology */ 306 + if (header.length > scontrol->max_size) { 307 + dev_err_ratelimited(scomp->dev, 308 + "Bytes data size %d exceeds max %zu\n", 309 + header.length, scontrol->max_size); 310 + return -EINVAL; 311 + } 312 + 313 + /* Verify the ABI header first */ 314 + if (copy_from_user(&abi_hdr, tlvd->tlv, sizeof(abi_hdr))) 315 + return -EFAULT; 316 + 317 + if (abi_hdr.magic != SOF_IPC4_ABI_MAGIC) { 318 + dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", 319 + abi_hdr.magic); 320 + return -EINVAL; 321 + } 322 + 323 + if (abi_hdr.size > scontrol->max_size - sizeof(abi_hdr)) { 324 + dev_err_ratelimited(scomp->dev, 325 + "%u bytes of control data is invalid, max is %zu\n", 326 + abi_hdr.size, scontrol->max_size - sizeof(abi_hdr)); 327 + return -EINVAL; 328 + } 329 + 330 + /* Copy the whole binary data which includes the ABI header and the payload */ 331 + if (copy_from_user(data, tlvd->tlv, header.length)) 332 + return -EFAULT; 333 + 334 + sof_ipc4_set_get_bytes_data(sdev, scontrol, true, true); 335 + 336 + return 0; 337 + } 338 + 339 + static int _sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, 340 + const unsigned int __user *binary_data, 341 + unsigned int size, bool from_dsp) 342 + { 343 + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; 344 + struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 345 + struct snd_soc_component *scomp = scontrol->scomp; 346 + struct sof_abi_hdr *data = cdata->data; 347 + struct snd_ctl_tlv header; 348 + size_t data_size; 349 + 350 + /* 351 + * Decrement the limit by ext bytes header size to ensure the user space 352 + * buffer is not exceeded. 353 + */ 354 + if (size < sizeof(struct snd_ctl_tlv)) 355 + return -ENOSPC; 356 + 357 + size -= sizeof(struct snd_ctl_tlv); 358 + 359 + /* get all the component data from DSP */ 360 + if (from_dsp) { 361 + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 362 + int ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, false, true); 363 + 364 + if (ret < 0) 365 + return ret; 366 + 367 + /* Set the ABI magic (if the control is not initialized) */ 368 + data->magic = SOF_IPC4_ABI_MAGIC; 369 + } 370 + 371 + if (data->size > scontrol->max_size - sizeof(*data)) { 372 + dev_err_ratelimited(scomp->dev, 373 + "%u bytes of control data is invalid, max is %zu\n", 374 + data->size, scontrol->max_size - sizeof(*data)); 375 + return -EINVAL; 376 + } 377 + 378 + data_size = 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 = scontrol->comp_id; 385 + header.length = data_size; 386 + 387 + if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) 388 + return -EFAULT; 389 + 390 + if (copy_to_user(tlvd->tlv, data, data_size)) 391 + return -EFAULT; 392 + 393 + return 0; 394 + } 395 + 396 + static int sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol, 397 + const unsigned int __user *binary_data, 398 + unsigned int size) 399 + { 400 + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, false); 401 + } 402 + 403 + static int sof_ipc4_bytes_ext_volatile_get(struct snd_sof_control *scontrol, 404 + const unsigned int __user *binary_data, 405 + unsigned int size) 406 + { 407 + return _sof_ipc4_bytes_ext_get(scontrol, binary_data, size, true); 408 + } 409 + 184 410 /* set up all controls for the widget */ 185 411 static int sof_ipc4_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 186 412 { 187 413 struct snd_sof_control *scontrol; 188 - int ret; 414 + int ret = 0; 189 415 190 - list_for_each_entry(scontrol, &sdev->kcontrol_list, list) 416 + list_for_each_entry(scontrol, &sdev->kcontrol_list, list) { 191 417 if (scontrol->comp_id == swidget->comp_id) { 192 - ret = sof_ipc4_set_volume_data(sdev, swidget, scontrol, false); 193 - if (ret < 0) { 194 - dev_err(sdev->dev, "%s: kcontrol %d set up failed for widget %s\n", 195 - __func__, scontrol->comp_id, swidget->widget->name); 196 - return ret; 418 + switch (scontrol->info_type) { 419 + case SND_SOC_TPLG_CTL_VOLSW: 420 + case SND_SOC_TPLG_CTL_VOLSW_SX: 421 + case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 422 + ret = sof_ipc4_set_volume_data(sdev, swidget, 423 + scontrol, false); 424 + break; 425 + case SND_SOC_TPLG_CTL_BYTES: 426 + ret = sof_ipc4_set_get_bytes_data(sdev, scontrol, 427 + true, false); 428 + break; 429 + default: 430 + break; 197 431 } 198 432 } 433 + } 199 434 200 - return 0; 435 + if (ret < 0) 436 + dev_err(sdev->dev, "kcontrol %d set up failed for widget %s\n", 437 + scontrol->comp_id, swidget->widget->name); 438 + 439 + return ret; 201 440 } 202 441 203 442 static int ··· 464 225 const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = { 465 226 .volume_put = sof_ipc4_volume_put, 466 227 .volume_get = sof_ipc4_volume_get, 228 + .bytes_put = sof_ipc4_bytes_put, 229 + .bytes_get = sof_ipc4_bytes_get, 230 + .bytes_ext_put = sof_ipc4_bytes_ext_put, 231 + .bytes_ext_get = sof_ipc4_bytes_ext_get, 232 + .bytes_ext_volatile_get = sof_ipc4_bytes_ext_volatile_get, 467 233 .widget_kcontrol_setup = sof_ipc4_widget_kcontrol_setup, 468 234 .set_up_volume_table = sof_ipc4_set_up_volume_table, 469 235 };
+67
sound/soc/sof/ipc4-topology.c
··· 1506 1506 return 0; 1507 1507 } 1508 1508 1509 + static int sof_ipc4_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1510 + { 1511 + struct sof_ipc4_control_data *control_data; 1512 + struct sof_ipc4_msg *msg; 1513 + int ret; 1514 + 1515 + if (scontrol->max_size < (sizeof(*control_data) + sizeof(struct sof_abi_hdr))) { 1516 + dev_err(sdev->dev, "insufficient size for a bytes control %s: %zu.\n", 1517 + scontrol->name, scontrol->max_size); 1518 + return -EINVAL; 1519 + } 1520 + 1521 + if (scontrol->priv_size > scontrol->max_size - sizeof(*control_data)) { 1522 + dev_err(sdev->dev, "scontrol %s bytes data size %zu exceeds max %zu.\n", 1523 + scontrol->name, scontrol->priv_size, 1524 + scontrol->max_size - sizeof(*control_data)); 1525 + return -EINVAL; 1526 + } 1527 + 1528 + scontrol->size = sizeof(struct sof_ipc4_control_data) + scontrol->priv_size; 1529 + 1530 + scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); 1531 + if (!scontrol->ipc_control_data) 1532 + return -ENOMEM; 1533 + 1534 + control_data = scontrol->ipc_control_data; 1535 + control_data->index = scontrol->index; 1536 + if (scontrol->priv_size > 0) { 1537 + memcpy(control_data->data, scontrol->priv, scontrol->priv_size); 1538 + kfree(scontrol->priv); 1539 + scontrol->priv = NULL; 1540 + 1541 + if (control_data->data->magic != SOF_IPC4_ABI_MAGIC) { 1542 + dev_err(sdev->dev, "Wrong ABI magic (%#x) for control: %s\n", 1543 + control_data->data->magic, scontrol->name); 1544 + ret = -EINVAL; 1545 + goto err; 1546 + } 1547 + 1548 + /* TODO: check the ABI version */ 1549 + 1550 + if (control_data->data->size + sizeof(struct sof_abi_hdr) != 1551 + scontrol->priv_size) { 1552 + dev_err(sdev->dev, "Control %s conflict in bytes %zu vs. priv size %zu.\n", 1553 + scontrol->name, 1554 + control_data->data->size + sizeof(struct sof_abi_hdr), 1555 + scontrol->priv_size); 1556 + ret = -EINVAL; 1557 + goto err; 1558 + } 1559 + } 1560 + 1561 + msg = &control_data->msg; 1562 + msg->primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_LARGE_CONFIG_SET); 1563 + msg->primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); 1564 + msg->primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); 1565 + 1566 + return 0; 1567 + 1568 + err: 1569 + kfree(scontrol->ipc_control_data); 1570 + scontrol->ipc_control_data = NULL; 1571 + return ret; 1572 + } 1573 + 1509 1574 static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol) 1510 1575 { 1511 1576 switch (scontrol->info_type) { ··· 1578 1513 case SND_SOC_TPLG_CTL_VOLSW_SX: 1579 1514 case SND_SOC_TPLG_CTL_VOLSW_XR_SX: 1580 1515 return sof_ipc4_control_load_volume(sdev, scontrol); 1516 + case SND_SOC_TPLG_CTL_BYTES: 1517 + return sof_ipc4_control_load_bytes(sdev, scontrol); 1581 1518 default: 1582 1519 break; 1583 1520 }