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/pm_runtime.h> 1643a6a7e7SGarlic Tseng 1743a6a7e7SGarlic Tseng #include "mt2701-afe-common.h" 1843a6a7e7SGarlic Tseng #include "mt2701-afe-clock-ctrl.h" 1943a6a7e7SGarlic Tseng #include "../common/mtk-afe-platform-driver.h" 2043a6a7e7SGarlic Tseng #include "../common/mtk-afe-fe-dai.h" 2143a6a7e7SGarlic Tseng 2243a6a7e7SGarlic Tseng static const struct snd_pcm_hardware mt2701_afe_hardware = { 2343a6a7e7SGarlic Tseng .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED 2443a6a7e7SGarlic Tseng | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID, 2543a6a7e7SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE 2643a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE, 2743a6a7e7SGarlic Tseng .period_bytes_min = 1024, 2843a6a7e7SGarlic Tseng .period_bytes_max = 1024 * 256, 2943a6a7e7SGarlic Tseng .periods_min = 4, 3043a6a7e7SGarlic Tseng .periods_max = 1024, 31bfdc56e5SRyder Lee .buffer_bytes_max = 1024 * 1024, 3243a6a7e7SGarlic Tseng .fifo_size = 0, 3343a6a7e7SGarlic Tseng }; 3443a6a7e7SGarlic Tseng 3543a6a7e7SGarlic Tseng struct mt2701_afe_rate { 3643a6a7e7SGarlic Tseng unsigned int rate; 3743a6a7e7SGarlic Tseng unsigned int regvalue; 3843a6a7e7SGarlic Tseng }; 3943a6a7e7SGarlic Tseng 4043a6a7e7SGarlic Tseng static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { 4143a6a7e7SGarlic Tseng { .rate = 8000, .regvalue = 0 }, 4243a6a7e7SGarlic Tseng { .rate = 12000, .regvalue = 1 }, 4343a6a7e7SGarlic Tseng { .rate = 16000, .regvalue = 2 }, 4443a6a7e7SGarlic Tseng { .rate = 24000, .regvalue = 3 }, 4543a6a7e7SGarlic Tseng { .rate = 32000, .regvalue = 4 }, 4643a6a7e7SGarlic Tseng { .rate = 48000, .regvalue = 5 }, 4743a6a7e7SGarlic Tseng { .rate = 96000, .regvalue = 6 }, 4843a6a7e7SGarlic Tseng { .rate = 192000, .regvalue = 7 }, 4943a6a7e7SGarlic Tseng { .rate = 384000, .regvalue = 8 }, 5043a6a7e7SGarlic Tseng { .rate = 7350, .regvalue = 16 }, 5143a6a7e7SGarlic Tseng { .rate = 11025, .regvalue = 17 }, 5243a6a7e7SGarlic Tseng { .rate = 14700, .regvalue = 18 }, 5343a6a7e7SGarlic Tseng { .rate = 22050, .regvalue = 19 }, 5443a6a7e7SGarlic Tseng { .rate = 29400, .regvalue = 20 }, 5543a6a7e7SGarlic Tseng { .rate = 44100, .regvalue = 21 }, 5643a6a7e7SGarlic Tseng { .rate = 88200, .regvalue = 22 }, 5743a6a7e7SGarlic Tseng { .rate = 176400, .regvalue = 23 }, 5843a6a7e7SGarlic Tseng { .rate = 352800, .regvalue = 24 }, 5943a6a7e7SGarlic Tseng }; 6043a6a7e7SGarlic Tseng 6197aad5ceSYueHaibing static const unsigned int mt2701_afe_backup_list[] = { 6297aad5ceSYueHaibing AUDIO_TOP_CON0, 6397aad5ceSYueHaibing AUDIO_TOP_CON4, 6497aad5ceSYueHaibing AUDIO_TOP_CON5, 6597aad5ceSYueHaibing ASYS_TOP_CON, 6697aad5ceSYueHaibing AFE_CONN0, 6797aad5ceSYueHaibing AFE_CONN1, 6897aad5ceSYueHaibing AFE_CONN2, 6997aad5ceSYueHaibing AFE_CONN3, 7097aad5ceSYueHaibing AFE_CONN15, 7197aad5ceSYueHaibing AFE_CONN16, 7297aad5ceSYueHaibing AFE_CONN17, 7397aad5ceSYueHaibing AFE_CONN18, 7497aad5ceSYueHaibing AFE_CONN19, 7597aad5ceSYueHaibing AFE_CONN20, 7697aad5ceSYueHaibing AFE_CONN21, 7797aad5ceSYueHaibing AFE_CONN22, 7897aad5ceSYueHaibing AFE_DAC_CON0, 7997aad5ceSYueHaibing AFE_MEMIF_PBUF_SIZE, 8097aad5ceSYueHaibing }; 8197aad5ceSYueHaibing 8225d01dc6SWei Yongjun static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) 8343a6a7e7SGarlic Tseng { 84bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 8543a6a7e7SGarlic Tseng int val = num - MT2701_IO_I2S; 8643a6a7e7SGarlic Tseng 87bfdc56e5SRyder Lee if (val < 0 || val >= afe_priv->soc->i2s_num) { 8843a6a7e7SGarlic Tseng dev_err(afe->dev, "%s, num not available, num %d, val %d\n", 8943a6a7e7SGarlic Tseng __func__, num, val); 9043a6a7e7SGarlic Tseng return -EINVAL; 9143a6a7e7SGarlic Tseng } 9243a6a7e7SGarlic Tseng return val; 9343a6a7e7SGarlic Tseng } 9443a6a7e7SGarlic Tseng 9543a6a7e7SGarlic Tseng static int mt2701_afe_i2s_fs(unsigned int sample_rate) 9643a6a7e7SGarlic Tseng { 9743a6a7e7SGarlic Tseng int i; 9843a6a7e7SGarlic Tseng 9943a6a7e7SGarlic Tseng for (i = 0; i < ARRAY_SIZE(mt2701_afe_i2s_rates); i++) 10043a6a7e7SGarlic Tseng if (mt2701_afe_i2s_rates[i].rate == sample_rate) 10143a6a7e7SGarlic Tseng return mt2701_afe_i2s_rates[i].regvalue; 10243a6a7e7SGarlic Tseng 10343a6a7e7SGarlic Tseng return -EINVAL; 10443a6a7e7SGarlic Tseng } 10543a6a7e7SGarlic Tseng 10643a6a7e7SGarlic Tseng static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, 10743a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 10843a6a7e7SGarlic Tseng { 109e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 110bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 11143a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 112bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 11343a6a7e7SGarlic Tseng 11443a6a7e7SGarlic Tseng if (i2s_num < 0) 11543a6a7e7SGarlic Tseng return i2s_num; 11643a6a7e7SGarlic Tseng 117bfdc56e5SRyder Lee return mt2701_afe_enable_mclk(afe, mode ? 1 : i2s_num); 11843a6a7e7SGarlic Tseng } 11943a6a7e7SGarlic Tseng 120cf870273SRyder Lee static int mt2701_afe_i2s_path_disable(struct mtk_base_afe *afe, 121cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 122cf870273SRyder Lee int stream_dir) 12343a6a7e7SGarlic Tseng { 124cf870273SRyder Lee const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; 12543a6a7e7SGarlic Tseng 126cf870273SRyder Lee if (--i2s_path->on[stream_dir] < 0) 12743a6a7e7SGarlic Tseng i2s_path->on[stream_dir] = 0; 128cf870273SRyder Lee 12943a6a7e7SGarlic Tseng if (i2s_path->on[stream_dir]) 13043a6a7e7SGarlic Tseng return 0; 13143a6a7e7SGarlic Tseng 13243a6a7e7SGarlic Tseng /* disable i2s */ 13343a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 13443a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_EN, 0); 135d8d99d8eSRyder Lee 136cf870273SRyder Lee mt2701_afe_disable_i2s(afe, i2s_path, stream_dir); 137d8d99d8eSRyder Lee 13843a6a7e7SGarlic Tseng return 0; 13943a6a7e7SGarlic Tseng } 14043a6a7e7SGarlic Tseng 14143a6a7e7SGarlic Tseng static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, 14243a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 14343a6a7e7SGarlic Tseng { 144e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 14543a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 14643a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 14743a6a7e7SGarlic Tseng struct mt2701_i2s_path *i2s_path; 148bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 14943a6a7e7SGarlic Tseng 15043a6a7e7SGarlic Tseng if (i2s_num < 0) 15143a6a7e7SGarlic Tseng return; 15243a6a7e7SGarlic Tseng 15343a6a7e7SGarlic Tseng i2s_path = &afe_priv->i2s_path[i2s_num]; 15443a6a7e7SGarlic Tseng 15543a6a7e7SGarlic Tseng if (i2s_path->occupied[substream->stream]) 15643a6a7e7SGarlic Tseng i2s_path->occupied[substream->stream] = 0; 15743a6a7e7SGarlic Tseng else 158cf870273SRyder Lee goto exit; 15943a6a7e7SGarlic Tseng 160cf870273SRyder Lee mt2701_afe_i2s_path_disable(afe, i2s_path, substream->stream); 16143a6a7e7SGarlic Tseng 16243a6a7e7SGarlic Tseng /* need to disable i2s-out path when disable i2s-in */ 16343a6a7e7SGarlic Tseng if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 164cf870273SRyder Lee mt2701_afe_i2s_path_disable(afe, i2s_path, !substream->stream); 16543a6a7e7SGarlic Tseng 166cf870273SRyder Lee exit: 16743a6a7e7SGarlic Tseng /* disable mclk */ 168bfdc56e5SRyder Lee mt2701_afe_disable_mclk(afe, mode ? 1 : i2s_num); 16943a6a7e7SGarlic Tseng } 17043a6a7e7SGarlic Tseng 171cf870273SRyder Lee static int mt2701_i2s_path_enable(struct mtk_base_afe *afe, 172cf870273SRyder Lee struct mt2701_i2s_path *i2s_path, 173cf870273SRyder Lee int stream_dir, int rate) 17443a6a7e7SGarlic Tseng { 175cf870273SRyder Lee const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir]; 176bfdc56e5SRyder Lee struct mt2701_afe_private *afe_priv = afe->platform_priv; 17743a6a7e7SGarlic Tseng int reg, fs, w_len = 1; /* now we support bck 64bits only */ 178e4b31b81SRyder Lee unsigned int mask, val; 17943a6a7e7SGarlic Tseng 18043a6a7e7SGarlic Tseng /* no need to enable if already done */ 181cf870273SRyder Lee if (++i2s_path->on[stream_dir] != 1) 18243a6a7e7SGarlic Tseng return 0; 18343a6a7e7SGarlic Tseng 184cf870273SRyder Lee fs = mt2701_afe_i2s_fs(rate); 18543a6a7e7SGarlic Tseng 18643a6a7e7SGarlic Tseng mask = ASYS_I2S_CON_FS | 18743a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */ 18843a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_MODE | 18943a6a7e7SGarlic Tseng ASYS_I2S_CON_WIDE_MODE; 19043a6a7e7SGarlic Tseng 19143a6a7e7SGarlic Tseng val = ASYS_I2S_CON_FS_SET(fs) | 19243a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_MODE | 19343a6a7e7SGarlic Tseng ASYS_I2S_CON_WIDE_MODE_SET(w_len); 19443a6a7e7SGarlic Tseng 19543a6a7e7SGarlic Tseng if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) { 19643a6a7e7SGarlic Tseng mask |= ASYS_I2S_IN_PHASE_FIX; 19743a6a7e7SGarlic Tseng val |= ASYS_I2S_IN_PHASE_FIX; 198cf870273SRyder Lee reg = ASMI_TIMING_CON1; 199cf870273SRyder Lee } else { 200bfdc56e5SRyder Lee if (afe_priv->soc->has_one_heart_mode) { 201bfdc56e5SRyder Lee mask |= ASYS_I2S_CON_ONE_HEART_MODE; 202bfdc56e5SRyder Lee val |= ASYS_I2S_CON_ONE_HEART_MODE; 203bfdc56e5SRyder Lee } 204cf870273SRyder Lee reg = ASMO_TIMING_CON1; 20543a6a7e7SGarlic Tseng } 20643a6a7e7SGarlic Tseng 20743a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val); 20843a6a7e7SGarlic Tseng 20943a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, reg, 21043a6a7e7SGarlic Tseng i2s_data->i2s_asrc_fs_mask 21143a6a7e7SGarlic Tseng << i2s_data->i2s_asrc_fs_shift, 21243a6a7e7SGarlic Tseng fs << i2s_data->i2s_asrc_fs_shift); 21343a6a7e7SGarlic Tseng 21443a6a7e7SGarlic Tseng /* enable i2s */ 215cf870273SRyder Lee mt2701_afe_enable_i2s(afe, i2s_path, stream_dir); 21643a6a7e7SGarlic Tseng 21743a6a7e7SGarlic Tseng /* reset i2s hw status before enable */ 21843a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 21943a6a7e7SGarlic Tseng ASYS_I2S_CON_RESET, ASYS_I2S_CON_RESET); 22043a6a7e7SGarlic Tseng udelay(1); 22143a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 22243a6a7e7SGarlic Tseng ASYS_I2S_CON_RESET, 0); 22343a6a7e7SGarlic Tseng udelay(1); 22443a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, 22543a6a7e7SGarlic Tseng ASYS_I2S_CON_I2S_EN, ASYS_I2S_CON_I2S_EN); 22643a6a7e7SGarlic Tseng return 0; 22743a6a7e7SGarlic Tseng } 22843a6a7e7SGarlic Tseng 22943a6a7e7SGarlic Tseng static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream, 23043a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 23143a6a7e7SGarlic Tseng { 232e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 23343a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 234cf870273SRyder Lee int ret, i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 23543a6a7e7SGarlic Tseng struct mt2701_i2s_path *i2s_path; 236bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 23743a6a7e7SGarlic Tseng 23843a6a7e7SGarlic Tseng if (i2s_num < 0) 23943a6a7e7SGarlic Tseng return i2s_num; 24043a6a7e7SGarlic Tseng 24143a6a7e7SGarlic Tseng i2s_path = &afe_priv->i2s_path[i2s_num]; 24243a6a7e7SGarlic Tseng 24343a6a7e7SGarlic Tseng if (i2s_path->occupied[substream->stream]) 24443a6a7e7SGarlic Tseng return -EBUSY; 245cf870273SRyder Lee 246bfdc56e5SRyder Lee ret = mt2701_mclk_configuration(afe, mode ? 1 : i2s_num); 247cf870273SRyder Lee if (ret) 248cf870273SRyder Lee return ret; 249cf870273SRyder Lee 25043a6a7e7SGarlic Tseng i2s_path->occupied[substream->stream] = 1; 25143a6a7e7SGarlic Tseng 25243a6a7e7SGarlic Tseng /* need to enable i2s-out path when enable i2s-in */ 253cf870273SRyder Lee if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 254cf870273SRyder Lee mt2701_i2s_path_enable(afe, i2s_path, !substream->stream, 255cf870273SRyder Lee substream->runtime->rate); 256cf870273SRyder Lee 257cf870273SRyder Lee mt2701_i2s_path_enable(afe, i2s_path, substream->stream, 258cf870273SRyder Lee substream->runtime->rate); 25943a6a7e7SGarlic Tseng 26043a6a7e7SGarlic Tseng return 0; 26143a6a7e7SGarlic Tseng } 26243a6a7e7SGarlic Tseng 26343a6a7e7SGarlic Tseng static int mt2701_afe_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, 26443a6a7e7SGarlic Tseng unsigned int freq, int dir) 26543a6a7e7SGarlic Tseng { 266e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 26743a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 26843a6a7e7SGarlic Tseng int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); 269bfdc56e5SRyder Lee bool mode = afe_priv->soc->has_one_heart_mode; 27043a6a7e7SGarlic Tseng 27143a6a7e7SGarlic Tseng if (i2s_num < 0) 27243a6a7e7SGarlic Tseng return i2s_num; 27343a6a7e7SGarlic Tseng 27443a6a7e7SGarlic Tseng /* mclk */ 27543a6a7e7SGarlic Tseng if (dir == SND_SOC_CLOCK_IN) { 276bfdc56e5SRyder Lee dev_warn(dai->dev, "The SoCs doesn't support mclk input\n"); 27743a6a7e7SGarlic Tseng return -EINVAL; 27843a6a7e7SGarlic Tseng } 279e4b31b81SRyder Lee 280bfdc56e5SRyder Lee afe_priv->i2s_path[mode ? 1 : i2s_num].mclk_rate = freq; 281e4b31b81SRyder Lee 28243a6a7e7SGarlic Tseng return 0; 28343a6a7e7SGarlic Tseng } 28443a6a7e7SGarlic Tseng 2854bdc8d45SGarlic Tseng static int mt2701_btmrg_startup(struct snd_pcm_substream *substream, 2864bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 2874bdc8d45SGarlic Tseng { 288e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 2894bdc8d45SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 290d8d99d8eSRyder Lee int ret; 2914bdc8d45SGarlic Tseng 292d8d99d8eSRyder Lee ret = mt2701_enable_btmrg_clk(afe); 293d8d99d8eSRyder Lee if (ret) 294d8d99d8eSRyder Lee return ret; 2954bdc8d45SGarlic Tseng 2964bdc8d45SGarlic Tseng afe_priv->mrg_enable[substream->stream] = 1; 297e4b31b81SRyder Lee 2984bdc8d45SGarlic Tseng return 0; 2994bdc8d45SGarlic Tseng } 3004bdc8d45SGarlic Tseng 3014bdc8d45SGarlic Tseng static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream, 3024bdc8d45SGarlic Tseng struct snd_pcm_hw_params *params, 3034bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 3044bdc8d45SGarlic Tseng { 305e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 3064bdc8d45SGarlic Tseng int stream_fs; 3074bdc8d45SGarlic Tseng u32 val, msk; 3084bdc8d45SGarlic Tseng 3094bdc8d45SGarlic Tseng stream_fs = params_rate(params); 3104bdc8d45SGarlic Tseng 311e4b31b81SRyder Lee if (stream_fs != 8000 && stream_fs != 16000) { 312e4b31b81SRyder Lee dev_err(afe->dev, "unsupported rate %d\n", stream_fs); 3134bdc8d45SGarlic Tseng return -EINVAL; 3144bdc8d45SGarlic Tseng } 3154bdc8d45SGarlic Tseng 3164bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3174bdc8d45SGarlic Tseng AFE_MRGIF_CON_I2S_MODE_MASK, 3184bdc8d45SGarlic Tseng AFE_MRGIF_CON_I2S_MODE_32K); 3194bdc8d45SGarlic Tseng 3204bdc8d45SGarlic Tseng val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY 3214bdc8d45SGarlic Tseng | AFE_DAIBT_CON0_MRG_USE; 3224bdc8d45SGarlic Tseng msk = val; 3234bdc8d45SGarlic Tseng 3244bdc8d45SGarlic Tseng if (stream_fs == 16000) 3254bdc8d45SGarlic Tseng val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; 3264bdc8d45SGarlic Tseng 3274bdc8d45SGarlic Tseng msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; 3284bdc8d45SGarlic Tseng 3294bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val); 3304bdc8d45SGarlic Tseng 3314bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, 3324bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN, 3334bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN); 3344bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3354bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN, 3364bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN); 3374bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3384bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN, 3394bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN); 3404bdc8d45SGarlic Tseng return 0; 3414bdc8d45SGarlic Tseng } 3424bdc8d45SGarlic Tseng 3434bdc8d45SGarlic Tseng static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream, 3444bdc8d45SGarlic Tseng struct snd_soc_dai *dai) 3454bdc8d45SGarlic Tseng { 346e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 3474bdc8d45SGarlic Tseng struct mt2701_afe_private *afe_priv = afe->platform_priv; 3484bdc8d45SGarlic Tseng 3494bdc8d45SGarlic Tseng /* if the other direction stream is not occupied */ 3504bdc8d45SGarlic Tseng if (!afe_priv->mrg_enable[!substream->stream]) { 3514bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, 3524bdc8d45SGarlic Tseng AFE_DAIBT_CON0_DAIBT_EN, 0); 3534bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3544bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_EN, 0); 3554bdc8d45SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MRGIF_CON, 3564bdc8d45SGarlic Tseng AFE_MRGIF_CON_MRG_I2S_EN, 0); 357d8d99d8eSRyder Lee mt2701_disable_btmrg_clk(afe); 3584bdc8d45SGarlic Tseng } 359e4b31b81SRyder Lee 3604bdc8d45SGarlic Tseng afe_priv->mrg_enable[substream->stream] = 0; 3614bdc8d45SGarlic Tseng } 3624bdc8d45SGarlic Tseng 36343a6a7e7SGarlic Tseng static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream, 36443a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 36543a6a7e7SGarlic Tseng { 366e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 36743a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp; 368e4b31b81SRyder Lee int stream_dir = substream->stream; 36943a6a7e7SGarlic Tseng 37043a6a7e7SGarlic Tseng /* can't run single DL & DLM at the same time */ 37143a6a7e7SGarlic Tseng if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) { 37243a6a7e7SGarlic Tseng memif_tmp = &afe->memif[MT2701_MEMIF_DLM]; 37343a6a7e7SGarlic Tseng if (memif_tmp->substream) { 374e4b31b81SRyder Lee dev_warn(afe->dev, "memif is not available"); 37543a6a7e7SGarlic Tseng return -EBUSY; 37643a6a7e7SGarlic Tseng } 37743a6a7e7SGarlic Tseng } 378e4b31b81SRyder Lee 37943a6a7e7SGarlic Tseng return mtk_afe_fe_startup(substream, dai); 38043a6a7e7SGarlic Tseng } 38143a6a7e7SGarlic Tseng 38243a6a7e7SGarlic Tseng static int mt2701_simple_fe_hw_params(struct snd_pcm_substream *substream, 38343a6a7e7SGarlic Tseng struct snd_pcm_hw_params *params, 38443a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 38543a6a7e7SGarlic Tseng { 386e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 38743a6a7e7SGarlic Tseng int stream_dir = substream->stream; 38843a6a7e7SGarlic Tseng 38943a6a7e7SGarlic Tseng /* single DL use PAIR_INTERLEAVE */ 390e4b31b81SRyder Lee if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) 39143a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 39243a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 39343a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_MASK, 39443a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_PAIR_INTERLEAVE); 395e4b31b81SRyder Lee 39643a6a7e7SGarlic Tseng return mtk_afe_fe_hw_params(substream, params, dai); 39743a6a7e7SGarlic Tseng } 39843a6a7e7SGarlic Tseng 39943a6a7e7SGarlic Tseng static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream, 40043a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 40143a6a7e7SGarlic Tseng { 402e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 40343a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp; 40443a6a7e7SGarlic Tseng const struct mtk_base_memif_data *memif_data; 40543a6a7e7SGarlic Tseng int i; 40643a6a7e7SGarlic Tseng 40743a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 40843a6a7e7SGarlic Tseng memif_tmp = &afe->memif[i]; 40943a6a7e7SGarlic Tseng if (memif_tmp->substream) 41043a6a7e7SGarlic Tseng return -EBUSY; 41143a6a7e7SGarlic Tseng } 41243a6a7e7SGarlic Tseng 41343a6a7e7SGarlic Tseng /* enable agent for all signal DL (due to hw design) */ 41443a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 41543a6a7e7SGarlic Tseng memif_data = afe->memif[i].data; 41643a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 41743a6a7e7SGarlic Tseng memif_data->agent_disable_reg, 41843a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift, 41943a6a7e7SGarlic Tseng 0 << memif_data->agent_disable_shift); 42043a6a7e7SGarlic Tseng } 42143a6a7e7SGarlic Tseng 42243a6a7e7SGarlic Tseng return mtk_afe_fe_startup(substream, dai); 42343a6a7e7SGarlic Tseng } 42443a6a7e7SGarlic Tseng 42543a6a7e7SGarlic Tseng static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream, 42643a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 42743a6a7e7SGarlic Tseng { 428e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 42943a6a7e7SGarlic Tseng const struct mtk_base_memif_data *memif_data; 43043a6a7e7SGarlic Tseng int i; 43143a6a7e7SGarlic Tseng 43243a6a7e7SGarlic Tseng for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { 43343a6a7e7SGarlic Tseng memif_data = afe->memif[i].data; 43443a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 43543a6a7e7SGarlic Tseng memif_data->agent_disable_reg, 43643a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift, 43743a6a7e7SGarlic Tseng 1 << memif_data->agent_disable_shift); 43843a6a7e7SGarlic Tseng } 439e4b31b81SRyder Lee 44043a6a7e7SGarlic Tseng return mtk_afe_fe_shutdown(substream, dai); 44143a6a7e7SGarlic Tseng } 44243a6a7e7SGarlic Tseng 44343a6a7e7SGarlic Tseng static int mt2701_dlm_fe_hw_params(struct snd_pcm_substream *substream, 44443a6a7e7SGarlic Tseng struct snd_pcm_hw_params *params, 44543a6a7e7SGarlic Tseng struct snd_soc_dai *dai) 44643a6a7e7SGarlic Tseng { 447e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 44843a6a7e7SGarlic Tseng int channels = params_channels(params); 44943a6a7e7SGarlic Tseng 45043a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 45143a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 45243a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_MASK, 45343a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_FULL_INTERLEAVE); 45443a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 45543a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 45643a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK, 45743a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_32BYTES); 45843a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, 45943a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE, 46043a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_CH_MASK, 46143a6a7e7SGarlic Tseng AFE_MEMIF_PBUF_SIZE_DLM_CH(channels)); 46243a6a7e7SGarlic Tseng 46343a6a7e7SGarlic Tseng return mtk_afe_fe_hw_params(substream, params, dai); 46443a6a7e7SGarlic Tseng } 46543a6a7e7SGarlic Tseng 46643a6a7e7SGarlic Tseng static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream, 46743a6a7e7SGarlic Tseng int cmd, struct snd_soc_dai *dai) 46843a6a7e7SGarlic Tseng { 469e4b31b81SRyder Lee struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 47043a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif_tmp = &afe->memif[MT2701_MEMIF_DL1]; 47143a6a7e7SGarlic Tseng 47243a6a7e7SGarlic Tseng switch (cmd) { 47343a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_START: 47443a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_RESUME: 47543a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, 47643a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift, 47743a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift); 47843a6a7e7SGarlic Tseng mtk_afe_fe_trigger(substream, cmd, dai); 47943a6a7e7SGarlic Tseng return 0; 48043a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_STOP: 48143a6a7e7SGarlic Tseng case SNDRV_PCM_TRIGGER_SUSPEND: 48243a6a7e7SGarlic Tseng mtk_afe_fe_trigger(substream, cmd, dai); 48343a6a7e7SGarlic Tseng regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, 48443a6a7e7SGarlic Tseng 1 << memif_tmp->data->enable_shift, 0); 48543a6a7e7SGarlic Tseng 48643a6a7e7SGarlic Tseng return 0; 48743a6a7e7SGarlic Tseng default: 48843a6a7e7SGarlic Tseng return -EINVAL; 48943a6a7e7SGarlic Tseng } 49043a6a7e7SGarlic Tseng } 49143a6a7e7SGarlic Tseng 49243a6a7e7SGarlic Tseng static int mt2701_memif_fs(struct snd_pcm_substream *substream, 49343a6a7e7SGarlic Tseng unsigned int rate) 49443a6a7e7SGarlic Tseng { 495de9e7013SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 49643a6a7e7SGarlic Tseng int fs; 49743a6a7e7SGarlic Tseng 498de9e7013SKuninori Morimoto if (snd_soc_rtd_to_cpu(rtd, 0)->id != MT2701_MEMIF_ULBT) 49943a6a7e7SGarlic Tseng fs = mt2701_afe_i2s_fs(rate); 50043a6a7e7SGarlic Tseng else 50143a6a7e7SGarlic Tseng fs = (rate == 16000 ? 1 : 0); 502e4b31b81SRyder Lee 50343a6a7e7SGarlic Tseng return fs; 50443a6a7e7SGarlic Tseng } 50543a6a7e7SGarlic Tseng 50643a6a7e7SGarlic Tseng static int mt2701_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) 50743a6a7e7SGarlic Tseng { 50843a6a7e7SGarlic Tseng return mt2701_afe_i2s_fs(rate); 50943a6a7e7SGarlic Tseng } 51043a6a7e7SGarlic Tseng 51143a6a7e7SGarlic Tseng /* FE DAIs */ 51243a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = { 51343a6a7e7SGarlic Tseng .startup = mt2701_simple_fe_startup, 51443a6a7e7SGarlic Tseng .shutdown = mtk_afe_fe_shutdown, 51543a6a7e7SGarlic Tseng .hw_params = mt2701_simple_fe_hw_params, 51643a6a7e7SGarlic Tseng .hw_free = mtk_afe_fe_hw_free, 51743a6a7e7SGarlic Tseng .prepare = mtk_afe_fe_prepare, 51843a6a7e7SGarlic Tseng .trigger = mtk_afe_fe_trigger, 51943a6a7e7SGarlic Tseng }; 52043a6a7e7SGarlic Tseng 52143a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = { 52243a6a7e7SGarlic Tseng .startup = mt2701_dlm_fe_startup, 52343a6a7e7SGarlic Tseng .shutdown = mt2701_dlm_fe_shutdown, 52443a6a7e7SGarlic Tseng .hw_params = mt2701_dlm_fe_hw_params, 52543a6a7e7SGarlic Tseng .hw_free = mtk_afe_fe_hw_free, 52643a6a7e7SGarlic Tseng .prepare = mtk_afe_fe_prepare, 52743a6a7e7SGarlic Tseng .trigger = mt2701_dlm_fe_trigger, 52843a6a7e7SGarlic Tseng }; 52943a6a7e7SGarlic Tseng 53043a6a7e7SGarlic Tseng /* I2S BE DAIs */ 53143a6a7e7SGarlic Tseng static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = { 53243a6a7e7SGarlic Tseng .startup = mt2701_afe_i2s_startup, 53343a6a7e7SGarlic Tseng .shutdown = mt2701_afe_i2s_shutdown, 53443a6a7e7SGarlic Tseng .prepare = mt2701_afe_i2s_prepare, 53543a6a7e7SGarlic Tseng .set_sysclk = mt2701_afe_i2s_set_sysclk, 53643a6a7e7SGarlic Tseng }; 53743a6a7e7SGarlic Tseng 5384bdc8d45SGarlic Tseng /* MRG BE DAIs */ 539549acff9SGustavo A. R. Silva static const struct snd_soc_dai_ops mt2701_btmrg_ops = { 5404bdc8d45SGarlic Tseng .startup = mt2701_btmrg_startup, 5414bdc8d45SGarlic Tseng .shutdown = mt2701_btmrg_shutdown, 5424bdc8d45SGarlic Tseng .hw_params = mt2701_btmrg_hw_params, 5434bdc8d45SGarlic Tseng }; 5444bdc8d45SGarlic Tseng 54543a6a7e7SGarlic Tseng static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { 54643a6a7e7SGarlic Tseng /* FE DAIs: memory intefaces to CPU */ 54743a6a7e7SGarlic Tseng { 5488625c1dbSRyder Lee .name = "PCMO0", 5498625c1dbSRyder Lee .id = MT2701_MEMIF_DL1, 5508625c1dbSRyder Lee .playback = { 5518625c1dbSRyder Lee .stream_name = "DL1", 5528625c1dbSRyder Lee .channels_min = 1, 5538625c1dbSRyder Lee .channels_max = 2, 5548625c1dbSRyder Lee .rates = SNDRV_PCM_RATE_8000_192000, 5558625c1dbSRyder Lee .formats = (SNDRV_PCM_FMTBIT_S16_LE 5568625c1dbSRyder Lee | SNDRV_PCM_FMTBIT_S24_LE 5578625c1dbSRyder Lee | SNDRV_PCM_FMTBIT_S32_LE) 5588625c1dbSRyder Lee }, 5598625c1dbSRyder Lee .ops = &mt2701_single_memif_dai_ops, 5608625c1dbSRyder Lee }, 5618625c1dbSRyder Lee { 56243a6a7e7SGarlic Tseng .name = "PCM_multi", 56343a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLM, 56443a6a7e7SGarlic Tseng .playback = { 56543a6a7e7SGarlic Tseng .stream_name = "DLM", 56643a6a7e7SGarlic Tseng .channels_min = 1, 56743a6a7e7SGarlic Tseng .channels_max = 8, 56843a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 56943a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 57043a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 57143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 57243a6a7e7SGarlic Tseng 57343a6a7e7SGarlic Tseng }, 57443a6a7e7SGarlic Tseng .ops = &mt2701_dlm_memif_dai_ops, 57543a6a7e7SGarlic Tseng }, 57643a6a7e7SGarlic Tseng { 57743a6a7e7SGarlic Tseng .name = "PCM0", 57843a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL1, 57943a6a7e7SGarlic Tseng .capture = { 58043a6a7e7SGarlic Tseng .stream_name = "UL1", 58143a6a7e7SGarlic Tseng .channels_min = 1, 58243a6a7e7SGarlic Tseng .channels_max = 2, 58343a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 58443a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 58543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 58643a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 58743a6a7e7SGarlic Tseng }, 58843a6a7e7SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 58943a6a7e7SGarlic Tseng }, 59043a6a7e7SGarlic Tseng { 59143a6a7e7SGarlic Tseng .name = "PCM1", 59243a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL2, 59343a6a7e7SGarlic Tseng .capture = { 59443a6a7e7SGarlic Tseng .stream_name = "UL2", 59543a6a7e7SGarlic Tseng .channels_min = 1, 59643a6a7e7SGarlic Tseng .channels_max = 2, 59743a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 59843a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 59943a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 60043a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 60143a6a7e7SGarlic Tseng 60243a6a7e7SGarlic Tseng }, 60343a6a7e7SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 60443a6a7e7SGarlic Tseng }, 6054bdc8d45SGarlic Tseng { 6064bdc8d45SGarlic Tseng .name = "PCM_BT_DL", 6074bdc8d45SGarlic Tseng .id = MT2701_MEMIF_DLBT, 6084bdc8d45SGarlic Tseng .playback = { 6094bdc8d45SGarlic Tseng .stream_name = "DLBT", 6104bdc8d45SGarlic Tseng .channels_min = 1, 6114bdc8d45SGarlic Tseng .channels_max = 1, 6124bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 6134bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 6144bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 6154bdc8d45SGarlic Tseng }, 6164bdc8d45SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 6174bdc8d45SGarlic Tseng }, 6184bdc8d45SGarlic Tseng { 6194bdc8d45SGarlic Tseng .name = "PCM_BT_UL", 6204bdc8d45SGarlic Tseng .id = MT2701_MEMIF_ULBT, 6214bdc8d45SGarlic Tseng .capture = { 6224bdc8d45SGarlic Tseng .stream_name = "ULBT", 6234bdc8d45SGarlic Tseng .channels_min = 1, 6244bdc8d45SGarlic Tseng .channels_max = 1, 6254bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 6264bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 6274bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 6284bdc8d45SGarlic Tseng }, 6294bdc8d45SGarlic Tseng .ops = &mt2701_single_memif_dai_ops, 6304bdc8d45SGarlic Tseng }, 63143a6a7e7SGarlic Tseng /* BE DAIs */ 63243a6a7e7SGarlic Tseng { 63343a6a7e7SGarlic Tseng .name = "I2S0", 63443a6a7e7SGarlic Tseng .id = MT2701_IO_I2S, 63543a6a7e7SGarlic Tseng .playback = { 63643a6a7e7SGarlic Tseng .stream_name = "I2S0 Playback", 63743a6a7e7SGarlic Tseng .channels_min = 1, 63843a6a7e7SGarlic Tseng .channels_max = 2, 63943a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 64043a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 64143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 64243a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 64343a6a7e7SGarlic Tseng 64443a6a7e7SGarlic Tseng }, 64543a6a7e7SGarlic Tseng .capture = { 64643a6a7e7SGarlic Tseng .stream_name = "I2S0 Capture", 64743a6a7e7SGarlic Tseng .channels_min = 1, 64843a6a7e7SGarlic Tseng .channels_max = 2, 64943a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 65043a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 65143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 65243a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 65343a6a7e7SGarlic Tseng 65443a6a7e7SGarlic Tseng }, 65543a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 6564b7ead03SKuninori Morimoto .symmetric_rate = 1, 65743a6a7e7SGarlic Tseng }, 65843a6a7e7SGarlic Tseng { 65943a6a7e7SGarlic Tseng .name = "I2S1", 66043a6a7e7SGarlic Tseng .id = MT2701_IO_2ND_I2S, 66143a6a7e7SGarlic Tseng .playback = { 66243a6a7e7SGarlic Tseng .stream_name = "I2S1 Playback", 66343a6a7e7SGarlic Tseng .channels_min = 1, 66443a6a7e7SGarlic Tseng .channels_max = 2, 66543a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 66643a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 66743a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 66843a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 66943a6a7e7SGarlic Tseng }, 67043a6a7e7SGarlic Tseng .capture = { 67143a6a7e7SGarlic Tseng .stream_name = "I2S1 Capture", 67243a6a7e7SGarlic Tseng .channels_min = 1, 67343a6a7e7SGarlic Tseng .channels_max = 2, 67443a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 67543a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 67643a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 67743a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 67843a6a7e7SGarlic Tseng }, 67943a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 6804b7ead03SKuninori Morimoto .symmetric_rate = 1, 68143a6a7e7SGarlic Tseng }, 68243a6a7e7SGarlic Tseng { 68343a6a7e7SGarlic Tseng .name = "I2S2", 68443a6a7e7SGarlic Tseng .id = MT2701_IO_3RD_I2S, 68543a6a7e7SGarlic Tseng .playback = { 68643a6a7e7SGarlic Tseng .stream_name = "I2S2 Playback", 68743a6a7e7SGarlic Tseng .channels_min = 1, 68843a6a7e7SGarlic Tseng .channels_max = 2, 68943a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 69043a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 69143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 69243a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 69343a6a7e7SGarlic Tseng }, 69443a6a7e7SGarlic Tseng .capture = { 69543a6a7e7SGarlic Tseng .stream_name = "I2S2 Capture", 69643a6a7e7SGarlic Tseng .channels_min = 1, 69743a6a7e7SGarlic Tseng .channels_max = 2, 69843a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 69943a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 70043a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 70143a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 70243a6a7e7SGarlic Tseng }, 70343a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 7044b7ead03SKuninori Morimoto .symmetric_rate = 1, 70543a6a7e7SGarlic Tseng }, 70643a6a7e7SGarlic Tseng { 70743a6a7e7SGarlic Tseng .name = "I2S3", 70843a6a7e7SGarlic Tseng .id = MT2701_IO_4TH_I2S, 70943a6a7e7SGarlic Tseng .playback = { 71043a6a7e7SGarlic Tseng .stream_name = "I2S3 Playback", 71143a6a7e7SGarlic Tseng .channels_min = 1, 71243a6a7e7SGarlic Tseng .channels_max = 2, 71343a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 71443a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 71543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 71643a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 71743a6a7e7SGarlic Tseng }, 71843a6a7e7SGarlic Tseng .capture = { 71943a6a7e7SGarlic Tseng .stream_name = "I2S3 Capture", 72043a6a7e7SGarlic Tseng .channels_min = 1, 72143a6a7e7SGarlic Tseng .channels_max = 2, 72243a6a7e7SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_192000, 72343a6a7e7SGarlic Tseng .formats = (SNDRV_PCM_FMTBIT_S16_LE 72443a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S24_LE 72543a6a7e7SGarlic Tseng | SNDRV_PCM_FMTBIT_S32_LE) 72643a6a7e7SGarlic Tseng }, 72743a6a7e7SGarlic Tseng .ops = &mt2701_afe_i2s_ops, 7284b7ead03SKuninori Morimoto .symmetric_rate = 1, 72943a6a7e7SGarlic Tseng }, 7304bdc8d45SGarlic Tseng { 7314bdc8d45SGarlic Tseng .name = "MRG BT", 7324bdc8d45SGarlic Tseng .id = MT2701_IO_MRG, 7334bdc8d45SGarlic Tseng .playback = { 7344bdc8d45SGarlic Tseng .stream_name = "BT Playback", 7354bdc8d45SGarlic Tseng .channels_min = 1, 7364bdc8d45SGarlic Tseng .channels_max = 1, 7374bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 7384bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 7394bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 7404bdc8d45SGarlic Tseng }, 7414bdc8d45SGarlic Tseng .capture = { 7424bdc8d45SGarlic Tseng .stream_name = "BT Capture", 7434bdc8d45SGarlic Tseng .channels_min = 1, 7444bdc8d45SGarlic Tseng .channels_max = 1, 7454bdc8d45SGarlic Tseng .rates = (SNDRV_PCM_RATE_8000 7464bdc8d45SGarlic Tseng | SNDRV_PCM_RATE_16000), 7474bdc8d45SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 7484bdc8d45SGarlic Tseng }, 7494bdc8d45SGarlic Tseng .ops = &mt2701_btmrg_ops, 7504b7ead03SKuninori Morimoto .symmetric_rate = 1, 7514bdc8d45SGarlic Tseng } 75243a6a7e7SGarlic Tseng }; 75343a6a7e7SGarlic Tseng 75443a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = { 75543a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN0, 0, 1, 0), 75643a6a7e7SGarlic Tseng }; 75743a6a7e7SGarlic Tseng 75843a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o01_mix[] = { 75943a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN1, 1, 1, 0), 76043a6a7e7SGarlic Tseng }; 76143a6a7e7SGarlic Tseng 76243a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o02_mix[] = { 76343a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I02 Switch", AFE_CONN2, 2, 1, 0), 76443a6a7e7SGarlic Tseng }; 76543a6a7e7SGarlic Tseng 76643a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o03_mix[] = { 76743a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 3, 1, 0), 76843a6a7e7SGarlic Tseng }; 76943a6a7e7SGarlic Tseng 77043a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o14_mix[] = { 77143a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN14, 26, 1, 0), 77243a6a7e7SGarlic Tseng }; 77343a6a7e7SGarlic Tseng 77443a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o15_mix[] = { 77543a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I12 Switch", AFE_CONN15, 12, 1, 0), 77643a6a7e7SGarlic Tseng }; 77743a6a7e7SGarlic Tseng 77843a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o16_mix[] = { 77943a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I13 Switch", AFE_CONN16, 13, 1, 0), 78043a6a7e7SGarlic Tseng }; 78143a6a7e7SGarlic Tseng 78243a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o17_mix[] = { 78343a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0), 78443a6a7e7SGarlic Tseng }; 78543a6a7e7SGarlic Tseng 78643a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o18_mix[] = { 78743a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0), 78843a6a7e7SGarlic Tseng }; 78943a6a7e7SGarlic Tseng 79043a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o19_mix[] = { 79143a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0), 79243a6a7e7SGarlic Tseng }; 79343a6a7e7SGarlic Tseng 79443a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o20_mix[] = { 79543a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0), 79643a6a7e7SGarlic Tseng }; 79743a6a7e7SGarlic Tseng 79843a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o21_mix[] = { 79943a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0), 80043a6a7e7SGarlic Tseng }; 80143a6a7e7SGarlic Tseng 80243a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o22_mix[] = { 80343a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), 80443a6a7e7SGarlic Tseng }; 80543a6a7e7SGarlic Tseng 80643a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = { 80743a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0), 80843a6a7e7SGarlic Tseng }; 80943a6a7e7SGarlic Tseng 81043a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_i02_mix[] = { 81143a6a7e7SGarlic Tseng SOC_DAPM_SINGLE("I2S0 Switch", SND_SOC_NOPM, 0, 1, 0), 81243a6a7e7SGarlic Tseng }; 81343a6a7e7SGarlic Tseng 81443a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s0[] = { 81543a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S0 Out Switch", 81643a6a7e7SGarlic Tseng ASYS_I2SO1_CON, 26, 1, 0), 81743a6a7e7SGarlic Tseng }; 81843a6a7e7SGarlic Tseng 81943a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s1[] = { 82043a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S1 Out Switch", 82143a6a7e7SGarlic Tseng ASYS_I2SO2_CON, 26, 1, 0), 82243a6a7e7SGarlic Tseng }; 82343a6a7e7SGarlic Tseng 82443a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s2[] = { 82543a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S2 Out Switch", 82643a6a7e7SGarlic Tseng PWR2_TOP_CON, 17, 1, 0), 82743a6a7e7SGarlic Tseng }; 82843a6a7e7SGarlic Tseng 82943a6a7e7SGarlic Tseng static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s3[] = { 83043a6a7e7SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S3 Out Switch", 83143a6a7e7SGarlic Tseng PWR2_TOP_CON, 18, 1, 0), 83243a6a7e7SGarlic Tseng }; 83343a6a7e7SGarlic Tseng 83443a6a7e7SGarlic Tseng static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { 83543a6a7e7SGarlic Tseng /* inter-connections */ 83643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), 83743a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0), 83843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I02", SND_SOC_NOPM, 0, 0, mt2701_afe_i02_mix, 83943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_i02_mix)), 84043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), 84143a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0), 84243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0), 84343a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0), 84443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0), 84543a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0), 84643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), 84743a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), 84843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0), 84943a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0), 85043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I35", SND_SOC_NOPM, 0, 0, NULL, 0), 85143a6a7e7SGarlic Tseng 85243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0, mt2701_afe_o00_mix, 85343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o00_mix)), 85443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0, mt2701_afe_o01_mix, 85543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o01_mix)), 85643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O02", SND_SOC_NOPM, 0, 0, mt2701_afe_o02_mix, 85743a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o02_mix)), 85843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, mt2701_afe_o03_mix, 85943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o03_mix)), 86043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0, mt2701_afe_o14_mix, 86143a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o14_mix)), 86243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0, mt2701_afe_o15_mix, 86343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o15_mix)), 86443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0, mt2701_afe_o16_mix, 86543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o16_mix)), 86643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0, mt2701_afe_o17_mix, 86743a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o17_mix)), 86843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0, mt2701_afe_o18_mix, 86943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o18_mix)), 87043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0, mt2701_afe_o19_mix, 87143a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o19_mix)), 87243a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0, mt2701_afe_o20_mix, 87343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o20_mix)), 87443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0, mt2701_afe_o21_mix, 87543a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o21_mix)), 87643a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0, mt2701_afe_o22_mix, 87743a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o22_mix)), 87843a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0, mt2701_afe_o31_mix, 87943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_o31_mix)), 88043a6a7e7SGarlic Tseng 88143a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I12I13", SND_SOC_NOPM, 0, 0, 88243a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s0, 88343a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s0)), 88443a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I14I15", SND_SOC_NOPM, 0, 0, 88543a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s1, 88643a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s1)), 88743a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I16I17", SND_SOC_NOPM, 0, 0, 88843a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s2, 88943a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s2)), 89043a6a7e7SGarlic Tseng SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0, 89143a6a7e7SGarlic Tseng mt2701_afe_multi_ch_out_i2s3, 89243a6a7e7SGarlic Tseng ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)), 89343a6a7e7SGarlic Tseng }; 89443a6a7e7SGarlic Tseng 89543a6a7e7SGarlic Tseng static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { 89643a6a7e7SGarlic Tseng {"I12", NULL, "DL1"}, 89743a6a7e7SGarlic Tseng {"I13", NULL, "DL1"}, 89843a6a7e7SGarlic Tseng {"I35", NULL, "DLBT"}, 89943a6a7e7SGarlic Tseng 90043a6a7e7SGarlic Tseng {"I2S0 Playback", NULL, "O15"}, 90143a6a7e7SGarlic Tseng {"I2S0 Playback", NULL, "O16"}, 90243a6a7e7SGarlic Tseng {"I2S1 Playback", NULL, "O17"}, 90343a6a7e7SGarlic Tseng {"I2S1 Playback", NULL, "O18"}, 90443a6a7e7SGarlic Tseng {"I2S2 Playback", NULL, "O19"}, 90543a6a7e7SGarlic Tseng {"I2S2 Playback", NULL, "O20"}, 90643a6a7e7SGarlic Tseng {"I2S3 Playback", NULL, "O21"}, 90743a6a7e7SGarlic Tseng {"I2S3 Playback", NULL, "O22"}, 90843a6a7e7SGarlic Tseng {"BT Playback", NULL, "O31"}, 90943a6a7e7SGarlic Tseng 91043a6a7e7SGarlic Tseng {"UL1", NULL, "O00"}, 91143a6a7e7SGarlic Tseng {"UL1", NULL, "O01"}, 91243a6a7e7SGarlic Tseng {"UL2", NULL, "O02"}, 91343a6a7e7SGarlic Tseng {"UL2", NULL, "O03"}, 91443a6a7e7SGarlic Tseng {"ULBT", NULL, "O14"}, 91543a6a7e7SGarlic Tseng 91643a6a7e7SGarlic Tseng {"I00", NULL, "I2S0 Capture"}, 91743a6a7e7SGarlic Tseng {"I01", NULL, "I2S0 Capture"}, 91843a6a7e7SGarlic Tseng {"I02", NULL, "I2S1 Capture"}, 91943a6a7e7SGarlic Tseng {"I03", NULL, "I2S1 Capture"}, 92043a6a7e7SGarlic Tseng /* I02,03 link to UL2, also need to open I2S0 */ 92143a6a7e7SGarlic Tseng {"I02", "I2S0 Switch", "I2S0 Capture"}, 92243a6a7e7SGarlic Tseng 92343a6a7e7SGarlic Tseng {"I26", NULL, "BT Capture"}, 92443a6a7e7SGarlic Tseng 925600b2fd4SRyder Lee {"I12I13", "Multich I2S0 Out Switch", "DLM"}, 926600b2fd4SRyder Lee {"I14I15", "Multich I2S1 Out Switch", "DLM"}, 927600b2fd4SRyder Lee {"I16I17", "Multich I2S2 Out Switch", "DLM"}, 928600b2fd4SRyder Lee {"I18I19", "Multich I2S3 Out Switch", "DLM"}, 92943a6a7e7SGarlic Tseng 93043a6a7e7SGarlic Tseng { "I12", NULL, "I12I13" }, 93143a6a7e7SGarlic Tseng { "I13", NULL, "I12I13" }, 93243a6a7e7SGarlic Tseng { "I14", NULL, "I14I15" }, 93343a6a7e7SGarlic Tseng { "I15", NULL, "I14I15" }, 93443a6a7e7SGarlic Tseng { "I16", NULL, "I16I17" }, 93543a6a7e7SGarlic Tseng { "I17", NULL, "I16I17" }, 93643a6a7e7SGarlic Tseng { "I18", NULL, "I18I19" }, 93743a6a7e7SGarlic Tseng { "I19", NULL, "I18I19" }, 93843a6a7e7SGarlic Tseng 93943a6a7e7SGarlic Tseng { "O00", "I00 Switch", "I00" }, 94043a6a7e7SGarlic Tseng { "O01", "I01 Switch", "I01" }, 94143a6a7e7SGarlic Tseng { "O02", "I02 Switch", "I02" }, 94243a6a7e7SGarlic Tseng { "O03", "I03 Switch", "I03" }, 94343a6a7e7SGarlic Tseng { "O14", "I26 Switch", "I26" }, 94443a6a7e7SGarlic Tseng { "O15", "I12 Switch", "I12" }, 94543a6a7e7SGarlic Tseng { "O16", "I13 Switch", "I13" }, 94643a6a7e7SGarlic Tseng { "O17", "I14 Switch", "I14" }, 94743a6a7e7SGarlic Tseng { "O18", "I15 Switch", "I15" }, 94843a6a7e7SGarlic Tseng { "O19", "I16 Switch", "I16" }, 94943a6a7e7SGarlic Tseng { "O20", "I17 Switch", "I17" }, 95043a6a7e7SGarlic Tseng { "O21", "I18 Switch", "I18" }, 95143a6a7e7SGarlic Tseng { "O22", "I19 Switch", "I19" }, 95243a6a7e7SGarlic Tseng { "O31", "I35 Switch", "I35" }, 95343a6a7e7SGarlic Tseng }; 95443a6a7e7SGarlic Tseng 95510abdc7cSRyder Lee static int mt2701_afe_pcm_probe(struct snd_soc_component *component) 95610abdc7cSRyder Lee { 95710abdc7cSRyder Lee struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 95810abdc7cSRyder Lee 95910abdc7cSRyder Lee snd_soc_component_init_regmap(component, afe->regmap); 96010abdc7cSRyder Lee 96110abdc7cSRyder Lee return 0; 96210abdc7cSRyder Lee } 96310abdc7cSRyder Lee 96443a6a7e7SGarlic Tseng static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = { 96510abdc7cSRyder Lee .probe = mt2701_afe_pcm_probe, 96643a6a7e7SGarlic Tseng .name = "mt2701-afe-pcm-dai", 96743a6a7e7SGarlic Tseng .dapm_widgets = mt2701_afe_pcm_widgets, 96843a6a7e7SGarlic Tseng .num_dapm_widgets = ARRAY_SIZE(mt2701_afe_pcm_widgets), 96943a6a7e7SGarlic Tseng .dapm_routes = mt2701_afe_pcm_routes, 97043a6a7e7SGarlic Tseng .num_dapm_routes = ARRAY_SIZE(mt2701_afe_pcm_routes), 9717ec6b431SKuninori Morimoto .suspend = mtk_afe_suspend, 9727ec6b431SKuninori Morimoto .resume = mtk_afe_resume, 97343a6a7e7SGarlic Tseng }; 97443a6a7e7SGarlic Tseng 975d9cdc133SPierre-Louis Bossart static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = { 97643a6a7e7SGarlic Tseng { 97743a6a7e7SGarlic Tseng .name = "DL1", 97843a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL1, 97943a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL1_BASE, 98043a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL1_CUR, 98143a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 98243a6a7e7SGarlic Tseng .fs_shift = 0, 98343a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 98443a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 98543a6a7e7SGarlic Tseng .mono_shift = 16, 98643a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 98743a6a7e7SGarlic Tseng .enable_shift = 1, 98843a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 98943a6a7e7SGarlic Tseng .hd_shift = 0, 99043a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 99143a6a7e7SGarlic Tseng .agent_disable_shift = 6, 99243a6a7e7SGarlic Tseng .msb_reg = -1, 99343a6a7e7SGarlic Tseng }, 99443a6a7e7SGarlic Tseng { 99543a6a7e7SGarlic Tseng .name = "DL2", 99643a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL2, 99743a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL2_BASE, 99843a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL2_CUR, 99943a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 100043a6a7e7SGarlic Tseng .fs_shift = 5, 100143a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 100243a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 100343a6a7e7SGarlic Tseng .mono_shift = 17, 100443a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 100543a6a7e7SGarlic Tseng .enable_shift = 2, 100643a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 100743a6a7e7SGarlic Tseng .hd_shift = 2, 100843a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 100943a6a7e7SGarlic Tseng .agent_disable_shift = 7, 101043a6a7e7SGarlic Tseng .msb_reg = -1, 101143a6a7e7SGarlic Tseng }, 101243a6a7e7SGarlic Tseng { 101343a6a7e7SGarlic Tseng .name = "DL3", 101443a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL3, 101543a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL3_BASE, 101643a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL3_CUR, 101743a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 101843a6a7e7SGarlic Tseng .fs_shift = 10, 101943a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 102043a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 102143a6a7e7SGarlic Tseng .mono_shift = 18, 102243a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 102343a6a7e7SGarlic Tseng .enable_shift = 3, 102443a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 102543a6a7e7SGarlic Tseng .hd_shift = 4, 102643a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 102743a6a7e7SGarlic Tseng .agent_disable_shift = 8, 102843a6a7e7SGarlic Tseng .msb_reg = -1, 102943a6a7e7SGarlic Tseng }, 103043a6a7e7SGarlic Tseng { 103143a6a7e7SGarlic Tseng .name = "DL4", 103243a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL4, 103343a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL4_BASE, 103443a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL4_CUR, 103543a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 103643a6a7e7SGarlic Tseng .fs_shift = 15, 103743a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 103843a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 103943a6a7e7SGarlic Tseng .mono_shift = 19, 104043a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 104143a6a7e7SGarlic Tseng .enable_shift = 4, 104243a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 104343a6a7e7SGarlic Tseng .hd_shift = 6, 104443a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 104543a6a7e7SGarlic Tseng .agent_disable_shift = 9, 104643a6a7e7SGarlic Tseng .msb_reg = -1, 104743a6a7e7SGarlic Tseng }, 104843a6a7e7SGarlic Tseng { 104943a6a7e7SGarlic Tseng .name = "DL5", 105043a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DL5, 105143a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DL5_BASE, 105243a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DL5_CUR, 105343a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 105443a6a7e7SGarlic Tseng .fs_shift = 20, 105543a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 105643a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 105743a6a7e7SGarlic Tseng .mono_shift = 20, 105843a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 105943a6a7e7SGarlic Tseng .enable_shift = 5, 106043a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 106143a6a7e7SGarlic Tseng .hd_shift = 8, 106243a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 106343a6a7e7SGarlic Tseng .agent_disable_shift = 10, 106443a6a7e7SGarlic Tseng .msb_reg = -1, 106543a6a7e7SGarlic Tseng }, 106643a6a7e7SGarlic Tseng { 106743a6a7e7SGarlic Tseng .name = "DLM", 106843a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLM, 106943a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DLMCH_BASE, 107043a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DLMCH_CUR, 107143a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON1, 107243a6a7e7SGarlic Tseng .fs_shift = 0, 107343a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 107443a6a7e7SGarlic Tseng .mono_reg = -1, 107543a6a7e7SGarlic Tseng .mono_shift = -1, 107643a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 107743a6a7e7SGarlic Tseng .enable_shift = 7, 107843a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_PBUF_SIZE, 107943a6a7e7SGarlic Tseng .hd_shift = 28, 108043a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 108143a6a7e7SGarlic Tseng .agent_disable_shift = 12, 108243a6a7e7SGarlic Tseng .msb_reg = -1, 108343a6a7e7SGarlic Tseng }, 108443a6a7e7SGarlic Tseng { 108543a6a7e7SGarlic Tseng .name = "UL1", 108643a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL1, 108743a6a7e7SGarlic Tseng .reg_ofs_base = AFE_VUL_BASE, 108843a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_VUL_CUR, 108943a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 109043a6a7e7SGarlic Tseng .fs_shift = 0, 109143a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 109243a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 109343a6a7e7SGarlic Tseng .mono_shift = 0, 109443a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 109543a6a7e7SGarlic Tseng .enable_shift = 10, 109643a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 109743a6a7e7SGarlic Tseng .hd_shift = 0, 109843a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 109943a6a7e7SGarlic Tseng .agent_disable_shift = 0, 110043a6a7e7SGarlic Tseng .msb_reg = -1, 110143a6a7e7SGarlic Tseng }, 110243a6a7e7SGarlic Tseng { 110343a6a7e7SGarlic Tseng .name = "UL2", 110443a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL2, 110543a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL2_BASE, 110643a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL2_CUR, 110743a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 110843a6a7e7SGarlic Tseng .fs_shift = 5, 110943a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 111043a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 111143a6a7e7SGarlic Tseng .mono_shift = 2, 111243a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 111343a6a7e7SGarlic Tseng .enable_shift = 11, 111443a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 111543a6a7e7SGarlic Tseng .hd_shift = 2, 111643a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 111743a6a7e7SGarlic Tseng .agent_disable_shift = 1, 111843a6a7e7SGarlic Tseng .msb_reg = -1, 111943a6a7e7SGarlic Tseng }, 112043a6a7e7SGarlic Tseng { 112143a6a7e7SGarlic Tseng .name = "UL3", 112243a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL3, 112343a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL3_BASE, 112443a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL3_CUR, 112543a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 112643a6a7e7SGarlic Tseng .fs_shift = 10, 112743a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 112843a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 112943a6a7e7SGarlic Tseng .mono_shift = 4, 113043a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 113143a6a7e7SGarlic Tseng .enable_shift = 12, 113243a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 113343a6a7e7SGarlic Tseng .hd_shift = 0, 113443a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 113543a6a7e7SGarlic Tseng .agent_disable_shift = 2, 113643a6a7e7SGarlic Tseng .msb_reg = -1, 113743a6a7e7SGarlic Tseng }, 113843a6a7e7SGarlic Tseng { 113943a6a7e7SGarlic Tseng .name = "UL4", 114043a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL4, 114143a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL4_BASE, 114243a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL4_CUR, 114343a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 114443a6a7e7SGarlic Tseng .fs_shift = 15, 114543a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 114643a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 114743a6a7e7SGarlic Tseng .mono_shift = 6, 114843a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 114943a6a7e7SGarlic Tseng .enable_shift = 13, 115043a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 115143a6a7e7SGarlic Tseng .hd_shift = 6, 115243a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 115343a6a7e7SGarlic Tseng .agent_disable_shift = 3, 115443a6a7e7SGarlic Tseng .msb_reg = -1, 115543a6a7e7SGarlic Tseng }, 115643a6a7e7SGarlic Tseng { 115743a6a7e7SGarlic Tseng .name = "UL5", 115843a6a7e7SGarlic Tseng .id = MT2701_MEMIF_UL5, 115943a6a7e7SGarlic Tseng .reg_ofs_base = AFE_UL5_BASE, 116043a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_UL5_CUR, 116143a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 116243a6a7e7SGarlic Tseng .fs_shift = 20, 116343a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON4, 116443a6a7e7SGarlic Tseng .mono_shift = 8, 116543a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 116643a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 116743a6a7e7SGarlic Tseng .enable_shift = 14, 116843a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 116943a6a7e7SGarlic Tseng .hd_shift = 8, 117043a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 117143a6a7e7SGarlic Tseng .agent_disable_shift = 4, 117243a6a7e7SGarlic Tseng .msb_reg = -1, 117343a6a7e7SGarlic Tseng }, 117443a6a7e7SGarlic Tseng { 117543a6a7e7SGarlic Tseng .name = "DLBT", 117643a6a7e7SGarlic Tseng .id = MT2701_MEMIF_DLBT, 117743a6a7e7SGarlic Tseng .reg_ofs_base = AFE_ARB1_BASE, 117843a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_ARB1_CUR, 117943a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON3, 118043a6a7e7SGarlic Tseng .fs_shift = 10, 118143a6a7e7SGarlic Tseng .fs_maskbit = 0x1f, 118243a6a7e7SGarlic Tseng .mono_reg = AFE_DAC_CON3, 118343a6a7e7SGarlic Tseng .mono_shift = 22, 118443a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 118543a6a7e7SGarlic Tseng .enable_shift = 8, 118643a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON0, 118743a6a7e7SGarlic Tseng .hd_shift = 14, 118843a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 118943a6a7e7SGarlic Tseng .agent_disable_shift = 13, 119043a6a7e7SGarlic Tseng .msb_reg = -1, 119143a6a7e7SGarlic Tseng }, 119243a6a7e7SGarlic Tseng { 119343a6a7e7SGarlic Tseng .name = "ULBT", 119443a6a7e7SGarlic Tseng .id = MT2701_MEMIF_ULBT, 119543a6a7e7SGarlic Tseng .reg_ofs_base = AFE_DAI_BASE, 119643a6a7e7SGarlic Tseng .reg_ofs_cur = AFE_DAI_CUR, 119743a6a7e7SGarlic Tseng .fs_reg = AFE_DAC_CON2, 119843a6a7e7SGarlic Tseng .fs_shift = 30, 119943a6a7e7SGarlic Tseng .fs_maskbit = 0x1, 120043a6a7e7SGarlic Tseng .mono_reg = -1, 120143a6a7e7SGarlic Tseng .mono_shift = -1, 120243a6a7e7SGarlic Tseng .enable_reg = AFE_DAC_CON0, 120343a6a7e7SGarlic Tseng .enable_shift = 17, 120443a6a7e7SGarlic Tseng .hd_reg = AFE_MEMIF_HD_CON1, 120543a6a7e7SGarlic Tseng .hd_shift = 20, 120643a6a7e7SGarlic Tseng .agent_disable_reg = AUDIO_TOP_CON5, 120743a6a7e7SGarlic Tseng .agent_disable_shift = 16, 120843a6a7e7SGarlic Tseng .msb_reg = -1, 120943a6a7e7SGarlic Tseng }, 121043a6a7e7SGarlic Tseng }; 121143a6a7e7SGarlic Tseng 121243a6a7e7SGarlic Tseng static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = { 121343a6a7e7SGarlic Tseng { 121443a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ1, 121543a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ1_CON, 121643a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 121743a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 121843a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ1_CON, 121943a6a7e7SGarlic Tseng .irq_fs_shift = 24, 122043a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 122143a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ1_CON, 122243a6a7e7SGarlic Tseng .irq_en_shift = 31, 122343a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 122443a6a7e7SGarlic Tseng .irq_clr_shift = 0, 122543a6a7e7SGarlic Tseng }, 122643a6a7e7SGarlic Tseng { 122743a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ2, 122843a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ2_CON, 122943a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 123043a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 123143a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ2_CON, 123243a6a7e7SGarlic Tseng .irq_fs_shift = 24, 123343a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 123443a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ2_CON, 123543a6a7e7SGarlic Tseng .irq_en_shift = 31, 123643a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 123743a6a7e7SGarlic Tseng .irq_clr_shift = 1, 123843a6a7e7SGarlic Tseng }, 123943a6a7e7SGarlic Tseng { 124043a6a7e7SGarlic Tseng .id = MT2701_IRQ_ASYS_IRQ3, 124143a6a7e7SGarlic Tseng .irq_cnt_reg = ASYS_IRQ3_CON, 124243a6a7e7SGarlic Tseng .irq_cnt_shift = 0, 124343a6a7e7SGarlic Tseng .irq_cnt_maskbit = 0xffffff, 124443a6a7e7SGarlic Tseng .irq_fs_reg = ASYS_IRQ3_CON, 124543a6a7e7SGarlic Tseng .irq_fs_shift = 24, 124643a6a7e7SGarlic Tseng .irq_fs_maskbit = 0x1f, 124743a6a7e7SGarlic Tseng .irq_en_reg = ASYS_IRQ3_CON, 124843a6a7e7SGarlic Tseng .irq_en_shift = 31, 124943a6a7e7SGarlic Tseng .irq_clr_reg = ASYS_IRQ_CLR, 125043a6a7e7SGarlic Tseng .irq_clr_shift = 2, 125143a6a7e7SGarlic Tseng } 125243a6a7e7SGarlic Tseng }; 125343a6a7e7SGarlic Tseng 1254ab7b4ee9SRyder Lee static const struct mt2701_i2s_data mt2701_i2s_data[][2] = { 125543a6a7e7SGarlic Tseng { 1256ab7b4ee9SRyder Lee { ASYS_I2SO1_CON, 0, 0x1f }, 1257ab7b4ee9SRyder Lee { ASYS_I2SIN1_CON, 0, 0x1f }, 125843a6a7e7SGarlic Tseng }, 125943a6a7e7SGarlic Tseng { 1260ab7b4ee9SRyder Lee { ASYS_I2SO2_CON, 5, 0x1f }, 1261ab7b4ee9SRyder Lee { ASYS_I2SIN2_CON, 5, 0x1f }, 126243a6a7e7SGarlic Tseng }, 126343a6a7e7SGarlic Tseng { 1264ab7b4ee9SRyder Lee { ASYS_I2SO3_CON, 10, 0x1f }, 1265ab7b4ee9SRyder Lee { ASYS_I2SIN3_CON, 10, 0x1f }, 126643a6a7e7SGarlic Tseng }, 126743a6a7e7SGarlic Tseng { 1268ab7b4ee9SRyder Lee { ASYS_I2SO4_CON, 15, 0x1f }, 1269ab7b4ee9SRyder Lee { ASYS_I2SIN4_CON, 15, 0x1f }, 127043a6a7e7SGarlic Tseng }, 1271ab7b4ee9SRyder Lee /* TODO - extend control registers supported by newer SoCs */ 127243a6a7e7SGarlic Tseng }; 127343a6a7e7SGarlic Tseng 127443a6a7e7SGarlic Tseng static irqreturn_t mt2701_asys_isr(int irq_id, void *dev) 127543a6a7e7SGarlic Tseng { 127643a6a7e7SGarlic Tseng int id; 127743a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev; 127843a6a7e7SGarlic Tseng struct mtk_base_afe_memif *memif; 127943a6a7e7SGarlic Tseng struct mtk_base_afe_irq *irq; 128043a6a7e7SGarlic Tseng u32 status; 128143a6a7e7SGarlic Tseng 128243a6a7e7SGarlic Tseng regmap_read(afe->regmap, ASYS_IRQ_STATUS, &status); 128343a6a7e7SGarlic Tseng regmap_write(afe->regmap, ASYS_IRQ_CLR, status); 128443a6a7e7SGarlic Tseng 128543a6a7e7SGarlic Tseng for (id = 0; id < MT2701_MEMIF_NUM; ++id) { 128643a6a7e7SGarlic Tseng memif = &afe->memif[id]; 128743a6a7e7SGarlic Tseng if (memif->irq_usage < 0) 128843a6a7e7SGarlic Tseng continue; 1289e4b31b81SRyder Lee 129043a6a7e7SGarlic Tseng irq = &afe->irqs[memif->irq_usage]; 1291e4b31b81SRyder Lee if (status & 1 << irq->irq_data->irq_clr_shift) 129243a6a7e7SGarlic Tseng snd_pcm_period_elapsed(memif->substream); 129343a6a7e7SGarlic Tseng } 1294e4b31b81SRyder Lee 129543a6a7e7SGarlic Tseng return IRQ_HANDLED; 129643a6a7e7SGarlic Tseng } 129743a6a7e7SGarlic Tseng 129843a6a7e7SGarlic Tseng static int mt2701_afe_runtime_suspend(struct device *dev) 129943a6a7e7SGarlic Tseng { 130043a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev_get_drvdata(dev); 130143a6a7e7SGarlic Tseng 1302d8d99d8eSRyder Lee return mt2701_afe_disable_clock(afe); 130343a6a7e7SGarlic Tseng } 130443a6a7e7SGarlic Tseng 130543a6a7e7SGarlic Tseng static int mt2701_afe_runtime_resume(struct device *dev) 130643a6a7e7SGarlic Tseng { 130743a6a7e7SGarlic Tseng struct mtk_base_afe *afe = dev_get_drvdata(dev); 130843a6a7e7SGarlic Tseng 130943a6a7e7SGarlic Tseng return mt2701_afe_enable_clock(afe); 131043a6a7e7SGarlic Tseng } 131143a6a7e7SGarlic Tseng 1312dc2a17f4SRyder Lee static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) 1313dc2a17f4SRyder Lee { 131443a6a7e7SGarlic Tseng struct mtk_base_afe *afe; 131543a6a7e7SGarlic Tseng struct mt2701_afe_private *afe_priv; 131643a6a7e7SGarlic Tseng struct device *dev; 1317f6c1626eSRyder Lee int i, irq_id, ret; 131843a6a7e7SGarlic Tseng 131943a6a7e7SGarlic Tseng afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); 132043a6a7e7SGarlic Tseng if (!afe) 132143a6a7e7SGarlic Tseng return -ENOMEM; 1322600b2fd4SRyder Lee 1323b02c5cc7SDan Carpenter afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), 1324b02c5cc7SDan Carpenter GFP_KERNEL); 1325b02c5cc7SDan Carpenter if (!afe->platform_priv) 1326b02c5cc7SDan Carpenter return -ENOMEM; 132743a6a7e7SGarlic Tseng 1328600b2fd4SRyder Lee afe_priv = afe->platform_priv; 1329bfdc56e5SRyder Lee afe_priv->soc = of_device_get_match_data(&pdev->dev); 133043a6a7e7SGarlic Tseng afe->dev = &pdev->dev; 133143a6a7e7SGarlic Tseng dev = afe->dev; 133243a6a7e7SGarlic Tseng 1333a86854d0SKees Cook afe_priv->i2s_path = devm_kcalloc(dev, 1334a86854d0SKees Cook afe_priv->soc->i2s_num, 1335bfdc56e5SRyder Lee sizeof(struct mt2701_i2s_path), 1336bfdc56e5SRyder Lee GFP_KERNEL); 1337bfdc56e5SRyder Lee if (!afe_priv->i2s_path) 1338bfdc56e5SRyder Lee return -ENOMEM; 1339bfdc56e5SRyder Lee 1340f6c1626eSRyder Lee irq_id = platform_get_irq_byname(pdev, "asys"); 1341cf9441adSStephen Boyd if (irq_id < 0) 1342f6c1626eSRyder Lee return irq_id; 1343f6c1626eSRyder Lee 134443a6a7e7SGarlic Tseng ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, 134543a6a7e7SGarlic Tseng IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); 134643a6a7e7SGarlic Tseng if (ret) { 134743a6a7e7SGarlic Tseng dev_err(dev, "could not request_irq for asys-isr\n"); 134843a6a7e7SGarlic Tseng return ret; 134943a6a7e7SGarlic Tseng } 135043a6a7e7SGarlic Tseng 1351dfa3cbb8SRyder Lee afe->regmap = syscon_node_to_regmap(dev->parent->of_node); 13523e8052d9SWei Yongjun if (IS_ERR(afe->regmap)) { 1353dfa3cbb8SRyder Lee dev_err(dev, "could not get regmap from parent\n"); 13543e8052d9SWei Yongjun return PTR_ERR(afe->regmap); 1355dfa3cbb8SRyder Lee } 135643a6a7e7SGarlic Tseng 135743a6a7e7SGarlic Tseng mutex_init(&afe->irq_alloc_lock); 135843a6a7e7SGarlic Tseng 135943a6a7e7SGarlic Tseng /* memif initialize */ 136043a6a7e7SGarlic Tseng afe->memif_size = MT2701_MEMIF_NUM; 136143a6a7e7SGarlic Tseng afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), 136243a6a7e7SGarlic Tseng GFP_KERNEL); 136343a6a7e7SGarlic Tseng if (!afe->memif) 136443a6a7e7SGarlic Tseng return -ENOMEM; 136543a6a7e7SGarlic Tseng 136643a6a7e7SGarlic Tseng for (i = 0; i < afe->memif_size; i++) { 1367d9cdc133SPierre-Louis Bossart afe->memif[i].data = &memif_data_array[i]; 136843a6a7e7SGarlic Tseng afe->memif[i].irq_usage = -1; 136943a6a7e7SGarlic Tseng } 137043a6a7e7SGarlic Tseng 137143a6a7e7SGarlic Tseng /* irq initialize */ 137243a6a7e7SGarlic Tseng afe->irqs_size = MT2701_IRQ_ASYS_END; 137343a6a7e7SGarlic Tseng afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), 137443a6a7e7SGarlic Tseng GFP_KERNEL); 137543a6a7e7SGarlic Tseng if (!afe->irqs) 137643a6a7e7SGarlic Tseng return -ENOMEM; 137743a6a7e7SGarlic Tseng 137843a6a7e7SGarlic Tseng for (i = 0; i < afe->irqs_size; i++) 137943a6a7e7SGarlic Tseng afe->irqs[i].irq_data = &irq_data[i]; 138043a6a7e7SGarlic Tseng 138143a6a7e7SGarlic Tseng /* I2S initialize */ 1382bfdc56e5SRyder Lee for (i = 0; i < afe_priv->soc->i2s_num; i++) { 1383ab7b4ee9SRyder Lee afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_PLAYBACK] = 1384ab7b4ee9SRyder Lee &mt2701_i2s_data[i][SNDRV_PCM_STREAM_PLAYBACK]; 1385ab7b4ee9SRyder Lee afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_CAPTURE] = 1386ab7b4ee9SRyder Lee &mt2701_i2s_data[i][SNDRV_PCM_STREAM_CAPTURE]; 138743a6a7e7SGarlic Tseng } 138843a6a7e7SGarlic Tseng 138943a6a7e7SGarlic Tseng afe->mtk_afe_hardware = &mt2701_afe_hardware; 139043a6a7e7SGarlic Tseng afe->memif_fs = mt2701_memif_fs; 139143a6a7e7SGarlic Tseng afe->irq_fs = mt2701_irq_fs; 139243a6a7e7SGarlic Tseng afe->reg_back_up_list = mt2701_afe_backup_list; 139343a6a7e7SGarlic Tseng afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list); 139443a6a7e7SGarlic Tseng afe->runtime_resume = mt2701_afe_runtime_resume; 139543a6a7e7SGarlic Tseng afe->runtime_suspend = mt2701_afe_runtime_suspend; 139643a6a7e7SGarlic Tseng 139743a6a7e7SGarlic Tseng /* initial audio related clock */ 139843a6a7e7SGarlic Tseng ret = mt2701_init_clock(afe); 139943a6a7e7SGarlic Tseng if (ret) { 140043a6a7e7SGarlic Tseng dev_err(dev, "init clock error\n"); 1401dc2a17f4SRyder Lee return ret; 140243a6a7e7SGarlic Tseng } 140343a6a7e7SGarlic Tseng 140443a6a7e7SGarlic Tseng platform_set_drvdata(pdev, afe); 140543a6a7e7SGarlic Tseng 1406dd6bb9b1SRyder Lee pm_runtime_enable(dev); 1407dd6bb9b1SRyder Lee if (!pm_runtime_enabled(dev)) { 1408dd6bb9b1SRyder Lee ret = mt2701_afe_runtime_resume(dev); 1409dd6bb9b1SRyder Lee if (ret) 1410dd6bb9b1SRyder Lee goto err_pm_disable; 1411dd6bb9b1SRyder Lee } 1412dd6bb9b1SRyder Lee pm_runtime_get_sync(dev); 1413dd6bb9b1SRyder Lee 1414f1b5bf07SKuninori Morimoto ret = devm_snd_soc_register_component(&pdev->dev, &mtk_afe_pcm_platform, 1415f1b5bf07SKuninori Morimoto NULL, 0); 141643a6a7e7SGarlic Tseng if (ret) { 141743a6a7e7SGarlic Tseng dev_warn(dev, "err_platform\n"); 141843a6a7e7SGarlic Tseng goto err_platform; 141943a6a7e7SGarlic Tseng } 142043a6a7e7SGarlic Tseng 142110abdc7cSRyder Lee ret = devm_snd_soc_register_component(&pdev->dev, 142210abdc7cSRyder Lee &mt2701_afe_pcm_dai_component, 142310abdc7cSRyder Lee mt2701_afe_pcm_dais, 142410abdc7cSRyder Lee ARRAY_SIZE(mt2701_afe_pcm_dais)); 142543a6a7e7SGarlic Tseng if (ret) { 142643a6a7e7SGarlic Tseng dev_warn(dev, "err_dai_component\n"); 1427f1b5bf07SKuninori Morimoto goto err_platform; 142843a6a7e7SGarlic Tseng } 142943a6a7e7SGarlic Tseng 143043a6a7e7SGarlic Tseng return 0; 143143a6a7e7SGarlic Tseng 143243a6a7e7SGarlic Tseng err_platform: 1433dd6bb9b1SRyder Lee pm_runtime_put_sync(dev); 143443a6a7e7SGarlic Tseng err_pm_disable: 1435dd6bb9b1SRyder Lee pm_runtime_disable(dev); 143643a6a7e7SGarlic Tseng 143743a6a7e7SGarlic Tseng return ret; 143843a6a7e7SGarlic Tseng } 143943a6a7e7SGarlic Tseng 1440b3dff59eSUwe Kleine-König static void mt2701_afe_pcm_dev_remove(struct platform_device *pdev) 144143a6a7e7SGarlic Tseng { 1442dd6bb9b1SRyder Lee pm_runtime_put_sync(&pdev->dev); 144343a6a7e7SGarlic Tseng pm_runtime_disable(&pdev->dev); 144443a6a7e7SGarlic Tseng if (!pm_runtime_status_suspended(&pdev->dev)) 144543a6a7e7SGarlic Tseng mt2701_afe_runtime_suspend(&pdev->dev); 144643a6a7e7SGarlic Tseng } 144743a6a7e7SGarlic Tseng 1448bfdc56e5SRyder Lee static const struct mt2701_soc_variants mt2701_soc_v1 = { 1449bfdc56e5SRyder Lee .i2s_num = 4, 1450bfdc56e5SRyder Lee }; 1451bfdc56e5SRyder Lee 1452bfdc56e5SRyder Lee static const struct mt2701_soc_variants mt2701_soc_v2 = { 1453bfdc56e5SRyder Lee .has_one_heart_mode = true, 1454bfdc56e5SRyder Lee .i2s_num = 4, 1455bfdc56e5SRyder Lee }; 1456bfdc56e5SRyder Lee 145743a6a7e7SGarlic Tseng static const struct of_device_id mt2701_afe_pcm_dt_match[] = { 1458bfdc56e5SRyder Lee { .compatible = "mediatek,mt2701-audio", .data = &mt2701_soc_v1 }, 1459bfdc56e5SRyder Lee { .compatible = "mediatek,mt7622-audio", .data = &mt2701_soc_v2 }, 146043a6a7e7SGarlic Tseng {}, 146143a6a7e7SGarlic Tseng }; 146243a6a7e7SGarlic Tseng MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match); 146343a6a7e7SGarlic Tseng 146443a6a7e7SGarlic Tseng static const struct dev_pm_ops mt2701_afe_pm_ops = { 146543a6a7e7SGarlic Tseng SET_RUNTIME_PM_OPS(mt2701_afe_runtime_suspend, 146643a6a7e7SGarlic Tseng mt2701_afe_runtime_resume, NULL) 146743a6a7e7SGarlic Tseng }; 146843a6a7e7SGarlic Tseng 146943a6a7e7SGarlic Tseng static struct platform_driver mt2701_afe_pcm_driver = { 147043a6a7e7SGarlic Tseng .driver = { 147143a6a7e7SGarlic Tseng .name = "mt2701-audio", 147243a6a7e7SGarlic Tseng .of_match_table = mt2701_afe_pcm_dt_match, 147343a6a7e7SGarlic Tseng .pm = &mt2701_afe_pm_ops, 147443a6a7e7SGarlic Tseng }, 147543a6a7e7SGarlic Tseng .probe = mt2701_afe_pcm_dev_probe, 1476*130af75bSUwe Kleine-König .remove = mt2701_afe_pcm_dev_remove, 147743a6a7e7SGarlic Tseng }; 147843a6a7e7SGarlic Tseng 147943a6a7e7SGarlic Tseng module_platform_driver(mt2701_afe_pcm_driver); 148043a6a7e7SGarlic Tseng 148143a6a7e7SGarlic Tseng MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701"); 148243a6a7e7SGarlic Tseng MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); 148343a6a7e7SGarlic Tseng MODULE_LICENSE("GPL v2"); 1484