1 // SPDX-License-Identifier: GPL-2.0
5 // Copyright (C) 2019 Renesas Electronics Corp.
6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
10 #include <sound/soc-dai.h>
13 * snd_soc_dai_set_sysclk - configure DAI system or master clock.
15 * @clk_id: DAI specific clock ID
16 * @freq: new clock frequency in Hz
17 * @dir: new clock direction - input/output.
19 * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
21 int snd_soc_dai_set_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
22 unsigned int freq
, int dir
)
24 if (dai
->driver
->ops
->set_sysclk
)
25 return dai
->driver
->ops
->set_sysclk(dai
, clk_id
, freq
, dir
);
27 return snd_soc_component_set_sysclk(dai
->component
, clk_id
, 0,
30 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk
);
33 * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
35 * @div_id: DAI specific clock divider ID
36 * @div: new clock divisor.
38 * Configures the clock dividers. This is used to derive the best DAI bit and
39 * frame clocks from the system or master clock. It's best to set the DAI bit
40 * and frame clocks as low as possible to save system power.
42 int snd_soc_dai_set_clkdiv(struct snd_soc_dai
*dai
,
45 if (dai
->driver
->ops
->set_clkdiv
)
46 return dai
->driver
->ops
->set_clkdiv(dai
, div_id
, div
);
50 EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv
);
53 * snd_soc_dai_set_pll - configure DAI PLL.
55 * @pll_id: DAI specific PLL ID
56 * @source: DAI specific source for the PLL
57 * @freq_in: PLL input clock frequency in Hz
58 * @freq_out: requested PLL output clock frequency in Hz
60 * Configures and enables PLL to generate output clock based on input clock.
62 int snd_soc_dai_set_pll(struct snd_soc_dai
*dai
, int pll_id
, int source
,
63 unsigned int freq_in
, unsigned int freq_out
)
65 if (dai
->driver
->ops
->set_pll
)
66 return dai
->driver
->ops
->set_pll(dai
, pll_id
, source
,
69 return snd_soc_component_set_pll(dai
->component
, pll_id
, source
,
72 EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll
);
75 * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
77 * @ratio: Ratio of BCLK to Sample rate.
79 * Configures the DAI for a preset BCLK to sample rate ratio.
81 int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai
*dai
, unsigned int ratio
)
83 if (dai
->driver
->ops
->set_bclk_ratio
)
84 return dai
->driver
->ops
->set_bclk_ratio(dai
, ratio
);
88 EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio
);
91 * snd_soc_dai_set_fmt - configure DAI hardware audio format.
93 * @fmt: SND_SOC_DAIFMT_* format value.
95 * Configures the DAI hardware format and clocking.
97 int snd_soc_dai_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
99 if (dai
->driver
->ops
->set_fmt
== NULL
)
101 return dai
->driver
->ops
->set_fmt(dai
, fmt
);
103 EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt
);
106 * snd_soc_xlate_tdm_slot - generate tx/rx slot mask.
107 * @slots: Number of slots in use.
108 * @tx_mask: bitmask representing active TX slots.
109 * @rx_mask: bitmask representing active RX slots.
111 * Generates the TDM tx and rx slot default masks for DAI.
113 static int snd_soc_xlate_tdm_slot_mask(unsigned int slots
,
114 unsigned int *tx_mask
,
115 unsigned int *rx_mask
)
117 if (*tx_mask
|| *rx_mask
)
123 *tx_mask
= (1 << slots
) - 1;
124 *rx_mask
= (1 << slots
) - 1;
130 * snd_soc_dai_set_tdm_slot() - Configures a DAI for TDM operation
131 * @dai: The DAI to configure
132 * @tx_mask: bitmask representing active TX slots.
133 * @rx_mask: bitmask representing active RX slots.
134 * @slots: Number of slots in use.
135 * @slot_width: Width in bits for each slot.
137 * This function configures the specified DAI for TDM operation. @slot contains
138 * the total number of slots of the TDM stream and @slot_with the width of each
139 * slot in bit clock cycles. @tx_mask and @rx_mask are bitmasks specifying the
140 * active slots of the TDM stream for the specified DAI, i.e. which slots the
141 * DAI should write to or read from. If a bit is set the corresponding slot is
142 * active, if a bit is cleared the corresponding slot is inactive. Bit 0 maps to
143 * the first slot, bit 1 to the second slot and so on. The first active slot
144 * maps to the first channel of the DAI, the second active slot to the second
147 * TDM mode can be disabled by passing 0 for @slots. In this case @tx_mask,
148 * @rx_mask and @slot_width will be ignored.
150 * Returns 0 on success, a negative error code otherwise.
152 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai
*dai
,
153 unsigned int tx_mask
, unsigned int rx_mask
,
154 int slots
, int slot_width
)
156 if (dai
->driver
->ops
->xlate_tdm_slot_mask
)
157 dai
->driver
->ops
->xlate_tdm_slot_mask(slots
,
160 snd_soc_xlate_tdm_slot_mask(slots
, &tx_mask
, &rx_mask
);
162 dai
->tx_mask
= tx_mask
;
163 dai
->rx_mask
= rx_mask
;
165 if (dai
->driver
->ops
->set_tdm_slot
)
166 return dai
->driver
->ops
->set_tdm_slot(dai
, tx_mask
, rx_mask
,
171 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot
);
174 * snd_soc_dai_set_channel_map - configure DAI audio channel map
176 * @tx_num: how many TX channels
177 * @tx_slot: pointer to an array which imply the TX slot number channel
179 * @rx_num: how many RX channels
180 * @rx_slot: pointer to an array which imply the RX slot number channel
183 * configure the relationship between channel number and TDM slot number.
185 int snd_soc_dai_set_channel_map(struct snd_soc_dai
*dai
,
186 unsigned int tx_num
, unsigned int *tx_slot
,
187 unsigned int rx_num
, unsigned int *rx_slot
)
189 if (dai
->driver
->ops
->set_channel_map
)
190 return dai
->driver
->ops
->set_channel_map(dai
, tx_num
, tx_slot
,
195 EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map
);
198 * snd_soc_dai_get_channel_map - Get DAI audio channel map
200 * @tx_num: how many TX channels
201 * @tx_slot: pointer to an array which imply the TX slot number channel
203 * @rx_num: how many RX channels
204 * @rx_slot: pointer to an array which imply the RX slot number channel
207 int snd_soc_dai_get_channel_map(struct snd_soc_dai
*dai
,
208 unsigned int *tx_num
, unsigned int *tx_slot
,
209 unsigned int *rx_num
, unsigned int *rx_slot
)
211 if (dai
->driver
->ops
->get_channel_map
)
212 return dai
->driver
->ops
->get_channel_map(dai
, tx_num
, tx_slot
,
217 EXPORT_SYMBOL_GPL(snd_soc_dai_get_channel_map
);
220 * snd_soc_dai_set_tristate - configure DAI system or master clock.
222 * @tristate: tristate enable
224 * Tristates the DAI so that others can use it.
226 int snd_soc_dai_set_tristate(struct snd_soc_dai
*dai
, int tristate
)
228 if (dai
->driver
->ops
->set_tristate
)
229 return dai
->driver
->ops
->set_tristate(dai
, tristate
);
233 EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate
);
236 * snd_soc_dai_digital_mute - configure DAI system or master clock.
239 * @direction: stream to mute
243 int snd_soc_dai_digital_mute(struct snd_soc_dai
*dai
, int mute
,
246 if (dai
->driver
->ops
->mute_stream
)
247 return dai
->driver
->ops
->mute_stream(dai
, mute
, direction
);
248 else if (direction
== SNDRV_PCM_STREAM_PLAYBACK
&&
249 dai
->driver
->ops
->digital_mute
)
250 return dai
->driver
->ops
->digital_mute(dai
, mute
);
254 EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute
);
256 int snd_soc_dai_hw_params(struct snd_soc_dai
*dai
,
257 struct snd_pcm_substream
*substream
,
258 struct snd_pcm_hw_params
*params
)
260 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
263 /* perform any topology hw_params fixups before DAI */
264 if (rtd
->dai_link
->be_hw_params_fixup
) {
265 ret
= rtd
->dai_link
->be_hw_params_fixup(rtd
, params
);
268 "ASoC: hw_params topology fixup failed %d\n",
274 if (dai
->driver
->ops
->hw_params
) {
275 ret
= dai
->driver
->ops
->hw_params(substream
, params
, dai
);
277 dev_err(dai
->dev
, "ASoC: can't set %s hw params: %d\n",
286 void snd_soc_dai_hw_free(struct snd_soc_dai
*dai
,
287 struct snd_pcm_substream
*substream
)
289 if (dai
->driver
->ops
->hw_free
)
290 dai
->driver
->ops
->hw_free(substream
, dai
);
293 int snd_soc_dai_startup(struct snd_soc_dai
*dai
,
294 struct snd_pcm_substream
*substream
)
298 if (dai
->driver
->ops
->startup
)
299 ret
= dai
->driver
->ops
->startup(substream
, dai
);
304 void snd_soc_dai_shutdown(struct snd_soc_dai
*dai
,
305 struct snd_pcm_substream
*substream
)
307 if (dai
->driver
->ops
->shutdown
)
308 dai
->driver
->ops
->shutdown(substream
, dai
);
311 int snd_soc_dai_prepare(struct snd_soc_dai
*dai
,
312 struct snd_pcm_substream
*substream
)
316 if (dai
->driver
->ops
->prepare
)
317 ret
= dai
->driver
->ops
->prepare(substream
, dai
);
322 int snd_soc_dai_trigger(struct snd_soc_dai
*dai
,
323 struct snd_pcm_substream
*substream
,
328 if (dai
->driver
->ops
->trigger
)
329 ret
= dai
->driver
->ops
->trigger(substream
, cmd
, dai
);
334 int snd_soc_dai_bespoke_trigger(struct snd_soc_dai
*dai
,
335 struct snd_pcm_substream
*substream
,
340 if (dai
->driver
->ops
->bespoke_trigger
)
341 ret
= dai
->driver
->ops
->bespoke_trigger(substream
, cmd
, dai
);
346 snd_pcm_sframes_t
snd_soc_dai_delay(struct snd_soc_dai
*dai
,
347 struct snd_pcm_substream
*substream
)
351 if (dai
->driver
->ops
->delay
)
352 delay
= dai
->driver
->ops
->delay(substream
, dai
);
357 int snd_soc_dai_probe(struct snd_soc_dai
*dai
)
359 if (dai
->driver
->probe
)
360 return dai
->driver
->probe(dai
);
364 int snd_soc_dai_remove(struct snd_soc_dai
*dai
)
366 if (dai
->driver
->remove
)
367 return dai
->driver
->remove(dai
);
371 int snd_soc_dai_compress_new(struct snd_soc_dai
*dai
,
372 struct snd_soc_pcm_runtime
*rtd
, int num
)
374 if (dai
->driver
->compress_new
)
375 return dai
->driver
->compress_new(rtd
, num
);
380 * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
382 * Returns true if the DAI supports the indicated stream type.
384 bool snd_soc_dai_stream_valid(struct snd_soc_dai
*dai
, int dir
)
386 struct snd_soc_pcm_stream
*stream
;
388 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
389 stream
= &dai
->driver
->playback
;
391 stream
= &dai
->driver
->capture
;
393 /* If the codec specifies any channels at all, it supports the stream */
394 return stream
->channels_min
;