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