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_clean(struct snd_compr_stream *cstream, int rollback) 26 { 27 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 28 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 29 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 30 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 31 32 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 33 34 if (!rollback) 35 snd_soc_runtime_deactivate(rtd, stream); 36 37 snd_soc_dai_digital_mute(codec_dai, 1, stream); 38 39 if (!snd_soc_dai_active(cpu_dai)) 40 cpu_dai->rate = 0; 41 42 if (!snd_soc_dai_active(codec_dai)) 43 codec_dai->rate = 0; 44 45 snd_soc_link_compr_shutdown(cstream, rollback); 46 47 snd_soc_component_compr_free(cstream, rollback); 48 49 snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback); 50 51 if (!rollback) 52 snd_soc_dapm_stream_stop(rtd, stream); 53 54 mutex_unlock(&rtd->card->pcm_mutex); 55 56 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback); 57 58 return 0; 59 } 60 61 static int soc_compr_free(struct snd_compr_stream *cstream) 62 { 63 return soc_compr_clean(cstream, 0); 64 } 65 66 static int soc_compr_open(struct snd_compr_stream *cstream) 67 { 68 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 69 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 70 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 71 int ret; 72 73 ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream); 74 if (ret < 0) 75 goto err_no_lock; 76 77 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 78 79 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 80 if (ret < 0) 81 goto err; 82 83 ret = snd_soc_component_compr_open(cstream); 84 if (ret < 0) 85 goto err; 86 87 ret = snd_soc_link_compr_startup(cstream); 88 if (ret < 0) 89 goto err; 90 91 snd_soc_runtime_activate(rtd, stream); 92 err: 93 mutex_unlock(&rtd->card->pcm_mutex); 94 err_no_lock: 95 if (ret < 0) 96 soc_compr_clean(cstream, 1); 97 98 return ret; 99 } 100 101 static int soc_compr_open_fe(struct snd_compr_stream *cstream) 102 { 103 struct snd_soc_pcm_runtime *fe = cstream->private_data; 104 struct snd_pcm_substream *fe_substream = 105 fe->pcm->streams[cstream->direction].substream; 106 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 107 struct snd_soc_dpcm *dpcm; 108 struct snd_soc_dapm_widget_list *list; 109 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 110 int ret; 111 112 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 113 fe->dpcm[stream].runtime = fe_substream->runtime; 114 115 ret = dpcm_path_get(fe, stream, &list); 116 if (ret < 0) 117 goto be_err; 118 else if (ret == 0) 119 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n", 120 fe->dai_link->name, stream ? "capture" : "playback"); 121 /* calculate valid and active FE <-> BE dpcms */ 122 dpcm_process_paths(fe, stream, &list, 1); 123 fe->dpcm[stream].runtime = fe_substream->runtime; 124 125 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 126 127 ret = dpcm_be_dai_startup(fe, stream); 128 if (ret < 0) { 129 /* clean up all links */ 130 for_each_dpcm_be(fe, stream, dpcm) 131 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 132 133 dpcm_be_disconnect(fe, stream); 134 fe->dpcm[stream].runtime = NULL; 135 goto out; 136 } 137 138 ret = snd_soc_dai_compr_startup(cpu_dai, cstream); 139 if (ret < 0) 140 goto out; 141 142 ret = snd_soc_component_compr_open(cstream); 143 if (ret < 0) 144 goto open_err; 145 146 ret = snd_soc_link_compr_startup(cstream); 147 if (ret < 0) 148 goto machine_err; 149 150 dpcm_clear_pending_state(fe, stream); 151 dpcm_path_put(&list); 152 153 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; 154 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 155 156 snd_soc_runtime_activate(fe, stream); 157 158 mutex_unlock(&fe->card->mutex); 159 160 return 0; 161 162 machine_err: 163 snd_soc_component_compr_free(cstream, 1); 164 open_err: 165 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1); 166 out: 167 dpcm_path_put(&list); 168 be_err: 169 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 170 mutex_unlock(&fe->card->mutex); 171 return ret; 172 } 173 174 static int soc_compr_free_fe(struct snd_compr_stream *cstream) 175 { 176 struct snd_soc_pcm_runtime *fe = cstream->private_data; 177 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 178 struct snd_soc_dpcm *dpcm; 179 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 180 int ret; 181 182 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 183 184 snd_soc_runtime_deactivate(fe, stream); 185 186 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 187 188 ret = dpcm_be_dai_hw_free(fe, stream); 189 if (ret < 0) 190 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret); 191 192 ret = dpcm_be_dai_shutdown(fe, stream); 193 194 /* mark FE's links ready to prune */ 195 for_each_dpcm_be(fe, stream, dpcm) 196 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; 197 198 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP); 199 200 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; 201 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 202 203 dpcm_be_disconnect(fe, stream); 204 205 fe->dpcm[stream].runtime = NULL; 206 207 snd_soc_link_compr_shutdown(cstream, 0); 208 209 snd_soc_component_compr_free(cstream, 0); 210 211 snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0); 212 213 mutex_unlock(&fe->card->mutex); 214 return 0; 215 } 216 217 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) 218 { 219 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 220 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 221 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 222 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 223 int ret; 224 225 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 226 227 ret = snd_soc_component_compr_trigger(cstream, cmd); 228 if (ret < 0) 229 goto out; 230 231 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 232 if (ret < 0) 233 goto out; 234 235 switch (cmd) { 236 case SNDRV_PCM_TRIGGER_START: 237 snd_soc_dai_digital_mute(codec_dai, 0, stream); 238 break; 239 case SNDRV_PCM_TRIGGER_STOP: 240 snd_soc_dai_digital_mute(codec_dai, 1, stream); 241 break; 242 } 243 244 out: 245 mutex_unlock(&rtd->card->pcm_mutex); 246 return ret; 247 } 248 249 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd) 250 { 251 struct snd_soc_pcm_runtime *fe = cstream->private_data; 252 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 253 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 254 int ret; 255 256 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN || 257 cmd == SND_COMPR_TRIGGER_DRAIN) 258 return snd_soc_component_compr_trigger(cstream, cmd); 259 260 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 261 262 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd); 263 if (ret < 0) 264 goto out; 265 266 ret = snd_soc_component_compr_trigger(cstream, cmd); 267 if (ret < 0) 268 goto out; 269 270 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 271 272 ret = dpcm_be_dai_trigger(fe, stream, cmd); 273 274 switch (cmd) { 275 case SNDRV_PCM_TRIGGER_START: 276 case SNDRV_PCM_TRIGGER_RESUME: 277 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 278 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START; 279 break; 280 case SNDRV_PCM_TRIGGER_STOP: 281 case SNDRV_PCM_TRIGGER_SUSPEND: 282 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; 283 break; 284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 285 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; 286 break; 287 } 288 289 out: 290 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 291 mutex_unlock(&fe->card->mutex); 292 return ret; 293 } 294 295 static int soc_compr_set_params(struct snd_compr_stream *cstream, 296 struct snd_compr_params *params) 297 { 298 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 299 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 300 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 301 int ret; 302 303 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 304 305 /* 306 * First we call set_params for the CPU DAI, then the component 307 * driver this should configure the SoC side. If the machine has 308 * compressed ops then we call that as well. The expectation is 309 * that these callbacks will configure everything for this compress 310 * path, like configuring a PCM port for a CODEC. 311 */ 312 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 313 if (ret < 0) 314 goto err; 315 316 ret = snd_soc_component_compr_set_params(cstream, params); 317 if (ret < 0) 318 goto err; 319 320 ret = snd_soc_link_compr_set_params(cstream); 321 if (ret < 0) 322 goto err; 323 324 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START); 325 326 /* cancel any delayed stream shutdown that is pending */ 327 rtd->pop_wait = 0; 328 mutex_unlock(&rtd->card->pcm_mutex); 329 330 cancel_delayed_work_sync(&rtd->delayed_work); 331 332 return 0; 333 334 err: 335 mutex_unlock(&rtd->card->pcm_mutex); 336 return ret; 337 } 338 339 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, 340 struct snd_compr_params *params) 341 { 342 struct snd_soc_pcm_runtime *fe = cstream->private_data; 343 struct snd_pcm_substream *fe_substream = 344 fe->pcm->streams[cstream->direction].substream; 345 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); 346 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ 347 int ret; 348 349 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); 350 351 /* 352 * Create an empty hw_params for the BE as the machine driver must 353 * fix this up to match DSP decoder and ASRC configuration. 354 * I.e. machine driver fixup for compressed BE is mandatory. 355 */ 356 memset(&fe->dpcm[fe_substream->stream].hw_params, 0, 357 sizeof(struct snd_pcm_hw_params)); 358 359 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; 360 361 ret = dpcm_be_dai_hw_params(fe, stream); 362 if (ret < 0) 363 goto out; 364 365 ret = dpcm_be_dai_prepare(fe, stream); 366 if (ret < 0) 367 goto out; 368 369 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params); 370 if (ret < 0) 371 goto out; 372 373 ret = snd_soc_component_compr_set_params(cstream, params); 374 if (ret < 0) 375 goto out; 376 377 ret = snd_soc_link_compr_set_params(cstream); 378 if (ret < 0) 379 goto out; 380 381 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START); 382 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; 383 384 out: 385 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; 386 mutex_unlock(&fe->card->mutex); 387 return ret; 388 } 389 390 static int soc_compr_get_params(struct snd_compr_stream *cstream, 391 struct snd_codec *params) 392 { 393 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 394 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 395 int ret = 0; 396 397 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 398 399 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params); 400 if (ret < 0) 401 goto err; 402 403 ret = snd_soc_component_compr_get_params(cstream, params); 404 err: 405 mutex_unlock(&rtd->card->pcm_mutex); 406 return ret; 407 } 408 409 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) 410 { 411 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 412 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 413 int ret; 414 415 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 416 417 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes); 418 if (ret < 0) 419 goto err; 420 421 ret = snd_soc_component_compr_ack(cstream, bytes); 422 err: 423 mutex_unlock(&rtd->card->pcm_mutex); 424 return ret; 425 } 426 427 static int soc_compr_pointer(struct snd_compr_stream *cstream, 428 struct snd_compr_tstamp *tstamp) 429 { 430 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 431 int ret; 432 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 433 434 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass); 435 436 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp); 437 if (ret < 0) 438 goto out; 439 440 ret = snd_soc_component_compr_pointer(cstream, tstamp); 441 out: 442 mutex_unlock(&rtd->card->pcm_mutex); 443 return ret; 444 } 445 446 static int soc_compr_set_metadata(struct snd_compr_stream *cstream, 447 struct snd_compr_metadata *metadata) 448 { 449 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 450 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 451 int ret; 452 453 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata); 454 if (ret < 0) 455 return ret; 456 457 return snd_soc_component_compr_set_metadata(cstream, metadata); 458 } 459 460 static int soc_compr_get_metadata(struct snd_compr_stream *cstream, 461 struct snd_compr_metadata *metadata) 462 { 463 struct snd_soc_pcm_runtime *rtd = cstream->private_data; 464 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 465 int ret; 466 467 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata); 468 if (ret < 0) 469 return ret; 470 471 return snd_soc_component_compr_get_metadata(cstream, metadata); 472 } 473 474 /* ASoC Compress operations */ 475 static struct snd_compr_ops soc_compr_ops = { 476 .open = soc_compr_open, 477 .free = soc_compr_free, 478 .set_params = soc_compr_set_params, 479 .set_metadata = soc_compr_set_metadata, 480 .get_metadata = soc_compr_get_metadata, 481 .get_params = soc_compr_get_params, 482 .trigger = soc_compr_trigger, 483 .pointer = soc_compr_pointer, 484 .ack = soc_compr_ack, 485 .get_caps = snd_soc_component_compr_get_caps, 486 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 487 }; 488 489 /* ASoC Dynamic Compress operations */ 490 static struct snd_compr_ops soc_compr_dyn_ops = { 491 .open = soc_compr_open_fe, 492 .free = soc_compr_free_fe, 493 .set_params = soc_compr_set_params_fe, 494 .get_params = soc_compr_get_params, 495 .set_metadata = soc_compr_set_metadata, 496 .get_metadata = soc_compr_get_metadata, 497 .trigger = soc_compr_trigger_fe, 498 .pointer = soc_compr_pointer, 499 .ack = soc_compr_ack, 500 .get_caps = snd_soc_component_compr_get_caps, 501 .get_codec_caps = snd_soc_component_compr_get_codec_caps, 502 }; 503 504 /** 505 * snd_soc_new_compress - create a new compress. 506 * 507 * @rtd: The runtime for which we will create compress 508 * @num: the device index number (zero based - shared with normal PCMs) 509 * 510 * Return: 0 for success, else error. 511 */ 512 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) 513 { 514 struct snd_soc_component *component; 515 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 516 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 517 struct snd_compr *compr; 518 struct snd_pcm *be_pcm; 519 char new_name[64]; 520 int ret = 0, direction = 0; 521 int playback = 0, capture = 0; 522 int i; 523 524 /* 525 * make sure these are same value, 526 * and then use these as equally 527 */ 528 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK); 529 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE); 530 531 if (rtd->num_cpus > 1 || 532 rtd->num_codecs > 1) { 533 dev_err(rtd->card->dev, 534 "Compress ASoC: Multi CPU/Codec not supported\n"); 535 return -EINVAL; 536 } 537 538 /* check client and interface hw capabilities */ 539 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) && 540 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK)) 541 playback = 1; 542 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) && 543 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE)) 544 capture = 1; 545 546 /* 547 * Compress devices are unidirectional so only one of the directions 548 * should be set, check for that (xor) 549 */ 550 if (playback + capture != 1) { 551 dev_err(rtd->card->dev, 552 "Compress ASoC: Invalid direction for P %d, C %d\n", 553 playback, capture); 554 return -EINVAL; 555 } 556 557 if (playback) 558 direction = SND_COMPRESS_PLAYBACK; 559 else 560 direction = SND_COMPRESS_CAPTURE; 561 562 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL); 563 if (!compr) 564 return -ENOMEM; 565 566 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops), 567 GFP_KERNEL); 568 if (!compr->ops) 569 return -ENOMEM; 570 571 if (rtd->dai_link->dynamic) { 572 snprintf(new_name, sizeof(new_name), "(%s)", 573 rtd->dai_link->stream_name); 574 575 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, 576 rtd->dai_link->dpcm_playback, 577 rtd->dai_link->dpcm_capture, &be_pcm); 578 if (ret < 0) { 579 dev_err(rtd->card->dev, 580 "Compress ASoC: can't create compressed for %s: %d\n", 581 rtd->dai_link->name, ret); 582 return ret; 583 } 584 585 rtd->pcm = be_pcm; 586 rtd->fe_compr = 1; 587 if (rtd->dai_link->dpcm_playback) 588 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd; 589 else if (rtd->dai_link->dpcm_capture) 590 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd; 591 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops)); 592 } else { 593 snprintf(new_name, sizeof(new_name), "%s %s-%d", 594 rtd->dai_link->stream_name, codec_dai->name, num); 595 596 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops)); 597 } 598 599 for_each_rtd_components(rtd, i, component) { 600 if (!component->driver->compress_ops || 601 !component->driver->compress_ops->copy) 602 continue; 603 604 compr->ops->copy = snd_soc_component_compr_copy; 605 break; 606 } 607 608 mutex_init(&compr->lock); 609 ret = snd_compress_new(rtd->card->snd_card, num, direction, 610 new_name, compr); 611 if (ret < 0) { 612 component = asoc_rtd_to_codec(rtd, 0)->component; 613 dev_err(component->dev, 614 "Compress ASoC: can't create compress for codec %s: %d\n", 615 component->name, ret); 616 return ret; 617 } 618 619 /* DAPM dai link stream work */ 620 rtd->close_delayed_work_func = snd_soc_close_delayed_work; 621 622 rtd->compr = compr; 623 compr->private_data = rtd; 624 625 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n", 626 codec_dai->name, cpu_dai->name); 627 628 return 0; 629 } 630 EXPORT_SYMBOL_GPL(snd_soc_new_compress); 631