1  // SPDX-License-Identifier: GPL-2.0
2  //
3  // soc-dai.c
4  //
5  // Copyright (C) 2019 Renesas Electronics Corp.
6  // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7  //
8  
9  #include <sound/soc.h>
10  #include <sound/soc-dai.h>
11  #include <sound/soc-link.h>
12  
13  #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
_soc_dai_ret(const struct snd_soc_dai * dai,const char * func,int ret)14  static inline int _soc_dai_ret(const struct snd_soc_dai *dai,
15  			       const char *func, int ret)
16  {
17  	/* Positive, Zero values are not errors */
18  	if (ret >= 0)
19  		return ret;
20  
21  	/* Negative values might be errors */
22  	switch (ret) {
23  	case -EPROBE_DEFER:
24  	case -ENOTSUPP:
25  		break;
26  	default:
27  		dev_err(dai->dev,
28  			"ASoC: error at %s on %s: %d\n",
29  			func, dai->name, ret);
30  	}
31  
32  	return ret;
33  }
34  
35  /*
36   * We might want to check substream by using list.
37   * In such case, we can update these macros.
38   */
39  #define soc_dai_mark_push(dai, substream, tgt)	((dai)->mark_##tgt = substream)
40  #define soc_dai_mark_pop(dai, substream, tgt)	((dai)->mark_##tgt = NULL)
41  #define soc_dai_mark_match(dai, substream, tgt)	((dai)->mark_##tgt == substream)
42  
43  /**
44   * snd_soc_dai_set_sysclk - configure DAI system or master clock.
45   * @dai: DAI
46   * @clk_id: DAI specific clock ID
47   * @freq: new clock frequency in Hz
48   * @dir: new clock direction (SND_SOC_CLOCK_IN or SND_SOC_CLOCK_OUT)
49   *
50   * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
51   */
snd_soc_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)52  int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
53  			   unsigned int freq, int dir)
54  {
55  	int ret;
56  
57  	if (dai->driver->ops &&
58  	    dai->driver->ops->set_sysclk)
59  		ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
60  	else
61  		ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
62  						   freq, dir);
63  
64  	return soc_dai_ret(dai, ret);
65  }
66  EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
67  
68  /**
69   * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
70   * @dai: DAI
71   * @div_id: DAI specific clock divider ID
72   * @div: new clock divisor.
73   *
74   * Configures the clock dividers. This is used to derive the best DAI bit and
75   * frame clocks from the system or master clock. It's best to set the DAI bit
76   * and frame clocks as low as possible to save system power.
77   */
snd_soc_dai_set_clkdiv(struct snd_soc_dai * dai,int div_id,int div)78  int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
79  			   int div_id, int div)
80  {
81  	int ret = -EINVAL;
82  
83  	if (dai->driver->ops &&
84  	    dai->driver->ops->set_clkdiv)
85  		ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
86  
87  	return soc_dai_ret(dai, ret);
88  }
89  EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
90  
91  /**
92   * snd_soc_dai_set_pll - configure DAI PLL.
93   * @dai: DAI
94   * @pll_id: DAI specific PLL ID
95   * @source: DAI specific source for the PLL
96   * @freq_in: PLL input clock frequency in Hz
97   * @freq_out: requested PLL output clock frequency in Hz
98   *
99   * Configures and enables PLL to generate output clock based on input clock.
100   */
snd_soc_dai_set_pll(struct snd_soc_dai * dai,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)101  int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
102  			unsigned int freq_in, unsigned int freq_out)
103  {
104  	int ret;
105  
106  	if (dai->driver->ops &&
107  	    dai->driver->ops->set_pll)
108  		ret = dai->driver->ops->set_pll(dai, pll_id, source,
109  						freq_in, freq_out);
110  	else
111  		ret = snd_soc_component_set_pll(dai->component, pll_id, source,
112  						freq_in, freq_out);
113  
114  	return soc_dai_ret(dai, ret);
115  }
116  EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
117  
118  /**
119   * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
120   * @dai: DAI
121   * @ratio: Ratio of BCLK to Sample rate.
122   *
123   * Configures the DAI for a preset BCLK to sample rate ratio.
124   */
snd_soc_dai_set_bclk_ratio(struct snd_soc_dai * dai,unsigned int ratio)125  int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
126  {
127  	int ret = -ENOTSUPP;
128  
129  	if (dai->driver->ops &&
130  	    dai->driver->ops->set_bclk_ratio)
131  		ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
132  
133  	return soc_dai_ret(dai, ret);
134  }
135  EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
136  
snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime * rtd)137  int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd)
138  {
139  	struct snd_soc_dai *dai;
140  	int i, max = 0;
141  
142  	/*
143  	 * return max num if *ALL* DAIs have .auto_selectable_formats
144  	 */
145  	for_each_rtd_dais(rtd, i, dai) {
146  		if (dai->driver->ops &&
147  		    dai->driver->ops->num_auto_selectable_formats)
148  			max = max(max, dai->driver->ops->num_auto_selectable_formats);
149  		else
150  			return 0;
151  	}
152  
153  	return max;
154  }
155  
156  /**
157   * snd_soc_dai_get_fmt - get supported audio format.
158   * @dai: DAI
159   * @priority: priority level of supported audio format.
160   *
161   * This should return only formats implemented with high
162   * quality by the DAI so that the core can configure a
163   * format which will work well with other devices.
164   * For example devices which don't support both edges of the
165   * LRCLK signal in I2S style formats should only list DSP
166   * modes.  This will mean that sometimes fewer formats
167   * are reported here than are supported by set_fmt().
168   */
snd_soc_dai_get_fmt(const struct snd_soc_dai * dai,int priority)169  u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority)
170  {
171  	const struct snd_soc_dai_ops *ops = dai->driver->ops;
172  	u64 fmt = 0;
173  	int i, max = 0, until = priority;
174  
175  	/*
176  	 * Collect auto_selectable_formats until priority
177  	 *
178  	 * ex)
179  	 *	auto_selectable_formats[] = { A, B, C };
180  	 *	(A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)
181  	 *
182  	 * priority = 1 :	A
183  	 * priority = 2 :	A | B
184  	 * priority = 3 :	A | B | C
185  	 * priority = 4 :	A | B | C
186  	 * ...
187  	 */
188  	if (ops)
189  		max = ops->num_auto_selectable_formats;
190  
191  	if (max < until)
192  		until = max;
193  
194  	for (i = 0; i < until; i++)
195  		fmt |= ops->auto_selectable_formats[i];
196  
197  	return fmt;
198  }
199  
200  /**
201   * snd_soc_dai_set_fmt - configure DAI hardware audio format.
202   * @dai: DAI
203   * @fmt: SND_SOC_DAIFMT_* format value.
204   *
205   * Configures the DAI hardware format and clocking.
206   */
snd_soc_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)207  int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
208  {
209  	int ret = -ENOTSUPP;
210  
211  	if (dai->driver->ops && dai->driver->ops->set_fmt)
212  		ret = dai->driver->ops->set_fmt(dai, fmt);
213  
214  	return soc_dai_ret(dai, ret);
215  }
216  EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
217  
218  /**
219   * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask.
220   * @slots: Number of slots in use.
221   * @tx_mask: bitmask representing active TX slots.
222   * @rx_mask: bitmask representing active RX slots.
223   *
224   * Generates the TDM tx and rx slot default masks for DAI.
225   */
snd_soc_xlate_tdm_slot_mask(unsigned int slots,unsigned int * tx_mask,unsigned int * rx_mask)226  static int snd_soc_xlate_tdm_slot_mask(unsigned int slots,
227  				       unsigned int *tx_mask,
228  				       unsigned int *rx_mask)
229  {
230  	if (*tx_mask || *rx_mask)
231  		return 0;
232  
233  	if (!slots)
234  		return -EINVAL;
235  
236  	*tx_mask = (1 << slots) - 1;
237  	*rx_mask = (1 << slots) - 1;
238  
239  	return 0;
240  }
241  
242  /**
243   * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
244   * @dai: The DAI to configure
245   * @tx_mask: bitmask representing active TX slots.
246   * @rx_mask: bitmask representing active RX slots.
247   * @slots: Number of slots in use.
248   * @slot_width: Width in bits for each slot.
249   *
250   * This function configures the specified DAI for TDM operation. @slot contains
251   * the total number of slots of the TDM stream and @slot_with the width of each
252   * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
253   * active slots of the TDM stream for the specified DAI, i.e. which slots the
254   * DAI should write to or read from. If a bit is set the corresponding slot is
255   * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
256   * the first slot, bit 1 to the second slot and so on. The first active slot
257   * maps to the first channel of the DAI, the second active slot to the second
258   * channel and so on.
259   *
260   * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
261   * @rx_mask and @slot_width will be ignored.
262   *
263   * Returns 0 on success, a negative error code otherwise.
264   */
snd_soc_dai_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)265  int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
266  			     unsigned int tx_mask, unsigned int rx_mask,
267  			     int slots, int slot_width)
268  {
269  	int ret = -ENOTSUPP;
270  	int stream;
271  	unsigned int *tdm_mask[] = {
272  		&tx_mask,
273  		&rx_mask,
274  	};
275  
276  	if (dai->driver->ops &&
277  	    dai->driver->ops->xlate_tdm_slot_mask)
278  		dai->driver->ops->xlate_tdm_slot_mask(slots,
279  						      &tx_mask, &rx_mask);
280  	else
281  		snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask);
282  
283  	for_each_pcm_streams(stream)
284  		snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]);
285  
286  	if (dai->driver->ops &&
287  	    dai->driver->ops->set_tdm_slot)
288  		ret = dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
289  						      slots, slot_width);
290  	return soc_dai_ret(dai, ret);
291  }
292  EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
293  
294  /**
295   * snd_soc_dai_set_channel_map - configure DAI audio channel map
296   * @dai: DAI
297   * @tx_num: how many TX channels
298   * @tx_slot: pointer to an array which imply the TX slot number channel
299   *           0~num-1 uses
300   * @rx_num: how many RX channels
301   * @rx_slot: pointer to an array which imply the RX slot number channel
302   *           0~num-1 uses
303   *
304   * configure the relationship between channel number and TDM slot number.
305   */
snd_soc_dai_set_channel_map(struct snd_soc_dai * dai,unsigned int tx_num,const unsigned int * tx_slot,unsigned int rx_num,const unsigned int * rx_slot)306  int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
307  				unsigned int tx_num, const unsigned int *tx_slot,
308  				unsigned int rx_num, const unsigned int *rx_slot)
309  {
310  	int ret = -ENOTSUPP;
311  
312  	if (dai->driver->ops &&
313  	    dai->driver->ops->set_channel_map)
314  		ret = dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
315  							rx_num, rx_slot);
316  	return soc_dai_ret(dai, ret);
317  }
318  EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
319  
320  /**
321   * snd_soc_dai_get_channel_map - Get DAI audio channel map
322   * @dai: DAI
323   * @tx_num: how many TX channels
324   * @tx_slot: pointer to an array which imply the TX slot number channel
325   *           0~num-1 uses
326   * @rx_num: how many RX channels
327   * @rx_slot: pointer to an array which imply the RX slot number channel
328   *           0~num-1 uses
329   */
snd_soc_dai_get_channel_map(const struct snd_soc_dai * dai,unsigned int * tx_num,unsigned int * tx_slot,unsigned int * rx_num,unsigned int * rx_slot)330  int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,
331  				unsigned int *tx_num, unsigned int *tx_slot,
332  				unsigned int *rx_num, unsigned int *rx_slot)
333  {
334  	int ret = -ENOTSUPP;
335  
336  	if (dai->driver->ops &&
337  	    dai->driver->ops->get_channel_map)
338  		ret = dai->driver->ops->get_channel_map(dai, tx_num, tx_slot,
339  							rx_num, rx_slot);
340  	return soc_dai_ret(dai, ret);
341  }
342  EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map);
343  
344  /**
345   * snd_soc_dai_set_tristate - configure DAI system or master clock.
346   * @dai: DAI
347   * @tristate: tristate enable
348   *
349   * Tristates the DAI so that others can use it.
350   */
snd_soc_dai_set_tristate(struct snd_soc_dai * dai,int tristate)351  int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
352  {
353  	int ret = -EINVAL;
354  
355  	if (dai->driver->ops &&
356  	    dai->driver->ops->set_tristate)
357  		ret = dai->driver->ops->set_tristate(dai, tristate);
358  
359  	return soc_dai_ret(dai, ret);
360  }
361  EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
362  
363  /**
364   * snd_soc_dai_digital_mute - configure DAI system or master clock.
365   * @dai: DAI
366   * @mute: mute enable
367   * @direction: stream to mute
368   *
369   * Mutes the DAI DAC.
370   */
snd_soc_dai_digital_mute(struct snd_soc_dai * dai,int mute,int direction)371  int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
372  			     int direction)
373  {
374  	int ret = -ENOTSUPP;
375  
376  	/*
377  	 * ignore if direction was CAPTURE
378  	 * and it had .no_capture_mute flag
379  	 */
380  	if (dai->driver->ops &&
381  	    dai->driver->ops->mute_stream &&
382  	    (direction == SNDRV_PCM_STREAM_PLAYBACK ||
383  	     !dai->driver->ops->no_capture_mute))
384  		ret = dai->driver->ops->mute_stream(dai, mute, direction);
385  
386  	return soc_dai_ret(dai, ret);
387  }
388  EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
389  
snd_soc_dai_hw_params(struct snd_soc_dai * dai,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)390  int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
391  			  struct snd_pcm_substream *substream,
392  			  struct snd_pcm_hw_params *params)
393  {
394  	int ret = 0;
395  
396  	if (dai->driver->ops &&
397  	    dai->driver->ops->hw_params)
398  		ret = dai->driver->ops->hw_params(substream, params, dai);
399  
400  	/* mark substream if succeeded */
401  	if (ret == 0)
402  		soc_dai_mark_push(dai, substream, hw_params);
403  
404  	return soc_dai_ret(dai, ret);
405  }
406  
snd_soc_dai_hw_free(struct snd_soc_dai * dai,struct snd_pcm_substream * substream,int rollback)407  void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
408  			 struct snd_pcm_substream *substream,
409  			 int rollback)
410  {
411  	if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
412  		return;
413  
414  	if (dai->driver->ops &&
415  	    dai->driver->ops->hw_free)
416  		dai->driver->ops->hw_free(substream, dai);
417  
418  	/* remove marked substream */
419  	soc_dai_mark_pop(dai, substream, hw_params);
420  }
421  
snd_soc_dai_startup(struct snd_soc_dai * dai,struct snd_pcm_substream * substream)422  int snd_soc_dai_startup(struct snd_soc_dai *dai,
423  			struct snd_pcm_substream *substream)
424  {
425  	int ret = 0;
426  
427  	if (!snd_soc_dai_stream_valid(dai, substream->stream))
428  		return 0;
429  
430  	if (dai->driver->ops &&
431  	    dai->driver->ops->startup)
432  		ret = dai->driver->ops->startup(substream, dai);
433  
434  	/* mark substream if succeeded */
435  	if (ret == 0)
436  		soc_dai_mark_push(dai, substream, startup);
437  
438  	return soc_dai_ret(dai, ret);
439  }
440  
snd_soc_dai_shutdown(struct snd_soc_dai * dai,struct snd_pcm_substream * substream,int rollback)441  void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
442  			  struct snd_pcm_substream *substream,
443  			  int rollback)
444  {
445  	if (!snd_soc_dai_stream_valid(dai, substream->stream))
446  		return;
447  
448  	if (rollback && !soc_dai_mark_match(dai, substream, startup))
449  		return;
450  
451  	if (dai->driver->ops &&
452  	    dai->driver->ops->shutdown)
453  		dai->driver->ops->shutdown(substream, dai);
454  
455  	/* remove marked substream */
456  	soc_dai_mark_pop(dai, substream, startup);
457  }
458  
snd_soc_dai_compress_new(struct snd_soc_dai * dai,struct snd_soc_pcm_runtime * rtd,int num)459  int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
460  			     struct snd_soc_pcm_runtime *rtd, int num)
461  {
462  	int ret = -ENOTSUPP;
463  	if (dai->driver->ops &&
464  	    dai->driver->ops->compress_new)
465  		ret = dai->driver->ops->compress_new(rtd, num);
466  	return soc_dai_ret(dai, ret);
467  }
468  
469  /*
470   * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
471   *
472   * Returns true if the DAI supports the indicated stream type.
473   */
snd_soc_dai_stream_valid(const struct snd_soc_dai * dai,int dir)474  bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir)
475  {
476  	const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
477  
478  	/* If the codec specifies any channels at all, it supports the stream */
479  	return stream->channels_min;
480  }
481  
snd_soc_dai_action(struct snd_soc_dai * dai,int stream,int action)482  void snd_soc_dai_action(struct snd_soc_dai *dai,
483  			int stream, int action)
484  {
485  	/* see snd_soc_dai_stream_active() */
486  	dai->stream[stream].active	+= action;
487  
488  	/* see snd_soc_component_active() */
489  	dai->component->active		+= action;
490  }
491  EXPORT_SYMBOL_GPL(snd_soc_dai_action);
492  
snd_soc_dai_active(const struct snd_soc_dai * dai)493  int snd_soc_dai_active(const struct snd_soc_dai *dai)
494  {
495  	int stream, active;
496  
497  	active = 0;
498  	for_each_pcm_streams(stream)
499  		active += dai->stream[stream].active;
500  
501  	return active;
502  }
503  EXPORT_SYMBOL_GPL(snd_soc_dai_active);
504  
snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime * rtd,int order)505  int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order)
506  {
507  	struct snd_soc_dai *dai;
508  	int i;
509  
510  	for_each_rtd_dais(rtd, i, dai) {
511  		if (dai->probed)
512  			continue;
513  
514  		if (dai->driver->ops) {
515  			if (dai->driver->ops->probe_order != order)
516  				continue;
517  
518  			if (dai->driver->ops->probe) {
519  				int ret = dai->driver->ops->probe(dai);
520  
521  				if (ret < 0)
522  					return soc_dai_ret(dai, ret);
523  			}
524  		}
525  		dai->probed = 1;
526  	}
527  
528  	return 0;
529  }
530  
snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime * rtd,int order)531  int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order)
532  {
533  	struct snd_soc_dai *dai;
534  	int i, r, ret = 0;
535  
536  	for_each_rtd_dais(rtd, i, dai) {
537  		if (!dai->probed)
538  			continue;
539  
540  		if (dai->driver->ops) {
541  			if (dai->driver->ops->remove_order != order)
542  				continue;
543  
544  			if (dai->driver->ops->remove) {
545  				r = dai->driver->ops->remove(dai);
546  				if (r < 0)
547  					ret = r; /* use last error */
548  			}
549  		}
550  		dai->probed = 0;
551  	}
552  
553  	return ret;
554  }
555  
snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime * rtd)556  int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd)
557  {
558  	struct snd_soc_dai *dai;
559  	int i;
560  
561  	for_each_rtd_dais(rtd, i, dai) {
562  		if (dai->driver->ops &&
563  		    dai->driver->ops->pcm_new) {
564  			int ret = dai->driver->ops->pcm_new(rtd, dai);
565  			if (ret < 0)
566  				return soc_dai_ret(dai, ret);
567  		}
568  	}
569  
570  	return 0;
571  }
572  
snd_soc_pcm_dai_prepare(struct snd_pcm_substream * substream)573  int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream)
574  {
575  	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
576  	struct snd_soc_dai *dai;
577  	int i, ret;
578  
579  	for_each_rtd_dais(rtd, i, dai) {
580  		if (!snd_soc_dai_stream_valid(dai, substream->stream))
581  			continue;
582  		if (dai->driver->ops &&
583  		    dai->driver->ops->prepare) {
584  			ret = dai->driver->ops->prepare(substream, dai);
585  			if (ret < 0)
586  				return soc_dai_ret(dai, ret);
587  		}
588  	}
589  
590  	return 0;
591  }
592  
soc_dai_trigger(struct snd_soc_dai * dai,struct snd_pcm_substream * substream,int cmd)593  static int soc_dai_trigger(struct snd_soc_dai *dai,
594  			   struct snd_pcm_substream *substream, int cmd)
595  {
596  	int ret = 0;
597  
598  	if (!snd_soc_dai_stream_valid(dai, substream->stream))
599  		return 0;
600  
601  	if (dai->driver->ops &&
602  	    dai->driver->ops->trigger)
603  		ret = dai->driver->ops->trigger(substream, cmd, dai);
604  
605  	return soc_dai_ret(dai, ret);
606  }
607  
snd_soc_pcm_dai_trigger(struct snd_pcm_substream * substream,int cmd,int rollback)608  int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream,
609  			    int cmd, int rollback)
610  {
611  	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
612  	struct snd_soc_dai *dai;
613  	int i, r, ret = 0;
614  
615  	switch (cmd) {
616  	case SNDRV_PCM_TRIGGER_START:
617  	case SNDRV_PCM_TRIGGER_RESUME:
618  	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
619  		for_each_rtd_dais(rtd, i, dai) {
620  			ret = soc_dai_trigger(dai, substream, cmd);
621  			if (ret < 0)
622  				break;
623  
624  			if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)
625  				snd_soc_dai_digital_mute(dai, 0, substream->stream);
626  
627  			soc_dai_mark_push(dai, substream, trigger);
628  		}
629  		break;
630  	case SNDRV_PCM_TRIGGER_STOP:
631  	case SNDRV_PCM_TRIGGER_SUSPEND:
632  	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
633  		for_each_rtd_dais(rtd, i, dai) {
634  			if (rollback && !soc_dai_mark_match(dai, substream, trigger))
635  				continue;
636  
637  			if (dai->driver->ops && dai->driver->ops->mute_unmute_on_trigger)
638  				snd_soc_dai_digital_mute(dai, 1, substream->stream);
639  
640  			r = soc_dai_trigger(dai, substream, cmd);
641  			if (r < 0)
642  				ret = r; /* use last ret */
643  			soc_dai_mark_pop(dai, substream, trigger);
644  		}
645  	}
646  
647  	return ret;
648  }
649  
snd_soc_pcm_dai_delay(struct snd_pcm_substream * substream,snd_pcm_sframes_t * cpu_delay,snd_pcm_sframes_t * codec_delay)650  void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream,
651  			   snd_pcm_sframes_t *cpu_delay,
652  			   snd_pcm_sframes_t *codec_delay)
653  {
654  	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
655  	struct snd_soc_dai *dai;
656  	int i;
657  
658  	/*
659  	 * We're looking for the delay through the full audio path so it needs to
660  	 * be the maximum of the DAIs doing transmit and the maximum of the DAIs
661  	 * doing receive (ie, all CPUs and all CODECs) rather than just the maximum
662  	 * of all DAIs.
663  	 */
664  
665  	/* for CPU */
666  	for_each_rtd_cpu_dais(rtd, i, dai)
667  		if (dai->driver->ops &&
668  		    dai->driver->ops->delay)
669  			*cpu_delay = max(*cpu_delay, dai->driver->ops->delay(substream, dai));
670  
671  	/* for Codec */
672  	for_each_rtd_codec_dais(rtd, i, dai)
673  		if (dai->driver->ops &&
674  		    dai->driver->ops->delay)
675  			*codec_delay = max(*codec_delay, dai->driver->ops->delay(substream, dai));
676  }
677  
snd_soc_dai_compr_startup(struct snd_soc_dai * dai,struct snd_compr_stream * cstream)678  int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
679  			      struct snd_compr_stream *cstream)
680  {
681  	int ret = 0;
682  
683  	if (dai->driver->cops &&
684  	    dai->driver->cops->startup)
685  		ret = dai->driver->cops->startup(cstream, dai);
686  
687  	/* mark cstream if succeeded */
688  	if (ret == 0)
689  		soc_dai_mark_push(dai, cstream, compr_startup);
690  
691  	return soc_dai_ret(dai, ret);
692  }
693  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_startup);
694  
snd_soc_dai_compr_shutdown(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,int rollback)695  void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
696  				struct snd_compr_stream *cstream,
697  				int rollback)
698  {
699  	if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
700  		return;
701  
702  	if (dai->driver->cops &&
703  	    dai->driver->cops->shutdown)
704  		dai->driver->cops->shutdown(cstream, dai);
705  
706  	/* remove marked cstream */
707  	soc_dai_mark_pop(dai, cstream, compr_startup);
708  }
709  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_shutdown);
710  
snd_soc_dai_compr_trigger(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,int cmd)711  int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
712  			      struct snd_compr_stream *cstream, int cmd)
713  {
714  	int ret = 0;
715  
716  	if (dai->driver->cops &&
717  	    dai->driver->cops->trigger)
718  		ret = dai->driver->cops->trigger(cstream, cmd, dai);
719  
720  	return soc_dai_ret(dai, ret);
721  }
722  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_trigger);
723  
snd_soc_dai_compr_set_params(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,struct snd_compr_params * params)724  int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
725  				 struct snd_compr_stream *cstream,
726  				 struct snd_compr_params *params)
727  {
728  	int ret = 0;
729  
730  	if (dai->driver->cops &&
731  	    dai->driver->cops->set_params)
732  		ret = dai->driver->cops->set_params(cstream, params, dai);
733  
734  	return soc_dai_ret(dai, ret);
735  }
736  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_params);
737  
snd_soc_dai_compr_get_params(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,struct snd_codec * params)738  int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
739  				 struct snd_compr_stream *cstream,
740  				 struct snd_codec *params)
741  {
742  	int ret = 0;
743  
744  	if (dai->driver->cops &&
745  	    dai->driver->cops->get_params)
746  		ret = dai->driver->cops->get_params(cstream, params, dai);
747  
748  	return soc_dai_ret(dai, ret);
749  }
750  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_params);
751  
snd_soc_dai_compr_ack(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,size_t bytes)752  int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
753  			  struct snd_compr_stream *cstream,
754  			  size_t bytes)
755  {
756  	int ret = 0;
757  
758  	if (dai->driver->cops &&
759  	    dai->driver->cops->ack)
760  		ret = dai->driver->cops->ack(cstream, bytes, dai);
761  
762  	return soc_dai_ret(dai, ret);
763  }
764  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_ack);
765  
snd_soc_dai_compr_pointer(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,struct snd_compr_tstamp * tstamp)766  int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
767  			      struct snd_compr_stream *cstream,
768  			      struct snd_compr_tstamp *tstamp)
769  {
770  	int ret = 0;
771  
772  	if (dai->driver->cops &&
773  	    dai->driver->cops->pointer)
774  		ret = dai->driver->cops->pointer(cstream, tstamp, dai);
775  
776  	return soc_dai_ret(dai, ret);
777  }
778  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_pointer);
779  
snd_soc_dai_compr_set_metadata(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,struct snd_compr_metadata * metadata)780  int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
781  				   struct snd_compr_stream *cstream,
782  				   struct snd_compr_metadata *metadata)
783  {
784  	int ret = 0;
785  
786  	if (dai->driver->cops &&
787  	    dai->driver->cops->set_metadata)
788  		ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
789  
790  	return soc_dai_ret(dai, ret);
791  }
792  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_set_metadata);
793  
snd_soc_dai_compr_get_metadata(struct snd_soc_dai * dai,struct snd_compr_stream * cstream,struct snd_compr_metadata * metadata)794  int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
795  				   struct snd_compr_stream *cstream,
796  				   struct snd_compr_metadata *metadata)
797  {
798  	int ret = 0;
799  
800  	if (dai->driver->cops &&
801  	    dai->driver->cops->get_metadata)
802  		ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
803  
804  	return soc_dai_ret(dai, ret);
805  }
806  EXPORT_SYMBOL_GPL(snd_soc_dai_compr_get_metadata);
807