aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/meson/axg-tdm.h
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2018-07-17 17:42:58 +0200
committerMark Brown <broonie@kernel.org>2018-07-20 17:38:27 +0100
commit1a11d88f499ceb69e9b4098ddc36866820335a54 (patch)
treed45bd34baecaf05d08351acf1b6231b1619d321f /sound/soc/meson/axg-tdm.h
parentASoC: meson: add axg tdm interface DT bindings documentation (diff)
downloadlinux-dev-1a11d88f499ceb69e9b4098ddc36866820335a54.tar.xz
linux-dev-1a11d88f499ceb69e9b4098ddc36866820335a54.zip
ASoC: meson: add tdm formatter base driver
Add Amlogic's axg TDM core driver. On this SoC, tdm is bit more complex than usual, mainly because the different TDM input decoders can be attached to any of TDM pad interface, including the output pads. For the this, TDM on this SoC is modeled like this: - TDM interface provides the DAIs the codecs will be attached to. The main responsibility of this driver is to manage the pad format and the TDM clock rates. - TDM Formatters: These are the entities which are actually dealing with the TDM signal. TDMOUT produce a TDM signal from the audio sample provided by FRDDR using the clocks provided the TDM interface. TDMIN feeds TODDR with audio sample using the clocks and TDM signal provided by the TDM Interface. - TDM Streams: This provides the link between 1 DAI stream of the TDM interface and one (or more) TDM formatters. This driver provides the TDM formatter and TDM stream operations. Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/meson/axg-tdm.h')
-rw-r--r--sound/soc/meson/axg-tdm.h74
1 files changed, 74 insertions, 0 deletions
diff --git a/sound/soc/meson/axg-tdm.h b/sound/soc/meson/axg-tdm.h
new file mode 100644
index 000000000000..435d95b86457
--- /dev/null
+++ b/sound/soc/meson/axg-tdm.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ *
+ * Copyright (c) 2018 Baylibre SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef _MESON_AXG_TDM_H
+#define _MESON_AXG_TDM_H
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+
+#define AXG_TDM_NUM_LANES 4
+#define AXG_TDM_CHANNEL_MAX 128
+#define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \
+ SNDRV_PCM_RATE_8000_192000)
+#define AXG_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+struct axg_tdm_iface {
+ struct clk *sclk;
+ struct clk *lrclk;
+ struct clk *mclk;
+ unsigned long mclk_rate;
+
+ /* format is common to all the DAIs of the iface */
+ unsigned int fmt;
+ unsigned int slots;
+ unsigned int slot_width;
+
+ /* For component wide symmetry */
+ int rate;
+};
+
+static inline bool axg_tdm_lrclk_invert(unsigned int fmt)
+{
+ return (fmt & SND_SOC_DAIFMT_I2S) ^
+ !!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF));
+}
+
+static inline bool axg_tdm_sclk_invert(unsigned int fmt)
+{
+ return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF);
+}
+
+struct axg_tdm_stream {
+ struct axg_tdm_iface *iface;
+ struct list_head formatter_list;
+ struct mutex lock;
+ unsigned int channels;
+ unsigned int width;
+ unsigned int physical_width;
+ u32 *mask;
+ bool ready;
+};
+
+struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
+void axg_tdm_stream_free(struct axg_tdm_stream *ts);
+int axg_tdm_stream_start(struct axg_tdm_stream *ts);
+void axg_tdm_stream_stop(struct axg_tdm_stream *ts);
+
+static inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
+{
+ axg_tdm_stream_stop(ts);
+ return axg_tdm_stream_start(ts);
+}
+
+#endif /* _MESON_AXG_TDM_H */