linux/sound/soc/soc-compress.c
<<
>>
Prefs
   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
  29static 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_component *component;
  34        struct snd_soc_rtdcom_list *rtdcom;
  35        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  36        int ret = 0, __ret;
  37
  38        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  39
  40        if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
  41                ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
  42                if (ret < 0) {
  43                        dev_err(cpu_dai->dev,
  44                                "Compress ASoC: can't open interface %s: %d\n",
  45                                cpu_dai->name, ret);
  46                        goto out;
  47                }
  48        }
  49
  50        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
  51                ret = platform->driver->compr_ops->open(cstream);
  52                if (ret < 0) {
  53                        dev_err(platform->dev,
  54                                "Compress ASoC: can't open platform %s: %d\n",
  55                                platform->component.name, ret);
  56                        goto plat_err;
  57                }
  58        }
  59
  60        for_each_rtdcom(rtd, rtdcom) {
  61                component = rtdcom->component;
  62
  63                /* ignore duplication for now */
  64                if (platform && (component == &platform->component))
  65                        continue;
  66
  67                if (!component->driver->compr_ops ||
  68                    !component->driver->compr_ops->open)
  69                        continue;
  70
  71                __ret = component->driver->compr_ops->open(cstream);
  72                if (__ret < 0) {
  73                        dev_err(component->dev,
  74                                "Compress ASoC: can't open platform %s: %d\n",
  75                                component->name, __ret);
  76                        ret = __ret;
  77                }
  78        }
  79        if (ret < 0)
  80                goto machine_err;
  81
  82        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
  83                ret = rtd->dai_link->compr_ops->startup(cstream);
  84                if (ret < 0) {
  85                        dev_err(rtd->dev,
  86                                "Compress ASoC: %s startup failed: %d\n",
  87                                rtd->dai_link->name, ret);
  88                        goto machine_err;
  89                }
  90        }
  91
  92        snd_soc_runtime_activate(rtd, cstream->direction);
  93
  94        mutex_unlock(&rtd->pcm_mutex);
  95
  96        return 0;
  97
  98machine_err:
  99        for_each_rtdcom(rtd, rtdcom) {
 100                component = rtdcom->component;
 101
 102                /* ignore duplication for now */
 103                if (platform && (component == &platform->component))
 104                        continue;
 105
 106                if (!component->driver->compr_ops ||
 107                    !component->driver->compr_ops->free)
 108                        continue;
 109
 110                component->driver->compr_ops->free(cstream);
 111        }
 112
 113        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 114                platform->driver->compr_ops->free(cstream);
 115plat_err:
 116        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 117                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 118out:
 119        mutex_unlock(&rtd->pcm_mutex);
 120        return ret;
 121}
 122
 123static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 124{
 125        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 126        struct snd_pcm_substream *fe_substream =
 127                 fe->pcm->streams[cstream->direction].substream;
 128        struct snd_soc_platform *platform = fe->platform;
 129        struct snd_soc_component *component;
 130        struct snd_soc_rtdcom_list *rtdcom;
 131        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 132        struct snd_soc_dpcm *dpcm;
 133        struct snd_soc_dapm_widget_list *list;
 134        int stream;
 135        int ret = 0, __ret;
 136
 137        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 138                stream = SNDRV_PCM_STREAM_PLAYBACK;
 139        else
 140                stream = SNDRV_PCM_STREAM_CAPTURE;
 141
 142        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 143
 144        if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
 145                ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
 146                if (ret < 0) {
 147                        dev_err(cpu_dai->dev,
 148                                "Compress ASoC: can't open interface %s: %d\n",
 149                                cpu_dai->name, ret);
 150                        goto out;
 151                }
 152        }
 153
 154        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
 155                ret = platform->driver->compr_ops->open(cstream);
 156                if (ret < 0) {
 157                        dev_err(platform->dev,
 158                                "Compress ASoC: can't open platform %s: %d\n",
 159                                platform->component.name, ret);
 160                        goto plat_err;
 161                }
 162        }
 163
 164        for_each_rtdcom(fe, rtdcom) {
 165                component = rtdcom->component;
 166
 167                /* ignore duplication for now */
 168                if (platform && (component == &platform->component))
 169                        continue;
 170
 171                if (!component->driver->compr_ops ||
 172                    !component->driver->compr_ops->open)
 173                        continue;
 174
 175                __ret = component->driver->compr_ops->open(cstream);
 176                if (__ret < 0) {
 177                        dev_err(component->dev,
 178                                "Compress ASoC: can't open platform %s: %d\n",
 179                                component->name, __ret);
 180                        ret = __ret;
 181                }
 182        }
 183        if (ret < 0)
 184                goto machine_err;
 185
 186        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
 187                ret = fe->dai_link->compr_ops->startup(cstream);
 188                if (ret < 0) {
 189                        pr_err("Compress ASoC: %s startup failed: %d\n",
 190                               fe->dai_link->name, ret);
 191                        goto machine_err;
 192                }
 193        }
 194
 195        fe->dpcm[stream].runtime = fe_substream->runtime;
 196
 197        ret = dpcm_path_get(fe, stream, &list);
 198        if (ret < 0)
 199                goto fe_err;
 200        else if (ret == 0)
 201                dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
 202                        fe->dai_link->name, stream ? "capture" : "playback");
 203
 204        /* calculate valid and active FE <-> BE dpcms */
 205        dpcm_process_paths(fe, stream, &list, 1);
 206
 207        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 208
 209        ret = dpcm_be_dai_startup(fe, stream);
 210        if (ret < 0) {
 211                /* clean up all links */
 212                list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
 213                        dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 214
 215                dpcm_be_disconnect(fe, stream);
 216                fe->dpcm[stream].runtime = NULL;
 217                goto path_err;
 218        }
 219
 220        dpcm_clear_pending_state(fe, stream);
 221        dpcm_path_put(&list);
 222
 223        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
 224        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 225
 226        snd_soc_runtime_activate(fe, stream);
 227
 228        mutex_unlock(&fe->card->mutex);
 229
 230        return 0;
 231
 232path_err:
 233        dpcm_path_put(&list);
 234fe_err:
 235        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 236                fe->dai_link->compr_ops->shutdown(cstream);
 237machine_err:
 238        for_each_rtdcom(fe, rtdcom) {
 239                component = rtdcom->component;
 240
 241                /* ignore duplication for now */
 242                if (platform && (component == &platform->component))
 243                        continue;
 244
 245                if (!component->driver->compr_ops ||
 246                    !component->driver->compr_ops->free)
 247                        continue;
 248
 249                component->driver->compr_ops->free(cstream);
 250        }
 251
 252        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 253                platform->driver->compr_ops->free(cstream);
 254plat_err:
 255        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 256                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 257out:
 258        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 259        mutex_unlock(&fe->card->mutex);
 260        return ret;
 261}
 262
 263/*
 264 * Power down the audio subsystem pmdown_time msecs after close is called.
 265 * This is to ensure there are no pops or clicks in between any music tracks
 266 * due to DAPM power cycling.
 267 */
 268static void close_delayed_work(struct work_struct *work)
 269{
 270        struct snd_soc_pcm_runtime *rtd =
 271                        container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
 272        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 273
 274        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 275
 276        dev_dbg(rtd->dev,
 277                "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
 278                codec_dai->driver->playback.stream_name,
 279                codec_dai->playback_active ? "active" : "inactive",
 280                rtd->pop_wait ? "yes" : "no");
 281
 282        /* are we waiting on this codec DAI stream */
 283        if (rtd->pop_wait == 1) {
 284                rtd->pop_wait = 0;
 285                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 286                                          SND_SOC_DAPM_STREAM_STOP);
 287        }
 288
 289        mutex_unlock(&rtd->pcm_mutex);
 290}
 291
 292static int soc_compr_free(struct snd_compr_stream *cstream)
 293{
 294        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 295        struct snd_soc_platform *platform = rtd->platform;
 296        struct snd_soc_component *component;
 297        struct snd_soc_rtdcom_list *rtdcom;
 298        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 299        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 300        int stream;
 301
 302        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 303
 304        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 305                stream = SNDRV_PCM_STREAM_PLAYBACK;
 306        else
 307                stream = SNDRV_PCM_STREAM_CAPTURE;
 308
 309        snd_soc_runtime_deactivate(rtd, stream);
 310
 311        snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 312
 313        if (!cpu_dai->active)
 314                cpu_dai->rate = 0;
 315
 316        if (!codec_dai->active)
 317                codec_dai->rate = 0;
 318
 319        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
 320                rtd->dai_link->compr_ops->shutdown(cstream);
 321
 322        for_each_rtdcom(rtd, rtdcom) {
 323                component = rtdcom->component;
 324
 325                /* ignore duplication for now */
 326                if (platform && (component == &platform->component))
 327                        continue;
 328
 329                if (!component->driver->compr_ops ||
 330                    !component->driver->compr_ops->free)
 331                        continue;
 332
 333                component->driver->compr_ops->free(cstream);
 334        }
 335
 336        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 337                platform->driver->compr_ops->free(cstream);
 338
 339        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 340                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 341
 342        if (cstream->direction == SND_COMPRESS_PLAYBACK) {
 343                if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
 344                        snd_soc_dapm_stream_event(rtd,
 345                                        SNDRV_PCM_STREAM_PLAYBACK,
 346                                        SND_SOC_DAPM_STREAM_STOP);
 347                } else {
 348                        rtd->pop_wait = 1;
 349                        queue_delayed_work(system_power_efficient_wq,
 350                                           &rtd->delayed_work,
 351                                           msecs_to_jiffies(rtd->pmdown_time));
 352                }
 353        } else {
 354                /* capture streams can be powered down now */
 355                snd_soc_dapm_stream_event(rtd,
 356                        SNDRV_PCM_STREAM_CAPTURE,
 357                        SND_SOC_DAPM_STREAM_STOP);
 358        }
 359
 360        mutex_unlock(&rtd->pcm_mutex);
 361        return 0;
 362}
 363
 364static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 365{
 366        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 367        struct snd_soc_platform *platform = fe->platform;
 368        struct snd_soc_component *component;
 369        struct snd_soc_rtdcom_list *rtdcom;
 370        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 371        struct snd_soc_dpcm *dpcm;
 372        int stream, ret;
 373
 374        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 375
 376        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 377                stream = SNDRV_PCM_STREAM_PLAYBACK;
 378        else
 379                stream = SNDRV_PCM_STREAM_CAPTURE;
 380
 381        snd_soc_runtime_deactivate(fe, stream);
 382
 383        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 384
 385        ret = dpcm_be_dai_hw_free(fe, stream);
 386        if (ret < 0)
 387                dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
 388
 389        ret = dpcm_be_dai_shutdown(fe, stream);
 390
 391        /* mark FE's links ready to prune */
 392        list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
 393                dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 394
 395        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 396
 397        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
 398        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 399
 400        dpcm_be_disconnect(fe, stream);
 401
 402        fe->dpcm[stream].runtime = NULL;
 403
 404        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 405                fe->dai_link->compr_ops->shutdown(cstream);
 406
 407        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 408                platform->driver->compr_ops->free(cstream);
 409
 410        for_each_rtdcom(fe, rtdcom) {
 411                component = rtdcom->component;
 412
 413                /* ignore duplication for now */
 414                if (platform && (component == &platform->component))
 415                        continue;
 416
 417                if (!component->driver->compr_ops ||
 418                    !component->driver->compr_ops->free)
 419                        continue;
 420
 421                component->driver->compr_ops->free(cstream);
 422        }
 423
 424        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 425                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 426
 427        mutex_unlock(&fe->card->mutex);
 428        return 0;
 429}
 430
 431static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 432{
 433
 434        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 435        struct snd_soc_platform *platform = rtd->platform;
 436        struct snd_soc_component *component;
 437        struct snd_soc_rtdcom_list *rtdcom;
 438        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 439        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 440        int ret = 0, __ret;
 441
 442        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 443
 444        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 445                ret = platform->driver->compr_ops->trigger(cstream, cmd);
 446                if (ret < 0)
 447                        goto out;
 448        }
 449
 450        for_each_rtdcom(rtd, rtdcom) {
 451                component = rtdcom->component;
 452
 453                /* ignore duplication for now */
 454                if (platform && (component == &platform->component))
 455                        continue;
 456
 457                if (!component->driver->compr_ops ||
 458                    !component->driver->compr_ops->trigger)
 459                        continue;
 460
 461                __ret = component->driver->compr_ops->trigger(cstream, cmd);
 462                if (__ret < 0)
 463                        ret = __ret;
 464        }
 465        if (ret < 0)
 466                goto out;
 467
 468        if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
 469                cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 470
 471        switch (cmd) {
 472        case SNDRV_PCM_TRIGGER_START:
 473                snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
 474                break;
 475        case SNDRV_PCM_TRIGGER_STOP:
 476                snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 477                break;
 478        }
 479
 480out:
 481        mutex_unlock(&rtd->pcm_mutex);
 482        return ret;
 483}
 484
 485static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
 486{
 487        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 488        struct snd_soc_platform *platform = fe->platform;
 489        struct snd_soc_component *component;
 490        struct snd_soc_rtdcom_list *rtdcom;
 491        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 492        int ret = 0, __ret, stream;
 493
 494        if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
 495                cmd == SND_COMPR_TRIGGER_DRAIN) {
 496
 497                if (platform &&
 498                    platform->driver->compr_ops &&
 499                    platform->driver->compr_ops->trigger)
 500                        return platform->driver->compr_ops->trigger(cstream,
 501                                                                    cmd);
 502
 503                for_each_rtdcom(fe, rtdcom) {
 504                        component = rtdcom->component;
 505
 506                        /* ignore duplication for now */
 507                        if (platform && (component == &platform->component))
 508                                continue;
 509
 510                        if (!component->driver->compr_ops ||
 511                            !component->driver->compr_ops->trigger)
 512                                continue;
 513
 514                        __ret = component->driver->compr_ops->trigger(cstream, cmd);
 515                        if (__ret < 0)
 516                                ret = __ret;
 517                }
 518                return ret;
 519        }
 520
 521        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 522                stream = SNDRV_PCM_STREAM_PLAYBACK;
 523        else
 524                stream = SNDRV_PCM_STREAM_CAPTURE;
 525
 526
 527        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 528
 529        if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
 530                ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 531                if (ret < 0)
 532                        goto out;
 533        }
 534
 535        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 536                ret = platform->driver->compr_ops->trigger(cstream, cmd);
 537                if (ret < 0)
 538                        goto out;
 539        }
 540
 541        for_each_rtdcom(fe, rtdcom) {
 542                component = rtdcom->component;
 543
 544                /* ignore duplication for now */
 545                if (platform && (component == &platform->component))
 546                        continue;
 547
 548                if (!component->driver->compr_ops ||
 549                    !component->driver->compr_ops->trigger)
 550                        continue;
 551
 552                __ret = component->driver->compr_ops->trigger(cstream, cmd);
 553                if (__ret < 0)
 554                        ret = __ret;
 555        }
 556        if (ret < 0)
 557                goto out;
 558
 559        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 560
 561        ret = dpcm_be_dai_trigger(fe, stream, cmd);
 562
 563        switch (cmd) {
 564        case SNDRV_PCM_TRIGGER_START:
 565        case SNDRV_PCM_TRIGGER_RESUME:
 566        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 567                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
 568                break;
 569        case SNDRV_PCM_TRIGGER_STOP:
 570        case SNDRV_PCM_TRIGGER_SUSPEND:
 571                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
 572                break;
 573        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 574                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
 575                break;
 576        }
 577
 578out:
 579        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 580        mutex_unlock(&fe->card->mutex);
 581        return ret;
 582}
 583
 584static int soc_compr_set_params(struct snd_compr_stream *cstream,
 585                                        struct snd_compr_params *params)
 586{
 587        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 588        struct snd_soc_platform *platform = rtd->platform;
 589        struct snd_soc_component *component;
 590        struct snd_soc_rtdcom_list *rtdcom;
 591        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 592        int ret = 0, __ret;
 593
 594        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 595
 596        /* first we call set_params for the platform driver
 597         * this should configure the soc side
 598         * if the machine has compressed ops then we call that as well
 599         * expectation is that platform and machine will configure everything
 600         * for this compress path, like configuring pcm port for codec
 601         */
 602        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 603                ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 604                if (ret < 0)
 605                        goto err;
 606        }
 607
 608        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
 609                ret = platform->driver->compr_ops->set_params(cstream, params);
 610                if (ret < 0)
 611                        goto err;
 612        }
 613
 614        for_each_rtdcom(rtd, rtdcom) {
 615                component = rtdcom->component;
 616
 617                /* ignore duplication for now */
 618                if (platform && (component == &platform->component))
 619                        continue;
 620
 621                if (!component->driver->compr_ops ||
 622                    !component->driver->compr_ops->set_params)
 623                        continue;
 624
 625                __ret = component->driver->compr_ops->set_params(cstream, params);
 626                if (__ret < 0)
 627                        ret = __ret;
 628        }
 629        if (ret < 0)
 630                goto err;
 631
 632        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
 633                ret = rtd->dai_link->compr_ops->set_params(cstream);
 634                if (ret < 0)
 635                        goto err;
 636        }
 637
 638        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 639                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 640                                        SND_SOC_DAPM_STREAM_START);
 641        else
 642                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
 643                                        SND_SOC_DAPM_STREAM_START);
 644
 645        /* cancel any delayed stream shutdown that is pending */
 646        rtd->pop_wait = 0;
 647        mutex_unlock(&rtd->pcm_mutex);
 648
 649        cancel_delayed_work_sync(&rtd->delayed_work);
 650
 651        return ret;
 652
 653err:
 654        mutex_unlock(&rtd->pcm_mutex);
 655        return ret;
 656}
 657
 658static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
 659                                        struct snd_compr_params *params)
 660{
 661        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 662        struct snd_pcm_substream *fe_substream =
 663                 fe->pcm->streams[cstream->direction].substream;
 664        struct snd_soc_platform *platform = fe->platform;
 665        struct snd_soc_component *component;
 666        struct snd_soc_rtdcom_list *rtdcom;
 667        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 668        int ret = 0, __ret, stream;
 669
 670        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 671                stream = SNDRV_PCM_STREAM_PLAYBACK;
 672        else
 673                stream = SNDRV_PCM_STREAM_CAPTURE;
 674
 675        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 676
 677        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 678                ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 679                if (ret < 0)
 680                        goto out;
 681        }
 682
 683        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
 684                ret = platform->driver->compr_ops->set_params(cstream, params);
 685                if (ret < 0)
 686                        goto out;
 687        }
 688
 689        for_each_rtdcom(fe, rtdcom) {
 690                component = rtdcom->component;
 691
 692                /* ignore duplication for now */
 693                if (platform && (component == &platform->component))
 694                        continue;
 695
 696                if (!component->driver->compr_ops ||
 697                    !component->driver->compr_ops->set_params)
 698                        continue;
 699
 700                __ret = component->driver->compr_ops->set_params(cstream, params);
 701                if (__ret < 0)
 702                        ret = __ret;
 703        }
 704        if (ret < 0)
 705                goto out;
 706
 707        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
 708                ret = fe->dai_link->compr_ops->set_params(cstream);
 709                if (ret < 0)
 710                        goto out;
 711        }
 712
 713        /*
 714         * Create an empty hw_params for the BE as the machine driver must
 715         * fix this up to match DSP decoder and ASRC configuration.
 716         * I.e. machine driver fixup for compressed BE is mandatory.
 717         */
 718        memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
 719                sizeof(struct snd_pcm_hw_params));
 720
 721        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 722
 723        ret = dpcm_be_dai_hw_params(fe, stream);
 724        if (ret < 0)
 725                goto out;
 726
 727        ret = dpcm_be_dai_prepare(fe, stream);
 728        if (ret < 0)
 729                goto out;
 730
 731        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
 732        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
 733
 734out:
 735        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 736        mutex_unlock(&fe->card->mutex);
 737        return ret;
 738}
 739
 740static int soc_compr_get_params(struct snd_compr_stream *cstream,
 741                                        struct snd_codec *params)
 742{
 743        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 744        struct snd_soc_platform *platform = rtd->platform;
 745        struct snd_soc_component *component;
 746        struct snd_soc_rtdcom_list *rtdcom;
 747        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 748        int ret = 0, __ret;
 749
 750        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 751
 752        if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
 753                ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
 754                if (ret < 0)
 755                        goto err;
 756        }
 757
 758        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_params) {
 759                ret = platform->driver->compr_ops->get_params(cstream, params);
 760                if (ret < 0)
 761                        goto err;
 762        }
 763
 764        for_each_rtdcom(rtd, rtdcom) {
 765                component = rtdcom->component;
 766
 767                /* ignore duplication for now */
 768                if (platform && (component == &platform->component))
 769                        continue;
 770
 771                if (!component->driver->compr_ops ||
 772                    !component->driver->compr_ops->get_params)
 773                        continue;
 774
 775                __ret = component->driver->compr_ops->get_params(cstream, params);
 776                if (__ret < 0)
 777                        ret = __ret;
 778        }
 779
 780err:
 781        mutex_unlock(&rtd->pcm_mutex);
 782        return ret;
 783}
 784
 785static int soc_compr_get_caps(struct snd_compr_stream *cstream,
 786                                struct snd_compr_caps *caps)
 787{
 788        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 789        struct snd_soc_platform *platform = rtd->platform;
 790        struct snd_soc_component *component;
 791        struct snd_soc_rtdcom_list *rtdcom;
 792        int ret = 0, __ret;
 793
 794        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 795
 796        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_caps) {
 797                ret = platform->driver->compr_ops->get_caps(cstream, caps);
 798                if (ret < 0)
 799                        goto err;
 800        }
 801
 802        for_each_rtdcom(rtd, rtdcom) {
 803                component = rtdcom->component;
 804
 805                /* ignore duplication for now */
 806                if (platform && (component == &platform->component))
 807                        continue;
 808
 809                if (!component->driver->compr_ops ||
 810                    !component->driver->compr_ops->get_caps)
 811                        continue;
 812
 813                __ret = component->driver->compr_ops->get_caps(cstream, caps);
 814                if (__ret < 0)
 815                        ret = __ret;
 816        }
 817
 818err:
 819        mutex_unlock(&rtd->pcm_mutex);
 820        return ret;
 821}
 822
 823static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
 824                                struct snd_compr_codec_caps *codec)
 825{
 826        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 827        struct snd_soc_platform *platform = rtd->platform;
 828        struct snd_soc_component *component;
 829        struct snd_soc_rtdcom_list *rtdcom;
 830        int ret = 0, __ret;
 831
 832        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 833
 834        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) {
 835                ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
 836                if (ret < 0)
 837                        goto err;
 838        }
 839
 840        for_each_rtdcom(rtd, rtdcom) {
 841                component = rtdcom->component;
 842
 843                /* ignore duplication for now */
 844                if (platform && (component == &platform->component))
 845                        continue;
 846
 847                if (!component->driver->compr_ops ||
 848                    !component->driver->compr_ops->get_codec_caps)
 849                        continue;
 850
 851                __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
 852                if (__ret < 0)
 853                        ret = __ret;
 854        }
 855
 856err:
 857        mutex_unlock(&rtd->pcm_mutex);
 858        return ret;
 859}
 860
 861static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 862{
 863        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 864        struct snd_soc_platform *platform = rtd->platform;
 865        struct snd_soc_component *component;
 866        struct snd_soc_rtdcom_list *rtdcom;
 867        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 868        int ret = 0, __ret;
 869
 870        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 871
 872        if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
 873                ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
 874                if (ret < 0)
 875                        goto err;
 876        }
 877
 878        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->ack) {
 879                ret = platform->driver->compr_ops->ack(cstream, bytes);
 880                if (ret < 0)
 881                        goto err;
 882        }
 883
 884        for_each_rtdcom(rtd, rtdcom) {
 885                component = rtdcom->component;
 886
 887                /* ignore duplication for now */
 888                if (platform && (component == &platform->component))
 889                        continue;
 890
 891                if (!component->driver->compr_ops ||
 892                    !component->driver->compr_ops->ack)
 893                        continue;
 894
 895                __ret = component->driver->compr_ops->ack(cstream, bytes);
 896                if (__ret < 0)
 897                        ret = __ret;
 898        }
 899
 900err:
 901        mutex_unlock(&rtd->pcm_mutex);
 902        return ret;
 903}
 904
 905static int soc_compr_pointer(struct snd_compr_stream *cstream,
 906                        struct snd_compr_tstamp *tstamp)
 907{
 908        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 909        struct snd_soc_platform *platform = rtd->platform;
 910        struct snd_soc_component *component;
 911        struct snd_soc_rtdcom_list *rtdcom;
 912        int ret = 0, __ret;
 913        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 914
 915        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 916
 917        if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
 918                cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
 919
 920        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->pointer) {
 921                ret = platform->driver->compr_ops->pointer(cstream, tstamp);
 922                if (ret < 0)
 923                        goto err;
 924        }
 925
 926        for_each_rtdcom(rtd, rtdcom) {
 927                component = rtdcom->component;
 928
 929                /* ignore duplication for now */
 930                if (platform && (component == &platform->component))
 931                        continue;
 932
 933                if (!component->driver->compr_ops ||
 934                    !component->driver->compr_ops->pointer)
 935                        continue;
 936
 937                __ret = component->driver->compr_ops->pointer(cstream, tstamp);
 938                if (__ret < 0)
 939                        ret = __ret;
 940        }
 941
 942err:
 943        mutex_unlock(&rtd->pcm_mutex);
 944        return ret;
 945}
 946
 947static int soc_compr_copy(struct snd_compr_stream *cstream,
 948                          char __user *buf, size_t count)
 949{
 950        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 951        struct snd_soc_platform *platform = rtd->platform;
 952        struct snd_soc_component *component;
 953        struct snd_soc_rtdcom_list *rtdcom;
 954        int ret = 0;
 955
 956        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 957
 958        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy) {
 959                ret = platform->driver->compr_ops->copy(cstream, buf, count);
 960                if (ret < 0)
 961                        goto err;
 962        }
 963
 964        for_each_rtdcom(rtd, rtdcom) {
 965                component = rtdcom->component;
 966
 967                /* ignore duplication for now */
 968                if (platform && (component == &platform->component))
 969                        continue;
 970
 971                if (!component->driver->compr_ops ||
 972                    !component->driver->compr_ops->copy)
 973                        continue;
 974
 975                ret = component->driver->compr_ops->copy(cstream, buf, count);
 976                break;
 977        }
 978
 979err:
 980        mutex_unlock(&rtd->pcm_mutex);
 981        return ret;
 982}
 983
 984static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 985                                struct snd_compr_metadata *metadata)
 986{
 987        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 988        struct snd_soc_platform *platform = rtd->platform;
 989        struct snd_soc_component *component;
 990        struct snd_soc_rtdcom_list *rtdcom;
 991        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 992        int ret = 0, __ret;
 993
 994        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
 995                ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
 996                if (ret < 0)
 997                        return ret;
 998        }
 999
