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