1*4882a593Smuzhiyun /* SPDX-License-Identifier: (GPL-2.0 OR MIT) 2*4882a593Smuzhiyun * 3*4882a593Smuzhiyun * Copyright (c) 2018 Baylibre SAS. 4*4882a593Smuzhiyun * Author: Jerome Brunet <jbrunet@baylibre.com> 5*4882a593Smuzhiyun */ 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun #ifndef _MESON_AXG_TDM_H 8*4882a593Smuzhiyun #define _MESON_AXG_TDM_H 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #include <linux/clk.h> 11*4882a593Smuzhiyun #include <linux/regmap.h> 12*4882a593Smuzhiyun #include <sound/pcm.h> 13*4882a593Smuzhiyun #include <sound/soc.h> 14*4882a593Smuzhiyun #include <sound/soc-dai.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #define AXG_TDM_NUM_LANES 4 17*4882a593Smuzhiyun #define AXG_TDM_CHANNEL_MAX 128 18*4882a593Smuzhiyun #define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \ 19*4882a593Smuzhiyun SNDRV_PCM_RATE_8000_192000) 20*4882a593Smuzhiyun #define AXG_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 21*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S16_LE | \ 22*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S20_LE | \ 23*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S24_LE | \ 24*4882a593Smuzhiyun SNDRV_PCM_FMTBIT_S32_LE) 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun struct axg_tdm_iface { 27*4882a593Smuzhiyun struct clk *sclk; 28*4882a593Smuzhiyun struct clk *lrclk; 29*4882a593Smuzhiyun struct clk *mclk; 30*4882a593Smuzhiyun unsigned long mclk_rate; 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun /* format is common to all the DAIs of the iface */ 33*4882a593Smuzhiyun unsigned int fmt; 34*4882a593Smuzhiyun unsigned int slots; 35*4882a593Smuzhiyun unsigned int slot_width; 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* For component wide symmetry */ 38*4882a593Smuzhiyun int rate; 39*4882a593Smuzhiyun }; 40*4882a593Smuzhiyun axg_tdm_lrclk_invert(unsigned int fmt)41*4882a593Smuzhiyunstatic inline bool axg_tdm_lrclk_invert(unsigned int fmt) 42*4882a593Smuzhiyun { 43*4882a593Smuzhiyun return ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) ^ 44*4882a593Smuzhiyun !!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF)); 45*4882a593Smuzhiyun } 46*4882a593Smuzhiyun axg_tdm_sclk_invert(unsigned int fmt)47*4882a593Smuzhiyunstatic inline bool axg_tdm_sclk_invert(unsigned int fmt) 48*4882a593Smuzhiyun { 49*4882a593Smuzhiyun return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF); 50*4882a593Smuzhiyun } 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun struct axg_tdm_stream { 53*4882a593Smuzhiyun struct axg_tdm_iface *iface; 54*4882a593Smuzhiyun struct list_head formatter_list; 55*4882a593Smuzhiyun struct mutex lock; 56*4882a593Smuzhiyun unsigned int channels; 57*4882a593Smuzhiyun unsigned int width; 58*4882a593Smuzhiyun unsigned int physical_width; 59*4882a593Smuzhiyun u32 *mask; 60*4882a593Smuzhiyun bool ready; 61*4882a593Smuzhiyun }; 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface); 64*4882a593Smuzhiyun void axg_tdm_stream_free(struct axg_tdm_stream *ts); 65*4882a593Smuzhiyun int axg_tdm_stream_start(struct axg_tdm_stream *ts); 66*4882a593Smuzhiyun void axg_tdm_stream_stop(struct axg_tdm_stream *ts); 67*4882a593Smuzhiyun axg_tdm_stream_reset(struct axg_tdm_stream * ts)68*4882a593Smuzhiyunstatic inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts) 69*4882a593Smuzhiyun { 70*4882a593Smuzhiyun axg_tdm_stream_stop(ts); 71*4882a593Smuzhiyun return axg_tdm_stream_start(ts); 72*4882a593Smuzhiyun } 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, 75*4882a593Smuzhiyun u32 *rx_mask, unsigned int slots, 76*4882a593Smuzhiyun unsigned int slot_width); 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun #endif /* _MESON_AXG_TDM_H */ 79