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
  23static int soc_compr_components_open(struct snd_compr_stream *cstream,
  24                                     struct snd_soc_component **last)
  25{
  26        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  27        struct snd_soc_component *component;
  28        struct snd_soc_rtdcom_list *rtdcom;
  29        int ret;
  30
  31        for_each_rtdcom(rtd, rtdcom) {
  32                component = rtdcom->component;
  33
  34                if (!component->driver->compr_ops ||
  35                    !component->driver->compr_ops->open)
  36                        continue;
  37
  38                ret = component->driver->compr_ops->open(cstream);
  39                if (ret < 0) {
  40                        dev_err(component->dev,
  41                                "Compress ASoC: can't open platform %s: %d\n",
  42                                component->name, ret);
  43
  44                        *last = component;
  45                        return ret;
  46                }
  47        }
  48
  49        *last = NULL;
  50        return 0;
  51}
  52
  53static int soc_compr_components_free(struct snd_compr_stream *cstream,
  54                                     struct snd_soc_component *last)
  55{
  56        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  57        struct snd_soc_component *component;
  58        struct snd_soc_rtdcom_list *rtdcom;
  59
  60        for_each_rtdcom(rtd, rtdcom) {
  61                component = rtdcom->component;
  62
  63                if (component == last)
  64                        break;
  65
  66                if (!component->driver->compr_ops ||
  67                    !component->driver->compr_ops->free)
  68                        continue;
  69
  70                component->driver->compr_ops->free(cstream);
  71        }
  72
  73        return 0;
  74}
  75
  76static int soc_compr_open(struct snd_compr_stream *cstream)
  77{
  78        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  79        struct snd_soc_component *component;
  80        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  81        int ret;
  82
  83        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
  84
  85        if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
  86                ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
  87                if (ret < 0) {
  88                        dev_err(cpu_dai->dev,
  89                                "Compress ASoC: can't open interface %s: %d\n",
  90                                cpu_dai->name, ret);
  91                        goto out;
  92                }
  93        }
  94
  95        ret = soc_compr_components_open(cstream, &component);
  96        if (ret < 0)
  97                goto machine_err;
  98
  99        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
 100                ret = rtd->dai_link->compr_ops->startup(cstream);
 101                if (ret < 0) {
 102                        dev_err(rtd->dev,
 103                                "Compress ASoC: %s startup failed: %d\n",
 104                                rtd->dai_link->name, ret);
 105                        goto machine_err;
 106                }
 107        }
 108
 109        snd_soc_runtime_activate(rtd, cstream->direction);
 110
 111        mutex_unlock(&rtd->pcm_mutex);
 112
 113        return 0;
 114
 115machine_err:
 116        soc_compr_components_free(cstream, component);
 117
 118        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 119                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 120out:
 121        mutex_unlock(&rtd->pcm_mutex);
 122        return ret;
 123}
 124
 125static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 126{
 127        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 128        struct snd_pcm_substream *fe_substream =
 129                 fe->pcm->streams[cstream->direction].substream;
 130        struct snd_soc_component *component;
 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;
 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        fe->dpcm[stream].runtime = fe_substream->runtime;
 144
 145        ret = dpcm_path_get(fe, stream, &list);
 146        if (ret < 0)
 147                goto be_err;
 148        else if (ret == 0)
 149                dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
 150                        fe->dai_link->name, stream ? "capture" : "playback");
 151        /* calculate valid and active FE <-> BE dpcms */
 152        dpcm_process_paths(fe, stream, &list, 1);
 153        fe->dpcm[stream].runtime = fe_substream->runtime;
 154
 155        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 156
 157        ret = dpcm_be_dai_startup(fe, stream);
 158        if (ret < 0) {
 159                /* clean up all links */
 160                for_each_dpcm_be(fe, stream, dpcm)
 161                        dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 162
 163                dpcm_be_disconnect(fe, stream);
 164                fe->dpcm[stream].runtime = NULL;
 165                goto out;
 166        }
 167
 168        if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
 169                ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
 170                if (ret < 0) {
 171                        dev_err(cpu_dai->dev,
 172                                "Compress ASoC: can't open interface %s: %d\n",
 173                                cpu_dai->name, ret);
 174                        goto out;
 175                }
 176        }
 177
 178        ret = soc_compr_components_open(cstream, &component);
 179        if (ret < 0)
 180                goto open_err;
 181
 182        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
 183                ret = fe->dai_link->compr_ops->startup(cstream);
 184                if (ret < 0) {
 185                        pr_err("Compress ASoC: %s startup failed: %d\n",
 186                               fe->dai_link->name, ret);
 187                        goto machine_err;
 188                }
 189        }
 190
 191        dpcm_clear_pending_state(fe, stream);
 192        dpcm_path_put(&list);
 193
 194        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
 195        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 196
 197        snd_soc_runtime_activate(fe, stream);
 198
 199        mutex_unlock(&fe->card->mutex);
 200
 201        return 0;
 202
 203machine_err:
 204        soc_compr_components_free(cstream, component);
 205open_err:
 206        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 207                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 208out:
 209        dpcm_path_put(&list);
 210be_err:
 211        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 212        mutex_unlock(&fe->card->mutex);
 213        return ret;
 214}
 215
 216/*
 217 * Power down the audio subsystem pmdown_time msecs after close is called.
 218 * This is to ensure there are no pops or clicks in between any music tracks
 219 * due to DAPM power cycling.
 220 */
 221static void close_delayed_work(struct work_struct *work)
 222{
 223        struct snd_soc_pcm_runtime *rtd =
 224                        container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
 225        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 226
 227        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 228
 229        dev_dbg(rtd->dev,
 230                "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
 231                codec_dai->driver->playback.stream_name,
 232                codec_dai->playback_active ? "active" : "inactive",
 233                rtd->pop_wait ? "yes" : "no");
 234
 235        /* are we waiting on this codec DAI stream */
 236        if (rtd->pop_wait == 1) {
 237                rtd->pop_wait = 0;
 238                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 239                                          SND_SOC_DAPM_STREAM_STOP);
 240        }
 241
 242        mutex_unlock(&rtd->pcm_mutex);
 243}
 244
 245static int soc_compr_free(struct snd_compr_stream *cstream)
 246{
 247        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 248        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 249        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 250        int stream;
 251
 252        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 253
 254        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 255                stream = SNDRV_PCM_STREAM_PLAYBACK;
 256        else
 257                stream = SNDRV_PCM_STREAM_CAPTURE;
 258
 259        snd_soc_runtime_deactivate(rtd, stream);
 260
 261        snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 262
 263        if (!cpu_dai->active)
 264                cpu_dai->rate = 0;
 265
 266        if (!codec_dai->active)
 267                codec_dai->rate = 0;
 268
 269        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
 270                rtd->dai_link->compr_ops->shutdown(cstream);
 271
 272        soc_compr_components_free(cstream, NULL);
 273
 274        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 275                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 276
 277        if (cstream->direction == SND_COMPRESS_PLAYBACK) {
 278                if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
 279                        snd_soc_dapm_stream_event(rtd,
 280                                                  SNDRV_PCM_STREAM_PLAYBACK,
 281                                                  SND_SOC_DAPM_STREAM_STOP);
 282                } else {
 283                        rtd->pop_wait = 1;
 284                        queue_delayed_work(system_power_efficient_wq,
 285                                           &rtd->delayed_work,
 286                                           msecs_to_jiffies(rtd->pmdown_time));
 287                }
 288        } else {
 289                /* capture streams can be powered down now */
 290                snd_soc_dapm_stream_event(rtd,
 291                                          SNDRV_PCM_STREAM_CAPTURE,
 292                                          SND_SOC_DAPM_STREAM_STOP);
 293        }
 294
 295        mutex_unlock(&rtd->pcm_mutex);
 296        return 0;
 297}
 298
 299static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 300{
 301        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 302        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 303        struct snd_soc_dpcm *dpcm;
 304        int stream, ret;
 305
 306        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 307
 308        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 309                stream = SNDRV_PCM_STREAM_PLAYBACK;
 310        else
 311                stream = SNDRV_PCM_STREAM_CAPTURE;
 312
 313        snd_soc_runtime_deactivate(fe, stream);
 314
 315        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 316
 317        ret = dpcm_be_dai_hw_free(fe, stream);
 318        if (ret < 0)
 319                dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
 320
 321        ret = dpcm_be_dai_shutdown(fe, stream);
 322
 323        /* mark FE's links ready to prune */
 324        for_each_dpcm_be(fe, stream, dpcm)
 325                dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 326
 327        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 328
 329        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
 330        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 331
 332        dpcm_be_disconnect(fe, stream);
 333
 334        fe->dpcm[stream].runtime = NULL;
 335
 336        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 337                fe->dai_link->compr_ops->shutdown(cstream);
 338
 339        soc_compr_components_free(cstream, NULL);
 340
 341        if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 342                cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 343
 344        mutex_unlock(&fe->card->mutex);
 345        return 0;
 346}
 347
 348static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
 349                                        int cmd)
 350{
 351        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 352        struct snd_soc_component *component;
 353        struct snd_soc_rtdcom_list *rtdcom;
 354        int ret;
 355
 356        for_each_rtdcom(rtd, rtdcom) {
 357                component = rtdcom->component;
 358
 359                if (!component->driver->compr_ops ||
 360                    !component->driver->compr_ops->trigger)
 361                        continue;
 362
 363                ret = component->driver->compr_ops->trigger(cstream, cmd);
 364                if (ret < 0)
 365                        return ret;
 366        }
 367
 368        return 0;
 369}
 370
 371static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 372{
 373        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 374        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 375        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 376        int ret;
 377
 378        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 379
 380        ret = soc_compr_components_trigger(cstream, cmd);
 381        if (ret < 0)
 382                goto out;
 383
 384        if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
 385                cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 386
 387        switch (cmd) {
 388        case SNDRV_PCM_TRIGGER_START:
 389                snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
 390                break;
 391        case SNDRV_PCM_TRIGGER_STOP:
 392                snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 393                break;
 394        }
 395
 396out:
 397        mutex_unlock(&rtd->pcm_mutex);
 398        return ret;
 399}
 400
 401static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
 402{
 403        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 404        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 405        int ret, stream;
 406
 407        if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
 408            cmd == SND_COMPR_TRIGGER_DRAIN)
 409                return soc_compr_components_trigger(cstream, cmd);
 410
 411        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 412                stream = SNDRV_PCM_STREAM_PLAYBACK;
 413        else
 414                stream = SNDRV_PCM_STREAM_CAPTURE;
 415
 416        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 417
 418        if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
 419                ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 420                if (ret < 0)
 421                        goto out;
 422        }
 423
 424        ret = soc_compr_components_trigger(cstream, cmd);
 425        if (ret < 0)
 426                goto out;
 427
 428        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 429
 430        ret = dpcm_be_dai_trigger(fe, stream, cmd);
 431
 432        switch (cmd) {
 433        case SNDRV_PCM_TRIGGER_START:
 434        case SNDRV_PCM_TRIGGER_RESUME:
 435        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 436                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
 437                break;
 438        case SNDRV_PCM_TRIGGER_STOP:
 439        case SNDRV_PCM_TRIGGER_SUSPEND:
 440                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
 441                break;
 442        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 443                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
 444                break;
 445        }
 446
 447out:
 448        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 449        mutex_unlock(&fe->card->mutex);
 450        return ret;
 451}
 452
 453static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
 454                                           struct snd_compr_params *params)
 455{
 456        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 457        struct snd_soc_component *component;
 458        struct snd_soc_rtdcom_list *rtdcom;
 459        int ret;
 460
 461        for_each_rtdcom(rtd, rtdcom) {
 462                component = rtdcom->component;
 463
 464                if (!component->driver->compr_ops ||
 465                    !component->driver->compr_ops->set_params)
 466                        continue;
 467
 468                ret = component->driver->compr_ops->set_params(cstream, params);
 469                if (ret < 0)
 470                        return ret;
 471        }
 472
 473        return 0;
 474}
 475
 476static int soc_compr_set_params(struct snd_compr_stream *cstream,
 477                                struct snd_compr_params *params)
 478{
 479        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 480        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 481        int ret;
 482
 483        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 484
 485        /*
 486         * First we call set_params for the CPU DAI, then the component
 487         * driver this should configure the SoC side. If the machine has
 488         * compressed ops then we call that as well. The expectation is
 489         * that these callbacks will configure everything for this compress
 490         * path, like configuring a PCM port for a CODEC.
 491         */
 492        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 493                ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 494                if (ret < 0)
 495                        goto err;
 496        }
 497
 498        ret = soc_compr_components_set_params(cstream, params);
 499        if (ret < 0)
 500                goto err;
 501
 502        if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
 503                ret = rtd->dai_link->compr_ops->set_params(cstream);
 504                if (ret < 0)
 505                        goto err;
 506        }
 507
 508        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 509                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 510                                          SND_SOC_DAPM_STREAM_START);
 511        else
 512                snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
 513                                          SND_SOC_DAPM_STREAM_START);
 514
 515        /* cancel any delayed stream shutdown that is pending */
 516        rtd->pop_wait = 0;
 517        mutex_unlock(&rtd->pcm_mutex);
 518
 519        cancel_delayed_work_sync(&rtd->delayed_work);
 520
 521        return 0;
 522
 523err:
 524        mutex_unlock(&rtd->pcm_mutex);
 525        return ret;
 526}
 527
 528static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
 529                                   struct snd_compr_params *params)
 530{
 531        struct snd_soc_pcm_runtime *fe = cstream->private_data;
 532        struct snd_pcm_substream *fe_substream =
 533                 fe->pcm->streams[cstream->direction].substream;
 534        struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 535        int ret, stream;
 536
 537        if (cstream->direction == SND_COMPRESS_PLAYBACK)
 538                stream = SNDRV_PCM_STREAM_PLAYBACK;
 539        else
 540                stream = SNDRV_PCM_STREAM_CAPTURE;
 541
 542        mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 543
 544        /*
 545         * Create an empty hw_params for the BE as the machine driver must
 546         * fix this up to match DSP decoder and ASRC configuration.
 547         * I.e. machine driver fixup for compressed BE is mandatory.
 548         */
 549        memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
 550                sizeof(struct snd_pcm_hw_params));
 551
 552        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 553
 554        ret = dpcm_be_dai_hw_params(fe, stream);
 555        if (ret < 0)
 556                goto out;
 557
 558        ret = dpcm_be_dai_prepare(fe, stream);
 559        if (ret < 0)
 560                goto out;
 561
 562        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 563                ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 564                if (ret < 0)
 565                        goto out;
 566        }
 567
 568        ret = soc_compr_components_set_params(cstream, params);
 569        if (ret < 0)
 570                goto out;
 571
 572        if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
 573                ret = fe->dai_link->compr_ops->set_params(cstream);
 574                if (ret < 0)
 575                        goto out;
 576        }
 577
 578        dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
 579        fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
 580
 581out:
 582        fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 583        mutex_unlock(&fe->card->mutex);
 584        return ret;
 585}
 586
 587static int soc_compr_get_params(struct snd_compr_stream *cstream,
 588                                struct snd_codec *params)
 589{
 590        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 591        struct snd_soc_component *component;
 592        struct snd_soc_rtdcom_list *rtdcom;
 593        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 594        int ret = 0;
 595
 596        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 597
 598        if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
 599                ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
 600                if (ret < 0)
 601                        goto err;
 602        }
 603
 604        for_each_rtdcom(rtd, rtdcom) {
 605                component = rtdcom->component;
 606
 607                if (!component->driver->compr_ops ||
 608                    !component->driver->compr_ops->get_params)
 609                        continue;
 610
 611                ret = component->driver->compr_ops->get_params(cstream, params);
 612                break;
 613        }
 614
 615err:
 616        mutex_unlock(&rtd->pcm_mutex);
 617        return ret;
 618}
 619
 620static int soc_compr_get_caps(struct snd_compr_stream *cstream,
 621                              struct snd_compr_caps *caps)
 622{
 623        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 624        struct snd_soc_component *component;
 625        struct snd_soc_rtdcom_list *rtdcom;
 626        int ret = 0;
 627
 628        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 629
 630        for_each_rtdcom(rtd, rtdcom) {
 631                component = rtdcom->component;
 632
 633                if (!component->driver->compr_ops ||
 634                    !component->driver->compr_ops->get_caps)
 635                        continue;
 636
 637                ret = component->driver->compr_ops->get_caps(cstream, caps);
 638                break;
 639        }
 640
 641        mutex_unlock(&rtd->pcm_mutex);
 642        return ret;
 643}
 644
 645static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
 646                                    struct snd_compr_codec_caps *codec)
 647{
 648        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 649        struct snd_soc_component *component;
 650        struct snd_soc_rtdcom_list *rtdcom;
 651        int ret = 0;
 652
 653        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 654
 655        for_each_rtdcom(rtd, rtdcom) {
 656                component = rtdcom->component;
 657
 658                if (!component->driver->compr_ops ||
 659                    !component->driver->compr_ops->get_codec_caps)
 660                        continue;
 661
 662                ret = component->driver->compr_ops->get_codec_caps(cstream,
 663                                                                   codec);
 664                break;
 665        }
 666
 667        mutex_unlock(&rtd->pcm_mutex);
 668        return ret;
 669}
 670
 671static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 672{
 673        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 674        struct snd_soc_component *component;
 675        struct snd_soc_rtdcom_list *rtdcom;
 676        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 677        int ret = 0;
 678
 679        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 680
 681        if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
 682                ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
 683                if (ret < 0)
 684                        goto err;
 685        }
 686
 687        for_each_rtdcom(rtd, rtdcom) {
 688                component = rtdcom->component;
 689
 690                if (!component->driver->compr_ops ||
 691                    !component->driver->compr_ops->ack)
 692                        continue;
 693
 694                ret = component->driver->compr_ops->ack(cstream, bytes);
 695                if (ret < 0)
 696                        goto err;
 697        }
 698
 699err:
 700        mutex_unlock(&rtd->pcm_mutex);
 701        return ret;
 702}
 703
 704static int soc_compr_pointer(struct snd_compr_stream *cstream,
 705                             struct snd_compr_tstamp *tstamp)
 706{
 707        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 708        struct snd_soc_component *component;
 709        struct snd_soc_rtdcom_list *rtdcom;
 710        int ret = 0;
 711        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 712
 713        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 714
 715        if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
 716                cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
 717
 718        for_each_rtdcom(rtd, rtdcom) {
 719                component = rtdcom->component;
 720
 721                if (!component->driver->compr_ops ||
 722                    !component->driver->compr_ops->pointer)
 723                        continue;
 724
 725                ret = component->driver->compr_ops->pointer(cstream, tstamp);
 726                break;
 727        }
 728
 729        mutex_unlock(&rtd->pcm_mutex);
 730        return ret;
 731}
 732
 733static int soc_compr_copy(struct snd_compr_stream *cstream,
 734                          char __user *buf, size_t count)
 735{
 736        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 737        struct snd_soc_component *component;
 738        struct snd_soc_rtdcom_list *rtdcom;
 739        int ret = 0;
 740
 741        mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 742
 743        for_each_rtdcom(rtd, rtdcom) {
 744                component = rtdcom->component;
 745
 746                if (!component->driver->compr_ops ||
 747                    !component->driver->compr_ops->copy)
 748                        continue;
 749
 750                ret = component->driver->compr_ops->copy(cstream, buf, count);
 751                break;
 752        }
 753
 754        mutex_unlock(&rtd->pcm_mutex);
 755        return ret;
 756}
 757
 758static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 759                                  struct snd_compr_metadata *metadata)
 760{
 761        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 762        struct snd_soc_component *component;
 763        struct snd_soc_rtdcom_list *rtdcom;
 764        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 765        int ret;
 766
 767        if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
 768                ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
 769                if (ret < 0)
 770                        return ret;
 771        }
 772
 773        for_each_rtdcom(rtd, rtdcom) {
 774                component = rtdcom->component;
 775
 776                if (!component->driver->compr_ops ||
 777                    !component->driver->compr_ops->set_metadata)
 778                        continue;
 779
 780                ret = component->driver->compr_ops->set_metadata(cstream,
 781                                                                 metadata);
 782                if (ret < 0)
 783                        return ret;
 784        }
 785
 786        return 0;
 787}
 788
 789static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
 790                                  struct snd_compr_metadata *metadata)
 791{
 792        struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 793        struct snd_soc_component *component;
 794        struct snd_soc_rtdcom_list *rtdcom;
 795        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 796        int ret;
 797
 798        if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
 799                ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
 800                if (ret < 0)
 801                        return ret;
 802        }
 803
 804        for_each_rtdcom(rtd, rtdcom) {
 805                component = rtdcom->component;
 806
 807                if (!component->driver->compr_ops ||
 808                    !component->driver->compr_ops->get_metadata)
 809                        continue;
 810
 811                return component->driver->compr_ops->get_metadata(cstream,
 812                                                                  metadata);
 813        }
 814
 815        return 0;
 816}
 817
 818/* ASoC Compress operations */
 819static struct snd_compr_ops soc_compr_ops = {
 820        .open           = soc_compr_open,
 821        .free           = soc_compr_free,
 822        .set_params     = soc_compr_set_params,
 823        .set_metadata   = soc_compr_set_metadata,
 824        .get_metadata   = soc_compr_get_metadata,
 825        .get_params     = soc_compr_get_params,
 826        .trigger        = soc_compr_trigger,
 827        .pointer        = soc_compr_pointer,
 828        .ack            = soc_compr_ack,
 829        .get_caps       = soc_compr_get_caps,
 830        .get_codec_caps = soc_compr_get_codec_caps
 831};
 832
 833/* ASoC Dynamic Compress operations */
 834static struct snd_compr_ops soc_compr_dyn_ops = {
 835        .open           = soc_compr_open_fe,
 836        .free           = soc_compr_free_fe,
 837        .set_params     = soc_compr_set_params_fe,
 838        .get_params     = soc_compr_get_params,
 839        .set_metadata   = soc_compr_set_metadata,
 840        .get_metadata   = soc_compr_get_metadata,
 841        .trigger        = soc_compr_trigger_fe,
 842        .pointer        = soc_compr_pointer,
 843        .ack            = soc_compr_ack,
 844        .get_caps       = soc_compr_get_caps,
 845        .get_codec_caps = soc_compr_get_codec_caps
 846};
 847
 848/**
 849 * snd_soc_new_compress - create a new compress.
 850 *
 851 * @rtd: The runtime for which we will create compress
 852 * @num: the device index number (zero based - shared with normal PCMs)
 853 *
 854 * Return: 0 for success, else error.
 855 */
 856int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
 857{
 858        struct snd_soc_component *component;
 859        struct snd_soc_rtdcom_list *rtdcom;
 860        struct snd_soc_dai *codec_dai = rtd->codec_dai;
 861        struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 862        struct snd_compr *compr;
 863        struct snd_pcm *be_pcm;
 864        char new_name[64];
 865        int ret = 0, direction = 0;
 866        int playback = 0, capture = 0;
 867
 868        if (rtd->num_codecs > 1) {
 869                dev_err(rtd->card->dev,
 870                        "Compress ASoC: Multicodec not supported\n");
 871                return -EINVAL;
 872        }
 873
 874        /* check client and interface hw capabilities */
 875        if (codec_dai->driver->playback.channels_min)
 876                playback = 1;
 877        if (codec_dai->driver->capture.channels_min)
 878                capture = 1;
 879
 880        capture = capture && cpu_dai->driver->capture.channels_min;
 881        playback = playback && cpu_dai->driver->playback.channels_min;
 882
 883        /*
 884         * Compress devices are unidirectional so only one of the directions
 885         * should be set, check for that (xor)
 886         */
 887        if (playback + capture != 1) {
 888                dev_err(rtd->card->dev,
 889                        "Compress ASoC: Invalid direction for P %d, C %d\n",
 890                        playback, capture);
 891                return -EINVAL;
 892        }
 893
 894        if (playback)
 895                direction = SND_COMPRESS_PLAYBACK;
 896        else
 897                direction = SND_COMPRESS_CAPTURE;
 898
 899        compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
 900        if (!compr)
 901                return -ENOMEM;
 902
 903        compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
 904                                  GFP_KERNEL);
 905        if (!compr->ops)
 906                return -ENOMEM;
 907
 908        if (rtd->dai_link->dynamic) {
 909                snprintf(new_name, sizeof(new_name), "(%s)",
 910                        rtd->dai_link->stream_name);
 911
 912                ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
 913                                rtd->dai_link->dpcm_playback,
 914                                rtd->dai_link->dpcm_capture, &be_pcm);
 915                if (ret < 0) {
 916                        dev_err(rtd->card->dev,
 917                                "Compress ASoC: can't create compressed for %s: %d\n",
 918                                rtd->dai_link->name, ret);
 919                        return ret;
 920                }
 921
 922                rtd->pcm = be_pcm;
 923                rtd->fe_compr = 1;
 924                if (rtd->dai_link->dpcm_playback)
 925                        be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
 926                else if (rtd->dai_link->dpcm_capture)
 927                        be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
 928                memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
 929        } else {
 930                snprintf(new_name, sizeof(new_name), "%s %s-%d",
 931                        rtd->dai_link->stream_name, codec_dai->name, num);
 932
 933                memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
 934        }
 935
 936        for_each_rtdcom(rtd, rtdcom) {
 937                component = rtdcom->component;
 938
 939                if (!component->driver->compr_ops ||
 940                    !component->driver->compr_ops->copy)
 941                        continue;
 942
 943                compr->ops->copy = soc_compr_copy;
 944                break;
 945        }
 946
 947        mutex_init(&compr->lock);
 948        ret = snd_compress_new(rtd->card->snd_card, num, direction,
 949                                new_name, compr);
 950        if (ret < 0) {
 951                component = rtd->codec_dai->component;
 952                dev_err(component->dev,
 953                        "Compress ASoC: can't create compress for codec %s: %d\n",
 954                        component->name, ret);
 955                return ret;
 956        }
 957
 958        /* DAPM dai link stream work */
 959        INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
 960
 961        rtd->compr = compr;
 962        compr->private_data = rtd;
 963
 964        dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
 965                 codec_dai->name, cpu_dai->name);
 966
 967        return 0;
 968}
 969EXPORT_SYMBOL_GPL(snd_soc_new_compress);
 970