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->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 = 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 * @num: the device index number (zero based - shared with normal PCMs) 541 * 542 * Return: 0 for success, else error. 543 */ 544 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 545 { 546 struct snd_soc_component *component; 547 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 548 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 549 struct snd_compr *compr; 550 struct snd_pcm *be_pcm; 551 char new_name[64]; 552 int ret = 0, direction = 0; 553 int playback = 0, capture = 0; 554 int i; 555 556 /* 557 * make sure these are same value, 558 * and then use these as equally 559 */ 560 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK); 561 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE); 562 563 if (rtd->dai_link->num_cpus > 1 || 564 rtd->dai_link->num_codecs > 1) { 565 dev_err(rtd->card->dev, 566 "Compress ASoC: Multi CPU/Codec not supported\n"); 567 return -EINVAL; 568 } 569 570 if (!codec_dai) { 571 dev_err(rtd->card->dev, "Missing codec\n"); 572 return -EINVAL; 573 } 574 575 /* check client and interface hw capabilities */ 576 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 577 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 578 playback = 1; 579 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 580 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 581 capture = 1; 582 583 /* 584 * Compress devices are unidirectional so only one of the directions 585 * should be set, check for that (xor) 586 */ 587 if (playback + capture != 1) { 588 dev_err(rtd->card->dev, 589 "Compress ASoC: Invalid direction for P %d, C %d\n", 590 playback, capture); 591 return -EINVAL; 592 } 593 594 if (playback) 595 direction = SND_COMPRESS_PLAYBACK; 596 else 597 direction = SND_COMPRESS_CAPTURE; 598 599 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 600 if (!compr) 601 return -ENOMEM; 602 603 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 604 GFP_KERNEL); 605 if (!compr->ops) 606 return -ENOMEM; 607 608 if (rtd->dai_link->dynamic) { 609 snprintf(new_name, sizeof(new_name), "(%s)", 610 rtd->dai_link->stream_name); 611 612 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 613 rtd->dai_link->dpcm_playback, 614 rtd->dai_link->dpcm_capture, &be_pcm); 615 if (ret < 0) { 616 dev_err(rtd->card->dev, 617 "Compress ASoC: can't create compressed for %s: %d\n", 618 rtd->dai_link->name, ret); 619 return ret; 620 } 621 622 /* inherit atomicity from DAI link */ 623 be_pcm->nonatomic = rtd->dai_link->nonatomic; 624 625 rtd->pcm = be_pcm; 626 rtd->fe_compr = 1; 627 if (rtd->dai_link->dpcm_playback) 628 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 629 if (rtd->dai_link->dpcm_capture) 630 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 631 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 632 } else { 633 snprintf(new_name, sizeof(new_name), "%s %s-%d", 634 rtd->dai_link->stream_name, codec_dai->name, num); 635 636 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 637 } 638 639 for_each_rtd_components(rtd, i, component) { 640 if (!component->driver->compress_ops || 641 !component->driver->compress_ops->copy) 642 continue; 643 644 compr->ops->copy = snd_soc_component_compr_copy; 645 break; 646 } 647 648 ret = snd_compress_new(rtd->card->snd_card, num, direction, 649 new_name, compr); 650 if (ret < 0) { 651 component = snd_soc_rtd_to_codec(rtd, 0)->component; 652 dev_err(component->dev, 653 "Compress ASoC: can't create compress for codec %s: %d\n", 654 component->name, ret); 655 return ret; 656 } 657 658 /* DAPM dai link stream work */ 659 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 660 661 rtd->compr = compr; 662 compr->private_data = rtd; 663 664 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 665 codec_dai->name, cpu_dai->name); 666 667 return 0; 668 } 669 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 670
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.