162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Copyright (c) 2018 Baylibre SAS.
462306a36Sopenharmony_ci * Author: Jerome Brunet <jbrunet@baylibre.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef _MESON_AXG_TDM_H
862306a36Sopenharmony_ci#define _MESON_AXG_TDM_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/clk.h>
1162306a36Sopenharmony_ci#include <linux/regmap.h>
1262306a36Sopenharmony_ci#include <sound/pcm.h>
1362306a36Sopenharmony_ci#include <sound/soc.h>
1462306a36Sopenharmony_ci#include <sound/soc-dai.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define AXG_TDM_NUM_LANES	4
1762306a36Sopenharmony_ci#define AXG_TDM_CHANNEL_MAX	128
1862306a36Sopenharmony_ci#define AXG_TDM_RATES		(SNDRV_PCM_RATE_5512 |		\
1962306a36Sopenharmony_ci				 SNDRV_PCM_RATE_8000_192000)
2062306a36Sopenharmony_ci#define AXG_TDM_FORMATS		(SNDRV_PCM_FMTBIT_S8 |		\
2162306a36Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S16_LE |	\
2262306a36Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S20_LE |	\
2362306a36Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S24_LE |	\
2462306a36Sopenharmony_ci				 SNDRV_PCM_FMTBIT_S32_LE)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistruct axg_tdm_iface {
2762306a36Sopenharmony_ci	struct clk *sclk;
2862306a36Sopenharmony_ci	struct clk *lrclk;
2962306a36Sopenharmony_ci	struct clk *mclk;
3062306a36Sopenharmony_ci	unsigned long mclk_rate;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	/* format is common to all the DAIs of the iface */
3362306a36Sopenharmony_ci	unsigned int fmt;
3462306a36Sopenharmony_ci	unsigned int slots;
3562306a36Sopenharmony_ci	unsigned int slot_width;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	/* For component wide symmetry */
3862306a36Sopenharmony_ci	int rate;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic inline bool axg_tdm_lrclk_invert(unsigned int fmt)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	return ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) ^
4462306a36Sopenharmony_ci		!!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF));
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic inline bool axg_tdm_sclk_invert(unsigned int fmt)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF);
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct axg_tdm_stream {
5362306a36Sopenharmony_ci	struct axg_tdm_iface *iface;
5462306a36Sopenharmony_ci	struct list_head formatter_list;
5562306a36Sopenharmony_ci	struct mutex lock;
5662306a36Sopenharmony_ci	unsigned int channels;
5762306a36Sopenharmony_ci	unsigned int width;
5862306a36Sopenharmony_ci	unsigned int physical_width;
5962306a36Sopenharmony_ci	u32 *mask;
6062306a36Sopenharmony_ci	bool ready;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface);
6462306a36Sopenharmony_civoid axg_tdm_stream_free(struct axg_tdm_stream *ts);
6562306a36Sopenharmony_ciint axg_tdm_stream_start(struct axg_tdm_stream *ts);
6662306a36Sopenharmony_civoid axg_tdm_stream_stop(struct axg_tdm_stream *ts);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	axg_tdm_stream_stop(ts);
7162306a36Sopenharmony_ci	return axg_tdm_stream_start(ts);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ciint axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask,
7562306a36Sopenharmony_ci			  u32 *rx_mask, unsigned int slots,
7662306a36Sopenharmony_ci			  unsigned int slot_width);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#endif /* _MESON_AXG_TDM_H */
79