11a11d88fSJerome Brunet /* SPDX-License-Identifier: (GPL-2.0 OR MIT) 21a11d88fSJerome Brunet * 31a11d88fSJerome Brunet * Copyright (c) 2018 Baylibre SAS. 41a11d88fSJerome Brunet * Author: Jerome Brunet <jbrunet@baylibre.com> 51a11d88fSJerome Brunet */ 61a11d88fSJerome Brunet 71a11d88fSJerome Brunet #ifndef _MESON_AXG_TDM_H 81a11d88fSJerome Brunet #define _MESON_AXG_TDM_H 91a11d88fSJerome Brunet 101a11d88fSJerome Brunet #include <linux/clk.h> 111a11d88fSJerome Brunet #include <linux/regmap.h> 121a11d88fSJerome Brunet #include <sound/pcm.h> 131a11d88fSJerome Brunet #include <sound/soc.h> 141a11d88fSJerome Brunet #include <sound/soc-dai.h> 151a11d88fSJerome Brunet 161a11d88fSJerome Brunet #define AXG_TDM_NUM_LANES 4 171a11d88fSJerome Brunet #define AXG_TDM_CHANNEL_MAX 128 181a11d88fSJerome Brunet #define AXG_TDM_RATES (SNDRV_PCM_RATE_5512 | \ 191a11d88fSJerome Brunet SNDRV_PCM_RATE_8000_192000) 201a11d88fSJerome Brunet #define AXG_TDM_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 211a11d88fSJerome Brunet SNDRV_PCM_FMTBIT_S16_LE | \ 221a11d88fSJerome Brunet SNDRV_PCM_FMTBIT_S20_LE | \ 231a11d88fSJerome Brunet SNDRV_PCM_FMTBIT_S24_LE | \ 241a11d88fSJerome Brunet SNDRV_PCM_FMTBIT_S32_LE) 251a11d88fSJerome Brunet 261a11d88fSJerome Brunet struct axg_tdm_iface { 271a11d88fSJerome Brunet struct clk *sclk; 281a11d88fSJerome Brunet struct clk *lrclk; 291a11d88fSJerome Brunet struct clk *mclk; 301a11d88fSJerome Brunet unsigned long mclk_rate; 311a11d88fSJerome Brunet 321a11d88fSJerome Brunet /* format is common to all the DAIs of the iface */ 331a11d88fSJerome Brunet unsigned int fmt; 341a11d88fSJerome Brunet unsigned int slots; 351a11d88fSJerome Brunet unsigned int slot_width; 361a11d88fSJerome Brunet 371a11d88fSJerome Brunet /* For component wide symmetry */ 381a11d88fSJerome Brunet int rate; 391a11d88fSJerome Brunet }; 401a11d88fSJerome Brunet axg_tdm_lrclk_invert(unsigned int fmt)411a11d88fSJerome Brunetstatic inline bool axg_tdm_lrclk_invert(unsigned int fmt) 421a11d88fSJerome Brunet { 43*cb36ff78SJerome Brunet return ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) ^ 441a11d88fSJerome Brunet !!(fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_NB_IF)); 451a11d88fSJerome Brunet } 461a11d88fSJerome Brunet axg_tdm_sclk_invert(unsigned int fmt)471a11d88fSJerome Brunetstatic inline bool axg_tdm_sclk_invert(unsigned int fmt) 481a11d88fSJerome Brunet { 491a11d88fSJerome Brunet return fmt & (SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_IB_NF); 501a11d88fSJerome Brunet } 511a11d88fSJerome Brunet 521a11d88fSJerome Brunet struct axg_tdm_stream { 531a11d88fSJerome Brunet struct axg_tdm_iface *iface; 541a11d88fSJerome Brunet struct list_head formatter_list; 551a11d88fSJerome Brunet struct mutex lock; 561a11d88fSJerome Brunet unsigned int channels; 571a11d88fSJerome Brunet unsigned int width; 581a11d88fSJerome Brunet unsigned int physical_width; 591a11d88fSJerome Brunet u32 *mask; 601a11d88fSJerome Brunet bool ready; 611a11d88fSJerome Brunet }; 621a11d88fSJerome Brunet 631a11d88fSJerome Brunet struct axg_tdm_stream *axg_tdm_stream_alloc(struct axg_tdm_iface *iface); 641a11d88fSJerome Brunet void axg_tdm_stream_free(struct axg_tdm_stream *ts); 651a11d88fSJerome Brunet int axg_tdm_stream_start(struct axg_tdm_stream *ts); 661a11d88fSJerome Brunet void axg_tdm_stream_stop(struct axg_tdm_stream *ts); 671a11d88fSJerome Brunet axg_tdm_stream_reset(struct axg_tdm_stream * ts)681a11d88fSJerome Brunetstatic inline int axg_tdm_stream_reset(struct axg_tdm_stream *ts) 691a11d88fSJerome Brunet { 701a11d88fSJerome Brunet axg_tdm_stream_stop(ts); 711a11d88fSJerome Brunet return axg_tdm_stream_start(ts); 721a11d88fSJerome Brunet } 731a11d88fSJerome Brunet 74d60e4f1eSJerome Brunet int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, 75d60e4f1eSJerome Brunet u32 *rx_mask, unsigned int slots, 76d60e4f1eSJerome Brunet unsigned int slot_width); 77d60e4f1eSJerome Brunet 781a11d88fSJerome Brunet #endif /* _MESON_AXG_TDM_H */ 79