18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * Copyright (c) 2018 Baylibre SAS.
48c2ecf20Sopenharmony_ci * Author: Jerome Brunet <jbrunet@baylibre.com>
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef _MESON_AXG_TDM_H
88c2ecf20Sopenharmony_ci#define _MESON_AXG_TDM_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/clk.h>
118c2ecf20Sopenharmony_ci#include <linux/regmap.h>
128c2ecf20Sopenharmony_ci#include <sound/pcm.h>
138c2ecf20Sopenharmony_ci#include <sound/soc.h>
148c2ecf20Sopenharmony_ci#include <sound/soc-dai.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define AXG_TDM_NUM_LANES	4
178c2ecf20Sopenharmony_ci#define AXG_TDM_CHANNEL_MAX	128
188c2ecf20Sopenharmony_ci#define AXG_TDM_RATES		(SNDRV_PCM_RATE_5512 |		\
198c2ecf20Sopenharmony_ci				 SNDRV_PCM_RATE_8000_192000)
208c2ecf20Sopenharmony_ci#define AXG_TDM_FORMATS		(SNDRV_PCM_FMTBIT_S8 |		\
218c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S16_LE |	\
228c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S20_LE |	\
238c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_LE |	\
248c2ecf20Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S32_LE)
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistruct axg_tdm_iface {
278c2ecf20Sopenharmony_ci	struct clk *sclk;
288c2ecf20Sopenharmony_ci	struct clk *lrclk;
298c2ecf20Sopenharmony_ci	struct clk *mclk;
308c2ecf20Sopenharmony_ci	unsigned long mclk_rate;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	/* format is common to all the DAIs of the iface */
338c2ecf20Sopenharmony_ci	unsigned int fmt;
348c2ecf20Sopenharmony_ci	unsigned int slots;
358c2ecf20Sopenharmony_ci	unsigned int slot_width;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	/* For component wide symmetry */
388c2ecf20Sopenharmony_ci	int rate;
398c2ecf20Sopenharmony_ci};
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline bool axg_tdm_lrclk_invert(unsigned int fmt)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	return ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) ^
448c2ecf20Sopenharmony_ci		!!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF));
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic inline bool axg_tdm_sclk_invert(unsigned int fmt)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF);
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cistruct axg_tdm_stream {
538c2ecf20Sopenharmony_ci	struct axg_tdm_iface *iface;
548c2ecf20Sopenharmony_ci	struct list_head formatter_list;
558c2ecf20Sopenharmony_ci	struct mutex lock;
568c2ecf20Sopenharmony_ci	unsigned int channels;
578c2ecf20Sopenharmony_ci	unsigned int width;
588c2ecf20Sopenharmony_ci	unsigned int physical_width;
598c2ecf20Sopenharmony_ci	u32 *mask;
608c2ecf20Sopenharmony_ci	bool ready;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
648c2ecf20Sopenharmony_civoid axg_tdm_stream_free(struct axg_tdm_stream *ts);
658c2ecf20Sopenharmony_ciint axg_tdm_stream_start(struct axg_tdm_stream *ts);
668c2ecf20Sopenharmony_civoid axg_tdm_stream_stop(struct axg_tdm_stream *ts);
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	axg_tdm_stream_stop(ts);
718c2ecf20Sopenharmony_ci	return axg_tdm_stream_start(ts);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ciint axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask,
758c2ecf20Sopenharmony_ci			  u32 *rx_mask, unsigned int slots,
768c2ecf20Sopenharmony_ci			  unsigned int slot_width);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#endif /* _MESON_AXG_TDM_H */
79