10d1d7a66SGarlic Tseng /* 20d1d7a66SGarlic Tseng * Mediatek 8173 ALSA SoC AFE platform driver 30d1d7a66SGarlic Tseng * 40d1d7a66SGarlic Tseng * Copyright (c) 2015 MediaTek Inc. 50d1d7a66SGarlic Tseng * Author: Koro Chen <koro.chen@mediatek.com> 60d1d7a66SGarlic Tseng * Sascha Hauer <s.hauer@pengutronix.de> 70d1d7a66SGarlic Tseng * Hidalgo Huang <hidalgo.huang@mediatek.com> 80d1d7a66SGarlic Tseng * Ir Lian <ir.lian@mediatek.com> 90d1d7a66SGarlic Tseng * 100d1d7a66SGarlic Tseng * This program is free software; you can redistribute it and/or modify 110d1d7a66SGarlic Tseng * it under the terms of the GNU General Public License version 2 and 120d1d7a66SGarlic Tseng * only version 2 as published by the Free Software Foundation. 130d1d7a66SGarlic Tseng * 140d1d7a66SGarlic Tseng * This program is distributed in the hope that it will be useful, 150d1d7a66SGarlic Tseng * but WITHOUT ANY WARRANTY; without even the implied warranty of 160d1d7a66SGarlic Tseng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 170d1d7a66SGarlic Tseng * GNU General Public License for more details. 180d1d7a66SGarlic Tseng */ 190d1d7a66SGarlic Tseng 200d1d7a66SGarlic Tseng #include <linux/delay.h> 210d1d7a66SGarlic Tseng #include <linux/module.h> 220d1d7a66SGarlic Tseng #include <linux/of.h> 230d1d7a66SGarlic Tseng #include <linux/of_address.h> 240d1d7a66SGarlic Tseng #include <linux/dma-mapping.h> 250d1d7a66SGarlic Tseng #include <linux/pm_runtime.h> 260d1d7a66SGarlic Tseng #include <sound/soc.h> 270d1d7a66SGarlic Tseng #include "mt8173-afe-common.h" 280d1d7a66SGarlic Tseng 290d1d7a66SGarlic Tseng /***************************************************************************** 300d1d7a66SGarlic Tseng * R E G I S T E R D E F I N I T I O N 310d1d7a66SGarlic Tseng *****************************************************************************/ 320d1d7a66SGarlic Tseng #define AUDIO_TOP_CON0 0x0000 330d1d7a66SGarlic Tseng #define AUDIO_TOP_CON1 0x0004 340d1d7a66SGarlic Tseng #define AFE_DAC_CON0 0x0010 350d1d7a66SGarlic Tseng #define AFE_DAC_CON1 0x0014 360d1d7a66SGarlic Tseng #define AFE_I2S_CON1 0x0034 370d1d7a66SGarlic Tseng #define AFE_I2S_CON2 0x0038 380d1d7a66SGarlic Tseng #define AFE_CONN_24BIT 0x006c 390d1d7a66SGarlic Tseng #define AFE_MEMIF_MSB 0x00cc 400d1d7a66SGarlic Tseng 410d1d7a66SGarlic Tseng #define AFE_CONN1 0x0024 420d1d7a66SGarlic Tseng #define AFE_CONN2 0x0028 430d1d7a66SGarlic Tseng #define AFE_CONN3 0x002c 440d1d7a66SGarlic Tseng #define AFE_CONN7 0x0460 450d1d7a66SGarlic Tseng #define AFE_CONN8 0x0464 460d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0 0x0390 470d1d7a66SGarlic Tseng 480d1d7a66SGarlic Tseng /* Memory interface */ 490d1d7a66SGarlic Tseng #define AFE_DL1_BASE 0x0040 500d1d7a66SGarlic Tseng #define AFE_DL1_CUR 0x0044 510d1d7a66SGarlic Tseng #define AFE_DL1_END 0x0048 520d1d7a66SGarlic Tseng #define AFE_DL2_BASE 0x0050 530d1d7a66SGarlic Tseng #define AFE_DL2_CUR 0x0054 540d1d7a66SGarlic Tseng #define AFE_AWB_BASE 0x0070 550d1d7a66SGarlic Tseng #define AFE_AWB_CUR 0x007c 560d1d7a66SGarlic Tseng #define AFE_VUL_BASE 0x0080 570d1d7a66SGarlic Tseng #define AFE_VUL_CUR 0x008c 580d1d7a66SGarlic Tseng #define AFE_VUL_END 0x0088 590d1d7a66SGarlic Tseng #define AFE_DAI_BASE 0x0090 600d1d7a66SGarlic Tseng #define AFE_DAI_CUR 0x009c 610d1d7a66SGarlic Tseng #define AFE_MOD_PCM_BASE 0x0330 620d1d7a66SGarlic Tseng #define AFE_MOD_PCM_CUR 0x033c 630d1d7a66SGarlic Tseng #define AFE_HDMI_OUT_BASE 0x0374 640d1d7a66SGarlic Tseng #define AFE_HDMI_OUT_CUR 0x0378 650d1d7a66SGarlic Tseng #define AFE_HDMI_OUT_END 0x037c 660d1d7a66SGarlic Tseng 670d1d7a66SGarlic Tseng #define AFE_ADDA_TOP_CON0 0x0120 680d1d7a66SGarlic Tseng #define AFE_ADDA2_TOP_CON0 0x0600 690d1d7a66SGarlic Tseng 700d1d7a66SGarlic Tseng #define AFE_HDMI_OUT_CON0 0x0370 710d1d7a66SGarlic Tseng 720d1d7a66SGarlic Tseng #define AFE_IRQ_MCU_CON 0x03a0 730d1d7a66SGarlic Tseng #define AFE_IRQ_STATUS 0x03a4 740d1d7a66SGarlic Tseng #define AFE_IRQ_CLR 0x03a8 750d1d7a66SGarlic Tseng #define AFE_IRQ_CNT1 0x03ac 760d1d7a66SGarlic Tseng #define AFE_IRQ_CNT2 0x03b0 770d1d7a66SGarlic Tseng #define AFE_IRQ_MCU_EN 0x03b4 780d1d7a66SGarlic Tseng #define AFE_IRQ_CNT5 0x03bc 790d1d7a66SGarlic Tseng #define AFE_IRQ_CNT7 0x03dc 800d1d7a66SGarlic Tseng 810d1d7a66SGarlic Tseng #define AFE_TDM_CON1 0x0548 820d1d7a66SGarlic Tseng #define AFE_TDM_CON2 0x054c 830d1d7a66SGarlic Tseng 840d1d7a66SGarlic Tseng #define AFE_BASE_END_OFFSET 8 850d1d7a66SGarlic Tseng #define AFE_IRQ_STATUS_BITS 0xff 860d1d7a66SGarlic Tseng 870d1d7a66SGarlic Tseng /* AUDIO_TOP_CON0 (0x0000) */ 880d1d7a66SGarlic Tseng #define AUD_TCON0_PDN_SPDF (0x1 << 21) 890d1d7a66SGarlic Tseng #define AUD_TCON0_PDN_HDMI (0x1 << 20) 900d1d7a66SGarlic Tseng #define AUD_TCON0_PDN_24M (0x1 << 9) 910d1d7a66SGarlic Tseng #define AUD_TCON0_PDN_22M (0x1 << 8) 920d1d7a66SGarlic Tseng #define AUD_TCON0_PDN_AFE (0x1 << 2) 930d1d7a66SGarlic Tseng 940d1d7a66SGarlic Tseng /* AFE_I2S_CON1 (0x0034) */ 950d1d7a66SGarlic Tseng #define AFE_I2S_CON1_LOW_JITTER_CLK (0x1 << 12) 960d1d7a66SGarlic Tseng #define AFE_I2S_CON1_RATE(x) (((x) & 0xf) << 8) 970d1d7a66SGarlic Tseng #define AFE_I2S_CON1_FORMAT_I2S (0x1 << 3) 980d1d7a66SGarlic Tseng #define AFE_I2S_CON1_EN (0x1 << 0) 990d1d7a66SGarlic Tseng 1000d1d7a66SGarlic Tseng /* AFE_I2S_CON2 (0x0038) */ 1010d1d7a66SGarlic Tseng #define AFE_I2S_CON2_LOW_JITTER_CLK (0x1 << 12) 1020d1d7a66SGarlic Tseng #define AFE_I2S_CON2_RATE(x) (((x) & 0xf) << 8) 1030d1d7a66SGarlic Tseng #define AFE_I2S_CON2_FORMAT_I2S (0x1 << 3) 1040d1d7a66SGarlic Tseng #define AFE_I2S_CON2_EN (0x1 << 0) 1050d1d7a66SGarlic Tseng 1060d1d7a66SGarlic Tseng /* AFE_CONN_24BIT (0x006c) */ 1070d1d7a66SGarlic Tseng #define AFE_CONN_24BIT_O04 (0x1 << 4) 1080d1d7a66SGarlic Tseng #define AFE_CONN_24BIT_O03 (0x1 << 3) 1090d1d7a66SGarlic Tseng 1100d1d7a66SGarlic Tseng /* AFE_HDMI_CONN0 (0x0390) */ 1110d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O37_I37 (0x7 << 21) 1120d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O36_I36 (0x6 << 18) 1130d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O35_I33 (0x3 << 15) 1140d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O34_I32 (0x2 << 12) 1150d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O33_I35 (0x5 << 9) 1160d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O32_I34 (0x4 << 6) 1170d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O31_I31 (0x1 << 3) 1180d1d7a66SGarlic Tseng #define AFE_HDMI_CONN0_O30_I30 (0x0 << 0) 1190d1d7a66SGarlic Tseng 1200d1d7a66SGarlic Tseng /* AFE_TDM_CON1 (0x0548) */ 1210d1d7a66SGarlic Tseng #define AFE_TDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 24) 1220d1d7a66SGarlic Tseng #define AFE_TDM_CON1_32_BCK_CYCLES (0x2 << 12) 1230d1d7a66SGarlic Tseng #define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8) 1240d1d7a66SGarlic Tseng #define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4) 1250d1d7a66SGarlic Tseng #define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3) 1260d1d7a66SGarlic Tseng #define AFE_TDM_CON1_LRCK_INV (0x1 << 2) 1270d1d7a66SGarlic Tseng #define AFE_TDM_CON1_BCK_INV (0x1 << 1) 1280d1d7a66SGarlic Tseng #define AFE_TDM_CON1_EN (0x1 << 0) 1290d1d7a66SGarlic Tseng 1300d1d7a66SGarlic Tseng enum afe_tdm_ch_start { 1310d1d7a66SGarlic Tseng AFE_TDM_CH_START_O30_O31 = 0, 1320d1d7a66SGarlic Tseng AFE_TDM_CH_START_O32_O33, 1330d1d7a66SGarlic Tseng AFE_TDM_CH_START_O34_O35, 1340d1d7a66SGarlic Tseng AFE_TDM_CH_START_O36_O37, 1350d1d7a66SGarlic Tseng AFE_TDM_CH_ZERO, 1360d1d7a66SGarlic Tseng }; 1370d1d7a66SGarlic Tseng 1380d1d7a66SGarlic Tseng static const unsigned int mt8173_afe_backup_list[] = { 1390d1d7a66SGarlic Tseng AUDIO_TOP_CON0, 1400d1d7a66SGarlic Tseng AFE_CONN1, 1410d1d7a66SGarlic Tseng AFE_CONN2, 1420d1d7a66SGarlic Tseng AFE_CONN7, 1430d1d7a66SGarlic Tseng AFE_CONN8, 1440d1d7a66SGarlic Tseng AFE_DAC_CON1, 1450d1d7a66SGarlic Tseng AFE_DL1_BASE, 1460d1d7a66SGarlic Tseng AFE_DL1_END, 1470d1d7a66SGarlic Tseng AFE_VUL_BASE, 1480d1d7a66SGarlic Tseng AFE_VUL_END, 1490d1d7a66SGarlic Tseng AFE_HDMI_OUT_BASE, 1500d1d7a66SGarlic Tseng AFE_HDMI_OUT_END, 1510d1d7a66SGarlic Tseng AFE_HDMI_CONN0, 1520d1d7a66SGarlic Tseng AFE_DAC_CON0, 1530d1d7a66SGarlic Tseng }; 1540d1d7a66SGarlic Tseng 1550d1d7a66SGarlic Tseng struct mt8173_afe { 1560d1d7a66SGarlic Tseng /* address for ioremap audio hardware register */ 1570d1d7a66SGarlic Tseng void __iomem *base_addr; 1580d1d7a66SGarlic Tseng struct device *dev; 1590d1d7a66SGarlic Tseng struct regmap *regmap; 1600d1d7a66SGarlic Tseng struct mt8173_afe_memif memif[MT8173_AFE_MEMIF_NUM]; 1610d1d7a66SGarlic Tseng struct clk *clocks[MT8173_CLK_NUM]; 1620d1d7a66SGarlic Tseng unsigned int backup_regs[ARRAY_SIZE(mt8173_afe_backup_list)]; 1630d1d7a66SGarlic Tseng bool suspended; 1640d1d7a66SGarlic Tseng }; 1650d1d7a66SGarlic Tseng 1660d1d7a66SGarlic Tseng static const struct snd_pcm_hardware mt8173_afe_hardware = { 1670d1d7a66SGarlic Tseng .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1680d1d7a66SGarlic Tseng SNDRV_PCM_INFO_MMAP_VALID), 1690d1d7a66SGarlic Tseng .buffer_bytes_max = 256 * 1024, 1700d1d7a66SGarlic Tseng .period_bytes_min = 512, 1710d1d7a66SGarlic Tseng .period_bytes_max = 128 * 1024, 1720d1d7a66SGarlic Tseng .periods_min = 2, 1730d1d7a66SGarlic Tseng .periods_max = 256, 1740d1d7a66SGarlic Tseng .fifo_size = 0, 1750d1d7a66SGarlic Tseng }; 1760d1d7a66SGarlic Tseng 1770d1d7a66SGarlic Tseng static snd_pcm_uframes_t mt8173_afe_pcm_pointer 1780d1d7a66SGarlic Tseng (struct snd_pcm_substream *substream) 1790d1d7a66SGarlic Tseng { 1800d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 1810d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 1820d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 1830d1d7a66SGarlic Tseng unsigned int hw_ptr; 1840d1d7a66SGarlic Tseng int ret; 1850d1d7a66SGarlic Tseng 1860d1d7a66SGarlic Tseng ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur, &hw_ptr); 1870d1d7a66SGarlic Tseng if (ret || hw_ptr == 0) { 1880d1d7a66SGarlic Tseng dev_err(afe->dev, "%s hw_ptr err\n", __func__); 1890d1d7a66SGarlic Tseng hw_ptr = memif->phys_buf_addr; 1900d1d7a66SGarlic Tseng } 1910d1d7a66SGarlic Tseng 1920d1d7a66SGarlic Tseng return bytes_to_frames(substream->runtime, 1930d1d7a66SGarlic Tseng hw_ptr - memif->phys_buf_addr); 1940d1d7a66SGarlic Tseng } 1950d1d7a66SGarlic Tseng 1960d1d7a66SGarlic Tseng static const struct snd_pcm_ops mt8173_afe_pcm_ops = { 1970d1d7a66SGarlic Tseng .ioctl = snd_pcm_lib_ioctl, 1980d1d7a66SGarlic Tseng .pointer = mt8173_afe_pcm_pointer, 1990d1d7a66SGarlic Tseng }; 2000d1d7a66SGarlic Tseng 2010d1d7a66SGarlic Tseng static int mt8173_afe_pcm_new(struct snd_soc_pcm_runtime *rtd) 2020d1d7a66SGarlic Tseng { 2030d1d7a66SGarlic Tseng size_t size; 2040d1d7a66SGarlic Tseng struct snd_card *card = rtd->card->snd_card; 2050d1d7a66SGarlic Tseng struct snd_pcm *pcm = rtd->pcm; 2060d1d7a66SGarlic Tseng 2070d1d7a66SGarlic Tseng size = mt8173_afe_hardware.buffer_bytes_max; 2080d1d7a66SGarlic Tseng 2090d1d7a66SGarlic Tseng return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 2100d1d7a66SGarlic Tseng card->dev, size, size); 2110d1d7a66SGarlic Tseng } 2120d1d7a66SGarlic Tseng 2130d1d7a66SGarlic Tseng static void mt8173_afe_pcm_free(struct snd_pcm *pcm) 2140d1d7a66SGarlic Tseng { 2150d1d7a66SGarlic Tseng snd_pcm_lib_preallocate_free_for_all(pcm); 2160d1d7a66SGarlic Tseng } 2170d1d7a66SGarlic Tseng 2180d1d7a66SGarlic Tseng static const struct snd_soc_platform_driver mt8173_afe_pcm_platform = { 2190d1d7a66SGarlic Tseng .ops = &mt8173_afe_pcm_ops, 2200d1d7a66SGarlic Tseng .pcm_new = mt8173_afe_pcm_new, 2210d1d7a66SGarlic Tseng .pcm_free = mt8173_afe_pcm_free, 2220d1d7a66SGarlic Tseng }; 2230d1d7a66SGarlic Tseng 2240d1d7a66SGarlic Tseng struct mt8173_afe_rate { 2250d1d7a66SGarlic Tseng unsigned int rate; 2260d1d7a66SGarlic Tseng unsigned int regvalue; 2270d1d7a66SGarlic Tseng }; 2280d1d7a66SGarlic Tseng 2290d1d7a66SGarlic Tseng static const struct mt8173_afe_rate mt8173_afe_i2s_rates[] = { 2300d1d7a66SGarlic Tseng { .rate = 8000, .regvalue = 0 }, 2310d1d7a66SGarlic Tseng { .rate = 11025, .regvalue = 1 }, 2320d1d7a66SGarlic Tseng { .rate = 12000, .regvalue = 2 }, 2330d1d7a66SGarlic Tseng { .rate = 16000, .regvalue = 4 }, 2340d1d7a66SGarlic Tseng { .rate = 22050, .regvalue = 5 }, 2350d1d7a66SGarlic Tseng { .rate = 24000, .regvalue = 6 }, 2360d1d7a66SGarlic Tseng { .rate = 32000, .regvalue = 8 }, 2370d1d7a66SGarlic Tseng { .rate = 44100, .regvalue = 9 }, 2380d1d7a66SGarlic Tseng { .rate = 48000, .regvalue = 10 }, 2390d1d7a66SGarlic Tseng { .rate = 88000, .regvalue = 11 }, 2400d1d7a66SGarlic Tseng { .rate = 96000, .regvalue = 12 }, 2410d1d7a66SGarlic Tseng { .rate = 174000, .regvalue = 13 }, 2420d1d7a66SGarlic Tseng { .rate = 192000, .regvalue = 14 }, 2430d1d7a66SGarlic Tseng }; 2440d1d7a66SGarlic Tseng 2450d1d7a66SGarlic Tseng static int mt8173_afe_i2s_fs(unsigned int sample_rate) 2460d1d7a66SGarlic Tseng { 2470d1d7a66SGarlic Tseng int i; 2480d1d7a66SGarlic Tseng 2490d1d7a66SGarlic Tseng for (i = 0; i < ARRAY_SIZE(mt8173_afe_i2s_rates); i++) 2500d1d7a66SGarlic Tseng if (mt8173_afe_i2s_rates[i].rate == sample_rate) 2510d1d7a66SGarlic Tseng return mt8173_afe_i2s_rates[i].regvalue; 2520d1d7a66SGarlic Tseng 2530d1d7a66SGarlic Tseng return -EINVAL; 2540d1d7a66SGarlic Tseng } 2550d1d7a66SGarlic Tseng 2560d1d7a66SGarlic Tseng static int mt8173_afe_set_i2s(struct mt8173_afe *afe, unsigned int rate) 2570d1d7a66SGarlic Tseng { 2580d1d7a66SGarlic Tseng unsigned int val; 2590d1d7a66SGarlic Tseng int fs = mt8173_afe_i2s_fs(rate); 2600d1d7a66SGarlic Tseng 2610d1d7a66SGarlic Tseng if (fs < 0) 2620d1d7a66SGarlic Tseng return -EINVAL; 2630d1d7a66SGarlic Tseng 2640d1d7a66SGarlic Tseng /* from external ADC */ 2650d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1); 2660d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1); 2670d1d7a66SGarlic Tseng 2680d1d7a66SGarlic Tseng /* set input */ 2690d1d7a66SGarlic Tseng val = AFE_I2S_CON2_LOW_JITTER_CLK | 2700d1d7a66SGarlic Tseng AFE_I2S_CON2_RATE(fs) | 2710d1d7a66SGarlic Tseng AFE_I2S_CON2_FORMAT_I2S; 2720d1d7a66SGarlic Tseng 2730d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_I2S_CON2, ~AFE_I2S_CON2_EN, val); 2740d1d7a66SGarlic Tseng 2750d1d7a66SGarlic Tseng /* set output */ 2760d1d7a66SGarlic Tseng val = AFE_I2S_CON1_LOW_JITTER_CLK | 2770d1d7a66SGarlic Tseng AFE_I2S_CON1_RATE(fs) | 2780d1d7a66SGarlic Tseng AFE_I2S_CON1_FORMAT_I2S; 2790d1d7a66SGarlic Tseng 2800d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_I2S_CON1, ~AFE_I2S_CON1_EN, val); 2810d1d7a66SGarlic Tseng return 0; 2820d1d7a66SGarlic Tseng } 2830d1d7a66SGarlic Tseng 2840d1d7a66SGarlic Tseng static void mt8173_afe_set_i2s_enable(struct mt8173_afe *afe, bool enable) 2850d1d7a66SGarlic Tseng { 2860d1d7a66SGarlic Tseng unsigned int val; 2870d1d7a66SGarlic Tseng 2880d1d7a66SGarlic Tseng regmap_read(afe->regmap, AFE_I2S_CON2, &val); 2890d1d7a66SGarlic Tseng if (!!(val & AFE_I2S_CON2_EN) == enable) 2900d1d7a66SGarlic Tseng return; 2910d1d7a66SGarlic Tseng 2920d1d7a66SGarlic Tseng /* input */ 2930d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable); 2940d1d7a66SGarlic Tseng 2950d1d7a66SGarlic Tseng /* output */ 2960d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable); 2970d1d7a66SGarlic Tseng } 2980d1d7a66SGarlic Tseng 2990d1d7a66SGarlic Tseng static int mt8173_afe_dais_enable_clks(struct mt8173_afe *afe, 3000d1d7a66SGarlic Tseng struct clk *m_ck, struct clk *b_ck) 3010d1d7a66SGarlic Tseng { 3020d1d7a66SGarlic Tseng int ret; 3030d1d7a66SGarlic Tseng 3040d1d7a66SGarlic Tseng if (m_ck) { 3050d1d7a66SGarlic Tseng ret = clk_prepare_enable(m_ck); 3060d1d7a66SGarlic Tseng if (ret) { 3070d1d7a66SGarlic Tseng dev_err(afe->dev, "Failed to enable m_ck\n"); 3080d1d7a66SGarlic Tseng return ret; 3090d1d7a66SGarlic Tseng } 3100d1d7a66SGarlic Tseng } 3110d1d7a66SGarlic Tseng 3120d1d7a66SGarlic Tseng if (b_ck) { 3130d1d7a66SGarlic Tseng ret = clk_prepare_enable(b_ck); 3140d1d7a66SGarlic Tseng if (ret) { 3150d1d7a66SGarlic Tseng dev_err(afe->dev, "Failed to enable b_ck\n"); 3160d1d7a66SGarlic Tseng return ret; 3170d1d7a66SGarlic Tseng } 3180d1d7a66SGarlic Tseng } 3190d1d7a66SGarlic Tseng return 0; 3200d1d7a66SGarlic Tseng } 3210d1d7a66SGarlic Tseng 3220d1d7a66SGarlic Tseng static int mt8173_afe_dais_set_clks(struct mt8173_afe *afe, 3230d1d7a66SGarlic Tseng struct clk *m_ck, unsigned int mck_rate, 3240d1d7a66SGarlic Tseng struct clk *b_ck, unsigned int bck_rate) 3250d1d7a66SGarlic Tseng { 3260d1d7a66SGarlic Tseng int ret; 3270d1d7a66SGarlic Tseng 3280d1d7a66SGarlic Tseng if (m_ck) { 3290d1d7a66SGarlic Tseng ret = clk_set_rate(m_ck, mck_rate); 3300d1d7a66SGarlic Tseng if (ret) { 3310d1d7a66SGarlic Tseng dev_err(afe->dev, "Failed to set m_ck rate\n"); 3320d1d7a66SGarlic Tseng return ret; 3330d1d7a66SGarlic Tseng } 3340d1d7a66SGarlic Tseng } 3350d1d7a66SGarlic Tseng 3360d1d7a66SGarlic Tseng if (b_ck) { 3370d1d7a66SGarlic Tseng ret = clk_set_rate(b_ck, bck_rate); 3380d1d7a66SGarlic Tseng if (ret) { 3390d1d7a66SGarlic Tseng dev_err(afe->dev, "Failed to set b_ck rate\n"); 3400d1d7a66SGarlic Tseng return ret; 3410d1d7a66SGarlic Tseng } 3420d1d7a66SGarlic Tseng } 3430d1d7a66SGarlic Tseng return 0; 3440d1d7a66SGarlic Tseng } 3450d1d7a66SGarlic Tseng 3460d1d7a66SGarlic Tseng static void mt8173_afe_dais_disable_clks(struct mt8173_afe *afe, 3470d1d7a66SGarlic Tseng struct clk *m_ck, struct clk *b_ck) 3480d1d7a66SGarlic Tseng { 3490d1d7a66SGarlic Tseng if (m_ck) 3500d1d7a66SGarlic Tseng clk_disable_unprepare(m_ck); 3510d1d7a66SGarlic Tseng if (b_ck) 3520d1d7a66SGarlic Tseng clk_disable_unprepare(b_ck); 3530d1d7a66SGarlic Tseng } 3540d1d7a66SGarlic Tseng 3550d1d7a66SGarlic Tseng static int mt8173_afe_i2s_startup(struct snd_pcm_substream *substream, 3560d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 3570d1d7a66SGarlic Tseng { 3580d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 3590d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 3600d1d7a66SGarlic Tseng 3610d1d7a66SGarlic Tseng if (dai->active) 3620d1d7a66SGarlic Tseng return 0; 3630d1d7a66SGarlic Tseng 3640d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 3650d1d7a66SGarlic Tseng AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0); 3660d1d7a66SGarlic Tseng return 0; 3670d1d7a66SGarlic Tseng } 3680d1d7a66SGarlic Tseng 3690d1d7a66SGarlic Tseng static void mt8173_afe_i2s_shutdown(struct snd_pcm_substream *substream, 3700d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 3710d1d7a66SGarlic Tseng { 3720d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 3730d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 3740d1d7a66SGarlic Tseng 3750d1d7a66SGarlic Tseng if (dai->active) 3760d1d7a66SGarlic Tseng return; 3770d1d7a66SGarlic Tseng 3780d1d7a66SGarlic Tseng mt8173_afe_set_i2s_enable(afe, false); 3790d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 3800d1d7a66SGarlic Tseng AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 3810d1d7a66SGarlic Tseng AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M); 3820d1d7a66SGarlic Tseng } 3830d1d7a66SGarlic Tseng 3840d1d7a66SGarlic Tseng static int mt8173_afe_i2s_prepare(struct snd_pcm_substream *substream, 3850d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 3860d1d7a66SGarlic Tseng { 3870d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 3880d1d7a66SGarlic Tseng struct snd_pcm_runtime * const runtime = substream->runtime; 3890d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 3900d1d7a66SGarlic Tseng int ret; 3910d1d7a66SGarlic Tseng 3920d1d7a66SGarlic Tseng mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S1_M], 3930d1d7a66SGarlic Tseng runtime->rate * 256, NULL, 0); 3940d1d7a66SGarlic Tseng mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S2_M], 3950d1d7a66SGarlic Tseng runtime->rate * 256, NULL, 0); 3960d1d7a66SGarlic Tseng /* config I2S */ 3970d1d7a66SGarlic Tseng ret = mt8173_afe_set_i2s(afe, substream->runtime->rate); 3980d1d7a66SGarlic Tseng if (ret) 3990d1d7a66SGarlic Tseng return ret; 4000d1d7a66SGarlic Tseng 4010d1d7a66SGarlic Tseng mt8173_afe_set_i2s_enable(afe, true); 4020d1d7a66SGarlic Tseng 4030d1d7a66SGarlic Tseng return 0; 4040d1d7a66SGarlic Tseng } 4050d1d7a66SGarlic Tseng 4060d1d7a66SGarlic Tseng static int mt8173_afe_hdmi_startup(struct snd_pcm_substream *substream, 4070d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 4080d1d7a66SGarlic Tseng { 4090d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 4100d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 4110d1d7a66SGarlic Tseng 4120d1d7a66SGarlic Tseng if (dai->active) 4130d1d7a66SGarlic Tseng return 0; 4140d1d7a66SGarlic Tseng 4150d1d7a66SGarlic Tseng mt8173_afe_dais_enable_clks(afe, afe->clocks[MT8173_CLK_I2S3_M], 4160d1d7a66SGarlic Tseng afe->clocks[MT8173_CLK_I2S3_B]); 4170d1d7a66SGarlic Tseng return 0; 4180d1d7a66SGarlic Tseng } 4190d1d7a66SGarlic Tseng 4200d1d7a66SGarlic Tseng static void mt8173_afe_hdmi_shutdown(struct snd_pcm_substream *substream, 4210d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 4220d1d7a66SGarlic Tseng { 4230d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 4240d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 4250d1d7a66SGarlic Tseng 4260d1d7a66SGarlic Tseng if (dai->active) 4270d1d7a66SGarlic Tseng return; 4280d1d7a66SGarlic Tseng 4290d1d7a66SGarlic Tseng mt8173_afe_dais_disable_clks(afe, afe->clocks[MT8173_CLK_I2S3_M], 4300d1d7a66SGarlic Tseng afe->clocks[MT8173_CLK_I2S3_B]); 4310d1d7a66SGarlic Tseng } 4320d1d7a66SGarlic Tseng 4330d1d7a66SGarlic Tseng static int mt8173_afe_hdmi_prepare(struct snd_pcm_substream *substream, 4340d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 4350d1d7a66SGarlic Tseng { 4360d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 4370d1d7a66SGarlic Tseng struct snd_pcm_runtime * const runtime = substream->runtime; 4380d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 4390d1d7a66SGarlic Tseng unsigned int val; 4400d1d7a66SGarlic Tseng 4410d1d7a66SGarlic Tseng mt8173_afe_dais_set_clks(afe, afe->clocks[MT8173_CLK_I2S3_M], 4420d1d7a66SGarlic Tseng runtime->rate * 128, 4430d1d7a66SGarlic Tseng afe->clocks[MT8173_CLK_I2S3_B], 4440d1d7a66SGarlic Tseng runtime->rate * runtime->channels * 32); 4450d1d7a66SGarlic Tseng 4460d1d7a66SGarlic Tseng val = AFE_TDM_CON1_BCK_INV | 4470d1d7a66SGarlic Tseng AFE_TDM_CON1_LRCK_INV | 4480d1d7a66SGarlic Tseng AFE_TDM_CON1_1_BCK_DELAY | 4490d1d7a66SGarlic Tseng AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */ 4500d1d7a66SGarlic Tseng AFE_TDM_CON1_WLEN_32BIT | 4510d1d7a66SGarlic Tseng AFE_TDM_CON1_32_BCK_CYCLES | 4520d1d7a66SGarlic Tseng AFE_TDM_CON1_LRCK_WIDTH(32); 4530d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_TDM_CON1, ~AFE_TDM_CON1_EN, val); 4540d1d7a66SGarlic Tseng 4550d1d7a66SGarlic Tseng /* set tdm2 config */ 4560d1d7a66SGarlic Tseng switch (runtime->channels) { 4570d1d7a66SGarlic Tseng case 1: 4580d1d7a66SGarlic Tseng case 2: 4590d1d7a66SGarlic Tseng val = AFE_TDM_CH_START_O30_O31; 4600d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 4); 4610d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 8); 4620d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 12); 4630d1d7a66SGarlic Tseng break; 4640d1d7a66SGarlic Tseng case 3: 4650d1d7a66SGarlic Tseng case 4: 4660d1d7a66SGarlic Tseng val = AFE_TDM_CH_START_O30_O31; 4670d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O32_O33 << 4); 4680d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 8); 4690d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 12); 4700d1d7a66SGarlic Tseng break; 4710d1d7a66SGarlic Tseng case 5: 4720d1d7a66SGarlic Tseng case 6: 4730d1d7a66SGarlic Tseng val = AFE_TDM_CH_START_O30_O31; 4740d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O32_O33 << 4); 4750d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O34_O35 << 8); 4760d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_ZERO << 12); 4770d1d7a66SGarlic Tseng break; 4780d1d7a66SGarlic Tseng case 7: 4790d1d7a66SGarlic Tseng case 8: 4800d1d7a66SGarlic Tseng val = AFE_TDM_CH_START_O30_O31; 4810d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O32_O33 << 4); 4820d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O34_O35 << 8); 4830d1d7a66SGarlic Tseng val |= (AFE_TDM_CH_START_O36_O37 << 12); 4840d1d7a66SGarlic Tseng break; 4850d1d7a66SGarlic Tseng default: 4860d1d7a66SGarlic Tseng val = 0; 4870d1d7a66SGarlic Tseng } 4880d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_TDM_CON2, 0x0000ffff, val); 4890d1d7a66SGarlic Tseng 4900d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 4910d1d7a66SGarlic Tseng 0x000000f0, runtime->channels << 4); 4920d1d7a66SGarlic Tseng return 0; 4930d1d7a66SGarlic Tseng } 4940d1d7a66SGarlic Tseng 4950d1d7a66SGarlic Tseng static int mt8173_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, 4960d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 4970d1d7a66SGarlic Tseng { 4980d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 4990d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 5000d1d7a66SGarlic Tseng 5010d1d7a66SGarlic Tseng dev_info(afe->dev, "%s cmd=%d %s\n", __func__, cmd, dai->name); 5020d1d7a66SGarlic Tseng 5030d1d7a66SGarlic Tseng switch (cmd) { 5040d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_START: 5050d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_RESUME: 5060d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 5070d1d7a66SGarlic Tseng AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF, 0); 5080d1d7a66SGarlic Tseng 5090d1d7a66SGarlic Tseng /* set connections: O30~O37: L/R/LS/RS/C/LFE/CH7/CH8 */ 5100d1d7a66SGarlic Tseng regmap_write(afe->regmap, AFE_HDMI_CONN0, 5110d1d7a66SGarlic Tseng AFE_HDMI_CONN0_O30_I30 | AFE_HDMI_CONN0_O31_I31 | 5120d1d7a66SGarlic Tseng AFE_HDMI_CONN0_O32_I34 | AFE_HDMI_CONN0_O33_I35 | 5130d1d7a66SGarlic Tseng AFE_HDMI_CONN0_O34_I32 | AFE_HDMI_CONN0_O35_I33 | 5140d1d7a66SGarlic Tseng AFE_HDMI_CONN0_O36_I36 | AFE_HDMI_CONN0_O37_I37); 5150d1d7a66SGarlic Tseng 5160d1d7a66SGarlic Tseng /* enable Out control */ 5170d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1); 5180d1d7a66SGarlic Tseng 5190d1d7a66SGarlic Tseng /* enable tdm */ 5200d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0x1); 5210d1d7a66SGarlic Tseng 5220d1d7a66SGarlic Tseng return 0; 5230d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_STOP: 5240d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_SUSPEND: 5250d1d7a66SGarlic Tseng /* disable tdm */ 5260d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0); 5270d1d7a66SGarlic Tseng 5280d1d7a66SGarlic Tseng /* disable Out control */ 5290d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0); 5300d1d7a66SGarlic Tseng 5310d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 5320d1d7a66SGarlic Tseng AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF, 5330d1d7a66SGarlic Tseng AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF); 5340d1d7a66SGarlic Tseng 5350d1d7a66SGarlic Tseng return 0; 5360d1d7a66SGarlic Tseng default: 5370d1d7a66SGarlic Tseng return -EINVAL; 5380d1d7a66SGarlic Tseng } 5390d1d7a66SGarlic Tseng } 5400d1d7a66SGarlic Tseng 5410d1d7a66SGarlic Tseng static int mt8173_afe_dais_startup(struct snd_pcm_substream *substream, 5420d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 5430d1d7a66SGarlic Tseng { 5440d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 5450d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 5460d1d7a66SGarlic Tseng struct snd_pcm_runtime *runtime = substream->runtime; 5470d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 5480d1d7a66SGarlic Tseng int ret; 5490d1d7a66SGarlic Tseng 5500d1d7a66SGarlic Tseng memif->substream = substream; 5510d1d7a66SGarlic Tseng 5520d1d7a66SGarlic Tseng snd_soc_set_runtime_hwparams(substream, &mt8173_afe_hardware); 5530d1d7a66SGarlic Tseng 5540d1d7a66SGarlic Tseng /* 5550d1d7a66SGarlic Tseng * Capture cannot use ping-pong buffer since hw_ptr at IRQ may be 5560d1d7a66SGarlic Tseng * smaller than period_size due to AFE's internal buffer. 5570d1d7a66SGarlic Tseng * This easily leads to overrun when avail_min is period_size. 5580d1d7a66SGarlic Tseng * One more period can hold the possible unread buffer. 5590d1d7a66SGarlic Tseng */ 5600d1d7a66SGarlic Tseng if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 5610d1d7a66SGarlic Tseng ret = snd_pcm_hw_constraint_minmax(runtime, 5620d1d7a66SGarlic Tseng SNDRV_PCM_HW_PARAM_PERIODS, 5630d1d7a66SGarlic Tseng 3, 5640d1d7a66SGarlic Tseng mt8173_afe_hardware.periods_max); 5650d1d7a66SGarlic Tseng if (ret < 0) { 5660d1d7a66SGarlic Tseng dev_err(afe->dev, "hw_constraint_minmax failed\n"); 5670d1d7a66SGarlic Tseng return ret; 5680d1d7a66SGarlic Tseng } 5690d1d7a66SGarlic Tseng } 5700d1d7a66SGarlic Tseng ret = snd_pcm_hw_constraint_integer(runtime, 5710d1d7a66SGarlic Tseng SNDRV_PCM_HW_PARAM_PERIODS); 5720d1d7a66SGarlic Tseng if (ret < 0) 5730d1d7a66SGarlic Tseng dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); 5740d1d7a66SGarlic Tseng return ret; 5750d1d7a66SGarlic Tseng } 5760d1d7a66SGarlic Tseng 5770d1d7a66SGarlic Tseng static void mt8173_afe_dais_shutdown(struct snd_pcm_substream *substream, 5780d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 5790d1d7a66SGarlic Tseng { 5800d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 5810d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 5820d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 5830d1d7a66SGarlic Tseng 5840d1d7a66SGarlic Tseng memif->substream = NULL; 5850d1d7a66SGarlic Tseng } 5860d1d7a66SGarlic Tseng 5870d1d7a66SGarlic Tseng static int mt8173_afe_dais_hw_params(struct snd_pcm_substream *substream, 5880d1d7a66SGarlic Tseng struct snd_pcm_hw_params *params, 5890d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 5900d1d7a66SGarlic Tseng { 5910d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 5920d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 5930d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 5940d1d7a66SGarlic Tseng int msb_at_bit33 = 0; 5950d1d7a66SGarlic Tseng int ret; 5960d1d7a66SGarlic Tseng 5970d1d7a66SGarlic Tseng dev_dbg(afe->dev, 5980d1d7a66SGarlic Tseng "%s period = %u, rate= %u, channels=%u\n", 5990d1d7a66SGarlic Tseng __func__, params_period_size(params), params_rate(params), 6000d1d7a66SGarlic Tseng params_channels(params)); 6010d1d7a66SGarlic Tseng 6020d1d7a66SGarlic Tseng ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 6030d1d7a66SGarlic Tseng if (ret < 0) 6040d1d7a66SGarlic Tseng return ret; 6050d1d7a66SGarlic Tseng 6060d1d7a66SGarlic Tseng msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0; 6070d1d7a66SGarlic Tseng memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); 6080d1d7a66SGarlic Tseng memif->buffer_size = substream->runtime->dma_bytes; 6090d1d7a66SGarlic Tseng 6100d1d7a66SGarlic Tseng /* start */ 6110d1d7a66SGarlic Tseng regmap_write(afe->regmap, 6120d1d7a66SGarlic Tseng memif->data->reg_ofs_base, memif->phys_buf_addr); 6130d1d7a66SGarlic Tseng /* end */ 6140d1d7a66SGarlic Tseng regmap_write(afe->regmap, 6150d1d7a66SGarlic Tseng memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, 6160d1d7a66SGarlic Tseng memif->phys_buf_addr + memif->buffer_size - 1); 6170d1d7a66SGarlic Tseng 6180d1d7a66SGarlic Tseng /* set MSB to 33-bit */ 6190d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_MEMIF_MSB, 6200d1d7a66SGarlic Tseng 1 << memif->data->msb_shift, 6210d1d7a66SGarlic Tseng msb_at_bit33 << memif->data->msb_shift); 6220d1d7a66SGarlic Tseng 6230d1d7a66SGarlic Tseng /* set channel */ 6240d1d7a66SGarlic Tseng if (memif->data->mono_shift >= 0) { 6250d1d7a66SGarlic Tseng unsigned int mono = (params_channels(params) == 1) ? 1 : 0; 6260d1d7a66SGarlic Tseng 6270d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON1, 6280d1d7a66SGarlic Tseng 1 << memif->data->mono_shift, 6290d1d7a66SGarlic Tseng mono << memif->data->mono_shift); 6300d1d7a66SGarlic Tseng } 6310d1d7a66SGarlic Tseng 6320d1d7a66SGarlic Tseng /* set rate */ 6330d1d7a66SGarlic Tseng if (memif->data->fs_shift < 0) 6340d1d7a66SGarlic Tseng return 0; 6350d1d7a66SGarlic Tseng if (memif->data->id == MT8173_AFE_MEMIF_DAI || 6360d1d7a66SGarlic Tseng memif->data->id == MT8173_AFE_MEMIF_MOD_DAI) { 6370d1d7a66SGarlic Tseng unsigned int val; 6380d1d7a66SGarlic Tseng 6390d1d7a66SGarlic Tseng switch (params_rate(params)) { 6400d1d7a66SGarlic Tseng case 8000: 6410d1d7a66SGarlic Tseng val = 0; 6420d1d7a66SGarlic Tseng break; 6430d1d7a66SGarlic Tseng case 16000: 6440d1d7a66SGarlic Tseng val = 1; 6450d1d7a66SGarlic Tseng break; 6460d1d7a66SGarlic Tseng case 32000: 6470d1d7a66SGarlic Tseng val = 2; 6480d1d7a66SGarlic Tseng break; 6490d1d7a66SGarlic Tseng default: 6500d1d7a66SGarlic Tseng return -EINVAL; 6510d1d7a66SGarlic Tseng } 6520d1d7a66SGarlic Tseng 6530d1d7a66SGarlic Tseng if (memif->data->id == MT8173_AFE_MEMIF_DAI) 6540d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 6550d1d7a66SGarlic Tseng 0x3 << memif->data->fs_shift, 6560d1d7a66SGarlic Tseng val << memif->data->fs_shift); 6570d1d7a66SGarlic Tseng else 6580d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON1, 6590d1d7a66SGarlic Tseng 0x3 << memif->data->fs_shift, 6600d1d7a66SGarlic Tseng val << memif->data->fs_shift); 6610d1d7a66SGarlic Tseng 6620d1d7a66SGarlic Tseng } else { 6630d1d7a66SGarlic Tseng int fs = mt8173_afe_i2s_fs(params_rate(params)); 6640d1d7a66SGarlic Tseng 6650d1d7a66SGarlic Tseng if (fs < 0) 6660d1d7a66SGarlic Tseng return -EINVAL; 6670d1d7a66SGarlic Tseng 6680d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON1, 6690d1d7a66SGarlic Tseng 0xf << memif->data->fs_shift, 6700d1d7a66SGarlic Tseng fs << memif->data->fs_shift); 6710d1d7a66SGarlic Tseng } 6720d1d7a66SGarlic Tseng 6730d1d7a66SGarlic Tseng return 0; 6740d1d7a66SGarlic Tseng } 6750d1d7a66SGarlic Tseng 6760d1d7a66SGarlic Tseng static int mt8173_afe_dais_hw_free(struct snd_pcm_substream *substream, 6770d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 6780d1d7a66SGarlic Tseng { 6790d1d7a66SGarlic Tseng return snd_pcm_lib_free_pages(substream); 6800d1d7a66SGarlic Tseng } 6810d1d7a66SGarlic Tseng 6820d1d7a66SGarlic Tseng static int mt8173_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd, 6830d1d7a66SGarlic Tseng struct snd_soc_dai *dai) 6840d1d7a66SGarlic Tseng { 6850d1d7a66SGarlic Tseng struct snd_soc_pcm_runtime *rtd = substream->private_data; 6860d1d7a66SGarlic Tseng struct snd_pcm_runtime * const runtime = substream->runtime; 6870d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); 6880d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; 6890d1d7a66SGarlic Tseng unsigned int counter = runtime->period_size; 6900d1d7a66SGarlic Tseng 6910d1d7a66SGarlic Tseng dev_info(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd); 6920d1d7a66SGarlic Tseng 6930d1d7a66SGarlic Tseng switch (cmd) { 6940d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_START: 6950d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_RESUME: 6960d1d7a66SGarlic Tseng if (memif->data->enable_shift >= 0) 6970d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 6980d1d7a66SGarlic Tseng 1 << memif->data->enable_shift, 6990d1d7a66SGarlic Tseng 1 << memif->data->enable_shift); 7000d1d7a66SGarlic Tseng 7010d1d7a66SGarlic Tseng /* set irq counter */ 7020d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, 7030d1d7a66SGarlic Tseng memif->data->irq_reg_cnt, 7040d1d7a66SGarlic Tseng 0x3ffff << memif->data->irq_cnt_shift, 7050d1d7a66SGarlic Tseng counter << memif->data->irq_cnt_shift); 7060d1d7a66SGarlic Tseng 7070d1d7a66SGarlic Tseng /* set irq fs */ 7080d1d7a66SGarlic Tseng if (memif->data->irq_fs_shift >= 0) { 7090d1d7a66SGarlic Tseng int fs = mt8173_afe_i2s_fs(runtime->rate); 7100d1d7a66SGarlic Tseng 7110d1d7a66SGarlic Tseng if (fs < 0) 7120d1d7a66SGarlic Tseng return -EINVAL; 7130d1d7a66SGarlic Tseng 7140d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, 7150d1d7a66SGarlic Tseng AFE_IRQ_MCU_CON, 7160d1d7a66SGarlic Tseng 0xf << memif->data->irq_fs_shift, 7170d1d7a66SGarlic Tseng fs << memif->data->irq_fs_shift); 7180d1d7a66SGarlic Tseng } 7190d1d7a66SGarlic Tseng /* enable interrupt */ 7200d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, 7210d1d7a66SGarlic Tseng 1 << memif->data->irq_en_shift, 7220d1d7a66SGarlic Tseng 1 << memif->data->irq_en_shift); 7230d1d7a66SGarlic Tseng 7240d1d7a66SGarlic Tseng return 0; 7250d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_STOP: 7260d1d7a66SGarlic Tseng case SNDRV_PCM_TRIGGER_SUSPEND: 7270d1d7a66SGarlic Tseng if (memif->data->enable_shift >= 0) 7280d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 7290d1d7a66SGarlic Tseng 1 << memif->data->enable_shift, 0); 7300d1d7a66SGarlic Tseng /* disable interrupt */ 7310d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON, 7320d1d7a66SGarlic Tseng 1 << memif->data->irq_en_shift, 7330d1d7a66SGarlic Tseng 0 << memif->data->irq_en_shift); 7340d1d7a66SGarlic Tseng /* and clear pending IRQ */ 7350d1d7a66SGarlic Tseng regmap_write(afe->regmap, AFE_IRQ_CLR, 7360d1d7a66SGarlic Tseng 1 << memif->data->irq_clr_shift); 7370d1d7a66SGarlic Tseng return 0; 7380d1d7a66SGarlic Tseng default: 7390d1d7a66SGarlic Tseng return -EINVAL; 7400d1d7a66SGarlic Tseng } 7410d1d7a66SGarlic Tseng } 7420d1d7a66SGarlic Tseng 7430d1d7a66SGarlic Tseng /* FE DAIs */ 7440d1d7a66SGarlic Tseng static const struct snd_soc_dai_ops mt8173_afe_dai_ops = { 7450d1d7a66SGarlic Tseng .startup = mt8173_afe_dais_startup, 7460d1d7a66SGarlic Tseng .shutdown = mt8173_afe_dais_shutdown, 7470d1d7a66SGarlic Tseng .hw_params = mt8173_afe_dais_hw_params, 7480d1d7a66SGarlic Tseng .hw_free = mt8173_afe_dais_hw_free, 7490d1d7a66SGarlic Tseng .trigger = mt8173_afe_dais_trigger, 7500d1d7a66SGarlic Tseng }; 7510d1d7a66SGarlic Tseng 7520d1d7a66SGarlic Tseng /* BE DAIs */ 7530d1d7a66SGarlic Tseng static const struct snd_soc_dai_ops mt8173_afe_i2s_ops = { 7540d1d7a66SGarlic Tseng .startup = mt8173_afe_i2s_startup, 7550d1d7a66SGarlic Tseng .shutdown = mt8173_afe_i2s_shutdown, 7560d1d7a66SGarlic Tseng .prepare = mt8173_afe_i2s_prepare, 7570d1d7a66SGarlic Tseng }; 7580d1d7a66SGarlic Tseng 7590d1d7a66SGarlic Tseng static const struct snd_soc_dai_ops mt8173_afe_hdmi_ops = { 7600d1d7a66SGarlic Tseng .startup = mt8173_afe_hdmi_startup, 7610d1d7a66SGarlic Tseng .shutdown = mt8173_afe_hdmi_shutdown, 7620d1d7a66SGarlic Tseng .prepare = mt8173_afe_hdmi_prepare, 7630d1d7a66SGarlic Tseng .trigger = mt8173_afe_hdmi_trigger, 7640d1d7a66SGarlic Tseng 7650d1d7a66SGarlic Tseng }; 7660d1d7a66SGarlic Tseng 7670d1d7a66SGarlic Tseng static int mt8173_afe_runtime_suspend(struct device *dev); 7680d1d7a66SGarlic Tseng static int mt8173_afe_runtime_resume(struct device *dev); 7690d1d7a66SGarlic Tseng 7700d1d7a66SGarlic Tseng static int mt8173_afe_dai_suspend(struct snd_soc_dai *dai) 7710d1d7a66SGarlic Tseng { 7720d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_dai_get_drvdata(dai); 7730d1d7a66SGarlic Tseng int i; 7740d1d7a66SGarlic Tseng 7750d1d7a66SGarlic Tseng dev_dbg(afe->dev, "%s\n", __func__); 7760d1d7a66SGarlic Tseng if (pm_runtime_status_suspended(afe->dev) || afe->suspended) 7770d1d7a66SGarlic Tseng return 0; 7780d1d7a66SGarlic Tseng 7790d1d7a66SGarlic Tseng for (i = 0; i < ARRAY_SIZE(mt8173_afe_backup_list); i++) 7800d1d7a66SGarlic Tseng regmap_read(afe->regmap, mt8173_afe_backup_list[i], 7810d1d7a66SGarlic Tseng &afe->backup_regs[i]); 7820d1d7a66SGarlic Tseng 7830d1d7a66SGarlic Tseng afe->suspended = true; 7840d1d7a66SGarlic Tseng mt8173_afe_runtime_suspend(afe->dev); 7850d1d7a66SGarlic Tseng return 0; 7860d1d7a66SGarlic Tseng } 7870d1d7a66SGarlic Tseng 7880d1d7a66SGarlic Tseng static int mt8173_afe_dai_resume(struct snd_soc_dai *dai) 7890d1d7a66SGarlic Tseng { 7900d1d7a66SGarlic Tseng struct mt8173_afe *afe = snd_soc_dai_get_drvdata(dai); 7910d1d7a66SGarlic Tseng int i = 0; 7920d1d7a66SGarlic Tseng 7930d1d7a66SGarlic Tseng dev_dbg(afe->dev, "%s\n", __func__); 7940d1d7a66SGarlic Tseng if (pm_runtime_status_suspended(afe->dev) || !afe->suspended) 7950d1d7a66SGarlic Tseng return 0; 7960d1d7a66SGarlic Tseng 7970d1d7a66SGarlic Tseng mt8173_afe_runtime_resume(afe->dev); 7980d1d7a66SGarlic Tseng 7990d1d7a66SGarlic Tseng for (i = 0; i < ARRAY_SIZE(mt8173_afe_backup_list); i++) 8000d1d7a66SGarlic Tseng regmap_write(afe->regmap, mt8173_afe_backup_list[i], 8010d1d7a66SGarlic Tseng afe->backup_regs[i]); 8020d1d7a66SGarlic Tseng 8030d1d7a66SGarlic Tseng afe->suspended = false; 8040d1d7a66SGarlic Tseng return 0; 8050d1d7a66SGarlic Tseng } 8060d1d7a66SGarlic Tseng 8070d1d7a66SGarlic Tseng static struct snd_soc_dai_driver mt8173_afe_pcm_dais[] = { 8080d1d7a66SGarlic Tseng /* FE DAIs: memory intefaces to CPU */ 8090d1d7a66SGarlic Tseng { 8100d1d7a66SGarlic Tseng .name = "DL1", /* downlink 1 */ 8110d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_DL1, 8120d1d7a66SGarlic Tseng .suspend = mt8173_afe_dai_suspend, 8130d1d7a66SGarlic Tseng .resume = mt8173_afe_dai_resume, 8140d1d7a66SGarlic Tseng .playback = { 8150d1d7a66SGarlic Tseng .stream_name = "DL1", 8160d1d7a66SGarlic Tseng .channels_min = 1, 8170d1d7a66SGarlic Tseng .channels_max = 2, 8180d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 8190d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8200d1d7a66SGarlic Tseng }, 8210d1d7a66SGarlic Tseng .ops = &mt8173_afe_dai_ops, 8220d1d7a66SGarlic Tseng }, { 8230d1d7a66SGarlic Tseng .name = "VUL", /* voice uplink */ 8240d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_VUL, 8250d1d7a66SGarlic Tseng .suspend = mt8173_afe_dai_suspend, 8260d1d7a66SGarlic Tseng .resume = mt8173_afe_dai_resume, 8270d1d7a66SGarlic Tseng .capture = { 8280d1d7a66SGarlic Tseng .stream_name = "VUL", 8290d1d7a66SGarlic Tseng .channels_min = 1, 8300d1d7a66SGarlic Tseng .channels_max = 2, 8310d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 8320d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8330d1d7a66SGarlic Tseng }, 8340d1d7a66SGarlic Tseng .ops = &mt8173_afe_dai_ops, 8350d1d7a66SGarlic Tseng }, { 8360d1d7a66SGarlic Tseng /* BE DAIs */ 8370d1d7a66SGarlic Tseng .name = "I2S", 8380d1d7a66SGarlic Tseng .id = MT8173_AFE_IO_I2S, 8390d1d7a66SGarlic Tseng .playback = { 8400d1d7a66SGarlic Tseng .stream_name = "I2S Playback", 8410d1d7a66SGarlic Tseng .channels_min = 1, 8420d1d7a66SGarlic Tseng .channels_max = 2, 8430d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 8440d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8450d1d7a66SGarlic Tseng }, 8460d1d7a66SGarlic Tseng .capture = { 8470d1d7a66SGarlic Tseng .stream_name = "I2S Capture", 8480d1d7a66SGarlic Tseng .channels_min = 1, 8490d1d7a66SGarlic Tseng .channels_max = 2, 8500d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_8000_48000, 8510d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8520d1d7a66SGarlic Tseng }, 8530d1d7a66SGarlic Tseng .ops = &mt8173_afe_i2s_ops, 8540d1d7a66SGarlic Tseng .symmetric_rates = 1, 8550d1d7a66SGarlic Tseng }, 8560d1d7a66SGarlic Tseng }; 8570d1d7a66SGarlic Tseng 8580d1d7a66SGarlic Tseng static struct snd_soc_dai_driver mt8173_afe_hdmi_dais[] = { 8590d1d7a66SGarlic Tseng /* FE DAIs */ 8600d1d7a66SGarlic Tseng { 8610d1d7a66SGarlic Tseng .name = "HDMI", 8620d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_HDMI, 8630d1d7a66SGarlic Tseng .suspend = mt8173_afe_dai_suspend, 8640d1d7a66SGarlic Tseng .resume = mt8173_afe_dai_resume, 8650d1d7a66SGarlic Tseng .playback = { 8660d1d7a66SGarlic Tseng .stream_name = "HDMI", 8670d1d7a66SGarlic Tseng .channels_min = 2, 8680d1d7a66SGarlic Tseng .channels_max = 8, 8690d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 8700d1d7a66SGarlic Tseng SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 8710d1d7a66SGarlic Tseng SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 8720d1d7a66SGarlic Tseng SNDRV_PCM_RATE_192000, 8730d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8740d1d7a66SGarlic Tseng }, 8750d1d7a66SGarlic Tseng .ops = &mt8173_afe_dai_ops, 8760d1d7a66SGarlic Tseng }, { 8770d1d7a66SGarlic Tseng /* BE DAIs */ 8780d1d7a66SGarlic Tseng .name = "HDMIO", 8790d1d7a66SGarlic Tseng .id = MT8173_AFE_IO_HDMI, 8800d1d7a66SGarlic Tseng .playback = { 8810d1d7a66SGarlic Tseng .stream_name = "HDMIO Playback", 8820d1d7a66SGarlic Tseng .channels_min = 2, 8830d1d7a66SGarlic Tseng .channels_max = 8, 8840d1d7a66SGarlic Tseng .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | 8850d1d7a66SGarlic Tseng SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | 8860d1d7a66SGarlic Tseng SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | 8870d1d7a66SGarlic Tseng SNDRV_PCM_RATE_192000, 8880d1d7a66SGarlic Tseng .formats = SNDRV_PCM_FMTBIT_S16_LE, 8890d1d7a66SGarlic Tseng }, 8900d1d7a66SGarlic Tseng .ops = &mt8173_afe_hdmi_ops, 8910d1d7a66SGarlic Tseng }, 8920d1d7a66SGarlic Tseng }; 8930d1d7a66SGarlic Tseng 8940d1d7a66SGarlic Tseng static const struct snd_kcontrol_new mt8173_afe_o03_mix[] = { 8950d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN1, 21, 1, 0), 8960d1d7a66SGarlic Tseng }; 8970d1d7a66SGarlic Tseng 8980d1d7a66SGarlic Tseng static const struct snd_kcontrol_new mt8173_afe_o04_mix[] = { 8990d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN2, 6, 1, 0), 9000d1d7a66SGarlic Tseng }; 9010d1d7a66SGarlic Tseng 9020d1d7a66SGarlic Tseng static const struct snd_kcontrol_new mt8173_afe_o09_mix[] = { 9030d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 0, 1, 0), 9040d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0), 9050d1d7a66SGarlic Tseng }; 9060d1d7a66SGarlic Tseng 9070d1d7a66SGarlic Tseng static const struct snd_kcontrol_new mt8173_afe_o10_mix[] = { 9080d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN3, 3, 1, 0), 9090d1d7a66SGarlic Tseng SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0), 9100d1d7a66SGarlic Tseng }; 9110d1d7a66SGarlic Tseng 9120d1d7a66SGarlic Tseng static const struct snd_soc_dapm_widget mt8173_afe_pcm_widgets[] = { 9130d1d7a66SGarlic Tseng /* inter-connections */ 9140d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), 9150d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0), 9160d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), 9170d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), 9180d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), 9190d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), 9200d1d7a66SGarlic Tseng 9210d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, 9220d1d7a66SGarlic Tseng mt8173_afe_o03_mix, ARRAY_SIZE(mt8173_afe_o03_mix)), 9230d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0, 9240d1d7a66SGarlic Tseng mt8173_afe_o04_mix, ARRAY_SIZE(mt8173_afe_o04_mix)), 9250d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0, 9260d1d7a66SGarlic Tseng mt8173_afe_o09_mix, ARRAY_SIZE(mt8173_afe_o09_mix)), 9270d1d7a66SGarlic Tseng SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0, 9280d1d7a66SGarlic Tseng mt8173_afe_o10_mix, ARRAY_SIZE(mt8173_afe_o10_mix)), 9290d1d7a66SGarlic Tseng }; 9300d1d7a66SGarlic Tseng 9310d1d7a66SGarlic Tseng static const struct snd_soc_dapm_route mt8173_afe_pcm_routes[] = { 9320d1d7a66SGarlic Tseng {"I05", NULL, "DL1"}, 9330d1d7a66SGarlic Tseng {"I06", NULL, "DL1"}, 9340d1d7a66SGarlic Tseng {"I2S Playback", NULL, "O03"}, 9350d1d7a66SGarlic Tseng {"I2S Playback", NULL, "O04"}, 9360d1d7a66SGarlic Tseng {"VUL", NULL, "O09"}, 9370d1d7a66SGarlic Tseng {"VUL", NULL, "O10"}, 9380d1d7a66SGarlic Tseng {"I03", NULL, "I2S Capture"}, 9390d1d7a66SGarlic Tseng {"I04", NULL, "I2S Capture"}, 9400d1d7a66SGarlic Tseng {"I17", NULL, "I2S Capture"}, 9410d1d7a66SGarlic Tseng {"I18", NULL, "I2S Capture"}, 9420d1d7a66SGarlic Tseng { "O03", "I05 Switch", "I05" }, 9430d1d7a66SGarlic Tseng { "O04", "I06 Switch", "I06" }, 9440d1d7a66SGarlic Tseng { "O09", "I17 Switch", "I17" }, 9450d1d7a66SGarlic Tseng { "O09", "I03 Switch", "I03" }, 9460d1d7a66SGarlic Tseng { "O10", "I18 Switch", "I18" }, 9470d1d7a66SGarlic Tseng { "O10", "I04 Switch", "I04" }, 9480d1d7a66SGarlic Tseng }; 9490d1d7a66SGarlic Tseng 9500d1d7a66SGarlic Tseng static const struct snd_soc_dapm_route mt8173_afe_hdmi_routes[] = { 9510d1d7a66SGarlic Tseng {"HDMIO Playback", NULL, "HDMI"}, 9520d1d7a66SGarlic Tseng }; 9530d1d7a66SGarlic Tseng 9540d1d7a66SGarlic Tseng static const struct snd_soc_component_driver mt8173_afe_pcm_dai_component = { 9550d1d7a66SGarlic Tseng .name = "mt8173-afe-pcm-dai", 9560d1d7a66SGarlic Tseng .dapm_widgets = mt8173_afe_pcm_widgets, 9570d1d7a66SGarlic Tseng .num_dapm_widgets = ARRAY_SIZE(mt8173_afe_pcm_widgets), 9580d1d7a66SGarlic Tseng .dapm_routes = mt8173_afe_pcm_routes, 9590d1d7a66SGarlic Tseng .num_dapm_routes = ARRAY_SIZE(mt8173_afe_pcm_routes), 9600d1d7a66SGarlic Tseng }; 9610d1d7a66SGarlic Tseng 9620d1d7a66SGarlic Tseng static const struct snd_soc_component_driver mt8173_afe_hdmi_dai_component = { 9630d1d7a66SGarlic Tseng .name = "mt8173-afe-hdmi-dai", 9640d1d7a66SGarlic Tseng .dapm_routes = mt8173_afe_hdmi_routes, 9650d1d7a66SGarlic Tseng .num_dapm_routes = ARRAY_SIZE(mt8173_afe_hdmi_routes), 9660d1d7a66SGarlic Tseng }; 9670d1d7a66SGarlic Tseng 9680d1d7a66SGarlic Tseng static const char *aud_clks[MT8173_CLK_NUM] = { 9690d1d7a66SGarlic Tseng [MT8173_CLK_INFRASYS_AUD] = "infra_sys_audio_clk", 9700d1d7a66SGarlic Tseng [MT8173_CLK_TOP_PDN_AUD] = "top_pdn_audio", 9710d1d7a66SGarlic Tseng [MT8173_CLK_TOP_PDN_AUD_BUS] = "top_pdn_aud_intbus", 9720d1d7a66SGarlic Tseng [MT8173_CLK_I2S0_M] = "i2s0_m", 9730d1d7a66SGarlic Tseng [MT8173_CLK_I2S1_M] = "i2s1_m", 9740d1d7a66SGarlic Tseng [MT8173_CLK_I2S2_M] = "i2s2_m", 9750d1d7a66SGarlic Tseng [MT8173_CLK_I2S3_M] = "i2s3_m", 9760d1d7a66SGarlic Tseng [MT8173_CLK_I2S3_B] = "i2s3_b", 9770d1d7a66SGarlic Tseng [MT8173_CLK_BCK0] = "bck0", 9780d1d7a66SGarlic Tseng [MT8173_CLK_BCK1] = "bck1", 9790d1d7a66SGarlic Tseng }; 9800d1d7a66SGarlic Tseng 9810d1d7a66SGarlic Tseng static const struct mt8173_afe_memif_data memif_data[MT8173_AFE_MEMIF_NUM] = { 9820d1d7a66SGarlic Tseng { 9830d1d7a66SGarlic Tseng .name = "DL1", 9840d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_DL1, 9850d1d7a66SGarlic Tseng .reg_ofs_base = AFE_DL1_BASE, 9860d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_DL1_CUR, 9870d1d7a66SGarlic Tseng .fs_shift = 0, 9880d1d7a66SGarlic Tseng .mono_shift = 21, 9890d1d7a66SGarlic Tseng .enable_shift = 1, 9900d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT1, 9910d1d7a66SGarlic Tseng .irq_cnt_shift = 0, 9920d1d7a66SGarlic Tseng .irq_en_shift = 0, 9930d1d7a66SGarlic Tseng .irq_fs_shift = 4, 9940d1d7a66SGarlic Tseng .irq_clr_shift = 0, 9950d1d7a66SGarlic Tseng .msb_shift = 0, 9960d1d7a66SGarlic Tseng }, { 9970d1d7a66SGarlic Tseng .name = "DL2", 9980d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_DL2, 9990d1d7a66SGarlic Tseng .reg_ofs_base = AFE_DL2_BASE, 10000d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_DL2_CUR, 10010d1d7a66SGarlic Tseng .fs_shift = 4, 10020d1d7a66SGarlic Tseng .mono_shift = 22, 10030d1d7a66SGarlic Tseng .enable_shift = 2, 10040d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT1, 10050d1d7a66SGarlic Tseng .irq_cnt_shift = 20, 10060d1d7a66SGarlic Tseng .irq_en_shift = 2, 10070d1d7a66SGarlic Tseng .irq_fs_shift = 16, 10080d1d7a66SGarlic Tseng .irq_clr_shift = 2, 10090d1d7a66SGarlic Tseng .msb_shift = 1, 10100d1d7a66SGarlic Tseng }, { 10110d1d7a66SGarlic Tseng .name = "VUL", 10120d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_VUL, 10130d1d7a66SGarlic Tseng .reg_ofs_base = AFE_VUL_BASE, 10140d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_VUL_CUR, 10150d1d7a66SGarlic Tseng .fs_shift = 16, 10160d1d7a66SGarlic Tseng .mono_shift = 27, 10170d1d7a66SGarlic Tseng .enable_shift = 3, 10180d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT2, 10190d1d7a66SGarlic Tseng .irq_cnt_shift = 0, 10200d1d7a66SGarlic Tseng .irq_en_shift = 1, 10210d1d7a66SGarlic Tseng .irq_fs_shift = 8, 10220d1d7a66SGarlic Tseng .irq_clr_shift = 1, 10230d1d7a66SGarlic Tseng .msb_shift = 6, 10240d1d7a66SGarlic Tseng }, { 10250d1d7a66SGarlic Tseng .name = "DAI", 10260d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_DAI, 10270d1d7a66SGarlic Tseng .reg_ofs_base = AFE_DAI_BASE, 10280d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_DAI_CUR, 10290d1d7a66SGarlic Tseng .fs_shift = 24, 10300d1d7a66SGarlic Tseng .mono_shift = -1, 10310d1d7a66SGarlic Tseng .enable_shift = 4, 10320d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT2, 10330d1d7a66SGarlic Tseng .irq_cnt_shift = 20, 10340d1d7a66SGarlic Tseng .irq_en_shift = 3, 10350d1d7a66SGarlic Tseng .irq_fs_shift = 20, 10360d1d7a66SGarlic Tseng .irq_clr_shift = 3, 10370d1d7a66SGarlic Tseng .msb_shift = 5, 10380d1d7a66SGarlic Tseng }, { 10390d1d7a66SGarlic Tseng .name = "AWB", 10400d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_AWB, 10410d1d7a66SGarlic Tseng .reg_ofs_base = AFE_AWB_BASE, 10420d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_AWB_CUR, 10430d1d7a66SGarlic Tseng .fs_shift = 12, 10440d1d7a66SGarlic Tseng .mono_shift = 24, 10450d1d7a66SGarlic Tseng .enable_shift = 6, 10460d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT7, 10470d1d7a66SGarlic Tseng .irq_cnt_shift = 0, 10480d1d7a66SGarlic Tseng .irq_en_shift = 14, 10490d1d7a66SGarlic Tseng .irq_fs_shift = 24, 10500d1d7a66SGarlic Tseng .irq_clr_shift = 6, 10510d1d7a66SGarlic Tseng .msb_shift = 3, 10520d1d7a66SGarlic Tseng }, { 10530d1d7a66SGarlic Tseng .name = "MOD_DAI", 10540d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_MOD_DAI, 10550d1d7a66SGarlic Tseng .reg_ofs_base = AFE_MOD_PCM_BASE, 10560d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_MOD_PCM_CUR, 10570d1d7a66SGarlic Tseng .fs_shift = 30, 10580d1d7a66SGarlic Tseng .mono_shift = 30, 10590d1d7a66SGarlic Tseng .enable_shift = 7, 10600d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT2, 10610d1d7a66SGarlic Tseng .irq_cnt_shift = 20, 10620d1d7a66SGarlic Tseng .irq_en_shift = 3, 10630d1d7a66SGarlic Tseng .irq_fs_shift = 20, 10640d1d7a66SGarlic Tseng .irq_clr_shift = 3, 10650d1d7a66SGarlic Tseng .msb_shift = 4, 10660d1d7a66SGarlic Tseng }, { 10670d1d7a66SGarlic Tseng .name = "HDMI", 10680d1d7a66SGarlic Tseng .id = MT8173_AFE_MEMIF_HDMI, 10690d1d7a66SGarlic Tseng .reg_ofs_base = AFE_HDMI_OUT_BASE, 10700d1d7a66SGarlic Tseng .reg_ofs_cur = AFE_HDMI_OUT_CUR, 10710d1d7a66SGarlic Tseng .fs_shift = -1, 10720d1d7a66SGarlic Tseng .mono_shift = -1, 10730d1d7a66SGarlic Tseng .enable_shift = -1, 10740d1d7a66SGarlic Tseng .irq_reg_cnt = AFE_IRQ_CNT5, 10750d1d7a66SGarlic Tseng .irq_cnt_shift = 0, 10760d1d7a66SGarlic Tseng .irq_en_shift = 12, 10770d1d7a66SGarlic Tseng .irq_fs_shift = -1, 10780d1d7a66SGarlic Tseng .irq_clr_shift = 4, 10790d1d7a66SGarlic Tseng .msb_shift = 8, 10800d1d7a66SGarlic Tseng }, 10810d1d7a66SGarlic Tseng }; 10820d1d7a66SGarlic Tseng 10830d1d7a66SGarlic Tseng static const struct regmap_config mt8173_afe_regmap_config = { 10840d1d7a66SGarlic Tseng .reg_bits = 32, 10850d1d7a66SGarlic Tseng .reg_stride = 4, 10860d1d7a66SGarlic Tseng .val_bits = 32, 10870d1d7a66SGarlic Tseng .max_register = AFE_ADDA2_TOP_CON0, 10880d1d7a66SGarlic Tseng .cache_type = REGCACHE_NONE, 10890d1d7a66SGarlic Tseng }; 10900d1d7a66SGarlic Tseng 10910d1d7a66SGarlic Tseng static irqreturn_t mt8173_afe_irq_handler(int irq, void *dev_id) 10920d1d7a66SGarlic Tseng { 10930d1d7a66SGarlic Tseng struct mt8173_afe *afe = dev_id; 10940d1d7a66SGarlic Tseng unsigned int reg_value; 10950d1d7a66SGarlic Tseng int i, ret; 10960d1d7a66SGarlic Tseng 10970d1d7a66SGarlic Tseng ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, ®_value); 10980d1d7a66SGarlic Tseng if (ret) { 10990d1d7a66SGarlic Tseng dev_err(afe->dev, "%s irq status err\n", __func__); 11000d1d7a66SGarlic Tseng reg_value = AFE_IRQ_STATUS_BITS; 11010d1d7a66SGarlic Tseng goto err_irq; 11020d1d7a66SGarlic Tseng } 11030d1d7a66SGarlic Tseng 11040d1d7a66SGarlic Tseng for (i = 0; i < MT8173_AFE_MEMIF_NUM; i++) { 11050d1d7a66SGarlic Tseng struct mt8173_afe_memif *memif = &afe->memif[i]; 11060d1d7a66SGarlic Tseng 11070d1d7a66SGarlic Tseng if (!(reg_value & (1 << memif->data->irq_clr_shift))) 11080d1d7a66SGarlic Tseng continue; 11090d1d7a66SGarlic Tseng 11100d1d7a66SGarlic Tseng snd_pcm_period_elapsed(memif->substream); 11110d1d7a66SGarlic Tseng } 11120d1d7a66SGarlic Tseng 11130d1d7a66SGarlic Tseng err_irq: 11140d1d7a66SGarlic Tseng /* clear irq */ 11150d1d7a66SGarlic Tseng regmap_write(afe->regmap, AFE_IRQ_CLR, reg_value & AFE_IRQ_STATUS_BITS); 11160d1d7a66SGarlic Tseng 11170d1d7a66SGarlic Tseng return IRQ_HANDLED; 11180d1d7a66SGarlic Tseng } 11190d1d7a66SGarlic Tseng 11200d1d7a66SGarlic Tseng static int mt8173_afe_runtime_suspend(struct device *dev) 11210d1d7a66SGarlic Tseng { 11220d1d7a66SGarlic Tseng struct mt8173_afe *afe = dev_get_drvdata(dev); 11230d1d7a66SGarlic Tseng 11240d1d7a66SGarlic Tseng /* disable AFE */ 11250d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0); 11260d1d7a66SGarlic Tseng 11270d1d7a66SGarlic Tseng /* disable AFE clk */ 11280d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, 11290d1d7a66SGarlic Tseng AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE); 11300d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S1_M]); 11310d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S2_M]); 11320d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK0]); 11330d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK1]); 11340d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD]); 11350d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]); 11360d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_INFRASYS_AUD]); 11370d1d7a66SGarlic Tseng return 0; 11380d1d7a66SGarlic Tseng } 11390d1d7a66SGarlic Tseng 11400d1d7a66SGarlic Tseng static int mt8173_afe_runtime_resume(struct device *dev) 11410d1d7a66SGarlic Tseng { 11420d1d7a66SGarlic Tseng struct mt8173_afe *afe = dev_get_drvdata(dev); 11430d1d7a66SGarlic Tseng int ret; 11440d1d7a66SGarlic Tseng 11450d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_INFRASYS_AUD]); 11460d1d7a66SGarlic Tseng if (ret) 11470d1d7a66SGarlic Tseng return ret; 11480d1d7a66SGarlic Tseng 11490d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]); 11500d1d7a66SGarlic Tseng if (ret) 11510d1d7a66SGarlic Tseng goto err_infra; 11520d1d7a66SGarlic Tseng 11530d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_TOP_PDN_AUD]); 11540d1d7a66SGarlic Tseng if (ret) 11550d1d7a66SGarlic Tseng goto err_top_aud_bus; 11560d1d7a66SGarlic Tseng 11570d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_BCK0]); 11580d1d7a66SGarlic Tseng if (ret) 11590d1d7a66SGarlic Tseng goto err_top_aud; 11600d1d7a66SGarlic Tseng 11610d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_BCK1]); 11620d1d7a66SGarlic Tseng if (ret) 11630d1d7a66SGarlic Tseng goto err_bck0; 11640d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_I2S1_M]); 11650d1d7a66SGarlic Tseng if (ret) 11660d1d7a66SGarlic Tseng goto err_i2s1_m; 11670d1d7a66SGarlic Tseng ret = clk_prepare_enable(afe->clocks[MT8173_CLK_I2S2_M]); 11680d1d7a66SGarlic Tseng if (ret) 11690d1d7a66SGarlic Tseng goto err_i2s2_m; 11700d1d7a66SGarlic Tseng 11710d1d7a66SGarlic Tseng /* enable AFE clk */ 11720d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, AUD_TCON0_PDN_AFE, 0); 11730d1d7a66SGarlic Tseng 11740d1d7a66SGarlic Tseng /* set O3/O4 16bits */ 11750d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_CONN_24BIT, 11760d1d7a66SGarlic Tseng AFE_CONN_24BIT_O03 | AFE_CONN_24BIT_O04, 0); 11770d1d7a66SGarlic Tseng 11780d1d7a66SGarlic Tseng /* unmask all IRQs */ 11790d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, 0xff, 0xff); 11800d1d7a66SGarlic Tseng 11810d1d7a66SGarlic Tseng /* enable AFE */ 11820d1d7a66SGarlic Tseng regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1); 11830d1d7a66SGarlic Tseng return 0; 11840d1d7a66SGarlic Tseng err_i2s1_m: 11850d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S1_M]); 11860d1d7a66SGarlic Tseng err_i2s2_m: 11870d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_I2S2_M]); 11880d1d7a66SGarlic Tseng err_bck0: 11890d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_BCK0]); 11900d1d7a66SGarlic Tseng err_top_aud: 11910d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD]); 11920d1d7a66SGarlic Tseng err_top_aud_bus: 11930d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_TOP_PDN_AUD_BUS]); 11940d1d7a66SGarlic Tseng err_infra: 11950d1d7a66SGarlic Tseng clk_disable_unprepare(afe->clocks[MT8173_CLK_INFRASYS_AUD]); 11960d1d7a66SGarlic Tseng return ret; 11970d1d7a66SGarlic Tseng } 11980d1d7a66SGarlic Tseng 11990d1d7a66SGarlic Tseng static int mt8173_afe_init_audio_clk(struct mt8173_afe *afe) 12000d1d7a66SGarlic Tseng { 12010d1d7a66SGarlic Tseng size_t i; 12020d1d7a66SGarlic Tseng 12030d1d7a66SGarlic Tseng for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { 12040d1d7a66SGarlic Tseng afe->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]); 12050d1d7a66SGarlic Tseng if (IS_ERR(afe->clocks[i])) { 12060d1d7a66SGarlic Tseng dev_err(afe->dev, "%s devm_clk_get %s fail\n", 12070d1d7a66SGarlic Tseng __func__, aud_clks[i]); 12080d1d7a66SGarlic Tseng return PTR_ERR(afe->clocks[i]); 12090d1d7a66SGarlic Tseng } 12100d1d7a66SGarlic Tseng } 12110d1d7a66SGarlic Tseng clk_set_rate(afe->clocks[MT8173_CLK_BCK0], 22579200); /* 22M */ 12120d1d7a66SGarlic Tseng clk_set_rate(afe->clocks[MT8173_CLK_BCK1], 24576000); /* 24M */ 12130d1d7a66SGarlic Tseng return 0; 12140d1d7a66SGarlic Tseng } 12150d1d7a66SGarlic Tseng 12160d1d7a66SGarlic Tseng static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) 12170d1d7a66SGarlic Tseng { 12180d1d7a66SGarlic Tseng int ret, i; 12190d1d7a66SGarlic Tseng unsigned int irq_id; 12200d1d7a66SGarlic Tseng struct mt8173_afe *afe; 12210d1d7a66SGarlic Tseng struct resource *res; 12220d1d7a66SGarlic Tseng 12230d1d7a66SGarlic Tseng ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); 12240d1d7a66SGarlic Tseng if (ret) 12250d1d7a66SGarlic Tseng return ret; 12260d1d7a66SGarlic Tseng 12270d1d7a66SGarlic Tseng afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); 12280d1d7a66SGarlic Tseng if (!afe) 12290d1d7a66SGarlic Tseng return -ENOMEM; 12300d1d7a66SGarlic Tseng 12310d1d7a66SGarlic Tseng afe->dev = &pdev->dev; 12320d1d7a66SGarlic Tseng 12330d1d7a66SGarlic Tseng irq_id = platform_get_irq(pdev, 0); 12340d1d7a66SGarlic Tseng if (!irq_id) { 12350d1d7a66SGarlic Tseng dev_err(afe->dev, "np %s no irq\n", afe->dev->of_node->name); 12360d1d7a66SGarlic Tseng return -ENXIO; 12370d1d7a66SGarlic Tseng } 12380d1d7a66SGarlic Tseng ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, 12390d1d7a66SGarlic Tseng 0, "Afe_ISR_Handle", (void *)afe); 12400d1d7a66SGarlic Tseng if (ret) { 12410d1d7a66SGarlic Tseng dev_err(afe->dev, "could not request_irq\n"); 12420d1d7a66SGarlic Tseng return ret; 12430d1d7a66SGarlic Tseng } 12440d1d7a66SGarlic Tseng 12450d1d7a66SGarlic Tseng res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 12460d1d7a66SGarlic Tseng afe->base_addr = devm_ioremap_resource(&pdev->dev, res); 12470d1d7a66SGarlic Tseng if (IS_ERR(afe->base_addr)) 12480d1d7a66SGarlic Tseng return PTR_ERR(afe->base_addr); 12490d1d7a66SGarlic Tseng 12500d1d7a66SGarlic Tseng afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, 12510d1d7a66SGarlic Tseng &mt8173_afe_regmap_config); 12520d1d7a66SGarlic Tseng if (IS_ERR(afe->regmap)) 12530d1d7a66SGarlic Tseng return PTR_ERR(afe->regmap); 12540d1d7a66SGarlic Tseng 12550d1d7a66SGarlic Tseng /* initial audio related clock */ 12560d1d7a66SGarlic Tseng ret = mt8173_afe_init_audio_clk(afe); 12570d1d7a66SGarlic Tseng if (ret) { 12580d1d7a66SGarlic Tseng dev_err(afe->dev, "mt8173_afe_init_audio_clk fail\n"); 12590d1d7a66SGarlic Tseng return ret; 12600d1d7a66SGarlic Tseng } 12610d1d7a66SGarlic Tseng 12620d1d7a66SGarlic Tseng for (i = 0; i < MT8173_AFE_MEMIF_NUM; i++) 12630d1d7a66SGarlic Tseng afe->memif[i].data = &memif_data[i]; 12640d1d7a66SGarlic Tseng 12650d1d7a66SGarlic Tseng platform_set_drvdata(pdev, afe); 12660d1d7a66SGarlic Tseng 12670d1d7a66SGarlic Tseng pm_runtime_enable(&pdev->dev); 12680d1d7a66SGarlic Tseng if (!pm_runtime_enabled(&pdev->dev)) { 12690d1d7a66SGarlic Tseng ret = mt8173_afe_runtime_resume(&pdev->dev); 12700d1d7a66SGarlic Tseng if (ret) 12710d1d7a66SGarlic Tseng goto err_pm_disable; 12720d1d7a66SGarlic Tseng } 12730d1d7a66SGarlic Tseng 12740d1d7a66SGarlic Tseng ret = snd_soc_register_platform(&pdev->dev, &mt8173_afe_pcm_platform); 12750d1d7a66SGarlic Tseng if (ret) 12760d1d7a66SGarlic Tseng goto err_pm_disable; 12770d1d7a66SGarlic Tseng 12780d1d7a66SGarlic Tseng ret = snd_soc_register_component(&pdev->dev, 12790d1d7a66SGarlic Tseng &mt8173_afe_pcm_dai_component, 12800d1d7a66SGarlic Tseng mt8173_afe_pcm_dais, 12810d1d7a66SGarlic Tseng ARRAY_SIZE(mt8173_afe_pcm_dais)); 12820d1d7a66SGarlic Tseng if (ret) 12830d1d7a66SGarlic Tseng goto err_platform; 12840d1d7a66SGarlic Tseng 12850d1d7a66SGarlic Tseng ret = snd_soc_register_component(&pdev->dev, 12860d1d7a66SGarlic Tseng &mt8173_afe_hdmi_dai_component, 12870d1d7a66SGarlic Tseng mt8173_afe_hdmi_dais, 12880d1d7a66SGarlic Tseng ARRAY_SIZE(mt8173_afe_hdmi_dais)); 12890d1d7a66SGarlic Tseng if (ret) 12900d1d7a66SGarlic Tseng goto err_comp; 12910d1d7a66SGarlic Tseng 12920d1d7a66SGarlic Tseng dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n"); 12930d1d7a66SGarlic Tseng return 0; 12940d1d7a66SGarlic Tseng 12950d1d7a66SGarlic Tseng err_comp: 12960d1d7a66SGarlic Tseng snd_soc_unregister_component(&pdev->dev); 12970d1d7a66SGarlic Tseng err_platform: 12980d1d7a66SGarlic Tseng snd_soc_unregister_platform(&pdev->dev); 12990d1d7a66SGarlic Tseng err_pm_disable: 13000d1d7a66SGarlic Tseng pm_runtime_disable(&pdev->dev); 13010d1d7a66SGarlic Tseng return ret; 13020d1d7a66SGarlic Tseng } 13030d1d7a66SGarlic Tseng 13040d1d7a66SGarlic Tseng static int mt8173_afe_pcm_dev_remove(struct platform_device *pdev) 13050d1d7a66SGarlic Tseng { 13060d1d7a66SGarlic Tseng pm_runtime_disable(&pdev->dev); 13070d1d7a66SGarlic Tseng if (!pm_runtime_status_suspended(&pdev->dev)) 13080d1d7a66SGarlic Tseng mt8173_afe_runtime_suspend(&pdev->dev); 13090d1d7a66SGarlic Tseng snd_soc_unregister_component(&pdev->dev); 13100d1d7a66SGarlic Tseng snd_soc_unregister_platform(&pdev->dev); 13110d1d7a66SGarlic Tseng return 0; 13120d1d7a66SGarlic Tseng } 13130d1d7a66SGarlic Tseng 13140d1d7a66SGarlic Tseng static const struct of_device_id mt8173_afe_pcm_dt_match[] = { 13150d1d7a66SGarlic Tseng { .compatible = "mediatek,mt8173-afe-pcm", }, 13160d1d7a66SGarlic Tseng { } 13170d1d7a66SGarlic Tseng }; 13180d1d7a66SGarlic Tseng MODULE_DEVICE_TABLE(of, mt8173_afe_pcm_dt_match); 13190d1d7a66SGarlic Tseng 13200d1d7a66SGarlic Tseng static const struct dev_pm_ops mt8173_afe_pm_ops = { 13210d1d7a66SGarlic Tseng SET_RUNTIME_PM_OPS(mt8173_afe_runtime_suspend, 13220d1d7a66SGarlic Tseng mt8173_afe_runtime_resume, NULL) 13230d1d7a66SGarlic Tseng }; 13240d1d7a66SGarlic Tseng 13250d1d7a66SGarlic Tseng static struct platform_driver mt8173_afe_pcm_driver = { 13260d1d7a66SGarlic Tseng .driver = { 13270d1d7a66SGarlic Tseng .name = "mt8173-afe-pcm", 13280d1d7a66SGarlic Tseng .of_match_table = mt8173_afe_pcm_dt_match, 13290d1d7a66SGarlic Tseng .pm = &mt8173_afe_pm_ops, 13300d1d7a66SGarlic Tseng }, 13310d1d7a66SGarlic Tseng .probe = mt8173_afe_pcm_dev_probe, 13320d1d7a66SGarlic Tseng .remove = mt8173_afe_pcm_dev_remove, 13330d1d7a66SGarlic Tseng }; 13340d1d7a66SGarlic Tseng 13350d1d7a66SGarlic Tseng module_platform_driver(mt8173_afe_pcm_driver); 13360d1d7a66SGarlic Tseng 13370d1d7a66SGarlic Tseng MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver"); 13380d1d7a66SGarlic Tseng MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>"); 13390d1d7a66SGarlic Tseng MODULE_LICENSE("GPL v2"); 1340