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