Path: blob/master/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* Mediatek ALSA SoC AFE platform driver for 27013*4* Copyright (c) 2016 MediaTek Inc.5* Author: Garlic Tseng <[email protected]>6* Ir Lian <[email protected]>7* Ryder Lee <[email protected]>8*/910#include <linux/delay.h>11#include <linux/module.h>12#include <linux/mfd/syscon.h>13#include <linux/of.h>14#include <linux/pm_runtime.h>1516#include "mt2701-afe-common.h"17#include "mt2701-afe-clock-ctrl.h"18#include "../common/mtk-afe-platform-driver.h"19#include "../common/mtk-afe-fe-dai.h"2021static const struct snd_pcm_hardware mt2701_afe_hardware = {22.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED23| SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID,24.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE25| SNDRV_PCM_FMTBIT_S32_LE,26.period_bytes_min = 1024,27.period_bytes_max = 1024 * 256,28.periods_min = 4,29.periods_max = 1024,30.buffer_bytes_max = 1024 * 1024,31.fifo_size = 0,32};3334struct mt2701_afe_rate {35unsigned int rate;36unsigned int regvalue;37};3839static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = {40{ .rate = 8000, .regvalue = 0 },41{ .rate = 12000, .regvalue = 1 },42{ .rate = 16000, .regvalue = 2 },43{ .rate = 24000, .regvalue = 3 },44{ .rate = 32000, .regvalue = 4 },45{ .rate = 48000, .regvalue = 5 },46{ .rate = 96000, .regvalue = 6 },47{ .rate = 192000, .regvalue = 7 },48{ .rate = 384000, .regvalue = 8 },49{ .rate = 7350, .regvalue = 16 },50{ .rate = 11025, .regvalue = 17 },51{ .rate = 14700, .regvalue = 18 },52{ .rate = 22050, .regvalue = 19 },53{ .rate = 29400, .regvalue = 20 },54{ .rate = 44100, .regvalue = 21 },55{ .rate = 88200, .regvalue = 22 },56{ .rate = 176400, .regvalue = 23 },57{ .rate = 352800, .regvalue = 24 },58};5960static const unsigned int mt2701_afe_backup_list[] = {61AUDIO_TOP_CON0,62AUDIO_TOP_CON4,63AUDIO_TOP_CON5,64ASYS_TOP_CON,65AFE_CONN0,66AFE_CONN1,67AFE_CONN2,68AFE_CONN3,69AFE_CONN15,70AFE_CONN16,71AFE_CONN17,72AFE_CONN18,73AFE_CONN19,74AFE_CONN20,75AFE_CONN21,76AFE_CONN22,77AFE_DAC_CON0,78AFE_MEMIF_PBUF_SIZE,79};8081static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num)82{83struct mt2701_afe_private *afe_priv = afe->platform_priv;84int val = num - MT2701_IO_I2S;8586if (val < 0 || val >= afe_priv->soc->i2s_num) {87dev_err(afe->dev, "%s, num not available, num %d, val %d\n",88__func__, num, val);89return -EINVAL;90}91return val;92}9394static int mt2701_afe_i2s_fs(unsigned int sample_rate)95{96int i;9798for (i = 0; i < ARRAY_SIZE(mt2701_afe_i2s_rates); i++)99if (mt2701_afe_i2s_rates[i].rate == sample_rate)100return mt2701_afe_i2s_rates[i].regvalue;101102return -EINVAL;103}104105static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream,106struct snd_soc_dai *dai)107{108struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);109struct mt2701_afe_private *afe_priv = afe->platform_priv;110int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);111bool mode = afe_priv->soc->has_one_heart_mode;112113if (i2s_num < 0)114return i2s_num;115116return mt2701_afe_enable_mclk(afe, mode ? 1 : i2s_num);117}118119static int mt2701_afe_i2s_path_disable(struct mtk_base_afe *afe,120struct mt2701_i2s_path *i2s_path,121int stream_dir)122{123const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir];124125if (--i2s_path->on[stream_dir] < 0)126i2s_path->on[stream_dir] = 0;127128if (i2s_path->on[stream_dir])129return 0;130131/* disable i2s */132regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,133ASYS_I2S_CON_I2S_EN, 0);134135mt2701_afe_disable_i2s(afe, i2s_path, stream_dir);136137return 0;138}139140static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,141struct snd_soc_dai *dai)142{143struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);144struct mt2701_afe_private *afe_priv = afe->platform_priv;145int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);146struct mt2701_i2s_path *i2s_path;147bool mode = afe_priv->soc->has_one_heart_mode;148149if (i2s_num < 0)150return;151152i2s_path = &afe_priv->i2s_path[i2s_num];153154if (i2s_path->occupied[substream->stream])155i2s_path->occupied[substream->stream] = 0;156else157goto exit;158159mt2701_afe_i2s_path_disable(afe, i2s_path, substream->stream);160161/* need to disable i2s-out path when disable i2s-in */162if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)163mt2701_afe_i2s_path_disable(afe, i2s_path, !substream->stream);164165exit:166/* disable mclk */167mt2701_afe_disable_mclk(afe, mode ? 1 : i2s_num);168}169170static int mt2701_i2s_path_enable(struct mtk_base_afe *afe,171struct mt2701_i2s_path *i2s_path,172int stream_dir, int rate)173{174const struct mt2701_i2s_data *i2s_data = i2s_path->i2s_data[stream_dir];175struct mt2701_afe_private *afe_priv = afe->platform_priv;176int reg, fs, w_len = 1; /* now we support bck 64bits only */177unsigned int mask, val;178179/* no need to enable if already done */180if (++i2s_path->on[stream_dir] != 1)181return 0;182183fs = mt2701_afe_i2s_fs(rate);184185mask = ASYS_I2S_CON_FS |186ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */187ASYS_I2S_CON_I2S_MODE |188ASYS_I2S_CON_WIDE_MODE;189190val = ASYS_I2S_CON_FS_SET(fs) |191ASYS_I2S_CON_I2S_MODE |192ASYS_I2S_CON_WIDE_MODE_SET(w_len);193194if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) {195mask |= ASYS_I2S_IN_PHASE_FIX;196val |= ASYS_I2S_IN_PHASE_FIX;197reg = ASMI_TIMING_CON1;198} else {199if (afe_priv->soc->has_one_heart_mode) {200mask |= ASYS_I2S_CON_ONE_HEART_MODE;201val |= ASYS_I2S_CON_ONE_HEART_MODE;202}203reg = ASMO_TIMING_CON1;204}205206regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val);207208regmap_update_bits(afe->regmap, reg,209i2s_data->i2s_asrc_fs_mask210<< i2s_data->i2s_asrc_fs_shift,211fs << i2s_data->i2s_asrc_fs_shift);212213/* enable i2s */214mt2701_afe_enable_i2s(afe, i2s_path, stream_dir);215216/* reset i2s hw status before enable */217regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,218ASYS_I2S_CON_RESET, ASYS_I2S_CON_RESET);219udelay(1);220regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,221ASYS_I2S_CON_RESET, 0);222udelay(1);223regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,224ASYS_I2S_CON_I2S_EN, ASYS_I2S_CON_I2S_EN);225return 0;226}227228static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream,229struct snd_soc_dai *dai)230{231struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);232struct mt2701_afe_private *afe_priv = afe->platform_priv;233int ret, i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);234struct mt2701_i2s_path *i2s_path;235bool mode = afe_priv->soc->has_one_heart_mode;236237if (i2s_num < 0)238return i2s_num;239240i2s_path = &afe_priv->i2s_path[i2s_num];241242if (i2s_path->occupied[substream->stream])243return -EBUSY;244245ret = mt2701_mclk_configuration(afe, mode ? 1 : i2s_num);246if (ret)247return ret;248249i2s_path->occupied[substream->stream] = 1;250251/* need to enable i2s-out path when enable i2s-in */252if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)253mt2701_i2s_path_enable(afe, i2s_path, !substream->stream,254substream->runtime->rate);255256mt2701_i2s_path_enable(afe, i2s_path, substream->stream,257substream->runtime->rate);258259return 0;260}261262static int mt2701_afe_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,263unsigned int freq, int dir)264{265struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);266struct mt2701_afe_private *afe_priv = afe->platform_priv;267int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);268bool mode = afe_priv->soc->has_one_heart_mode;269270if (i2s_num < 0)271return i2s_num;272273/* mclk */274if (dir == SND_SOC_CLOCK_IN) {275dev_warn(dai->dev, "The SoCs doesn't support mclk input\n");276return -EINVAL;277}278279afe_priv->i2s_path[mode ? 1 : i2s_num].mclk_rate = freq;280281return 0;282}283284static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,285struct snd_soc_dai *dai)286{287struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);288struct mt2701_afe_private *afe_priv = afe->platform_priv;289int ret;290291ret = mt2701_enable_btmrg_clk(afe);292if (ret)293return ret;294295afe_priv->mrg_enable[substream->stream] = 1;296297return 0;298}299300static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream,301struct snd_pcm_hw_params *params,302struct snd_soc_dai *dai)303{304struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);305int stream_fs;306u32 val, msk;307308stream_fs = params_rate(params);309310if (stream_fs != 8000 && stream_fs != 16000) {311dev_err(afe->dev, "unsupported rate %d\n", stream_fs);312return -EINVAL;313}314315regmap_update_bits(afe->regmap, AFE_MRGIF_CON,316AFE_MRGIF_CON_I2S_MODE_MASK,317AFE_MRGIF_CON_I2S_MODE_32K);318319val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY320| AFE_DAIBT_CON0_MRG_USE;321msk = val;322323if (stream_fs == 16000)324val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;325326msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN;327328regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val);329330regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,331AFE_DAIBT_CON0_DAIBT_EN,332AFE_DAIBT_CON0_DAIBT_EN);333regmap_update_bits(afe->regmap, AFE_MRGIF_CON,334AFE_MRGIF_CON_MRG_I2S_EN,335AFE_MRGIF_CON_MRG_I2S_EN);336regmap_update_bits(afe->regmap, AFE_MRGIF_CON,337AFE_MRGIF_CON_MRG_EN,338AFE_MRGIF_CON_MRG_EN);339return 0;340}341342static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,343struct snd_soc_dai *dai)344{345struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);346struct mt2701_afe_private *afe_priv = afe->platform_priv;347348/* if the other direction stream is not occupied */349if (!afe_priv->mrg_enable[!substream->stream]) {350regmap_update_bits(afe->regmap, AFE_DAIBT_CON0,351AFE_DAIBT_CON0_DAIBT_EN, 0);352regmap_update_bits(afe->regmap, AFE_MRGIF_CON,353AFE_MRGIF_CON_MRG_EN, 0);354regmap_update_bits(afe->regmap, AFE_MRGIF_CON,355AFE_MRGIF_CON_MRG_I2S_EN, 0);356mt2701_disable_btmrg_clk(afe);357}358359afe_priv->mrg_enable[substream->stream] = 0;360}361362static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream,363struct snd_soc_dai *dai)364{365struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);366struct mtk_base_afe_memif *memif_tmp;367int stream_dir = substream->stream;368369/* can't run single DL & DLM at the same time */370if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) {371memif_tmp = &afe->memif[MT2701_MEMIF_DLM];372if (memif_tmp->substream) {373dev_warn(afe->dev, "memif is not available");374return -EBUSY;375}376}377378return mtk_afe_fe_startup(substream, dai);379}380381static int mt2701_simple_fe_hw_params(struct snd_pcm_substream *substream,382struct snd_pcm_hw_params *params,383struct snd_soc_dai *dai)384{385struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);386int stream_dir = substream->stream;387388/* single DL use PAIR_INTERLEAVE */389if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)390regmap_update_bits(afe->regmap,391AFE_MEMIF_PBUF_SIZE,392AFE_MEMIF_PBUF_SIZE_DLM_MASK,393AFE_MEMIF_PBUF_SIZE_PAIR_INTERLEAVE);394395return mtk_afe_fe_hw_params(substream, params, dai);396}397398static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream,399struct snd_soc_dai *dai)400{401struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);402struct mtk_base_afe_memif *memif_tmp;403const struct mtk_base_memif_data *memif_data;404int i;405406for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) {407memif_tmp = &afe->memif[i];408if (memif_tmp->substream)409return -EBUSY;410}411412/* enable agent for all signal DL (due to hw design) */413for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) {414memif_data = afe->memif[i].data;415regmap_update_bits(afe->regmap,416memif_data->agent_disable_reg,4171 << memif_data->agent_disable_shift,4180 << memif_data->agent_disable_shift);419}420421return mtk_afe_fe_startup(substream, dai);422}423424static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream,425struct snd_soc_dai *dai)426{427struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);428const struct mtk_base_memif_data *memif_data;429int i;430431for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) {432memif_data = afe->memif[i].data;433regmap_update_bits(afe->regmap,434memif_data->agent_disable_reg,4351 << memif_data->agent_disable_shift,4361 << memif_data->agent_disable_shift);437}438439return mtk_afe_fe_shutdown(substream, dai);440}441442static int mt2701_dlm_fe_hw_params(struct snd_pcm_substream *substream,443struct snd_pcm_hw_params *params,444struct snd_soc_dai *dai)445{446struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);447int channels = params_channels(params);448449regmap_update_bits(afe->regmap,450AFE_MEMIF_PBUF_SIZE,451AFE_MEMIF_PBUF_SIZE_DLM_MASK,452AFE_MEMIF_PBUF_SIZE_FULL_INTERLEAVE);453regmap_update_bits(afe->regmap,454AFE_MEMIF_PBUF_SIZE,455AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK,456AFE_MEMIF_PBUF_SIZE_DLM_32BYTES);457regmap_update_bits(afe->regmap,458AFE_MEMIF_PBUF_SIZE,459AFE_MEMIF_PBUF_SIZE_DLM_CH_MASK,460AFE_MEMIF_PBUF_SIZE_DLM_CH(channels));461462return mtk_afe_fe_hw_params(substream, params, dai);463}464465static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream,466int cmd, struct snd_soc_dai *dai)467{468struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);469struct mtk_base_afe_memif *memif_tmp = &afe->memif[MT2701_MEMIF_DL1];470471switch (cmd) {472case SNDRV_PCM_TRIGGER_START:473case SNDRV_PCM_TRIGGER_RESUME:474regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg,4751 << memif_tmp->data->enable_shift,4761 << memif_tmp->data->enable_shift);477mtk_afe_fe_trigger(substream, cmd, dai);478return 0;479case SNDRV_PCM_TRIGGER_STOP:480case SNDRV_PCM_TRIGGER_SUSPEND:481mtk_afe_fe_trigger(substream, cmd, dai);482regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg,4831 << memif_tmp->data->enable_shift, 0);484485return 0;486default:487return -EINVAL;488}489}490491static int mt2701_memif_fs(struct snd_pcm_substream *substream,492unsigned int rate)493{494struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);495int fs;496497if (snd_soc_rtd_to_cpu(rtd, 0)->id != MT2701_MEMIF_ULBT)498fs = mt2701_afe_i2s_fs(rate);499else500fs = (rate == 16000 ? 1 : 0);501502return fs;503}504505static int mt2701_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)506{507return mt2701_afe_i2s_fs(rate);508}509510/* FE DAIs */511static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = {512.startup = mt2701_simple_fe_startup,513.shutdown = mtk_afe_fe_shutdown,514.hw_params = mt2701_simple_fe_hw_params,515.hw_free = mtk_afe_fe_hw_free,516.prepare = mtk_afe_fe_prepare,517.trigger = mtk_afe_fe_trigger,518};519520static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = {521.startup = mt2701_dlm_fe_startup,522.shutdown = mt2701_dlm_fe_shutdown,523.hw_params = mt2701_dlm_fe_hw_params,524.hw_free = mtk_afe_fe_hw_free,525.prepare = mtk_afe_fe_prepare,526.trigger = mt2701_dlm_fe_trigger,527};528529/* I2S BE DAIs */530static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = {531.startup = mt2701_afe_i2s_startup,532.shutdown = mt2701_afe_i2s_shutdown,533.prepare = mt2701_afe_i2s_prepare,534.set_sysclk = mt2701_afe_i2s_set_sysclk,535};536537/* MRG BE DAIs */538static const struct snd_soc_dai_ops mt2701_btmrg_ops = {539.startup = mt2701_btmrg_startup,540.shutdown = mt2701_btmrg_shutdown,541.hw_params = mt2701_btmrg_hw_params,542};543544static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {545/* FE DAIs: memory intefaces to CPU */546{547.name = "PCMO0",548.id = MT2701_MEMIF_DL1,549.playback = {550.stream_name = "DL1",551.channels_min = 1,552.channels_max = 2,553.rates = SNDRV_PCM_RATE_8000_192000,554.formats = (SNDRV_PCM_FMTBIT_S16_LE555| SNDRV_PCM_FMTBIT_S24_LE556| SNDRV_PCM_FMTBIT_S32_LE)557},558.ops = &mt2701_single_memif_dai_ops,559},560{561.name = "PCM_multi",562.id = MT2701_MEMIF_DLM,563.playback = {564.stream_name = "DLM",565.channels_min = 1,566.channels_max = 8,567.rates = SNDRV_PCM_RATE_8000_192000,568.formats = (SNDRV_PCM_FMTBIT_S16_LE569| SNDRV_PCM_FMTBIT_S24_LE570| SNDRV_PCM_FMTBIT_S32_LE)571572},573.ops = &mt2701_dlm_memif_dai_ops,574},575{576.name = "PCM0",577.id = MT2701_MEMIF_UL1,578.capture = {579.stream_name = "UL1",580.channels_min = 1,581.channels_max = 2,582.rates = SNDRV_PCM_RATE_8000_48000,583.formats = (SNDRV_PCM_FMTBIT_S16_LE584| SNDRV_PCM_FMTBIT_S24_LE585| SNDRV_PCM_FMTBIT_S32_LE)586},587.ops = &mt2701_single_memif_dai_ops,588},589{590.name = "PCM1",591.id = MT2701_MEMIF_UL2,592.capture = {593.stream_name = "UL2",594.channels_min = 1,595.channels_max = 2,596.rates = SNDRV_PCM_RATE_8000_192000,597.formats = (SNDRV_PCM_FMTBIT_S16_LE598| SNDRV_PCM_FMTBIT_S24_LE599| SNDRV_PCM_FMTBIT_S32_LE)600601},602.ops = &mt2701_single_memif_dai_ops,603},604{605.name = "PCM_BT_DL",606.id = MT2701_MEMIF_DLBT,607.playback = {608.stream_name = "DLBT",609.channels_min = 1,610.channels_max = 1,611.rates = (SNDRV_PCM_RATE_8000612| SNDRV_PCM_RATE_16000),613.formats = SNDRV_PCM_FMTBIT_S16_LE,614},615.ops = &mt2701_single_memif_dai_ops,616},617{618.name = "PCM_BT_UL",619.id = MT2701_MEMIF_ULBT,620.capture = {621.stream_name = "ULBT",622.channels_min = 1,623.channels_max = 1,624.rates = (SNDRV_PCM_RATE_8000625| SNDRV_PCM_RATE_16000),626.formats = SNDRV_PCM_FMTBIT_S16_LE,627},628.ops = &mt2701_single_memif_dai_ops,629},630/* BE DAIs */631{632.name = "I2S0",633.id = MT2701_IO_I2S,634.playback = {635.stream_name = "I2S0 Playback",636.channels_min = 1,637.channels_max = 2,638.rates = SNDRV_PCM_RATE_8000_192000,639.formats = (SNDRV_PCM_FMTBIT_S16_LE640| SNDRV_PCM_FMTBIT_S24_LE641| SNDRV_PCM_FMTBIT_S32_LE)642643},644.capture = {645.stream_name = "I2S0 Capture",646.channels_min = 1,647.channels_max = 2,648.rates = SNDRV_PCM_RATE_8000_192000,649.formats = (SNDRV_PCM_FMTBIT_S16_LE650| SNDRV_PCM_FMTBIT_S24_LE651| SNDRV_PCM_FMTBIT_S32_LE)652653},654.ops = &mt2701_afe_i2s_ops,655.symmetric_rate = 1,656},657{658.name = "I2S1",659.id = MT2701_IO_2ND_I2S,660.playback = {661.stream_name = "I2S1 Playback",662.channels_min = 1,663.channels_max = 2,664.rates = SNDRV_PCM_RATE_8000_192000,665.formats = (SNDRV_PCM_FMTBIT_S16_LE666| SNDRV_PCM_FMTBIT_S24_LE667| SNDRV_PCM_FMTBIT_S32_LE)668},669.capture = {670.stream_name = "I2S1 Capture",671.channels_min = 1,672.channels_max = 2,673.rates = SNDRV_PCM_RATE_8000_192000,674.formats = (SNDRV_PCM_FMTBIT_S16_LE675| SNDRV_PCM_FMTBIT_S24_LE676| SNDRV_PCM_FMTBIT_S32_LE)677},678.ops = &mt2701_afe_i2s_ops,679.symmetric_rate = 1,680},681{682.name = "I2S2",683.id = MT2701_IO_3RD_I2S,684.playback = {685.stream_name = "I2S2 Playback",686.channels_min = 1,687.channels_max = 2,688.rates = SNDRV_PCM_RATE_8000_192000,689.formats = (SNDRV_PCM_FMTBIT_S16_LE690| SNDRV_PCM_FMTBIT_S24_LE691| SNDRV_PCM_FMTBIT_S32_LE)692},693.capture = {694.stream_name = "I2S2 Capture",695.channels_min = 1,696.channels_max = 2,697.rates = SNDRV_PCM_RATE_8000_192000,698.formats = (SNDRV_PCM_FMTBIT_S16_LE699| SNDRV_PCM_FMTBIT_S24_LE700| SNDRV_PCM_FMTBIT_S32_LE)701},702.ops = &mt2701_afe_i2s_ops,703.symmetric_rate = 1,704},705{706.name = "I2S3",707.id = MT2701_IO_4TH_I2S,708.playback = {709.stream_name = "I2S3 Playback",710.channels_min = 1,711.channels_max = 2,712.rates = SNDRV_PCM_RATE_8000_192000,713.formats = (SNDRV_PCM_FMTBIT_S16_LE714| SNDRV_PCM_FMTBIT_S24_LE715| SNDRV_PCM_FMTBIT_S32_LE)716},717.capture = {718.stream_name = "I2S3 Capture",719.channels_min = 1,720.channels_max = 2,721.rates = SNDRV_PCM_RATE_8000_192000,722.formats = (SNDRV_PCM_FMTBIT_S16_LE723| SNDRV_PCM_FMTBIT_S24_LE724| SNDRV_PCM_FMTBIT_S32_LE)725},726.ops = &mt2701_afe_i2s_ops,727.symmetric_rate = 1,728},729{730.name = "MRG BT",731.id = MT2701_IO_MRG,732.playback = {733.stream_name = "BT Playback",734.channels_min = 1,735.channels_max = 1,736.rates = (SNDRV_PCM_RATE_8000737| SNDRV_PCM_RATE_16000),738.formats = SNDRV_PCM_FMTBIT_S16_LE,739},740.capture = {741.stream_name = "BT Capture",742.channels_min = 1,743.channels_max = 1,744.rates = (SNDRV_PCM_RATE_8000745| SNDRV_PCM_RATE_16000),746.formats = SNDRV_PCM_FMTBIT_S16_LE,747},748.ops = &mt2701_btmrg_ops,749.symmetric_rate = 1,750}751};752753static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = {754SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN0, 0, 1, 0),755};756757static const struct snd_kcontrol_new mt2701_afe_o01_mix[] = {758SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN1, 1, 1, 0),759};760761static const struct snd_kcontrol_new mt2701_afe_o02_mix[] = {762SOC_DAPM_SINGLE_AUTODISABLE("I02 Switch", AFE_CONN2, 2, 1, 0),763};764765static const struct snd_kcontrol_new mt2701_afe_o03_mix[] = {766SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 3, 1, 0),767};768769static const struct snd_kcontrol_new mt2701_afe_o14_mix[] = {770SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN14, 26, 1, 0),771};772773static const struct snd_kcontrol_new mt2701_afe_o15_mix[] = {774SOC_DAPM_SINGLE_AUTODISABLE("I12 Switch", AFE_CONN15, 12, 1, 0),775};776777static const struct snd_kcontrol_new mt2701_afe_o16_mix[] = {778SOC_DAPM_SINGLE_AUTODISABLE("I13 Switch", AFE_CONN16, 13, 1, 0),779};780781static const struct snd_kcontrol_new mt2701_afe_o17_mix[] = {782SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0),783};784785static const struct snd_kcontrol_new mt2701_afe_o18_mix[] = {786SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0),787};788789static const struct snd_kcontrol_new mt2701_afe_o19_mix[] = {790SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0),791};792793static const struct snd_kcontrol_new mt2701_afe_o20_mix[] = {794SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0),795};796797static const struct snd_kcontrol_new mt2701_afe_o21_mix[] = {798SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0),799};800801static const struct snd_kcontrol_new mt2701_afe_o22_mix[] = {802SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0),803};804805static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = {806SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0),807};808809static const struct snd_kcontrol_new mt2701_afe_i02_mix[] = {810SOC_DAPM_SINGLE("I2S0 Switch", SND_SOC_NOPM, 0, 1, 0),811};812813static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s0[] = {814SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S0 Out Switch",815ASYS_I2SO1_CON, 26, 1, 0),816};817818static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s1[] = {819SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S1 Out Switch",820ASYS_I2SO2_CON, 26, 1, 0),821};822823static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s2[] = {824SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S2 Out Switch",825PWR2_TOP_CON, 17, 1, 0),826};827828static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s3[] = {829SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S3 Out Switch",830PWR2_TOP_CON, 18, 1, 0),831};832833static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = {834/* inter-connections */835SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0),836SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0),837SND_SOC_DAPM_MIXER("I02", SND_SOC_NOPM, 0, 0, mt2701_afe_i02_mix,838ARRAY_SIZE(mt2701_afe_i02_mix)),839SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0),840SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0),841SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0),842SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0),843SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0),844SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0),845SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),846SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0),847SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0),848SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0),849SND_SOC_DAPM_MIXER("I35", SND_SOC_NOPM, 0, 0, NULL, 0),850851SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0, mt2701_afe_o00_mix,852ARRAY_SIZE(mt2701_afe_o00_mix)),853SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0, mt2701_afe_o01_mix,854ARRAY_SIZE(mt2701_afe_o01_mix)),855SND_SOC_DAPM_MIXER("O02", SND_SOC_NOPM, 0, 0, mt2701_afe_o02_mix,856ARRAY_SIZE(mt2701_afe_o02_mix)),857SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, mt2701_afe_o03_mix,858ARRAY_SIZE(mt2701_afe_o03_mix)),859SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0, mt2701_afe_o14_mix,860ARRAY_SIZE(mt2701_afe_o14_mix)),861SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0, mt2701_afe_o15_mix,862ARRAY_SIZE(mt2701_afe_o15_mix)),863SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0, mt2701_afe_o16_mix,864ARRAY_SIZE(mt2701_afe_o16_mix)),865SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0, mt2701_afe_o17_mix,866ARRAY_SIZE(mt2701_afe_o17_mix)),867SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0, mt2701_afe_o18_mix,868ARRAY_SIZE(mt2701_afe_o18_mix)),869SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0, mt2701_afe_o19_mix,870ARRAY_SIZE(mt2701_afe_o19_mix)),871SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0, mt2701_afe_o20_mix,872ARRAY_SIZE(mt2701_afe_o20_mix)),873SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0, mt2701_afe_o21_mix,874ARRAY_SIZE(mt2701_afe_o21_mix)),875SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0, mt2701_afe_o22_mix,876ARRAY_SIZE(mt2701_afe_o22_mix)),877SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0, mt2701_afe_o31_mix,878ARRAY_SIZE(mt2701_afe_o31_mix)),879880SND_SOC_DAPM_MIXER("I12I13", SND_SOC_NOPM, 0, 0,881mt2701_afe_multi_ch_out_i2s0,882ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s0)),883SND_SOC_DAPM_MIXER("I14I15", SND_SOC_NOPM, 0, 0,884mt2701_afe_multi_ch_out_i2s1,885ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s1)),886SND_SOC_DAPM_MIXER("I16I17", SND_SOC_NOPM, 0, 0,887mt2701_afe_multi_ch_out_i2s2,888ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s2)),889SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0,890mt2701_afe_multi_ch_out_i2s3,891ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)),892};893894static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {895{"I12", NULL, "DL1"},896{"I13", NULL, "DL1"},897{"I35", NULL, "DLBT"},898899{"I2S0 Playback", NULL, "O15"},900{"I2S0 Playback", NULL, "O16"},901{"I2S1 Playback", NULL, "O17"},902{"I2S1 Playback", NULL, "O18"},903{"I2S2 Playback", NULL, "O19"},904{"I2S2 Playback", NULL, "O20"},905{"I2S3 Playback", NULL, "O21"},906{"I2S3 Playback", NULL, "O22"},907{"BT Playback", NULL, "O31"},908909{"UL1", NULL, "O00"},910{"UL1", NULL, "O01"},911{"UL2", NULL, "O02"},912{"UL2", NULL, "O03"},913{"ULBT", NULL, "O14"},914915{"I00", NULL, "I2S0 Capture"},916{"I01", NULL, "I2S0 Capture"},917{"I02", NULL, "I2S1 Capture"},918{"I03", NULL, "I2S1 Capture"},919/* I02,03 link to UL2, also need to open I2S0 */920{"I02", "I2S0 Switch", "I2S0 Capture"},921922{"I26", NULL, "BT Capture"},923924{"I12I13", "Multich I2S0 Out Switch", "DLM"},925{"I14I15", "Multich I2S1 Out Switch", "DLM"},926{"I16I17", "Multich I2S2 Out Switch", "DLM"},927{"I18I19", "Multich I2S3 Out Switch", "DLM"},928929{ "I12", NULL, "I12I13" },930{ "I13", NULL, "I12I13" },931{ "I14", NULL, "I14I15" },932{ "I15", NULL, "I14I15" },933{ "I16", NULL, "I16I17" },934{ "I17", NULL, "I16I17" },935{ "I18", NULL, "I18I19" },936{ "I19", NULL, "I18I19" },937938{ "O00", "I00 Switch", "I00" },939{ "O01", "I01 Switch", "I01" },940{ "O02", "I02 Switch", "I02" },941{ "O03", "I03 Switch", "I03" },942{ "O14", "I26 Switch", "I26" },943{ "O15", "I12 Switch", "I12" },944{ "O16", "I13 Switch", "I13" },945{ "O17", "I14 Switch", "I14" },946{ "O18", "I15 Switch", "I15" },947{ "O19", "I16 Switch", "I16" },948{ "O20", "I17 Switch", "I17" },949{ "O21", "I18 Switch", "I18" },950{ "O22", "I19 Switch", "I19" },951{ "O31", "I35 Switch", "I35" },952};953954static int mt2701_afe_pcm_probe(struct snd_soc_component *component)955{956struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);957958snd_soc_component_init_regmap(component, afe->regmap);959960return 0;961}962963static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = {964.probe = mt2701_afe_pcm_probe,965.name = "mt2701-afe-pcm-dai",966.dapm_widgets = mt2701_afe_pcm_widgets,967.num_dapm_widgets = ARRAY_SIZE(mt2701_afe_pcm_widgets),968.dapm_routes = mt2701_afe_pcm_routes,969.num_dapm_routes = ARRAY_SIZE(mt2701_afe_pcm_routes),970.suspend = mtk_afe_suspend,971.resume = mtk_afe_resume,972};973974static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = {975{976.name = "DL1",977.id = MT2701_MEMIF_DL1,978.reg_ofs_base = AFE_DL1_BASE,979.reg_ofs_cur = AFE_DL1_CUR,980.fs_reg = AFE_DAC_CON1,981.fs_shift = 0,982.fs_maskbit = 0x1f,983.mono_reg = AFE_DAC_CON3,984.mono_shift = 16,985.enable_reg = AFE_DAC_CON0,986.enable_shift = 1,987.hd_reg = AFE_MEMIF_HD_CON0,988.hd_shift = 0,989.agent_disable_reg = AUDIO_TOP_CON5,990.agent_disable_shift = 6,991.msb_reg = -1,992},993{994.name = "DL2",995.id = MT2701_MEMIF_DL2,996.reg_ofs_base = AFE_DL2_BASE,997.reg_ofs_cur = AFE_DL2_CUR,998.fs_reg = AFE_DAC_CON1,999.fs_shift = 5,1000.fs_maskbit = 0x1f,1001.mono_reg = AFE_DAC_CON3,1002.mono_shift = 17,1003.enable_reg = AFE_DAC_CON0,1004.enable_shift = 2,1005.hd_reg = AFE_MEMIF_HD_CON0,1006.hd_shift = 2,1007.agent_disable_reg = AUDIO_TOP_CON5,1008.agent_disable_shift = 7,1009.msb_reg = -1,1010},1011{1012.name = "DL3",1013.id = MT2701_MEMIF_DL3,1014.reg_ofs_base = AFE_DL3_BASE,1015.reg_ofs_cur = AFE_DL3_CUR,1016.fs_reg = AFE_DAC_CON1,1017.fs_shift = 10,1018.fs_maskbit = 0x1f,1019.mono_reg = AFE_DAC_CON3,1020.mono_shift = 18,1021.enable_reg = AFE_DAC_CON0,1022.enable_shift = 3,1023.hd_reg = AFE_MEMIF_HD_CON0,1024.hd_shift = 4,1025.agent_disable_reg = AUDIO_TOP_CON5,1026.agent_disable_shift = 8,1027.msb_reg = -1,1028},1029{1030.name = "DL4",1031.id = MT2701_MEMIF_DL4,1032.reg_ofs_base = AFE_DL4_BASE,1033.reg_ofs_cur = AFE_DL4_CUR,1034.fs_reg = AFE_DAC_CON1,1035.fs_shift = 15,1036.fs_maskbit = 0x1f,1037.mono_reg = AFE_DAC_CON3,1038.mono_shift = 19,1039.enable_reg = AFE_DAC_CON0,1040.enable_shift = 4,1041.hd_reg = AFE_MEMIF_HD_CON0,1042.hd_shift = 6,1043.agent_disable_reg = AUDIO_TOP_CON5,1044.agent_disable_shift = 9,1045.msb_reg = -1,1046},1047{1048.name = "DL5",1049.id = MT2701_MEMIF_DL5,1050.reg_ofs_base = AFE_DL5_BASE,1051.reg_ofs_cur = AFE_DL5_CUR,1052.fs_reg = AFE_DAC_CON1,1053.fs_shift = 20,1054.fs_maskbit = 0x1f,1055.mono_reg = AFE_DAC_CON3,1056.mono_shift = 20,1057.enable_reg = AFE_DAC_CON0,1058.enable_shift = 5,1059.hd_reg = AFE_MEMIF_HD_CON0,1060.hd_shift = 8,1061.agent_disable_reg = AUDIO_TOP_CON5,1062.agent_disable_shift = 10,1063.msb_reg = -1,1064},1065{1066.name = "DLM",1067.id = MT2701_MEMIF_DLM,1068.reg_ofs_base = AFE_DLMCH_BASE,1069.reg_ofs_cur = AFE_DLMCH_CUR,1070.fs_reg = AFE_DAC_CON1,1071.fs_shift = 0,1072.fs_maskbit = 0x1f,1073.mono_reg = -1,1074.mono_shift = -1,1075.enable_reg = AFE_DAC_CON0,1076.enable_shift = 7,1077.hd_reg = AFE_MEMIF_PBUF_SIZE,1078.hd_shift = 28,1079.agent_disable_reg = AUDIO_TOP_CON5,1080.agent_disable_shift = 12,1081.msb_reg = -1,1082},1083{1084.name = "UL1",1085.id = MT2701_MEMIF_UL1,1086.reg_ofs_base = AFE_VUL_BASE,1087.reg_ofs_cur = AFE_VUL_CUR,1088.fs_reg = AFE_DAC_CON2,1089.fs_shift = 0,1090.fs_maskbit = 0x1f,1091.mono_reg = AFE_DAC_CON4,1092.mono_shift = 0,1093.enable_reg = AFE_DAC_CON0,1094.enable_shift = 10,1095.hd_reg = AFE_MEMIF_HD_CON1,1096.hd_shift = 0,1097.agent_disable_reg = AUDIO_TOP_CON5,1098.agent_disable_shift = 0,1099.msb_reg = -1,1100},1101{1102.name = "UL2",1103.id = MT2701_MEMIF_UL2,1104.reg_ofs_base = AFE_UL2_BASE,1105.reg_ofs_cur = AFE_UL2_CUR,1106.fs_reg = AFE_DAC_CON2,1107.fs_shift = 5,1108.fs_maskbit = 0x1f,1109.mono_reg = AFE_DAC_CON4,1110.mono_shift = 2,1111.enable_reg = AFE_DAC_CON0,1112.enable_shift = 11,1113.hd_reg = AFE_MEMIF_HD_CON1,1114.hd_shift = 2,1115.agent_disable_reg = AUDIO_TOP_CON5,1116.agent_disable_shift = 1,1117.msb_reg = -1,1118},1119{1120.name = "UL3",1121.id = MT2701_MEMIF_UL3,1122.reg_ofs_base = AFE_UL3_BASE,1123.reg_ofs_cur = AFE_UL3_CUR,1124.fs_reg = AFE_DAC_CON2,1125.fs_shift = 10,1126.fs_maskbit = 0x1f,1127.mono_reg = AFE_DAC_CON4,1128.mono_shift = 4,1129.enable_reg = AFE_DAC_CON0,1130.enable_shift = 12,1131.hd_reg = AFE_MEMIF_HD_CON0,1132.hd_shift = 0,1133.agent_disable_reg = AUDIO_TOP_CON5,1134.agent_disable_shift = 2,1135.msb_reg = -1,1136},1137{1138.name = "UL4",1139.id = MT2701_MEMIF_UL4,1140.reg_ofs_base = AFE_UL4_BASE,1141.reg_ofs_cur = AFE_UL4_CUR,1142.fs_reg = AFE_DAC_CON2,1143.fs_shift = 15,1144.fs_maskbit = 0x1f,1145.mono_reg = AFE_DAC_CON4,1146.mono_shift = 6,1147.enable_reg = AFE_DAC_CON0,1148.enable_shift = 13,1149.hd_reg = AFE_MEMIF_HD_CON0,1150.hd_shift = 6,1151.agent_disable_reg = AUDIO_TOP_CON5,1152.agent_disable_shift = 3,1153.msb_reg = -1,1154},1155{1156.name = "UL5",1157.id = MT2701_MEMIF_UL5,1158.reg_ofs_base = AFE_UL5_BASE,1159.reg_ofs_cur = AFE_UL5_CUR,1160.fs_reg = AFE_DAC_CON2,1161.fs_shift = 20,1162.mono_reg = AFE_DAC_CON4,1163.mono_shift = 8,1164.fs_maskbit = 0x1f,1165.enable_reg = AFE_DAC_CON0,1166.enable_shift = 14,1167.hd_reg = AFE_MEMIF_HD_CON0,1168.hd_shift = 8,1169.agent_disable_reg = AUDIO_TOP_CON5,1170.agent_disable_shift = 4,1171.msb_reg = -1,1172},1173{1174.name = "DLBT",1175.id = MT2701_MEMIF_DLBT,1176.reg_ofs_base = AFE_ARB1_BASE,1177.reg_ofs_cur = AFE_ARB1_CUR,1178.fs_reg = AFE_DAC_CON3,1179.fs_shift = 10,1180.fs_maskbit = 0x1f,1181.mono_reg = AFE_DAC_CON3,1182.mono_shift = 22,1183.enable_reg = AFE_DAC_CON0,1184.enable_shift = 8,1185.hd_reg = AFE_MEMIF_HD_CON0,1186.hd_shift = 14,1187.agent_disable_reg = AUDIO_TOP_CON5,1188.agent_disable_shift = 13,1189.msb_reg = -1,1190},1191{1192.name = "ULBT",1193.id = MT2701_MEMIF_ULBT,1194.reg_ofs_base = AFE_DAI_BASE,1195.reg_ofs_cur = AFE_DAI_CUR,1196.fs_reg = AFE_DAC_CON2,1197.fs_shift = 30,1198.fs_maskbit = 0x1,1199.mono_reg = -1,1200.mono_shift = -1,1201.enable_reg = AFE_DAC_CON0,1202.enable_shift = 17,1203.hd_reg = AFE_MEMIF_HD_CON1,1204.hd_shift = 20,1205.agent_disable_reg = AUDIO_TOP_CON5,1206.agent_disable_shift = 16,1207.msb_reg = -1,1208},1209};12101211static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = {1212{1213.id = MT2701_IRQ_ASYS_IRQ1,1214.irq_cnt_reg = ASYS_IRQ1_CON,1215.irq_cnt_shift = 0,1216.irq_cnt_maskbit = 0xffffff,1217.irq_fs_reg = ASYS_IRQ1_CON,1218.irq_fs_shift = 24,1219.irq_fs_maskbit = 0x1f,1220.irq_en_reg = ASYS_IRQ1_CON,1221.irq_en_shift = 31,1222.irq_clr_reg = ASYS_IRQ_CLR,1223.irq_clr_shift = 0,1224},1225{1226.id = MT2701_IRQ_ASYS_IRQ2,1227.irq_cnt_reg = ASYS_IRQ2_CON,1228.irq_cnt_shift = 0,1229.irq_cnt_maskbit = 0xffffff,1230.irq_fs_reg = ASYS_IRQ2_CON,1231.irq_fs_shift = 24,1232.irq_fs_maskbit = 0x1f,1233.irq_en_reg = ASYS_IRQ2_CON,1234.irq_en_shift = 31,1235.irq_clr_reg = ASYS_IRQ_CLR,1236.irq_clr_shift = 1,1237},1238{1239.id = MT2701_IRQ_ASYS_IRQ3,1240.irq_cnt_reg = ASYS_IRQ3_CON,1241.irq_cnt_shift = 0,1242.irq_cnt_maskbit = 0xffffff,1243.irq_fs_reg = ASYS_IRQ3_CON,1244.irq_fs_shift = 24,1245.irq_fs_maskbit = 0x1f,1246.irq_en_reg = ASYS_IRQ3_CON,1247.irq_en_shift = 31,1248.irq_clr_reg = ASYS_IRQ_CLR,1249.irq_clr_shift = 2,1250}1251};12521253static const struct mt2701_i2s_data mt2701_i2s_data[][2] = {1254{1255{ ASYS_I2SO1_CON, 0, 0x1f },1256{ ASYS_I2SIN1_CON, 0, 0x1f },1257},1258{1259{ ASYS_I2SO2_CON, 5, 0x1f },1260{ ASYS_I2SIN2_CON, 5, 0x1f },1261},1262{1263{ ASYS_I2SO3_CON, 10, 0x1f },1264{ ASYS_I2SIN3_CON, 10, 0x1f },1265},1266{1267{ ASYS_I2SO4_CON, 15, 0x1f },1268{ ASYS_I2SIN4_CON, 15, 0x1f },1269},1270/* TODO - extend control registers supported by newer SoCs */1271};12721273static irqreturn_t mt2701_asys_isr(int irq_id, void *dev)1274{1275int id;1276struct mtk_base_afe *afe = dev;1277struct mtk_base_afe_memif *memif;1278struct mtk_base_afe_irq *irq;1279u32 status;12801281regmap_read(afe->regmap, ASYS_IRQ_STATUS, &status);1282regmap_write(afe->regmap, ASYS_IRQ_CLR, status);12831284for (id = 0; id < MT2701_MEMIF_NUM; ++id) {1285memif = &afe->memif[id];1286if (memif->irq_usage < 0)1287continue;12881289irq = &afe->irqs[memif->irq_usage];1290if (status & 1 << irq->irq_data->irq_clr_shift)1291snd_pcm_period_elapsed(memif->substream);1292}12931294return IRQ_HANDLED;1295}12961297static int mt2701_afe_runtime_suspend(struct device *dev)1298{1299struct mtk_base_afe *afe = dev_get_drvdata(dev);13001301return mt2701_afe_disable_clock(afe);1302}13031304static int mt2701_afe_runtime_resume(struct device *dev)1305{1306struct mtk_base_afe *afe = dev_get_drvdata(dev);13071308return mt2701_afe_enable_clock(afe);1309}13101311static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)1312{1313struct mtk_base_afe *afe;1314struct mt2701_afe_private *afe_priv;1315struct device *dev;1316int i, irq_id, ret;13171318afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);1319if (!afe)1320return -ENOMEM;13211322afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),1323GFP_KERNEL);1324if (!afe->platform_priv)1325return -ENOMEM;13261327afe_priv = afe->platform_priv;1328afe_priv->soc = of_device_get_match_data(&pdev->dev);1329afe->dev = &pdev->dev;1330dev = afe->dev;13311332afe_priv->i2s_path = devm_kcalloc(dev,1333afe_priv->soc->i2s_num,1334sizeof(struct mt2701_i2s_path),1335GFP_KERNEL);1336if (!afe_priv->i2s_path)1337return -ENOMEM;13381339irq_id = platform_get_irq_byname(pdev, "asys");1340if (irq_id < 0)1341return irq_id;13421343ret = devm_request_irq(dev, irq_id, mt2701_asys_isr,1344IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);1345if (ret) {1346dev_err(dev, "could not request_irq for asys-isr\n");1347return ret;1348}13491350afe->regmap = syscon_node_to_regmap(dev->parent->of_node);1351if (IS_ERR(afe->regmap)) {1352dev_err(dev, "could not get regmap from parent\n");1353return PTR_ERR(afe->regmap);1354}13551356mutex_init(&afe->irq_alloc_lock);13571358/* memif initialize */1359afe->memif_size = MT2701_MEMIF_NUM;1360afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),1361GFP_KERNEL);1362if (!afe->memif)1363return -ENOMEM;13641365for (i = 0; i < afe->memif_size; i++) {1366afe->memif[i].data = &memif_data_array[i];1367afe->memif[i].irq_usage = -1;1368}13691370/* irq initialize */1371afe->irqs_size = MT2701_IRQ_ASYS_END;1372afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),1373GFP_KERNEL);1374if (!afe->irqs)1375return -ENOMEM;13761377for (i = 0; i < afe->irqs_size; i++)1378afe->irqs[i].irq_data = &irq_data[i];13791380/* I2S initialize */1381for (i = 0; i < afe_priv->soc->i2s_num; i++) {1382afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_PLAYBACK] =1383&mt2701_i2s_data[i][SNDRV_PCM_STREAM_PLAYBACK];1384afe_priv->i2s_path[i].i2s_data[SNDRV_PCM_STREAM_CAPTURE] =1385&mt2701_i2s_data[i][SNDRV_PCM_STREAM_CAPTURE];1386}13871388afe->mtk_afe_hardware = &mt2701_afe_hardware;1389afe->memif_fs = mt2701_memif_fs;1390afe->irq_fs = mt2701_irq_fs;1391afe->reg_back_up_list = mt2701_afe_backup_list;1392afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list);1393afe->runtime_resume = mt2701_afe_runtime_resume;1394afe->runtime_suspend = mt2701_afe_runtime_suspend;13951396/* initial audio related clock */1397ret = mt2701_init_clock(afe);1398if (ret) {1399dev_err(dev, "init clock error\n");1400return ret;1401}14021403platform_set_drvdata(pdev, afe);14041405pm_runtime_enable(dev);1406if (!pm_runtime_enabled(dev)) {1407ret = mt2701_afe_runtime_resume(dev);1408if (ret)1409goto err_pm_disable;1410}1411pm_runtime_get_sync(dev);14121413ret = devm_snd_soc_register_component(&pdev->dev, &mtk_afe_pcm_platform,1414NULL, 0);1415if (ret) {1416dev_warn(dev, "err_platform\n");1417goto err_platform;1418}14191420ret = devm_snd_soc_register_component(&pdev->dev,1421&mt2701_afe_pcm_dai_component,1422mt2701_afe_pcm_dais,1423ARRAY_SIZE(mt2701_afe_pcm_dais));1424if (ret) {1425dev_warn(dev, "err_dai_component\n");1426goto err_platform;1427}14281429return 0;14301431err_platform:1432pm_runtime_put_sync(dev);1433err_pm_disable:1434pm_runtime_disable(dev);14351436return ret;1437}14381439static void mt2701_afe_pcm_dev_remove(struct platform_device *pdev)1440{1441pm_runtime_put_sync(&pdev->dev);1442pm_runtime_disable(&pdev->dev);1443if (!pm_runtime_status_suspended(&pdev->dev))1444mt2701_afe_runtime_suspend(&pdev->dev);1445}14461447static const struct mt2701_soc_variants mt2701_soc_v1 = {1448.i2s_num = 4,1449};14501451static const struct mt2701_soc_variants mt2701_soc_v2 = {1452.has_one_heart_mode = true,1453.i2s_num = 4,1454};14551456static const struct of_device_id mt2701_afe_pcm_dt_match[] = {1457{ .compatible = "mediatek,mt2701-audio", .data = &mt2701_soc_v1 },1458{ .compatible = "mediatek,mt7622-audio", .data = &mt2701_soc_v2 },1459{},1460};1461MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match);14621463static const struct dev_pm_ops mt2701_afe_pm_ops = {1464RUNTIME_PM_OPS(mt2701_afe_runtime_suspend,1465mt2701_afe_runtime_resume, NULL)1466};14671468static struct platform_driver mt2701_afe_pcm_driver = {1469.driver = {1470.name = "mt2701-audio",1471.of_match_table = mt2701_afe_pcm_dt_match,1472.pm = pm_ptr(&mt2701_afe_pm_ops),1473},1474.probe = mt2701_afe_pcm_dev_probe,1475.remove = mt2701_afe_pcm_dev_remove,1476};14771478module_platform_driver(mt2701_afe_pcm_driver);14791480MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701");1481MODULE_AUTHOR("Garlic Tseng <[email protected]>");1482MODULE_LICENSE("GPL v2");148314841485