1000        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) {
1001                ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
1002                if (ret < 0)
1003                        return ret;
1004        }
1005
1006        for_each_rtdcom(rtd, rtdcom) {
1007                component = rtdcom->component;
1008
1009                /* ignore duplication for now */
1010                if (platform && (component == &platform->component))
1011                        continue;
1012
1013                if (!component->driver->compr_ops ||
1014                    !component->driver->compr_ops->set_metadata)
1015                        continue;
1016
1017                __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
1018                if (__ret < 0)
1019                        ret = __ret;
1020        }
1021
1022        return ret;
1023}
1024
1025static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
1026                                struct snd_compr_metadata *metadata)
1027{
1028        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1029        struct snd_soc_platform *platform = rtd->platform;
1030        struct snd_soc_component *component;
1031        struct snd_soc_rtdcom_list *rtdcom;
1032        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1033        int ret = 0, __ret;
1034
1035        if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
1036                ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
1037                if (ret < 0)
1038                        return ret;
1039        }
1040
1041        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) {
1042                ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
1043                if (ret < 0)
1044                        return ret;
1045        }
1046
1047        for_each_rtdcom(rtd, rtdcom) {
1048                component = rtdcom->component;
1049
1050                /* ignore duplication for now */
1051                if (platform && (component == &platform->component))
1052                        continue;
1053
1054                if (!component->driver->compr_ops ||
1055                    !component->driver->compr_ops->get_metadata)
1056                        continue;
1057
1058                __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
1059                if (__ret < 0)
1060                        ret = __ret;
1061        }
1062
1063        return ret;
1064}
1065
1066/* ASoC Compress operations */
1067static struct snd_compr_ops soc_compr_ops = {
1068        .open           = soc_compr_open,
1069        .free           = soc_compr_free,
1070        .set_params     = soc_compr_set_params,
1071        .set_metadata   = soc_compr_set_metadata,
1072        .get_metadata   = soc_compr_get_metadata,
1073        .get_params     = soc_compr_get_params,
1074        .trigger        = soc_compr_trigger,
1075        .pointer        = soc_compr_pointer,
1076        .ack            = soc_compr_ack,
1077        .get_caps       = soc_compr_get_caps,
1078        .get_codec_caps = soc_compr_get_codec_caps
1079};
1080
1081/* ASoC Dynamic Compress operations */
1082static struct snd_compr_ops soc_compr_dyn_ops = {
1083        .open           = soc_compr_open_fe,
1084        .free           = soc_compr_free_fe,
1085        .set_params     = soc_compr_set_params_fe,
1086        .get_params     = soc_compr_get_params,
1087        .set_metadata   = soc_compr_set_metadata,
1088        .get_metadata   = soc_compr_get_metadata,
1089        .trigger        = soc_compr_trigger_fe,
1090        .pointer        = soc_compr_pointer,
1091        .ack            = soc_compr_ack,
1092        .get_caps       = soc_compr_get_caps,
1093        .get_codec_caps = soc_compr_get_codec_caps
1094};
1095
1096/**
1097 * snd_soc_new_compress - create a new compress.
1098 *
1099 * @rtd: The runtime for which we will create compress
1100 * @num: the device index number (zero based - shared with normal PCMs)
1101 *
1102 * Return: 0 for success, else error.
1103 */
1104int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
1105{
1106        struct snd_soc_platform *platform = rtd->platform;
1107        struct snd_soc_component *component;
1108        struct snd_soc_rtdcom_list *rtdcom;
1109        struct snd_soc_dai *codec_dai = rtd->codec_dai;
1110        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1111        struct snd_compr *compr;
1112        struct snd_pcm *be_pcm;
1113        char new_name[64];
1114        int ret = 0, direction = 0;
1115        int playback = 0, capture = 0;
1116
1117        if (rtd->num_codecs > 1) {
1118                dev_err(rtd->card->dev,
1119                        "Compress ASoC: Multicodec not supported\n");
1120                return -EINVAL;
1121        }
1122
1123        /* check client and interface hw capabilities */
1124        if (codec_dai->driver->playback.channels_min)
1125                playback = 1;
1126        if (codec_dai->driver->capture.channels_min)
1127                capture = 1;
1128
1129        capture = capture && cpu_dai->driver->capture.channels_min;
1130        playback = playback && cpu_dai->driver->playback.channels_min;
1131
1132        /*
1133         * Compress devices are unidirectional so only one of the directions
1134         * should be set, check for that (xor)
1135         */
1136        if (playback + capture != 1) {
1137                dev_err(rtd->card->dev,
1138                        "Compress ASoC: Invalid direction for P %d, C %d\n",
1139                        playback, capture);
1140                return -EINVAL;
1141        }
1142
1143        if (playback)
1144                direction = SND_COMPRESS_PLAYBACK;
1145        else
1146                direction = SND_COMPRESS_CAPTURE;
1147
1148        compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1149        if (!compr)
1150                return -ENOMEM;
1151
1152        compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
1153                                  GFP_KERNEL);
1154        if (!compr->ops) {
1155                ret = -ENOMEM;
1156                goto compr_err;
1157        }
1158
1159        if (rtd->dai_link->dynamic) {
1160                snprintf(new_name, sizeof(new_name), "(%s)",
1161                        rtd->dai_link->stream_name);
1162
1163                ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
1164                                rtd->dai_link->dpcm_playback,
1165                                rtd->dai_link->dpcm_capture, &be_pcm);
1166                if (ret < 0) {
1167                        dev_err(rtd->card->dev,
1168                                "Compress ASoC: can't create compressed for %s: %d\n",
1169                                rtd->dai_link->name, ret);
1170                        goto compr_err;
1171                }
1172
1173                rtd->pcm = be_pcm;
1174                rtd->fe_compr = 1;
1175                if (rtd->dai_link->dpcm_playback)
1176                        be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1177                else if (rtd->dai_link->dpcm_capture)
1178                        be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
1179                memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
1180        } else {
1181                snprintf(new_name, sizeof(new_name), "%s %s-%d",
1182                        rtd->dai_link->stream_name, codec_dai->name, num);
1183
1184                memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
1185        }
1186
1187
1188        /* Add copy callback for not memory mapped DSPs */
1189        if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy)
1190                compr->ops->copy = soc_compr_copy;
1191
1192        for_each_rtdcom(rtd, rtdcom) {
1193                component = rtdcom->component;
1194
1195                /* ignore duplication for now */
1196                if (platform && (component == &platform->component))
1197                        continue;
1198
1199                if (!component->driver->compr_ops ||
1200                    !component->driver->compr_ops->copy)
1201                        continue;
1202
1203                compr->ops->copy = soc_compr_copy;
1204        }
1205
1206
1207        mutex_init(&compr->lock);
1208        ret = snd_compress_new(rtd->card->snd_card, num, direction,
1209                                new_name, compr);
1210        if (ret < 0) {
1211                component = rtd->codec_dai->component;
1212                dev_err(component->dev,
1213                        "Compress ASoC: can't create compress for codec %s: %d\n",
1214                        component->name, ret);
1215                goto compr_err;
1216        }
1217
1218        /* DAPM dai link stream work */
1219        INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1220
1221        rtd->compr = compr;
1222        compr->private_data = rtd;
1223
1224        dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1225                 codec_dai->name, cpu_dai->name);
1226        return ret;
1227
1228compr_err:
1229        kfree(compr);
1230        return ret;
1231}
1232EXPORT_SYMBOL_GPL(snd_soc_new_compress);
1233