xref: /OK3568_Linux_fs/kernel/sound/soc/rockchip/rockchip_vad.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Rockchip VAD driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2018 Fuzhou Rockchip Electronics Co., Ltd
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/uaccess.h>
11*4882a593Smuzhiyun #include <linux/clk.h>
12*4882a593Smuzhiyun #include <linux/interrupt.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/of_device.h>
15*4882a593Smuzhiyun #include <linux/of_address.h>
16*4882a593Smuzhiyun #include <linux/pm_runtime.h>
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <sound/pcm.h>
19*4882a593Smuzhiyun #include <sound/pcm_params.h>
20*4882a593Smuzhiyun #include <sound/soc.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "rockchip_vad.h"
23*4882a593Smuzhiyun #include "rockchip_multi_dais.h"
24*4882a593Smuzhiyun #include "vad_preprocess.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define DRV_NAME "rockchip-vad"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define VAD_RATES	SNDRV_PCM_RATE_8000_192000
29*4882a593Smuzhiyun #define VAD_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
30*4882a593Smuzhiyun 			SNDRV_PCM_FMTBIT_S20_3LE | \
31*4882a593Smuzhiyun 			SNDRV_PCM_FMTBIT_S24_LE | \
32*4882a593Smuzhiyun 			SNDRV_PCM_FMTBIT_S32_LE)
33*4882a593Smuzhiyun #define ACODEC_REG_NUM	28
34*4882a593Smuzhiyun #define CHUNK_SIZE	64 /* bytes */
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static struct snd_pcm_substream *vad_substream;
37*4882a593Smuzhiyun static unsigned int voice_inactive_frames;
38*4882a593Smuzhiyun module_param(voice_inactive_frames, uint, 0644);
39*4882a593Smuzhiyun MODULE_PARM_DESC(voice_inactive_frames, "voice inactive frame count");
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun enum rk_vad_version {
42*4882a593Smuzhiyun 	VAD_RK1808ES = 1,
43*4882a593Smuzhiyun 	VAD_RK1808,
44*4882a593Smuzhiyun 	VAD_RK3308,
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun struct vad_buf {
48*4882a593Smuzhiyun 	void __iomem *begin;
49*4882a593Smuzhiyun 	void __iomem *end;
50*4882a593Smuzhiyun 	void __iomem *cur;
51*4882a593Smuzhiyun 	void __iomem *pos;
52*4882a593Smuzhiyun 	int size;
53*4882a593Smuzhiyun 	int loop_cnt;
54*4882a593Smuzhiyun 	bool loop;
55*4882a593Smuzhiyun 	bool sorted;
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun struct audio_src_addr_map {
59*4882a593Smuzhiyun 	u32 id;
60*4882a593Smuzhiyun 	u32 addr;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun struct vad_soc_data {
64*4882a593Smuzhiyun 	enum rk_vad_version version;
65*4882a593Smuzhiyun 	const struct audio_src_addr_map *map;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun struct rockchip_vad {
69*4882a593Smuzhiyun 	struct device *dev;
70*4882a593Smuzhiyun 	struct device_node *audio_node;
71*4882a593Smuzhiyun 	struct clk *hclk;
72*4882a593Smuzhiyun 	struct regmap *regmap;
73*4882a593Smuzhiyun 	unsigned int memphy;
74*4882a593Smuzhiyun 	unsigned int memphy_end;
75*4882a593Smuzhiyun 	void __iomem *membase;
76*4882a593Smuzhiyun 	struct vad_buf vbuf;
77*4882a593Smuzhiyun 	struct vad_params params;
78*4882a593Smuzhiyun 	struct vad_uparams uparams;
79*4882a593Smuzhiyun 	struct snd_soc_dai *cpu_dai;
80*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
81*4882a593Smuzhiyun 	struct vad_soc_data *soc_data;
82*4882a593Smuzhiyun 	int mode;
83*4882a593Smuzhiyun 	u32 audio_src;
84*4882a593Smuzhiyun 	u32 audio_src_addr;
85*4882a593Smuzhiyun 	u32 audio_chnl;
86*4882a593Smuzhiyun 	u32 channels;
87*4882a593Smuzhiyun 	u32 sample_bytes;
88*4882a593Smuzhiyun 	u32 buffer_time; /* msec */
89*4882a593Smuzhiyun 	struct dentry *debugfs_dir;
90*4882a593Smuzhiyun 	void *buf;
91*4882a593Smuzhiyun 	bool acodec_cfg;
92*4882a593Smuzhiyun 	bool vswitch;
93*4882a593Smuzhiyun 	bool h_16bit;
94*4882a593Smuzhiyun 	enum rk_vad_version version;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
vframe_size(struct rockchip_vad * vad,int bytes)97*4882a593Smuzhiyun static inline int vframe_size(struct rockchip_vad *vad, int bytes)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	return bytes / vad->channels / vad->sample_bytes;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
chunk_sort(void __iomem * pos,void __iomem * end,int loop_cnt)102*4882a593Smuzhiyun static int chunk_sort(void __iomem *pos, void __iomem *end, int loop_cnt)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	char tbuf[CHUNK_SIZE];
105*4882a593Smuzhiyun 	int size1, size2;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	size1 = loop_cnt * 4;
108*4882a593Smuzhiyun 	size2 = CHUNK_SIZE - size1;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	while (pos < end) {
111*4882a593Smuzhiyun 		memcpy_fromio(&tbuf[0], pos + size1, size2);
112*4882a593Smuzhiyun 		memcpy_fromio(&tbuf[size2], pos, size1);
113*4882a593Smuzhiyun 		memcpy_toio(pos, &tbuf[0], CHUNK_SIZE);
114*4882a593Smuzhiyun 		pos += CHUNK_SIZE;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
vad_buffer_sort(struct rockchip_vad * vad)120*4882a593Smuzhiyun static int vad_buffer_sort(struct rockchip_vad *vad)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	struct vad_buf *vbuf = &vad->vbuf;
123*4882a593Smuzhiyun 	int loop_cnt = vbuf->loop_cnt;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	if (vad->version != VAD_RK1808ES)
126*4882a593Smuzhiyun 		return 0;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	if (vbuf->sorted || !vbuf->loop)
129*4882a593Smuzhiyun 		return 0;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	/* 16 words align */
132*4882a593Smuzhiyun 	if ((vbuf->pos - vbuf->begin) % CHUNK_SIZE ||
133*4882a593Smuzhiyun 	    (vbuf->end - vbuf->pos) % CHUNK_SIZE)
134*4882a593Smuzhiyun 		return -EINVAL;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	switch (loop_cnt) {
137*4882a593Smuzhiyun 	case 0:
138*4882a593Smuzhiyun 		loop_cnt = 16;
139*4882a593Smuzhiyun 		chunk_sort(vbuf->pos, vbuf->end, loop_cnt - 1);
140*4882a593Smuzhiyun 		vbuf->sorted = true;
141*4882a593Smuzhiyun 		break;
142*4882a593Smuzhiyun 	case 1:
143*4882a593Smuzhiyun 		chunk_sort(vbuf->begin, vbuf->pos, loop_cnt);
144*4882a593Smuzhiyun 		vbuf->sorted = true;
145*4882a593Smuzhiyun 		break;
146*4882a593Smuzhiyun 	case 2 ... 15:
147*4882a593Smuzhiyun 		chunk_sort(vbuf->pos, vbuf->end, loop_cnt - 1);
148*4882a593Smuzhiyun 		chunk_sort(vbuf->begin, vbuf->pos, loop_cnt);
149*4882a593Smuzhiyun 		vbuf->sorted = true;
150*4882a593Smuzhiyun 		break;
151*4882a593Smuzhiyun 	default:
152*4882a593Smuzhiyun 		return -EINVAL;
153*4882a593Smuzhiyun 	}
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
rockchip_vad_stop(struct rockchip_vad * vad)158*4882a593Smuzhiyun static int rockchip_vad_stop(struct rockchip_vad *vad)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	unsigned int val, frames;
161*4882a593Smuzhiyun 	struct vad_buf *vbuf = &vad->vbuf;
162*4882a593Smuzhiyun 	struct vad_params *params = &vad->params;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_CTRL, &val);
165*4882a593Smuzhiyun 	if ((val & VAD_EN_MASK) == VAD_DISABLE)
166*4882a593Smuzhiyun 		return 0;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	/* sample cnt will be clear after vad disabled */
169*4882a593Smuzhiyun 	if (vad->version == VAD_RK1808ES)
170*4882a593Smuzhiyun 		regmap_read(vad->regmap, VAD_SAMPLE_CNT, &frames);
171*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, VAD_EN_MASK, VAD_DISABLE);
172*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_CTRL, &val);
173*4882a593Smuzhiyun 	vad->h_16bit = (val & AUDIO_24BIT_SAT_MASK) == AUDIO_H16B;
174*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_RAM_END_ADDR, &val);
175*4882a593Smuzhiyun 	vbuf->end = vbuf->begin + (val - vad->memphy) + 0x8;
176*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_INT, &val);
177*4882a593Smuzhiyun 	val &= BIT(8);
178*4882a593Smuzhiyun 	vbuf->loop = val;
179*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_RAM_CUR_ADDR, &val);
180*4882a593Smuzhiyun 	if (!val) {
181*4882a593Smuzhiyun 		vbuf->size = 0;
182*4882a593Smuzhiyun 		vbuf->cur = vbuf->begin;
183*4882a593Smuzhiyun 		return 0;
184*4882a593Smuzhiyun 	}
185*4882a593Smuzhiyun 	vbuf->cur = vbuf->begin + (val - vad->memphy);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if (vbuf->loop) {
188*4882a593Smuzhiyun 		vbuf->size = vbuf->end - vbuf->begin;
189*4882a593Smuzhiyun 		vbuf->pos = vbuf->cur;
190*4882a593Smuzhiyun 	} else {
191*4882a593Smuzhiyun 		vbuf->size = vbuf->cur - vbuf->begin;
192*4882a593Smuzhiyun 		vbuf->end = vbuf->cur;
193*4882a593Smuzhiyun 		vbuf->pos = vbuf->begin;
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (vad->version == VAD_RK1808ES) {
197*4882a593Smuzhiyun 		vbuf->loop_cnt = (frames / vframe_size(vad, vbuf->size)) % 16;
198*4882a593Smuzhiyun 		/* due to get loop_cnt before vad disable, we should take
199*4882a593Smuzhiyun 		 * the boundary issue into account, and judge whether the
200*4882a593Smuzhiyun 		 * loop_cnt change to loop_cnt + 1 or not when vad disable.
201*4882a593Smuzhiyun 		 */
202*4882a593Smuzhiyun 		if (vbuf->loop) {
203*4882a593Smuzhiyun 			frames = frames % vframe_size(vad, vbuf->size);
204*4882a593Smuzhiyun 			val = vframe_size(vad, vbuf->pos - vbuf->begin);
205*4882a593Smuzhiyun 			if (frames > val)
206*4882a593Smuzhiyun 				vbuf->loop_cnt = (vbuf->loop_cnt + 1) % 16;
207*4882a593Smuzhiyun 		}
208*4882a593Smuzhiyun 		vbuf->sorted = false;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_DET_CON0, &val);
211*4882a593Smuzhiyun 	params->noise_level = (val & NOISE_LEVEL_MASK) >> NOISE_LEVEL_SHIFT;
212*4882a593Smuzhiyun 	params->vad_con_thd = (val & VAD_CON_THD_MASK) >> VAD_CON_THD_SHIFT;
213*4882a593Smuzhiyun 	params->voice_gain = (val & GAIN_MASK) >> GAIN_SHIFT;
214*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_DET_CON1, &val);
215*4882a593Smuzhiyun 	params->sound_thd = val & SOUND_THD_MASK;
216*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_DET_CON5, &val);
217*4882a593Smuzhiyun 	params->noise_abs = val & NOISE_ABS_MASK;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	vad_preprocess_init(params);
220*4882a593Smuzhiyun 	voice_inactive_frames = 0;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	dev_info(vad->dev, "bufsize: %d, hw_abs: 0x%x\n",
223*4882a593Smuzhiyun 		 vbuf->size, params->noise_abs);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
rockchip_vad_setup(struct rockchip_vad * vad)228*4882a593Smuzhiyun static int rockchip_vad_setup(struct rockchip_vad *vad)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	struct regmap *regmap = vad->regmap;
231*4882a593Smuzhiyun 	u32 val, mask;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	dev_info(vad->dev, "sw_abs: 0x%x\n",
234*4882a593Smuzhiyun 		 vad->uparams.noise_abs);
235*4882a593Smuzhiyun 	regmap_update_bits(regmap, VAD_DET_CON5,
236*4882a593Smuzhiyun 			   NOISE_ABS_MASK, vad->uparams.noise_abs);
237*4882a593Smuzhiyun 	regmap_update_bits(regmap, VAD_CTRL, VAD_EN_MASK, VAD_EN);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	val = ERR_INT_EN | VAD_DET_INT_EN;
240*4882a593Smuzhiyun 	mask = ERR_INT_EN_MASK | VAD_DET_INT_EN_MASK;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	regmap_update_bits(regmap, VAD_INT, mask, val);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	vad_preprocess_destroy();
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
substream_get_drvdata(struct snd_pcm_substream * substream)249*4882a593Smuzhiyun static struct rockchip_vad *substream_get_drvdata(struct snd_pcm_substream *substream)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
252*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
253*4882a593Smuzhiyun 	unsigned int i;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (!rtd)
256*4882a593Smuzhiyun 		return NULL;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	for (i = 0; i < rtd->num_codecs; i++) {
259*4882a593Smuzhiyun 		struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, i);
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 		if (strstr(codec_dai->name, "vad"))
262*4882a593Smuzhiyun 			vad = snd_soc_component_get_drvdata(codec_dai->component);
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return vad;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /**
269*4882a593Smuzhiyun  * snd_pcm_vad_avail - Get the available (readable) space for vad
270*4882a593Smuzhiyun  * @runtime: PCM substream instance
271*4882a593Smuzhiyun  *
272*4882a593Smuzhiyun  * Result is between 0 ... (boundary - 1)
273*4882a593Smuzhiyun  */
snd_pcm_vad_avail(struct snd_pcm_substream * substream)274*4882a593Smuzhiyun snd_pcm_uframes_t snd_pcm_vad_avail(struct snd_pcm_substream *substream)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
277*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
278*4882a593Smuzhiyun 	struct vad_buf *vbuf;
279*4882a593Smuzhiyun 	snd_pcm_uframes_t vframes;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	vad = substream_get_drvdata(substream);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	if (!vad)
284*4882a593Smuzhiyun 		return 0;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	vbuf = &vad->vbuf;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	if (vbuf->size <= 0)
289*4882a593Smuzhiyun 		return 0;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	vframes = samples_to_bytes(runtime, vad->channels);
292*4882a593Smuzhiyun 	if (vframes)
293*4882a593Smuzhiyun 		vframes = vbuf->size / vframes;
294*4882a593Smuzhiyun 	if (!vframes)
295*4882a593Smuzhiyun 		dev_err(vad->dev, "residue bytes: %d\n", vbuf->size);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	return vframes;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun EXPORT_SYMBOL(snd_pcm_vad_avail);
300*4882a593Smuzhiyun 
snd_pcm_vad_read(struct snd_pcm_substream * substream,void __user * buf,snd_pcm_uframes_t frames)301*4882a593Smuzhiyun snd_pcm_sframes_t snd_pcm_vad_read(struct snd_pcm_substream *substream,
302*4882a593Smuzhiyun 				   void __user *buf, snd_pcm_uframes_t frames)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
305*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
306*4882a593Smuzhiyun 	struct vad_buf *vbuf;
307*4882a593Smuzhiyun 	snd_pcm_uframes_t avail;
308*4882a593Smuzhiyun 	int bytes, vbytes, frame_sz, vframe_sz, padding_sz;
309*4882a593Smuzhiyun 	unsigned int i;
310*4882a593Smuzhiyun 	void *pbuf, *sbuf;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	vad = substream_get_drvdata(substream);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	if (!vad)
315*4882a593Smuzhiyun 		return -EFAULT;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	vbuf = &vad->vbuf;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	avail = snd_pcm_vad_avail(substream);
320*4882a593Smuzhiyun 	avail = avail > frames ? frames : avail;
321*4882a593Smuzhiyun 	bytes = frames_to_bytes(runtime, avail);
322*4882a593Smuzhiyun 	if (bytes <= 0)
323*4882a593Smuzhiyun 		return -EFAULT;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	if (vad_buffer_sort(vad) < 0) {
326*4882a593Smuzhiyun 		dev_err(vad->dev, "buffer sort failed\n");
327*4882a593Smuzhiyun 		return -EFAULT;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (!vad->buf) {
331*4882a593Smuzhiyun 		vad->buf = kzalloc(bytes, GFP_KERNEL);
332*4882a593Smuzhiyun 		if (!vad->buf)
333*4882a593Smuzhiyun 			return -ENOMEM;
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	frame_sz = frames_to_bytes(runtime, 1);
337*4882a593Smuzhiyun 	vframe_sz = samples_to_bytes(runtime, vad->channels);
338*4882a593Smuzhiyun 	padding_sz = frame_sz - vframe_sz;
339*4882a593Smuzhiyun 	vbytes = vframe_sz * avail;
340*4882a593Smuzhiyun 	sbuf = vad->buf;
341*4882a593Smuzhiyun 	pbuf = vad->buf + bytes - vbytes;
342*4882a593Smuzhiyun 	if (!vbuf->loop) {
343*4882a593Smuzhiyun 		memcpy_fromio(pbuf, vbuf->pos, vbytes);
344*4882a593Smuzhiyun 		vbuf->pos += vbytes;
345*4882a593Smuzhiyun 	} else {
346*4882a593Smuzhiyun 		if ((vbuf->pos + vbytes) <= vbuf->end) {
347*4882a593Smuzhiyun 			memcpy_fromio(pbuf, vbuf->pos, vbytes);
348*4882a593Smuzhiyun 			vbuf->pos += vbytes;
349*4882a593Smuzhiyun 		} else {
350*4882a593Smuzhiyun 			int part1 = vbuf->end - vbuf->pos;
351*4882a593Smuzhiyun 			int part2 = vbytes - part1;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 			memcpy_fromio(pbuf, vbuf->pos, part1);
354*4882a593Smuzhiyun 			memcpy_fromio(pbuf + part1, vbuf->begin, part2);
355*4882a593Smuzhiyun 			vbuf->pos = vbuf->begin + part2;
356*4882a593Smuzhiyun 		}
357*4882a593Smuzhiyun 	}
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	if (padding_sz) {
360*4882a593Smuzhiyun 		for (i = 0; i < avail; i++) {
361*4882a593Smuzhiyun 			memmove(sbuf, pbuf, vframe_sz);
362*4882a593Smuzhiyun 			sbuf += vframe_sz;
363*4882a593Smuzhiyun 			pbuf += vframe_sz;
364*4882a593Smuzhiyun 			memset(sbuf, 0x0, padding_sz);
365*4882a593Smuzhiyun 			sbuf += padding_sz;
366*4882a593Smuzhiyun 		}
367*4882a593Smuzhiyun 	}
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	if (copy_to_user(buf, vad->buf, bytes))
370*4882a593Smuzhiyun 		return -EFAULT;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	vbuf->size -= vbytes;
373*4882a593Smuzhiyun 	if (vbuf->size <= 0) {
374*4882a593Smuzhiyun 		kfree(vad->buf);
375*4882a593Smuzhiyun 		vad->buf = NULL;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	return avail;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun EXPORT_SYMBOL(snd_pcm_vad_read);
381*4882a593Smuzhiyun 
snd_pcm_vad_preprocess(struct snd_pcm_substream * substream,void * buf,snd_pcm_uframes_t size)382*4882a593Smuzhiyun int snd_pcm_vad_preprocess(struct snd_pcm_substream *substream,
383*4882a593Smuzhiyun 			   void *buf, snd_pcm_uframes_t size)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
386*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
387*4882a593Smuzhiyun 	unsigned int i;
388*4882a593Smuzhiyun 	s16 *data;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	vad = substream_get_drvdata(substream);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	if (!vad)
393*4882a593Smuzhiyun 		return 0;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	buf += samples_to_bytes(runtime, vad->audio_chnl);
396*4882a593Smuzhiyun 	/* retrieve the high 16bit data */
397*4882a593Smuzhiyun 	if (runtime->sample_bits == 32 && vad->h_16bit)
398*4882a593Smuzhiyun 		buf += 2;
399*4882a593Smuzhiyun 	for (i = 0; i < size; i++) {
400*4882a593Smuzhiyun 		data = buf;
401*4882a593Smuzhiyun 		if (vad_preprocess(*data))
402*4882a593Smuzhiyun 			voice_inactive_frames = 0;
403*4882a593Smuzhiyun 		else
404*4882a593Smuzhiyun 			voice_inactive_frames++;
405*4882a593Smuzhiyun 		buf += frames_to_bytes(runtime, 1);
406*4882a593Smuzhiyun 	}
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	vad_preprocess_update_params(&vad->uparams);
409*4882a593Smuzhiyun 	return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun EXPORT_SYMBOL(snd_pcm_vad_preprocess);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun /**
414*4882a593Smuzhiyun  * snd_pcm_vad_attached - Check whether vad is attached to substream or not
415*4882a593Smuzhiyun  * @substream: PCM substream instance
416*4882a593Smuzhiyun  *
417*4882a593Smuzhiyun  * Result is true for attached or false for detached
418*4882a593Smuzhiyun  */
snd_pcm_vad_attached(struct snd_pcm_substream * substream)419*4882a593Smuzhiyun bool snd_pcm_vad_attached(struct snd_pcm_substream *substream)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	if (vad_substream == substream)
424*4882a593Smuzhiyun 		vad = substream_get_drvdata(substream);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	if (vad && vad->vswitch)
427*4882a593Smuzhiyun 		return true;
428*4882a593Smuzhiyun 	else
429*4882a593Smuzhiyun 		return false;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun EXPORT_SYMBOL(snd_pcm_vad_attached);
432*4882a593Smuzhiyun 
vad_memcpy_fromio(void * to,void __iomem * from,int size,int frame_sz,int padding_sz)433*4882a593Smuzhiyun static int vad_memcpy_fromio(void *to, void __iomem *from,
434*4882a593Smuzhiyun 			     int size, int frame_sz, int padding_sz)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	int i, step_src, step_dst, fcount;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	step_src = frame_sz;
439*4882a593Smuzhiyun 	step_dst = frame_sz + padding_sz;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	if (size % frame_sz) {
442*4882a593Smuzhiyun 		pr_err("%s: invalid size: %d\n", __func__, size);
443*4882a593Smuzhiyun 		return -EINVAL;
444*4882a593Smuzhiyun 	}
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	fcount = size / frame_sz;
447*4882a593Smuzhiyun 	if (padding_sz) {
448*4882a593Smuzhiyun 		for (i = 0; i < fcount; i++) {
449*4882a593Smuzhiyun 			memcpy_fromio(to, from, frame_sz);
450*4882a593Smuzhiyun 			to += step_dst;
451*4882a593Smuzhiyun 			from += step_src;
452*4882a593Smuzhiyun 		}
453*4882a593Smuzhiyun 	} else {
454*4882a593Smuzhiyun 		memcpy_fromio(to, from, size);
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	return 0;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun /**
461*4882a593Smuzhiyun  * snd_pcm_vad_memcpy - Copy vad data to dst
462*4882a593Smuzhiyun  * @substream: PCM substream instance
463*4882a593Smuzhiyun  * @buf: dst buf
464*4882a593Smuzhiyun  * @frames:  size in frame
465*4882a593Smuzhiyun  *
466*4882a593Smuzhiyun  * Result is copied frames for success or errno for fail
467*4882a593Smuzhiyun  */
snd_pcm_vad_memcpy(struct snd_pcm_substream * substream,void * buf,snd_pcm_uframes_t frames)468*4882a593Smuzhiyun snd_pcm_sframes_t snd_pcm_vad_memcpy(struct snd_pcm_substream *substream,
469*4882a593Smuzhiyun 				     void *buf, snd_pcm_uframes_t frames)
470*4882a593Smuzhiyun {
471*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = substream->runtime;
472*4882a593Smuzhiyun 	struct rockchip_vad *vad = NULL;
473*4882a593Smuzhiyun 	struct vad_buf *vbuf;
474*4882a593Smuzhiyun 	snd_pcm_uframes_t avail;
475*4882a593Smuzhiyun 	int bytes, vbytes, frame_sz, vframe_sz, padding_sz;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	vad = substream_get_drvdata(substream);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	if (!vad)
480*4882a593Smuzhiyun 		return -EFAULT;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	vbuf = &vad->vbuf;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	avail = snd_pcm_vad_avail(substream);
485*4882a593Smuzhiyun 	avail = avail > frames ? frames : avail;
486*4882a593Smuzhiyun 	bytes = frames_to_bytes(runtime, avail);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	if (bytes <= 0)
489*4882a593Smuzhiyun 		return -EFAULT;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	if (vad_buffer_sort(vad) < 0) {
492*4882a593Smuzhiyun 		dev_err(vad->dev, "buffer sort failed\n");
493*4882a593Smuzhiyun 		return -EFAULT;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	frame_sz = frames_to_bytes(runtime, 1);
497*4882a593Smuzhiyun 	vframe_sz = samples_to_bytes(runtime, vad->channels);
498*4882a593Smuzhiyun 	padding_sz = frame_sz - vframe_sz;
499*4882a593Smuzhiyun 	vbytes = vframe_sz * avail;
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	memset(buf, 0x0, bytes);
502*4882a593Smuzhiyun 	if (!vbuf->loop) {
503*4882a593Smuzhiyun 		vad_memcpy_fromio(buf, vbuf->pos, vbytes,
504*4882a593Smuzhiyun 				  vframe_sz, padding_sz);
505*4882a593Smuzhiyun 		vbuf->pos += vbytes;
506*4882a593Smuzhiyun 	} else {
507*4882a593Smuzhiyun 		if ((vbuf->pos + vbytes) <= vbuf->end) {
508*4882a593Smuzhiyun 			vad_memcpy_fromio(buf, vbuf->pos, vbytes,
509*4882a593Smuzhiyun 					  vframe_sz, padding_sz);
510*4882a593Smuzhiyun 			vbuf->pos += vbytes;
511*4882a593Smuzhiyun 		} else {
512*4882a593Smuzhiyun 			int part1 = vbuf->end - vbuf->pos;
513*4882a593Smuzhiyun 			int part2 = vbytes - part1;
514*4882a593Smuzhiyun 			int offset = part1;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 			if (padding_sz)
517*4882a593Smuzhiyun 				offset = part1 / vframe_sz * frame_sz;
518*4882a593Smuzhiyun 			vad_memcpy_fromio(buf, vbuf->pos, part1,
519*4882a593Smuzhiyun 					  vframe_sz, padding_sz);
520*4882a593Smuzhiyun 			vad_memcpy_fromio(buf + offset, vbuf->begin, part2,
521*4882a593Smuzhiyun 					  vframe_sz, padding_sz);
522*4882a593Smuzhiyun 			vbuf->pos = vbuf->begin + part2;
523*4882a593Smuzhiyun 		}
524*4882a593Smuzhiyun 	}
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	vbuf->size -= vbytes;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	return avail;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun EXPORT_SYMBOL(snd_pcm_vad_memcpy);
531*4882a593Smuzhiyun 
rockchip_vad_writeable_reg(struct device * dev,unsigned int reg)532*4882a593Smuzhiyun static bool rockchip_vad_writeable_reg(struct device *dev, unsigned int reg)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun 	return true;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
rockchip_vad_readable_reg(struct device * dev,unsigned int reg)537*4882a593Smuzhiyun static bool rockchip_vad_readable_reg(struct device *dev, unsigned int reg)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	return true;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun 
rockchip_vad_volatile_reg(struct device * dev,unsigned int reg)542*4882a593Smuzhiyun static bool rockchip_vad_volatile_reg(struct device *dev, unsigned int reg)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun 	switch (reg) {
545*4882a593Smuzhiyun 	case VAD_INT:
546*4882a593Smuzhiyun 	case VAD_RAM_CUR_ADDR:
547*4882a593Smuzhiyun 	case VAD_DET_CON5:
548*4882a593Smuzhiyun 	case VAD_SAMPLE_CNT:
549*4882a593Smuzhiyun 		return true;
550*4882a593Smuzhiyun 	default:
551*4882a593Smuzhiyun 		return false;
552*4882a593Smuzhiyun 	}
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static const struct reg_default rk1808_vad_reg_defaults[] = {
556*4882a593Smuzhiyun 	{VAD_CTRL,     0x03000000},
557*4882a593Smuzhiyun 	{VAD_DET_CON0, 0x01024008},
558*4882a593Smuzhiyun 	{VAD_DET_CON1, 0x04ff0064},
559*4882a593Smuzhiyun 	{VAD_DET_CON2, 0x3bf5e663},
560*4882a593Smuzhiyun 	{VAD_DET_CON3, 0x3bf58817},
561*4882a593Smuzhiyun 	{VAD_DET_CON4, 0x382b8858},
562*4882a593Smuzhiyun };
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun static const struct reg_default rk3308_vad_reg_defaults[] = {
565*4882a593Smuzhiyun 	{VAD_CTRL,     0x03000000},
566*4882a593Smuzhiyun 	{VAD_DET_CON0, 0x00024020},
567*4882a593Smuzhiyun 	{VAD_DET_CON1, 0x00ff0064},
568*4882a593Smuzhiyun 	{VAD_DET_CON2, 0x3bf5e663},
569*4882a593Smuzhiyun 	{VAD_DET_CON3, 0x3bf58817},
570*4882a593Smuzhiyun 	{VAD_DET_CON4, 0x382b8858},
571*4882a593Smuzhiyun 	{VAD_RAM_BEGIN_ADDR, 0xfff88000},
572*4882a593Smuzhiyun 	{VAD_RAM_END_ADDR, 0xfffbfff8},
573*4882a593Smuzhiyun };
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun static const struct regmap_config rk1808_vad_regmap_config = {
576*4882a593Smuzhiyun 	.reg_bits = 32,
577*4882a593Smuzhiyun 	.reg_stride = 4,
578*4882a593Smuzhiyun 	.val_bits = 32,
579*4882a593Smuzhiyun 	.max_register = VAD_NOISE_DATA,
580*4882a593Smuzhiyun 	.reg_defaults = rk1808_vad_reg_defaults,
581*4882a593Smuzhiyun 	.num_reg_defaults = ARRAY_SIZE(rk1808_vad_reg_defaults),
582*4882a593Smuzhiyun 	.writeable_reg = rockchip_vad_writeable_reg,
583*4882a593Smuzhiyun 	.readable_reg = rockchip_vad_readable_reg,
584*4882a593Smuzhiyun 	.volatile_reg = rockchip_vad_volatile_reg,
585*4882a593Smuzhiyun 	.cache_type = REGCACHE_FLAT,
586*4882a593Smuzhiyun };
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun static const struct regmap_config rk3308_vad_regmap_config = {
589*4882a593Smuzhiyun 	.reg_bits = 32,
590*4882a593Smuzhiyun 	.reg_stride = 4,
591*4882a593Smuzhiyun 	.val_bits = 32,
592*4882a593Smuzhiyun 	.max_register = VAD_INT,
593*4882a593Smuzhiyun 	.reg_defaults = rk3308_vad_reg_defaults,
594*4882a593Smuzhiyun 	.num_reg_defaults = ARRAY_SIZE(rk3308_vad_reg_defaults),
595*4882a593Smuzhiyun 	.writeable_reg = rockchip_vad_writeable_reg,
596*4882a593Smuzhiyun 	.readable_reg = rockchip_vad_readable_reg,
597*4882a593Smuzhiyun 	.volatile_reg = rockchip_vad_volatile_reg,
598*4882a593Smuzhiyun 	.cache_type = REGCACHE_FLAT,
599*4882a593Smuzhiyun };
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun static const struct audio_src_addr_map rk1808_addr_map[] = {
602*4882a593Smuzhiyun 	{ 1, RK1808_I2S0 },
603*4882a593Smuzhiyun 	{ 3, RK1808_I2S1 },
604*4882a593Smuzhiyun 	{ 4, RK1808_PDM },
605*4882a593Smuzhiyun 	{ /* sentinel */ },
606*4882a593Smuzhiyun };
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun static const struct audio_src_addr_map rk3308_addr_map[] = {
609*4882a593Smuzhiyun 	{ 0, RK3308_I2S_8CH_0 },
610*4882a593Smuzhiyun 	{ 1, RK3308_I2S_8CH_1 },
611*4882a593Smuzhiyun 	{ 2, RK3308_I2S_8CH_2 },
612*4882a593Smuzhiyun 	{ 3, RK3308_I2S_8CH_3 },
613*4882a593Smuzhiyun 	{ 4, RK3308_PDM_8CH },
614*4882a593Smuzhiyun 	{ /* sentinel */ },
615*4882a593Smuzhiyun };
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun static const struct audio_src_addr_map rk3568_addr_map[] = {
618*4882a593Smuzhiyun 	{ 0, RK3568_I2S_8CH_1 },
619*4882a593Smuzhiyun 	{ 1, RK3568_I2S_2CH_2 },
620*4882a593Smuzhiyun 	{ 2, RK3568_I2S_2CH_3 },
621*4882a593Smuzhiyun 	{ 3, RK3568_PDM },
622*4882a593Smuzhiyun 	{ /* sentinel */ },
623*4882a593Smuzhiyun };
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun static const struct audio_src_addr_map rk3588_addr_map[] = {
626*4882a593Smuzhiyun 	{ 0, RK3588_PDM0 },
627*4882a593Smuzhiyun 	{ 1, RK3588_I2S1_8CH },
628*4882a593Smuzhiyun 	{ /* sentinel */ },
629*4882a593Smuzhiyun };
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun static const struct vad_soc_data rk1808es_soc_data = {
632*4882a593Smuzhiyun 	.version = VAD_RK1808ES,
633*4882a593Smuzhiyun 	.map = rk1808_addr_map,
634*4882a593Smuzhiyun };
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun static const struct vad_soc_data rk1808_soc_data = {
637*4882a593Smuzhiyun 	.version = VAD_RK1808,
638*4882a593Smuzhiyun 	.map = rk1808_addr_map,
639*4882a593Smuzhiyun };
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun static const struct vad_soc_data rk3308_soc_data = {
642*4882a593Smuzhiyun 	.version = VAD_RK3308,
643*4882a593Smuzhiyun 	.map = rk3308_addr_map,
644*4882a593Smuzhiyun };
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun static const struct vad_soc_data rk3568_soc_data = {
647*4882a593Smuzhiyun 	.version = VAD_RK1808,
648*4882a593Smuzhiyun 	.map = rk3568_addr_map,
649*4882a593Smuzhiyun };
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun static const struct vad_soc_data rk3588_soc_data = {
652*4882a593Smuzhiyun 	.version = VAD_RK1808,
653*4882a593Smuzhiyun 	.map = rk3588_addr_map,
654*4882a593Smuzhiyun };
655*4882a593Smuzhiyun 
rockchip_vad_get_audio_src_address(struct rockchip_vad * vad,u32 addr)656*4882a593Smuzhiyun static int rockchip_vad_get_audio_src_address(struct rockchip_vad *vad,
657*4882a593Smuzhiyun 					      u32 addr)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun 	const struct audio_src_addr_map *map = vad->soc_data->map;
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	for (; map->addr; map++) {
662*4882a593Smuzhiyun 		if ((map->addr & 0xffff0000) == addr) {
663*4882a593Smuzhiyun 			vad->audio_src = map->id;
664*4882a593Smuzhiyun 			vad->audio_src_addr = map->addr;
665*4882a593Smuzhiyun 			return 0;
666*4882a593Smuzhiyun 		}
667*4882a593Smuzhiyun 	}
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	return -ENODEV;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
rockchip_vad_irq(int irqno,void * dev_id)672*4882a593Smuzhiyun static irqreturn_t rockchip_vad_irq(int irqno, void *dev_id)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun 	struct rockchip_vad *vad = dev_id;
675*4882a593Smuzhiyun 	unsigned  int val;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	regmap_read(vad->regmap, VAD_INT, &val);
678*4882a593Smuzhiyun 	regmap_write(vad->regmap, VAD_INT, val);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	dev_dbg(vad->dev, "irq 0x%08x\n", val);
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	return IRQ_HANDLED;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun static const struct reg_sequence rockchip_vad_acodec_adc_enable[] = {
686*4882a593Smuzhiyun 	{ VAD_OD_ADDR0, 0x36261606 },
687*4882a593Smuzhiyun 	{ VAD_D_DATA0, 0x51515151 },
688*4882a593Smuzhiyun 	{ VAD_OD_ADDR1, 0x30201000 },
689*4882a593Smuzhiyun 	{ VAD_D_DATA1, 0xbbbbbbbb },
690*4882a593Smuzhiyun 	{ VAD_OD_ADDR2, 0x32221202 },
691*4882a593Smuzhiyun 	{ VAD_D_DATA2, 0x11111111 },
692*4882a593Smuzhiyun 	{ VAD_OD_ADDR3, 0x35251505 },
693*4882a593Smuzhiyun 	{ VAD_D_DATA3, 0x77777777 },
694*4882a593Smuzhiyun 	{ VAD_OD_ADDR4, 0x32221202 },
695*4882a593Smuzhiyun 	{ VAD_D_DATA4, 0x33333333 },
696*4882a593Smuzhiyun 	{ VAD_OD_ADDR5, 0x30201000 },
697*4882a593Smuzhiyun 	{ VAD_D_DATA5, 0xffffffff },
698*4882a593Smuzhiyun 	{ VAD_OD_ADDR6, 0x32221202 },
699*4882a593Smuzhiyun 	{ VAD_D_DATA6, 0x77777777 },
700*4882a593Smuzhiyun };
701*4882a593Smuzhiyun 
rockchip_vad_config_acodec(struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)702*4882a593Smuzhiyun static int rockchip_vad_config_acodec(struct snd_pcm_hw_params *params,
703*4882a593Smuzhiyun 				      struct snd_soc_dai *dai)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
706*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
707*4882a593Smuzhiyun 	unsigned int val = 0;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (!vad->acodec_cfg)
710*4882a593Smuzhiyun 		return 0;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	val = ACODEC_BASE + ACODEC_ADC_ANA_CON0;
713*4882a593Smuzhiyun 	regmap_write(vad->regmap, VAD_ID_ADDR, val);
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	regmap_multi_reg_write(vad->regmap, rockchip_vad_acodec_adc_enable,
716*4882a593Smuzhiyun 			       ARRAY_SIZE(rockchip_vad_acodec_adc_enable));
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, ACODE_CFG_REG_NUM_MASK,
719*4882a593Smuzhiyun 			   ACODE_CFG_REG_NUM(ACODEC_REG_NUM));
720*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, CFG_ACODE_AFTER_DET_EN_MASK,
721*4882a593Smuzhiyun 			   CFG_ACODE_AFTER_DET_EN);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	return 0;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun 
rockchip_vad_find_dai(struct device_node * np)726*4882a593Smuzhiyun static struct snd_soc_dai *rockchip_vad_find_dai(struct device_node *np)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun 	struct snd_soc_dai_link_component dai_component = { 0 };
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	dai_component.of_node = np;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	return snd_soc_find_dai_with_mutex(&dai_component);
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun 
hw_refine_channels(struct snd_pcm_hw_params * params,unsigned int channel)735*4882a593Smuzhiyun static void hw_refine_channels(struct snd_pcm_hw_params *params,
736*4882a593Smuzhiyun 			       unsigned int channel)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun 	struct snd_interval *c =
739*4882a593Smuzhiyun 		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	c->min = channel;
742*4882a593Smuzhiyun 	c->max = channel;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun 
rockchip_vad_params_fixup(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)745*4882a593Smuzhiyun static void rockchip_vad_params_fixup(struct snd_pcm_substream *substream,
746*4882a593Smuzhiyun 				      struct snd_pcm_hw_params *params,
747*4882a593Smuzhiyun 				      struct snd_soc_dai *dai)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(dai->component);
750*4882a593Smuzhiyun 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
751*4882a593Smuzhiyun 	struct snd_soc_dai *cpu_dai, *audio_src_dai;
752*4882a593Smuzhiyun 	struct device_node *np;
753*4882a593Smuzhiyun 	struct rk_mdais_dev *mdais;
754*4882a593Smuzhiyun 	unsigned int *channel_maps;
755*4882a593Smuzhiyun 	int i;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	cpu_dai = asoc_rtd_to_cpu(rtd, 0);
758*4882a593Smuzhiyun 	vad->cpu_dai = cpu_dai;
759*4882a593Smuzhiyun 	vad->substream = substream;
760*4882a593Smuzhiyun 	np = cpu_dai->dev->of_node;
761*4882a593Smuzhiyun 	if (of_device_is_compatible(np, "rockchip,multi-dais")) {
762*4882a593Smuzhiyun 		audio_src_dai = rockchip_vad_find_dai(vad->audio_node);
763*4882a593Smuzhiyun 		mdais = snd_soc_dai_get_drvdata(cpu_dai);
764*4882a593Smuzhiyun 		channel_maps = mdais->capture_channel_maps;
765*4882a593Smuzhiyun 		for (i = 0; i < mdais->num_dais; i++) {
766*4882a593Smuzhiyun 			if (audio_src_dai == mdais->dais[i].dai &&
767*4882a593Smuzhiyun 			    channel_maps[i])
768*4882a593Smuzhiyun 				hw_refine_channels(params, channel_maps[i]);
769*4882a593Smuzhiyun 		}
770*4882a593Smuzhiyun 	}
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun 
rockchip_vad_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)773*4882a593Smuzhiyun static int rockchip_vad_hw_params(struct snd_pcm_substream *substream,
774*4882a593Smuzhiyun 				  struct snd_pcm_hw_params *params,
775*4882a593Smuzhiyun 				  struct snd_soc_dai *dai)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
778*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
779*4882a593Smuzhiyun 	unsigned int val = 0, mask = 0, frame_bytes, buf_time;
780*4882a593Smuzhiyun 
781*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
782*4882a593Smuzhiyun 		return 0;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	rockchip_vad_params_fixup(substream, params, dai);
785*4882a593Smuzhiyun 	vad->channels = params_channels(params);
786*4882a593Smuzhiyun 	switch (params_format(params)) {
787*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S16_LE:
788*4882a593Smuzhiyun 		val = AUDIO_CHNL_16B;
789*4882a593Smuzhiyun 		vad->sample_bytes = 2;
790*4882a593Smuzhiyun 		break;
791*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_LE:
792*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S32_LE:
793*4882a593Smuzhiyun 		val = AUDIO_CHNL_24B;
794*4882a593Smuzhiyun 		vad->sample_bytes = 4;
795*4882a593Smuzhiyun 		break;
796*4882a593Smuzhiyun 	default:
797*4882a593Smuzhiyun 		return -EINVAL;
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, AUDIO_CHNL_BW_MASK, val);
801*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, AUDIO_CHNL_NUM_MASK,
802*4882a593Smuzhiyun 			   AUDIO_CHNL_NUM(params_channels(params)));
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	val = SRC_ADDR_MODE_INC | SRC_BURST_INCR;
805*4882a593Smuzhiyun 	mask = SRC_ADDR_MODE_MASK | SRC_BURST_MASK | INCR_BURST_LEN_MASK;
806*4882a593Smuzhiyun 	switch (params_channels(params)) {
807*4882a593Smuzhiyun 	case 8:
808*4882a593Smuzhiyun 		/* fallthrough */
809*4882a593Smuzhiyun 	case 6:
810*4882a593Smuzhiyun 		/* fallthrough */
811*4882a593Smuzhiyun 	case 4:
812*4882a593Smuzhiyun 		/* fallthrough */
813*4882a593Smuzhiyun 	case 2:
814*4882a593Smuzhiyun 		val |= INCR_BURST_LEN(params_channels(params));
815*4882a593Smuzhiyun 		break;
816*4882a593Smuzhiyun 	default:
817*4882a593Smuzhiyun 		return -EINVAL;
818*4882a593Smuzhiyun 	}
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	if (vad->version == VAD_RK1808ES) {
821*4882a593Smuzhiyun 		val = SRC_ADDR_MODE_INC | SRC_BURST_INCR16;
822*4882a593Smuzhiyun 		mask = SRC_ADDR_MODE_MASK | SRC_BURST_MASK | SRC_BURST_NUM_MASK;
823*4882a593Smuzhiyun 		if (params_channels(params) == 6)
824*4882a593Smuzhiyun 			val |= SRC_BURST_NUM(3);
825*4882a593Smuzhiyun 	}
826*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, mask, val);
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	/* calculate buffer space according buffer time */
829*4882a593Smuzhiyun 	if (vad->buffer_time) {
830*4882a593Smuzhiyun 		frame_bytes = snd_pcm_format_size(params_format(params),
831*4882a593Smuzhiyun 						  params_channels(params));
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 		buf_time = vad->memphy_end - vad->memphy + 0x8;
834*4882a593Smuzhiyun 		buf_time *= 1000;
835*4882a593Smuzhiyun 		buf_time /= (frame_bytes * params_rate(params));
836*4882a593Smuzhiyun 		if (buf_time < vad->buffer_time)
837*4882a593Smuzhiyun 			dev_info(vad->dev, "max buffer time: %u ms.\n", buf_time);
838*4882a593Smuzhiyun 		buf_time = min(buf_time, vad->buffer_time);
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 		val = params_rate(params) * buf_time / 1000;
841*4882a593Smuzhiyun 		if (vad->version == VAD_RK1808ES)
842*4882a593Smuzhiyun 			val &= ~0xf; /* 16 align */
843*4882a593Smuzhiyun 		val *= frame_bytes;
844*4882a593Smuzhiyun 		val += vad->memphy;
845*4882a593Smuzhiyun 		val -= 0x8;
846*4882a593Smuzhiyun 		if (val < vad->memphy || val > vad->memphy_end)
847*4882a593Smuzhiyun 			return -EINVAL;
848*4882a593Smuzhiyun 		regmap_write(vad->regmap, VAD_RAM_END_ADDR, val);
849*4882a593Smuzhiyun 	}
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	/*
852*4882a593Smuzhiyun 	 * config acodec
853*4882a593Smuzhiyun 	 * audio_src 2/3 is connected to acodec
854*4882a593Smuzhiyun 	 */
855*4882a593Smuzhiyun 	val = vad->audio_src >> AUDIO_SRC_SEL_SHIFT;
856*4882a593Smuzhiyun 	if (val == 2 || val == 3)
857*4882a593Smuzhiyun 		rockchip_vad_config_acodec(params, dai);
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun 	return 0;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun 
rockchip_vad_enable_cpudai(struct rockchip_vad * vad)862*4882a593Smuzhiyun static int rockchip_vad_enable_cpudai(struct rockchip_vad *vad)
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun 	struct snd_soc_dai *cpu_dai;
865*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
866*4882a593Smuzhiyun 	int ret = 0;
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	cpu_dai = vad->cpu_dai;
869*4882a593Smuzhiyun 	substream = vad->substream;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	if (!cpu_dai || !substream)
872*4882a593Smuzhiyun 		return 0;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	pm_runtime_get_sync(cpu_dai->dev);
875*4882a593Smuzhiyun 	if (cpu_dai->driver->ops) {
876*4882a593Smuzhiyun 		if (cpu_dai->driver->ops->startup)
877*4882a593Smuzhiyun 			ret = cpu_dai->driver->ops->startup(substream,
878*4882a593Smuzhiyun 							    cpu_dai);
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 		if (cpu_dai->driver->ops->prepare)
881*4882a593Smuzhiyun 			ret |= cpu_dai->driver->ops->prepare(substream,
882*4882a593Smuzhiyun 							    cpu_dai);
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 		if (cpu_dai->driver->ops->trigger)
885*4882a593Smuzhiyun 			ret |= cpu_dai->driver->ops->trigger(substream,
886*4882a593Smuzhiyun 							    SNDRV_PCM_TRIGGER_START,
887*4882a593Smuzhiyun 							    cpu_dai);
888*4882a593Smuzhiyun 	}
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	return ret;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun 
rockchip_vad_disable_cpudai(struct rockchip_vad * vad)893*4882a593Smuzhiyun static int rockchip_vad_disable_cpudai(struct rockchip_vad *vad)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun 	struct snd_soc_dai *cpu_dai;
896*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
897*4882a593Smuzhiyun 	int ret = 0;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	cpu_dai = vad->cpu_dai;
900*4882a593Smuzhiyun 	substream = vad->substream;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	if (!cpu_dai || !substream)
903*4882a593Smuzhiyun 		return 0;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	pm_runtime_get_sync(cpu_dai->dev);
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun 	if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger)
908*4882a593Smuzhiyun 		ret = cpu_dai->driver->ops->trigger(substream,
909*4882a593Smuzhiyun 						    SNDRV_PCM_TRIGGER_STOP,
910*4882a593Smuzhiyun 						    cpu_dai);
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	pm_runtime_put(cpu_dai->dev);
913*4882a593Smuzhiyun 	return ret;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun 
rockchip_vad_pcm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)916*4882a593Smuzhiyun static int rockchip_vad_pcm_startup(struct snd_pcm_substream *substream,
917*4882a593Smuzhiyun 				    struct snd_soc_dai *dai)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
920*4882a593Smuzhiyun 		return 0;
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	vad_substream = substream;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	return 0;
925*4882a593Smuzhiyun }
926*4882a593Smuzhiyun 
rockchip_vad_pcm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)927*4882a593Smuzhiyun static void rockchip_vad_pcm_shutdown(struct snd_pcm_substream *substream,
928*4882a593Smuzhiyun 				      struct snd_soc_dai *dai)
929*4882a593Smuzhiyun {
930*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
931*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
934*4882a593Smuzhiyun 		return;
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun 	if (vad->vswitch) {
937*4882a593Smuzhiyun 		rockchip_vad_enable_cpudai(vad);
938*4882a593Smuzhiyun 		rockchip_vad_setup(vad);
939*4882a593Smuzhiyun 	}
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	vad_substream = NULL;
942*4882a593Smuzhiyun }
943*4882a593Smuzhiyun 
rockchip_vad_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)944*4882a593Smuzhiyun static int rockchip_vad_trigger(struct snd_pcm_substream *substream, int cmd,
945*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
946*4882a593Smuzhiyun {
947*4882a593Smuzhiyun 	struct snd_soc_component *component = dai->component;
948*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	switch (cmd) {
951*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_START:
952*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_RESUME:
953*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
954*4882a593Smuzhiyun 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
955*4882a593Smuzhiyun 			return 0;
956*4882a593Smuzhiyun 		rockchip_vad_stop(vad);
957*4882a593Smuzhiyun 		break;
958*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_STOP:
959*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_SUSPEND:
960*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
961*4882a593Smuzhiyun 		break;
962*4882a593Smuzhiyun 	default:
963*4882a593Smuzhiyun 		break;
964*4882a593Smuzhiyun 	}
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	return 0;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun static struct snd_soc_dai_ops rockchip_vad_dai_ops = {
970*4882a593Smuzhiyun 	.hw_params = rockchip_vad_hw_params,
971*4882a593Smuzhiyun 	.shutdown = rockchip_vad_pcm_shutdown,
972*4882a593Smuzhiyun 	.startup = rockchip_vad_pcm_startup,
973*4882a593Smuzhiyun 	.trigger = rockchip_vad_trigger,
974*4882a593Smuzhiyun };
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun static struct snd_soc_dai_driver vad_dai = {
977*4882a593Smuzhiyun 	.name = "vad",
978*4882a593Smuzhiyun 	.playback = {
979*4882a593Smuzhiyun 		.stream_name = "Playback",
980*4882a593Smuzhiyun 		.channels_min = 1,
981*4882a593Smuzhiyun 		.channels_max = 8,
982*4882a593Smuzhiyun 		.rates = VAD_RATES,
983*4882a593Smuzhiyun 		.formats = VAD_FORMATS,
984*4882a593Smuzhiyun 	},
985*4882a593Smuzhiyun 	.capture = {
986*4882a593Smuzhiyun 		 .stream_name = "Capture",
987*4882a593Smuzhiyun 		.channels_min = 1,
988*4882a593Smuzhiyun 		.channels_max = 8,
989*4882a593Smuzhiyun 		.rates = VAD_RATES,
990*4882a593Smuzhiyun 		.formats = VAD_FORMATS,
991*4882a593Smuzhiyun 	},
992*4882a593Smuzhiyun 	.ops = &rockchip_vad_dai_ops,
993*4882a593Smuzhiyun };
994*4882a593Smuzhiyun 
rockchip_vad_switch_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)995*4882a593Smuzhiyun static int rockchip_vad_switch_info(struct snd_kcontrol *kcontrol,
996*4882a593Smuzhiyun 				    struct snd_ctl_elem_info *uinfo)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
999*4882a593Smuzhiyun 	uinfo->count = 1;
1000*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
1001*4882a593Smuzhiyun 	uinfo->value.integer.max = 1;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 	return 0;
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun 
rockchip_vad_switch_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1006*4882a593Smuzhiyun static int rockchip_vad_switch_get(struct snd_kcontrol *kcontrol,
1007*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
1010*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = vad->vswitch;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	return 0;
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun 
rockchip_vad_switch_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1017*4882a593Smuzhiyun static int rockchip_vad_switch_put(struct snd_kcontrol *kcontrol,
1018*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
1019*4882a593Smuzhiyun {
1020*4882a593Smuzhiyun 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
1021*4882a593Smuzhiyun 	struct rockchip_vad *vad = snd_soc_component_get_drvdata(component);
1022*4882a593Smuzhiyun 	int val;
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun 	val = ucontrol->value.integer.value[0];
1025*4882a593Smuzhiyun 	if (val && !vad->vswitch) {
1026*4882a593Smuzhiyun 		vad->vswitch = true;
1027*4882a593Smuzhiyun 	} else if (!val && vad->vswitch) {
1028*4882a593Smuzhiyun 		vad->vswitch = false;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 		regmap_read(vad->regmap, VAD_CTRL, &val);
1031*4882a593Smuzhiyun 		if ((val & VAD_EN_MASK) == VAD_DISABLE)
1032*4882a593Smuzhiyun 			return 0;
1033*4882a593Smuzhiyun 		rockchip_vad_stop(vad);
1034*4882a593Smuzhiyun 		rockchip_vad_disable_cpudai(vad);
1035*4882a593Smuzhiyun 		/* this case we don't need vad data */
1036*4882a593Smuzhiyun 		vad->vbuf.size = 0;
1037*4882a593Smuzhiyun 	}
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	return 0;
1040*4882a593Smuzhiyun }
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun #define SOC_ROCKCHIP_VAD_SWITCH_DECL(xname) \
1043*4882a593Smuzhiyun {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1044*4882a593Smuzhiyun 	.info = rockchip_vad_switch_info, .get = rockchip_vad_switch_get, \
1045*4882a593Smuzhiyun 	.put = rockchip_vad_switch_put, }
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun static const struct snd_kcontrol_new rockchip_vad_dapm_controls[] = {
1048*4882a593Smuzhiyun 	SOC_ROCKCHIP_VAD_SWITCH_DECL("vad switch"),
1049*4882a593Smuzhiyun };
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun static const struct snd_soc_component_driver soc_vad_codec = {
1052*4882a593Smuzhiyun 	.controls = rockchip_vad_dapm_controls,
1053*4882a593Smuzhiyun 	.num_controls = ARRAY_SIZE(rockchip_vad_dapm_controls),
1054*4882a593Smuzhiyun };
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
1057*4882a593Smuzhiyun #include <linux/fs.h>
1058*4882a593Smuzhiyun #include <linux/debugfs.h>
1059*4882a593Smuzhiyun #include <linux/seq_file.h>
1060*4882a593Smuzhiyun 
rockchip_vad_debugfs_reg_show(struct seq_file * s,void * v)1061*4882a593Smuzhiyun static int rockchip_vad_debugfs_reg_show(struct seq_file *s, void *v)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun 	struct rockchip_vad *vad = s->private;
1064*4882a593Smuzhiyun 	unsigned int i;
1065*4882a593Smuzhiyun 	unsigned int val;
1066*4882a593Smuzhiyun 	unsigned int max_register;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	if (vad->version == VAD_RK1808 ||
1069*4882a593Smuzhiyun 	    vad->version == VAD_RK1808ES)
1070*4882a593Smuzhiyun 		max_register = VAD_NOISE_DATA;
1071*4882a593Smuzhiyun 	else
1072*4882a593Smuzhiyun 		max_register = VAD_INT;
1073*4882a593Smuzhiyun 	for (i = VAD_CTRL; i <= max_register; i += 4) {
1074*4882a593Smuzhiyun 		regmap_read(vad->regmap, i, &val);
1075*4882a593Smuzhiyun 		if (!(i % 16))
1076*4882a593Smuzhiyun 			seq_printf(s, "\n%08x:  ", i);
1077*4882a593Smuzhiyun 		seq_printf(s, "%08x ", val);
1078*4882a593Smuzhiyun 	}
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun 	return 0;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun 
rockchip_vad_debugfs_reg_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)1083*4882a593Smuzhiyun static ssize_t rockchip_vad_debugfs_reg_write(struct file *file,
1084*4882a593Smuzhiyun 					      const char __user *buf,
1085*4882a593Smuzhiyun 					      size_t count, loff_t *ppos)
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun 	struct rockchip_vad *vad = ((struct seq_file *)file->private_data)->private;
1088*4882a593Smuzhiyun 	unsigned int reg, val;
1089*4882a593Smuzhiyun 	char kbuf[24];
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun 	if (count >= sizeof(kbuf))
1092*4882a593Smuzhiyun 		return -EINVAL;
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun 	if (copy_from_user(kbuf, buf, count))
1095*4882a593Smuzhiyun 		return -EFAULT;
1096*4882a593Smuzhiyun 	kbuf[count] = '\0';
1097*4882a593Smuzhiyun 	if (sscanf(kbuf, "%x %x", &reg, &val) != 2)
1098*4882a593Smuzhiyun 		return -EFAULT;
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	regmap_write(vad->regmap, reg, val);
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun 	return count;
1103*4882a593Smuzhiyun }
1104*4882a593Smuzhiyun 
rockchip_vad_debugfs_open(struct inode * inode,struct file * file)1105*4882a593Smuzhiyun static int rockchip_vad_debugfs_open(struct inode *inode, struct file *file)
1106*4882a593Smuzhiyun {
1107*4882a593Smuzhiyun 	return single_open(file, rockchip_vad_debugfs_reg_show, inode->i_private);
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun static const struct file_operations rockchip_vad_reg_debugfs_fops = {
1111*4882a593Smuzhiyun 	.owner = THIS_MODULE,
1112*4882a593Smuzhiyun 	.open = rockchip_vad_debugfs_open,
1113*4882a593Smuzhiyun 	.read = seq_read,
1114*4882a593Smuzhiyun 	.write = rockchip_vad_debugfs_reg_write,
1115*4882a593Smuzhiyun 	.llseek = seq_lseek,
1116*4882a593Smuzhiyun 	.release = single_release,
1117*4882a593Smuzhiyun };
1118*4882a593Smuzhiyun #endif
1119*4882a593Smuzhiyun 
rockchip_vad_init(struct rockchip_vad * vad)1120*4882a593Smuzhiyun static void rockchip_vad_init(struct rockchip_vad *vad)
1121*4882a593Smuzhiyun {
1122*4882a593Smuzhiyun 	unsigned int val, mask;
1123*4882a593Smuzhiyun 
1124*4882a593Smuzhiyun 	regmap_write(vad->regmap, VAD_RAM_BEGIN_ADDR, vad->memphy);
1125*4882a593Smuzhiyun 	regmap_write(vad->regmap, VAD_RAM_END_ADDR, vad->memphy_end);
1126*4882a593Smuzhiyun 	vad->vbuf.begin = vad->membase;
1127*4882a593Smuzhiyun 	regmap_write(vad->regmap, VAD_IS_ADDR, vad->audio_src_addr);
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun 	val = VAD_DET_CHNL(vad->audio_chnl);
1130*4882a593Smuzhiyun 	val |= vad->audio_src;
1131*4882a593Smuzhiyun 	val |= vad->mode << VAD_MODE_SHIFT;
1132*4882a593Smuzhiyun 	mask = VAD_DET_CHNL_MASK | AUDIO_SRC_SEL_MASK |
1133*4882a593Smuzhiyun 	       VAD_MODE_MASK;
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun 	regmap_update_bits(vad->regmap, VAD_CTRL, mask, val);
1136*4882a593Smuzhiyun 	if (vad->version == VAD_RK1808 ||
1137*4882a593Smuzhiyun 	    vad->version == VAD_RK1808ES) {
1138*4882a593Smuzhiyun 		regmap_update_bits(vad->regmap, VAD_AUX_CONTROL,
1139*4882a593Smuzhiyun 				   RAM_ITF_EN_MASK | BUS_WRITE_EN_MASK,
1140*4882a593Smuzhiyun 				   RAM_ITF_DIS | BUS_WRITE_EN);
1141*4882a593Smuzhiyun 		regmap_update_bits(vad->regmap, VAD_AUX_CONTROL,
1142*4882a593Smuzhiyun 				   SAMPLE_CNT_EN_MASK, SAMPLE_CNT_EN);
1143*4882a593Smuzhiyun 	}
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun 
1146*4882a593Smuzhiyun static const struct of_device_id rockchip_vad_match[] = {
1147*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk1808es-vad", .data = &rk1808es_soc_data },
1148*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk1808-vad", .data = &rk1808_soc_data },
1149*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3308-vad", .data = &rk3308_soc_data },
1150*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3568-vad", .data = &rk3568_soc_data },
1151*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3588-vad", .data = &rk3588_soc_data },
1152*4882a593Smuzhiyun 	{},
1153*4882a593Smuzhiyun };
1154*4882a593Smuzhiyun 
rockchip_vad_probe(struct platform_device * pdev)1155*4882a593Smuzhiyun static int rockchip_vad_probe(struct platform_device *pdev)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun 	struct device_node *np = pdev->dev.of_node;
1158*4882a593Smuzhiyun 	struct device_node *asrc_np = NULL;
1159*4882a593Smuzhiyun 	struct device_node *sram_np = NULL;
1160*4882a593Smuzhiyun 	const struct of_device_id *match;
1161*4882a593Smuzhiyun 	const struct regmap_config *regmap_config;
1162*4882a593Smuzhiyun 	struct rockchip_vad *vad;
1163*4882a593Smuzhiyun 	struct resource *res;
1164*4882a593Smuzhiyun 	struct resource audio_res;
1165*4882a593Smuzhiyun 	struct resource sram_res;
1166*4882a593Smuzhiyun 	void __iomem *regbase;
1167*4882a593Smuzhiyun 	int irq;
1168*4882a593Smuzhiyun 	int ret;
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	vad = devm_kzalloc(&pdev->dev, sizeof(*vad), GFP_KERNEL);
1171*4882a593Smuzhiyun 	if (!vad)
1172*4882a593Smuzhiyun 		return -ENOMEM;
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	vad->dev = &pdev->dev;
1175*4882a593Smuzhiyun 
1176*4882a593Smuzhiyun 	match = of_match_device(rockchip_vad_match, &pdev->dev);
1177*4882a593Smuzhiyun 	if (!match || !match->data)
1178*4882a593Smuzhiyun 		return -EINVAL;
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	vad->soc_data = (struct vad_soc_data *)match->data;
1181*4882a593Smuzhiyun 	vad->version = vad->soc_data->version;
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 	switch (vad->version) {
1184*4882a593Smuzhiyun 	case VAD_RK1808:
1185*4882a593Smuzhiyun 	case VAD_RK1808ES:
1186*4882a593Smuzhiyun 		regmap_config = &rk1808_vad_regmap_config;
1187*4882a593Smuzhiyun 		break;
1188*4882a593Smuzhiyun 	case VAD_RK3308:
1189*4882a593Smuzhiyun 		regmap_config = &rk3308_vad_regmap_config;
1190*4882a593Smuzhiyun 		break;
1191*4882a593Smuzhiyun 	default:
1192*4882a593Smuzhiyun 		return -EINVAL;
1193*4882a593Smuzhiyun 	}
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	vad->acodec_cfg = of_property_read_bool(np, "rockchip,acodec-cfg");
1196*4882a593Smuzhiyun 	of_property_read_u32(np, "rockchip,mode", &vad->mode);
1197*4882a593Smuzhiyun 	of_property_read_u32(np, "rockchip,det-channel", &vad->audio_chnl);
1198*4882a593Smuzhiyun 	of_property_read_u32(np, "rockchip,buffer-time-ms", &vad->buffer_time);
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vad");
1201*4882a593Smuzhiyun 	regbase = devm_ioremap_resource(&pdev->dev, res);
1202*4882a593Smuzhiyun 	if (IS_ERR(regbase))
1203*4882a593Smuzhiyun 		return PTR_ERR(regbase);
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	sram_np = of_parse_phandle(np, "rockchip,audio-sram", 0);
1206*4882a593Smuzhiyun 	if (!sram_np) {
1207*4882a593Smuzhiyun 		dev_err(&pdev->dev, "could not find sram dt node\n");
1208*4882a593Smuzhiyun 		return -ENODEV;
1209*4882a593Smuzhiyun 	}
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun 	asrc_np = of_parse_phandle(np, "rockchip,audio-src", 0);
1212*4882a593Smuzhiyun 	if (!asrc_np) {
1213*4882a593Smuzhiyun 		ret = -ENODEV;
1214*4882a593Smuzhiyun 		goto err_phandle;
1215*4882a593Smuzhiyun 	}
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 	ret = of_address_to_resource(asrc_np, 0, &audio_res);
1218*4882a593Smuzhiyun 	if (ret)
1219*4882a593Smuzhiyun 		goto err_phandle;
1220*4882a593Smuzhiyun 	ret = rockchip_vad_get_audio_src_address(vad, audio_res.start);
1221*4882a593Smuzhiyun 	if (ret)
1222*4882a593Smuzhiyun 		goto err_phandle;
1223*4882a593Smuzhiyun 	vad->audio_node = asrc_np;
1224*4882a593Smuzhiyun 	vad->audio_src <<= AUDIO_SRC_SEL_SHIFT;
1225*4882a593Smuzhiyun 
1226*4882a593Smuzhiyun 	ret = of_address_to_resource(sram_np, 0, &sram_res);
1227*4882a593Smuzhiyun 	if (ret)
1228*4882a593Smuzhiyun 		goto err_phandle;
1229*4882a593Smuzhiyun 	vad->memphy = sram_res.start;
1230*4882a593Smuzhiyun 	vad->memphy_end = sram_res.start + resource_size(&sram_res) - 0x8;
1231*4882a593Smuzhiyun 	vad->membase = devm_ioremap(&pdev->dev, sram_res.start,
1232*4882a593Smuzhiyun 				    resource_size(&sram_res));
1233*4882a593Smuzhiyun 	if (!vad->membase) {
1234*4882a593Smuzhiyun 		ret = -ENOMEM;
1235*4882a593Smuzhiyun 		goto err_phandle;
1236*4882a593Smuzhiyun 	}
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun 	if (IS_ERR(vad->membase)) {
1239*4882a593Smuzhiyun 		ret = PTR_ERR(vad->membase);
1240*4882a593Smuzhiyun 		goto err_phandle;
1241*4882a593Smuzhiyun 	}
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun 	vad->hclk = devm_clk_get(&pdev->dev, "hclk");
1244*4882a593Smuzhiyun 	if (IS_ERR(vad->hclk)) {
1245*4882a593Smuzhiyun 		ret = PTR_ERR(vad->hclk);
1246*4882a593Smuzhiyun 		goto err_phandle;
1247*4882a593Smuzhiyun 	}
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun 	ret = clk_prepare_enable(vad->hclk);
1250*4882a593Smuzhiyun 	if (ret)
1251*4882a593Smuzhiyun 		goto err_phandle;
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	vad->regmap = devm_regmap_init_mmio(&pdev->dev, regbase,
1254*4882a593Smuzhiyun 					    regmap_config);
1255*4882a593Smuzhiyun 	if (IS_ERR(vad->regmap)) {
1256*4882a593Smuzhiyun 		ret = PTR_ERR(vad->regmap);
1257*4882a593Smuzhiyun 		goto err;
1258*4882a593Smuzhiyun 	}
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	rockchip_vad_init(vad);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	irq = platform_get_irq(pdev, 0);
1263*4882a593Smuzhiyun 	if (irq < 0) {
1264*4882a593Smuzhiyun 		ret = irq;
1265*4882a593Smuzhiyun 		goto err;
1266*4882a593Smuzhiyun 	}
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun 	ret = devm_request_irq(&pdev->dev, irq, rockchip_vad_irq,
1269*4882a593Smuzhiyun 			       0, dev_name(&pdev->dev), vad);
1270*4882a593Smuzhiyun 	if (ret < 0)
1271*4882a593Smuzhiyun 		goto err;
1272*4882a593Smuzhiyun 
1273*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
1274*4882a593Smuzhiyun 	vad->debugfs_dir = debugfs_create_dir("vad", NULL);
1275*4882a593Smuzhiyun 	if (IS_ERR(vad->debugfs_dir))
1276*4882a593Smuzhiyun 		dev_err(&pdev->dev, "failed to create debugfs dir for vad!\n");
1277*4882a593Smuzhiyun 	else
1278*4882a593Smuzhiyun 		debugfs_create_file("reg", 0644, vad->debugfs_dir, vad,
1279*4882a593Smuzhiyun 				    &rockchip_vad_reg_debugfs_fops);
1280*4882a593Smuzhiyun #endif
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun 	platform_set_drvdata(pdev, vad);
1283*4882a593Smuzhiyun 	ret = snd_soc_register_component(&pdev->dev, &soc_vad_codec,
1284*4882a593Smuzhiyun 					 &vad_dai, 1);
1285*4882a593Smuzhiyun 	if (ret)
1286*4882a593Smuzhiyun 		goto err;
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun 	of_node_put(sram_np);
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun 	return 0;
1291*4882a593Smuzhiyun err:
1292*4882a593Smuzhiyun 	clk_disable_unprepare(vad->hclk);
1293*4882a593Smuzhiyun err_phandle:
1294*4882a593Smuzhiyun 	of_node_put(sram_np);
1295*4882a593Smuzhiyun 	of_node_put(asrc_np);
1296*4882a593Smuzhiyun 	return ret;
1297*4882a593Smuzhiyun }
1298*4882a593Smuzhiyun 
rockchip_vad_remove(struct platform_device * pdev)1299*4882a593Smuzhiyun static int rockchip_vad_remove(struct platform_device *pdev)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun 	struct rockchip_vad *vad = dev_get_drvdata(&pdev->dev);
1302*4882a593Smuzhiyun 
1303*4882a593Smuzhiyun 	if (!IS_ERR(vad->hclk))
1304*4882a593Smuzhiyun 		clk_disable_unprepare(vad->hclk);
1305*4882a593Smuzhiyun 	of_node_put(vad->audio_node);
1306*4882a593Smuzhiyun 	snd_soc_unregister_component(&pdev->dev);
1307*4882a593Smuzhiyun 	return 0;
1308*4882a593Smuzhiyun }
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun static struct platform_driver rockchip_vad_driver = {
1311*4882a593Smuzhiyun 	.probe = rockchip_vad_probe,
1312*4882a593Smuzhiyun 	.remove = rockchip_vad_remove,
1313*4882a593Smuzhiyun 	.driver = {
1314*4882a593Smuzhiyun 		.name = DRV_NAME,
1315*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rockchip_vad_match),
1316*4882a593Smuzhiyun 	},
1317*4882a593Smuzhiyun };
1318*4882a593Smuzhiyun module_platform_driver(rockchip_vad_driver);
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip VAD Controller");
1321*4882a593Smuzhiyun MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
1322*4882a593Smuzhiyun MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
1323*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1324*4882a593Smuzhiyun MODULE_ALIAS("platform:" DRV_NAME);
1325*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_vad_match);
1326