Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: mediatek: Add AFE platform driver

This is the DPCM based platform driver of AFE (Audio Front End) unit.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Koro Chen <koro.chen@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Koro Chen and committed by
Mark Brown
ee0bcaff b787f68c

+1400
+45
Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt
··· 1 + Mediatek AFE PCM controller 2 + 3 + Required properties: 4 + - compatible = "mediatek,mt8173-afe-pcm"; 5 + - reg: register location and size 6 + - interrupts: Should contain AFE interrupt 7 + - clock-names: should have these clock names: 8 + "infra_sys_audio_clk", 9 + "top_pdn_audio", 10 + "top_pdn_aud_intbus", 11 + "bck0", 12 + "bck1", 13 + "i2s0_m", 14 + "i2s1_m", 15 + "i2s2_m", 16 + "i2s3_m", 17 + "i2s3_b"; 18 + 19 + Example: 20 + 21 + afe: mt8173-afe-pcm@11220000 { 22 + compatible = "mediatek,mt8173-afe-pcm"; 23 + reg = <0 0x11220000 0 0x1000>; 24 + interrupts = <GIC_SPI 134 IRQ_TYPE_EDGE_FALLING>; 25 + clocks = <&infracfg INFRA_AUDIO>, 26 + <&topckgen TOP_AUDIO_SEL>, 27 + <&topckgen TOP_AUD_INTBUS_SEL>, 28 + <&topckgen TOP_APLL1_DIV0>, 29 + <&topckgen TOP_APLL2_DIV0>, 30 + <&topckgen TOP_I2S0_M_CK_SEL>, 31 + <&topckgen TOP_I2S1_M_CK_SEL>, 32 + <&topckgen TOP_I2S2_M_CK_SEL>, 33 + <&topckgen TOP_I2S3_M_CK_SEL>, 34 + <&topckgen TOP_I2S3_B_CK_SEL>; 35 + clock-names = "infra_sys_audio_clk", 36 + "top_pdn_audio", 37 + "top_pdn_aud_intbus", 38 + "bck0", 39 + "bck1", 40 + "i2s0_m", 41 + "i2s1_m", 42 + "i2s2_m", 43 + "i2s3_m", 44 + "i2s3_b"; 45 + };
+1
sound/soc/Kconfig
··· 45 45 source "sound/soc/omap/Kconfig" 46 46 source "sound/soc/kirkwood/Kconfig" 47 47 source "sound/soc/intel/Kconfig" 48 + source "sound/soc/mediatek/Kconfig" 48 49 source "sound/soc/mxs/Kconfig" 49 50 source "sound/soc/pxa/Kconfig" 50 51 source "sound/soc/qcom/Kconfig"
+1
sound/soc/Makefile
··· 23 23 obj-$(CONFIG_SND_SOC) += fsl/ 24 24 obj-$(CONFIG_SND_SOC) += jz4740/ 25 25 obj-$(CONFIG_SND_SOC) += intel/ 26 + obj-$(CONFIG_SND_SOC) += mediatek/ 26 27 obj-$(CONFIG_SND_SOC) += mxs/ 27 28 obj-$(CONFIG_SND_SOC) += nuc900/ 28 29 obj-$(CONFIG_SND_SOC) += omap/
+9
sound/soc/mediatek/Kconfig
··· 1 + config SND_SOC_MEDIATEK 2 + tristate "ASoC support for Mediatek chip" 3 + depends on ARCH_MEDIATEK 4 + help 5 + This adds ASoC platform driver support for Mediatek chip 6 + that can be used with other codecs. 7 + Select Y if you have such device. 8 + Ex: MT8173 9 +
+2
sound/soc/mediatek/Makefile
··· 1 + # MTK Platform Support 2 + obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o
+109
sound/soc/mediatek/mtk-afe-common.h
··· 1 + /* 2 + * mtk_afe_common.h -- Mediatek audio driver common definitions 3 + * 4 + * Copyright (c) 2015 MediaTek Inc. 5 + * Author: Koro Chen <koro.chen@mediatek.com> 6 + * Sascha Hauer <s.hauer@pengutronix.de> 7 + * Hidalgo Huang <hidalgo.huang@mediatek.com> 8 + * Ir Lian <ir.lian@mediatek.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 and 12 + * only version 2 as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + 20 + #ifndef _MTK_AFE_COMMON_H_ 21 + #define _MTK_AFE_COMMON_H_ 22 + 23 + #include <linux/clk.h> 24 + #include <linux/regmap.h> 25 + 26 + enum { 27 + MTK_AFE_MEMIF_DL1, 28 + MTK_AFE_MEMIF_DL2, 29 + MTK_AFE_MEMIF_VUL, 30 + MTK_AFE_MEMIF_DAI, 31 + MTK_AFE_MEMIF_AWB, 32 + MTK_AFE_MEMIF_MOD_DAI, 33 + MTK_AFE_MEMIF_HDMI, 34 + MTK_AFE_MEMIF_NUM, 35 + MTK_AFE_IO_MOD_PCM1 = MTK_AFE_MEMIF_NUM, 36 + MTK_AFE_IO_MOD_PCM2, 37 + MTK_AFE_IO_PMIC, 38 + MTK_AFE_IO_I2S, 39 + MTK_AFE_IO_2ND_I2S, 40 + MTK_AFE_IO_HW_GAIN1, 41 + MTK_AFE_IO_HW_GAIN2, 42 + MTK_AFE_IO_MRG_O, 43 + MTK_AFE_IO_MRG_I, 44 + MTK_AFE_IO_DAIBT, 45 + MTK_AFE_IO_HDMI, 46 + }; 47 + 48 + enum { 49 + MTK_AFE_IRQ_1, 50 + MTK_AFE_IRQ_2, 51 + MTK_AFE_IRQ_3, 52 + MTK_AFE_IRQ_4, 53 + MTK_AFE_IRQ_5, 54 + MTK_AFE_IRQ_6, 55 + MTK_AFE_IRQ_7, 56 + MTK_AFE_IRQ_8, 57 + MTK_AFE_IRQ_NUM, 58 + }; 59 + 60 + enum { 61 + MTK_CLK_INFRASYS_AUD, 62 + MTK_CLK_TOP_PDN_AUD, 63 + MTK_CLK_TOP_PDN_AUD_BUS, 64 + MTK_CLK_I2S0_M, 65 + MTK_CLK_I2S1_M, 66 + MTK_CLK_I2S2_M, 67 + MTK_CLK_I2S3_M, 68 + MTK_CLK_I2S3_B, 69 + MTK_CLK_BCK0, 70 + MTK_CLK_BCK1, 71 + MTK_CLK_NUM 72 + }; 73 + 74 + struct mtk_afe; 75 + struct snd_pcm_substream; 76 + 77 + struct mtk_afe_memif_data { 78 + int id; 79 + const char *name; 80 + int reg_ofs_base; 81 + int reg_ofs_cur; 82 + int fs_shift; 83 + int mono_shift; 84 + int enable_shift; 85 + int irq_reg_cnt; 86 + int irq_cnt_shift; 87 + int irq_en_shift; 88 + int irq_fs_shift; 89 + int irq_clr_shift; 90 + }; 91 + 92 + struct mtk_afe_memif { 93 + unsigned int phys_buf_addr; 94 + int buffer_size; 95 + unsigned int hw_ptr; /* Previous IRQ's HW ptr */ 96 + struct snd_pcm_substream *substream; 97 + const struct mtk_afe_memif_data *data; 98 + const struct mtk_afe_irq_data *irqdata; 99 + }; 100 + 101 + struct mtk_afe { 102 + /* address for ioremap audio hardware register */ 103 + void __iomem *base_addr; 104 + struct device *dev; 105 + struct regmap *regmap; 106 + struct mtk_afe_memif memif[MTK_AFE_MEMIF_NUM]; 107 + struct clk *clocks[MTK_CLK_NUM]; 108 + }; 109 + #endif
+1233
sound/soc/mediatek/mtk-afe-pcm.c
··· 1 + /* 2 + * Mediatek ALSA SoC AFE platform driver 3 + * 4 + * Copyright (c) 2015 MediaTek Inc. 5 + * Author: Koro Chen <koro.chen@mediatek.com> 6 + * Sascha Hauer <s.hauer@pengutronix.de> 7 + * Hidalgo Huang <hidalgo.huang@mediatek.com> 8 + * Ir Lian <ir.lian@mediatek.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 and 12 + * only version 2 as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, 15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 + * GNU General Public License for more details. 18 + */ 19 + 20 + #include <linux/delay.h> 21 + #include <linux/module.h> 22 + #include <linux/of.h> 23 + #include <linux/of_address.h> 24 + #include <linux/pm_runtime.h> 25 + #include <sound/soc.h> 26 + #include "mtk-afe-common.h" 27 + 28 + /***************************************************************************** 29 + * R E G I S T E R D E F I N I T I O N 30 + *****************************************************************************/ 31 + #define AUDIO_TOP_CON0 0x0000 32 + #define AUDIO_TOP_CON1 0x0004 33 + #define AFE_DAC_CON0 0x0010 34 + #define AFE_DAC_CON1 0x0014 35 + #define AFE_I2S_CON1 0x0034 36 + #define AFE_I2S_CON2 0x0038 37 + #define AFE_CONN_24BIT 0x006c 38 + 39 + #define AFE_CONN1 0x0024 40 + #define AFE_CONN2 0x0028 41 + #define AFE_CONN7 0x0460 42 + #define AFE_CONN8 0x0464 43 + #define AFE_HDMI_CONN0 0x0390 44 + 45 + /* Memory interface */ 46 + #define AFE_DL1_BASE 0x0040 47 + #define AFE_DL1_CUR 0x0044 48 + #define AFE_DL2_BASE 0x0050 49 + #define AFE_DL2_CUR 0x0054 50 + #define AFE_AWB_BASE 0x0070 51 + #define AFE_AWB_CUR 0x007c 52 + #define AFE_VUL_BASE 0x0080 53 + #define AFE_VUL_CUR 0x008c 54 + #define AFE_DAI_BASE 0x0090 55 + #define AFE_DAI_CUR 0x009c 56 + #define AFE_MOD_PCM_BASE 0x0330 57 + #define AFE_MOD_PCM_CUR 0x033c 58 + #define AFE_HDMI_OUT_BASE 0x0374 59 + #define AFE_HDMI_OUT_CUR 0x0378 60 + 61 + #define AFE_ADDA2_TOP_CON0 0x0600 62 + 63 + #define AFE_HDMI_OUT_CON0 0x0370 64 + 65 + #define AFE_IRQ_MCU_CON 0x03a0 66 + #define AFE_IRQ_STATUS 0x03a4 67 + #define AFE_IRQ_CLR 0x03a8 68 + #define AFE_IRQ_CNT1 0x03ac 69 + #define AFE_IRQ_CNT2 0x03b0 70 + #define AFE_IRQ_MCU_EN 0x03b4 71 + #define AFE_IRQ_CNT5 0x03bc 72 + #define AFE_IRQ_CNT7 0x03dc 73 + 74 + #define AFE_TDM_CON1 0x0548 75 + #define AFE_TDM_CON2 0x054c 76 + 77 + #define AFE_BASE_END_OFFSET 8 78 + #define AFE_IRQ_STATUS_BITS 0xff 79 + 80 + /* AUDIO_TOP_CON0 (0x0000) */ 81 + #define AUD_TCON0_PDN_SPDF (0x1 << 21) 82 + #define AUD_TCON0_PDN_HDMI (0x1 << 20) 83 + #define AUD_TCON0_PDN_24M (0x1 << 9) 84 + #define AUD_TCON0_PDN_22M (0x1 << 8) 85 + #define AUD_TCON0_PDN_AFE (0x1 << 2) 86 + 87 + /* AFE_I2S_CON1 (0x0034) */ 88 + #define AFE_I2S_CON1_LOW_JITTER_CLK (0x1 << 12) 89 + #define AFE_I2S_CON1_RATE(x) (((x) & 0xf) << 8) 90 + #define AFE_I2S_CON1_FORMAT_I2S (0x1 << 3) 91 + #define AFE_I2S_CON1_EN (0x1 << 0) 92 + 93 + /* AFE_I2S_CON2 (0x0038) */ 94 + #define AFE_I2S_CON2_LOW_JITTER_CLK (0x1 << 12) 95 + #define AFE_I2S_CON2_RATE(x) (((x) & 0xf) << 8) 96 + #define AFE_I2S_CON2_FORMAT_I2S (0x1 << 3) 97 + #define AFE_I2S_CON2_EN (0x1 << 0) 98 + 99 + /* AFE_CONN_24BIT (0x006c) */ 100 + #define AFE_CONN_24BIT_O04 (0x1 << 4) 101 + #define AFE_CONN_24BIT_O03 (0x1 << 3) 102 + 103 + /* AFE_HDMI_CONN0 (0x0390) */ 104 + #define AFE_HDMI_CONN0_O37_I37 (0x7 << 21) 105 + #define AFE_HDMI_CONN0_O36_I36 (0x6 << 18) 106 + #define AFE_HDMI_CONN0_O35_I33 (0x3 << 15) 107 + #define AFE_HDMI_CONN0_O34_I32 (0x2 << 12) 108 + #define AFE_HDMI_CONN0_O33_I35 (0x5 << 9) 109 + #define AFE_HDMI_CONN0_O32_I34 (0x4 << 6) 110 + #define AFE_HDMI_CONN0_O31_I31 (0x1 << 3) 111 + #define AFE_HDMI_CONN0_O30_I30 (0x0 << 0) 112 + 113 + /* AFE_TDM_CON1 (0x0548) */ 114 + #define AFE_TDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 24) 115 + #define AFE_TDM_CON1_32_BCK_CYCLES (0x2 << 12) 116 + #define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8) 117 + #define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4) 118 + #define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3) 119 + #define AFE_TDM_CON1_BCK_INV (0x1 << 1) 120 + #define AFE_TDM_CON1_EN (0x1 << 0) 121 + 122 + enum afe_tdm_ch_start { 123 + AFE_TDM_CH_START_O30_O31 = 0, 124 + AFE_TDM_CH_START_O32_O33, 125 + AFE_TDM_CH_START_O34_O35, 126 + AFE_TDM_CH_START_O36_O37, 127 + AFE_TDM_CH_ZERO, 128 + }; 129 + 130 + static const struct snd_pcm_hardware mtk_afe_hardware = { 131 + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 132 + SNDRV_PCM_INFO_MMAP_VALID), 133 + .buffer_bytes_max = 256 * 1024, 134 + .period_bytes_min = 512, 135 + .period_bytes_max = 128 * 1024, 136 + .periods_min = 2, 137 + .periods_max = 256, 138 + .fifo_size = 0, 139 + }; 140 + 141 + static snd_pcm_uframes_t mtk_afe_pcm_pointer 142 + (struct snd_pcm_substream *substream) 143 + { 144 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 145 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 146 + struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 147 + 148 + return bytes_to_frames(substream->runtime, memif->hw_ptr); 149 + } 150 + 151 + static const struct snd_pcm_ops mtk_afe_pcm_ops = { 152 + .ioctl = snd_pcm_lib_ioctl, 153 + .pointer = mtk_afe_pcm_pointer, 154 + }; 155 + 156 + static int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd) 157 + { 158 + size_t size; 159 + struct snd_card *card = rtd->card->snd_card; 160 + struct snd_pcm *pcm = rtd->pcm; 161 + 162 + size = mtk_afe_hardware.buffer_bytes_max; 163 + 164 + return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 165 + card->dev, size, size); 166 + } 167 + 168 + static void mtk_afe_pcm_free(struct snd_pcm *pcm) 169 + { 170 + snd_pcm_lib_preallocate_free_for_all(pcm); 171 + } 172 + 173 + static const struct snd_soc_platform_driver mtk_afe_pcm_platform = { 174 + .ops = &mtk_afe_pcm_ops, 175 + .pcm_new = mtk_afe_pcm_new, 176 + .pcm_free = mtk_afe_pcm_free, 177 + }; 178 + 179 + struct mtk_afe_rate { 180 + unsigned int rate; 181 + unsigned int regvalue; 182 + }; 183 + 184 + static const struct mtk_afe_rate mtk_afe_i2s_rates[] = { 185 + { .rate = 8000, .regvalue = 0 }, 186 + { .rate = 11025, .regvalue = 1 }, 187 + { .rate = 12000, .regvalue = 2 }, 188 + { .rate = 16000, .regvalue = 4 }, 189 + { .rate = 22050, .regvalue = 5 }, 190 + { .rate = 24000, .regvalue = 6 }, 191 + { .rate = 32000, .regvalue = 8 }, 192 + { .rate = 44100, .regvalue = 9 }, 193 + { .rate = 48000, .regvalue = 10 }, 194 + { .rate = 88000, .regvalue = 11 }, 195 + { .rate = 96000, .regvalue = 12 }, 196 + { .rate = 174000, .regvalue = 13 }, 197 + { .rate = 192000, .regvalue = 14 }, 198 + }; 199 + 200 + static int mtk_afe_i2s_fs(unsigned int sample_rate) 201 + { 202 + int i; 203 + 204 + for (i = 0; i < ARRAY_SIZE(mtk_afe_i2s_rates); i++) 205 + if (mtk_afe_i2s_rates[i].rate == sample_rate) 206 + return mtk_afe_i2s_rates[i].regvalue; 207 + 208 + return -EINVAL; 209 + } 210 + 211 + static int mtk_afe_set_i2s(struct mtk_afe *afe, unsigned int rate) 212 + { 213 + unsigned int val; 214 + int fs = mtk_afe_i2s_fs(rate); 215 + 216 + if (fs < 0) 217 + return -EINVAL; 218 + 219 + /* from external ADC */ 220 + regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1); 221 + 222 + /* set input */ 223 + val = AFE_I2S_CON2_LOW_JITTER_CLK | 224 + AFE_I2S_CON2_RATE(fs) | 225 + AFE_I2S_CON2_FORMAT_I2S; 226 + 227 + regmap_update_bits(afe->regmap, AFE_I2S_CON2, ~AFE_I2S_CON2_EN, val); 228 + 229 + /* set output */ 230 + val = AFE_I2S_CON1_LOW_JITTER_CLK | 231 + AFE_I2S_CON1_RATE(fs) | 232 + AFE_I2S_CON1_FORMAT_I2S; 233 + 234 + regmap_update_bits(afe->regmap, AFE_I2S_CON1, ~AFE_I2S_CON1_EN, val); 235 + return 0; 236 + } 237 + 238 + static void mtk_afe_set_i2s_enable(struct mtk_afe *afe, bool enable) 239 + { 240 + unsigned int val; 241 + 242 + regmap_read(afe->regmap, AFE_I2S_CON2, &val); 243 + if (!!(val & AFE_I2S_CON2_EN) == enable) 244 + return; /* must skip soft reset */ 245 + 246 + /* I2S soft reset begin */ 247 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0x4); 248 + 249 + /* input */ 250 + regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable); 251 + 252 + /* output */ 253 + regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable); 254 + 255 + /* I2S soft reset end */ 256 + udelay(1); 257 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0); 258 + } 259 + 260 + static int mtk_afe_dais_enable_clks(struct mtk_afe *afe, 261 + struct clk *m_ck, struct clk *b_ck) 262 + { 263 + int ret; 264 + 265 + if (m_ck) { 266 + ret = clk_prepare_enable(m_ck); 267 + if (ret) { 268 + dev_err(afe->dev, "Failed to enable m_ck\n"); 269 + return ret; 270 + } 271 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 272 + AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0); 273 + } 274 + 275 + if (b_ck) { 276 + ret = clk_prepare_enable(b_ck); 277 + if (ret) { 278 + dev_err(afe->dev, "Failed to enable b_ck\n"); 279 + return ret; 280 + } 281 + } 282 + return 0; 283 + } 284 + 285 + static int mtk_afe_dais_set_clks(struct mtk_afe *afe, 286 + struct clk *m_ck, unsigned int mck_rate, 287 + struct clk *b_ck, unsigned int bck_rate) 288 + { 289 + int ret; 290 + 291 + if (m_ck) { 292 + ret = clk_set_rate(m_ck, mck_rate); 293 + if (ret) { 294 + dev_err(afe->dev, "Failed to set m_ck rate\n"); 295 + return ret; 296 + } 297 + } 298 + 299 + if (b_ck) { 300 + ret = clk_set_rate(b_ck, bck_rate); 301 + if (ret) { 302 + dev_err(afe->dev, "Failed to set b_ck rate\n"); 303 + return ret; 304 + } 305 + } 306 + return 0; 307 + } 308 + 309 + static void mtk_afe_dais_disable_clks(struct mtk_afe *afe, 310 + struct clk *m_ck, struct clk *b_ck) 311 + { 312 + if (m_ck) { 313 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 314 + AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 315 + AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M); 316 + clk_disable_unprepare(m_ck); 317 + } 318 + if (b_ck) 319 + clk_disable_unprepare(b_ck); 320 + } 321 + 322 + static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream, 323 + struct snd_soc_dai *dai) 324 + { 325 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 326 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 327 + 328 + if (dai->active) 329 + return 0; 330 + 331 + mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); 332 + return 0; 333 + } 334 + 335 + static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream, 336 + struct snd_soc_dai *dai) 337 + { 338 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 339 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 340 + 341 + if (dai->active) 342 + return; 343 + 344 + mtk_afe_set_i2s_enable(afe, false); 345 + mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL); 346 + 347 + /* disable AFE */ 348 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0); 349 + } 350 + 351 + static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream, 352 + struct snd_soc_dai *dai) 353 + { 354 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 355 + struct snd_pcm_runtime * const runtime = substream->runtime; 356 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 357 + int ret; 358 + 359 + mtk_afe_dais_set_clks(afe, 360 + afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256, 361 + NULL, 0); 362 + /* config I2S */ 363 + ret = mtk_afe_set_i2s(afe, substream->runtime->rate); 364 + if (ret) 365 + return ret; 366 + 367 + mtk_afe_set_i2s_enable(afe, true); 368 + 369 + return 0; 370 + } 371 + 372 + static int mtk_afe_hdmi_startup(struct snd_pcm_substream *substream, 373 + struct snd_soc_dai *dai) 374 + { 375 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 376 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 377 + 378 + if (dai->active) 379 + return 0; 380 + 381 + mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S3_M], 382 + afe->clocks[MTK_CLK_I2S3_B]); 383 + return 0; 384 + } 385 + 386 + static void mtk_afe_hdmi_shutdown(struct snd_pcm_substream *substream, 387 + struct snd_soc_dai *dai) 388 + { 389 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 390 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 391 + 392 + if (dai->active) 393 + return; 394 + 395 + mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S3_M], 396 + afe->clocks[MTK_CLK_I2S3_B]); 397 + 398 + /* disable AFE */ 399 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0); 400 + } 401 + 402 + static int mtk_afe_hdmi_prepare(struct snd_pcm_substream *substream, 403 + struct snd_soc_dai *dai) 404 + { 405 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 406 + struct snd_pcm_runtime * const runtime = substream->runtime; 407 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 408 + unsigned int val; 409 + 410 + mtk_afe_dais_set_clks(afe, 411 + afe->clocks[MTK_CLK_I2S3_M], runtime->rate * 128, 412 + afe->clocks[MTK_CLK_I2S3_B], 413 + runtime->rate * runtime->channels * 32); 414 + 415 + val = AFE_TDM_CON1_BCK_INV | 416 + AFE_TDM_CON1_1_BCK_DELAY | 417 + AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */ 418 + AFE_TDM_CON1_WLEN_32BIT | 419 + AFE_TDM_CON1_32_BCK_CYCLES | 420 + AFE_TDM_CON1_LRCK_WIDTH(32); 421 + regmap_update_bits(afe->regmap, AFE_TDM_CON1, ~AFE_TDM_CON1_EN, val); 422 + 423 + /* set tdm2 config */ 424 + switch (runtime->channels) { 425 + case 1: 426 + case 2: 427 + val = AFE_TDM_CH_START_O30_O31; 428 + val |= (AFE_TDM_CH_ZERO << 4); 429 + val |= (AFE_TDM_CH_ZERO << 8); 430 + val |= (AFE_TDM_CH_ZERO << 12); 431 + break; 432 + case 3: 433 + case 4: 434 + val = AFE_TDM_CH_START_O30_O31; 435 + val |= (AFE_TDM_CH_START_O32_O33 << 4); 436 + val |= (AFE_TDM_CH_ZERO << 8); 437 + val |= (AFE_TDM_CH_ZERO << 12); 438 + break; 439 + case 5: 440 + case 6: 441 + val = AFE_TDM_CH_START_O30_O31; 442 + val |= (AFE_TDM_CH_START_O32_O33 << 4); 443 + val |= (AFE_TDM_CH_START_O34_O35 << 8); 444 + val |= (AFE_TDM_CH_ZERO << 12); 445 + break; 446 + case 7: 447 + case 8: 448 + val = AFE_TDM_CH_START_O30_O31; 449 + val |= (AFE_TDM_CH_START_O32_O33 << 4); 450 + val |= (AFE_TDM_CH_START_O34_O35 << 8); 451 + val |= (AFE_TDM_CH_START_O36_O37 << 12); 452 + break; 453 + default: 454 + val = 0; 455 + } 456 + regmap_update_bits(afe->regmap, AFE_TDM_CON2, 0x0000ffff, val); 457 + 458 + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 459 + 0x000000f0, runtime->channels << 4); 460 + return 0; 461 + } 462 + 463 + static int mtk_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, 464 + struct snd_soc_dai *dai) 465 + { 466 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 467 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 468 + 469 + dev_info(afe->dev, "%s cmd=%d %s\n", __func__, cmd, dai->name); 470 + 471 + switch (cmd) { 472 + case SNDRV_PCM_TRIGGER_START: 473 + case SNDRV_PCM_TRIGGER_RESUME: 474 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 475 + AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF, 0); 476 + 477 + /* set connections: O30~O37: L/R/LS/RS/C/LFE/CH7/CH8 */ 478 + regmap_write(afe->regmap, AFE_HDMI_CONN0, 479 + AFE_HDMI_CONN0_O30_I30 | AFE_HDMI_CONN0_O31_I31 | 480 + AFE_HDMI_CONN0_O32_I34 | AFE_HDMI_CONN0_O33_I35 | 481 + AFE_HDMI_CONN0_O34_I32 | AFE_HDMI_CONN0_O35_I33 | 482 + AFE_HDMI_CONN0_O36_I36 | AFE_HDMI_CONN0_O37_I37); 483 + 484 + /* enable Out control */ 485 + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1); 486 + 487 + /* enable tdm */ 488 + regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0x1); 489 + 490 + return 0; 491 + case SNDRV_PCM_TRIGGER_STOP: 492 + case SNDRV_PCM_TRIGGER_SUSPEND: 493 + /* disable tdm */ 494 + regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0); 495 + 496 + /* disable Out control */ 497 + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0); 498 + 499 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 500 + AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF, 501 + AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF); 502 + 503 + return 0; 504 + default: 505 + return -EINVAL; 506 + } 507 + } 508 + 509 + static int mtk_afe_dais_startup(struct snd_pcm_substream *substream, 510 + struct snd_soc_dai *dai) 511 + { 512 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 513 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 514 + struct snd_pcm_runtime *runtime = substream->runtime; 515 + struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 516 + int ret; 517 + 518 + memif->substream = substream; 519 + 520 + snd_soc_set_runtime_hwparams(substream, &mtk_afe_hardware); 521 + ret = snd_pcm_hw_constraint_integer(runtime, 522 + SNDRV_PCM_HW_PARAM_PERIODS); 523 + if (ret < 0) 524 + dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); 525 + return ret; 526 + } 527 + 528 + static void mtk_afe_dais_shutdown(struct snd_pcm_substream *substream, 529 + struct snd_soc_dai *dai) 530 + { 531 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 532 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 533 + struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 534 + 535 + memif->substream = NULL; 536 + } 537 + 538 + static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, 539 + struct snd_pcm_hw_params *params, 540 + struct snd_soc_dai *dai) 541 + { 542 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 543 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 544 + struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 545 + int ret; 546 + 547 + dev_dbg(afe->dev, 548 + "%s period = %u, rate= %u, channels=%u\n", 549 + __func__, params_period_size(params), params_rate(params), 550 + params_channels(params)); 551 + 552 + ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 553 + if (ret < 0) 554 + return ret; 555 + 556 + memif->phys_buf_addr = substream->runtime->dma_addr; 557 + memif->buffer_size = substream->runtime->dma_bytes; 558 + memif->hw_ptr = 0; 559 + 560 + /* start */ 561 + regmap_write(afe->regmap, 562 + memif->data->reg_ofs_base, memif->phys_buf_addr); 563 + /* end */ 564 + regmap_write(afe->regmap, 565 + memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, 566 + memif->phys_buf_addr + memif->buffer_size - 1); 567 + 568 + /* set channel */ 569 + if (memif->data->mono_shift >= 0) { 570 + unsigned int mono = (params_channels(params) == 1) ? 1 : 0; 571 + 572 + regmap_update_bits(afe->regmap, AFE_DAC_CON1, 573 + 1 << memif->data->mono_shift, 574 + mono << memif->data->mono_shift); 575 + } 576 + 577 + /* set rate */ 578 + if (memif->data->fs_shift < 0) 579 + return 0; 580 + if (memif->data->id == MTK_AFE_MEMIF_DAI || 581 + memif->data->id == MTK_AFE_MEMIF_MOD_DAI) { 582 + unsigned int val; 583 + 584 + switch (params_rate(params)) { 585 + case 8000: 586 + val = 0; 587 + break; 588 + case 16000: 589 + val = 1; 590 + break; 591 + case 32000: 592 + val = 2; 593 + break; 594 + default: 595 + return -EINVAL; 596 + } 597 + 598 + if (memif->data->id == MTK_AFE_MEMIF_DAI) 599 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 600 + 0x3 << memif->data->fs_shift, 601 + val << memif->data->fs_shift); 602 + else 603 + regmap_update_bits(afe->regmap, AFE_DAC_CON1, 604 + 0x3 << memif->data->fs_shift, 605 + val << memif->data->fs_shift); 606 + 607 + } else { 608 + int fs = mtk_afe_i2s_fs(params_rate(params)); 609 + 610 + if (fs < 0) 611 + return -EINVAL; 612 + 613 + regmap_update_bits(afe->regmap, AFE_DAC_CON1, 614 + 0xf << memif->data->fs_shift, 615 + fs << memif->data->fs_shift); 616 + } 617 + 618 + return 0; 619 + } 620 + 621 + static int mtk_afe_dais_hw_free(struct snd_pcm_substream *substream, 622 + struct snd_soc_dai *dai) 623 + { 624 + return snd_pcm_lib_free_pages(substream); 625 + } 626 + 627 + static int mtk_afe_dais_prepare(struct snd_pcm_substream *substream, 628 + struct snd_soc_dai *dai) 629 + { 630 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 631 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 632 + 633 + /* enable AFE */ 634 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1); 635 + return 0; 636 + } 637 + 638 + static int mtk_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd, 639 + struct snd_soc_dai *dai) 640 + { 641 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 642 + struct snd_pcm_runtime * const runtime = substream->runtime; 643 + struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 644 + struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 645 + unsigned int counter = runtime->period_size; 646 + 647 + dev_info(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd); 648 + 649 + switch (cmd) { 650 + case SNDRV_PCM_TRIGGER_START: 651 + case SNDRV_PCM_TRIGGER_RESUME: 652 + if (memif->data->enable_shift >= 0) 653 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 654 + 1 << memif->data->enable_shift, 655 + 1 << memif->data->enable_shift); 656 + 657 + /* set irq counter */ 658 + regmap_update_bits(afe->regmap, 659 + memif->data->irq_reg_cnt, 660 + 0x3ffff << memif->data->irq_cnt_shift, 661 + counter << memif->data->irq_cnt_shift); 662 + 663 + /* set irq fs */ 664 + if (memif->data->irq_fs_shift >= 0) { 665 + int fs = mtk_afe_i2s_fs(runtime->rate); 666 + 667 + if (fs < 0) 668 + return -EINVAL; 669 + 670 + regmap_update_bits(afe->regmap, 671 + AFE_IRQ_MCU_CON, 672 + 0xf << memif->data->irq_fs_shift, 673 + fs << memif->data->irq_fs_shift); 674 + } 675 + /* enable interrupt */ 676 + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, 677 + 1 << memif->data->irq_en_shift, 678 + 1 << memif->data->irq_en_shift); 679 + 680 + return 0; 681 + case SNDRV_PCM_TRIGGER_STOP: 682 + case SNDRV_PCM_TRIGGER_SUSPEND: 683 + if (memif->data->enable_shift >= 0) 684 + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 685 + 1 << memif->data->enable_shift, 0); 686 + /* disable interrupt */ 687 + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, 688 + 1 << memif->data->irq_en_shift, 689 + 0 << memif->data->irq_en_shift); 690 + /* and clear pending IRQ */ 691 + regmap_write(afe->regmap, AFE_IRQ_CLR, 692 + 1 << memif->data->irq_clr_shift); 693 + memif->hw_ptr = 0; 694 + return 0; 695 + default: 696 + return -EINVAL; 697 + } 698 + } 699 + 700 + /* FE DAIs */ 701 + static const struct snd_soc_dai_ops mtk_afe_dai_ops = { 702 + .startup = mtk_afe_dais_startup, 703 + .shutdown = mtk_afe_dais_shutdown, 704 + .hw_params = mtk_afe_dais_hw_params, 705 + .hw_free = mtk_afe_dais_hw_free, 706 + .prepare = mtk_afe_dais_prepare, 707 + .trigger = mtk_afe_dais_trigger, 708 + }; 709 + 710 + /* BE DAIs */ 711 + static const struct snd_soc_dai_ops mtk_afe_i2s_ops = { 712 + .startup = mtk_afe_i2s_startup, 713 + .shutdown = mtk_afe_i2s_shutdown, 714 + .prepare = mtk_afe_i2s_prepare, 715 + }; 716 + 717 + static const struct snd_soc_dai_ops mtk_afe_hdmi_ops = { 718 + .startup = mtk_afe_hdmi_startup, 719 + .shutdown = mtk_afe_hdmi_shutdown, 720 + .prepare = mtk_afe_hdmi_prepare, 721 + .trigger = mtk_afe_hdmi_trigger, 722 + 723 + }; 724 + 725 + static struct snd_soc_dai_driver mtk_afe_pcm_dais[] = { 726 + /* FE DAIs: memory intefaces to CPU */ 727 + { 728 + .name = "DL1", /* downlink 1 */ 729 + .id = MTK_AFE_MEMIF_DL1, 730 + .playback = { 731 + .stream_name = "DL1", 732 + .channels_min = 1, 733 + .channels_max = 2, 734 + .rates = SNDRV_PCM_RATE_8000_48000, 735 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 736 + }, 737 + .ops = &mtk_afe_dai_ops, 738 + }, { 739 + .name = "VUL", /* voice uplink */ 740 + .id = MTK_AFE_MEMIF_VUL, 741 + .capture = { 742 + .stream_name = "VUL", 743 + .channels_min = 1, 744 + .channels_max = 2, 745 + .rates = SNDRV_PCM_RATE_8000_48000, 746 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 747 + }, 748 + .ops = &mtk_afe_dai_ops, 749 + }, { 750 + /* BE DAIs */ 751 + .name = "I2S", 752 + .id = MTK_AFE_IO_I2S, 753 + .playback = { 754 + .stream_name = "I2S Playback", 755 + .channels_min = 1, 756 + .channels_max = 2, 757 + .rates = SNDRV_PCM_RATE_8000_48000, 758 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 759 + }, 760 + .capture = { 761 + .stream_name = "I2S Capture", 762 + .channels_min = 1, 763 + .channels_max = 2, 764 + .rates = SNDRV_PCM_RATE_8000_48000, 765 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 766 + }, 767 + .ops = &mtk_afe_i2s_ops, 768 + .symmetric_rates = 1, 769 + }, 770 + }; 771 + 772 + static struct snd_soc_dai_driver mtk_afe_hdmi_dais[] = { 773 + /* FE DAIs */ 774 + { 775 + .name = "HDMI", 776 + .id = MTK_AFE_MEMIF_HDMI, 777 + .playback = { 778 + .stream_name = "HDMI", 779 + .channels_min = 2, 780 + .channels_max = 8, 781 + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 782 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 783 + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 784 + SNDRV_PCM_RATE_192000, 785 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 786 + }, 787 + .ops = &mtk_afe_dai_ops, 788 + }, { 789 + /* BE DAIs */ 790 + .name = "HDMIO", 791 + .id = MTK_AFE_IO_HDMI, 792 + .playback = { 793 + .stream_name = "HDMIO Playback", 794 + .channels_min = 2, 795 + .channels_max = 8, 796 + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 797 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 798 + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 799 + SNDRV_PCM_RATE_192000, 800 + .formats = SNDRV_PCM_FMTBIT_S16_LE, 801 + }, 802 + .ops = &mtk_afe_hdmi_ops, 803 + }, 804 + }; 805 + 806 + static const struct snd_kcontrol_new mtk_afe_o03_mix[] = { 807 + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN1, 21, 1, 0), 808 + }; 809 + 810 + static const struct snd_kcontrol_new mtk_afe_o04_mix[] = { 811 + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN2, 6, 1, 0), 812 + }; 813 + 814 + static const struct snd_kcontrol_new mtk_afe_o09_mix[] = { 815 + SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0), 816 + }; 817 + 818 + static const struct snd_kcontrol_new mtk_afe_o10_mix[] = { 819 + SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0), 820 + }; 821 + 822 + static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = { 823 + /* Backend DAIs */ 824 + SND_SOC_DAPM_AIF_IN("I2S Capture", NULL, 0, SND_SOC_NOPM, 0, 0), 825 + SND_SOC_DAPM_AIF_OUT("I2S Playback", NULL, 0, SND_SOC_NOPM, 0, 0), 826 + 827 + /* inter-connections */ 828 + SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), 829 + SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), 830 + SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), 831 + SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), 832 + 833 + SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, 834 + mtk_afe_o03_mix, ARRAY_SIZE(mtk_afe_o03_mix)), 835 + SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0, 836 + mtk_afe_o04_mix, ARRAY_SIZE(mtk_afe_o04_mix)), 837 + SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0, 838 + mtk_afe_o09_mix, ARRAY_SIZE(mtk_afe_o09_mix)), 839 + SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0, 840 + mtk_afe_o10_mix, ARRAY_SIZE(mtk_afe_o10_mix)), 841 + }; 842 + 843 + static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = { 844 + {"I05", NULL, "DL1"}, 845 + {"I06", NULL, "DL1"}, 846 + {"I2S Playback", NULL, "O03"}, 847 + {"I2S Playback", NULL, "O04"}, 848 + {"VUL", NULL, "O09"}, 849 + {"VUL", NULL, "O10"}, 850 + {"I17", NULL, "I2S Capture"}, 851 + {"I18", NULL, "I2S Capture"}, 852 + { "O03", "I05 Switch", "I05" }, 853 + { "O04", "I06 Switch", "I06" }, 854 + { "O09", "I17 Switch", "I17" }, 855 + { "O10", "I18 Switch", "I18" }, 856 + }; 857 + 858 + static const struct snd_soc_dapm_widget mtk_afe_hdmi_widgets[] = { 859 + /* Backend DAIs */ 860 + SND_SOC_DAPM_AIF_OUT("HDMIO Playback", NULL, 0, SND_SOC_NOPM, 0, 0), 861 + }; 862 + 863 + static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = { 864 + {"HDMIO Playback", NULL, "HDMI"}, 865 + }; 866 + 867 + static const struct snd_soc_component_driver mtk_afe_pcm_dai_component = { 868 + .name = "mtk-afe-pcm-dai", 869 + .dapm_widgets = mtk_afe_pcm_widgets, 870 + .num_dapm_widgets = ARRAY_SIZE(mtk_afe_pcm_widgets), 871 + .dapm_routes = mtk_afe_pcm_routes, 872 + .num_dapm_routes = ARRAY_SIZE(mtk_afe_pcm_routes), 873 + }; 874 + 875 + static const struct snd_soc_component_driver mtk_afe_hdmi_dai_component = { 876 + .name = "mtk-afe-hdmi-dai", 877 + .dapm_widgets = mtk_afe_hdmi_widgets, 878 + .num_dapm_widgets = ARRAY_SIZE(mtk_afe_hdmi_widgets), 879 + .dapm_routes = mtk_afe_hdmi_routes, 880 + .num_dapm_routes = ARRAY_SIZE(mtk_afe_hdmi_routes), 881 + }; 882 + 883 + static const char *aud_clks[MTK_CLK_NUM] = { 884 + [MTK_CLK_INFRASYS_AUD] = "infra_sys_audio_clk", 885 + [MTK_CLK_TOP_PDN_AUD] = "top_pdn_audio", 886 + [MTK_CLK_TOP_PDN_AUD_BUS] = "top_pdn_aud_intbus", 887 + [MTK_CLK_I2S0_M] = "i2s0_m", 888 + [MTK_CLK_I2S1_M] = "i2s1_m", 889 + [MTK_CLK_I2S2_M] = "i2s2_m", 890 + [MTK_CLK_I2S3_M] = "i2s3_m", 891 + [MTK_CLK_I2S3_B] = "i2s3_b", 892 + [MTK_CLK_BCK0] = "bck0", 893 + [MTK_CLK_BCK1] = "bck1", 894 + }; 895 + 896 + static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { 897 + { 898 + .name = "DL1", 899 + .id = MTK_AFE_MEMIF_DL1, 900 + .reg_ofs_base = AFE_DL1_BASE, 901 + .reg_ofs_cur = AFE_DL1_CUR, 902 + .fs_shift = 0, 903 + .mono_shift = 21, 904 + .enable_shift = 1, 905 + .irq_reg_cnt = AFE_IRQ_CNT1, 906 + .irq_cnt_shift = 0, 907 + .irq_en_shift = 0, 908 + .irq_fs_shift = 4, 909 + .irq_clr_shift = 0, 910 + }, { 911 + .name = "DL2", 912 + .id = MTK_AFE_MEMIF_DL2, 913 + .reg_ofs_base = AFE_DL2_BASE, 914 + .reg_ofs_cur = AFE_DL2_CUR, 915 + .fs_shift = 4, 916 + .mono_shift = 22, 917 + .enable_shift = 2, 918 + .irq_reg_cnt = AFE_IRQ_CNT1, 919 + .irq_cnt_shift = 20, 920 + .irq_en_shift = 2, 921 + .irq_fs_shift = 16, 922 + .irq_clr_shift = 2, 923 + }, { 924 + .name = "VUL", 925 + .id = MTK_AFE_MEMIF_VUL, 926 + .reg_ofs_base = AFE_VUL_BASE, 927 + .reg_ofs_cur = AFE_VUL_CUR, 928 + .fs_shift = 16, 929 + .mono_shift = 27, 930 + .enable_shift = 3, 931 + .irq_reg_cnt = AFE_IRQ_CNT2, 932 + .irq_cnt_shift = 0, 933 + .irq_en_shift = 1, 934 + .irq_fs_shift = 8, 935 + .irq_clr_shift = 1, 936 + }, { 937 + .name = "DAI", 938 + .id = MTK_AFE_MEMIF_DAI, 939 + .reg_ofs_base = AFE_DAI_BASE, 940 + .reg_ofs_cur = AFE_DAI_CUR, 941 + .fs_shift = 24, 942 + .mono_shift = -1, 943 + .enable_shift = 4, 944 + .irq_reg_cnt = AFE_IRQ_CNT2, 945 + .irq_cnt_shift = 20, 946 + .irq_en_shift = 3, 947 + .irq_fs_shift = 20, 948 + .irq_clr_shift = 3, 949 + }, { 950 + .name = "AWB", 951 + .id = MTK_AFE_MEMIF_AWB, 952 + .reg_ofs_base = AFE_AWB_BASE, 953 + .reg_ofs_cur = AFE_AWB_CUR, 954 + .fs_shift = 12, 955 + .mono_shift = 24, 956 + .enable_shift = 6, 957 + .irq_reg_cnt = AFE_IRQ_CNT7, 958 + .irq_cnt_shift = 0, 959 + .irq_en_shift = 14, 960 + .irq_fs_shift = 24, 961 + .irq_clr_shift = 6, 962 + }, { 963 + .name = "MOD_DAI", 964 + .id = MTK_AFE_MEMIF_MOD_DAI, 965 + .reg_ofs_base = AFE_MOD_PCM_BASE, 966 + .reg_ofs_cur = AFE_MOD_PCM_CUR, 967 + .fs_shift = 30, 968 + .mono_shift = 30, 969 + .enable_shift = 7, 970 + .irq_reg_cnt = AFE_IRQ_CNT2, 971 + .irq_cnt_shift = 20, 972 + .irq_en_shift = 3, 973 + .irq_fs_shift = 20, 974 + .irq_clr_shift = 3, 975 + }, { 976 + .name = "HDMI", 977 + .id = MTK_AFE_MEMIF_HDMI, 978 + .reg_ofs_base = AFE_HDMI_OUT_BASE, 979 + .reg_ofs_cur = AFE_HDMI_OUT_CUR, 980 + .fs_shift = -1, 981 + .mono_shift = -1, 982 + .enable_shift = -1, 983 + .irq_reg_cnt = AFE_IRQ_CNT5, 984 + .irq_cnt_shift = 0, 985 + .irq_en_shift = 12, 986 + .irq_fs_shift = -1, 987 + .irq_clr_shift = 4, 988 + }, 989 + }; 990 + 991 + static const struct regmap_config mtk_afe_regmap_config = { 992 + .reg_bits = 32, 993 + .reg_stride = 4, 994 + .val_bits = 32, 995 + .max_register = AFE_ADDA2_TOP_CON0, 996 + .cache_type = REGCACHE_NONE, 997 + }; 998 + 999 + static irqreturn_t mtk_afe_irq_handler(int irq, void *dev_id) 1000 + { 1001 + struct mtk_afe *afe = dev_id; 1002 + unsigned int reg_value, hw_ptr; 1003 + int i, ret; 1004 + 1005 + ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &reg_value); 1006 + if (ret) { 1007 + dev_err(afe->dev, "%s irq status err\n", __func__); 1008 + reg_value = AFE_IRQ_STATUS_BITS; 1009 + goto err_irq; 1010 + } 1011 + 1012 + for (i = 0; i < MTK_AFE_MEMIF_NUM; i++) { 1013 + struct mtk_afe_memif *memif = &afe->memif[i]; 1014 + 1015 + if (!(reg_value & (1 << memif->data->irq_clr_shift))) 1016 + continue; 1017 + 1018 + ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur, 1019 + &hw_ptr); 1020 + if (ret || hw_ptr == 0) { 1021 + dev_err(afe->dev, "%s hw_ptr err\n", __func__); 1022 + hw_ptr = memif->phys_buf_addr; 1023 + } 1024 + memif->hw_ptr = hw_ptr - memif->phys_buf_addr; 1025 + snd_pcm_period_elapsed(memif->substream); 1026 + } 1027 + 1028 + err_irq: 1029 + /* clear irq */ 1030 + regmap_write(afe->regmap, AFE_IRQ_CLR, reg_value & AFE_IRQ_STATUS_BITS); 1031 + 1032 + return IRQ_HANDLED; 1033 + } 1034 + 1035 + static int mtk_afe_runtime_suspend(struct device *dev) 1036 + { 1037 + struct mtk_afe *afe = dev_get_drvdata(dev); 1038 + 1039 + /* disable AFE clk */ 1040 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 1041 + AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE); 1042 + 1043 + clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]); 1044 + clk_disable_unprepare(afe->clocks[MTK_CLK_BCK1]); 1045 + clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]); 1046 + clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]); 1047 + clk_disable_unprepare(afe->clocks[MTK_CLK_INFRASYS_AUD]); 1048 + return 0; 1049 + } 1050 + 1051 + static int mtk_afe_runtime_resume(struct device *dev) 1052 + { 1053 + struct mtk_afe *afe = dev_get_drvdata(dev); 1054 + int ret; 1055 + 1056 + ret = clk_prepare_enable(afe->clocks[MTK_CLK_INFRASYS_AUD]); 1057 + if (ret) 1058 + return ret; 1059 + 1060 + ret = clk_prepare_enable(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]); 1061 + if (ret) 1062 + goto err_infra; 1063 + 1064 + ret = clk_prepare_enable(afe->clocks[MTK_CLK_TOP_PDN_AUD]); 1065 + if (ret) 1066 + goto err_top_aud_bus; 1067 + 1068 + ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK0]); 1069 + if (ret) 1070 + goto err_top_aud; 1071 + 1072 + ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK1]); 1073 + if (ret) 1074 + goto err_bck0; 1075 + 1076 + /* enable AFE clk */ 1077 + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, AUD_TCON0_PDN_AFE, 0); 1078 + 1079 + /* set O3/O4 16bits */ 1080 + regmap_update_bits(afe->regmap, AFE_CONN_24BIT, 1081 + AFE_CONN_24BIT_O03 | AFE_CONN_24BIT_O04, 0); 1082 + 1083 + /* unmask all IRQs */ 1084 + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, 0xff, 0xff); 1085 + return 0; 1086 + 1087 + err_bck0: 1088 + clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]); 1089 + err_top_aud: 1090 + clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]); 1091 + err_top_aud_bus: 1092 + clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]); 1093 + err_infra: 1094 + clk_disable_unprepare(afe->clocks[MTK_CLK_INFRASYS_AUD]); 1095 + return ret; 1096 + } 1097 + 1098 + static int mtk_afe_init_audio_clk(struct mtk_afe *afe) 1099 + { 1100 + size_t i; 1101 + 1102 + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { 1103 + afe->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]); 1104 + if (IS_ERR(afe->clocks[i])) { 1105 + dev_err(afe->dev, "%s devm_clk_get %s fail\n", 1106 + __func__, aud_clks[i]); 1107 + return PTR_ERR(afe->clocks[i]); 1108 + } 1109 + } 1110 + clk_set_rate(afe->clocks[MTK_CLK_BCK0], 22579200); /* 22M */ 1111 + clk_set_rate(afe->clocks[MTK_CLK_BCK1], 24576000); /* 24M */ 1112 + return 0; 1113 + } 1114 + 1115 + static int mtk_afe_pcm_dev_probe(struct platform_device *pdev) 1116 + { 1117 + int ret, i; 1118 + unsigned int irq_id; 1119 + struct mtk_afe *afe; 1120 + struct resource *res; 1121 + 1122 + afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); 1123 + if (!afe) 1124 + return -ENOMEM; 1125 + 1126 + afe->dev = &pdev->dev; 1127 + 1128 + irq_id = platform_get_irq(pdev, 0); 1129 + if (!irq_id) { 1130 + dev_err(afe->dev, "np %s no irq\n", afe->dev->of_node->name); 1131 + return -ENXIO; 1132 + } 1133 + ret = devm_request_irq(afe->dev, irq_id, mtk_afe_irq_handler, 1134 + 0, "Afe_ISR_Handle", (void *)afe); 1135 + if (ret) { 1136 + dev_err(afe->dev, "could not request_irq\n"); 1137 + return ret; 1138 + } 1139 + 1140 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1141 + afe->base_addr = devm_ioremap_resource(&pdev->dev, res); 1142 + if (IS_ERR(afe->base_addr)) 1143 + return PTR_ERR(afe->base_addr); 1144 + 1145 + afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, 1146 + &mtk_afe_regmap_config); 1147 + if (IS_ERR(afe->regmap)) 1148 + return PTR_ERR(afe->regmap); 1149 + 1150 + /* initial audio related clock */ 1151 + ret = mtk_afe_init_audio_clk(afe); 1152 + if (ret) { 1153 + dev_err(afe->dev, "mtk_afe_init_audio_clk fail\n"); 1154 + return ret; 1155 + } 1156 + 1157 + for (i = 0; i < MTK_AFE_MEMIF_NUM; i++) 1158 + afe->memif[i].data = &memif_data[i]; 1159 + 1160 + platform_set_drvdata(pdev, afe); 1161 + 1162 + pm_runtime_enable(&pdev->dev); 1163 + if (!pm_runtime_enabled(&pdev->dev)) { 1164 + ret = mtk_afe_runtime_resume(&pdev->dev); 1165 + if (ret) 1166 + goto err_pm_disable; 1167 + } 1168 + 1169 + ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform); 1170 + if (ret) 1171 + goto err_pm_disable; 1172 + 1173 + ret = snd_soc_register_component(&pdev->dev, 1174 + &mtk_afe_pcm_dai_component, 1175 + mtk_afe_pcm_dais, 1176 + ARRAY_SIZE(mtk_afe_pcm_dais)); 1177 + if (ret) 1178 + goto err_platform; 1179 + 1180 + ret = snd_soc_register_component(&pdev->dev, 1181 + &mtk_afe_hdmi_dai_component, 1182 + mtk_afe_hdmi_dais, 1183 + ARRAY_SIZE(mtk_afe_hdmi_dais)); 1184 + if (ret) 1185 + goto err_comp; 1186 + 1187 + dev_info(&pdev->dev, "MTK AFE driver initialized.\n"); 1188 + return 0; 1189 + 1190 + err_comp: 1191 + snd_soc_unregister_component(&pdev->dev); 1192 + err_platform: 1193 + snd_soc_unregister_platform(&pdev->dev); 1194 + err_pm_disable: 1195 + pm_runtime_disable(&pdev->dev); 1196 + return ret; 1197 + } 1198 + 1199 + static int mtk_afe_pcm_dev_remove(struct platform_device *pdev) 1200 + { 1201 + pm_runtime_disable(&pdev->dev); 1202 + snd_soc_unregister_component(&pdev->dev); 1203 + snd_soc_unregister_platform(&pdev->dev); 1204 + return 0; 1205 + } 1206 + 1207 + static const struct of_device_id mtk_afe_pcm_dt_match[] = { 1208 + { .compatible = "mediatek,mt8173-afe-pcm", }, 1209 + { } 1210 + }; 1211 + MODULE_DEVICE_TABLE(of, mtk_afe_pcm_dt_match); 1212 + 1213 + static const struct dev_pm_ops mtk_afe_pm_ops = { 1214 + SET_RUNTIME_PM_OPS(mtk_afe_runtime_suspend, mtk_afe_runtime_resume, 1215 + NULL) 1216 + }; 1217 + 1218 + static struct platform_driver mtk_afe_pcm_driver = { 1219 + .driver = { 1220 + .name = "mtk-afe-pcm", 1221 + .owner = THIS_MODULE, 1222 + .of_match_table = mtk_afe_pcm_dt_match, 1223 + .pm = &mtk_afe_pm_ops, 1224 + }, 1225 + .probe = mtk_afe_pcm_dev_probe, 1226 + .remove = mtk_afe_pcm_dev_remove, 1227 + }; 1228 + 1229 + module_platform_driver(mtk_afe_pcm_driver); 1230 + 1231 + MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver"); 1232 + MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>"); 1233 + MODULE_LICENSE("GPL v2");