1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // soc-compress.c -- ALSA SoC Compress 4 // 5 // Copyright (C) 2012 Intel Corp. 6 // 7 // Authors: Namarta Kohli <namartax.kohli@intel.com> 8 // Ramesh Babu K V <ramesh.babu@linux.intel.com> 9 // Vinod Koul <vinod.koul@linux.intel.com> 10 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/delay.h> 14 #include <linux/slab.h> 15 #include <linux/workqueue.h> 16 #include <sound/core.h> 17 #include <sound/compress_params.h> 18 #include <sound/compress_driver.h> 19 #include <sound/soc.h> 20 #include <sound/initval.h> 21 #include <sound/soc-dpcm.h> 22 #include <sound/soc-link.h> 23 24 static int snd_soc_compr_components_open(struct snd_compr_stream *cstream) 25 { 26 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 27 struct snd_soc_component *component; 28 int ret = 0; 29 int i; 30 31 for_each_rtd_components(rtd, i, component) { 32 ret = snd_soc_component_module_get_when_open(component, cstream); 33 if (ret < 0) 34 break; 35 36 ret = snd_soc_component_compr_open(component, cstream); 37 if (ret < 0) 38 break; 39 } 40 41 return ret; 42 } 43 44 static void snd_soc_compr_components_free(struct snd_compr_stream *cstream, 45 int rollback) 46 { 47 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 48 struct snd_soc_component *component; 49 int i; 50 51 for_each_rtd_components(rtd, i, component) { 52 snd_soc_component_compr_free(component, cstream, rollback); 53 snd_soc_component_module_put_when_close(component, cstream, rollback); 54 } 55 } 56 57 static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback) 58 { 59 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 60 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 61 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 62 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 63 64 snd_soc_dpcm_mutex_lock(rtd); 65 66 if (!rollback) 67 snd_soc_runtime_deactivate(rtd, stream); 68 69 snd_soc_dai_digital_mute(codec_dai, 1, stream); 70 71 if (!snd_soc_dai_active(cpu_dai)) 72 cpu_dai->rate = 0; 73 74 if (!snd_soc_dai_active(codec_dai)) 75 codec_dai->rate = 0; 76 77 snd_soc_link_compr_shutdown(cstream, rollback); 78 79 snd_soc_compr_components_free(cstream, rollback); 80 81 snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback); 82 83 if (!rollback) 84 snd_soc_dapm_stream_stop(rtd, stream); 85 86 snd_soc_dpcm_mutex_unlock(rtd); 87 88 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback); 89 90 return 0; 91 } 92 93 static int soc_compr_free(struct snd_compr_stream *cstream) 94 { 95 return soc_compr_clean(cstream, 0); 96 } 97 98 static int soc_compr_open(struct snd_compr_stream *cstream) 99 { 100 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 101 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 102 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 103 int ret; 104 105 ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream); 106 if (ret < 0) 107 goto err_no_lock; 108 109 snd_soc_dpcm_mutex_lock(rtd); 110 111 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 112 if (ret < 0) 113 goto err; 114 115 ret = snd_soc_compr_components_open(cstream); 116 if (ret < 0) 117 goto err; 118 119 ret = snd_soc_link_compr_startup(cstream); 120 if (ret < 0) 121 goto err; 122 123 snd_soc_runtime_activate(rtd, stream); 124 err: 125 snd_soc_dpcm_mutex_unlock(rtd); 126 err_no_lock: 127 if (ret < 0) 128 soc_compr_clean(cstream, 1); 129 130 return ret; 131 } 132 133 static int soc_compr_open_fe(struct snd_compr_stream *cstream) 134 { 135 struct snd_soc_pcm_runtime *fe = cstream->private_data; 136 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 137 struct snd_soc_dpcm *dpcm; 138 struct snd_soc_dapm_widget_list *list; 139 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 140 int ret; 141 142 snd_soc_card_mutex_lock(fe->card); 143 144 ret = dpcm_path_get(fe, stream, &list); 145 if (ret < 0) 146 goto be_err; 147 148 snd_soc_dpcm_mutex_lock(fe); 149 150 /* calculate valid and active FE <-> BE dpcms */ 151 dpcm_process_paths(fe, stream, &list, 1); 152 153 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 154 155 ret = dpcm_be_dai_startup(fe, stream); 156 if (ret < 0) { 157 /* clean up all links */ 158 for_each_dpcm_be(fe, stream, dpcm) 159 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 160 161 dpcm_be_disconnect(fe, stream); 162 goto out; 163 } 164 165 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 166 if (ret < 0) 167 goto out; 168 169 ret = snd_soc_compr_components_open(cstream); 170 if (ret < 0) 171 goto open_err; 172 173 ret = snd_soc_link_compr_startup(cstream); 174 if (ret < 0) 175 goto machine_err; 176 177 dpcm_clear_pending_state(fe, stream); 178 dpcm_path_put(&list); 179 180 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; 181 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 182 183 snd_soc_runtime_activate(fe, stream); 184 snd_soc_dpcm_mutex_unlock(fe); 185 186 snd_soc_card_mutex_unlock(fe->card); 187 188 return 0; 189 190 machine_err: 191 snd_soc_compr_components_free(cstream, 1); 192 open_err: 193 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1); 194 out: 195 dpcm_path_put(&list); 196 snd_soc_dpcm_mutex_unlock(fe); 197 be_err: 198 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 199 snd_soc_card_mutex_unlock(fe->card); 200 return ret; 201 } 202 203 static int soc_compr_free_fe(struct snd_compr_stream *cstream) 204 { 205 struct snd_soc_pcm_runtime *fe = cstream->private_data; 206 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 207 struct snd_soc_dpcm *dpcm; 208 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 209 210 snd_soc_card_mutex_lock(fe->card); 211 212 snd_soc_dpcm_mutex_lock(fe); 213 snd_soc_runtime_deactivate(fe, stream); 214 215 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 216 217 dpcm_be_dai_hw_free(fe, stream); 218 219 dpcm_be_dai_shutdown(fe, stream); 220 221 /* mark FE's links ready to prune */ 222 for_each_dpcm_be(fe, stream, dpcm) 223 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 224 225 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 226 227 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; 228 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 229 230 dpcm_be_disconnect(fe, stream); 231 232 snd_soc_dpcm_mutex_unlock(fe); 233 234 snd_soc_link_compr_shutdown(cstream, 0); 235 236 snd_soc_compr_components_free(cstream, 0); 237 238 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0); 239 240 snd_soc_card_mutex_unlock(fe->card); 241 return 0; 242 } 243 244 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 245 { 246 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 247 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 248 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 249 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 250 int ret; 251 252 snd_soc_dpcm_mutex_lock(rtd); 253 254 ret = snd_soc_component_compr_trigger(cstream, cmd); 255 if (ret < 0) 256 goto out; 257 258 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 259 if (ret < 0) 260 goto out; 261 262 switch (cmd) { 263 case SNDRV_PCM_TRIGGER_START: 264 snd_soc_dai_digital_mute(codec_dai, 0, stream); 265 break; 266 case SNDRV_PCM_TRIGGER_STOP: 267 snd_soc_dai_digital_mute(codec_dai, 1, stream); 268 break; 269 } 270 271 out: 272 snd_soc_dpcm_mutex_unlock(rtd); 273 return ret; 274 } 275 276 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 277 { 278 struct snd_soc_pcm_runtime *fe = cstream->private_data; 279 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 280 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 281 int ret; 282 283 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || 284 cmd == SND_COMPR_TRIGGER_DRAIN) 285 return snd_soc_component_compr_trigger(cstream, cmd); 286 287 snd_soc_card_mutex_lock(fe->card); 288 289 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 290 if (ret < 0) 291 goto out; 292 293 ret = snd_soc_component_compr_trigger(cstream, cmd); 294 if (ret < 0) 295 goto out; 296 297 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 298 299 ret = dpcm_be_dai_trigger(fe, stream, cmd); 300 301 switch (cmd) { 302 case SNDRV_PCM_TRIGGER_START: 303 case SNDRV_PCM_TRIGGER_RESUME: 304 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 305 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; 306 break; 307 case SNDRV_PCM_TRIGGER_STOP: 308 case SNDRV_PCM_TRIGGER_SUSPEND: 309 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; 310 break; 311 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 312 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; 313 break; 314 } 315 316 out: 317 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 318 snd_soc_card_mutex_unlock(fe->card); 319 return ret; 320 } 321 322 static int soc_compr_set_params(struct snd_compr_stream *cstream, 323 struct snd_compr_params *params) 324 { 325 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 326 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 327 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 328 int ret; 329 330 snd_soc_dpcm_mutex_lock(rtd); 331 332 /* 333 * First we call set_params for the CPU DAI, then the component 334 * driver this should configure the SoC side. If the machine has 335 * compressed ops then we call that as well. The expectation is 336 * that these callbacks will configure everything for this compress 337 * path, like configuring a PCM port for a CODEC. 338 */ 339 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 340 if (ret < 0) 341 goto err; 342 343 ret = snd_soc_component_compr_set_params(cstream, params); 344 if (ret < 0) 345 goto err; 346 347 ret = snd_soc_link_compr_set_params(cstream); 348 if (ret < 0) 349 goto err; 350 351 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START); 352 353 /* cancel any delayed stream shutdown that is pending */ 354 rtd->pop_wait = 0; 355 snd_soc_dpcm_mutex_unlock(rtd); 356 357 cancel_delayed_work_sync(&rtd->delayed_work); 358 359 return 0; 360 361 err: 362 snd_soc_dpcm_mutex_unlock(rtd); 363 return ret; 364 } 365 366 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 367 struct snd_compr_params *params) 368 { 369 struct snd_soc_pcm_runtime *fe = cstream->private_data; 370 struct snd_pcm_substream *fe_substream = 371 fe->pcm->streams[cstream->direction].substream; 372 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 373 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 374 int ret; 375 376 snd_soc_card_mutex_lock(fe->card); 377 378 /* 379 * Create an empty hw_params for the BE as the machine driver must 380 * fix this up to match DSP decoder and ASRC configuration. 381 * I.e. machine driver fixup for compressed BE is mandatory. 382 */ 383 memset(&fe->dpcm[fe_substream->stream].hw_params, 0, 384 sizeof(struct snd_pcm_hw_params)); 385 386 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 387 388 ret = dpcm_be_dai_hw_params(fe, stream); 389 if (ret < 0) 390 goto out; 391 392 ret = dpcm_be_dai_prepare(fe, stream); 393 if (ret < 0) 394 goto out; 395 396 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 397 if (ret < 0) 398 goto out; 399 400 ret = snd_soc_component_compr_set_params(cstream, params); 401 if (ret < 0) 402 goto out; 403 404 ret = snd_soc_link_compr_set_params(cstream); 405 if (ret < 0) 406 goto out; 407 snd_soc_dpcm_mutex_lock(fe); 408 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 409 snd_soc_dpcm_mutex_unlock(fe); 410 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 411 412 out: 413 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 414 snd_soc_card_mutex_unlock(fe->card); 415 return ret; 416 } 417 418 static int soc_compr_get_params(struct snd_compr_stream *cstream, 419 struct snd_codec *params) 420 { 421 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 422 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 423 int ret = 0; 424 425 snd_soc_dpcm_mutex_lock(rtd); 426 427 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); 428 if (ret < 0) 429 goto err; 430 431 ret = snd_soc_component_compr_get_params(cstream, params); 432 err: 433 snd_soc_dpcm_mutex_unlock(rtd); 434 return ret; 435 } 436 437 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 438 { 439 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 440 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 441 int ret; 442 443 snd_soc_dpcm_mutex_lock(rtd); 444 445 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); 446 if (ret < 0) 447 goto err; 448 449 ret = snd_soc_component_compr_ack(cstream, bytes); 450 err: 451 snd_soc_dpcm_mutex_unlock(rtd); 452 return ret; 453 } 454 455 static int soc_compr_pointer(struct snd_compr_stream *cstream, 456 struct snd_compr_tstamp *tstamp) 457 { 458 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 459 int ret; 460 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 461 462 snd_soc_dpcm_mutex_lock(rtd); 463 464 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); 465 if (ret < 0) 466 goto out; 467 468 ret = snd_soc_component_compr_pointer(cstream, tstamp); 469 out: 470 snd_soc_dpcm_mutex_unlock(rtd); 471 return ret; 472 } 473 474 static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 475 struct snd_compr_metadata *metadata) 476 { 477 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 478 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 479 int ret; 480 481 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); 482 if (ret < 0) 483 return ret; 484 485 return snd_soc_component_compr_set_metadata(cstream, metadata); 486 } 487 488 static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 489 struct snd_compr_metadata *metadata) 490 { 491 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 492 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 493 int ret; 494 495 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); 496 if (ret < 0) 497 return ret; 498 499 return snd_soc_component_compr_get_metadata(cstream, metadata); 500 } 501 502 /* ASoC Compress operations */ 503 static struct snd_compr_ops soc_compr_ops = { 504 .open = soc_compr_open, 505 .free = soc_compr_free, 506 .set_params = soc_compr_set_params, 507 .set_metadata = soc_compr_set_metadata, 508 .get_metadata = soc_compr_get_metadata, 509 .get_params = soc_compr_get_params, 510 .trigger = soc_compr_trigger, 511 .pointer = soc_compr_pointer, 512 .ack = soc_compr_ack, 513 .get_caps = snd_soc_component_compr_get_caps, 514 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 515 }; 516 517 /* ASoC Dynamic Compress operations */ 518 static struct snd_compr_ops soc_compr_dyn_ops = { 519 .open = soc_compr_open_fe, 520 .free = soc_compr_free_fe, 521 .set_params = soc_compr_set_params_fe, 522 .get_params = soc_compr_get_params, 523 .set_metadata = soc_compr_set_metadata, 524 .get_metadata = soc_compr_get_metadata, 525 .trigger = soc_compr_trigger_fe, 526 .pointer = soc_compr_pointer, 527 .ack = soc_compr_ack, 528 .get_caps = snd_soc_component_compr_get_caps, 529 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 530 }; 531 532 /** 533 * snd_soc_new_compress - create a new compress. 534 * 535 * @rtd: The runtime for which we will create compress 536 * @num: the device index number (zero based - shared with normal PCMs) 537 * 538 * Return: 0 for success, else error. 539 */ 540 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 541 { 542 struct snd_soc_component *component; 543 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 544 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 545 struct snd_compr *compr; 546 struct snd_pcm *be_pcm; 547 char new_name[64]; 548 int ret = 0, direction = 0; 549 int playback = 0, capture = 0; 550 int i; 551 552 /* 553 * make sure these are same value, 554 * and then use these as equally 555 */ 556 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK); 557 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE); 558 559 if (rtd->dai_link->num_cpus > 1 || 560 rtd->dai_link->num_codecs > 1) { 561 dev_err(rtd->card->dev, 562 "Compress ASoC: Multi CPU/Codec not supported\n"); 563 return -EINVAL; 564 } 565 566 if (!codec_dai) { 567 dev_err(rtd->card->dev, "Missing codec\n"); 568 return -EINVAL; 569 } 570 571 /* check client and interface hw capabilities */ 572 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 573 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 574 playback = 1; 575 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 576 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 577 capture = 1; 578 579 /* 580 * Compress devices are unidirectional so only one of the directions 581 * should be set, check for that (xor) 582 */ 583 if (playback + capture != 1) { 584 dev_err(rtd->card->dev, 585 "Compress ASoC: Invalid direction for P %d, C %d\n", 586 playback, capture); 587 return -EINVAL; 588 } 589 590 if (playback) 591 direction = SND_COMPRESS_PLAYBACK; 592 else 593 direction = SND_COMPRESS_CAPTURE; 594 595 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 596 if (!compr) 597 return -ENOMEM; 598 599 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 600 GFP_KERNEL); 601 if (!compr->ops) 602 return -ENOMEM; 603 604 if (rtd->dai_link->dynamic) { 605 snprintf(new_name, sizeof(new_name), "(%s)", 606 rtd->dai_link->stream_name); 607 608 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 609 rtd->dai_link->dpcm_playback, 610 rtd->dai_link->dpcm_capture, &be_pcm); 611 if (ret < 0) { 612 dev_err(rtd->card->dev, 613 "Compress ASoC: can't create compressed for %s: %d\n", 614 rtd->dai_link->name, ret); 615 return ret; 616 } 617 618 /* inherit atomicity from DAI link */ 619 be_pcm->nonatomic = rtd->dai_link->nonatomic; 620 621 rtd->pcm = be_pcm; 622 rtd->fe_compr = 1; 623 if (rtd->dai_link->dpcm_playback) 624 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 625 if (rtd->dai_link->dpcm_capture) 626 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 627 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 628 } else { 629 snprintf(new_name, sizeof(new_name), "%s %s-%d", 630 rtd->dai_link->stream_name, codec_dai->name, num); 631 632 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 633 } 634 635 for_each_rtd_components(rtd, i, component) { 636 if (!component->driver->compress_ops || 637 !component->driver->compress_ops->copy) 638 continue; 639 640 compr->ops->copy = snd_soc_component_compr_copy; 641 break; 642 } 643 644 ret = snd_compress_new(rtd->card->snd_card, num, direction, 645 new_name, compr); 646 if (ret < 0) { 647 component = asoc_rtd_to_codec(rtd, 0)->component; 648 dev_err(component->dev, 649 "Compress ASoC: can't create compress for codec %s: %d\n", 650 component->name, ret); 651 return ret; 652 } 653 654 /* DAPM dai link stream work */ 655 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 656 657 rtd->compr = compr; 658 compr->private_data = rtd; 659 660 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 661 codec_dai->name, cpu_dai->name); 662 663 return 0; 664 } 665 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 666