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, &reg_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