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