162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// MediaTek ALSA SoC Audio DAI TDM Control 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (c) 2020 MediaTek Inc. 662306a36Sopenharmony_ci// Author: Shane Chien <shane.chien@mediatek.com> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/regmap.h> 962306a36Sopenharmony_ci#include <sound/pcm_params.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "mt8192-afe-clk.h" 1262306a36Sopenharmony_ci#include "mt8192-afe-common.h" 1362306a36Sopenharmony_ci#include "mt8192-afe-gpio.h" 1462306a36Sopenharmony_ci#include "mt8192-interconnection.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct mtk_afe_tdm_priv { 1762306a36Sopenharmony_ci int id; 1862306a36Sopenharmony_ci int bck_id; 1962306a36Sopenharmony_ci int bck_rate; 2062306a36Sopenharmony_ci int tdm_out_mode; 2162306a36Sopenharmony_ci int bck_invert; 2262306a36Sopenharmony_ci int lck_invert; 2362306a36Sopenharmony_ci int mclk_id; 2462306a36Sopenharmony_ci int mclk_multiple; /* according to sample rate */ 2562306a36Sopenharmony_ci int mclk_rate; 2662306a36Sopenharmony_ci int mclk_apll; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cienum { 3062306a36Sopenharmony_ci TDM_OUT_I2S = 0, 3162306a36Sopenharmony_ci TDM_OUT_DSP_A = 1, 3262306a36Sopenharmony_ci TDM_OUT_DSP_B = 2, 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cienum { 3662306a36Sopenharmony_ci TDM_BCK_NON_INV = 0, 3762306a36Sopenharmony_ci TDM_BCK_INV = 1, 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cienum { 4162306a36Sopenharmony_ci TDM_LCK_NON_INV = 0, 4262306a36Sopenharmony_ci TDM_LCK_INV = 1, 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cienum { 4662306a36Sopenharmony_ci TDM_WLEN_16_BIT = 1, 4762306a36Sopenharmony_ci TDM_WLEN_32_BIT = 2, 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cienum { 5162306a36Sopenharmony_ci TDM_CHANNEL_BCK_16 = 0, 5262306a36Sopenharmony_ci TDM_CHANNEL_BCK_24 = 1, 5362306a36Sopenharmony_ci TDM_CHANNEL_BCK_32 = 2, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cienum { 5762306a36Sopenharmony_ci TDM_CHANNEL_NUM_2 = 0, 5862306a36Sopenharmony_ci TDM_CHANNEL_NUM_4 = 1, 5962306a36Sopenharmony_ci TDM_CHANNEL_NUM_8 = 2, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cienum { 6362306a36Sopenharmony_ci TDM_CH_START_O30_O31 = 0, 6462306a36Sopenharmony_ci TDM_CH_START_O32_O33, 6562306a36Sopenharmony_ci TDM_CH_START_O34_O35, 6662306a36Sopenharmony_ci TDM_CH_START_O36_O37, 6762306a36Sopenharmony_ci TDM_CH_ZERO, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic unsigned int get_tdm_wlen(snd_pcm_format_t format) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci return snd_pcm_format_physical_width(format) <= 16 ? 7362306a36Sopenharmony_ci TDM_WLEN_16_BIT : TDM_WLEN_32_BIT; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic unsigned int get_tdm_channel_bck(snd_pcm_format_t format) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci return snd_pcm_format_physical_width(format) <= 16 ? 7962306a36Sopenharmony_ci TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic unsigned int get_tdm_lrck_width(snd_pcm_format_t format) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci return snd_pcm_format_physical_width(format) - 1; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic unsigned int get_tdm_ch(unsigned int ch) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci switch (ch) { 9062306a36Sopenharmony_ci case 1: 9162306a36Sopenharmony_ci case 2: 9262306a36Sopenharmony_ci return TDM_CHANNEL_NUM_2; 9362306a36Sopenharmony_ci case 3: 9462306a36Sopenharmony_ci case 4: 9562306a36Sopenharmony_ci return TDM_CHANNEL_NUM_4; 9662306a36Sopenharmony_ci case 5: 9762306a36Sopenharmony_ci case 6: 9862306a36Sopenharmony_ci case 7: 9962306a36Sopenharmony_ci case 8: 10062306a36Sopenharmony_ci default: 10162306a36Sopenharmony_ci return TDM_CHANNEL_NUM_8; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic unsigned int get_tdm_ch_fixup(unsigned int channels) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci if (channels > 4) 10862306a36Sopenharmony_ci return 8; 10962306a36Sopenharmony_ci else if (channels > 2) 11062306a36Sopenharmony_ci return 4; 11162306a36Sopenharmony_ci else 11262306a36Sopenharmony_ci return 2; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic unsigned int get_tdm_ch_per_sdata(unsigned int mode, 11662306a36Sopenharmony_ci unsigned int channels) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci if (mode == TDM_OUT_DSP_A || mode == TDM_OUT_DSP_B) 11962306a36Sopenharmony_ci return get_tdm_ch_fixup(channels); 12062306a36Sopenharmony_ci else 12162306a36Sopenharmony_ci return 2; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* interconnection */ 12562306a36Sopenharmony_cienum { 12662306a36Sopenharmony_ci HDMI_CONN_CH0 = 0, 12762306a36Sopenharmony_ci HDMI_CONN_CH1, 12862306a36Sopenharmony_ci HDMI_CONN_CH2, 12962306a36Sopenharmony_ci HDMI_CONN_CH3, 13062306a36Sopenharmony_ci HDMI_CONN_CH4, 13162306a36Sopenharmony_ci HDMI_CONN_CH5, 13262306a36Sopenharmony_ci HDMI_CONN_CH6, 13362306a36Sopenharmony_ci HDMI_CONN_CH7, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const char *const hdmi_conn_mux_map[] = { 13762306a36Sopenharmony_ci "CH0", "CH1", "CH2", "CH3", 13862306a36Sopenharmony_ci "CH4", "CH5", "CH6", "CH7", 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int hdmi_conn_mux_map_value[] = { 14262306a36Sopenharmony_ci HDMI_CONN_CH0, 14362306a36Sopenharmony_ci HDMI_CONN_CH1, 14462306a36Sopenharmony_ci HDMI_CONN_CH2, 14562306a36Sopenharmony_ci HDMI_CONN_CH3, 14662306a36Sopenharmony_ci HDMI_CONN_CH4, 14762306a36Sopenharmony_ci HDMI_CONN_CH5, 14862306a36Sopenharmony_ci HDMI_CONN_CH6, 14962306a36Sopenharmony_ci HDMI_CONN_CH7, 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum, 15362306a36Sopenharmony_ci AFE_HDMI_CONN0, 15462306a36Sopenharmony_ci HDMI_O_0_SFT, 15562306a36Sopenharmony_ci HDMI_O_0_MASK, 15662306a36Sopenharmony_ci hdmi_conn_mux_map, 15762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch0_mux_control = 16062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum, 16362306a36Sopenharmony_ci AFE_HDMI_CONN0, 16462306a36Sopenharmony_ci HDMI_O_1_SFT, 16562306a36Sopenharmony_ci HDMI_O_1_MASK, 16662306a36Sopenharmony_ci hdmi_conn_mux_map, 16762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch1_mux_control = 17062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum, 17362306a36Sopenharmony_ci AFE_HDMI_CONN0, 17462306a36Sopenharmony_ci HDMI_O_2_SFT, 17562306a36Sopenharmony_ci HDMI_O_2_MASK, 17662306a36Sopenharmony_ci hdmi_conn_mux_map, 17762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch2_mux_control = 18062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum, 18362306a36Sopenharmony_ci AFE_HDMI_CONN0, 18462306a36Sopenharmony_ci HDMI_O_3_SFT, 18562306a36Sopenharmony_ci HDMI_O_3_MASK, 18662306a36Sopenharmony_ci hdmi_conn_mux_map, 18762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch3_mux_control = 19062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum, 19362306a36Sopenharmony_ci AFE_HDMI_CONN0, 19462306a36Sopenharmony_ci HDMI_O_4_SFT, 19562306a36Sopenharmony_ci HDMI_O_4_MASK, 19662306a36Sopenharmony_ci hdmi_conn_mux_map, 19762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch4_mux_control = 20062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum, 20362306a36Sopenharmony_ci AFE_HDMI_CONN0, 20462306a36Sopenharmony_ci HDMI_O_5_SFT, 20562306a36Sopenharmony_ci HDMI_O_5_MASK, 20662306a36Sopenharmony_ci hdmi_conn_mux_map, 20762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch5_mux_control = 21062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum, 21362306a36Sopenharmony_ci AFE_HDMI_CONN0, 21462306a36Sopenharmony_ci HDMI_O_6_SFT, 21562306a36Sopenharmony_ci HDMI_O_6_MASK, 21662306a36Sopenharmony_ci hdmi_conn_mux_map, 21762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch6_mux_control = 22062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum, 22362306a36Sopenharmony_ci AFE_HDMI_CONN0, 22462306a36Sopenharmony_ci HDMI_O_7_SFT, 22562306a36Sopenharmony_ci HDMI_O_7_MASK, 22662306a36Sopenharmony_ci hdmi_conn_mux_map, 22762306a36Sopenharmony_ci hdmi_conn_mux_map_value); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch7_mux_control = 23062306a36Sopenharmony_ci SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cienum { 23362306a36Sopenharmony_ci SUPPLY_SEQ_APLL, 23462306a36Sopenharmony_ci SUPPLY_SEQ_TDM_MCK_EN, 23562306a36Sopenharmony_ci SUPPLY_SEQ_TDM_BCK_EN, 23662306a36Sopenharmony_ci SUPPLY_SEQ_TDM_EN, 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int get_tdm_id_by_name(const char *name) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci return MT8192_DAI_TDM; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic int mtk_tdm_en_event(struct snd_soc_dapm_widget *w, 24562306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, 24662306a36Sopenharmony_ci int event) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 24962306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 25062306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 25162306a36Sopenharmony_ci int dai_id = get_tdm_id_by_name(w->name); 25262306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (!tdm_priv) { 25562306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); 25662306a36Sopenharmony_ci return -EINVAL; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", 26062306a36Sopenharmony_ci __func__, w->name, event); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci switch (event) { 26362306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 26462306a36Sopenharmony_ci mt8192_afe_gpio_request(afe->dev, true, tdm_priv->id, 0); 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 26762306a36Sopenharmony_ci mt8192_afe_gpio_request(afe->dev, false, tdm_priv->id, 0); 26862306a36Sopenharmony_ci break; 26962306a36Sopenharmony_ci default: 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w, 27762306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, 27862306a36Sopenharmony_ci int event) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 28162306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 28262306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 28362306a36Sopenharmony_ci int dai_id = get_tdm_id_by_name(w->name); 28462306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (!tdm_priv) { 28762306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); 28862306a36Sopenharmony_ci return -EINVAL; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", 29262306a36Sopenharmony_ci __func__, w->name, event, dai_id); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci switch (event) { 29562306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 29662306a36Sopenharmony_ci mt8192_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate); 29762306a36Sopenharmony_ci break; 29862306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 29962306a36Sopenharmony_ci mt8192_mck_disable(afe, tdm_priv->bck_id); 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci default: 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, 30962306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, 31062306a36Sopenharmony_ci int event) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 31362306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 31462306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 31562306a36Sopenharmony_ci int dai_id = get_tdm_id_by_name(w->name); 31662306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (!tdm_priv) { 31962306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); 32062306a36Sopenharmony_ci return -EINVAL; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", 32462306a36Sopenharmony_ci __func__, w->name, event, dai_id); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci switch (event) { 32762306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 32862306a36Sopenharmony_ci mt8192_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate); 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 33162306a36Sopenharmony_ci tdm_priv->mclk_rate = 0; 33262306a36Sopenharmony_ci mt8192_mck_disable(afe, tdm_priv->mclk_id); 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci default: 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = { 34262306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0, 34362306a36Sopenharmony_ci &hdmi_ch0_mux_control), 34462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0, 34562306a36Sopenharmony_ci &hdmi_ch1_mux_control), 34662306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0, 34762306a36Sopenharmony_ci &hdmi_ch2_mux_control), 34862306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0, 34962306a36Sopenharmony_ci &hdmi_ch3_mux_control), 35062306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0, 35162306a36Sopenharmony_ci &hdmi_ch4_mux_control), 35262306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0, 35362306a36Sopenharmony_ci &hdmi_ch5_mux_control), 35462306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0, 35562306a36Sopenharmony_ci &hdmi_ch6_mux_control), 35662306a36Sopenharmony_ci SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0, 35762306a36Sopenharmony_ci &hdmi_ch7_mux_control), 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"), 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN, 36262306a36Sopenharmony_ci AFE_TDM_CON1, TDM_EN_SFT, 0, 36362306a36Sopenharmony_ci mtk_tdm_en_event, 36462306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN, 36762306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0, 36862306a36Sopenharmony_ci mtk_tdm_bck_en_event, 36962306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN, 37262306a36Sopenharmony_ci SND_SOC_NOPM, 0, 0, 37362306a36Sopenharmony_ci mtk_tdm_mck_en_event, 37462306a36Sopenharmony_ci SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source, 37862306a36Sopenharmony_ci struct snd_soc_dapm_widget *sink) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci struct snd_soc_dapm_widget *w = sink; 38162306a36Sopenharmony_ci struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 38262306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 38362306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 38462306a36Sopenharmony_ci int dai_id = get_tdm_id_by_name(w->name); 38562306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 38662306a36Sopenharmony_ci int cur_apll; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* which apll */ 38962306a36Sopenharmony_ci cur_apll = mt8192_get_apll_by_name(afe, source->name); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = { 39562306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH0", "HDMI"}, 39662306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH1", "HDMI"}, 39762306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH2", "HDMI"}, 39862306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH3", "HDMI"}, 39962306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH4", "HDMI"}, 40062306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH5", "HDMI"}, 40162306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH6", "HDMI"}, 40262306a36Sopenharmony_ci {"HDMI_CH0_MUX", "CH7", "HDMI"}, 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH0", "HDMI"}, 40562306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH1", "HDMI"}, 40662306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH2", "HDMI"}, 40762306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH3", "HDMI"}, 40862306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH4", "HDMI"}, 40962306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH5", "HDMI"}, 41062306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH6", "HDMI"}, 41162306a36Sopenharmony_ci {"HDMI_CH1_MUX", "CH7", "HDMI"}, 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH0", "HDMI"}, 41462306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH1", "HDMI"}, 41562306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH2", "HDMI"}, 41662306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH3", "HDMI"}, 41762306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH4", "HDMI"}, 41862306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH5", "HDMI"}, 41962306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH6", "HDMI"}, 42062306a36Sopenharmony_ci {"HDMI_CH2_MUX", "CH7", "HDMI"}, 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH0", "HDMI"}, 42362306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH1", "HDMI"}, 42462306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH2", "HDMI"}, 42562306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH3", "HDMI"}, 42662306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH4", "HDMI"}, 42762306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH5", "HDMI"}, 42862306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH6", "HDMI"}, 42962306a36Sopenharmony_ci {"HDMI_CH3_MUX", "CH7", "HDMI"}, 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH0", "HDMI"}, 43262306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH1", "HDMI"}, 43362306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH2", "HDMI"}, 43462306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH3", "HDMI"}, 43562306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH4", "HDMI"}, 43662306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH5", "HDMI"}, 43762306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH6", "HDMI"}, 43862306a36Sopenharmony_ci {"HDMI_CH4_MUX", "CH7", "HDMI"}, 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH0", "HDMI"}, 44162306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH1", "HDMI"}, 44262306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH2", "HDMI"}, 44362306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH3", "HDMI"}, 44462306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH4", "HDMI"}, 44562306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH5", "HDMI"}, 44662306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH6", "HDMI"}, 44762306a36Sopenharmony_ci {"HDMI_CH5_MUX", "CH7", "HDMI"}, 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH0", "HDMI"}, 45062306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH1", "HDMI"}, 45162306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH2", "HDMI"}, 45262306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH3", "HDMI"}, 45362306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH4", "HDMI"}, 45462306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH5", "HDMI"}, 45562306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH6", "HDMI"}, 45662306a36Sopenharmony_ci {"HDMI_CH6_MUX", "CH7", "HDMI"}, 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH0", "HDMI"}, 45962306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH1", "HDMI"}, 46062306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH2", "HDMI"}, 46162306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH3", "HDMI"}, 46262306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH4", "HDMI"}, 46362306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH5", "HDMI"}, 46462306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH6", "HDMI"}, 46562306a36Sopenharmony_ci {"HDMI_CH7_MUX", "CH7", "HDMI"}, 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH0_MUX"}, 46862306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH1_MUX"}, 46962306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH2_MUX"}, 47062306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH3_MUX"}, 47162306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH4_MUX"}, 47262306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH5_MUX"}, 47362306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH6_MUX"}, 47462306a36Sopenharmony_ci {"TDM", NULL, "HDMI_CH7_MUX"}, 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci {"TDM", NULL, "aud_tdm_clk"}, 47762306a36Sopenharmony_ci {"TDM", NULL, "TDM_BCK"}, 47862306a36Sopenharmony_ci {"TDM", NULL, "TDM_EN"}, 47962306a36Sopenharmony_ci {"TDM_BCK", NULL, "TDM_MCK"}, 48062306a36Sopenharmony_ci {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, 48162306a36Sopenharmony_ci {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, 48262306a36Sopenharmony_ci}; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci/* dai ops */ 48562306a36Sopenharmony_cistatic int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe, 48662306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv, 48762306a36Sopenharmony_ci int freq) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci int apll; 49062306a36Sopenharmony_ci int apll_rate; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci apll = mt8192_get_apll_by_rate(afe, freq); 49362306a36Sopenharmony_ci apll_rate = mt8192_get_apll_rate(afe, apll); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci if (!freq || freq > apll_rate) { 49662306a36Sopenharmony_ci dev_warn(afe->dev, 49762306a36Sopenharmony_ci "%s(), freq(%d Hz) invalid\n", __func__, freq); 49862306a36Sopenharmony_ci return -EINVAL; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (apll_rate % freq != 0) { 50262306a36Sopenharmony_ci dev_warn(afe->dev, 50362306a36Sopenharmony_ci "%s(), APLL cannot generate %d Hz", __func__, freq); 50462306a36Sopenharmony_ci return -EINVAL; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci tdm_priv->mclk_rate = freq; 50862306a36Sopenharmony_ci tdm_priv->mclk_apll = apll; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci return 0; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, 51462306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 51562306a36Sopenharmony_ci struct snd_soc_dai *dai) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 51862306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 51962306a36Sopenharmony_ci int tdm_id = dai->id; 52062306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id]; 52162306a36Sopenharmony_ci unsigned int tdm_out_mode = tdm_priv->tdm_out_mode; 52262306a36Sopenharmony_ci unsigned int rate = params_rate(params); 52362306a36Sopenharmony_ci unsigned int channels = params_channels(params); 52462306a36Sopenharmony_ci unsigned int out_channels_per_sdata = 52562306a36Sopenharmony_ci get_tdm_ch_per_sdata(tdm_out_mode, channels); 52662306a36Sopenharmony_ci snd_pcm_format_t format = params_format(params); 52762306a36Sopenharmony_ci unsigned int tdm_con = 0; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci /* calculate mclk_rate, if not set explicitly */ 53062306a36Sopenharmony_ci if (!tdm_priv->mclk_rate) { 53162306a36Sopenharmony_ci tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple; 53262306a36Sopenharmony_ci mtk_dai_tdm_cal_mclk(afe, 53362306a36Sopenharmony_ci tdm_priv, 53462306a36Sopenharmony_ci tdm_priv->mclk_rate); 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci /* calculate bck */ 53862306a36Sopenharmony_ci tdm_priv->bck_rate = rate * 53962306a36Sopenharmony_ci out_channels_per_sdata * 54062306a36Sopenharmony_ci snd_pcm_format_physical_width(format); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (tdm_priv->bck_rate > tdm_priv->mclk_rate) 54362306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0) 54662306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), bck cannot generate", __func__); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci dev_dbg(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n", 54962306a36Sopenharmony_ci __func__, 55062306a36Sopenharmony_ci tdm_id, rate, channels, format, 55162306a36Sopenharmony_ci tdm_priv->mclk_rate, tdm_priv->bck_rate); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci dev_dbg(afe->dev, "%s(), out_channels_per_sdata = %d\n", 55462306a36Sopenharmony_ci __func__, out_channels_per_sdata); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* set tdm */ 55762306a36Sopenharmony_ci if (tdm_priv->bck_invert) 55862306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_TOP_CON3, 55962306a36Sopenharmony_ci BCK_INVERSE_MASK_SFT, 56062306a36Sopenharmony_ci 0x1 << BCK_INVERSE_SFT); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (tdm_priv->lck_invert) 56362306a36Sopenharmony_ci tdm_con |= 1 << LRCK_INVERSE_SFT; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) { 56662306a36Sopenharmony_ci tdm_con |= 1 << DELAY_DATA_SFT; 56762306a36Sopenharmony_ci tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; 56862306a36Sopenharmony_ci } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) { 56962306a36Sopenharmony_ci tdm_con |= 0 << DELAY_DATA_SFT; 57062306a36Sopenharmony_ci tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; 57162306a36Sopenharmony_ci } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) { 57262306a36Sopenharmony_ci tdm_con |= 1 << DELAY_DATA_SFT; 57362306a36Sopenharmony_ci tdm_con |= 0 << LRCK_TDM_WIDTH_SFT; 57462306a36Sopenharmony_ci } 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci tdm_con |= 1 << LEFT_ALIGN_SFT; 57762306a36Sopenharmony_ci tdm_con |= get_tdm_wlen(format) << WLEN_SFT; 57862306a36Sopenharmony_ci tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT; 57962306a36Sopenharmony_ci tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT; 58062306a36Sopenharmony_ci regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con); 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (out_channels_per_sdata == 2) { 58362306a36Sopenharmony_ci switch (channels) { 58462306a36Sopenharmony_ci case 1: 58562306a36Sopenharmony_ci case 2: 58662306a36Sopenharmony_ci tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 58762306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; 58862306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; 58962306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 59062306a36Sopenharmony_ci break; 59162306a36Sopenharmony_ci case 3: 59262306a36Sopenharmony_ci case 4: 59362306a36Sopenharmony_ci tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 59462306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 59562306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; 59662306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 59762306a36Sopenharmony_ci break; 59862306a36Sopenharmony_ci case 5: 59962306a36Sopenharmony_ci case 6: 60062306a36Sopenharmony_ci tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 60162306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 60262306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; 60362306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 60462306a36Sopenharmony_ci break; 60562306a36Sopenharmony_ci case 7: 60662306a36Sopenharmony_ci case 8: 60762306a36Sopenharmony_ci tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 60862306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 60962306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; 61062306a36Sopenharmony_ci tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT; 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci default: 61362306a36Sopenharmony_ci tdm_con = 0; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci } else { 61662306a36Sopenharmony_ci tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 61762306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; 61862306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; 61962306a36Sopenharmony_ci tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 62562306a36Sopenharmony_ci HDMI_CH_NUM_MASK_SFT, 62662306a36Sopenharmony_ci channels << HDMI_CH_NUM_SFT); 62762306a36Sopenharmony_ci return 0; 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, 63162306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); 63462306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 63562306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci if (!tdm_priv) { 63862306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); 63962306a36Sopenharmony_ci return -EINVAL; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (dir != SND_SOC_CLOCK_OUT) { 64362306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__); 64462306a36Sopenharmony_ci return -EINVAL; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); 65062306a36Sopenharmony_ci} 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_cistatic int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); 65562306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 65662306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (!tdm_priv) { 65962306a36Sopenharmony_ci dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__); 66062306a36Sopenharmony_ci return -EINVAL; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci /* DAI mode*/ 66462306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 66562306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 66662306a36Sopenharmony_ci tdm_priv->tdm_out_mode = TDM_OUT_I2S; 66762306a36Sopenharmony_ci break; 66862306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 66962306a36Sopenharmony_ci tdm_priv->tdm_out_mode = TDM_OUT_DSP_A; 67062306a36Sopenharmony_ci break; 67162306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 67262306a36Sopenharmony_ci tdm_priv->tdm_out_mode = TDM_OUT_DSP_B; 67362306a36Sopenharmony_ci break; 67462306a36Sopenharmony_ci default: 67562306a36Sopenharmony_ci tdm_priv->tdm_out_mode = TDM_OUT_I2S; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci /* DAI clock inversion*/ 67962306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 68062306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 68162306a36Sopenharmony_ci tdm_priv->bck_invert = TDM_BCK_NON_INV; 68262306a36Sopenharmony_ci tdm_priv->lck_invert = TDM_LCK_NON_INV; 68362306a36Sopenharmony_ci break; 68462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 68562306a36Sopenharmony_ci tdm_priv->bck_invert = TDM_BCK_NON_INV; 68662306a36Sopenharmony_ci tdm_priv->lck_invert = TDM_LCK_INV; 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 68962306a36Sopenharmony_ci tdm_priv->bck_invert = TDM_BCK_INV; 69062306a36Sopenharmony_ci tdm_priv->lck_invert = TDM_LCK_NON_INV; 69162306a36Sopenharmony_ci break; 69262306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 69362306a36Sopenharmony_ci default: 69462306a36Sopenharmony_ci tdm_priv->bck_invert = TDM_BCK_INV; 69562306a36Sopenharmony_ci tdm_priv->lck_invert = TDM_LCK_INV; 69662306a36Sopenharmony_ci break; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci return 0; 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic const struct snd_soc_dai_ops mtk_dai_tdm_ops = { 70362306a36Sopenharmony_ci .hw_params = mtk_dai_tdm_hw_params, 70462306a36Sopenharmony_ci .set_sysclk = mtk_dai_tdm_set_sysclk, 70562306a36Sopenharmony_ci .set_fmt = mtk_dai_tdm_set_fmt, 70662306a36Sopenharmony_ci}; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci/* dai driver */ 70962306a36Sopenharmony_ci#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ 71062306a36Sopenharmony_ci SNDRV_PCM_RATE_88200 |\ 71162306a36Sopenharmony_ci SNDRV_PCM_RATE_96000 |\ 71262306a36Sopenharmony_ci SNDRV_PCM_RATE_176400 |\ 71362306a36Sopenharmony_ci SNDRV_PCM_RATE_192000) 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 71662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE |\ 71762306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE) 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic struct snd_soc_dai_driver mtk_dai_tdm_driver[] = { 72062306a36Sopenharmony_ci { 72162306a36Sopenharmony_ci .name = "TDM", 72262306a36Sopenharmony_ci .id = MT8192_DAI_TDM, 72362306a36Sopenharmony_ci .playback = { 72462306a36Sopenharmony_ci .stream_name = "TDM", 72562306a36Sopenharmony_ci .channels_min = 2, 72662306a36Sopenharmony_ci .channels_max = 8, 72762306a36Sopenharmony_ci .rates = MTK_TDM_RATES, 72862306a36Sopenharmony_ci .formats = MTK_TDM_FORMATS, 72962306a36Sopenharmony_ci }, 73062306a36Sopenharmony_ci .ops = &mtk_dai_tdm_ops, 73162306a36Sopenharmony_ci }, 73262306a36Sopenharmony_ci}; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_cistatic struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv), 73962306a36Sopenharmony_ci GFP_KERNEL); 74062306a36Sopenharmony_ci if (!tdm_priv) 74162306a36Sopenharmony_ci return NULL; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci tdm_priv->mclk_multiple = 512; 74462306a36Sopenharmony_ci tdm_priv->bck_id = MT8192_I2S4_BCK; 74562306a36Sopenharmony_ci tdm_priv->mclk_id = MT8192_I2S4_MCK; 74662306a36Sopenharmony_ci tdm_priv->id = MT8192_DAI_TDM; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci return tdm_priv; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ciint mt8192_dai_tdm_register(struct mtk_base_afe *afe) 75262306a36Sopenharmony_ci{ 75362306a36Sopenharmony_ci struct mt8192_afe_private *afe_priv = afe->platform_priv; 75462306a36Sopenharmony_ci struct mtk_afe_tdm_priv *tdm_priv; 75562306a36Sopenharmony_ci struct mtk_base_afe_dai *dai; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 75862306a36Sopenharmony_ci if (!dai) 75962306a36Sopenharmony_ci return -ENOMEM; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci list_add(&dai->list, &afe->sub_dais); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci dai->dai_drivers = mtk_dai_tdm_driver; 76462306a36Sopenharmony_ci dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci dai->dapm_widgets = mtk_dai_tdm_widgets; 76762306a36Sopenharmony_ci dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets); 76862306a36Sopenharmony_ci dai->dapm_routes = mtk_dai_tdm_routes; 76962306a36Sopenharmony_ci dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci tdm_priv = init_tdm_priv_data(afe); 77262306a36Sopenharmony_ci if (!tdm_priv) 77362306a36Sopenharmony_ci return -ENOMEM; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci afe_priv->dai_priv[MT8192_DAI_TDM] = tdm_priv; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci return 0; 77862306a36Sopenharmony_ci} 779