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 = snd_soc_rtd_to_cpu(rtd, 0); 61 struct snd_soc_dai *codec_dai = snd_soc_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->symmetric_rate = 0; 73 74 if (!snd_soc_dai_active(codec_dai)) 75 codec_dai->symmetric_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 = snd_soc_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 = snd_soc_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 = snd_soc_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 = snd_soc_rtd_to_codec(rtd, 0); 248 struct snd_soc_dai *cpu_dai = snd_soc_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 = snd_soc_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 = snd_soc_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 = snd_soc_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 snd_soc_dpcm_mutex_lock(fe); 389 ret = dpcm_be_dai_hw_params(fe, stream); 390 snd_soc_dpcm_mutex_unlock(fe); 391 if (ret < 0) 392 goto out; 393 394 snd_soc_dpcm_mutex_lock(fe); 395 ret = dpcm_be_dai_prepare(fe, stream); 396 snd_soc_dpcm_mutex_unlock(fe); 397 if (ret < 0) 398 goto out; 399 400 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 401 if (ret < 0) 402 goto out; 403 404 ret = snd_soc_component_compr_set_params(cstream, params); 405 if (ret < 0) 406 goto out; 407 408 ret = snd_soc_link_compr_set_params(cstream); 409 if (ret < 0) 410 goto out; 411 snd_soc_dpcm_mutex_lock(fe); 412 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 413 snd_soc_dpcm_mutex_unlock(fe); 414 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 415 416 out: 417 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 418 snd_soc_card_mutex_unlock(fe->card); 419 return ret; 420 } 421 422 static int soc_compr_get_params(struct snd_compr_stream *cstream, 423 struct snd_codec *params) 424 { 425 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 426 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 427 int ret = 0; 428 429 snd_soc_dpcm_mutex_lock(rtd); 430 431 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); 432 if (ret < 0) 433 goto err; 434 435 ret = snd_soc_component_compr_get_params(cstream, params); 436 err: 437 snd_soc_dpcm_mutex_unlock(rtd); 438 return ret; 439 } 440 441 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 442 { 443 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 444 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 445 int ret; 446 447 snd_soc_dpcm_mutex_lock(rtd); 448 449 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); 450 if (ret < 0) 451 goto err; 452 453 ret = snd_soc_component_compr_ack(cstream, bytes); 454 err: 455 snd_soc_dpcm_mutex_unlock(rtd); 456 return ret; 457 } 458 459 static int soc_compr_pointer(struct snd_compr_stream *cstream, 460 struct snd_compr_tstamp *tstamp) 461 { 462 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 463 int ret; 464 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 465 466 snd_soc_dpcm_mutex_lock(rtd); 467 468 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); 469 if (ret < 0) 470 goto out; 471 472 ret = snd_soc_component_compr_pointer(cstream, tstamp); 473 out: 474 snd_soc_dpcm_mutex_unlock(rtd); 475 return ret; 476 } 477 478 static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 479 struct snd_compr_metadata *metadata) 480 { 481 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 482 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 483 int ret; 484 485 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); 486 if (ret < 0) 487 return ret; 488 489 return snd_soc_component_compr_set_metadata(cstream, metadata); 490 } 491 492 static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 493 struct snd_compr_metadata *metadata) 494 { 495 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 496 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 497 int ret; 498 499 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); 500 if (ret < 0) 501 return ret; 502 503 return snd_soc_component_compr_get_metadata(cstream, metadata); 504 } 505 506 /* ASoC Compress operations */ 507 static struct snd_compr_ops soc_compr_ops = { 508 .open = soc_compr_open, 509 .free = soc_compr_free, 510 .set_params = soc_compr_set_params, 511 .set_metadata = soc_compr_set_metadata, 512 .get_metadata = soc_compr_get_metadata, 513 .get_params = soc_compr_get_params, 514 .trigger = soc_compr_trigger, 515 .pointer = soc_compr_pointer, 516 .ack = soc_compr_ack, 517 .get_caps = snd_soc_component_compr_get_caps, 518 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 519 }; 520 521 /* ASoC Dynamic Compress operations */ 522 static struct snd_compr_ops soc_compr_dyn_ops = { 523 .open = soc_compr_open_fe, 524 .free = soc_compr_free_fe, 525 .set_params = soc_compr_set_params_fe, 526 .get_params = soc_compr_get_params, 527 .set_metadata = soc_compr_set_metadata, 528 .get_metadata = soc_compr_get_metadata, 529 .trigger = soc_compr_trigger_fe, 530 .pointer = soc_compr_pointer, 531 .ack = soc_compr_ack, 532 .get_caps = snd_soc_component_compr_get_caps, 533 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 534 }; 535 536 /** 537 * snd_soc_new_compress - create a new compress. 538 * 539 * @rtd: The runtime for which we will create compress 540 * 541 * Return: 0 for success, else error. 542 */ 543 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd) 544 { 545 struct snd_soc_component *component; 546 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 547 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 548 struct snd_compr *compr; 549 struct snd_pcm *be_pcm; 550 char new_name[64]; 551 int ret = 0, direction = 0; 552 int playback = 0, capture = 0; 553 int i; 554 555 /* 556 * make sure these are same value, 557 * and then use these as equally 558 */ 559 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK); 560 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE); 561 562 if (rtd->dai_link->num_cpus > 1 || 563 rtd->dai_link->num_codecs > 1) { 564 dev_err(rtd->card->dev, 565 "Compress ASoC: Multi CPU/Codec not supported\n"); 566 return -EINVAL; 567 } 568 569 if (!codec_dai) { 570 dev_err(rtd->card->dev, "Missing codec\n"); 571 return -EINVAL; 572 } 573 574 /* check client and interface hw capabilities */ 575 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 576 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 577 playback = 1; 578 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 579 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 580 capture = 1; 581 582 /* 583 * Compress devices are unidirectional so only one of the directions 584 * should be set, check for that (xor) 585 */ 586 if (playback + capture != 1) { 587 dev_err(rtd->card->dev, 588 "Compress ASoC: Invalid direction for P %d, C %d\n", 589 playback, capture); 590 return -EINVAL; 591 } 592 593 if (playback) 594 direction = SND_COMPRESS_PLAYBACK; 595 else 596 direction = SND_COMPRESS_CAPTURE; 597 598 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 599 if (!compr) 600 return -ENOMEM; 601 602 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 603 GFP_KERNEL); 604 if (!compr->ops) 605 return -ENOMEM; 606 607 if (rtd->dai_link->dynamic) { 608 int playback = 1; 609 int capture = 1; 610 611 if (rtd->dai_link->capture_only) 612 playback = 0; 613 if (rtd->dai_link->playback_only) 614 capture = 0; 615 616 snprintf(new_name, sizeof(new_name), "(%s)", 617 rtd->dai_link->stream_name); 618 619 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, rtd->id, 620 playback, capture, &be_pcm); 621 if (ret < 0) { 622 dev_err(rtd->card->dev, 623 "Compress ASoC: can't create compressed for %s: %d\n", 624 rtd->dai_link->name, ret); 625 return ret; 626 } 627 628 /* inherit atomicity from DAI link */ 629 be_pcm->nonatomic = rtd->dai_link->nonatomic; 630 631 rtd->pcm = be_pcm; 632 rtd->fe_compr = 1; 633 if (playback) 634 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 635 if (capture) 636 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 637 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 638 } else { 639 snprintf(new_name, sizeof(new_name), "%s %s-%d", 640 rtd->dai_link->stream_name, codec_dai->name, rtd->id); 641 642 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 643 } 644 645 for_each_rtd_components(rtd, i, component) { 646 if (!component->driver->compress_ops || 647 !component->driver->compress_ops->copy) 648 continue; 649 650 compr->ops->copy = snd_soc_component_compr_copy; 651 break; 652 } 653 654 ret = snd_compress_new(rtd->card->snd_card, rtd->id, direction, 655 new_name, compr); 656 if (ret < 0) { 657 component = snd_soc_rtd_to_codec(rtd, 0)->component; 658 dev_err(component->dev, 659 "Compress ASoC: can't create compress for codec %s: %d\n", 660 component->name, ret); 661 return ret; 662 } 663 664 /* DAPM dai link stream work */ 665 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 666 667 rtd->compr = compr; 668 compr->private_data = rtd; 669 670 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 671 codec_dai->name, cpu_dai->name); 672 673 return 0; 674 } 675 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 676