Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // soc-compress.c  --  ALSA SoC Compress
0004 //
0005 // Copyright (C) 2012 Intel Corp.
0006 //
0007 // Authors: Namarta Kohli <namartax.kohli@intel.com>
0008 //          Ramesh Babu K V <ramesh.babu@linux.intel.com>
0009 //          Vinod Koul <vinod.koul@linux.intel.com>
0010 
0011 #include <linux/kernel.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/slab.h>
0015 #include <linux/workqueue.h>
0016 #include <sound/core.h>
0017 #include <sound/compress_params.h>
0018 #include <sound/compress_driver.h>
0019 #include <sound/soc.h>
0020 #include <sound/initval.h>
0021 #include <sound/soc-dpcm.h>
0022 #include <sound/soc-link.h>
0023 #include <linux/pm_runtime.h>
0024 
0025 static int snd_soc_compr_components_open(struct snd_compr_stream *cstream)
0026 {
0027     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0028     struct snd_soc_component *component;
0029     int ret = 0;
0030     int i;
0031 
0032     for_each_rtd_components(rtd, i, component) {
0033         ret = snd_soc_component_module_get_when_open(component, cstream);
0034         if (ret < 0)
0035             break;
0036 
0037         ret = snd_soc_component_compr_open(component, cstream);
0038         if (ret < 0)
0039             break;
0040     }
0041 
0042     return ret;
0043 }
0044 
0045 static void snd_soc_compr_components_free(struct snd_compr_stream *cstream,
0046                       int rollback)
0047 {
0048     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0049     struct snd_soc_component *component;
0050     int i;
0051 
0052     for_each_rtd_components(rtd, i, component) {
0053         snd_soc_component_compr_free(component, cstream, rollback);
0054         snd_soc_component_module_put_when_close(component, cstream, rollback);
0055     }
0056 }
0057 
0058 static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)
0059 {
0060     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0061     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0062     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0063     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0064 
0065     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0066 
0067     if (!rollback)
0068         snd_soc_runtime_deactivate(rtd, stream);
0069 
0070     snd_soc_dai_digital_mute(codec_dai, 1, stream);
0071 
0072     if (!snd_soc_dai_active(cpu_dai))
0073         cpu_dai->rate = 0;
0074 
0075     if (!snd_soc_dai_active(codec_dai))
0076         codec_dai->rate = 0;
0077 
0078     snd_soc_link_compr_shutdown(cstream, rollback);
0079 
0080     snd_soc_compr_components_free(cstream, rollback);
0081 
0082     snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback);
0083 
0084     if (!rollback)
0085         snd_soc_dapm_stream_stop(rtd, stream);
0086 
0087     mutex_unlock(&rtd->card->pcm_mutex);
0088 
0089     snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback);
0090 
0091     return 0;
0092 }
0093 
0094 static int soc_compr_free(struct snd_compr_stream *cstream)
0095 {
0096     return soc_compr_clean(cstream, 0);
0097 }
0098 
0099 static int soc_compr_open(struct snd_compr_stream *cstream)
0100 {
0101     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0102     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0103     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0104     int ret;
0105 
0106     ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
0107     if (ret < 0)
0108         goto err_no_lock;
0109 
0110     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0111 
0112     ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
0113     if (ret < 0)
0114         goto err;
0115 
0116     ret = snd_soc_compr_components_open(cstream);
0117     if (ret < 0)
0118         goto err;
0119 
0120     ret = snd_soc_link_compr_startup(cstream);
0121     if (ret < 0)
0122         goto err;
0123 
0124     snd_soc_runtime_activate(rtd, stream);
0125 err:
0126     mutex_unlock(&rtd->card->pcm_mutex);
0127 err_no_lock:
0128     if (ret < 0)
0129         soc_compr_clean(cstream, 1);
0130 
0131     return ret;
0132 }
0133 
0134 static int soc_compr_open_fe(struct snd_compr_stream *cstream)
0135 {
0136     struct snd_soc_pcm_runtime *fe = cstream->private_data;
0137     struct snd_pcm_substream *fe_substream =
0138          fe->pcm->streams[cstream->direction].substream;
0139     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
0140     struct snd_soc_dpcm *dpcm;
0141     struct snd_soc_dapm_widget_list *list;
0142     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0143     int ret;
0144 
0145     mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
0146     fe->dpcm[stream].runtime = fe_substream->runtime;
0147 
0148     ret = dpcm_path_get(fe, stream, &list);
0149     if (ret < 0)
0150         goto be_err;
0151 
0152     /* calculate valid and active FE <-> BE dpcms */
0153     dpcm_process_paths(fe, stream, &list, 1);
0154     fe->dpcm[stream].runtime = fe_substream->runtime;
0155 
0156     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
0157 
0158     ret = dpcm_be_dai_startup(fe, stream);
0159     if (ret < 0) {
0160         /* clean up all links */
0161         for_each_dpcm_be(fe, stream, dpcm)
0162             dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
0163 
0164         dpcm_be_disconnect(fe, stream);
0165         fe->dpcm[stream].runtime = NULL;
0166         goto out;
0167     }
0168 
0169     ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
0170     if (ret < 0)
0171         goto out;
0172 
0173     ret = snd_soc_compr_components_open(cstream);
0174     if (ret < 0)
0175         goto open_err;
0176 
0177     ret = snd_soc_link_compr_startup(cstream);
0178     if (ret < 0)
0179         goto machine_err;
0180 
0181     dpcm_clear_pending_state(fe, stream);
0182     dpcm_path_put(&list);
0183 
0184     fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
0185     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
0186 
0187     mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
0188     snd_soc_runtime_activate(fe, stream);
0189     mutex_unlock(&fe->card->pcm_mutex);
0190 
0191     mutex_unlock(&fe->card->mutex);
0192 
0193     return 0;
0194 
0195 machine_err:
0196     snd_soc_compr_components_free(cstream, 1);
0197 open_err:
0198     snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1);
0199 out:
0200     dpcm_path_put(&list);
0201 be_err:
0202     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
0203     mutex_unlock(&fe->card->mutex);
0204     return ret;
0205 }
0206 
0207 static int soc_compr_free_fe(struct snd_compr_stream *cstream)
0208 {
0209     struct snd_soc_pcm_runtime *fe = cstream->private_data;
0210     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
0211     struct snd_soc_dpcm *dpcm;
0212     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0213 
0214     mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
0215 
0216     mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass);
0217     snd_soc_runtime_deactivate(fe, stream);
0218     mutex_unlock(&fe->card->pcm_mutex);
0219 
0220     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
0221 
0222     dpcm_be_dai_hw_free(fe, stream);
0223 
0224     dpcm_be_dai_shutdown(fe, stream);
0225 
0226     /* mark FE's links ready to prune */
0227     for_each_dpcm_be(fe, stream, dpcm)
0228         dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
0229 
0230     dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
0231 
0232     fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
0233     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
0234 
0235     dpcm_be_disconnect(fe, stream);
0236 
0237     fe->dpcm[stream].runtime = NULL;
0238 
0239     snd_soc_link_compr_shutdown(cstream, 0);
0240 
0241     snd_soc_compr_components_free(cstream, 0);
0242 
0243     snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0);
0244 
0245     mutex_unlock(&fe->card->mutex);
0246     return 0;
0247 }
0248 
0249 static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
0250 {
0251     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0252     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0253     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0254     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0255     int ret;
0256 
0257     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0258 
0259     ret = snd_soc_component_compr_trigger(cstream, cmd);
0260     if (ret < 0)
0261         goto out;
0262 
0263     ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
0264     if (ret < 0)
0265         goto out;
0266 
0267     switch (cmd) {
0268     case SNDRV_PCM_TRIGGER_START:
0269         snd_soc_dai_digital_mute(codec_dai, 0, stream);
0270         break;
0271     case SNDRV_PCM_TRIGGER_STOP:
0272         snd_soc_dai_digital_mute(codec_dai, 1, stream);
0273         break;
0274     }
0275 
0276 out:
0277     mutex_unlock(&rtd->card->pcm_mutex);
0278     return ret;
0279 }
0280 
0281 static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
0282 {
0283     struct snd_soc_pcm_runtime *fe = cstream->private_data;
0284     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
0285     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0286     int ret;
0287 
0288     if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
0289         cmd == SND_COMPR_TRIGGER_DRAIN)
0290         return snd_soc_component_compr_trigger(cstream, cmd);
0291 
0292     mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
0293 
0294     ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
0295     if (ret < 0)
0296         goto out;
0297 
0298     ret = snd_soc_component_compr_trigger(cstream, cmd);
0299     if (ret < 0)
0300         goto out;
0301 
0302     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
0303 
0304     ret = dpcm_be_dai_trigger(fe, stream, cmd);
0305 
0306     switch (cmd) {
0307     case SNDRV_PCM_TRIGGER_START:
0308     case SNDRV_PCM_TRIGGER_RESUME:
0309     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0310         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
0311         break;
0312     case SNDRV_PCM_TRIGGER_STOP:
0313     case SNDRV_PCM_TRIGGER_SUSPEND:
0314         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
0315         break;
0316     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0317         fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
0318         break;
0319     }
0320 
0321 out:
0322     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
0323     mutex_unlock(&fe->card->mutex);
0324     return ret;
0325 }
0326 
0327 static int soc_compr_set_params(struct snd_compr_stream *cstream,
0328                 struct snd_compr_params *params)
0329 {
0330     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0331     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0332     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0333     int ret;
0334 
0335     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0336 
0337     /*
0338      * First we call set_params for the CPU DAI, then the component
0339      * driver this should configure the SoC side. If the machine has
0340      * compressed ops then we call that as well. The expectation is
0341      * that these callbacks will configure everything for this compress
0342      * path, like configuring a PCM port for a CODEC.
0343      */
0344     ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
0345     if (ret < 0)
0346         goto err;
0347 
0348     ret = snd_soc_component_compr_set_params(cstream, params);
0349     if (ret < 0)
0350         goto err;
0351 
0352     ret = snd_soc_link_compr_set_params(cstream);
0353     if (ret < 0)
0354         goto err;
0355 
0356     snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
0357 
0358     /* cancel any delayed stream shutdown that is pending */
0359     rtd->pop_wait = 0;
0360     mutex_unlock(&rtd->card->pcm_mutex);
0361 
0362     cancel_delayed_work_sync(&rtd->delayed_work);
0363 
0364     return 0;
0365 
0366 err:
0367     mutex_unlock(&rtd->card->pcm_mutex);
0368     return ret;
0369 }
0370 
0371 static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
0372                    struct snd_compr_params *params)
0373 {
0374     struct snd_soc_pcm_runtime *fe = cstream->private_data;
0375     struct snd_pcm_substream *fe_substream =
0376          fe->pcm->streams[cstream->direction].substream;
0377     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
0378     int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
0379     int ret;
0380 
0381     mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
0382 
0383     /*
0384      * Create an empty hw_params for the BE as the machine driver must
0385      * fix this up to match DSP decoder and ASRC configuration.
0386      * I.e. machine driver fixup for compressed BE is mandatory.
0387      */
0388     memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
0389         sizeof(struct snd_pcm_hw_params));
0390 
0391     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
0392 
0393     ret = dpcm_be_dai_hw_params(fe, stream);
0394     if (ret < 0)
0395         goto out;
0396 
0397     ret = dpcm_be_dai_prepare(fe, stream);
0398     if (ret < 0)
0399         goto out;
0400 
0401     ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
0402     if (ret < 0)
0403         goto out;
0404 
0405     ret = snd_soc_component_compr_set_params(cstream, params);
0406     if (ret < 0)
0407         goto out;
0408 
0409     ret = snd_soc_link_compr_set_params(cstream);
0410     if (ret < 0)
0411         goto out;
0412 
0413     dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
0414     fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
0415 
0416 out:
0417     fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
0418     mutex_unlock(&fe->card->mutex);
0419     return ret;
0420 }
0421 
0422 static int soc_compr_get_params(struct snd_compr_stream *cstream,
0423                 struct snd_codec *params)
0424 {
0425     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0426     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0427     int ret = 0;
0428 
0429     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0430 
0431     ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
0432     if (ret < 0)
0433         goto err;
0434 
0435     ret = snd_soc_component_compr_get_params(cstream, params);
0436 err:
0437     mutex_unlock(&rtd->card->pcm_mutex);
0438     return ret;
0439 }
0440 
0441 static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
0442 {
0443     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0444     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0445     int ret;
0446 
0447     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0448 
0449     ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
0450     if (ret < 0)
0451         goto err;
0452 
0453     ret = snd_soc_component_compr_ack(cstream, bytes);
0454 err:
0455     mutex_unlock(&rtd->card->pcm_mutex);
0456     return ret;
0457 }
0458 
0459 static int soc_compr_pointer(struct snd_compr_stream *cstream,
0460                  struct snd_compr_tstamp *tstamp)
0461 {
0462     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0463     int ret;
0464     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0465 
0466     mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
0467 
0468     ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
0469     if (ret < 0)
0470         goto out;
0471 
0472     ret = snd_soc_component_compr_pointer(cstream, tstamp);
0473 out:
0474     mutex_unlock(&rtd->card->pcm_mutex);
0475     return ret;
0476 }
0477 
0478 static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
0479                   struct snd_compr_metadata *metadata)
0480 {
0481     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0482     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0483     int ret;
0484 
0485     ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
0486     if (ret < 0)
0487         return ret;
0488 
0489     return snd_soc_component_compr_set_metadata(cstream, metadata);
0490 }
0491 
0492 static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
0493                   struct snd_compr_metadata *metadata)
0494 {
0495     struct snd_soc_pcm_runtime *rtd = cstream->private_data;
0496     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0497     int ret;
0498 
0499     ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
0500     if (ret < 0)
0501         return ret;
0502 
0503     return snd_soc_component_compr_get_metadata(cstream, metadata);
0504 }
0505 
0506 /* ASoC Compress operations */
0507 static struct snd_compr_ops soc_compr_ops = {
0508     .open       = soc_compr_open,
0509     .free       = soc_compr_free,
0510     .set_params = soc_compr_set_params,
0511     .set_metadata   = soc_compr_set_metadata,
0512     .get_metadata   = soc_compr_get_metadata,
0513     .get_params = soc_compr_get_params,
0514     .trigger    = soc_compr_trigger,
0515     .pointer    = soc_compr_pointer,
0516     .ack        = soc_compr_ack,
0517     .get_caps   = snd_soc_component_compr_get_caps,
0518     .get_codec_caps = snd_soc_component_compr_get_codec_caps,
0519 };
0520 
0521 /* ASoC Dynamic Compress operations */
0522 static struct snd_compr_ops soc_compr_dyn_ops = {
0523     .open       = soc_compr_open_fe,
0524     .free       = soc_compr_free_fe,
0525     .set_params = soc_compr_set_params_fe,
0526     .get_params = soc_compr_get_params,
0527     .set_metadata   = soc_compr_set_metadata,
0528     .get_metadata   = soc_compr_get_metadata,
0529     .trigger    = soc_compr_trigger_fe,
0530     .pointer    = soc_compr_pointer,
0531     .ack        = soc_compr_ack,
0532     .get_caps   = snd_soc_component_compr_get_caps,
0533     .get_codec_caps = snd_soc_component_compr_get_codec_caps,
0534 };
0535 
0536 /**
0537  * snd_soc_new_compress - create a new compress.
0538  *
0539  * @rtd: The runtime for which we will create compress
0540  * @num: the device index number (zero based - shared with normal PCMs)
0541  *
0542  * Return: 0 for success, else error.
0543  */
0544 int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
0545 {
0546     struct snd_soc_component *component;
0547     struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
0548     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0549     struct snd_compr *compr;
0550     struct snd_pcm *be_pcm;
0551     char new_name[64];
0552     int ret = 0, direction = 0;
0553     int playback = 0, capture = 0;
0554     int i;
0555 
0556     /*
0557      * make sure these are same value,
0558      * and then use these as equally
0559      */
0560     BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
0561     BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE  != (int)SND_COMPRESS_CAPTURE);
0562 
0563     if (rtd->num_cpus > 1 ||
0564         rtd->num_codecs > 1) {
0565         dev_err(rtd->card->dev,
0566             "Compress ASoC: Multi CPU/Codec not supported\n");
0567         return -EINVAL;
0568     }
0569 
0570     if (!codec_dai) {
0571         dev_err(rtd->card->dev, "Missing codec\n");
0572         return -EINVAL;
0573     }
0574 
0575     /* check client and interface hw capabilities */
0576     if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
0577         snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
0578         playback = 1;
0579     if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
0580         snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
0581         capture = 1;
0582 
0583     /*
0584      * Compress devices are unidirectional so only one of the directions
0585      * should be set, check for that (xor)
0586      */
0587     if (playback + capture != 1) {
0588         dev_err(rtd->card->dev,
0589             "Compress ASoC: Invalid direction for P %d, C %d\n",
0590             playback, capture);
0591         return -EINVAL;
0592     }
0593 
0594     if (playback)
0595         direction = SND_COMPRESS_PLAYBACK;
0596     else
0597         direction = SND_COMPRESS_CAPTURE;
0598 
0599     compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
0600     if (!compr)
0601         return -ENOMEM;
0602 
0603     compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
0604                   GFP_KERNEL);
0605     if (!compr->ops)
0606         return -ENOMEM;
0607 
0608     if (rtd->dai_link->dynamic) {
0609         snprintf(new_name, sizeof(new_name), "(%s)",
0610             rtd->dai_link->stream_name);
0611 
0612         ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
0613                 rtd->dai_link->dpcm_playback,
0614                 rtd->dai_link->dpcm_capture, &be_pcm);
0615         if (ret < 0) {
0616             dev_err(rtd->card->dev,
0617                 "Compress ASoC: can't create compressed for %s: %d\n",
0618                 rtd->dai_link->name, ret);
0619             return ret;
0620         }
0621 
0622         rtd->pcm = be_pcm;
0623         rtd->fe_compr = 1;
0624         if (rtd->dai_link->dpcm_playback)
0625             be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
0626         else if (rtd->dai_link->dpcm_capture)
0627             be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
0628         memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
0629     } else {
0630         snprintf(new_name, sizeof(new_name), "%s %s-%d",
0631             rtd->dai_link->stream_name, codec_dai->name, num);
0632 
0633         memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
0634     }
0635 
0636     for_each_rtd_components(rtd, i, component) {
0637         if (!component->driver->compress_ops ||
0638             !component->driver->compress_ops->copy)
0639             continue;
0640 
0641         compr->ops->copy = snd_soc_component_compr_copy;
0642         break;
0643     }
0644 
0645     ret = snd_compress_new(rtd->card->snd_card, num, direction,
0646                 new_name, compr);
0647     if (ret < 0) {
0648         component = asoc_rtd_to_codec(rtd, 0)->component;
0649         dev_err(component->dev,
0650             "Compress ASoC: can't create compress for codec %s: %d\n",
0651             component->name, ret);
0652         return ret;
0653     }
0654 
0655     /* DAPM dai link stream work */
0656     rtd->close_delayed_work_func = snd_soc_close_delayed_work;
0657 
0658     rtd->compr = compr;
0659     compr->private_data = rtd;
0660 
0661     dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
0662         codec_dai->name, cpu_dai->name);
0663 
0664     return 0;
0665 }
0666 EXPORT_SYMBOL_GPL(snd_soc_new_compress);