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 be_err: 197 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 198 snd_soc_card_mutex_unlock(fe->card); 199 return ret; 200 } 201 202 static int soc_compr_free_fe(struct snd_compr_stream *cstream) 203 { 204 struct snd_soc_pcm_runtime *fe = cstream->private_data; 205 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 206 struct snd_soc_dpcm *dpcm; 207 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 208 209 snd_soc_card_mutex_lock(fe->card); 210 211 snd_soc_dpcm_mutex_lock(fe); 212 snd_soc_runtime_deactivate(fe, stream); 213 214 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 215 216 dpcm_be_dai_hw_free(fe, stream); 217 218 dpcm_be_dai_shutdown(fe, stream); 219 220 /* mark FE's links ready to prune */ 221 for_each_dpcm_be(fe, stream, dpcm) 222 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 223 224 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 225 226 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; 227 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 228 229 dpcm_be_disconnect(fe, stream); 230 231 snd_soc_dpcm_mutex_unlock(fe); 232 233 snd_soc_link_compr_shutdown(cstream, 0); 234 235 snd_soc_compr_components_free(cstream, 0); 236 237 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0); 238 239 snd_soc_card_mutex_unlock(fe->card); 240 return 0; 241 } 242 243 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 244 { 245 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 246 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 247 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 248 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 249 int ret; 250 251 snd_soc_dpcm_mutex_lock(rtd); 252 253 ret = snd_soc_component_compr_trigger(cstream, cmd); 254 if (ret < 0) 255 goto out; 256 257 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 258 if (ret < 0) 259 goto out; 260 261 switch (cmd) { 262 case SNDRV_PCM_TRIGGER_START: 263 snd_soc_dai_digital_mute(codec_dai, 0, stream); 264 break; 265 case SNDRV_PCM_TRIGGER_STOP: 266 snd_soc_dai_digital_mute(codec_dai, 1, stream); 267 break; 268 } 269 270 out: 271 snd_soc_dpcm_mutex_unlock(rtd); 272 return ret; 273 } 274 275 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 276 { 277 struct snd_soc_pcm_runtime *fe = cstream->private_data; 278 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 279 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 280 int ret; 281 282 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || 283 cmd == SND_COMPR_TRIGGER_DRAIN) 284 return snd_soc_component_compr_trigger(cstream, cmd); 285 286 snd_soc_card_mutex_lock(fe->card); 287 288 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 289 if (ret < 0) 290 goto out; 291 292 ret = snd_soc_component_compr_trigger(cstream, cmd); 293 if (ret < 0) 294 goto out; 295 296 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 297 298 ret = dpcm_be_dai_trigger(fe, stream, cmd); 299 300 switch (cmd) { 301 case SNDRV_PCM_TRIGGER_START: 302 case SNDRV_PCM_TRIGGER_RESUME: 303 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 304 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; 305 break; 306 case SNDRV_PCM_TRIGGER_STOP: 307 case SNDRV_PCM_TRIGGER_SUSPEND: 308 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; 309 break; 310 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 311 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; 312 break; 313 } 314 315 out: 316 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 317 snd_soc_card_mutex_unlock(fe->card); 318 return ret; 319 } 320 321 static int soc_compr_set_params(struct snd_compr_stream *cstream, 322 struct snd_compr_params *params) 323 { 324 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 325 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 326 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 327 int ret; 328 329 snd_soc_dpcm_mutex_lock(rtd); 330 331 /* 332 * First we call set_params for the CPU DAI, then the component 333 * driver this should configure the SoC side. If the machine has 334 * compressed ops then we call that as well. The expectation is 335 * that these callbacks will configure everything for this compress 336 * path, like configuring a PCM port for a CODEC. 337 */ 338 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 339 if (ret < 0) 340 goto err; 341 342 ret = snd_soc_component_compr_set_params(cstream, params); 343 if (ret < 0) 344 goto err; 345 346 ret = snd_soc_link_compr_set_params(cstream); 347 if (ret < 0) 348 goto err; 349 350 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START); 351 352 /* cancel any delayed stream shutdown that is pending */ 353 rtd->pop_wait = 0; 354 snd_soc_dpcm_mutex_unlock(rtd); 355 356 cancel_delayed_work_sync(&rtd->delayed_work); 357 358 return 0; 359 360 err: 361 snd_soc_dpcm_mutex_unlock(rtd); 362 return ret; 363 } 364 365 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 366 struct snd_compr_params *params) 367 { 368 struct snd_soc_pcm_runtime *fe = cstream->private_data; 369 struct snd_pcm_substream *fe_substream = 370 fe->pcm->streams[cstream->direction].substream; 371 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 372 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 373 int ret; 374 375 snd_soc_card_mutex_lock(fe->card); 376 377 /* 378 * Create an empty hw_params for the BE as the machine driver must 379 * fix this up to match DSP decoder and ASRC configuration. 380 * I.e. machine driver fixup for compressed BE is mandatory. 381 */ 382 memset(&fe->dpcm[fe_substream->stream].hw_params, 0, 383 sizeof(struct snd_pcm_hw_params)); 384 385 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 386 387 ret = dpcm_be_dai_hw_params(fe, stream); 388 if (ret < 0) 389 goto out; 390 391 ret = dpcm_be_dai_prepare(fe, stream); 392 if (ret < 0) 393 goto out; 394 395 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 396 if (ret < 0) 397 goto out; 398 399 ret = snd_soc_component_compr_set_params(cstream, params); 400 if (ret < 0) 401 goto out; 402 403 ret = snd_soc_link_compr_set_params(cstream); 404 if (ret < 0) 405 goto out; 406 snd_soc_dpcm_mutex_lock(fe); 407 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 408 snd_soc_dpcm_mutex_unlock(fe); 409 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 410 411 out: 412 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 413 snd_soc_card_mutex_unlock(fe->card); 414 return ret; 415 } 416 417 static int soc_compr_get_params(struct snd_compr_stream *cstream, 418 struct snd_codec *params) 419 { 420 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 421 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 422 int ret = 0; 423 424 snd_soc_dpcm_mutex_lock(rtd); 425 426 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); 427 if (ret < 0) 428 goto err; 429 430 ret = snd_soc_component_compr_get_params(cstream, params); 431 err: 432 snd_soc_dpcm_mutex_unlock(rtd); 433 return ret; 434 } 435 436 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 437 { 438 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 439 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 440 int ret; 441 442 snd_soc_dpcm_mutex_lock(rtd); 443 444 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); 445 if (ret < 0) 446 goto err; 447 448 ret = snd_soc_component_compr_ack(cstream, bytes); 449 err: 450 snd_soc_dpcm_mutex_unlock(rtd); 451 return ret; 452 } 453 454 static int soc_compr_pointer(struct snd_compr_stream *cstream, 455 struct snd_compr_tstamp *tstamp) 456 { 457 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 458 int ret; 459 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 460 461 snd_soc_dpcm_mutex_lock(rtd); 462 463 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); 464 if (ret < 0) 465 goto out; 466 467 ret = snd_soc_component_compr_pointer(cstream, tstamp); 468 out: 469 snd_soc_dpcm_mutex_unlock(rtd); 470 return ret; 471 } 472 473 static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 474 struct snd_compr_metadata *metadata) 475 { 476 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 477 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 478 int ret; 479 480 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); 481 if (ret < 0) 482 return ret; 483 484 return snd_soc_component_compr_set_metadata(cstream, metadata); 485 } 486 487 static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 488 struct snd_compr_metadata *metadata) 489 { 490 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 491 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 492 int ret; 493 494 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); 495 if (ret < 0) 496 return ret; 497 498 return snd_soc_component_compr_get_metadata(cstream, metadata); 499 } 500 501 /* ASoC Compress operations */ 502 static struct snd_compr_ops soc_compr_ops = { 503 .open = soc_compr_open, 504 .free = soc_compr_free, 505 .set_params = soc_compr_set_params, 506 .set_metadata = soc_compr_set_metadata, 507 .get_metadata = soc_compr_get_metadata, 508 .get_params = soc_compr_get_params, 509 .trigger = soc_compr_trigger, 510 .pointer = soc_compr_pointer, 511 .ack = soc_compr_ack, 512 .get_caps = snd_soc_component_compr_get_caps, 513 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 514 }; 515 516 /* ASoC Dynamic Compress operations */ 517 static struct snd_compr_ops soc_compr_dyn_ops = { 518 .open = soc_compr_open_fe, 519 .free = soc_compr_free_fe, 520 .set_params = soc_compr_set_params_fe, 521 .get_params = soc_compr_get_params, 522 .set_metadata = soc_compr_set_metadata, 523 .get_metadata = soc_compr_get_metadata, 524 .trigger = soc_compr_trigger_fe, 525 .pointer = soc_compr_pointer, 526 .ack = soc_compr_ack, 527 .get_caps = snd_soc_component_compr_get_caps, 528 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 529 }; 530 531 /** 532 * snd_soc_new_compress - create a new compress. 533 * 534 * @rtd: The runtime for which we will create compress 535 * @num: the device index number (zero based - shared with normal PCMs) 536 * 537 * Return: 0 for success, else error. 538 */ 539 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 540 { 541 struct snd_soc_component *component; 542 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 543 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 544 struct snd_compr *compr; 545 struct snd_pcm *be_pcm; 546 char new_name[64]; 547 int ret = 0, direction = 0; 548 int playback = 0, capture = 0; 549 int i; 550 551 /* 552 * make sure these are same value, 553 * and then use these as equally 554 */ 555 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK); 556 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE); 557 558 if (rtd->dai_link->num_cpus > 1 || 559 rtd->dai_link->num_codecs > 1) { 560 dev_err(rtd->card->dev, 561 "Compress ASoC: Multi CPU/Codec not supported\n"); 562 return -EINVAL; 563 } 564 565 if (!codec_dai) { 566 dev_err(rtd->card->dev, "Missing codec\n"); 567 return -EINVAL; 568 } 569 570 /* check client and interface hw capabilities */ 571 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 572 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 573 playback = 1; 574 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 575 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 576 capture = 1; 577 578 /* 579 * Compress devices are unidirectional so only one of the directions 580 * should be set, check for that (xor) 581 */ 582 if (playback + capture != 1) { 583 dev_err(rtd->card->dev, 584 "Compress ASoC: Invalid direction for P %d, C %d\n", 585 playback, capture); 586 return -EINVAL; 587 } 588 589 if (playback) 590 direction = SND_COMPRESS_PLAYBACK; 591 else 592 direction = SND_COMPRESS_CAPTURE; 593 594 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 595 if (!compr) 596 return -ENOMEM; 597 598 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 599 GFP_KERNEL); 600 if (!compr->ops) 601 return -ENOMEM; 602 603 if (rtd->dai_link->dynamic) { 604 snprintf(new_name, sizeof(new_name), "(%s)", 605 rtd->dai_link->stream_name); 606 607 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 608 rtd->dai_link->dpcm_playback, 609 rtd->dai_link->dpcm_capture, &be_pcm); 610 if (ret < 0) { 611 dev_err(rtd->card->dev, 612 "Compress ASoC: can't create compressed for %s: %d\n", 613 rtd->dai_link->name, ret); 614 return ret; 615 } 616 617 /* inherit atomicity from DAI link */ 618 be_pcm->nonatomic = rtd->dai_link->nonatomic; 619 620 rtd->pcm = be_pcm; 621 rtd->fe_compr = 1; 622 if (rtd->dai_link->dpcm_playback) 623 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 624 if (rtd->dai_link->dpcm_capture) 625 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 626 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 627 } else { 628 snprintf(new_name, sizeof(new_name), "%s %s-%d", 629 rtd->dai_link->stream_name, codec_dai->name, num); 630 631 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 632 } 633 634 for_each_rtd_components(rtd, i, component) { 635 if (!component->driver->compress_ops || 636 !component->driver->compress_ops->copy) 637 continue; 638 639 compr->ops->copy = snd_soc_component_compr_copy; 640 break; 641 } 642 643 ret = snd_compress_new(rtd->card->snd_card, num, direction, 644 new_name, compr); 645 if (ret < 0) { 646 component = asoc_rtd_to_codec(rtd, 0)->component; 647 dev_err(component->dev, 648 "Compress ASoC: can't create compress for codec %s: %d\n", 649 component->name, ret); 650 return ret; 651 } 652 653 /* DAPM dai link stream work */ 654 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 655 656 rtd->compr = compr; 657 compr->private_data = rtd; 658 659 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 660 codec_dai->name, cpu_dai->name); 661 662 return 0; 663 } 664 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 665