brintos

brintos / linux-shallow public Read only

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