cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mt8183-dai-tdm.c (19948B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// MediaTek ALSA SoC Audio DAI TDM Control
      4//
      5// Copyright (c) 2018 MediaTek Inc.
      6// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
      7
      8#include <linux/regmap.h>
      9#include <sound/pcm_params.h>
     10#include "mt8183-afe-clk.h"
     11#include "mt8183-afe-common.h"
     12#include "mt8183-interconnection.h"
     13#include "mt8183-reg.h"
     14
     15struct mtk_afe_tdm_priv {
     16	int bck_id;
     17	int bck_rate;
     18	int tdm_out_mode;
     19	int bck_invert;
     20	int lck_invert;
     21	int mclk_id;
     22	int mclk_multiple; /* according to sample rate */
     23	int mclk_rate;
     24	int mclk_apll;
     25};
     26
     27enum {
     28	TDM_OUT_I2S = 0,
     29	TDM_OUT_TDM = 1,
     30};
     31
     32enum {
     33	TDM_BCK_NON_INV = 0,
     34	TDM_BCK_INV = 1,
     35};
     36
     37enum {
     38	TDM_LCK_NON_INV = 0,
     39	TDM_LCK_INV = 1,
     40};
     41
     42enum {
     43	TDM_WLEN_16_BIT = 1,
     44	TDM_WLEN_32_BIT = 2,
     45};
     46
     47enum {
     48	TDM_CHANNEL_BCK_16 = 0,
     49	TDM_CHANNEL_BCK_24 = 1,
     50	TDM_CHANNEL_BCK_32 = 2,
     51};
     52
     53enum {
     54	TDM_CHANNEL_NUM_2 = 0,
     55	TDM_CHANNEL_NUM_4 = 1,
     56	TDM_CHANNEL_NUM_8 = 2,
     57};
     58
     59enum  {
     60	TDM_CH_START_O30_O31 = 0,
     61	TDM_CH_START_O32_O33,
     62	TDM_CH_START_O34_O35,
     63	TDM_CH_START_O36_O37,
     64	TDM_CH_ZERO,
     65};
     66
     67enum {
     68	HDMI_BIT_WIDTH_16_BIT = 0,
     69	HDMI_BIT_WIDTH_32_BIT = 1,
     70};
     71
     72static unsigned int get_hdmi_wlen(snd_pcm_format_t format)
     73{
     74	return snd_pcm_format_physical_width(format) <= 16 ?
     75	       HDMI_BIT_WIDTH_16_BIT : HDMI_BIT_WIDTH_32_BIT;
     76}
     77
     78static unsigned int get_tdm_wlen(snd_pcm_format_t format)
     79{
     80	return snd_pcm_format_physical_width(format) <= 16 ?
     81	       TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
     82}
     83
     84static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
     85{
     86	return snd_pcm_format_physical_width(format) <= 16 ?
     87	       TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
     88}
     89
     90static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
     91{
     92	return snd_pcm_format_physical_width(format) - 1;
     93}
     94
     95static unsigned int get_tdm_ch(unsigned int ch)
     96{
     97	switch (ch) {
     98	case 1:
     99	case 2:
    100		return TDM_CHANNEL_NUM_2;
    101	case 3:
    102	case 4:
    103		return TDM_CHANNEL_NUM_4;
    104	case 5:
    105	case 6:
    106	case 7:
    107	case 8:
    108	default:
    109		return TDM_CHANNEL_NUM_8;
    110	}
    111}
    112
    113static unsigned int get_tdm_ch_fixup(unsigned int channels)
    114{
    115	if (channels > 4)
    116		return 8;
    117	else if (channels > 2)
    118		return 4;
    119	else
    120		return 2;
    121}
    122
    123static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
    124					 unsigned int channels)
    125{
    126	if (mode == TDM_OUT_TDM)
    127		return get_tdm_ch_fixup(channels);
    128	else
    129		return 2;
    130}
    131
    132/* interconnection */
    133enum {
    134	HDMI_CONN_CH0 = 0,
    135	HDMI_CONN_CH1,
    136	HDMI_CONN_CH2,
    137	HDMI_CONN_CH3,
    138	HDMI_CONN_CH4,
    139	HDMI_CONN_CH5,
    140	HDMI_CONN_CH6,
    141	HDMI_CONN_CH7,
    142};
    143
    144static const char *const hdmi_conn_mux_map[] = {
    145	"CH0", "CH1", "CH2", "CH3",
    146	"CH4", "CH5", "CH6", "CH7",
    147};
    148
    149static int hdmi_conn_mux_map_value[] = {
    150	HDMI_CONN_CH0,
    151	HDMI_CONN_CH1,
    152	HDMI_CONN_CH2,
    153	HDMI_CONN_CH3,
    154	HDMI_CONN_CH4,
    155	HDMI_CONN_CH5,
    156	HDMI_CONN_CH6,
    157	HDMI_CONN_CH7,
    158};
    159
    160static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
    161				  AFE_HDMI_CONN0,
    162				  HDMI_O_0_SFT,
    163				  HDMI_O_0_MASK,
    164				  hdmi_conn_mux_map,
    165				  hdmi_conn_mux_map_value);
    166
    167static const struct snd_kcontrol_new hdmi_ch0_mux_control =
    168	SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
    169
    170static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
    171				  AFE_HDMI_CONN0,
    172				  HDMI_O_1_SFT,
    173				  HDMI_O_1_MASK,
    174				  hdmi_conn_mux_map,
    175				  hdmi_conn_mux_map_value);
    176
    177static const struct snd_kcontrol_new hdmi_ch1_mux_control =
    178	SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
    179
    180static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
    181				  AFE_HDMI_CONN0,
    182				  HDMI_O_2_SFT,
    183				  HDMI_O_2_MASK,
    184				  hdmi_conn_mux_map,
    185				  hdmi_conn_mux_map_value);
    186
    187static const struct snd_kcontrol_new hdmi_ch2_mux_control =
    188	SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
    189
    190static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
    191				  AFE_HDMI_CONN0,
    192				  HDMI_O_3_SFT,
    193				  HDMI_O_3_MASK,
    194				  hdmi_conn_mux_map,
    195				  hdmi_conn_mux_map_value);
    196
    197static const struct snd_kcontrol_new hdmi_ch3_mux_control =
    198	SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
    199
    200static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
    201				  AFE_HDMI_CONN0,
    202				  HDMI_O_4_SFT,
    203				  HDMI_O_4_MASK,
    204				  hdmi_conn_mux_map,
    205				  hdmi_conn_mux_map_value);
    206
    207static const struct snd_kcontrol_new hdmi_ch4_mux_control =
    208	SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
    209
    210static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
    211				  AFE_HDMI_CONN0,
    212				  HDMI_O_5_SFT,
    213				  HDMI_O_5_MASK,
    214				  hdmi_conn_mux_map,
    215				  hdmi_conn_mux_map_value);
    216
    217static const struct snd_kcontrol_new hdmi_ch5_mux_control =
    218	SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
    219
    220static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
    221				  AFE_HDMI_CONN0,
    222				  HDMI_O_6_SFT,
    223				  HDMI_O_6_MASK,
    224				  hdmi_conn_mux_map,
    225				  hdmi_conn_mux_map_value);
    226
    227static const struct snd_kcontrol_new hdmi_ch6_mux_control =
    228	SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
    229
    230static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
    231				  AFE_HDMI_CONN0,
    232				  HDMI_O_7_SFT,
    233				  HDMI_O_7_MASK,
    234				  hdmi_conn_mux_map,
    235				  hdmi_conn_mux_map_value);
    236
    237static const struct snd_kcontrol_new hdmi_ch7_mux_control =
    238	SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
    239
    240enum {
    241	SUPPLY_SEQ_APLL,
    242	SUPPLY_SEQ_TDM_MCK_EN,
    243	SUPPLY_SEQ_TDM_BCK_EN,
    244};
    245
    246static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
    247				struct snd_kcontrol *kcontrol,
    248				int event)
    249{
    250	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
    251	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
    252	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    253	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
    254
    255	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
    256		 __func__, w->name, event);
    257
    258	switch (event) {
    259	case SND_SOC_DAPM_PRE_PMU:
    260		mt8183_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
    261		break;
    262	case SND_SOC_DAPM_POST_PMD:
    263		mt8183_mck_disable(afe, tdm_priv->bck_id);
    264		break;
    265	default:
    266		break;
    267	}
    268
    269	return 0;
    270}
    271
    272static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
    273				struct snd_kcontrol *kcontrol,
    274				int event)
    275{
    276	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
    277	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
    278	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    279	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
    280
    281	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
    282		 __func__, w->name, event);
    283
    284	switch (event) {
    285	case SND_SOC_DAPM_PRE_PMU:
    286		mt8183_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
    287		break;
    288	case SND_SOC_DAPM_POST_PMD:
    289		tdm_priv->mclk_rate = 0;
    290		mt8183_mck_disable(afe, tdm_priv->mclk_id);
    291		break;
    292	default:
    293		break;
    294	}
    295
    296	return 0;
    297}
    298
    299static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
    300	SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
    301			 &hdmi_ch0_mux_control),
    302	SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
    303			 &hdmi_ch1_mux_control),
    304	SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
    305			 &hdmi_ch2_mux_control),
    306	SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
    307			 &hdmi_ch3_mux_control),
    308	SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
    309			 &hdmi_ch4_mux_control),
    310	SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
    311			 &hdmi_ch5_mux_control),
    312	SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
    313			 &hdmi_ch6_mux_control),
    314	SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
    315			 &hdmi_ch7_mux_control),
    316
    317	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
    318
    319	SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
    320			      SND_SOC_NOPM, 0, 0,
    321			      mtk_tdm_bck_en_event,
    322			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
    323
    324	SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
    325			      SND_SOC_NOPM, 0, 0,
    326			      mtk_tdm_mck_en_event,
    327			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
    328};
    329
    330static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
    331				    struct snd_soc_dapm_widget *sink)
    332{
    333	struct snd_soc_dapm_widget *w = sink;
    334	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
    335	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
    336	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    337	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
    338	int cur_apll;
    339
    340	/* which apll */
    341	cur_apll = mt8183_get_apll_by_name(afe, source->name);
    342
    343	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
    344}
    345
    346static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
    347	{"HDMI_CH0_MUX", "CH0", "HDMI"},
    348	{"HDMI_CH0_MUX", "CH1", "HDMI"},
    349	{"HDMI_CH0_MUX", "CH2", "HDMI"},
    350	{"HDMI_CH0_MUX", "CH3", "HDMI"},
    351	{"HDMI_CH0_MUX", "CH4", "HDMI"},
    352	{"HDMI_CH0_MUX", "CH5", "HDMI"},
    353	{"HDMI_CH0_MUX", "CH6", "HDMI"},
    354	{"HDMI_CH0_MUX", "CH7", "HDMI"},
    355
    356	{"HDMI_CH1_MUX", "CH0", "HDMI"},
    357	{"HDMI_CH1_MUX", "CH1", "HDMI"},
    358	{"HDMI_CH1_MUX", "CH2", "HDMI"},
    359	{"HDMI_CH1_MUX", "CH3", "HDMI"},
    360	{"HDMI_CH1_MUX", "CH4", "HDMI"},
    361	{"HDMI_CH1_MUX", "CH5", "HDMI"},
    362	{"HDMI_CH1_MUX", "CH6", "HDMI"},
    363	{"HDMI_CH1_MUX", "CH7", "HDMI"},
    364
    365	{"HDMI_CH2_MUX", "CH0", "HDMI"},
    366	{"HDMI_CH2_MUX", "CH1", "HDMI"},
    367	{"HDMI_CH2_MUX", "CH2", "HDMI"},
    368	{"HDMI_CH2_MUX", "CH3", "HDMI"},
    369	{"HDMI_CH2_MUX", "CH4", "HDMI"},
    370	{"HDMI_CH2_MUX", "CH5", "HDMI"},
    371	{"HDMI_CH2_MUX", "CH6", "HDMI"},
    372	{"HDMI_CH2_MUX", "CH7", "HDMI"},
    373
    374	{"HDMI_CH3_MUX", "CH0", "HDMI"},
    375	{"HDMI_CH3_MUX", "CH1", "HDMI"},
    376	{"HDMI_CH3_MUX", "CH2", "HDMI"},
    377	{"HDMI_CH3_MUX", "CH3", "HDMI"},
    378	{"HDMI_CH3_MUX", "CH4", "HDMI"},
    379	{"HDMI_CH3_MUX", "CH5", "HDMI"},
    380	{"HDMI_CH3_MUX", "CH6", "HDMI"},
    381	{"HDMI_CH3_MUX", "CH7", "HDMI"},
    382
    383	{"HDMI_CH4_MUX", "CH0", "HDMI"},
    384	{"HDMI_CH4_MUX", "CH1", "HDMI"},
    385	{"HDMI_CH4_MUX", "CH2", "HDMI"},
    386	{"HDMI_CH4_MUX", "CH3", "HDMI"},
    387	{"HDMI_CH4_MUX", "CH4", "HDMI"},
    388	{"HDMI_CH4_MUX", "CH5", "HDMI"},
    389	{"HDMI_CH4_MUX", "CH6", "HDMI"},
    390	{"HDMI_CH4_MUX", "CH7", "HDMI"},
    391
    392	{"HDMI_CH5_MUX", "CH0", "HDMI"},
    393	{"HDMI_CH5_MUX", "CH1", "HDMI"},
    394	{"HDMI_CH5_MUX", "CH2", "HDMI"},
    395	{"HDMI_CH5_MUX", "CH3", "HDMI"},
    396	{"HDMI_CH5_MUX", "CH4", "HDMI"},
    397	{"HDMI_CH5_MUX", "CH5", "HDMI"},
    398	{"HDMI_CH5_MUX", "CH6", "HDMI"},
    399	{"HDMI_CH5_MUX", "CH7", "HDMI"},
    400
    401	{"HDMI_CH6_MUX", "CH0", "HDMI"},
    402	{"HDMI_CH6_MUX", "CH1", "HDMI"},
    403	{"HDMI_CH6_MUX", "CH2", "HDMI"},
    404	{"HDMI_CH6_MUX", "CH3", "HDMI"},
    405	{"HDMI_CH6_MUX", "CH4", "HDMI"},
    406	{"HDMI_CH6_MUX", "CH5", "HDMI"},
    407	{"HDMI_CH6_MUX", "CH6", "HDMI"},
    408	{"HDMI_CH6_MUX", "CH7", "HDMI"},
    409
    410	{"HDMI_CH7_MUX", "CH0", "HDMI"},
    411	{"HDMI_CH7_MUX", "CH1", "HDMI"},
    412	{"HDMI_CH7_MUX", "CH2", "HDMI"},
    413	{"HDMI_CH7_MUX", "CH3", "HDMI"},
    414	{"HDMI_CH7_MUX", "CH4", "HDMI"},
    415	{"HDMI_CH7_MUX", "CH5", "HDMI"},
    416	{"HDMI_CH7_MUX", "CH6", "HDMI"},
    417	{"HDMI_CH7_MUX", "CH7", "HDMI"},
    418
    419	{"TDM", NULL, "HDMI_CH0_MUX"},
    420	{"TDM", NULL, "HDMI_CH1_MUX"},
    421	{"TDM", NULL, "HDMI_CH2_MUX"},
    422	{"TDM", NULL, "HDMI_CH3_MUX"},
    423	{"TDM", NULL, "HDMI_CH4_MUX"},
    424	{"TDM", NULL, "HDMI_CH5_MUX"},
    425	{"TDM", NULL, "HDMI_CH6_MUX"},
    426	{"TDM", NULL, "HDMI_CH7_MUX"},
    427
    428	{"TDM", NULL, "aud_tdm_clk"},
    429	{"TDM", NULL, "TDM_BCK"},
    430	{"TDM_BCK", NULL, "TDM_MCK"},
    431	{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
    432	{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
    433};
    434
    435/* dai ops */
    436static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
    437				struct mtk_afe_tdm_priv *tdm_priv,
    438				int freq)
    439{
    440	int apll;
    441	int apll_rate;
    442
    443	apll = mt8183_get_apll_by_rate(afe, freq);
    444	apll_rate = mt8183_get_apll_rate(afe, apll);
    445
    446	if (!freq || freq > apll_rate) {
    447		dev_warn(afe->dev,
    448			 "%s(), freq(%d Hz) invalid\n", __func__, freq);
    449		return -EINVAL;
    450	}
    451
    452	if (apll_rate % freq != 0) {
    453		dev_warn(afe->dev,
    454			 "%s(), APLL cannot generate %d Hz", __func__, freq);
    455		return -EINVAL;
    456	}
    457
    458	tdm_priv->mclk_rate = freq;
    459	tdm_priv->mclk_apll = apll;
    460
    461	return 0;
    462}
    463
    464static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
    465				 struct snd_pcm_hw_params *params,
    466				 struct snd_soc_dai *dai)
    467{
    468	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
    469	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    470	int tdm_id = dai->id;
    471	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
    472	unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
    473	unsigned int rate = params_rate(params);
    474	unsigned int channels = params_channels(params);
    475	unsigned int out_channels_per_sdata =
    476		get_tdm_ch_per_sdata(tdm_out_mode, channels);
    477	snd_pcm_format_t format = params_format(params);
    478	unsigned int tdm_con = 0;
    479
    480	/* calculate mclk_rate, if not set explicitly */
    481	if (!tdm_priv->mclk_rate) {
    482		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
    483		mtk_dai_tdm_cal_mclk(afe,
    484				     tdm_priv,
    485				     tdm_priv->mclk_rate);
    486	}
    487
    488	/* calculate bck */
    489	tdm_priv->bck_rate = rate *
    490			     out_channels_per_sdata *
    491			     snd_pcm_format_physical_width(format);
    492
    493	if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
    494		dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
    495
    496	if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
    497		dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
    498
    499	dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
    500		 __func__,
    501		 tdm_id, rate, channels, format,
    502		 tdm_priv->mclk_rate, tdm_priv->bck_rate);
    503	dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
    504		 __func__, out_channels_per_sdata);
    505
    506	/* set tdm */
    507	if (tdm_priv->bck_invert)
    508		regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
    509				   BCK_INVERSE_MASK_SFT,
    510				   0x1 << BCK_INVERSE_SFT);
    511
    512	if (tdm_priv->lck_invert)
    513		tdm_con |= 1 << LRCK_INVERSE_SFT;
    514
    515	if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
    516		tdm_con |= 1 << DELAY_DATA_SFT;
    517		tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
    518	} else if (tdm_priv->tdm_out_mode == TDM_OUT_TDM) {
    519		tdm_con |= 0 << DELAY_DATA_SFT;
    520		tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
    521	}
    522
    523	tdm_con |= 1 << LEFT_ALIGN_SFT;
    524	tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
    525	tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
    526	tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
    527	regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
    528
    529	if (out_channels_per_sdata == 2) {
    530		switch (channels) {
    531		case 1:
    532		case 2:
    533			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
    534			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
    535			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
    536			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
    537			break;
    538		case 3:
    539		case 4:
    540			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
    541			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
    542			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
    543			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
    544			break;
    545		case 5:
    546		case 6:
    547			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
    548			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
    549			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
    550			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
    551			break;
    552		case 7:
    553		case 8:
    554			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
    555			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
    556			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
    557			tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
    558			break;
    559		default:
    560			tdm_con = 0;
    561		}
    562	} else {
    563		tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
    564		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
    565		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
    566		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
    567	}
    568
    569	regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
    570
    571	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
    572			   AFE_HDMI_OUT_CH_NUM_MASK_SFT,
    573			   channels << AFE_HDMI_OUT_CH_NUM_SFT);
    574
    575	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
    576			   AFE_HDMI_OUT_BIT_WIDTH_MASK_SFT,
    577			   get_hdmi_wlen(format) << AFE_HDMI_OUT_BIT_WIDTH_SFT);
    578	return 0;
    579}
    580
    581static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
    582			       int cmd,
    583			       struct snd_soc_dai *dai)
    584{
    585	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
    586
    587	switch (cmd) {
    588	case SNDRV_PCM_TRIGGER_START:
    589	case SNDRV_PCM_TRIGGER_RESUME:
    590		/* enable Out control */
    591		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
    592				   AFE_HDMI_OUT_ON_MASK_SFT,
    593				   0x1 << AFE_HDMI_OUT_ON_SFT);
    594		/* enable tdm */
    595		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
    596				   TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
    597		break;
    598	case SNDRV_PCM_TRIGGER_STOP:
    599	case SNDRV_PCM_TRIGGER_SUSPEND:
    600		/* disable tdm */
    601		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
    602				   TDM_EN_MASK_SFT, 0);
    603		/* disable Out control */
    604		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
    605				   AFE_HDMI_OUT_ON_MASK_SFT,
    606				   0);
    607		break;
    608	default:
    609		return -EINVAL;
    610	}
    611
    612	return 0;
    613}
    614
    615static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
    616				  int clk_id, unsigned int freq, int dir)
    617{
    618	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
    619	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    620	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
    621
    622	if (!tdm_priv) {
    623		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
    624		return -EINVAL;
    625	}
    626
    627	if (dir != SND_SOC_CLOCK_OUT) {
    628		dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
    629		return -EINVAL;
    630	}
    631
    632	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
    633
    634	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
    635}
    636
    637static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
    638{
    639	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
    640	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    641	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
    642
    643	if (!tdm_priv) {
    644		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
    645		return -EINVAL;
    646	}
    647
    648	/* DAI mode*/
    649	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    650	case SND_SOC_DAIFMT_I2S:
    651		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
    652		break;
    653	case SND_SOC_DAIFMT_DSP_A:
    654		tdm_priv->tdm_out_mode = TDM_OUT_TDM;
    655		break;
    656	default:
    657		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
    658	}
    659
    660	/* DAI clock inversion*/
    661	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
    662	case SND_SOC_DAIFMT_NB_NF:
    663		tdm_priv->bck_invert = TDM_BCK_NON_INV;
    664		tdm_priv->lck_invert = TDM_LCK_NON_INV;
    665		break;
    666	case SND_SOC_DAIFMT_NB_IF:
    667		tdm_priv->bck_invert = TDM_BCK_NON_INV;
    668		tdm_priv->lck_invert = TDM_LCK_INV;
    669		break;
    670	case SND_SOC_DAIFMT_IB_NF:
    671		tdm_priv->bck_invert = TDM_BCK_INV;
    672		tdm_priv->lck_invert = TDM_LCK_NON_INV;
    673		break;
    674	case SND_SOC_DAIFMT_IB_IF:
    675	default:
    676		tdm_priv->bck_invert = TDM_BCK_INV;
    677		tdm_priv->lck_invert = TDM_LCK_INV;
    678		break;
    679	}
    680
    681	return 0;
    682}
    683
    684static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
    685	.hw_params = mtk_dai_tdm_hw_params,
    686	.trigger = mtk_dai_tdm_trigger,
    687	.set_sysclk = mtk_dai_tdm_set_sysclk,
    688	.set_fmt = mtk_dai_tdm_set_fmt,
    689};
    690
    691/* dai driver */
    692#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
    693		       SNDRV_PCM_RATE_88200 |\
    694		       SNDRV_PCM_RATE_96000 |\
    695		       SNDRV_PCM_RATE_176400 |\
    696		       SNDRV_PCM_RATE_192000)
    697
    698#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
    699			 SNDRV_PCM_FMTBIT_S24_LE |\
    700			 SNDRV_PCM_FMTBIT_S32_LE)
    701
    702static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
    703	{
    704		.name = "TDM",
    705		.id = MT8183_DAI_TDM,
    706		.playback = {
    707			.stream_name = "TDM",
    708			.channels_min = 2,
    709			.channels_max = 8,
    710			.rates = MTK_TDM_RATES,
    711			.formats = MTK_TDM_FORMATS,
    712		},
    713		.ops = &mtk_dai_tdm_ops,
    714	},
    715};
    716
    717int mt8183_dai_tdm_register(struct mtk_base_afe *afe)
    718{
    719	struct mt8183_afe_private *afe_priv = afe->platform_priv;
    720	struct mtk_afe_tdm_priv *tdm_priv;
    721	struct mtk_base_afe_dai *dai;
    722
    723	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
    724	if (!dai)
    725		return -ENOMEM;
    726
    727	list_add(&dai->list, &afe->sub_dais);
    728
    729	dai->dai_drivers = mtk_dai_tdm_driver;
    730	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
    731
    732	dai->dapm_widgets = mtk_dai_tdm_widgets;
    733	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
    734	dai->dapm_routes = mtk_dai_tdm_routes;
    735	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
    736
    737	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
    738				GFP_KERNEL);
    739	if (!tdm_priv)
    740		return -ENOMEM;
    741
    742	tdm_priv->mclk_multiple = 128;
    743	tdm_priv->bck_id = MT8183_I2S4_BCK;
    744	tdm_priv->mclk_id = MT8183_I2S4_MCK;
    745
    746	afe_priv->dai_priv[MT8183_DAI_TDM] = tdm_priv;
    747	return 0;
    748}