Lines Matching +full:dai +full:- +full:tdm +full:- +full:slot +full:- +full:width
1 // SPDX-License-Identifier: GPL-2.0
3 // soc-dai.c
10 #include <sound/soc-dai.h>
11 #include <sound/soc-link.h>
13 #define soc_dai_ret(dai, ret) _soc_dai_ret(dai, __func__, ret)
14 static inline int _soc_dai_ret(const struct snd_soc_dai *dai,
17 return snd_soc_ret(dai->dev, ret,
18 "at %s() on %s\n", func, dai->name);
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)
30 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
31 * @dai: DAI
32 * @clk_id: DAI specific clock ID
36 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
38 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
43 if (dai->driver->ops &&
44 dai->driver->ops->set_sysclk)
45 ret = dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
47 ret = snd_soc_component_set_sysclk(dai->component, clk_id, 0,
50 return soc_dai_ret(dai, ret);
55 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
56 * @dai: DAI
57 * @div_id: DAI specific clock divider ID
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
64 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
67 int ret = -EINVAL;
69 if (dai->driver->ops &&
70 dai->driver->ops->set_clkdiv)
71 ret = dai->driver->ops->set_clkdiv(dai, div_id, div);
73 return soc_dai_ret(dai, ret);
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
87 int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
92 if (dai->driver->ops &&
93 dai->driver->ops->set_pll)
94 ret = dai->driver->ops->set_pll(dai, pll_id, source,
97 ret = snd_soc_component_set_pll(dai->component, pll_id, source,
100 return soc_dai_ret(dai, ret);
105 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
106 * @dai: DAI
109 * Configures the DAI for a preset BCLK to sample rate ratio.
111 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
113 int ret = -ENOTSUPP;
115 if (dai->driver->ops &&
116 dai->driver->ops->set_bclk_ratio)
117 ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
119 return soc_dai_ret(dai, ret);
125 struct snd_soc_dai *dai;
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);
143 * snd_soc_dai_get_fmt - get supported audio format.
144 * @dai: DAI
148 * quality by the DAI so that the core can configure a
155 u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority)
157 const struct snd_soc_dai_ops *ops = dai->driver->ops;
175 max = ops->num_auto_selectable_formats;
181 fmt |= ops->auto_selectable_formats[i];
187 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
188 * @dai: DAI
191 * Configures the DAI hardware format and clocking.
193 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
195 int ret = -ENOTSUPP;
197 if (dai->driver->ops && dai->driver->ops->set_fmt)
198 ret = dai->driver->ops->set_fmt(dai, fmt);
200 return soc_dai_ret(dai, ret);
205 * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask.
210 * Generates the TDM tx and rx slot default masks for DAI.
220 return -EINVAL;
222 *tx_mask = (1 << slots) - 1;
223 *rx_mask = (1 << slots) - 1;
229 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
230 * @dai: The DAI to configure
234 * @slot_width: Width in bits for each slot.
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
246 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
251 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
255 int ret = -ENOTSUPP;
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);
273 snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]);
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,
280 return soc_dai_ret(dai, ret);
285 * snd_soc_dai_set_channel_map - configure DAI audio channel map
286 * @dai: DAI
288 * @tx_slot: pointer to an array which imply the TX slot number channel
289 * 0~num-1 uses
291 * @rx_slot: pointer to an array which imply the RX slot number channel
292 * 0~num-1 uses
294 * configure the relationship between channel number and TDM slot number.
296 int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
300 int ret = -ENOTSUPP;
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,
306 return soc_dai_ret(dai, ret);
311 * snd_soc_dai_get_channel_map - Get DAI audio channel map
312 * @dai: DAI
314 * @tx_slot: pointer to an array which imply the TX slot number channel
315 * 0~num-1 uses
317 * @rx_slot: pointer to an array which imply the RX slot number channel
318 * 0~num-1 uses
320 int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai,
324 int ret = -ENOTSUPP;
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,
330 return soc_dai_ret(dai, ret);
335 * snd_soc_dai_set_tristate - configure DAI system or master clock.
336 * @dai: DAI
339 * Tristates the DAI so that others can use it.
341 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
343 int ret = -EINVAL;
345 if (dai->driver->ops &&
346 dai->driver->ops->set_tristate)
347 ret = dai->driver->ops->set_tristate(dai, tristate);
349 return soc_dai_ret(dai, ret);
353 int snd_soc_dai_prepare(struct snd_soc_dai *dai,
358 if (!snd_soc_dai_stream_valid(dai, substream->stream))
361 if (dai->driver->ops &&
362 dai->driver->ops->prepare)
363 ret = dai->driver->ops->prepare(substream, dai);
365 return soc_dai_ret(dai, ret);
369 int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai)
371 if (dai->driver->ops)
372 return dai->driver->ops->mute_unmute_on_trigger;
378 * snd_soc_dai_digital_mute - configure DAI system or master clock.
379 * @dai: DAI
383 * Mutes the DAI DAC.
385 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute,
388 int ret = -ENOTSUPP;
394 if (dai->driver->ops &&
395 dai->driver->ops->mute_stream &&
397 !dai->driver->ops->no_capture_mute))
398 ret = dai->driver->ops->mute_stream(dai, mute, direction);
400 return soc_dai_ret(dai, ret);
404 int snd_soc_dai_hw_params(struct snd_soc_dai *dai,
410 if (dai->driver->ops &&
411 dai->driver->ops->hw_params)
412 ret = dai->driver->ops->hw_params(substream, params, dai);
416 soc_dai_mark_push(dai, substream, hw_params);
418 return soc_dai_ret(dai, ret);
421 void snd_soc_dai_hw_free(struct snd_soc_dai *dai,
425 if (rollback && !soc_dai_mark_match(dai, substream, hw_params))
428 if (dai->driver->ops &&
429 dai->driver->ops->hw_free)
430 dai->driver->ops->hw_free(substream, dai);
433 soc_dai_mark_pop(dai, hw_params);
436 int snd_soc_dai_startup(struct snd_soc_dai *dai,
441 if (!snd_soc_dai_stream_valid(dai, substream->stream))
444 if (dai->driver->ops &&
445 dai->driver->ops->startup)
446 ret = dai->driver->ops->startup(substream, dai);
450 soc_dai_mark_push(dai, substream, startup);
452 return soc_dai_ret(dai, ret);
455 void snd_soc_dai_shutdown(struct snd_soc_dai *dai,
459 if (!snd_soc_dai_stream_valid(dai, substream->stream))
462 if (rollback && !soc_dai_mark_match(dai, substream, startup))
465 if (dai->driver->ops &&
466 dai->driver->ops->shutdown)
467 dai->driver->ops->shutdown(substream, dai);
470 soc_dai_mark_pop(dai, startup);
473 int snd_soc_dai_compress_new(struct snd_soc_dai *dai,
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);
484 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
486 * Returns true if the DAI supports the indicated stream type.
488 bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int dir)
490 const struct snd_soc_pcm_stream *stream = snd_soc_dai_get_pcm_stream(dai, dir);
493 return stream->channels_min;
496 void snd_soc_dai_action(struct snd_soc_dai *dai,
500 dai->stream[stream].active += action;
503 dai->component->active += action;
507 int snd_soc_dai_active(const struct snd_soc_dai *dai)
513 active += dai->stream[stream].active;
521 struct snd_soc_dai *dai;
524 for_each_rtd_dais(rtd, i, dai) {
525 if (dai->probed)
528 if (dai->driver->ops) {
529 if (dai->driver->ops->probe_order != order)
532 if (dai->driver->ops->probe) {
533 int ret = dai->driver->ops->probe(dai);
536 return soc_dai_ret(dai, ret);
539 dai->probed = 1;
547 struct snd_soc_dai *dai;
550 for_each_rtd_dais(rtd, i, dai) {
551 if (!dai->probed)
554 if (dai->driver->ops) {
555 if (dai->driver->ops->remove_order != order)
558 if (dai->driver->ops->remove) {
559 r = dai->driver->ops->remove(dai);
564 dai->probed = 0;
572 struct snd_soc_dai *dai;
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);
580 return soc_dai_ret(dai, ret);
590 struct snd_soc_dai *dai;
593 for_each_rtd_dais(rtd, i, dai) {
594 ret = snd_soc_dai_prepare(dai, substream);
602 static int soc_dai_trigger(struct snd_soc_dai *dai,
607 if (!snd_soc_dai_stream_valid(dai, substream->stream))
610 if (dai->driver->ops &&
611 dai->driver->ops->trigger)
612 ret = dai->driver->ops->trigger(substream, cmd, dai);
614 return soc_dai_ret(dai, ret);
621 struct snd_soc_dai *dai;
628 for_each_rtd_dais(rtd, i, dai) {
629 ret = soc_dai_trigger(dai, substream, cmd);
633 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai))
634 snd_soc_dai_digital_mute(dai, 0, substream->stream);
636 soc_dai_mark_push(dai, substream, trigger);
642 for_each_rtd_dais(rtd, i, dai) {
643 if (rollback && !soc_dai_mark_match(dai, substream, trigger))
646 if (snd_soc_dai_mute_is_ctrled_at_trigger(dai))
647 snd_soc_dai_digital_mute(dai, 1, substream->stream);
649 r = soc_dai_trigger(dai, substream, cmd);
652 soc_dai_mark_pop(dai, trigger);
664 struct snd_soc_dai *dai;
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));
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));
687 int snd_soc_dai_compr_startup(struct snd_soc_dai *dai,
692 if (dai->driver->cops &&
693 dai->driver->cops->startup)
694 ret = dai->driver->cops->startup(cstream, dai);
698 soc_dai_mark_push(dai, cstream, compr_startup);
700 return soc_dai_ret(dai, ret);
704 void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai,
708 if (rollback && !soc_dai_mark_match(dai, cstream, compr_startup))
711 if (dai->driver->cops &&
712 dai->driver->cops->shutdown)
713 dai->driver->cops->shutdown(cstream, dai);
716 soc_dai_mark_pop(dai, compr_startup);
720 int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai,
725 if (dai->driver->cops &&
726 dai->driver->cops->trigger)
727 ret = dai->driver->cops->trigger(cstream, cmd, dai);
729 return soc_dai_ret(dai, ret);
733 int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai,
739 if (dai->driver->cops &&
740 dai->driver->cops->set_params)
741 ret = dai->driver->cops->set_params(cstream, params, dai);
743 return soc_dai_ret(dai, ret);
747 int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai,
753 if (dai->driver->cops &&
754 dai->driver->cops->get_params)
755 ret = dai->driver->cops->get_params(cstream, params, dai);
757 return soc_dai_ret(dai, ret);
761 int snd_soc_dai_compr_ack(struct snd_soc_dai *dai,
767 if (dai->driver->cops &&
768 dai->driver->cops->ack)
769 ret = dai->driver->cops->ack(cstream, bytes, dai);
771 return soc_dai_ret(dai, ret);
775 int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai,
781 if (dai->driver->cops &&
782 dai->driver->cops->pointer)
783 ret = dai->driver->cops->pointer(cstream, tstamp, dai);
785 return soc_dai_ret(dai, ret);
789 int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai,
795 if (dai->driver->cops &&
796 dai->driver->cops->set_metadata)
797 ret = dai->driver->cops->set_metadata(cstream, metadata, dai);
799 return soc_dai_ret(dai, ret);
803 int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai,
809 if (dai->driver->cops &&
810 dai->driver->cops->get_metadata)
811 ret = dai->driver->cops->get_metadata(cstream, metadata, dai);
813 return soc_dai_ret(dai, ret);