Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // soc-dai.c
0004 //
0005 // Copyright (C) 2019 Renesas Electronics Corp.
0006 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
0007 //
0008 
0009 #include <sound/soc.h>
0010 #include <sound/soc-dai.h>
0011 #include <sound/soc-link.h>
0012 
0013 #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
0014 static inline int _soc_dai_ret(struct snd_soc_dai *dai,
0015                    const char *func, int ret)
0016 {
0017     /* Positive, Zero values are not errors */
0018     if (ret >= 0)
0019         return ret;
0020 
0021     /* Negative values might be errors */
0022     switch (ret) {
0023     case -EPROBE_DEFER:
0024     case -ENOTSUPP:
0025         break;
0026     default:
0027         dev_err(dai->dev,
0028             "ASoC: error at %s on %s: %d\n",
0029             func, dai->name, ret);
0030     }
0031 
0032     return ret;
0033 }
0034 
0035 /*
0036  * We might want to check substream by using list.
0037  * In such case, we can update these macros.
0038  */
0039 #define soc_dai_mark_push(dai, substream, tgt)  ((dai)->mark_##tgt = substream)
0040 #define soc_dai_mark_pop(dai, substream, tgt)   ((dai)->mark_##tgt = NULL)
0041 #define soc_dai_mark_match(dai, substream, tgt) ((dai)->mark_##tgt == substream)
0042 
0043 /**
0044  * snd_soc_dai_set_sysclk - configure DAI system or master clock.
0045  * @dai: DAI
0046  * @clk_id: DAI specific clock ID
0047  * @freq: new clock frequency in Hz
0048  * @dir: new clock direction - input/output.
0049  *
0050  * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
0051  */
0052 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
0053                unsigned int freq, int dir)
0054 {
0055     int ret;
0056 
0057     if (dai->driver->ops &&
0058         dai->driver->ops->set_sysclk)
0059         ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
0060     else
0061         ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
0062                            freq, dir);
0063 
0064     return soc_dai_ret(dai, ret);
0065 }
0066 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
0067 
0068 /**
0069  * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
0070  * @dai: DAI
0071  * @div_id: DAI specific clock divider ID
0072  * @div: new clock divisor.
0073  *
0074  * Configures the clock dividers. This is used to derive the best DAI bit and
0075  * frame clocks from the system or master clock. It's best to set the DAI bit
0076  * and frame clocks as low as possible to save system power.
0077  */
0078 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
0079                int div_id, int div)
0080 {
0081     int ret = -EINVAL;
0082 
0083     if (dai->driver->ops &&
0084         dai->driver->ops->set_clkdiv)
0085         ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
0086 
0087     return soc_dai_ret(dai, ret);
0088 }
0089 EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
0090 
0091 /**
0092  * snd_soc_dai_set_pll - configure DAI PLL.
0093  * @dai: DAI
0094  * @pll_id: DAI specific PLL ID
0095  * @source: DAI specific source for the PLL
0096  * @freq_in: PLL input clock frequency in Hz
0097  * @freq_out: requested PLL output clock frequency in Hz
0098  *
0099  * Configures and enables PLL to generate output clock based on input clock.
0100  */
0101 int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
0102             unsigned int freq_in, unsigned int freq_out)
0103 {
0104     int ret;
0105 
0106     if (dai->driver->ops &&
0107         dai->driver->ops->set_pll)
0108         ret = dai->driver->ops->set_pll(dai, pll_id, source,
0109                         freq_in, freq_out);
0110     else
0111         ret = snd_soc_component_set_pll(dai->component, pll_id, source,
0112                         freq_in, freq_out);
0113 
0114     return soc_dai_ret(dai, ret);
0115 }
0116 EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
0117 
0118 /**
0119  * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
0120  * @dai: DAI
0121  * @ratio: Ratio of BCLK to Sample rate.
0122  *
0123  * Configures the DAI for a preset BCLK to sample rate ratio.
0124  */
0125 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
0126 {
0127     int ret = -EINVAL;
0128 
0129     if (dai->driver->ops &&
0130         dai->driver->ops->set_bclk_ratio)
0131         ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
0132 
0133     return soc_dai_ret(dai, ret);
0134 }
0135 EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
0136 
0137 int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd)
0138 {
0139     struct snd_soc_dai *dai;
0140     int i, max = 0;
0141 
0142     /*
0143      * return max num if *ALL* DAIs have .auto_selectable_formats
0144      */
0145     for_each_rtd_dais(rtd, i, dai) {
0146         if (dai->driver->ops &&
0147             dai->driver->ops->num_auto_selectable_formats)
0148             max = max(max, dai->driver->ops->num_auto_selectable_formats);
0149         else
0150             return 0;
0151     }
0152 
0153     return max;
0154 }
0155 
0156 /**
0157  * snd_soc_dai_get_fmt - get supported audio format.
0158  * @dai: DAI
0159  * @priority: priority level of supported audio format.
0160  *
0161  * This should return only formats implemented with high
0162  * quality by the DAI so that the core can configure a
0163  * format which will work well with other devices.
0164  * For example devices which don't support both edges of the
0165  * LRCLK signal in I2S style formats should only list DSP
0166  * modes.  This will mean that sometimes fewer formats
0167  * are reported here than are supported by set_fmt().
0168  */
0169 u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority)
0170 {
0171     const struct snd_soc_dai_ops *ops = dai->driver->ops;
0172     u64 fmt = 0;
0173     int i, max = 0, until = priority;
0174 
0175     /*
0176      * Collect auto_selectable_formats until priority
0177      *
0178      * ex)
0179      *  auto_selectable_formats[] = { A, B, C };
0180      *  (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)
0181      *
0182      * priority = 1 :   A
0183      * priority = 2 :   A | B
0184      * priority = 3 :   A | B | C
0185      * priority = 4 :   A | B | C
0186      * ...
0187      */
0188     if (ops)
0189         max = ops->num_auto_selectable_formats;
0190 
0191     if (max < until)
0192         until = max;
0193 
0194     for (i = 0; i < until; i++)
0195         fmt |= ops->auto_selectable_formats[i];
0196 
0197     return fmt;
0198 }
0199 
0200 /**
0201  * snd_soc_dai_set_fmt - configure DAI hardware audio format.
0202  * @dai: DAI
0203  * @fmt: SND_SOC_DAIFMT_* format value.
0204  *
0205  * Configures the DAI hardware format and clocking.
0206  */
0207 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0208 {
0209     int ret = -ENOTSUPP;
0210 
0211     if (dai->driver->ops && dai->driver->ops->set_fmt)
0212         ret = dai->driver->ops->set_fmt(dai, fmt);
0213 
0214     return soc_dai_ret(dai, ret);
0215 }
0216 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
0217 
0218 /**
0219  * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask.
0220  * @slots: Number of slots in use.
0221  * @tx_mask: bitmask representing active TX slots.
0222  * @rx_mask: bitmask representing active RX slots.
0223  *
0224  * Generates the TDM tx and rx slot default masks for DAI.
0225  */
0226 static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
0227                        unsigned int *tx_mask,
0228                        unsigned int *rx_mask)
0229 {
0230     if (*tx_mask || *rx_mask)
0231         return 0;
0232 
0233     if (!slots)
0234         return -EINVAL;
0235 
0236     *tx_mask = (1 << slots) - 1;
0237     *rx_mask = (1 << slots) - 1;
0238 
0239     return 0;
0240 }
0241 
0242 /**
0243  * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
0244  * @dai: The DAI to configure
0245  * @tx_mask: bitmask representing active TX slots.
0246  * @rx_mask: bitmask representing active RX slots.
0247  * @slots: Number of slots in use.
0248  * @slot_width: Width in bits for each slot.
0249  *
0250  * This function configures the specified DAI for TDM operation. @slot contains
0251  * the total number of slots of the TDM stream and @slot_with the width of each
0252  * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
0253  * active slots of the TDM stream for the specified DAI, i.e. which slots the
0254  * DAI should write to or read from. If a bit is set the corresponding slot is
0255  * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
0256  * the first slot, bit 1 to the second slot and so on. The first active slot
0257  * maps to the first channel of the DAI, the second active slot to the second
0258  * channel and so on.
0259  *
0260  * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
0261  * @rx_mask and @slot_width will be ignored.
0262  *
0263  * Returns 0 on success, a negative error code otherwise.
0264  */
0265 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
0266                  unsigned int tx_mask, unsigned int rx_mask,
0267                  int slots, int slot_width)
0268 {
0269     int ret = -ENOTSUPP;
0270 
0271     if (dai->driver->ops &&
0272         dai->driver->ops->xlate_tdm_slot_mask)
0273         dai->driver->ops->xlate_tdm_slot_mask(slots,
0274                               &tx_mask, &rx_mask);
0275     else
0276         snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
0277 
0278     dai->tx_mask = tx_mask;
0279     dai->rx_mask = rx_mask;
0280 
0281     if (dai->driver->ops &&
0282         dai->driver->ops->set_tdm_slot)
0283         ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
0284                               slots, slot_width);
0285     return soc_dai_ret(dai, ret);
0286 }
0287 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
0288 
0289 /**
0290  * snd_soc_dai_set_channel_map - configure DAI audio channel map
0291  * @dai: DAI
0292  * @tx_num: how many TX channels
0293  * @tx_slot: pointer to an array which imply the TX slot number channel
0294  *           0~num-1 uses
0295  * @rx_num: how many RX channels
0296  * @rx_slot: pointer to an array which imply the RX slot number channel
0297  *           0~num-1 uses
0298  *
0299  * configure the relationship between channel number and TDM slot number.
0300  */
0301 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
0302                 unsigned int tx_num, unsigned int *tx_slot,
0303                 unsigned int rx_num, unsigned int *rx_slot)
0304 {
0305     int ret = -ENOTSUPP;
0306 
0307     if (dai->driver->ops &&
0308         dai->driver->ops->set_channel_map)
0309         ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
0310                             rx_num, rx_slot);
0311     return soc_dai_ret(dai, ret);
0312 }
0313 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
0314 
0315 /**
0316  * snd_soc_dai_get_channel_map - Get DAI audio channel map
0317  * @dai: DAI
0318  * @tx_num: how many TX channels
0319  * @tx_slot: pointer to an array which imply the TX slot number channel
0320  *           0~num-1 uses
0321  * @rx_num: how many RX channels
0322  * @rx_slot: pointer to an array which imply the RX slot number channel
0323  *           0~num-1 uses
0324  */
0325 int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai,
0326                 unsigned int *tx_num, unsigned int *tx_slot,
0327                 unsigned int *rx_num, unsigned int *rx_slot)
0328 {
0329     int ret = -ENOTSUPP;
0330 
0331     if (dai->driver->ops &&
0332         dai->driver->ops->get_channel_map)
0333         ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
0334                             rx_num, rx_slot);
0335     return soc_dai_ret(dai, ret);
0336 }
0337 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
0338 
0339 /**
0340  * snd_soc_dai_set_tristate - configure DAI system or master clock.
0341  * @dai: DAI
0342  * @tristate: tristate enable
0343  *
0344  * Tristates the DAI so that others can use it.
0345  */
0346 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
0347 {
0348     int ret = -EINVAL;
0349 
0350     if (dai->driver->ops &&
0351         dai->driver->ops->set_tristate)
0352         ret = dai->driver->ops->set_tristate(dai, tristate);
0353 
0354     return soc_dai_ret(dai, ret);
0355 }
0356 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
0357 
0358 /**
0359  * snd_soc_dai_digital_mute - configure DAI system or master clock.
0360  * @dai: DAI
0361  * @mute: mute enable
0362  * @direction: stream to mute
0363  *
0364  * Mutes the DAI DAC.
0365  */
0366 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
0367                  int direction)
0368 {
0369     int ret = -ENOTSUPP;
0370 
0371     /*
0372      * ignore if direction was CAPTURE
0373      * and it had .no_capture_mute flag
0374      */
0375     if (dai->driver->ops &&
0376         dai->driver->ops->mute_stream &&
0377         (direction == SNDRV_PCM_STREAM_PLAYBACK ||
0378          !dai->driver->ops->no_capture_mute))
0379         ret = dai->driver->ops->mute_stream(dai, mute, direction);
0380 
0381     return soc_dai_ret(dai, ret);
0382 }
0383 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
0384 
0385 int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
0386               struct snd_pcm_substream *substream,
0387               struct snd_pcm_hw_params *params)
0388 {
0389     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0390     int ret = 0;
0391 
0392     if (dai->driver->ops &&
0393         dai->driver->ops->hw_params) {
0394         /* perform any topology hw_params fixups before DAI  */
0395         ret = snd_soc_link_be_hw_params_fixup(rtd, params);
0396         if (ret < 0)
0397             goto end;
0398 
0399         ret = dai->driver->ops->hw_params(substream, params, dai);
0400     }
0401 
0402     /* mark substream if succeeded */
0403     if (ret == 0)
0404         soc_dai_mark_push(dai, substream, hw_params);
0405 end:
0406     return soc_dai_ret(dai, ret);
0407 }
0408 
0409 void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
0410              struct snd_pcm_substream *substream,
0411              int rollback)
0412 {
0413     if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
0414         return;
0415 
0416     if (dai->driver->ops &&
0417         dai->driver->ops->hw_free)
0418         dai->driver->ops->hw_free(substream, dai);
0419 
0420     /* remove marked substream */
0421     soc_dai_mark_pop(dai, substream, hw_params);
0422 }
0423 
0424 int snd_soc_dai_startup(struct snd_soc_dai *dai,
0425             struct snd_pcm_substream *substream)
0426 {
0427     int ret = 0;
0428 
0429     if (dai->driver->ops &&
0430         dai->driver->ops->startup)
0431         ret = dai->driver->ops->startup(substream, dai);
0432 
0433     /* mark substream if succeeded */
0434     if (ret == 0)
0435         soc_dai_mark_push(dai, substream, startup);
0436 
0437     return soc_dai_ret(dai, ret);
0438 }
0439 
0440 void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
0441               struct snd_pcm_substream *substream,
0442               int rollback)
0443 {
0444     if (rollback && !soc_dai_mark_match(dai, substream, startup))
0445         return;
0446 
0447     if (dai->driver->ops &&
0448         dai->driver->ops->shutdown)
0449         dai->driver->ops->shutdown(substream, dai);
0450 
0451     /* remove marked substream */
0452     soc_dai_mark_pop(dai, substream, startup);
0453 }
0454 
0455 int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
0456                  struct snd_soc_pcm_runtime *rtd, int num)
0457 {
0458     int ret = -ENOTSUPP;
0459     if (dai->driver->compress_new)
0460         ret = dai->driver->compress_new(rtd, num);
0461     return soc_dai_ret(dai, ret);
0462 }
0463 
0464 /*
0465  * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
0466  *
0467  * Returns true if the DAI supports the indicated stream type.
0468  */
0469 bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir)
0470 {
0471     struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
0472 
0473     /* If the codec specifies any channels at all, it supports the stream */
0474     return stream->channels_min;
0475 }
0476 
0477 /*
0478  * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs
0479  */
0480 void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link)
0481 {
0482     bool supported[SNDRV_PCM_STREAM_LAST + 1];
0483     int direction;
0484 
0485     for_each_pcm_streams(direction) {
0486         struct snd_soc_dai_link_component *cpu;
0487         struct snd_soc_dai_link_component *codec;
0488         struct snd_soc_dai *dai;
0489         bool supported_cpu = false;
0490         bool supported_codec = false;
0491         int i;
0492 
0493         for_each_link_cpus(dai_link, i, cpu) {
0494             dai = snd_soc_find_dai_with_mutex(cpu);
0495             if (dai && snd_soc_dai_stream_valid(dai, direction)) {
0496                 supported_cpu = true;
0497                 break;
0498             }
0499         }
0500         for_each_link_codecs(dai_link, i, codec) {
0501             dai = snd_soc_find_dai_with_mutex(codec);
0502             if (dai && snd_soc_dai_stream_valid(dai, direction)) {
0503                 supported_codec = true;
0504                 break;
0505             }
0506         }
0507         supported[direction] = supported_cpu && supported_codec;
0508     }
0509 
0510     dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK];
0511     dai_link->dpcm_capture  = supported[SNDRV_PCM_STREAM_CAPTURE];
0512 }
0513 EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities);
0514 
0515 void snd_soc_dai_action(struct snd_soc_dai *dai,
0516             int stream, int action)
0517 {
0518     /* see snd_soc_dai_stream_active() */
0519     dai->stream_active[stream]  += action;
0520 
0521     /* see snd_soc_component_active() */
0522     dai->component->active      += action;
0523 }
0524 EXPORT_SYMBOL_GPL(snd_soc_dai_action);
0525 
0526 int snd_soc_dai_active(struct snd_soc_dai *dai)
0527 {
0528     int stream, active;
0529 
0530     active = 0;
0531     for_each_pcm_streams(stream)
0532         active += dai->stream_active[stream];
0533 
0534     return active;
0535 }
0536 EXPORT_SYMBOL_GPL(snd_soc_dai_active);
0537 
0538 int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
0539 {
0540     struct snd_soc_dai *dai;
0541     int i;
0542 
0543     for_each_rtd_dais(rtd, i, dai) {
0544         if (dai->driver->probe_order != order)
0545             continue;
0546 
0547         if (dai->driver->probe) {
0548             int ret = dai->driver->probe(dai);
0549 
0550             if (ret < 0)
0551                 return soc_dai_ret(dai, ret);
0552         }
0553 
0554         dai->probed = 1;
0555     }
0556 
0557     return 0;
0558 }
0559 
0560 int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
0561 {
0562     struct snd_soc_dai *dai;
0563     int i, r, ret = 0;
0564 
0565     for_each_rtd_dais(rtd, i, dai) {
0566         if (dai->driver->remove_order != order)
0567             continue;
0568 
0569         if (dai->probed &&
0570             dai->driver->remove) {
0571             r = dai->driver->remove(dai);
0572             if (r < 0)
0573                 ret = r; /* use last error */
0574         }
0575 
0576         dai->probed = 0;
0577     }
0578 
0579     return ret;
0580 }
0581 
0582 int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
0583 {
0584     struct snd_soc_dai *dai;
0585     int i;
0586 
0587     for_each_rtd_dais(rtd, i, dai) {
0588         if (dai->driver->pcm_new) {
0589             int ret = dai->driver->pcm_new(rtd, dai);
0590             if (ret < 0)
0591                 return soc_dai_ret(dai, ret);
0592         }
0593     }
0594 
0595     return 0;
0596 }
0597 
0598 int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
0599 {
0600     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0601     struct snd_soc_dai *dai;
0602     int i, ret;
0603 
0604     for_each_rtd_dais(rtd, i, dai) {
0605         if (dai->driver->ops &&
0606             dai->driver->ops->prepare) {
0607             ret = dai->driver->ops->prepare(substream, dai);
0608             if (ret < 0)
0609                 return soc_dai_ret(dai, ret);
0610         }
0611     }
0612 
0613     return 0;
0614 }
0615 
0616 static int soc_dai_trigger(struct snd_soc_dai *dai,
0617                struct snd_pcm_substream *substream, int cmd)
0618 {
0619     int ret = 0;
0620 
0621     if (dai->driver->ops &&
0622         dai->driver->ops->trigger)
0623         ret = dai->driver->ops->trigger(substream, cmd, dai);
0624 
0625     return soc_dai_ret(dai, ret);
0626 }
0627 
0628 int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
0629                 int cmd, int rollback)
0630 {
0631     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0632     struct snd_soc_dai *dai;
0633     int i, r, ret = 0;
0634 
0635     switch (cmd) {
0636     case SNDRV_PCM_TRIGGER_START:
0637     case SNDRV_PCM_TRIGGER_RESUME:
0638     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0639         for_each_rtd_dais(rtd, i, dai) {
0640             ret = soc_dai_trigger(dai, substream, cmd);
0641             if (ret < 0)
0642                 break;
0643             soc_dai_mark_push(dai, substream, trigger);
0644         }
0645         break;
0646     case SNDRV_PCM_TRIGGER_STOP:
0647     case SNDRV_PCM_TRIGGER_SUSPEND:
0648     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0649         for_each_rtd_dais(rtd, i, dai) {
0650             if (rollback && !soc_dai_mark_match(dai, substream, trigger))
0651                 continue;
0652 
0653             r = soc_dai_trigger(dai, substream, cmd);
0654             if (r < 0)
0655                 ret = r; /* use last ret */
0656             soc_dai_mark_pop(dai, substream, trigger);
0657         }
0658     }
0659 
0660     return ret;
0661 }
0662 
0663 int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream,
0664                     int cmd)
0665 {
0666     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0667     struct snd_soc_dai *dai;
0668     int i, ret;
0669 
0670     for_each_rtd_dais(rtd, i, dai) {
0671         if (dai->driver->ops &&
0672             dai->driver->ops->bespoke_trigger) {
0673             ret = dai->driver->ops->bespoke_trigger(substream,
0674                                 cmd, dai);
0675             if (ret < 0)
0676                 return soc_dai_ret(dai, ret);
0677         }
0678     }
0679 
0680     return 0;
0681 }
0682 
0683 void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
0684                snd_pcm_sframes_t *cpu_delay,
0685                snd_pcm_sframes_t *codec_delay)
0686 {
0687     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0688     struct snd_soc_dai *dai;
0689     int i;
0690 
0691     /*
0692      * We're looking for the delay through the full audio path so it needs to
0693      * be the maximum of the DAIs doing transmit and the maximum of the DAIs
0694      * doing receive (ie, all CPUs and all CODECs) rather than just the maximum
0695      * of all DAIs.
0696      */
0697 
0698     /* for CPU */
0699     for_each_rtd_cpu_dais(rtd, i, dai)
0700         if (dai->driver->ops &&
0701             dai->driver->ops->delay)
0702             *cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
0703 
0704     /* for Codec */
0705     for_each_rtd_codec_dais(rtd, i, dai)
0706         if (dai->driver->ops &&
0707             dai->driver->ops->delay)
0708             *codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
0709 }
0710 
0711 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
0712                   struct snd_compr_stream *cstream)
0713 {
0714     int ret = 0;
0715 
0716     if (dai->driver->cops &&
0717         dai->driver->cops->startup)
0718         ret = dai->driver->cops->startup(cstream, dai);
0719 
0720     /* mark cstream if succeeded */
0721     if (ret == 0)
0722         soc_dai_mark_push(dai, cstream, compr_startup);
0723 
0724     return soc_dai_ret(dai, ret);
0725 }
0726 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
0727 
0728 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
0729                 struct snd_compr_stream *cstream,
0730                 int rollback)
0731 {
0732     if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
0733         return;
0734 
0735     if (dai->driver->cops &&
0736         dai->driver->cops->shutdown)
0737         dai->driver->cops->shutdown(cstream, dai);
0738 
0739     /* remove marked cstream */
0740     soc_dai_mark_pop(dai, cstream, compr_startup);
0741 }
0742 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
0743 
0744 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
0745                   struct snd_compr_stream *cstream, int cmd)
0746 {
0747     int ret = 0;
0748 
0749     if (dai->driver->cops &&
0750         dai->driver->cops->trigger)
0751         ret = dai->driver->cops->trigger(cstream, cmd, dai);
0752 
0753     return soc_dai_ret(dai, ret);
0754 }
0755 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
0756 
0757 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
0758                  struct snd_compr_stream *cstream,
0759                  struct snd_compr_params *params)
0760 {
0761     int ret = 0;
0762 
0763     if (dai->driver->cops &&
0764         dai->driver->cops->set_params)
0765         ret = dai->driver->cops->set_params(cstream, params, dai);
0766 
0767     return soc_dai_ret(dai, ret);
0768 }
0769 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
0770 
0771 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
0772                  struct snd_compr_stream *cstream,
0773                  struct snd_codec *params)
0774 {
0775     int ret = 0;
0776 
0777     if (dai->driver->cops &&
0778         dai->driver->cops->get_params)
0779         ret = dai->driver->cops->get_params(cstream, params, dai);
0780 
0781     return soc_dai_ret(dai, ret);
0782 }
0783 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
0784 
0785 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
0786               struct snd_compr_stream *cstream,
0787               size_t bytes)
0788 {
0789     int ret = 0;
0790 
0791     if (dai->driver->cops &&
0792         dai->driver->cops->ack)
0793         ret = dai->driver->cops->ack(cstream, bytes, dai);
0794 
0795     return soc_dai_ret(dai, ret);
0796 }
0797 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
0798 
0799 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
0800                   struct snd_compr_stream *cstream,
0801                   struct snd_compr_tstamp *tstamp)
0802 {
0803     int ret = 0;
0804 
0805     if (dai->driver->cops &&
0806         dai->driver->cops->pointer)
0807         ret = dai->driver->cops->pointer(cstream, tstamp, dai);
0808 
0809     return soc_dai_ret(dai, ret);
0810 }
0811 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
0812 
0813 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
0814                    struct snd_compr_stream *cstream,
0815                    struct snd_compr_metadata *metadata)
0816 {
0817     int ret = 0;
0818 
0819     if (dai->driver->cops &&
0820         dai->driver->cops->set_metadata)
0821         ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
0822 
0823     return soc_dai_ret(dai, ret);
0824 }
0825 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
0826 
0827 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
0828                    struct snd_compr_stream *cstream,
0829                    struct snd_compr_metadata *metadata)
0830 {
0831     int ret = 0;
0832 
0833     if (dai->driver->cops &&
0834         dai->driver->cops->get_metadata)
0835         ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
0836 
0837     return soc_dai_ret(dai, ret);
0838 }
0839 EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);