162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * MediaTek ALSA SoC AFE platform driver for MT7986 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2023 MediaTek Inc. 662306a36Sopenharmony_ci * Authors: Vic Wu <vic.wu@mediatek.com> 762306a36Sopenharmony_ci * Maso Huang <maso.huang@mediatek.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/clk.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/of.h> 1462306a36Sopenharmony_ci#include <linux/of_address.h> 1562306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "mt7986-afe-common.h" 1862306a36Sopenharmony_ci#include "mt7986-reg.h" 1962306a36Sopenharmony_ci#include "../common/mtk-afe-platform-driver.h" 2062306a36Sopenharmony_ci#include "../common/mtk-afe-fe-dai.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cienum { 2362306a36Sopenharmony_ci MTK_AFE_RATE_8K = 0, 2462306a36Sopenharmony_ci MTK_AFE_RATE_11K = 1, 2562306a36Sopenharmony_ci MTK_AFE_RATE_12K = 2, 2662306a36Sopenharmony_ci MTK_AFE_RATE_16K = 4, 2762306a36Sopenharmony_ci MTK_AFE_RATE_22K = 5, 2862306a36Sopenharmony_ci MTK_AFE_RATE_24K = 6, 2962306a36Sopenharmony_ci MTK_AFE_RATE_32K = 8, 3062306a36Sopenharmony_ci MTK_AFE_RATE_44K = 9, 3162306a36Sopenharmony_ci MTK_AFE_RATE_48K = 10, 3262306a36Sopenharmony_ci MTK_AFE_RATE_88K = 13, 3362306a36Sopenharmony_ci MTK_AFE_RATE_96K = 14, 3462306a36Sopenharmony_ci MTK_AFE_RATE_176K = 17, 3562306a36Sopenharmony_ci MTK_AFE_RATE_192K = 18, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cienum { 3962306a36Sopenharmony_ci CLK_INFRA_AUD_BUS_CK = 0, 4062306a36Sopenharmony_ci CLK_INFRA_AUD_26M_CK, 4162306a36Sopenharmony_ci CLK_INFRA_AUD_L_CK, 4262306a36Sopenharmony_ci CLK_INFRA_AUD_AUD_CK, 4362306a36Sopenharmony_ci CLK_INFRA_AUD_EG2_CK, 4462306a36Sopenharmony_ci CLK_NUM 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic const char *aud_clks[CLK_NUM] = { 4862306a36Sopenharmony_ci [CLK_INFRA_AUD_BUS_CK] = "aud_bus_ck", 4962306a36Sopenharmony_ci [CLK_INFRA_AUD_26M_CK] = "aud_26m_ck", 5062306a36Sopenharmony_ci [CLK_INFRA_AUD_L_CK] = "aud_l_ck", 5162306a36Sopenharmony_ci [CLK_INFRA_AUD_AUD_CK] = "aud_aud_ck", 5262306a36Sopenharmony_ci [CLK_INFRA_AUD_EG2_CK] = "aud_eg2_ck", 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ciunsigned int mt7986_afe_rate_transform(struct device *dev, unsigned int rate) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci switch (rate) { 5862306a36Sopenharmony_ci case 8000: 5962306a36Sopenharmony_ci return MTK_AFE_RATE_8K; 6062306a36Sopenharmony_ci case 11025: 6162306a36Sopenharmony_ci return MTK_AFE_RATE_11K; 6262306a36Sopenharmony_ci case 12000: 6362306a36Sopenharmony_ci return MTK_AFE_RATE_12K; 6462306a36Sopenharmony_ci case 16000: 6562306a36Sopenharmony_ci return MTK_AFE_RATE_16K; 6662306a36Sopenharmony_ci case 22050: 6762306a36Sopenharmony_ci return MTK_AFE_RATE_22K; 6862306a36Sopenharmony_ci case 24000: 6962306a36Sopenharmony_ci return MTK_AFE_RATE_24K; 7062306a36Sopenharmony_ci case 32000: 7162306a36Sopenharmony_ci return MTK_AFE_RATE_32K; 7262306a36Sopenharmony_ci case 44100: 7362306a36Sopenharmony_ci return MTK_AFE_RATE_44K; 7462306a36Sopenharmony_ci case 48000: 7562306a36Sopenharmony_ci return MTK_AFE_RATE_48K; 7662306a36Sopenharmony_ci case 88200: 7762306a36Sopenharmony_ci return MTK_AFE_RATE_88K; 7862306a36Sopenharmony_ci case 96000: 7962306a36Sopenharmony_ci return MTK_AFE_RATE_96K; 8062306a36Sopenharmony_ci case 176400: 8162306a36Sopenharmony_ci return MTK_AFE_RATE_176K; 8262306a36Sopenharmony_ci case 192000: 8362306a36Sopenharmony_ci return MTK_AFE_RATE_192K; 8462306a36Sopenharmony_ci default: 8562306a36Sopenharmony_ci dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", 8662306a36Sopenharmony_ci __func__, rate, MTK_AFE_RATE_48K); 8762306a36Sopenharmony_ci return MTK_AFE_RATE_48K; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic const struct snd_pcm_hardware mt7986_afe_hardware = { 9262306a36Sopenharmony_ci .info = SNDRV_PCM_INFO_MMAP | 9362306a36Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 9462306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID, 9562306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE | 9662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | 9762306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE, 9862306a36Sopenharmony_ci .period_bytes_min = 256, 9962306a36Sopenharmony_ci .period_bytes_max = 4 * 48 * 1024, 10062306a36Sopenharmony_ci .periods_min = 2, 10162306a36Sopenharmony_ci .periods_max = 256, 10262306a36Sopenharmony_ci .buffer_bytes_max = 8 * 48 * 1024, 10362306a36Sopenharmony_ci .fifo_size = 0, 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic int mt7986_memif_fs(struct snd_pcm_substream *substream, 10762306a36Sopenharmony_ci unsigned int rate) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = substream->private_data; 11062306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 11162306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return mt7986_afe_rate_transform(afe->dev, rate); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cistatic int mt7986_irq_fs(struct snd_pcm_substream *substream, 11762306a36Sopenharmony_ci unsigned int rate) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = substream->private_data; 12062306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 12162306a36Sopenharmony_ci struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return mt7986_afe_rate_transform(afe->dev, rate); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\ 12762306a36Sopenharmony_ci SNDRV_PCM_RATE_88200 |\ 12862306a36Sopenharmony_ci SNDRV_PCM_RATE_96000 |\ 12962306a36Sopenharmony_ci SNDRV_PCM_RATE_176400 |\ 13062306a36Sopenharmony_ci SNDRV_PCM_RATE_192000) 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 13362306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE |\ 13462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE) 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic struct snd_soc_dai_driver mt7986_memif_dai_driver[] = { 13762306a36Sopenharmony_ci /* FE DAIs: memory intefaces to CPU */ 13862306a36Sopenharmony_ci { 13962306a36Sopenharmony_ci .name = "DL1", 14062306a36Sopenharmony_ci .id = MT7986_MEMIF_DL1, 14162306a36Sopenharmony_ci .playback = { 14262306a36Sopenharmony_ci .stream_name = "DL1", 14362306a36Sopenharmony_ci .channels_min = 1, 14462306a36Sopenharmony_ci .channels_max = 2, 14562306a36Sopenharmony_ci .rates = MTK_PCM_RATES, 14662306a36Sopenharmony_ci .formats = MTK_PCM_FORMATS, 14762306a36Sopenharmony_ci }, 14862306a36Sopenharmony_ci .ops = &mtk_afe_fe_ops, 14962306a36Sopenharmony_ci }, 15062306a36Sopenharmony_ci { 15162306a36Sopenharmony_ci .name = "UL1", 15262306a36Sopenharmony_ci .id = MT7986_MEMIF_VUL12, 15362306a36Sopenharmony_ci .capture = { 15462306a36Sopenharmony_ci .stream_name = "UL1", 15562306a36Sopenharmony_ci .channels_min = 1, 15662306a36Sopenharmony_ci .channels_max = 2, 15762306a36Sopenharmony_ci .rates = MTK_PCM_RATES, 15862306a36Sopenharmony_ci .formats = MTK_PCM_FORMATS, 15962306a36Sopenharmony_ci }, 16062306a36Sopenharmony_ci .ops = &mtk_afe_fe_ops, 16162306a36Sopenharmony_ci }, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const struct snd_kcontrol_new o018_mix[] = { 16562306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I150_Switch", AFE_CONN018_4, 22, 1, 0), 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic const struct snd_kcontrol_new o019_mix[] = { 16962306a36Sopenharmony_ci SOC_DAPM_SINGLE_AUTODISABLE("I151_Switch", AFE_CONN019_4, 23, 1, 0), 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget mt7986_memif_widgets[] = { 17362306a36Sopenharmony_ci /* DL */ 17462306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0), 17562306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0), 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* UL */ 17862306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0, 17962306a36Sopenharmony_ci o018_mix, ARRAY_SIZE(o018_mix)), 18062306a36Sopenharmony_ci SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0, 18162306a36Sopenharmony_ci o019_mix, ARRAY_SIZE(o019_mix)), 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic const struct snd_soc_dapm_route mt7986_memif_routes[] = { 18562306a36Sopenharmony_ci {"I032", NULL, "DL1"}, 18662306a36Sopenharmony_ci {"I033", NULL, "DL1"}, 18762306a36Sopenharmony_ci {"UL1", NULL, "O018"}, 18862306a36Sopenharmony_ci {"UL1", NULL, "O019"}, 18962306a36Sopenharmony_ci {"O018", "I150_Switch", "I150"}, 19062306a36Sopenharmony_ci {"O019", "I151_Switch", "I151"}, 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic const struct snd_soc_component_driver mt7986_afe_pcm_dai_component = { 19462306a36Sopenharmony_ci .name = "mt7986-afe-pcm-dai", 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic const struct mtk_base_memif_data memif_data[MT7986_MEMIF_NUM] = { 19862306a36Sopenharmony_ci [MT7986_MEMIF_DL1] = { 19962306a36Sopenharmony_ci .name = "DL1", 20062306a36Sopenharmony_ci .id = MT7986_MEMIF_DL1, 20162306a36Sopenharmony_ci .reg_ofs_base = AFE_DL0_BASE, 20262306a36Sopenharmony_ci .reg_ofs_cur = AFE_DL0_CUR, 20362306a36Sopenharmony_ci .reg_ofs_end = AFE_DL0_END, 20462306a36Sopenharmony_ci .reg_ofs_base_msb = AFE_DL0_BASE_MSB, 20562306a36Sopenharmony_ci .reg_ofs_cur_msb = AFE_DL0_CUR_MSB, 20662306a36Sopenharmony_ci .reg_ofs_end_msb = AFE_DL0_END_MSB, 20762306a36Sopenharmony_ci .fs_reg = AFE_DL0_CON0, 20862306a36Sopenharmony_ci .fs_shift = DL0_MODE_SFT, 20962306a36Sopenharmony_ci .fs_maskbit = DL0_MODE_MASK, 21062306a36Sopenharmony_ci .mono_reg = AFE_DL0_CON0, 21162306a36Sopenharmony_ci .mono_shift = DL0_MONO_SFT, 21262306a36Sopenharmony_ci .enable_reg = AFE_DL0_CON0, 21362306a36Sopenharmony_ci .enable_shift = DL0_ON_SFT, 21462306a36Sopenharmony_ci .hd_reg = AFE_DL0_CON0, 21562306a36Sopenharmony_ci .hd_shift = DL0_HD_MODE_SFT, 21662306a36Sopenharmony_ci .hd_align_reg = AFE_DL0_CON0, 21762306a36Sopenharmony_ci .hd_align_mshift = DL0_HALIGN_SFT, 21862306a36Sopenharmony_ci .pbuf_reg = AFE_DL0_CON0, 21962306a36Sopenharmony_ci .pbuf_shift = DL0_PBUF_SIZE_SFT, 22062306a36Sopenharmony_ci .minlen_reg = AFE_DL0_CON0, 22162306a36Sopenharmony_ci .minlen_shift = DL0_MINLEN_SFT, 22262306a36Sopenharmony_ci }, 22362306a36Sopenharmony_ci [MT7986_MEMIF_VUL12] = { 22462306a36Sopenharmony_ci .name = "VUL12", 22562306a36Sopenharmony_ci .id = MT7986_MEMIF_VUL12, 22662306a36Sopenharmony_ci .reg_ofs_base = AFE_VUL0_BASE, 22762306a36Sopenharmony_ci .reg_ofs_cur = AFE_VUL0_CUR, 22862306a36Sopenharmony_ci .reg_ofs_end = AFE_VUL0_END, 22962306a36Sopenharmony_ci .reg_ofs_base_msb = AFE_VUL0_BASE_MSB, 23062306a36Sopenharmony_ci .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB, 23162306a36Sopenharmony_ci .reg_ofs_end_msb = AFE_VUL0_END_MSB, 23262306a36Sopenharmony_ci .fs_reg = AFE_VUL0_CON0, 23362306a36Sopenharmony_ci .fs_shift = VUL0_MODE_SFT, 23462306a36Sopenharmony_ci .fs_maskbit = VUL0_MODE_MASK, 23562306a36Sopenharmony_ci .mono_reg = AFE_VUL0_CON0, 23662306a36Sopenharmony_ci .mono_shift = VUL0_MONO_SFT, 23762306a36Sopenharmony_ci .enable_reg = AFE_VUL0_CON0, 23862306a36Sopenharmony_ci .enable_shift = VUL0_ON_SFT, 23962306a36Sopenharmony_ci .hd_reg = AFE_VUL0_CON0, 24062306a36Sopenharmony_ci .hd_shift = VUL0_HD_MODE_SFT, 24162306a36Sopenharmony_ci .hd_align_reg = AFE_VUL0_CON0, 24262306a36Sopenharmony_ci .hd_align_mshift = VUL0_HALIGN_SFT, 24362306a36Sopenharmony_ci }, 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic const struct mtk_base_irq_data irq_data[MT7986_IRQ_NUM] = { 24762306a36Sopenharmony_ci [MT7986_IRQ_0] = { 24862306a36Sopenharmony_ci .id = MT7986_IRQ_0, 24962306a36Sopenharmony_ci .irq_cnt_reg = AFE_IRQ0_MCU_CFG1, 25062306a36Sopenharmony_ci .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, 25162306a36Sopenharmony_ci .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, 25262306a36Sopenharmony_ci .irq_fs_reg = AFE_IRQ0_MCU_CFG0, 25362306a36Sopenharmony_ci .irq_fs_shift = IRQ_MCU_MODE_SFT, 25462306a36Sopenharmony_ci .irq_fs_maskbit = IRQ_MCU_MODE_MASK, 25562306a36Sopenharmony_ci .irq_en_reg = AFE_IRQ0_MCU_CFG0, 25662306a36Sopenharmony_ci .irq_en_shift = IRQ_MCU_ON_SFT, 25762306a36Sopenharmony_ci .irq_clr_reg = AFE_IRQ_MCU_CLR, 25862306a36Sopenharmony_ci .irq_clr_shift = IRQ0_MCU_CLR_SFT, 25962306a36Sopenharmony_ci }, 26062306a36Sopenharmony_ci [MT7986_IRQ_1] = { 26162306a36Sopenharmony_ci .id = MT7986_IRQ_1, 26262306a36Sopenharmony_ci .irq_cnt_reg = AFE_IRQ1_MCU_CFG1, 26362306a36Sopenharmony_ci .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, 26462306a36Sopenharmony_ci .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, 26562306a36Sopenharmony_ci .irq_fs_reg = AFE_IRQ1_MCU_CFG0, 26662306a36Sopenharmony_ci .irq_fs_shift = IRQ_MCU_MODE_SFT, 26762306a36Sopenharmony_ci .irq_fs_maskbit = IRQ_MCU_MODE_MASK, 26862306a36Sopenharmony_ci .irq_en_reg = AFE_IRQ1_MCU_CFG0, 26962306a36Sopenharmony_ci .irq_en_shift = IRQ_MCU_ON_SFT, 27062306a36Sopenharmony_ci .irq_clr_reg = AFE_IRQ_MCU_CLR, 27162306a36Sopenharmony_ci .irq_clr_shift = IRQ1_MCU_CLR_SFT, 27262306a36Sopenharmony_ci }, 27362306a36Sopenharmony_ci [MT7986_IRQ_2] = { 27462306a36Sopenharmony_ci .id = MT7986_IRQ_2, 27562306a36Sopenharmony_ci .irq_cnt_reg = AFE_IRQ2_MCU_CFG1, 27662306a36Sopenharmony_ci .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, 27762306a36Sopenharmony_ci .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, 27862306a36Sopenharmony_ci .irq_fs_reg = AFE_IRQ2_MCU_CFG0, 27962306a36Sopenharmony_ci .irq_fs_shift = IRQ_MCU_MODE_SFT, 28062306a36Sopenharmony_ci .irq_fs_maskbit = IRQ_MCU_MODE_MASK, 28162306a36Sopenharmony_ci .irq_en_reg = AFE_IRQ2_MCU_CFG0, 28262306a36Sopenharmony_ci .irq_en_shift = IRQ_MCU_ON_SFT, 28362306a36Sopenharmony_ci .irq_clr_reg = AFE_IRQ_MCU_CLR, 28462306a36Sopenharmony_ci .irq_clr_shift = IRQ2_MCU_CLR_SFT, 28562306a36Sopenharmony_ci }, 28662306a36Sopenharmony_ci}; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic bool mt7986_is_volatile_reg(struct device *dev, unsigned int reg) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * Those auto-gen regs are read-only, so put it as volatile because 29262306a36Sopenharmony_ci * volatile registers cannot be cached, which means that they cannot 29362306a36Sopenharmony_ci * be set when power is off 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci switch (reg) { 29762306a36Sopenharmony_ci case AFE_DL0_CUR_MSB: 29862306a36Sopenharmony_ci case AFE_DL0_CUR: 29962306a36Sopenharmony_ci case AFE_DL0_RCH_MON: 30062306a36Sopenharmony_ci case AFE_DL0_LCH_MON: 30162306a36Sopenharmony_ci case AFE_VUL0_CUR_MSB: 30262306a36Sopenharmony_ci case AFE_VUL0_CUR: 30362306a36Sopenharmony_ci case AFE_IRQ_MCU_STATUS: 30462306a36Sopenharmony_ci case AFE_MEMIF_RD_MON: 30562306a36Sopenharmony_ci case AFE_MEMIF_WR_MON: 30662306a36Sopenharmony_ci return true; 30762306a36Sopenharmony_ci default: 30862306a36Sopenharmony_ci return false; 30962306a36Sopenharmony_ci }; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic const struct regmap_config mt7986_afe_regmap_config = { 31362306a36Sopenharmony_ci .reg_bits = 32, 31462306a36Sopenharmony_ci .reg_stride = 4, 31562306a36Sopenharmony_ci .val_bits = 32, 31662306a36Sopenharmony_ci .volatile_reg = mt7986_is_volatile_reg, 31762306a36Sopenharmony_ci .max_register = AFE_MAX_REGISTER, 31862306a36Sopenharmony_ci .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1), 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic int mt7986_init_clock(struct mtk_base_afe *afe) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct mt7986_afe_private *afe_priv = afe->platform_priv; 32462306a36Sopenharmony_ci int ret, i; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci afe_priv->clks = devm_kcalloc(afe->dev, CLK_NUM, 32762306a36Sopenharmony_ci sizeof(*afe_priv->clks), GFP_KERNEL); 32862306a36Sopenharmony_ci if (!afe_priv->clks) 32962306a36Sopenharmony_ci return -ENOMEM; 33062306a36Sopenharmony_ci afe_priv->num_clks = CLK_NUM; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci for (i = 0; i < afe_priv->num_clks; i++) 33362306a36Sopenharmony_ci afe_priv->clks[i].id = aud_clks[i]; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci ret = devm_clk_bulk_get(afe->dev, afe_priv->num_clks, afe_priv->clks); 33662306a36Sopenharmony_ci if (ret) 33762306a36Sopenharmony_ci return dev_err_probe(afe->dev, ret, "Failed to get clocks\n"); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci return 0; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic irqreturn_t mt7986_afe_irq_handler(int irq_id, void *dev) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct mtk_base_afe *afe = dev; 34562306a36Sopenharmony_ci struct mtk_base_afe_irq *irq; 34662306a36Sopenharmony_ci u32 mcu_en, status, status_mcu; 34762306a36Sopenharmony_ci int i, ret; 34862306a36Sopenharmony_ci irqreturn_t irq_ret = IRQ_HANDLED; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* get irq that is sent to MCU */ 35162306a36Sopenharmony_ci regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status); 35462306a36Sopenharmony_ci /* only care IRQ which is sent to MCU */ 35562306a36Sopenharmony_ci status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (ret || status_mcu == 0) { 35862306a36Sopenharmony_ci dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x, mcu_en 0x%x\n", 35962306a36Sopenharmony_ci __func__, ret, status, mcu_en); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci irq_ret = IRQ_NONE; 36262306a36Sopenharmony_ci goto err_irq; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci for (i = 0; i < MT7986_MEMIF_NUM; i++) { 36662306a36Sopenharmony_ci struct mtk_base_afe_memif *memif = &afe->memif[i]; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (!memif->substream) 36962306a36Sopenharmony_ci continue; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (memif->irq_usage < 0) 37262306a36Sopenharmony_ci continue; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci irq = &afe->irqs[memif->irq_usage]; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (status_mcu & (1 << irq->irq_data->irq_en_shift)) 37762306a36Sopenharmony_ci snd_pcm_period_elapsed(memif->substream); 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cierr_irq: 38162306a36Sopenharmony_ci /* clear irq */ 38262306a36Sopenharmony_ci regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, status_mcu); 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci return irq_ret; 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic int mt7986_afe_runtime_suspend(struct device *dev) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci struct mtk_base_afe *afe = dev_get_drvdata(dev); 39062306a36Sopenharmony_ci struct mt7986_afe_private *afe_priv = afe->platform_priv; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) 39362306a36Sopenharmony_ci goto skip_regmap; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* disable clk*/ 39662306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0x3fff); 39762306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, 0); 39862306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, 0); 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* make sure all irq status are cleared, twice intended */ 40162306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CLR, 0xffff, 0xffff); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ciskip_regmap: 40462306a36Sopenharmony_ci clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci return 0; 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_cistatic int mt7986_afe_runtime_resume(struct device *dev) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct mtk_base_afe *afe = dev_get_drvdata(dev); 41262306a36Sopenharmony_ci struct mt7986_afe_private *afe_priv = afe->platform_priv; 41362306a36Sopenharmony_ci int ret; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks); 41662306a36Sopenharmony_ci if (ret) 41762306a36Sopenharmony_ci return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n"); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl) 42062306a36Sopenharmony_ci return 0; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* enable clk*/ 42362306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0); 42462306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK, 42562306a36Sopenharmony_ci AUD_APLL2_EN); 42662306a36Sopenharmony_ci regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK, 42762306a36Sopenharmony_ci AUD_26M_EN); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci return 0; 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic int mt7986_afe_component_probe(struct snd_soc_component *component) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci return mtk_afe_add_sub_dai_control(component); 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic const struct snd_soc_component_driver mt7986_afe_component = { 43862306a36Sopenharmony_ci .name = AFE_PCM_NAME, 43962306a36Sopenharmony_ci .probe = mt7986_afe_component_probe, 44062306a36Sopenharmony_ci .pointer = mtk_afe_pcm_pointer, 44162306a36Sopenharmony_ci .pcm_construct = mtk_afe_pcm_new, 44262306a36Sopenharmony_ci}; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic int mt7986_dai_memif_register(struct mtk_base_afe *afe) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct mtk_base_afe_dai *dai; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 44962306a36Sopenharmony_ci if (!dai) 45062306a36Sopenharmony_ci return -ENOMEM; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci list_add(&dai->list, &afe->sub_dais); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci dai->dai_drivers = mt7986_memif_dai_driver; 45562306a36Sopenharmony_ci dai->num_dai_drivers = ARRAY_SIZE(mt7986_memif_dai_driver); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci dai->dapm_widgets = mt7986_memif_widgets; 45862306a36Sopenharmony_ci dai->num_dapm_widgets = ARRAY_SIZE(mt7986_memif_widgets); 45962306a36Sopenharmony_ci dai->dapm_routes = mt7986_memif_routes; 46062306a36Sopenharmony_ci dai->num_dapm_routes = ARRAY_SIZE(mt7986_memif_routes); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci return 0; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_citypedef int (*dai_register_cb)(struct mtk_base_afe *); 46662306a36Sopenharmony_cistatic const dai_register_cb dai_register_cbs[] = { 46762306a36Sopenharmony_ci mt7986_dai_etdm_register, 46862306a36Sopenharmony_ci mt7986_dai_memif_register, 46962306a36Sopenharmony_ci}; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic int mt7986_afe_pcm_dev_probe(struct platform_device *pdev) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci struct mtk_base_afe *afe; 47462306a36Sopenharmony_ci struct mt7986_afe_private *afe_priv; 47562306a36Sopenharmony_ci struct device *dev; 47662306a36Sopenharmony_ci int i, irq_id, ret; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); 47962306a36Sopenharmony_ci if (!afe) 48062306a36Sopenharmony_ci return -ENOMEM; 48162306a36Sopenharmony_ci platform_set_drvdata(pdev, afe); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), 48462306a36Sopenharmony_ci GFP_KERNEL); 48562306a36Sopenharmony_ci if (!afe->platform_priv) 48662306a36Sopenharmony_ci return -ENOMEM; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci afe_priv = afe->platform_priv; 48962306a36Sopenharmony_ci afe->dev = &pdev->dev; 49062306a36Sopenharmony_ci dev = afe->dev; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci afe->base_addr = devm_platform_ioremap_resource(pdev, 0); 49362306a36Sopenharmony_ci if (IS_ERR(afe->base_addr)) 49462306a36Sopenharmony_ci return PTR_ERR(afe->base_addr); 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* initial audio related clock */ 49762306a36Sopenharmony_ci ret = mt7986_init_clock(afe); 49862306a36Sopenharmony_ci if (ret) 49962306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Cannot initialize clocks\n"); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci ret = devm_pm_runtime_enable(dev); 50262306a36Sopenharmony_ci if (ret) 50362306a36Sopenharmony_ci return ret; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci /* enable clock for regcache get default value from hw */ 50662306a36Sopenharmony_ci afe_priv->pm_runtime_bypass_reg_ctl = true; 50762306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, 51062306a36Sopenharmony_ci &mt7986_afe_regmap_config); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 51362306a36Sopenharmony_ci if (IS_ERR(afe->regmap)) 51462306a36Sopenharmony_ci return PTR_ERR(afe->regmap); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci afe_priv->pm_runtime_bypass_reg_ctl = false; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* init memif */ 51962306a36Sopenharmony_ci afe->memif_size = MT7986_MEMIF_NUM; 52062306a36Sopenharmony_ci afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), 52162306a36Sopenharmony_ci GFP_KERNEL); 52262306a36Sopenharmony_ci if (!afe->memif) 52362306a36Sopenharmony_ci return -ENOMEM; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci for (i = 0; i < afe->memif_size; i++) { 52662306a36Sopenharmony_ci afe->memif[i].data = &memif_data[i]; 52762306a36Sopenharmony_ci afe->memif[i].irq_usage = -1; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci mutex_init(&afe->irq_alloc_lock); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* irq initialize */ 53362306a36Sopenharmony_ci afe->irqs_size = MT7986_IRQ_NUM; 53462306a36Sopenharmony_ci afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), 53562306a36Sopenharmony_ci GFP_KERNEL); 53662306a36Sopenharmony_ci if (!afe->irqs) 53762306a36Sopenharmony_ci return -ENOMEM; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci for (i = 0; i < afe->irqs_size; i++) 54062306a36Sopenharmony_ci afe->irqs[i].irq_data = &irq_data[i]; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci /* request irq */ 54362306a36Sopenharmony_ci irq_id = platform_get_irq(pdev, 0); 54462306a36Sopenharmony_ci if (irq_id < 0) { 54562306a36Sopenharmony_ci ret = irq_id; 54662306a36Sopenharmony_ci return dev_err_probe(dev, ret, "No irq found\n"); 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci ret = devm_request_irq(dev, irq_id, mt7986_afe_irq_handler, 54962306a36Sopenharmony_ci IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); 55062306a36Sopenharmony_ci if (ret) 55162306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Failed to request irq for asys-isr\n"); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* init sub_dais */ 55462306a36Sopenharmony_ci INIT_LIST_HEAD(&afe->sub_dais); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { 55762306a36Sopenharmony_ci ret = dai_register_cbs[i](afe); 55862306a36Sopenharmony_ci if (ret) 55962306a36Sopenharmony_ci return dev_err_probe(dev, ret, "DAI register failed, i: %d\n", i); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* init dai_driver and component_driver */ 56362306a36Sopenharmony_ci ret = mtk_afe_combine_sub_dai(afe); 56462306a36Sopenharmony_ci if (ret) 56562306a36Sopenharmony_ci return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n"); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci afe->mtk_afe_hardware = &mt7986_afe_hardware; 56862306a36Sopenharmony_ci afe->memif_fs = mt7986_memif_fs; 56962306a36Sopenharmony_ci afe->irq_fs = mt7986_irq_fs; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci afe->runtime_resume = mt7986_afe_runtime_resume; 57262306a36Sopenharmony_ci afe->runtime_suspend = mt7986_afe_runtime_suspend; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* register component */ 57562306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&pdev->dev, 57662306a36Sopenharmony_ci &mt7986_afe_component, 57762306a36Sopenharmony_ci NULL, 0); 57862306a36Sopenharmony_ci if (ret) 57962306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Cannot register AFE component\n"); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci ret = devm_snd_soc_register_component(afe->dev, 58262306a36Sopenharmony_ci &mt7986_afe_pcm_dai_component, 58362306a36Sopenharmony_ci afe->dai_drivers, 58462306a36Sopenharmony_ci afe->num_dai_drivers); 58562306a36Sopenharmony_ci if (ret) 58662306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Cannot register PCM DAI component\n"); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci return 0; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic void mt7986_afe_pcm_dev_remove(struct platform_device *pdev) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 59462306a36Sopenharmony_ci if (!pm_runtime_status_suspended(&pdev->dev)) 59562306a36Sopenharmony_ci mt7986_afe_runtime_suspend(&pdev->dev); 59662306a36Sopenharmony_ci} 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const struct of_device_id mt7986_afe_pcm_dt_match[] = { 59962306a36Sopenharmony_ci { .compatible = "mediatek,mt7986-afe" }, 60062306a36Sopenharmony_ci { /* sentinel */ } 60162306a36Sopenharmony_ci}; 60262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mt7986_afe_pcm_dt_match); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic const struct dev_pm_ops mt7986_afe_pm_ops = { 60562306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(mt7986_afe_runtime_suspend, 60662306a36Sopenharmony_ci mt7986_afe_runtime_resume, NULL) 60762306a36Sopenharmony_ci}; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic struct platform_driver mt7986_afe_pcm_driver = { 61062306a36Sopenharmony_ci .driver = { 61162306a36Sopenharmony_ci .name = "mt7986-audio", 61262306a36Sopenharmony_ci .of_match_table = mt7986_afe_pcm_dt_match, 61362306a36Sopenharmony_ci .pm = &mt7986_afe_pm_ops, 61462306a36Sopenharmony_ci }, 61562306a36Sopenharmony_ci .probe = mt7986_afe_pcm_dev_probe, 61662306a36Sopenharmony_ci .remove_new = mt7986_afe_pcm_dev_remove, 61762306a36Sopenharmony_ci}; 61862306a36Sopenharmony_cimodule_platform_driver(mt7986_afe_pcm_driver); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ciMODULE_DESCRIPTION("MediaTek SoC AFE platform driver for ALSA MT7986"); 62162306a36Sopenharmony_ciMODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>"); 62262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 623