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