13a280ed1SRyder Lee // SPDX-License-Identifier: GPL-2.0 243a6a7e7SGarlic Tseng /* 343a6a7e7SGarlic Tseng * Mediatek ALSA SoC AFE platform driver for 2701 443a6a7e7SGarlic Tseng * 543a6a7e7SGarlic Tseng * Copyright (c) 2016 MediaTek Inc. 643a6a7e7SGarlic Tseng * Author: Garlic Tseng <garlic.tseng@mediatek.com> 743a6a7e7SGarlic Tseng * Ir Lian <ir.lian@mediatek.com> 8cf870273SRyder Lee * Ryder Lee <ryder.lee@mediatek.com> 943a6a7e7SGarlic Tseng */ 1043a6a7e7SGarlic Tseng 1143a6a7e7SGarlic Tseng #include <linux/delay.h> 1243a6a7e7SGarlic Tseng #include <linux/module.h> 13dfa3cbb8SRyder Lee #include <linux/mfd/syscon.h> 1443a6a7e7SGarlic Tseng #include <linux/of.h> 1543a6a7e7SGarlic Tseng #include <linux/of_address.h> 16bfdc56e5SRyder Lee #include <linux/of_device.h> 1743a6a7e7SGarlic Tseng #include <linux/pm_runtime.h> 1843a6a7e7SGarlic Tseng 1943a6a7e7SGarlic Tseng #include "mt2701-afe-common.h" 2043a6a7e7SGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 2143a6a7e7SGarlic Tseng #include "../common/mtk-afe-platform-driver.h" 2243a6a7e7SGarlic Tseng #include "../common/mtk-afe-fe-dai.h" 2343a6a7e7SGarlic Tseng 2443a6a7e7SGarlic Tseng static const struct snd_pcm_hardware mt2701_afe_hardware = { 2543a6a7e7SGarlic Tseng .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED 2643a6a7e7SGarlic Tseng | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID, 2743a6a7e7SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE 2843a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE, 2943a6a7e7SGarlic Tseng .period_bytes_min = 1024, 3043a6a7e7SGarlic Tseng .period_bytes_max = 1024 * 256, 3143a6a7e7SGarlic Tseng .periods_min = 4, 3243a6a7e7SGarlic Tseng .periods_max = 1024, 33bfdc56e5SRyder Lee .buffer_bytes_max = 1024 * 1024, 3443a6a7e7SGarlic Tseng .fifo_size = 0, 3543a6a7e7SGarlic Tseng }; 3643a6a7e7SGarlic Tseng 3743a6a7e7SGarlic Tseng struct mt2701_afe_rate { 3843a6a7e7SGarlic Tseng unsigned int rate; 3943a6a7e7SGarlic Tseng unsigned int regvalue; 4043a6a7e7SGarlic Tseng }; 4143a6a7e7SGarlic Tseng 4243a6a7e7SGarlic Tseng static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { 4343a6a7e7SGarlic Tseng { .rate = 8000, .regvalue = 0 }, 4443a6a7e7SGarlic Tseng { .rate = 12000, .regvalue = 1 }, 4543a6a7e7SGarlic Tseng { .rate = 16000, .regvalue = 2 }, 4643a6a7e7SGarlic Tseng { .rate = 24000, .regvalue = 3 }, 4743a6a7e7SGarlic Tseng { .rate = 32000, .regvalue = 4 }, 4843a6a7e7SGarlic Tseng { .rate = 48000, .regvalue = 5 }, 4943a6a7e7SGarlic Tseng { .rate = 96000, .regvalue = 6 }, 5043a6a7e7SGarlic Tseng { .rate = 192000, .regvalue = 7 }, 5143a6a7e7SGarlic Tseng { .rate = 384000, .regvalue = 8 }, 5243a6a7e7SGarlic Tseng { .rate = 7350, .regvalue = 16 }, 5343a6a7e7SGarlic Tseng { .rate = 11025, .regvalue = 17 }, 5443a6a7e7SGarlic Tseng { .rate = 14700, .regvalue = 18 }, 5543a6a7e7SGarlic Tseng { .rate = 22050, .regvalue = 19 }, 5643a6a7e7SGarlic Tseng { .rate = 29400, .regvalue = 20 }, 5743a6a7e7SGarlic Tseng { .rate = 44100, .regvalue = 21 }, 5843a6a7e7SGarlic Tseng { .rate = 88200, .regvalue = 22 }, 5943a6a7e7SGarlic Tseng { .rate = 176400, .regvalue = 23 }, 6043a6a7e7SGarlic Tseng { .rate = 352800, .regvalue = 24 }, 6143a6a7e7SGarlic Tseng }; 6243a6a7e7SGarlic Tseng 6325d01dc6SWei Yongjun static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) 6443a6a7e7SGarlic Tseng { 65bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 6643a6a7e7SGarlic Tseng int val = num - MT2701_IO_I2S; 6743a6a7e7SGarlic Tseng 68bfdc56e5SRyder Lee if (val < 0 || val >= afe_priv->soc->i2s_num) { 6943a6a7e7SGarlic Tseng dev_err(afe->dev, "%s, num not available, num %d, val %d\n", 7043a6a7e7SGarlic Tseng __func__, num, val); 7143a6a7e7SGarlic Tseng return -EINVAL; 7243a6a7e7SGarlic Tseng } 7343a6a7e7SGarlic Tseng return val; 7443a6a7e7SGarlic Tseng } 7543a6a7e7SGarlic Tseng 7643a6a7e7SGarlic Tseng static int mt2701_afe_i2s_fs(unsigned int sample_rate) 7743a6a7e7SGarlic Tseng { 7843a6a7e7SGarlic Tseng int i; 7943a6a7e7SGarlic Tseng 8043a6a7e7SGarlic Tseng for (i = 0; i < ARRAY_SIZE(mt2701_afe_i2s_rates); i++) 8143a6a7e7SGarlic Tseng if (mt2701_afe_i2s_rates[i].rate == sample_rate) 8243a6a7e7SGarlic Tseng return mt2701_afe_i2s_rates[i].regvalue; 8343a6a7e7SGarlic Tseng 8443a6a7e7SGarlic Tseng return -EINVAL; 8543a6a7e7SGarlic Tseng } 8643a6a7e7SGarlic Tseng 8743a6a7e7SGarlic Tseng static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, 8843a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 8943a6a7e7SGarlic Tseng { 90e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 91bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 9243a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 93bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 9443a6a7e7SGarlic Tseng 9543a6a7e7SGarlic Tseng if (i2s_num < 0) 9643a6a7e7SGarlic Tseng return i2s_num; 9743a6a7e7SGarlic Tseng 98bfdc56e5SRyder Lee return mt2701_afe_enable_mclk(afe, mode ? 1 : i2s_num); 9943a6a7e7SGarlic Tseng } 10043a6a7e7SGarlic Tseng 101cf870273SRyder Lee static int mt2701_afe_i2s_path_disable(struct mtk_base_afe *afe, 102cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 103cf870273SRyder Lee int stream_dir) 10443a6a7e7SGarlic Tseng { 105cf870273SRyder Lee const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; 10643a6a7e7SGarlic Tseng 107cf870273SRyder Lee if (--i2s_path->on[stream_dir] < 0) 10843a6a7e7SGarlic Tseng i2s_path->on[stream_dir] = 0; 109cf870273SRyder Lee 11043a6a7e7SGarlic Tseng if (i2s_path->on[stream_dir]) 11143a6a7e7SGarlic Tseng return 0; 11243a6a7e7SGarlic Tseng 11343a6a7e7SGarlic Tseng /* disable i2s */ 11443a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 11543a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_EN, 0); 116d8d99d8eSRyder Lee 117cf870273SRyder Lee mt2701_afe_disable_i2s(afe, i2s_path, stream_dir); 118d8d99d8eSRyder Lee 11943a6a7e7SGarlic Tseng return 0; 12043a6a7e7SGarlic Tseng } 12143a6a7e7SGarlic Tseng 12243a6a7e7SGarlic Tseng static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, 12343a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 12443a6a7e7SGarlic Tseng { 125e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 12643a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 12743a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 12843a6a7e7SGarlic Tseng struct mt2701_i2s_path *i2s_path; 129bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 13043a6a7e7SGarlic Tseng 13143a6a7e7SGarlic Tseng if (i2s_num < 0) 13243a6a7e7SGarlic Tseng return; 13343a6a7e7SGarlic Tseng 13443a6a7e7SGarlic Tseng i2s_path = &afe_priv->i2s_path[i2s_num]; 13543a6a7e7SGarlic Tseng 13643a6a7e7SGarlic Tseng if (i2s_path->occupied[substream->stream]) 13743a6a7e7SGarlic Tseng i2s_path->occupied[substream->stream] = 0; 13843a6a7e7SGarlic Tseng else 139cf870273SRyder Lee goto exit; 14043a6a7e7SGarlic Tseng 141cf870273SRyder Lee mt2701_afe_i2s_path_disable(afe, i2s_path, substream->stream); 14243a6a7e7SGarlic Tseng 14343a6a7e7SGarlic Tseng /* need to disable i2s-out path when disable i2s-in */ 14443a6a7e7SGarlic Tseng if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 145cf870273SRyder Lee mt2701_afe_i2s_path_disable(afe, i2s_path, !substream->stream); 14643a6a7e7SGarlic Tseng 147cf870273SRyder Lee exit: 14843a6a7e7SGarlic Tseng /* disable mclk */ 149bfdc56e5SRyder Lee mt2701_afe_disable_mclk(afe, mode ? 1 : i2s_num); 15043a6a7e7SGarlic Tseng } 15143a6a7e7SGarlic Tseng 152cf870273SRyder Lee static int mt2701_i2s_path_enable(struct mtk_base_afe *afe, 153cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 154cf870273SRyder Lee int stream_dir, int rate) 15543a6a7e7SGarlic Tseng { 156cf870273SRyder Lee const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; 157bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 15843a6a7e7SGarlic Tseng int reg, fs, w_len = 1; /* now we support bck 64bits only */ 159e4b31b81SRyder Lee unsigned int mask, val; 16043a6a7e7SGarlic Tseng 16143a6a7e7SGarlic Tseng /* no need to enable if already done */ 162cf870273SRyder Lee if (++i2s_path->on[stream_dir] != 1) 16343a6a7e7SGarlic Tseng return 0; 16443a6a7e7SGarlic Tseng 165cf870273SRyder Lee fs = mt2701_afe_i2s_fs(rate); 16643a6a7e7SGarlic Tseng 16743a6a7e7SGarlic Tseng mask = ASYS_I2S_CON_FS | 16843a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */ 16943a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_MODE | 17043a6a7e7SGarlic Tseng ASYS_I2S_CON_WIDE_MODE; 17143a6a7e7SGarlic Tseng 17243a6a7e7SGarlic Tseng val = ASYS_I2S_CON_FS_SET(fs) | 17343a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_MODE | 17443a6a7e7SGarlic Tseng ASYS_I2S_CON_WIDE_MODE_SET(w_len); 17543a6a7e7SGarlic Tseng 17643a6a7e7SGarlic Tseng if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) { 17743a6a7e7SGarlic Tseng mask |= ASYS_I2S_IN_PHASE_FIX; 17843a6a7e7SGarlic Tseng val |= ASYS_I2S_IN_PHASE_FIX; 179cf870273SRyder Lee reg = ASMI_TIMING_CON1; 180cf870273SRyder Lee } else { 181bfdc56e5SRyder Lee if (afe_priv->soc->has_one_heart_mode) { 182bfdc56e5SRyder Lee mask |= ASYS_I2S_CON_ONE_HEART_MODE; 183bfdc56e5SRyder Lee val |= ASYS_I2S_CON_ONE_HEART_MODE; 184bfdc56e5SRyder Lee } 185cf870273SRyder Lee reg = ASMO_TIMING_CON1; 18643a6a7e7SGarlic Tseng } 18743a6a7e7SGarlic Tseng 18843a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val); 18943a6a7e7SGarlic Tseng 19043a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, reg, 19143a6a7e7SGarlic Tseng i2s_data->i2s_asrc_fs_mask 19243a6a7e7SGarlic Tseng << i2s_data->i2s_asrc_fs_shift, 19343a6a7e7SGarlic Tseng fs << i2s_data->i2s_asrc_fs_shift); 19443a6a7e7SGarlic Tseng 19543a6a7e7SGarlic Tseng /* enable i2s */ 196cf870273SRyder Lee mt2701_afe_enable_i2s(afe, i2s_path, stream_dir); 19743a6a7e7SGarlic Tseng 19843a6a7e7SGarlic Tseng /* reset i2s hw status before enable */ 19943a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 20043a6a7e7SGarlic Tseng ASYS_I2S_CON_RESET, ASYS_I2S_CON_RESET); 20143a6a7e7SGarlic Tseng udelay(1); 20243a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 20343a6a7e7SGarlic Tseng ASYS_I2S_CON_RESET, 0); 20443a6a7e7SGarlic Tseng udelay(1); 20543a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 20643a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_EN, ASYS_I2S_CON_I2S_EN); 20743a6a7e7SGarlic Tseng return 0; 20843a6a7e7SGarlic Tseng } 20943a6a7e7SGarlic Tseng 21043a6a7e7SGarlic Tseng static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream, 21143a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 21243a6a7e7SGarlic Tseng { 213e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 21443a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 215cf870273SRyder Lee int ret, i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 21643a6a7e7SGarlic Tseng struct mt2701_i2s_path *i2s_path; 217bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 21843a6a7e7SGarlic Tseng 21943a6a7e7SGarlic Tseng if (i2s_num < 0) 22043a6a7e7SGarlic Tseng return i2s_num; 22143a6a7e7SGarlic Tseng 22243a6a7e7SGarlic Tseng i2s_path = &afe_priv->i2s_path[i2s_num]; 22343a6a7e7SGarlic Tseng 22443a6a7e7SGarlic Tseng if (i2s_path->occupied[substream->stream]) 22543a6a7e7SGarlic Tseng return -EBUSY; 226cf870273SRyder Lee 227bfdc56e5SRyder Lee ret = mt2701_mclk_configuration(afe, mode ? 1 : i2s_num); 228cf870273SRyder Lee if (ret) 229cf870273SRyder Lee return ret; 230cf870273SRyder Lee 23143a6a7e7SGarlic Tseng i2s_path->occupied[substream->stream] = 1; 23243a6a7e7SGarlic Tseng 23343a6a7e7SGarlic Tseng /* need to enable i2s-out path when enable i2s-in */ 234cf870273SRyder Lee if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 235cf870273SRyder Lee mt2701_i2s_path_enable(afe, i2s_path, !substream->stream, 236cf870273SRyder Lee substream->runtime->rate); 237cf870273SRyder Lee 238cf870273SRyder Lee mt2701_i2s_path_enable(afe, i2s_path, substream->stream, 239cf870273SRyder Lee substream->runtime->rate); 24043a6a7e7SGarlic Tseng 24143a6a7e7SGarlic Tseng return 0; 24243a6a7e7SGarlic Tseng } 24343a6a7e7SGarlic Tseng 24443a6a7e7SGarlic Tseng static int mt2701_afe_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, 24543a6a7e7SGarlic Tseng unsigned int freq, int dir) 24643a6a7e7SGarlic Tseng { 247e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 24843a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 24943a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 250bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 25143a6a7e7SGarlic Tseng 25243a6a7e7SGarlic Tseng if (i2s_num < 0) 25343a6a7e7SGarlic Tseng return i2s_num; 25443a6a7e7SGarlic Tseng 25543a6a7e7SGarlic Tseng /* mclk */ 25643a6a7e7SGarlic Tseng if (dir == SND_SOC_CLOCK_IN) { 257bfdc56e5SRyder Lee dev_warn(dai->dev, "The SoCs doesn't support mclk input\n"); 25843a6a7e7SGarlic Tseng return -EINVAL; 25943a6a7e7SGarlic Tseng } 260e4b31b81SRyder Lee 261bfdc56e5SRyder Lee afe_priv->i2s_path[mode ? 1 : i2s_num].mclk_rate = freq; 262e4b31b81SRyder Lee 26343a6a7e7SGarlic Tseng return 0; 26443a6a7e7SGarlic Tseng } 26543a6a7e7SGarlic Tseng 2664bdc8d45SGarlic Tseng static int mt2701_btmrg_startup(struct snd_pcm_substream *substream, 2674bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 2684bdc8d45SGarlic Tseng { 269e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 2704bdc8d45SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 271d8d99d8eSRyder Lee int ret; 2724bdc8d45SGarlic Tseng 273d8d99d8eSRyder Lee ret = mt2701_enable_btmrg_clk(afe); 274d8d99d8eSRyder Lee if (ret) 275d8d99d8eSRyder Lee return ret; 2764bdc8d45SGarlic Tseng 2774bdc8d45SGarlic Tseng afe_priv->mrg_enable[substream->stream] = 1; 278e4b31b81SRyder Lee 2794bdc8d45SGarlic Tseng return 0; 2804bdc8d45SGarlic Tseng } 2814bdc8d45SGarlic Tseng 2824bdc8d45SGarlic Tseng static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream, 2834bdc8d45SGarlic Tseng struct snd_pcm_hw_params *params, 2844bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 2854bdc8d45SGarlic Tseng { 286e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 2874bdc8d45SGarlic Tseng int stream_fs; 2884bdc8d45SGarlic Tseng u32 val, msk; 2894bdc8d45SGarlic Tseng 2904bdc8d45SGarlic Tseng stream_fs = params_rate(params); 2914bdc8d45SGarlic Tseng 292e4b31b81SRyder Lee if (stream_fs != 8000 && stream_fs != 16000) { 293e4b31b81SRyder Lee dev_err(afe->dev, "unsupported rate %d\n", stream_fs); 2944bdc8d45SGarlic Tseng return -EINVAL; 2954bdc8d45SGarlic Tseng } 2964bdc8d45SGarlic Tseng 2974bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 2984bdc8d45SGarlic Tseng AFE_MRGIF_CON_I2S_MODE_MASK, 2994bdc8d45SGarlic Tseng AFE_MRGIF_CON_I2S_MODE_32K); 3004bdc8d45SGarlic Tseng 3014bdc8d45SGarlic Tseng val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY 3024bdc8d45SGarlic Tseng | AFE_DAIBT_CON0_MRG_USE; 3034bdc8d45SGarlic Tseng msk = val; 3044bdc8d45SGarlic Tseng 3054bdc8d45SGarlic Tseng if (stream_fs == 16000) 3064bdc8d45SGarlic Tseng val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; 3074bdc8d45SGarlic Tseng 3084bdc8d45SGarlic Tseng msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; 3094bdc8d45SGarlic Tseng 3104bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val); 3114bdc8d45SGarlic Tseng 3124bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, 3134bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN, 3144bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN); 3154bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3164bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN, 3174bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN); 3184bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3194bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN, 3204bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN); 3214bdc8d45SGarlic Tseng return 0; 3224bdc8d45SGarlic Tseng } 3234bdc8d45SGarlic Tseng 3244bdc8d45SGarlic Tseng static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream, 3254bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 3264bdc8d45SGarlic Tseng { 327e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 3284bdc8d45SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 3294bdc8d45SGarlic Tseng 3304bdc8d45SGarlic Tseng /* if the other direction stream is not occupied */ 3314bdc8d45SGarlic Tseng if (!afe_priv->mrg_enable[!substream->stream]) { 3324bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, 3334bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN, 0); 3344bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3354bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN, 0); 3364bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3374bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN, 0); 338d8d99d8eSRyder Lee mt2701_disable_btmrg_clk(afe); 3394bdc8d45SGarlic Tseng } 340e4b31b81SRyder Lee 3414bdc8d45SGarlic Tseng afe_priv->mrg_enable[substream->stream] = 0; 3424bdc8d45SGarlic Tseng } 3434bdc8d45SGarlic Tseng 34443a6a7e7SGarlic Tseng static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream, 34543a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 34643a6a7e7SGarlic Tseng { 347e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 34843a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp; 349e4b31b81SRyder Lee int stream_dir = substream->stream; 35043a6a7e7SGarlic Tseng 35143a6a7e7SGarlic Tseng /* can't run single DL & DLM at the same time */ 35243a6a7e7SGarlic Tseng if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) { 35343a6a7e7SGarlic Tseng memif_tmp = &afe->memif[MT2701_MEMIF_DLM]; 35443a6a7e7SGarlic Tseng if (memif_tmp->substream) { 355e4b31b81SRyder Lee dev_warn(afe->dev, "memif is not available"); 35643a6a7e7SGarlic Tseng return -EBUSY; 35743a6a7e7SGarlic Tseng } 35843a6a7e7SGarlic Tseng } 359e4b31b81SRyder Lee 36043a6a7e7SGarlic Tseng return mtk_afe_fe_startup(substream, dai); 36143a6a7e7SGarlic Tseng } 36243a6a7e7SGarlic Tseng 36343a6a7e7SGarlic Tseng static int mt2701_simple_fe_hw_params(struct snd_pcm_substream *substream, 36443a6a7e7SGarlic Tseng struct snd_pcm_hw_params *params, 36543a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 36643a6a7e7SGarlic Tseng { 367e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 36843a6a7e7SGarlic Tseng int stream_dir = substream->stream; 36943a6a7e7SGarlic Tseng 37043a6a7e7SGarlic Tseng /* single DL use PAIR_INTERLEAVE */ 371e4b31b81SRyder Lee if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) 37243a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 37343a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 37443a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_MASK, 37543a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_PAIR_INTERLEAVE); 376e4b31b81SRyder Lee 37743a6a7e7SGarlic Tseng return mtk_afe_fe_hw_params(substream, params, dai); 37843a6a7e7SGarlic Tseng } 37943a6a7e7SGarlic Tseng 38043a6a7e7SGarlic Tseng static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream, 38143a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 38243a6a7e7SGarlic Tseng { 383e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 38443a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp; 38543a6a7e7SGarlic Tseng const struct mtk_base_memif_data *memif_data; 38643a6a7e7SGarlic Tseng int i; 38743a6a7e7SGarlic Tseng 38843a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 38943a6a7e7SGarlic Tseng memif_tmp = &afe->memif[i]; 39043a6a7e7SGarlic Tseng if (memif_tmp->substream) 39143a6a7e7SGarlic Tseng return -EBUSY; 39243a6a7e7SGarlic Tseng } 39343a6a7e7SGarlic Tseng 39443a6a7e7SGarlic Tseng /* enable agent for all signal DL (due to hw design) */ 39543a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 39643a6a7e7SGarlic Tseng memif_data = afe->memif[i].data; 39743a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 39843a6a7e7SGarlic Tseng memif_data->agent_disable_reg, 39943a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift, 40043a6a7e7SGarlic Tseng 0 << memif_data->agent_disable_shift); 40143a6a7e7SGarlic Tseng } 40243a6a7e7SGarlic Tseng 40343a6a7e7SGarlic Tseng return mtk_afe_fe_startup(substream, dai); 40443a6a7e7SGarlic Tseng } 40543a6a7e7SGarlic Tseng 40643a6a7e7SGarlic Tseng static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream, 40743a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 40843a6a7e7SGarlic Tseng { 409e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 41043a6a7e7SGarlic Tseng const struct mtk_base_memif_data *memif_data; 41143a6a7e7SGarlic Tseng int i; 41243a6a7e7SGarlic Tseng 41343a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 41443a6a7e7SGarlic Tseng memif_data = afe->memif[i].data; 41543a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 41643a6a7e7SGarlic Tseng memif_data->agent_disable_reg, 41743a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift, 41843a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift); 41943a6a7e7SGarlic Tseng } 420e4b31b81SRyder Lee 42143a6a7e7SGarlic Tseng return mtk_afe_fe_shutdown(substream, dai); 42243a6a7e7SGarlic Tseng } 42343a6a7e7SGarlic Tseng 42443a6a7e7SGarlic Tseng static int mt2701_dlm_fe_hw_params(struct snd_pcm_substream *substream, 42543a6a7e7SGarlic Tseng struct snd_pcm_hw_params *params, 42643a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 42743a6a7e7SGarlic Tseng { 428e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 42943a6a7e7SGarlic Tseng int channels = params_channels(params); 43043a6a7e7SGarlic Tseng 43143a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 43243a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 43343a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_MASK, 43443a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_FULL_INTERLEAVE); 43543a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 43643a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 43743a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK, 43843a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_32BYTES); 43943a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 44043a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 44143a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_CH_MASK, 44243a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_CH(channels)); 44343a6a7e7SGarlic Tseng 44443a6a7e7SGarlic Tseng return mtk_afe_fe_hw_params(substream, params, dai); 44543a6a7e7SGarlic Tseng } 44643a6a7e7SGarlic Tseng 44743a6a7e7SGarlic Tseng static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream, 44843a6a7e7SGarlic Tseng int cmd, struct snd_soc_dai *dai) 44943a6a7e7SGarlic Tseng { 450e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 45143a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp = &afe->memif[MT2701_MEMIF_DL1]; 45243a6a7e7SGarlic Tseng 45343a6a7e7SGarlic Tseng switch (cmd) { 45443a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_START: 45543a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_RESUME: 45643a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, 45743a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift, 45843a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift); 45943a6a7e7SGarlic Tseng mtk_afe_fe_trigger(substream, cmd, dai); 46043a6a7e7SGarlic Tseng return 0; 46143a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_STOP: 46243a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_SUSPEND: 46343a6a7e7SGarlic Tseng mtk_afe_fe_trigger(substream, cmd, dai); 46443a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, 46543a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift, 0); 46643a6a7e7SGarlic Tseng 46743a6a7e7SGarlic Tseng return 0; 46843a6a7e7SGarlic Tseng default: 46943a6a7e7SGarlic Tseng return -EINVAL; 47043a6a7e7SGarlic Tseng } 47143a6a7e7SGarlic Tseng } 47243a6a7e7SGarlic Tseng 47343a6a7e7SGarlic Tseng static int mt2701_memif_fs(struct snd_pcm_substream *substream, 47443a6a7e7SGarlic Tseng unsigned int rate) 47543a6a7e7SGarlic Tseng { 47643a6a7e7SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 47743a6a7e7SGarlic Tseng int fs; 47843a6a7e7SGarlic Tseng 47943a6a7e7SGarlic Tseng if (rtd->cpu_dai->id != MT2701_MEMIF_ULBT) 48043a6a7e7SGarlic Tseng fs = mt2701_afe_i2s_fs(rate); 48143a6a7e7SGarlic Tseng else 48243a6a7e7SGarlic Tseng fs = (rate == 16000 ? 1 : 0); 483e4b31b81SRyder Lee 48443a6a7e7SGarlic Tseng return fs; 48543a6a7e7SGarlic Tseng } 48643a6a7e7SGarlic Tseng 48743a6a7e7SGarlic Tseng static int mt2701_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) 48843a6a7e7SGarlic Tseng { 48943a6a7e7SGarlic Tseng return mt2701_afe_i2s_fs(rate); 49043a6a7e7SGarlic Tseng } 49143a6a7e7SGarlic Tseng 49243a6a7e7SGarlic Tseng /* FE DAIs */ 49343a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = { 49443a6a7e7SGarlic Tseng .startup = mt2701_simple_fe_startup, 49543a6a7e7SGarlic Tseng .shutdown = mtk_afe_fe_shutdown, 49643a6a7e7SGarlic Tseng .hw_params = mt2701_simple_fe_hw_params, 49743a6a7e7SGarlic Tseng .hw_free = mtk_afe_fe_hw_free, 49843a6a7e7SGarlic Tseng .prepare = mtk_afe_fe_prepare, 49943a6a7e7SGarlic Tseng .trigger = mtk_afe_fe_trigger, 50043a6a7e7SGarlic Tseng }; 50143a6a7e7SGarlic Tseng 50243a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = { 50343a6a7e7SGarlic Tseng .startup = mt2701_dlm_fe_startup, 50443a6a7e7SGarlic Tseng .shutdown = mt2701_dlm_fe_shutdown, 50543a6a7e7SGarlic Tseng .hw_params = mt2701_dlm_fe_hw_params, 50643a6a7e7SGarlic Tseng .hw_free = mtk_afe_fe_hw_free, 50743a6a7e7SGarlic Tseng .prepare = mtk_afe_fe_prepare, 50843a6a7e7SGarlic Tseng .trigger = mt2701_dlm_fe_trigger, 50943a6a7e7SGarlic Tseng }; 51043a6a7e7SGarlic Tseng 51143a6a7e7SGarlic Tseng /* I2S BE DAIs */ 51243a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = { 51343a6a7e7SGarlic Tseng .startup = mt2701_afe_i2s_startup, 51443a6a7e7SGarlic Tseng .shutdown = mt2701_afe_i2s_shutdown, 51543a6a7e7SGarlic Tseng .prepare = mt2701_afe_i2s_prepare, 51643a6a7e7SGarlic Tseng .set_sysclk = mt2701_afe_i2s_set_sysclk, 51743a6a7e7SGarlic Tseng }; 51843a6a7e7SGarlic Tseng 5194bdc8d45SGarlic Tseng /* MRG BE DAIs */ 520549acff9SGustavo A. R. Silva static const struct snd_soc_dai_ops mt2701_btmrg_ops = { 5214bdc8d45SGarlic Tseng .startup = mt2701_btmrg_startup, 5224bdc8d45SGarlic Tseng .shutdown = mt2701_btmrg_shutdown, 5234bdc8d45SGarlic Tseng .hw_params = mt2701_btmrg_hw_params, 5244bdc8d45SGarlic Tseng }; 5254bdc8d45SGarlic Tseng 52643a6a7e7SGarlic Tseng static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { 52743a6a7e7SGarlic Tseng /* FE DAIs: memory intefaces to CPU */ 52843a6a7e7SGarlic Tseng { 5298625c1dbSRyder Lee .name = "PCMO0", 5308625c1dbSRyder Lee .id = MT2701_MEMIF_DL1, 5318625c1dbSRyder Lee .suspend = mtk_afe_dai_suspend, 5328625c1dbSRyder Lee .resume = mtk_afe_dai_resume, 5338625c1dbSRyder Lee .playback = { 5348625c1dbSRyder Lee .stream_name = "DL1", 5358625c1dbSRyder Lee .channels_min = 1, 5368625c1dbSRyder Lee .channels_max = 2, 5378625c1dbSRyder Lee .rates = SNDRV_PCM_RATE_8000_192000, 5388625c1dbSRyder Lee .formats = (SNDRV_PCM_FMTBIT_S16_LE 5398625c1dbSRyder Lee | SNDRV_PCM_FMTBIT_S24_LE 5408625c1dbSRyder Lee | SNDRV_PCM_FMTBIT_S32_LE) 5418625c1dbSRyder Lee }, 5428625c1dbSRyder Lee .ops = &mt2701_single_memif_dai_ops, 5438625c1dbSRyder Lee }, 5448625c1dbSRyder Lee { 54543a6a7e7SGarlic Tseng .name = "PCM_multi", 54643a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLM, 54743a6a7e7SGarlic Tseng .suspend = mtk_afe_dai_suspend, 54843a6a7e7SGarlic Tseng .resume = mtk_afe_dai_resume, 54943a6a7e7SGarlic Tseng .playback = { 55043a6a7e7SGarlic Tseng .stream_name = "DLM", 55143a6a7e7SGarlic Tseng .channels_min = 1, 55243a6a7e7SGarlic Tseng .channels_max = 8, 55343a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 55443a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 55543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 55643a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 55743a6a7e7SGarlic Tseng 55843a6a7e7SGarlic Tseng }, 55943a6a7e7SGarlic Tseng .ops = &mt2701_dlm_memif_dai_ops, 56043a6a7e7SGarlic Tseng }, 56143a6a7e7SGarlic Tseng { 56243a6a7e7SGarlic Tseng .name = "PCM0", 56343a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL1, 56443a6a7e7SGarlic Tseng .suspend = mtk_afe_dai_suspend, 56543a6a7e7SGarlic Tseng .resume = mtk_afe_dai_resume, 56643a6a7e7SGarlic Tseng .capture = { 56743a6a7e7SGarlic Tseng .stream_name = "UL1", 56843a6a7e7SGarlic Tseng .channels_min = 1, 56943a6a7e7SGarlic Tseng .channels_max = 2, 57043a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 57143a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 57243a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 57343a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 57443a6a7e7SGarlic Tseng }, 57543a6a7e7SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 57643a6a7e7SGarlic Tseng }, 57743a6a7e7SGarlic Tseng { 57843a6a7e7SGarlic Tseng .name = "PCM1", 57943a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL2, 58043a6a7e7SGarlic Tseng .suspend = mtk_afe_dai_suspend, 58143a6a7e7SGarlic Tseng .resume = mtk_afe_dai_resume, 58243a6a7e7SGarlic Tseng .capture = { 58343a6a7e7SGarlic Tseng .stream_name = "UL2", 58443a6a7e7SGarlic Tseng .channels_min = 1, 58543a6a7e7SGarlic Tseng .channels_max = 2, 58643a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 58743a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 58843a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 58943a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 59043a6a7e7SGarlic Tseng 59143a6a7e7SGarlic Tseng }, 59243a6a7e7SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 59343a6a7e7SGarlic Tseng }, 5944bdc8d45SGarlic Tseng { 5954bdc8d45SGarlic Tseng .name = "PCM_BT_DL", 5964bdc8d45SGarlic Tseng .id = MT2701_MEMIF_DLBT, 5974bdc8d45SGarlic Tseng .suspend = mtk_afe_dai_suspend, 5984bdc8d45SGarlic Tseng .resume = mtk_afe_dai_resume, 5994bdc8d45SGarlic Tseng .playback = { 6004bdc8d45SGarlic Tseng .stream_name = "DLBT", 6014bdc8d45SGarlic Tseng .channels_min = 1, 6024bdc8d45SGarlic Tseng .channels_max = 1, 6034bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 6044bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 6054bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 6064bdc8d45SGarlic Tseng }, 6074bdc8d45SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 6084bdc8d45SGarlic Tseng }, 6094bdc8d45SGarlic Tseng { 6104bdc8d45SGarlic Tseng .name = "PCM_BT_UL", 6114bdc8d45SGarlic Tseng .id = MT2701_MEMIF_ULBT, 6124bdc8d45SGarlic Tseng .suspend = mtk_afe_dai_suspend, 6134bdc8d45SGarlic Tseng .resume = mtk_afe_dai_resume, 6144bdc8d45SGarlic Tseng .capture = { 6154bdc8d45SGarlic Tseng .stream_name = "ULBT", 6164bdc8d45SGarlic Tseng .channels_min = 1, 6174bdc8d45SGarlic Tseng .channels_max = 1, 6184bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 6194bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 6204bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 6214bdc8d45SGarlic Tseng }, 6224bdc8d45SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 6234bdc8d45SGarlic Tseng }, 62443a6a7e7SGarlic Tseng /* BE DAIs */ 62543a6a7e7SGarlic Tseng { 62643a6a7e7SGarlic Tseng .name = "I2S0", 62743a6a7e7SGarlic Tseng .id = MT2701_IO_I2S, 62843a6a7e7SGarlic Tseng .playback = { 62943a6a7e7SGarlic Tseng .stream_name = "I2S0 Playback", 63043a6a7e7SGarlic Tseng .channels_min = 1, 63143a6a7e7SGarlic Tseng .channels_max = 2, 63243a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 63343a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 63443a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 63543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 63643a6a7e7SGarlic Tseng 63743a6a7e7SGarlic Tseng }, 63843a6a7e7SGarlic Tseng .capture = { 63943a6a7e7SGarlic Tseng .stream_name = "I2S0 Capture", 64043a6a7e7SGarlic Tseng .channels_min = 1, 64143a6a7e7SGarlic Tseng .channels_max = 2, 64243a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 64343a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 64443a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 64543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 64643a6a7e7SGarlic Tseng 64743a6a7e7SGarlic Tseng }, 64843a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 64943a6a7e7SGarlic Tseng .symmetric_rates = 1, 65043a6a7e7SGarlic Tseng }, 65143a6a7e7SGarlic Tseng { 65243a6a7e7SGarlic Tseng .name = "I2S1", 65343a6a7e7SGarlic Tseng .id = MT2701_IO_2ND_I2S, 65443a6a7e7SGarlic Tseng .playback = { 65543a6a7e7SGarlic Tseng .stream_name = "I2S1 Playback", 65643a6a7e7SGarlic Tseng .channels_min = 1, 65743a6a7e7SGarlic Tseng .channels_max = 2, 65843a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 65943a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 66043a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 66143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 66243a6a7e7SGarlic Tseng }, 66343a6a7e7SGarlic Tseng .capture = { 66443a6a7e7SGarlic Tseng .stream_name = "I2S1 Capture", 66543a6a7e7SGarlic Tseng .channels_min = 1, 66643a6a7e7SGarlic Tseng .channels_max = 2, 66743a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 66843a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 66943a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 67043a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 67143a6a7e7SGarlic Tseng }, 67243a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 67343a6a7e7SGarlic Tseng .symmetric_rates = 1, 67443a6a7e7SGarlic Tseng }, 67543a6a7e7SGarlic Tseng { 67643a6a7e7SGarlic Tseng .name = "I2S2", 67743a6a7e7SGarlic Tseng .id = MT2701_IO_3RD_I2S, 67843a6a7e7SGarlic Tseng .playback = { 67943a6a7e7SGarlic Tseng .stream_name = "I2S2 Playback", 68043a6a7e7SGarlic Tseng .channels_min = 1, 68143a6a7e7SGarlic Tseng .channels_max = 2, 68243a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 68343a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 68443a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 68543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 68643a6a7e7SGarlic Tseng }, 68743a6a7e7SGarlic Tseng .capture = { 68843a6a7e7SGarlic Tseng .stream_name = "I2S2 Capture", 68943a6a7e7SGarlic Tseng .channels_min = 1, 69043a6a7e7SGarlic Tseng .channels_max = 2, 69143a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 69243a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 69343a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 69443a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 69543a6a7e7SGarlic Tseng }, 69643a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 69743a6a7e7SGarlic Tseng .symmetric_rates = 1, 69843a6a7e7SGarlic Tseng }, 69943a6a7e7SGarlic Tseng { 70043a6a7e7SGarlic Tseng .name = "I2S3", 70143a6a7e7SGarlic Tseng .id = MT2701_IO_4TH_I2S, 70243a6a7e7SGarlic Tseng .playback = { 70343a6a7e7SGarlic Tseng .stream_name = "I2S3 Playback", 70443a6a7e7SGarlic Tseng .channels_min = 1, 70543a6a7e7SGarlic Tseng .channels_max = 2, 70643a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 70743a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 70843a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 70943a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 71043a6a7e7SGarlic Tseng }, 71143a6a7e7SGarlic Tseng .capture = { 71243a6a7e7SGarlic Tseng .stream_name = "I2S3 Capture", 71343a6a7e7SGarlic Tseng .channels_min = 1, 71443a6a7e7SGarlic Tseng .channels_max = 2, 71543a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 71643a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 71743a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 71843a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 71943a6a7e7SGarlic Tseng }, 72043a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 72143a6a7e7SGarlic Tseng .symmetric_rates = 1, 72243a6a7e7SGarlic Tseng }, 7234bdc8d45SGarlic Tseng { 7244bdc8d45SGarlic Tseng .name = "MRG BT", 7254bdc8d45SGarlic Tseng .id = MT2701_IO_MRG, 7264bdc8d45SGarlic Tseng .playback = { 7274bdc8d45SGarlic Tseng .stream_name = "BT Playback", 7284bdc8d45SGarlic Tseng .channels_min = 1, 7294bdc8d45SGarlic Tseng .channels_max = 1, 7304bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 7314bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 7324bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 7334bdc8d45SGarlic Tseng }, 7344bdc8d45SGarlic Tseng .capture = { 7354bdc8d45SGarlic Tseng .stream_name = "BT Capture", 7364bdc8d45SGarlic Tseng .channels_min = 1, 7374bdc8d45SGarlic Tseng .channels_max = 1, 7384bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 7394bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 7404bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 7414bdc8d45SGarlic Tseng }, 7424bdc8d45SGarlic Tseng .ops = &mt2701_btmrg_ops, 7434bdc8d45SGarlic Tseng .symmetric_rates = 1, 7444bdc8d45SGarlic Tseng } 74543a6a7e7SGarlic Tseng }; 74643a6a7e7SGarlic Tseng 74743a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = { 74843a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN0, 0, 1, 0), 74943a6a7e7SGarlic Tseng }; 75043a6a7e7SGarlic Tseng 75143a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o01_mix[] = { 75243a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN1, 1, 1, 0), 75343a6a7e7SGarlic Tseng }; 75443a6a7e7SGarlic Tseng 75543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o02_mix[] = { 75643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I02 Switch", AFE_CONN2, 2, 1, 0), 75743a6a7e7SGarlic Tseng }; 75843a6a7e7SGarlic Tseng 75943a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o03_mix[] = { 76043a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 3, 1, 0), 76143a6a7e7SGarlic Tseng }; 76243a6a7e7SGarlic Tseng 76343a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o14_mix[] = { 76443a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN14, 26, 1, 0), 76543a6a7e7SGarlic Tseng }; 76643a6a7e7SGarlic Tseng 76743a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o15_mix[] = { 76843a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I12 Switch", AFE_CONN15, 12, 1, 0), 76943a6a7e7SGarlic Tseng }; 77043a6a7e7SGarlic Tseng 77143a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o16_mix[] = { 77243a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I13 Switch", AFE_CONN16, 13, 1, 0), 77343a6a7e7SGarlic Tseng }; 77443a6a7e7SGarlic Tseng 77543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o17_mix[] = { 77643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0), 77743a6a7e7SGarlic Tseng }; 77843a6a7e7SGarlic Tseng 77943a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o18_mix[] = { 78043a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0), 78143a6a7e7SGarlic Tseng }; 78243a6a7e7SGarlic Tseng 78343a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o19_mix[] = { 78443a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0), 78543a6a7e7SGarlic Tseng }; 78643a6a7e7SGarlic Tseng 78743a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o20_mix[] = { 78843a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0), 78943a6a7e7SGarlic Tseng }; 79043a6a7e7SGarlic Tseng 79143a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o21_mix[] = { 79243a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0), 79343a6a7e7SGarlic Tseng }; 79443a6a7e7SGarlic Tseng 79543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o22_mix[] = { 79643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), 79743a6a7e7SGarlic Tseng }; 79843a6a7e7SGarlic Tseng 79943a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o23_mix[] = { 80043a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0), 80143a6a7e7SGarlic Tseng }; 80243a6a7e7SGarlic Tseng 80343a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o24_mix[] = { 80443a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0), 80543a6a7e7SGarlic Tseng }; 80643a6a7e7SGarlic Tseng 80743a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = { 80843a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0), 80943a6a7e7SGarlic Tseng }; 81043a6a7e7SGarlic Tseng 81143a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_i02_mix[] = { 81243a6a7e7SGarlic Tseng SOC_DAPM_SINGLE("I2S0 Switch", SND_SOC_NOPM, 0, 1, 0), 81343a6a7e7SGarlic Tseng }; 81443a6a7e7SGarlic Tseng 81543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s0[] = { 81643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S0 Out Switch", 81743a6a7e7SGarlic Tseng ASYS_I2SO1_CON, 26, 1, 0), 81843a6a7e7SGarlic Tseng }; 81943a6a7e7SGarlic Tseng 82043a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s1[] = { 82143a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S1 Out Switch", 82243a6a7e7SGarlic Tseng ASYS_I2SO2_CON, 26, 1, 0), 82343a6a7e7SGarlic Tseng }; 82443a6a7e7SGarlic Tseng 82543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s2[] = { 82643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S2 Out Switch", 82743a6a7e7SGarlic Tseng PWR2_TOP_CON, 17, 1, 0), 82843a6a7e7SGarlic Tseng }; 82943a6a7e7SGarlic Tseng 83043a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s3[] = { 83143a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S3 Out Switch", 83243a6a7e7SGarlic Tseng PWR2_TOP_CON, 18, 1, 0), 83343a6a7e7SGarlic Tseng }; 83443a6a7e7SGarlic Tseng 83543a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = { 83643a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S4 Out Switch", 83743a6a7e7SGarlic Tseng PWR2_TOP_CON, 19, 1, 0), 83843a6a7e7SGarlic Tseng }; 83943a6a7e7SGarlic Tseng 84043a6a7e7SGarlic Tseng static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { 84143a6a7e7SGarlic Tseng /* inter-connections */ 84243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), 84343a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0), 84443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I02", SND_SOC_NOPM, 0, 0, mt2701_afe_i02_mix, 84543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_i02_mix)), 84643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), 84743a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0), 84843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0), 84943a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0), 85043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0), 85143a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0), 85243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), 85343a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), 85443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0), 85543a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0), 85643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I35", SND_SOC_NOPM, 0, 0, NULL, 0), 85743a6a7e7SGarlic Tseng 85843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0, mt2701_afe_o00_mix, 85943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o00_mix)), 86043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0, mt2701_afe_o01_mix, 86143a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o01_mix)), 86243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O02", SND_SOC_NOPM, 0, 0, mt2701_afe_o02_mix, 86343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o02_mix)), 86443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, mt2701_afe_o03_mix, 86543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o03_mix)), 86643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0, mt2701_afe_o14_mix, 86743a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o14_mix)), 86843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0, mt2701_afe_o15_mix, 86943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o15_mix)), 87043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0, mt2701_afe_o16_mix, 87143a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o16_mix)), 87243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0, mt2701_afe_o17_mix, 87343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o17_mix)), 87443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0, mt2701_afe_o18_mix, 87543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o18_mix)), 87643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0, mt2701_afe_o19_mix, 87743a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o19_mix)), 87843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0, mt2701_afe_o20_mix, 87943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o20_mix)), 88043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0, mt2701_afe_o21_mix, 88143a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o21_mix)), 88243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0, mt2701_afe_o22_mix, 88343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o22_mix)), 88443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0, mt2701_afe_o31_mix, 88543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o31_mix)), 88643a6a7e7SGarlic Tseng 88743a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I12I13", SND_SOC_NOPM, 0, 0, 88843a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s0, 88943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s0)), 89043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I14I15", SND_SOC_NOPM, 0, 0, 89143a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s1, 89243a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s1)), 89343a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I16I17", SND_SOC_NOPM, 0, 0, 89443a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s2, 89543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s2)), 89643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0, 89743a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s3, 89843a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)), 89943a6a7e7SGarlic Tseng }; 90043a6a7e7SGarlic Tseng 90143a6a7e7SGarlic Tseng static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { 90243a6a7e7SGarlic Tseng {"I12", NULL, "DL1"}, 90343a6a7e7SGarlic Tseng {"I13", NULL, "DL1"}, 90443a6a7e7SGarlic Tseng {"I35", NULL, "DLBT"}, 90543a6a7e7SGarlic Tseng 90643a6a7e7SGarlic Tseng {"I2S0 Playback", NULL, "O15"}, 90743a6a7e7SGarlic Tseng {"I2S0 Playback", NULL, "O16"}, 90843a6a7e7SGarlic Tseng {"I2S1 Playback", NULL, "O17"}, 90943a6a7e7SGarlic Tseng {"I2S1 Playback", NULL, "O18"}, 91043a6a7e7SGarlic Tseng {"I2S2 Playback", NULL, "O19"}, 91143a6a7e7SGarlic Tseng {"I2S2 Playback", NULL, "O20"}, 91243a6a7e7SGarlic Tseng {"I2S3 Playback", NULL, "O21"}, 91343a6a7e7SGarlic Tseng {"I2S3 Playback", NULL, "O22"}, 91443a6a7e7SGarlic Tseng {"BT Playback", NULL, "O31"}, 91543a6a7e7SGarlic Tseng 91643a6a7e7SGarlic Tseng {"UL1", NULL, "O00"}, 91743a6a7e7SGarlic Tseng {"UL1", NULL, "O01"}, 91843a6a7e7SGarlic Tseng {"UL2", NULL, "O02"}, 91943a6a7e7SGarlic Tseng {"UL2", NULL, "O03"}, 92043a6a7e7SGarlic Tseng {"ULBT", NULL, "O14"}, 92143a6a7e7SGarlic Tseng 92243a6a7e7SGarlic Tseng {"I00", NULL, "I2S0 Capture"}, 92343a6a7e7SGarlic Tseng {"I01", NULL, "I2S0 Capture"}, 92443a6a7e7SGarlic Tseng {"I02", NULL, "I2S1 Capture"}, 92543a6a7e7SGarlic Tseng {"I03", NULL, "I2S1 Capture"}, 92643a6a7e7SGarlic Tseng /* I02,03 link to UL2, also need to open I2S0 */ 92743a6a7e7SGarlic Tseng {"I02", "I2S0 Switch", "I2S0 Capture"}, 92843a6a7e7SGarlic Tseng 92943a6a7e7SGarlic Tseng {"I26", NULL, "BT Capture"}, 93043a6a7e7SGarlic Tseng 931600b2fd4SRyder Lee {"I12I13", "Multich I2S0 Out Switch", "DLM"}, 932600b2fd4SRyder Lee {"I14I15", "Multich I2S1 Out Switch", "DLM"}, 933600b2fd4SRyder Lee {"I16I17", "Multich I2S2 Out Switch", "DLM"}, 934600b2fd4SRyder Lee {"I18I19", "Multich I2S3 Out Switch", "DLM"}, 93543a6a7e7SGarlic Tseng 93643a6a7e7SGarlic Tseng { "I12", NULL, "I12I13" }, 93743a6a7e7SGarlic Tseng { "I13", NULL, "I12I13" }, 93843a6a7e7SGarlic Tseng { "I14", NULL, "I14I15" }, 93943a6a7e7SGarlic Tseng { "I15", NULL, "I14I15" }, 94043a6a7e7SGarlic Tseng { "I16", NULL, "I16I17" }, 94143a6a7e7SGarlic Tseng { "I17", NULL, "I16I17" }, 94243a6a7e7SGarlic Tseng { "I18", NULL, "I18I19" }, 94343a6a7e7SGarlic Tseng { "I19", NULL, "I18I19" }, 94443a6a7e7SGarlic Tseng 94543a6a7e7SGarlic Tseng { "O00", "I00 Switch", "I00" }, 94643a6a7e7SGarlic Tseng { "O01", "I01 Switch", "I01" }, 94743a6a7e7SGarlic Tseng { "O02", "I02 Switch", "I02" }, 94843a6a7e7SGarlic Tseng { "O03", "I03 Switch", "I03" }, 94943a6a7e7SGarlic Tseng { "O14", "I26 Switch", "I26" }, 95043a6a7e7SGarlic Tseng { "O15", "I12 Switch", "I12" }, 95143a6a7e7SGarlic Tseng { "O16", "I13 Switch", "I13" }, 95243a6a7e7SGarlic Tseng { "O17", "I14 Switch", "I14" }, 95343a6a7e7SGarlic Tseng { "O18", "I15 Switch", "I15" }, 95443a6a7e7SGarlic Tseng { "O19", "I16 Switch", "I16" }, 95543a6a7e7SGarlic Tseng { "O20", "I17 Switch", "I17" }, 95643a6a7e7SGarlic Tseng { "O21", "I18 Switch", "I18" }, 95743a6a7e7SGarlic Tseng { "O22", "I19 Switch", "I19" }, 95843a6a7e7SGarlic Tseng { "O31", "I35 Switch", "I35" }, 95943a6a7e7SGarlic Tseng }; 96043a6a7e7SGarlic Tseng 961*10abdc7cSRyder Lee static int mt2701_afe_pcm_probe(struct snd_soc_component *component) 962*10abdc7cSRyder Lee { 963*10abdc7cSRyder Lee struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 964*10abdc7cSRyder Lee 965*10abdc7cSRyder Lee snd_soc_component_init_regmap(component, afe->regmap); 966*10abdc7cSRyder Lee 967*10abdc7cSRyder Lee return 0; 968*10abdc7cSRyder Lee } 969*10abdc7cSRyder Lee 97043a6a7e7SGarlic Tseng static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = { 971*10abdc7cSRyder Lee .probe = mt2701_afe_pcm_probe, 97243a6a7e7SGarlic Tseng .name = "mt2701-afe-pcm-dai", 97343a6a7e7SGarlic Tseng .dapm_widgets = mt2701_afe_pcm_widgets, 97443a6a7e7SGarlic Tseng .num_dapm_widgets = ARRAY_SIZE(mt2701_afe_pcm_widgets), 97543a6a7e7SGarlic Tseng .dapm_routes = mt2701_afe_pcm_routes, 97643a6a7e7SGarlic Tseng .num_dapm_routes = ARRAY_SIZE(mt2701_afe_pcm_routes), 97743a6a7e7SGarlic Tseng }; 97843a6a7e7SGarlic Tseng 97943a6a7e7SGarlic Tseng static const struct mtk_base_memif_data memif_data[MT2701_MEMIF_NUM] = { 98043a6a7e7SGarlic Tseng { 98143a6a7e7SGarlic Tseng .name = "DL1", 98243a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL1, 98343a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL1_BASE, 98443a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL1_CUR, 98543a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 98643a6a7e7SGarlic Tseng .fs_shift = 0, 98743a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 98843a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 98943a6a7e7SGarlic Tseng .mono_shift = 16, 99043a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 99143a6a7e7SGarlic Tseng .enable_shift = 1, 99243a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 99343a6a7e7SGarlic Tseng .hd_shift = 0, 99443a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 99543a6a7e7SGarlic Tseng .agent_disable_shift = 6, 99643a6a7e7SGarlic Tseng .msb_reg = -1, 99743a6a7e7SGarlic Tseng .msb_shift = -1, 99843a6a7e7SGarlic Tseng }, 99943a6a7e7SGarlic Tseng { 100043a6a7e7SGarlic Tseng .name = "DL2", 100143a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL2, 100243a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL2_BASE, 100343a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL2_CUR, 100443a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 100543a6a7e7SGarlic Tseng .fs_shift = 5, 100643a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 100743a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 100843a6a7e7SGarlic Tseng .mono_shift = 17, 100943a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 101043a6a7e7SGarlic Tseng .enable_shift = 2, 101143a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 101243a6a7e7SGarlic Tseng .hd_shift = 2, 101343a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 101443a6a7e7SGarlic Tseng .agent_disable_shift = 7, 101543a6a7e7SGarlic Tseng .msb_reg = -1, 101643a6a7e7SGarlic Tseng .msb_shift = -1, 101743a6a7e7SGarlic Tseng }, 101843a6a7e7SGarlic Tseng { 101943a6a7e7SGarlic Tseng .name = "DL3", 102043a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL3, 102143a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL3_BASE, 102243a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL3_CUR, 102343a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 102443a6a7e7SGarlic Tseng .fs_shift = 10, 102543a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 102643a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 102743a6a7e7SGarlic Tseng .mono_shift = 18, 102843a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 102943a6a7e7SGarlic Tseng .enable_shift = 3, 103043a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 103143a6a7e7SGarlic Tseng .hd_shift = 4, 103243a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 103343a6a7e7SGarlic Tseng .agent_disable_shift = 8, 103443a6a7e7SGarlic Tseng .msb_reg = -1, 103543a6a7e7SGarlic Tseng .msb_shift = -1, 103643a6a7e7SGarlic Tseng }, 103743a6a7e7SGarlic Tseng { 103843a6a7e7SGarlic Tseng .name = "DL4", 103943a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL4, 104043a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL4_BASE, 104143a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL4_CUR, 104243a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 104343a6a7e7SGarlic Tseng .fs_shift = 15, 104443a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 104543a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 104643a6a7e7SGarlic Tseng .mono_shift = 19, 104743a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 104843a6a7e7SGarlic Tseng .enable_shift = 4, 104943a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 105043a6a7e7SGarlic Tseng .hd_shift = 6, 105143a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 105243a6a7e7SGarlic Tseng .agent_disable_shift = 9, 105343a6a7e7SGarlic Tseng .msb_reg = -1, 105443a6a7e7SGarlic Tseng .msb_shift = -1, 105543a6a7e7SGarlic Tseng }, 105643a6a7e7SGarlic Tseng { 105743a6a7e7SGarlic Tseng .name = "DL5", 105843a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL5, 105943a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL5_BASE, 106043a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL5_CUR, 106143a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 106243a6a7e7SGarlic Tseng .fs_shift = 20, 106343a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 106443a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 106543a6a7e7SGarlic Tseng .mono_shift = 20, 106643a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 106743a6a7e7SGarlic Tseng .enable_shift = 5, 106843a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 106943a6a7e7SGarlic Tseng .hd_shift = 8, 107043a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 107143a6a7e7SGarlic Tseng .agent_disable_shift = 10, 107243a6a7e7SGarlic Tseng .msb_reg = -1, 107343a6a7e7SGarlic Tseng .msb_shift = -1, 107443a6a7e7SGarlic Tseng }, 107543a6a7e7SGarlic Tseng { 107643a6a7e7SGarlic Tseng .name = "DLM", 107743a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLM, 107843a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DLMCH_BASE, 107943a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DLMCH_CUR, 108043a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 108143a6a7e7SGarlic Tseng .fs_shift = 0, 108243a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 108343a6a7e7SGarlic Tseng .mono_reg = -1, 108443a6a7e7SGarlic Tseng .mono_shift = -1, 108543a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 108643a6a7e7SGarlic Tseng .enable_shift = 7, 108743a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_PBUF_SIZE, 108843a6a7e7SGarlic Tseng .hd_shift = 28, 108943a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 109043a6a7e7SGarlic Tseng .agent_disable_shift = 12, 109143a6a7e7SGarlic Tseng .msb_reg = -1, 109243a6a7e7SGarlic Tseng .msb_shift = -1, 109343a6a7e7SGarlic Tseng }, 109443a6a7e7SGarlic Tseng { 109543a6a7e7SGarlic Tseng .name = "UL1", 109643a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL1, 109743a6a7e7SGarlic Tseng .reg_ofs_base = AFE_VUL_BASE, 109843a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_VUL_CUR, 109943a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 110043a6a7e7SGarlic Tseng .fs_shift = 0, 110143a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 110243a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 110343a6a7e7SGarlic Tseng .mono_shift = 0, 110443a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 110543a6a7e7SGarlic Tseng .enable_shift = 10, 110643a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 110743a6a7e7SGarlic Tseng .hd_shift = 0, 110843a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 110943a6a7e7SGarlic Tseng .agent_disable_shift = 0, 111043a6a7e7SGarlic Tseng .msb_reg = -1, 111143a6a7e7SGarlic Tseng .msb_shift = -1, 111243a6a7e7SGarlic Tseng }, 111343a6a7e7SGarlic Tseng { 111443a6a7e7SGarlic Tseng .name = "UL2", 111543a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL2, 111643a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL2_BASE, 111743a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL2_CUR, 111843a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 111943a6a7e7SGarlic Tseng .fs_shift = 5, 112043a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 112143a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 112243a6a7e7SGarlic Tseng .mono_shift = 2, 112343a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 112443a6a7e7SGarlic Tseng .enable_shift = 11, 112543a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 112643a6a7e7SGarlic Tseng .hd_shift = 2, 112743a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 112843a6a7e7SGarlic Tseng .agent_disable_shift = 1, 112943a6a7e7SGarlic Tseng .msb_reg = -1, 113043a6a7e7SGarlic Tseng .msb_shift = -1, 113143a6a7e7SGarlic Tseng }, 113243a6a7e7SGarlic Tseng { 113343a6a7e7SGarlic Tseng .name = "UL3", 113443a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL3, 113543a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL3_BASE, 113643a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL3_CUR, 113743a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 113843a6a7e7SGarlic Tseng .fs_shift = 10, 113943a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 114043a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 114143a6a7e7SGarlic Tseng .mono_shift = 4, 114243a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 114343a6a7e7SGarlic Tseng .enable_shift = 12, 114443a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 114543a6a7e7SGarlic Tseng .hd_shift = 0, 114643a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 114743a6a7e7SGarlic Tseng .agent_disable_shift = 2, 114843a6a7e7SGarlic Tseng .msb_reg = -1, 114943a6a7e7SGarlic Tseng .msb_shift = -1, 115043a6a7e7SGarlic Tseng }, 115143a6a7e7SGarlic Tseng { 115243a6a7e7SGarlic Tseng .name = "UL4", 115343a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL4, 115443a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL4_BASE, 115543a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL4_CUR, 115643a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 115743a6a7e7SGarlic Tseng .fs_shift = 15, 115843a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 115943a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 116043a6a7e7SGarlic Tseng .mono_shift = 6, 116143a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 116243a6a7e7SGarlic Tseng .enable_shift = 13, 116343a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 116443a6a7e7SGarlic Tseng .hd_shift = 6, 116543a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 116643a6a7e7SGarlic Tseng .agent_disable_shift = 3, 116743a6a7e7SGarlic Tseng .msb_reg = -1, 116843a6a7e7SGarlic Tseng .msb_shift = -1, 116943a6a7e7SGarlic Tseng }, 117043a6a7e7SGarlic Tseng { 117143a6a7e7SGarlic Tseng .name = "UL5", 117243a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL5, 117343a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL5_BASE, 117443a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL5_CUR, 117543a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 117643a6a7e7SGarlic Tseng .fs_shift = 20, 117743a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 117843a6a7e7SGarlic Tseng .mono_shift = 8, 117943a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 118043a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 118143a6a7e7SGarlic Tseng .enable_shift = 14, 118243a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 118343a6a7e7SGarlic Tseng .hd_shift = 8, 118443a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 118543a6a7e7SGarlic Tseng .agent_disable_shift = 4, 118643a6a7e7SGarlic Tseng .msb_reg = -1, 118743a6a7e7SGarlic Tseng .msb_shift = -1, 118843a6a7e7SGarlic Tseng }, 118943a6a7e7SGarlic Tseng { 119043a6a7e7SGarlic Tseng .name = "DLBT", 119143a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLBT, 119243a6a7e7SGarlic Tseng .reg_ofs_base = AFE_ARB1_BASE, 119343a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_ARB1_CUR, 119443a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON3, 119543a6a7e7SGarlic Tseng .fs_shift = 10, 119643a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 119743a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 119843a6a7e7SGarlic Tseng .mono_shift = 22, 119943a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 120043a6a7e7SGarlic Tseng .enable_shift = 8, 120143a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 120243a6a7e7SGarlic Tseng .hd_shift = 14, 120343a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 120443a6a7e7SGarlic Tseng .agent_disable_shift = 13, 120543a6a7e7SGarlic Tseng .msb_reg = -1, 120643a6a7e7SGarlic Tseng .msb_shift = -1, 120743a6a7e7SGarlic Tseng }, 120843a6a7e7SGarlic Tseng { 120943a6a7e7SGarlic Tseng .name = "ULBT", 121043a6a7e7SGarlic Tseng .id = MT2701_MEMIF_ULBT, 121143a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DAI_BASE, 121243a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DAI_CUR, 121343a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 121443a6a7e7SGarlic Tseng .fs_shift = 30, 121543a6a7e7SGarlic Tseng .fs_maskbit = 0x1, 121643a6a7e7SGarlic Tseng .mono_reg = -1, 121743a6a7e7SGarlic Tseng .mono_shift = -1, 121843a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 121943a6a7e7SGarlic Tseng .enable_shift = 17, 122043a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 122143a6a7e7SGarlic Tseng .hd_shift = 20, 122243a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 122343a6a7e7SGarlic Tseng .agent_disable_shift = 16, 122443a6a7e7SGarlic Tseng .msb_reg = -1, 122543a6a7e7SGarlic Tseng .msb_shift = -1, 122643a6a7e7SGarlic Tseng }, 122743a6a7e7SGarlic Tseng }; 122843a6a7e7SGarlic Tseng 122943a6a7e7SGarlic Tseng static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = { 123043a6a7e7SGarlic Tseng { 123143a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ1, 123243a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ1_CON, 123343a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 123443a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 123543a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ1_CON, 123643a6a7e7SGarlic Tseng .irq_fs_shift = 24, 123743a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 123843a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ1_CON, 123943a6a7e7SGarlic Tseng .irq_en_shift = 31, 124043a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 124143a6a7e7SGarlic Tseng .irq_clr_shift = 0, 124243a6a7e7SGarlic Tseng }, 124343a6a7e7SGarlic Tseng { 124443a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ2, 124543a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ2_CON, 124643a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 124743a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 124843a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ2_CON, 124943a6a7e7SGarlic Tseng .irq_fs_shift = 24, 125043a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 125143a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ2_CON, 125243a6a7e7SGarlic Tseng .irq_en_shift = 31, 125343a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 125443a6a7e7SGarlic Tseng .irq_clr_shift = 1, 125543a6a7e7SGarlic Tseng }, 125643a6a7e7SGarlic Tseng { 125743a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ3, 125843a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ3_CON, 125943a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 126043a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 126143a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ3_CON, 126243a6a7e7SGarlic Tseng .irq_fs_shift = 24, 126343a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 126443a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ3_CON, 126543a6a7e7SGarlic Tseng .irq_en_shift = 31, 126643a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 126743a6a7e7SGarlic Tseng .irq_clr_shift = 2, 126843a6a7e7SGarlic Tseng } 126943a6a7e7SGarlic Tseng }; 127043a6a7e7SGarlic Tseng 1271ab7b4ee9SRyder Lee static const struct mt2701_i2s_data mt2701_i2s_data[][2] = { 127243a6a7e7SGarlic Tseng { 1273ab7b4ee9SRyder Lee { ASYS_I2SO1_CON, 0, 0x1f }, 1274ab7b4ee9SRyder Lee { ASYS_I2SIN1_CON, 0, 0x1f }, 127543a6a7e7SGarlic Tseng }, 127643a6a7e7SGarlic Tseng { 1277ab7b4ee9SRyder Lee { ASYS_I2SO2_CON, 5, 0x1f }, 1278ab7b4ee9SRyder Lee { ASYS_I2SIN2_CON, 5, 0x1f }, 127943a6a7e7SGarlic Tseng }, 128043a6a7e7SGarlic Tseng { 1281ab7b4ee9SRyder Lee { ASYS_I2SO3_CON, 10, 0x1f }, 1282ab7b4ee9SRyder Lee { ASYS_I2SIN3_CON, 10, 0x1f }, 128343a6a7e7SGarlic Tseng }, 128443a6a7e7SGarlic Tseng { 1285ab7b4ee9SRyder Lee { ASYS_I2SO4_CON, 15, 0x1f }, 1286ab7b4ee9SRyder Lee { ASYS_I2SIN4_CON, 15, 0x1f }, 128743a6a7e7SGarlic Tseng }, 1288ab7b4ee9SRyder Lee /* TODO - extend control registers supported by newer SoCs */ 128943a6a7e7SGarlic Tseng }; 129043a6a7e7SGarlic Tseng 129143a6a7e7SGarlic Tseng static irqreturn_t mt2701_asys_isr(int irq_id, void *dev) 129243a6a7e7SGarlic Tseng { 129343a6a7e7SGarlic Tseng int id; 129443a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev; 129543a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif; 129643a6a7e7SGarlic Tseng struct mtk_base_afe_irq *irq; 129743a6a7e7SGarlic Tseng u32 status; 129843a6a7e7SGarlic Tseng 129943a6a7e7SGarlic Tseng regmap_read(afe->regmap, ASYS_IRQ_STATUS, &status); 130043a6a7e7SGarlic Tseng regmap_write(afe->regmap, ASYS_IRQ_CLR, status); 130143a6a7e7SGarlic Tseng 130243a6a7e7SGarlic Tseng for (id = 0; id < MT2701_MEMIF_NUM; ++id) { 130343a6a7e7SGarlic Tseng memif = &afe->memif[id]; 130443a6a7e7SGarlic Tseng if (memif->irq_usage < 0) 130543a6a7e7SGarlic Tseng continue; 1306e4b31b81SRyder Lee 130743a6a7e7SGarlic Tseng irq = &afe->irqs[memif->irq_usage]; 1308e4b31b81SRyder Lee if (status & 1 << irq->irq_data->irq_clr_shift) 130943a6a7e7SGarlic Tseng snd_pcm_period_elapsed(memif->substream); 131043a6a7e7SGarlic Tseng } 1311e4b31b81SRyder Lee 131243a6a7e7SGarlic Tseng return IRQ_HANDLED; 131343a6a7e7SGarlic Tseng } 131443a6a7e7SGarlic Tseng 131543a6a7e7SGarlic Tseng static int mt2701_afe_runtime_suspend(struct device *dev) 131643a6a7e7SGarlic Tseng { 131743a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev_get_drvdata(dev); 131843a6a7e7SGarlic Tseng 1319d8d99d8eSRyder Lee return mt2701_afe_disable_clock(afe); 132043a6a7e7SGarlic Tseng } 132143a6a7e7SGarlic Tseng 132243a6a7e7SGarlic Tseng static int mt2701_afe_runtime_resume(struct device *dev) 132343a6a7e7SGarlic Tseng { 132443a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev_get_drvdata(dev); 132543a6a7e7SGarlic Tseng 132643a6a7e7SGarlic Tseng return mt2701_afe_enable_clock(afe); 132743a6a7e7SGarlic Tseng } 132843a6a7e7SGarlic Tseng 1329dc2a17f4SRyder Lee static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) 1330dc2a17f4SRyder Lee { 133143a6a7e7SGarlic Tseng struct mtk_base_afe *afe; 133243a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv; 133343a6a7e7SGarlic Tseng struct device *dev; 1334f6c1626eSRyder Lee int i, irq_id, ret; 133543a6a7e7SGarlic Tseng 133643a6a7e7SGarlic Tseng afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); 133743a6a7e7SGarlic Tseng if (!afe) 133843a6a7e7SGarlic Tseng return -ENOMEM; 1339600b2fd4SRyder Lee 1340b02c5cc7SDan Carpenter afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), 1341b02c5cc7SDan Carpenter GFP_KERNEL); 1342b02c5cc7SDan Carpenter if (!afe->platform_priv) 1343b02c5cc7SDan Carpenter return -ENOMEM; 134443a6a7e7SGarlic Tseng 1345600b2fd4SRyder Lee afe_priv = afe->platform_priv; 1346bfdc56e5SRyder Lee afe_priv->soc = of_device_get_match_data(&pdev->dev); 134743a6a7e7SGarlic Tseng afe->dev = &pdev->dev; 134843a6a7e7SGarlic Tseng dev = afe->dev; 134943a6a7e7SGarlic Tseng 1350bfdc56e5SRyder Lee afe_priv->i2s_path = devm_kzalloc(dev, afe_priv->soc->i2s_num * 1351bfdc56e5SRyder Lee sizeof(struct mt2701_i2s_path), 1352bfdc56e5SRyder Lee GFP_KERNEL); 1353bfdc56e5SRyder Lee if (!afe_priv->i2s_path) 1354bfdc56e5SRyder Lee return -ENOMEM; 1355bfdc56e5SRyder Lee 1356f6c1626eSRyder Lee irq_id = platform_get_irq_byname(pdev, "asys"); 1357f6c1626eSRyder Lee if (irq_id < 0) { 1358f6c1626eSRyder Lee dev_err(dev, "unable to get ASYS IRQ\n"); 1359f6c1626eSRyder Lee return irq_id; 136043a6a7e7SGarlic Tseng } 1361f6c1626eSRyder Lee 136243a6a7e7SGarlic Tseng ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, 136343a6a7e7SGarlic Tseng IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); 136443a6a7e7SGarlic Tseng if (ret) { 136543a6a7e7SGarlic Tseng dev_err(dev, "could not request_irq for asys-isr\n"); 136643a6a7e7SGarlic Tseng return ret; 136743a6a7e7SGarlic Tseng } 136843a6a7e7SGarlic Tseng 1369dfa3cbb8SRyder Lee afe->regmap = syscon_node_to_regmap(dev->parent->of_node); 13703e8052d9SWei Yongjun if (IS_ERR(afe->regmap)) { 1371dfa3cbb8SRyder Lee dev_err(dev, "could not get regmap from parent\n"); 13723e8052d9SWei Yongjun return PTR_ERR(afe->regmap); 1373dfa3cbb8SRyder Lee } 137443a6a7e7SGarlic Tseng 137543a6a7e7SGarlic Tseng mutex_init(&afe->irq_alloc_lock); 137643a6a7e7SGarlic Tseng 137743a6a7e7SGarlic Tseng /* memif initialize */ 137843a6a7e7SGarlic Tseng afe->memif_size = MT2701_MEMIF_NUM; 137943a6a7e7SGarlic Tseng afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), 138043a6a7e7SGarlic Tseng GFP_KERNEL); 138143a6a7e7SGarlic Tseng if (!afe->memif) 138243a6a7e7SGarlic Tseng return -ENOMEM; 138343a6a7e7SGarlic Tseng 138443a6a7e7SGarlic Tseng for (i = 0; i < afe->memif_size; i++) { 138543a6a7e7SGarlic Tseng afe->memif[i].data = &memif_data[i]; 138643a6a7e7SGarlic Tseng afe->memif[i].irq_usage = -1; 138743a6a7e7SGarlic Tseng } 138843a6a7e7SGarlic Tseng 138943a6a7e7SGarlic Tseng /* irq initialize */ 139043a6a7e7SGarlic Tseng afe->irqs_size = MT2701_IRQ_ASYS_END; 139143a6a7e7SGarlic Tseng afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), 139243a6a7e7SGarlic Tseng GFP_KERNEL); 139343a6a7e7SGarlic Tseng if (!afe->irqs) 139443a6a7e7SGarlic Tseng return -ENOMEM; 139543a6a7e7SGarlic Tseng 139643a6a7e7SGarlic Tseng for (i = 0; i < afe->irqs_size; i++) 139743a6a7e7SGarlic Tseng afe->irqs[i].irq_data = &irq_data[i]; 139843a6a7e7SGarlic Tseng 139943a6a7e7SGarlic Tseng /* I2S initialize */ 1400bfdc56e5SRyder Lee for (i = 0; i < afe_priv->soc->i2s_num; i++) { 1401ab7b4ee9SRyder Lee afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_PLAYBACK] = 1402ab7b4ee9SRyder Lee &mt2701_i2s_data[i][SNDRV_PCM_STREAM_PLAYBACK]; 1403ab7b4ee9SRyder Lee afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_CAPTURE] = 1404ab7b4ee9SRyder Lee &mt2701_i2s_data[i][SNDRV_PCM_STREAM_CAPTURE]; 140543a6a7e7SGarlic Tseng } 140643a6a7e7SGarlic Tseng 140743a6a7e7SGarlic Tseng afe->mtk_afe_hardware = &mt2701_afe_hardware; 140843a6a7e7SGarlic Tseng afe->memif_fs = mt2701_memif_fs; 140943a6a7e7SGarlic Tseng afe->irq_fs = mt2701_irq_fs; 141043a6a7e7SGarlic Tseng afe->reg_back_up_list = mt2701_afe_backup_list; 141143a6a7e7SGarlic Tseng afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list); 141243a6a7e7SGarlic Tseng afe->runtime_resume = mt2701_afe_runtime_resume; 141343a6a7e7SGarlic Tseng afe->runtime_suspend = mt2701_afe_runtime_suspend; 141443a6a7e7SGarlic Tseng 141543a6a7e7SGarlic Tseng /* initial audio related clock */ 141643a6a7e7SGarlic Tseng ret = mt2701_init_clock(afe); 141743a6a7e7SGarlic Tseng if (ret) { 141843a6a7e7SGarlic Tseng dev_err(dev, "init clock error\n"); 1419dc2a17f4SRyder Lee return ret; 142043a6a7e7SGarlic Tseng } 142143a6a7e7SGarlic Tseng 142243a6a7e7SGarlic Tseng platform_set_drvdata(pdev, afe); 142343a6a7e7SGarlic Tseng 1424dd6bb9b1SRyder Lee pm_runtime_enable(dev); 1425dd6bb9b1SRyder Lee if (!pm_runtime_enabled(dev)) { 1426dd6bb9b1SRyder Lee ret = mt2701_afe_runtime_resume(dev); 1427dd6bb9b1SRyder Lee if (ret) 1428dd6bb9b1SRyder Lee goto err_pm_disable; 1429dd6bb9b1SRyder Lee } 1430dd6bb9b1SRyder Lee pm_runtime_get_sync(dev); 1431dd6bb9b1SRyder Lee 1432f1b5bf07SKuninori Morimoto ret = devm_snd_soc_register_component(&pdev->dev, &mtk_afe_pcm_platform, 1433f1b5bf07SKuninori Morimoto NULL, 0); 143443a6a7e7SGarlic Tseng if (ret) { 143543a6a7e7SGarlic Tseng dev_warn(dev, "err_platform\n"); 143643a6a7e7SGarlic Tseng goto err_platform; 143743a6a7e7SGarlic Tseng } 143843a6a7e7SGarlic Tseng 1439*10abdc7cSRyder Lee ret = devm_snd_soc_register_component(&pdev->dev, 1440*10abdc7cSRyder Lee &mt2701_afe_pcm_dai_component, 1441*10abdc7cSRyder Lee mt2701_afe_pcm_dais, 1442*10abdc7cSRyder Lee ARRAY_SIZE(mt2701_afe_pcm_dais)); 144343a6a7e7SGarlic Tseng if (ret) { 144443a6a7e7SGarlic Tseng dev_warn(dev, "err_dai_component\n"); 1445f1b5bf07SKuninori Morimoto goto err_platform; 144643a6a7e7SGarlic Tseng } 144743a6a7e7SGarlic Tseng 144843a6a7e7SGarlic Tseng return 0; 144943a6a7e7SGarlic Tseng 145043a6a7e7SGarlic Tseng err_platform: 1451dd6bb9b1SRyder Lee pm_runtime_put_sync(dev); 145243a6a7e7SGarlic Tseng err_pm_disable: 1453dd6bb9b1SRyder Lee pm_runtime_disable(dev); 145443a6a7e7SGarlic Tseng 145543a6a7e7SGarlic Tseng return ret; 145643a6a7e7SGarlic Tseng } 145743a6a7e7SGarlic Tseng 145843a6a7e7SGarlic Tseng static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) 145943a6a7e7SGarlic Tseng { 1460dd6bb9b1SRyder Lee pm_runtime_put_sync(&pdev->dev); 146143a6a7e7SGarlic Tseng pm_runtime_disable(&pdev->dev); 146243a6a7e7SGarlic Tseng if (!pm_runtime_status_suspended(&pdev->dev)) 146343a6a7e7SGarlic Tseng mt2701_afe_runtime_suspend(&pdev->dev); 146443a6a7e7SGarlic Tseng 146543a6a7e7SGarlic Tseng return 0; 146643a6a7e7SGarlic Tseng } 146743a6a7e7SGarlic Tseng 1468bfdc56e5SRyder Lee static const struct mt2701_soc_variants mt2701_soc_v1 = { 1469bfdc56e5SRyder Lee .i2s_num = 4, 1470bfdc56e5SRyder Lee }; 1471bfdc56e5SRyder Lee 1472bfdc56e5SRyder Lee static const struct mt2701_soc_variants mt2701_soc_v2 = { 1473bfdc56e5SRyder Lee .has_one_heart_mode = true, 1474bfdc56e5SRyder Lee .i2s_num = 4, 1475bfdc56e5SRyder Lee }; 1476bfdc56e5SRyder Lee 147743a6a7e7SGarlic Tseng static const struct of_device_id mt2701_afe_pcm_dt_match[] = { 1478bfdc56e5SRyder Lee { .compatible = "mediatek,mt2701-audio", .data = &mt2701_soc_v1 }, 1479bfdc56e5SRyder Lee { .compatible = "mediatek,mt7622-audio", .data = &mt2701_soc_v2 }, 148043a6a7e7SGarlic Tseng {}, 148143a6a7e7SGarlic Tseng }; 148243a6a7e7SGarlic Tseng MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match); 148343a6a7e7SGarlic Tseng 148443a6a7e7SGarlic Tseng static const struct dev_pm_ops mt2701_afe_pm_ops = { 148543a6a7e7SGarlic Tseng SET_RUNTIME_PM_OPS(mt2701_afe_runtime_suspend, 148643a6a7e7SGarlic Tseng mt2701_afe_runtime_resume, NULL) 148743a6a7e7SGarlic Tseng }; 148843a6a7e7SGarlic Tseng 148943a6a7e7SGarlic Tseng static struct platform_driver mt2701_afe_pcm_driver = { 149043a6a7e7SGarlic Tseng .driver = { 149143a6a7e7SGarlic Tseng .name = "mt2701-audio", 149243a6a7e7SGarlic Tseng .of_match_table = mt2701_afe_pcm_dt_match, 149343a6a7e7SGarlic Tseng #ifdef CONFIG_PM 149443a6a7e7SGarlic Tseng .pm = &mt2701_afe_pm_ops, 149543a6a7e7SGarlic Tseng #endif 149643a6a7e7SGarlic Tseng }, 149743a6a7e7SGarlic Tseng .probe = mt2701_afe_pcm_dev_probe, 149843a6a7e7SGarlic Tseng .remove = mt2701_afe_pcm_dev_remove, 149943a6a7e7SGarlic Tseng }; 150043a6a7e7SGarlic Tseng 150143a6a7e7SGarlic Tseng module_platform_driver(mt2701_afe_pcm_driver); 150243a6a7e7SGarlic Tseng 150343a6a7e7SGarlic Tseng MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701"); 150443a6a7e7SGarlic Tseng MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); 150543a6a7e7SGarlic Tseng MODULE_LICENSE("GPL v2"); 1506