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 #include <linux/pm_runtime.h> 24 25 static int soc_compr_components_open(struct snd_compr_stream *cstream, 26 struct snd_soc_component **last) 27 { 28 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 29 struct snd_soc_component *component; 30 int i, ret; 31 32 for_each_rtd_components(rtd, i, component) { 33 if (!component->driver->compress_ops || 34 !component->driver->compress_ops->open) 35 continue; 36 37 ret = component->driver->compress_ops->open(component, cstream); 38 if (ret < 0) { 39 dev_err(component->dev, 40 "Compress ASoC: can't open platform %s: %d\n", 41 component->name, ret); 42 43 *last = component; 44 return ret; 45 } 46 } 47 48 *last = NULL; 49 return 0; 50 } 51 52 static int soc_compr_components_free(struct snd_compr_stream *cstream, 53 struct snd_soc_component *last) 54 { 55 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 56 struct snd_soc_component *component; 57 int i; 58 59 for_each_rtd_components(rtd, i, component) { 60 if (component == last) 61 break; 62 63 if (!component->driver->compress_ops || 64 !component->driver->compress_ops->free) 65 continue; 66 67 component->driver->compress_ops->free(component, cstream); 68 } 69 70 return 0; 71 } 72 73 static int soc_compr_open(struct snd_compr_stream *cstream) 74 { 75 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 76 struct snd_soc_component *component = NULL; 77 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 78 int ret; 79 80 ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream); 81 if (ret < 0) 82 goto pm_err; 83 84 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 85 86 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 87 if (ret < 0) 88 goto out; 89 90 ret = soc_compr_components_open(cstream, &component); 91 if (ret < 0) 92 goto machine_err; 93 94 ret = snd_soc_link_compr_startup(cstream); 95 if (ret < 0) 96 goto machine_err; 97 98 snd_soc_runtime_activate(rtd, cstream->direction); 99 100 mutex_unlock(&rtd->card->pcm_mutex); 101 102 return 0; 103 104 machine_err: 105 soc_compr_components_free(cstream, component); 106 107 snd_soc_dai_compr_shutdown(cpu_dai, cstream); 108 out: 109 mutex_unlock(&rtd->card->pcm_mutex); 110 pm_err: 111 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 1); 112 113 return ret; 114 } 115 116 static int soc_compr_open_fe(struct snd_compr_stream *cstream) 117 { 118 struct snd_soc_pcm_runtime *fe = cstream->private_data; 119 struct snd_pcm_substream *fe_substream = 120 fe->pcm->streams[cstream->direction].substream; 121 struct snd_soc_component *component; 122 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 123 struct snd_soc_dpcm *dpcm; 124 struct snd_soc_dapm_widget_list *list; 125 int stream; 126 int ret; 127 128 if (cstream->direction == SND_COMPRESS_PLAYBACK) 129 stream = SNDRV_PCM_STREAM_PLAYBACK; 130 else 131 stream = SNDRV_PCM_STREAM_CAPTURE; 132 133 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 134 fe->dpcm[stream].runtime = fe_substream->runtime; 135 136 ret = dpcm_path_get(fe, stream, &list); 137 if (ret < 0) 138 goto be_err; 139 else if (ret == 0) 140 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n", 141 fe->dai_link->name, stream ? "capture" : "playback"); 142 /* calculate valid and active FE <-> BE dpcms */ 143 dpcm_process_paths(fe, stream, &list, 1); 144 fe->dpcm[stream].runtime = fe_substream->runtime; 145 146 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 147 148 ret = dpcm_be_dai_startup(fe, stream); 149 if (ret < 0) { 150 /* clean up all links */ 151 for_each_dpcm_be(fe, stream, dpcm) 152 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 153 154 dpcm_be_disconnect(fe, stream); 155 fe->dpcm[stream].runtime = NULL; 156 goto out; 157 } 158 159 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 160 if (ret < 0) 161 goto out; 162 163 ret = soc_compr_components_open(cstream, &component); 164 if (ret < 0) 165 goto open_err; 166 167 ret = snd_soc_link_compr_startup(cstream); 168 if (ret < 0) 169 goto machine_err; 170 171 dpcm_clear_pending_state(fe, stream); 172 dpcm_path_put(&list); 173 174 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; 175 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 176 177 snd_soc_runtime_activate(fe, stream); 178 179 mutex_unlock(&fe->card->mutex); 180 181 return 0; 182 183 machine_err: 184 soc_compr_components_free(cstream, component); 185 open_err: 186 snd_soc_dai_compr_shutdown(cpu_dai, cstream); 187 out: 188 dpcm_path_put(&list); 189 be_err: 190 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 191 mutex_unlock(&fe->card->mutex); 192 return ret; 193 } 194 195 static int soc_compr_free(struct snd_compr_stream *cstream) 196 { 197 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 198 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 199 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 200 int stream; 201 202 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 203 204 if (cstream->direction == SND_COMPRESS_PLAYBACK) 205 stream = SNDRV_PCM_STREAM_PLAYBACK; 206 else 207 stream = SNDRV_PCM_STREAM_CAPTURE; 208 209 snd_soc_runtime_deactivate(rtd, stream); 210 211 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 212 213 if (!snd_soc_dai_active(cpu_dai)) 214 cpu_dai->rate = 0; 215 216 if (!snd_soc_dai_active(codec_dai)) 217 codec_dai->rate = 0; 218 219 snd_soc_link_compr_shutdown(cstream); 220 221 soc_compr_components_free(cstream, NULL); 222 223 snd_soc_dai_compr_shutdown(cpu_dai, cstream); 224 225 snd_soc_dapm_stream_stop(rtd, stream); 226 227 mutex_unlock(&rtd->card->pcm_mutex); 228 229 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 0); 230 231 return 0; 232 } 233 234 static int soc_compr_free_fe(struct snd_compr_stream *cstream) 235 { 236 struct snd_soc_pcm_runtime *fe = cstream->private_data; 237 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 238 struct snd_soc_dpcm *dpcm; 239 int stream, ret; 240 241 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 242 243 if (cstream->direction == SND_COMPRESS_PLAYBACK) 244 stream = SNDRV_PCM_STREAM_PLAYBACK; 245 else 246 stream = SNDRV_PCM_STREAM_CAPTURE; 247 248 snd_soc_runtime_deactivate(fe, stream); 249 250 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 251 252 ret = dpcm_be_dai_hw_free(fe, stream); 253 if (ret < 0) 254 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret); 255 256 ret = dpcm_be_dai_shutdown(fe, stream); 257 258 /* mark FE's links ready to prune */ 259 for_each_dpcm_be(fe, stream, dpcm) 260 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 261 262 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 263 264 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; 265 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 266 267 dpcm_be_disconnect(fe, stream); 268 269 fe->dpcm[stream].runtime = NULL; 270 271 snd_soc_link_compr_shutdown(cstream); 272 273 soc_compr_components_free(cstream, NULL); 274 275 snd_soc_dai_compr_shutdown(cpu_dai, cstream); 276 277 mutex_unlock(&fe->card->mutex); 278 return 0; 279 } 280 281 static int soc_compr_components_trigger(struct snd_compr_stream *cstream, 282 int cmd) 283 { 284 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 285 struct snd_soc_component *component; 286 int i, ret; 287 288 for_each_rtd_components(rtd, i, component) { 289 if (!component->driver->compress_ops || 290 !component->driver->compress_ops->trigger) 291 continue; 292 293 ret = component->driver->compress_ops->trigger( 294 component, cstream, cmd); 295 if (ret < 0) 296 return ret; 297 } 298 299 return 0; 300 } 301 302 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 303 { 304 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 305 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 306 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 307 int ret; 308 309 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 310 311 ret = soc_compr_components_trigger(cstream, cmd); 312 if (ret < 0) 313 goto out; 314 315 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 316 if (ret < 0) 317 goto out; 318 319 switch (cmd) { 320 case SNDRV_PCM_TRIGGER_START: 321 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction); 322 break; 323 case SNDRV_PCM_TRIGGER_STOP: 324 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction); 325 break; 326 } 327 328 out: 329 mutex_unlock(&rtd->card->pcm_mutex); 330 return ret; 331 } 332 333 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 334 { 335 struct snd_soc_pcm_runtime *fe = cstream->private_data; 336 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 337 int ret, stream; 338 339 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || 340 cmd == SND_COMPR_TRIGGER_DRAIN) 341 return soc_compr_components_trigger(cstream, cmd); 342 343 if (cstream->direction == SND_COMPRESS_PLAYBACK) 344 stream = SNDRV_PCM_STREAM_PLAYBACK; 345 else 346 stream = SNDRV_PCM_STREAM_CAPTURE; 347 348 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 349 350 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 351 if (ret < 0) 352 goto out; 353 354 ret = soc_compr_components_trigger(cstream, cmd); 355 if (ret < 0) 356 goto out; 357 358 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 359 360 ret = dpcm_be_dai_trigger(fe, stream, cmd); 361 362 switch (cmd) { 363 case SNDRV_PCM_TRIGGER_START: 364 case SNDRV_PCM_TRIGGER_RESUME: 365 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 366 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; 367 break; 368 case SNDRV_PCM_TRIGGER_STOP: 369 case SNDRV_PCM_TRIGGER_SUSPEND: 370 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; 371 break; 372 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 373 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; 374 break; 375 } 376 377 out: 378 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 379 mutex_unlock(&fe->card->mutex); 380 return ret; 381 } 382 383 static int soc_compr_components_set_params(struct snd_compr_stream *cstream, 384 struct snd_compr_params *params) 385 { 386 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 387 struct snd_soc_component *component; 388 int i, ret; 389 390 for_each_rtd_components(rtd, i, component) { 391 if (!component->driver->compress_ops || 392 !component->driver->compress_ops->set_params) 393 continue; 394 395 ret = component->driver->compress_ops->set_params( 396 component, cstream, params); 397 if (ret < 0) 398 return ret; 399 } 400 401 return 0; 402 } 403 404 static int soc_compr_set_params(struct snd_compr_stream *cstream, 405 struct snd_compr_params *params) 406 { 407 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 408 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 409 int ret; 410 411 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 412 413 /* 414 * First we call set_params for the CPU DAI, then the component 415 * driver this should configure the SoC side. If the machine has 416 * compressed ops then we call that as well. The expectation is 417 * that these callbacks will configure everything for this compress 418 * path, like configuring a PCM port for a CODEC. 419 */ 420 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 421 if (ret < 0) 422 goto err; 423 424 ret = soc_compr_components_set_params(cstream, params); 425 if (ret < 0) 426 goto err; 427 428 ret = snd_soc_link_compr_set_params(cstream); 429 if (ret < 0) 430 goto err; 431 432 if (cstream->direction == SND_COMPRESS_PLAYBACK) 433 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, 434 SND_SOC_DAPM_STREAM_START); 435 else 436 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE, 437 SND_SOC_DAPM_STREAM_START); 438 439 /* cancel any delayed stream shutdown that is pending */ 440 rtd->pop_wait = 0; 441 mutex_unlock(&rtd->card->pcm_mutex); 442 443 cancel_delayed_work_sync(&rtd->delayed_work); 444 445 return 0; 446 447 err: 448 mutex_unlock(&rtd->card->pcm_mutex); 449 return ret; 450 } 451 452 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 453 struct snd_compr_params *params) 454 { 455 struct snd_soc_pcm_runtime *fe = cstream->private_data; 456 struct snd_pcm_substream *fe_substream = 457 fe->pcm->streams[cstream->direction].substream; 458 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 459 int ret, stream; 460 461 if (cstream->direction == SND_COMPRESS_PLAYBACK) 462 stream = SNDRV_PCM_STREAM_PLAYBACK; 463 else 464 stream = SNDRV_PCM_STREAM_CAPTURE; 465 466 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 467 468 /* 469 * Create an empty hw_params for the BE as the machine driver must 470 * fix this up to match DSP decoder and ASRC configuration. 471 * I.e. machine driver fixup for compressed BE is mandatory. 472 */ 473 memset(&fe->dpcm[fe_substream->stream].hw_params, 0, 474 sizeof(struct snd_pcm_hw_params)); 475 476 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 477 478 ret = dpcm_be_dai_hw_params(fe, stream); 479 if (ret < 0) 480 goto out; 481 482 ret = dpcm_be_dai_prepare(fe, stream); 483 if (ret < 0) 484 goto out; 485 486 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 487 if (ret < 0) 488 goto out; 489 490 ret = soc_compr_components_set_params(cstream, params); 491 if (ret < 0) 492 goto out; 493 494 ret = snd_soc_link_compr_set_params(cstream); 495 if (ret < 0) 496 goto out; 497 498 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 499 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 500 501 out: 502 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 503 mutex_unlock(&fe->card->mutex); 504 return ret; 505 } 506 507 static int soc_compr_get_params(struct snd_compr_stream *cstream, 508 struct snd_codec *params) 509 { 510 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 511 struct snd_soc_component *component; 512 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 513 int i, ret = 0; 514 515 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 516 517 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); 518 if (ret < 0) 519 goto err; 520 521 for_each_rtd_components(rtd, i, component) { 522 if (!component->driver->compress_ops || 523 !component->driver->compress_ops->get_params) 524 continue; 525 526 ret = component->driver->compress_ops->get_params( 527 component, cstream, params); 528 break; 529 } 530 531 err: 532 mutex_unlock(&rtd->card->pcm_mutex); 533 return ret; 534 } 535 536 static int soc_compr_get_caps(struct snd_compr_stream *cstream, 537 struct snd_compr_caps *caps) 538 { 539 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 540 struct snd_soc_component *component; 541 int i, ret = 0; 542 543 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 544 545 for_each_rtd_components(rtd, i, component) { 546 if (!component->driver->compress_ops || 547 !component->driver->compress_ops->get_caps) 548 continue; 549 550 ret = component->driver->compress_ops->get_caps( 551 component, cstream, caps); 552 break; 553 } 554 555 mutex_unlock(&rtd->card->pcm_mutex); 556 return ret; 557 } 558 559 static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, 560 struct snd_compr_codec_caps *codec) 561 { 562 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 563 struct snd_soc_component *component; 564 int i, ret = 0; 565 566 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 567 568 for_each_rtd_components(rtd, i, component) { 569 if (!component->driver->compress_ops || 570 !component->driver->compress_ops->get_codec_caps) 571 continue; 572 573 ret = component->driver->compress_ops->get_codec_caps( 574 component, cstream, codec); 575 break; 576 } 577 578 mutex_unlock(&rtd->card->pcm_mutex); 579 return ret; 580 } 581 582 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 583 { 584 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 585 struct snd_soc_component *component; 586 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 587 int i, ret = 0; 588 589 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 590 591 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); 592 if (ret < 0) 593 goto err; 594 595 for_each_rtd_components(rtd, i, component) { 596 if (!component->driver->compress_ops || 597 !component->driver->compress_ops->ack) 598 continue; 599 600 ret = component->driver->compress_ops->ack( 601 component, cstream, bytes); 602 if (ret < 0) 603 goto err; 604 } 605 606 err: 607 mutex_unlock(&rtd->card->pcm_mutex); 608 return ret; 609 } 610 611 static int soc_compr_pointer(struct snd_compr_stream *cstream, 612 struct snd_compr_tstamp *tstamp) 613 { 614 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 615 struct snd_soc_component *component; 616 int i, ret = 0; 617 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 618 619 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 620 621 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); 622 if (ret < 0) 623 goto out; 624 625 for_each_rtd_components(rtd, i, component) { 626 if (!component->driver->compress_ops || 627 !component->driver->compress_ops->pointer) 628 continue; 629 630 ret = component->driver->compress_ops->pointer( 631 component, cstream, tstamp); 632 break; 633 } 634 out: 635 mutex_unlock(&rtd->card->pcm_mutex); 636 return ret; 637 } 638 639 static int soc_compr_copy(struct snd_compr_stream *cstream, 640 char __user *buf, size_t count) 641 { 642 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 643 struct snd_soc_component *component; 644 int i, ret = 0; 645 646 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 647 648 for_each_rtd_components(rtd, i, component) { 649 if (!component->driver->compress_ops || 650 !component->driver->compress_ops->copy) 651 continue; 652 653 ret = component->driver->compress_ops->copy( 654 component, cstream, buf, count); 655 break; 656 } 657 658 mutex_unlock(&rtd->card->pcm_mutex); 659 return ret; 660 } 661 662 static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 663 struct snd_compr_metadata *metadata) 664 { 665 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 666 struct snd_soc_component *component; 667 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 668 int i, ret; 669 670 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); 671 if (ret < 0) 672 return ret; 673 674 for_each_rtd_components(rtd, i, component) { 675 if (!component->driver->compress_ops || 676 !component->driver->compress_ops->set_metadata) 677 continue; 678 679 ret = component->driver->compress_ops->set_metadata( 680 component, cstream, metadata); 681 if (ret < 0) 682 return ret; 683 } 684 685 return 0; 686 } 687 688 static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 689 struct snd_compr_metadata *metadata) 690 { 691 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 692 struct snd_soc_component *component; 693 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 694 int i, ret; 695 696 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); 697 if (ret < 0) 698 return ret; 699 700 for_each_rtd_components(rtd, i, component) { 701 if (!component->driver->compress_ops || 702 !component->driver->compress_ops->get_metadata) 703 continue; 704 705 return component->driver->compress_ops->get_metadata( 706 component, cstream, metadata); 707 } 708 709 return 0; 710 } 711 712 /* ASoC Compress operations */ 713 static struct snd_compr_ops soc_compr_ops = { 714 .open = soc_compr_open, 715 .free = soc_compr_free, 716 .set_params = soc_compr_set_params, 717 .set_metadata = soc_compr_set_metadata, 718 .get_metadata = soc_compr_get_metadata, 719 .get_params = soc_compr_get_params, 720 .trigger = soc_compr_trigger, 721 .pointer = soc_compr_pointer, 722 .ack = soc_compr_ack, 723 .get_caps = soc_compr_get_caps, 724 .get_codec_caps = soc_compr_get_codec_caps 725 }; 726 727 /* ASoC Dynamic Compress operations */ 728 static struct snd_compr_ops soc_compr_dyn_ops = { 729 .open = soc_compr_open_fe, 730 .free = soc_compr_free_fe, 731 .set_params = soc_compr_set_params_fe, 732 .get_params = soc_compr_get_params, 733 .set_metadata = soc_compr_set_metadata, 734 .get_metadata = soc_compr_get_metadata, 735 .trigger = soc_compr_trigger_fe, 736 .pointer = soc_compr_pointer, 737 .ack = soc_compr_ack, 738 .get_caps = soc_compr_get_caps, 739 .get_codec_caps = soc_compr_get_codec_caps 740 }; 741 742 /** 743 * snd_soc_new_compress - create a new compress. 744 * 745 * @rtd: The runtime for which we will create compress 746 * @num: the device index number (zero based - shared with normal PCMs) 747 * 748 * Return: 0 for success, else error. 749 */ 750 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 751 { 752 struct snd_soc_component *component; 753 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 754 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 755 struct snd_compr *compr; 756 struct snd_pcm *be_pcm; 757 char new_name[64]; 758 int ret = 0, direction = 0; 759 int playback = 0, capture = 0; 760 int i; 761 762 if (rtd->num_cpus > 1 || 763 rtd->num_codecs > 1) { 764 dev_err(rtd->card->dev, 765 "Compress ASoC: Multi CPU/Codec not supported\n"); 766 return -EINVAL; 767 } 768 769 /* check client and interface hw capabilities */ 770 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 771 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 772 playback = 1; 773 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 774 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 775 capture = 1; 776 777 /* 778 * Compress devices are unidirectional so only one of the directions 779 * should be set, check for that (xor) 780 */ 781 if (playback + capture != 1) { 782 dev_err(rtd->card->dev, 783 "Compress ASoC: Invalid direction for P %d, C %d\n", 784 playback, capture); 785 return -EINVAL; 786 } 787 788 if (playback) 789 direction = SND_COMPRESS_PLAYBACK; 790 else 791 direction = SND_COMPRESS_CAPTURE; 792 793 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 794 if (!compr) 795 return -ENOMEM; 796 797 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 798 GFP_KERNEL); 799 if (!compr->ops) 800 return -ENOMEM; 801 802 if (rtd->dai_link->dynamic) { 803 snprintf(new_name, sizeof(new_name), "(%s)", 804 rtd->dai_link->stream_name); 805 806 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 807 rtd->dai_link->dpcm_playback, 808 rtd->dai_link->dpcm_capture, &be_pcm); 809 if (ret < 0) { 810 dev_err(rtd->card->dev, 811 "Compress ASoC: can't create compressed for %s: %d\n", 812 rtd->dai_link->name, ret); 813 return ret; 814 } 815 816 rtd->pcm = be_pcm; 817 rtd->fe_compr = 1; 818 if (rtd->dai_link->dpcm_playback) 819 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 820 else if (rtd->dai_link->dpcm_capture) 821 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 822 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 823 } else { 824 snprintf(new_name, sizeof(new_name), "%s %s-%d", 825 rtd->dai_link->stream_name, codec_dai->name, num); 826 827 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 828 } 829 830 for_each_rtd_components(rtd, i, component) { 831 if (!component->driver->compress_ops || 832 !component->driver->compress_ops->copy) 833 continue; 834 835 compr->ops->copy = soc_compr_copy; 836 break; 837 } 838 839 mutex_init(&compr->lock); 840 ret = snd_compress_new(rtd->card->snd_card, num, direction, 841 new_name, compr); 842 if (ret < 0) { 843 component = asoc_rtd_to_codec(rtd, 0)->component; 844 dev_err(component->dev, 845 "Compress ASoC: can't create compress for codec %s: %d\n", 846 component->name, ret); 847 return ret; 848 } 849 850 /* DAPM dai link stream work */ 851 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 852 853 rtd->compr = compr; 854 compr->private_data = rtd; 855 856 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 857 codec_dai->name, cpu_dai->name); 858 859 return 0; 860 } 861 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 862