summaryrefslogtreecommitdiff
path: root/sound/soc/soc-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-utils.c')
-rw-r--r--sound/soc/soc-utils.c45
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 |