diff options
Diffstat (limited to 'sound/soc/soc-utils.c')
-rw-r--r-- | sound/soc/soc-utils.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index a4efe7e52a8b..594cb311ff30 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -9,6 +9,7 @@ #include <linux/platform_device.h> #include <linux/export.h> +#include <linux/math.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -52,6 +53,50 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params) } EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk); +/** + * snd_soc_tdm_params_to_bclk - calculate bclk from params and tdm slot info. + * + * Calculate the bclk from the params sample rate and the tdm slot count and + * tdm slot width. Either or both of tdm_width and tdm_slots can be 0. + * + * If tdm_width == 0 and tdm_slots > 0: the params_width will be used. + * If tdm_width > 0 and tdm_slots == 0: the params_channels will be used + * as the slot count. + * Both tdm_width and tdm_slots are 0: this is equivalent to calling + * snd_soc_params_to_bclk(). + * + * If slot_multiple > 1 the slot count (or params_channels if tdm_slots == 0) + * will be rounded up to a multiple of this value. This is mainly useful for + * I2S mode, which has a left and right phase so the number of slots is always + * a multiple of 2. + * + * @params: Pointer to struct_pcm_hw_params. + * @tdm_width: Width in bits of the tdm slots. + * @tdm_slots: Number of tdm slots per frame. + * @slot_multiple: If >1 roundup slot count to a multiple of this value. + * + * Return: bclk frequency in Hz, else a negative error code if params format + * is invalid. + */ +int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params, + int tdm_width, int tdm_slots, int slot_multiple) +{ + if (!tdm_slots) + tdm_slots = params_channels(params); + + if (slot_multiple > 1) + tdm_slots = roundup(tdm_slots, slot_multiple); + + if (!tdm_width) { + tdm_width = snd_pcm_format_width(params_format(params)); + if (tdm_width < 0) + return tdm_width; + } + + return snd_soc_calc_bclk(params_rate(params), tdm_width, 1, tdm_slots); +} +EXPORT_SYMBOL_GPL(snd_soc_tdm_params_to_bclk); + static const struct snd_pcm_hardware dummy_dma_hardware = { /* Random values to keep userspace happy when checking constraints */ .info = SNDRV_PCM_INFO_INTERLEAVED | |