root/sound/soc/soc-compress.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. soc_compr_components_open
  2. soc_compr_components_free
  3. soc_compr_open
  4. soc_compr_open_fe
  5. close_delayed_work
  6. soc_compr_free
  7. soc_compr_free_fe
  8. soc_compr_components_trigger
  9. soc_compr_trigger
  10. soc_compr_trigger_fe
  11. soc_compr_components_set_params
  12. soc_compr_set_params
  13. soc_compr_set_params_fe
  14. soc_compr_get_params
  15. soc_compr_get_caps
  16. soc_compr_get_codec_caps
  17. soc_compr_ack
  18. soc_compr_pointer
  19. soc_compr_copy
  20. soc_compr_set_metadata
  21. soc_compr_get_metadata
  22. snd_soc_new_compress

   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 
  23 static 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 
  53 static 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 
  76 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 112 
 113         return 0;
 114 
 115 machine_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);
 120 out:
 121         mutex_unlock(&rtd->card->pcm_mutex);
 122         return ret;
 123 }
 124 
 125 static 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 
 203 machine_err:
 204         soc_compr_components_free(cstream, component);
 205 open_err:
 206         if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 207                 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 208 out:
 209         dpcm_path_put(&list);
 210 be_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  */
 221 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 243 }
 244 
 245 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 296         return 0;
 297 }
 298 
 299 static 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 
 348 static 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 
 371 static 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->card->pcm_mutex, rtd->card->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 
 396 out:
 397         mutex_unlock(&rtd->card->pcm_mutex);
 398         return ret;
 399 }
 400 
 401 static 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 
 447 out:
 448         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 449         mutex_unlock(&fe->card->mutex);
 450         return ret;
 451 }
 452 
 453 static 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 
 476 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 518 
 519         cancel_delayed_work_sync(&rtd->delayed_work);
 520 
 521         return 0;
 522 
 523 err:
 524         mutex_unlock(&rtd->card->pcm_mutex);
 525         return ret;
 526 }
 527 
 528 static 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 
 581 out:
 582         fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 583         mutex_unlock(&fe->card->mutex);
 584         return ret;
 585 }
 586 
 587 static 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->card->pcm_mutex, rtd->card->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 
 615 err:
 616         mutex_unlock(&rtd->card->pcm_mutex);
 617         return ret;
 618 }
 619 
 620 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 642         return ret;
 643 }
 644 
 645 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 668         return ret;
 669 }
 670 
 671 static 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->card->pcm_mutex, rtd->card->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 
 699 err:
 700         mutex_unlock(&rtd->card->pcm_mutex);
 701         return ret;
 702 }
 703 
 704 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 730         return ret;
 731 }
 732 
 733 static 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->card->pcm_mutex, rtd->card->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->card->pcm_mutex);
 755         return ret;
 756 }
 757 
 758 static 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 
 789 static 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 */
 819 static 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 */
 834 static 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  */
 856 int 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 (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
 876             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
 877                 playback = 1;
 878         if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
 879             snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
 880                 capture = 1;
 881 
 882         /*
 883          * Compress devices are unidirectional so only one of the directions
 884          * should be set, check for that (xor)
 885          */
 886         if (playback + capture != 1) {
 887                 dev_err(rtd->card->dev,
 888                         "Compress ASoC: Invalid direction for P %d, C %d\n",
 889                         playback, capture);
 890                 return -EINVAL;
 891         }
 892 
 893         if (playback)
 894                 direction = SND_COMPRESS_PLAYBACK;
 895         else
 896                 direction = SND_COMPRESS_CAPTURE;
 897 
 898         compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
 899         if (!compr)
 900                 return -ENOMEM;
 901 
 902         compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
 903                                   GFP_KERNEL);
 904         if (!compr->ops)
 905                 return -ENOMEM;
 906 
 907         if (rtd->dai_link->dynamic) {
 908                 snprintf(new_name, sizeof(new_name), "(%s)",
 909                         rtd->dai_link->stream_name);
 910 
 911                 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
 912                                 rtd->dai_link->dpcm_playback,
 913                                 rtd->dai_link->dpcm_capture, &be_pcm);
 914                 if (ret < 0) {
 915                         dev_err(rtd->card->dev,
 916                                 "Compress ASoC: can't create compressed for %s: %d\n",
 917                                 rtd->dai_link->name, ret);
 918                         return ret;
 919                 }
 920 
 921                 rtd->pcm = be_pcm;
 922                 rtd->fe_compr = 1;
 923                 if (rtd->dai_link->dpcm_playback)
 924                         be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
 925                 else if (rtd->dai_link->dpcm_capture)
 926                         be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
 927                 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
 928         } else {
 929                 snprintf(new_name, sizeof(new_name), "%s %s-%d",
 930                         rtd->dai_link->stream_name, codec_dai->name, num);
 931 
 932                 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
 933         }
 934 
 935         for_each_rtdcom(rtd, rtdcom) {
 936                 component = rtdcom->component;
 937 
 938                 if (!component->driver->compr_ops ||
 939                     !component->driver->compr_ops->copy)
 940                         continue;
 941 
 942                 compr->ops->copy = soc_compr_copy;
 943                 break;
 944         }
 945 
 946         mutex_init(&compr->lock);
 947         ret = snd_compress_new(rtd->card->snd_card, num, direction,
 948                                 new_name, compr);
 949         if (ret < 0) {
 950                 component = rtd->codec_dai->component;
 951                 dev_err(component->dev,
 952                         "Compress ASoC: can't create compress for codec %s: %d\n",
 953                         component->name, ret);
 954                 return ret;
 955         }
 956 
 957         /* DAPM dai link stream work */
 958         INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
 959 
 960         rtd->compr = compr;
 961         compr->private_data = rtd;
 962 
 963         dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
 964                  codec_dai->name, cpu_dai->name);
 965 
 966         return 0;
 967 }
 968 EXPORT_SYMBOL_GPL(snd_soc_new_compress);

/* [<][>][^][v][top][bottom][index][help] */