xref: /OK3568_Linux_fs/kernel/sound/soc/rockchip/rockchip_pdm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Rockchip PDM ALSA SoC Digital Audio Interface(DAI)  driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/clk/rockchip.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/of_device.h>
13*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
14*4882a593Smuzhiyun #include <linux/pm_runtime.h>
15*4882a593Smuzhiyun #include <linux/rational.h>
16*4882a593Smuzhiyun #include <linux/regmap.h>
17*4882a593Smuzhiyun #include <linux/reset.h>
18*4882a593Smuzhiyun #include <sound/dmaengine_pcm.h>
19*4882a593Smuzhiyun #include <sound/pcm_params.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include "rockchip_pdm.h"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define PDM_DMA_BURST_SIZE		(8) /* size * width: 8*4 = 32 bytes */
24*4882a593Smuzhiyun #define PDM_SIGNOFF_CLK_100M		(100000000)
25*4882a593Smuzhiyun #define PDM_SIGNOFF_CLK_300M		(300000000)
26*4882a593Smuzhiyun #define PDM_PATH_MAX			(4)
27*4882a593Smuzhiyun #define PDM_DEFAULT_RATE		(48000)
28*4882a593Smuzhiyun #define PDM_START_DELAY_MS_DEFAULT	(20)
29*4882a593Smuzhiyun #define PDM_START_DELAY_MS_MIN		(0)
30*4882a593Smuzhiyun #define PDM_START_DELAY_MS_MAX		(1000)
31*4882a593Smuzhiyun #define PDM_FILTER_DELAY_MS_MIN		(20)
32*4882a593Smuzhiyun #define PDM_FILTER_DELAY_MS_MAX		(1000)
33*4882a593Smuzhiyun #define PDM_CLK_SHIFT_PPM_MAX		(1000000) /* 1 ppm */
34*4882a593Smuzhiyun #define CLK_PPM_MIN		(-1000)
35*4882a593Smuzhiyun #define CLK_PPM_MAX		(1000)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun enum rk_pdm_version {
38*4882a593Smuzhiyun 	RK_PDM_RK3229,
39*4882a593Smuzhiyun 	RK_PDM_RK3308,
40*4882a593Smuzhiyun 	RK_PDM_RK3588,
41*4882a593Smuzhiyun 	RK_PDM_RV1126,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun struct rk_pdm_dev {
45*4882a593Smuzhiyun 	struct device *dev;
46*4882a593Smuzhiyun 	struct clk *clk;
47*4882a593Smuzhiyun 	struct clk *clk_root;
48*4882a593Smuzhiyun 	struct clk *hclk;
49*4882a593Smuzhiyun 	struct regmap *regmap;
50*4882a593Smuzhiyun 	struct snd_dmaengine_dai_dma_data capture_dma_data;
51*4882a593Smuzhiyun 	struct reset_control *reset;
52*4882a593Smuzhiyun 	struct pinctrl *pinctrl;
53*4882a593Smuzhiyun 	struct pinctrl_state *clk_state;
54*4882a593Smuzhiyun 	unsigned int start_delay_ms;
55*4882a593Smuzhiyun 	unsigned int filter_delay_ms;
56*4882a593Smuzhiyun 	enum rk_pdm_version version;
57*4882a593Smuzhiyun 	unsigned int clk_root_rate;
58*4882a593Smuzhiyun 	unsigned int clk_root_initial_rate;
59*4882a593Smuzhiyun 	int clk_ppm;
60*4882a593Smuzhiyun 	bool clk_calibrate;
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun struct rk_pdm_clkref {
64*4882a593Smuzhiyun 	unsigned int sr;
65*4882a593Smuzhiyun 	unsigned int clk;
66*4882a593Smuzhiyun 	unsigned int clk_out;
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun struct rk_pdm_ds_ratio {
70*4882a593Smuzhiyun 	unsigned int ratio;
71*4882a593Smuzhiyun 	unsigned int sr;
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static struct rk_pdm_clkref clkref[] = {
75*4882a593Smuzhiyun 	{ 8000, 40960000, 2048000 },
76*4882a593Smuzhiyun 	{ 11025, 56448000, 2822400 },
77*4882a593Smuzhiyun 	{ 12000, 61440000, 3072000 },
78*4882a593Smuzhiyun 	{ 8000, 98304000, 2048000 },
79*4882a593Smuzhiyun 	{ 12000, 98304000, 3072000 },
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun static struct rk_pdm_ds_ratio ds_ratio[] = {
83*4882a593Smuzhiyun 	{ 0, 192000 },
84*4882a593Smuzhiyun 	{ 0, 176400 },
85*4882a593Smuzhiyun 	{ 0, 128000 },
86*4882a593Smuzhiyun 	{ 1, 96000 },
87*4882a593Smuzhiyun 	{ 1, 88200 },
88*4882a593Smuzhiyun 	{ 1, 64000 },
89*4882a593Smuzhiyun 	{ 2, 48000 },
90*4882a593Smuzhiyun 	{ 2, 44100 },
91*4882a593Smuzhiyun 	{ 2, 32000 },
92*4882a593Smuzhiyun 	{ 3, 24000 },
93*4882a593Smuzhiyun 	{ 3, 22050 },
94*4882a593Smuzhiyun 	{ 3, 16000 },
95*4882a593Smuzhiyun 	{ 4, 12000 },
96*4882a593Smuzhiyun 	{ 4, 11025 },
97*4882a593Smuzhiyun 	{ 4, 8000 },
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun 
get_pdm_clk(struct rk_pdm_dev * pdm,unsigned int sr,unsigned int * clk_src,unsigned int * clk_out,unsigned int signoff)100*4882a593Smuzhiyun static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
101*4882a593Smuzhiyun 				unsigned int *clk_src, unsigned int *clk_out,
102*4882a593Smuzhiyun 				unsigned int signoff)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	unsigned int i, count, clk, div, rate, delta;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	clk = 0;
107*4882a593Smuzhiyun 	if (!sr)
108*4882a593Smuzhiyun 		return clk;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	count = ARRAY_SIZE(clkref);
111*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
112*4882a593Smuzhiyun 		if (sr % clkref[i].sr)
113*4882a593Smuzhiyun 			continue;
114*4882a593Smuzhiyun 		div = sr / clkref[i].sr;
115*4882a593Smuzhiyun 		if ((div & (div - 1)) == 0) {
116*4882a593Smuzhiyun 			*clk_out = clkref[i].clk_out;
117*4882a593Smuzhiyun 			if (pdm->clk_calibrate) {
118*4882a593Smuzhiyun 				clk = clkref[i].clk;
119*4882a593Smuzhiyun 				*clk_src = clk;
120*4882a593Smuzhiyun 				break;
121*4882a593Smuzhiyun 			}
122*4882a593Smuzhiyun 			rate = clk_round_rate(pdm->clk, clkref[i].clk);
123*4882a593Smuzhiyun 			delta = clkref[i].clk / PDM_CLK_SHIFT_PPM_MAX;
124*4882a593Smuzhiyun 			if (rate < clkref[i].clk - delta ||
125*4882a593Smuzhiyun 			    rate > clkref[i].clk + delta)
126*4882a593Smuzhiyun 				continue;
127*4882a593Smuzhiyun 			clk = clkref[i].clk;
128*4882a593Smuzhiyun 			*clk_src = clkref[i].clk;
129*4882a593Smuzhiyun 			break;
130*4882a593Smuzhiyun 		}
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	if (!clk) {
134*4882a593Smuzhiyun 		clk = clk_round_rate(pdm->clk, signoff);
135*4882a593Smuzhiyun 		*clk_src = clk;
136*4882a593Smuzhiyun 	}
137*4882a593Smuzhiyun 	return clk;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
get_pdm_ds_ratio(unsigned int sr)140*4882a593Smuzhiyun static unsigned int get_pdm_ds_ratio(unsigned int sr)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun 	unsigned int i, count, ratio;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	ratio = 0;
145*4882a593Smuzhiyun 	if (!sr)
146*4882a593Smuzhiyun 		return ratio;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	count = ARRAY_SIZE(ds_ratio);
149*4882a593Smuzhiyun 	for (i = 0; i < count; i++) {
150*4882a593Smuzhiyun 		if (sr == ds_ratio[i].sr)
151*4882a593Smuzhiyun 			ratio = ds_ratio[i].ratio;
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 	return ratio;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
get_pdm_cic_ratio(unsigned int clk)156*4882a593Smuzhiyun static unsigned int get_pdm_cic_ratio(unsigned int clk)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	switch (clk) {
159*4882a593Smuzhiyun 	case 4096000:
160*4882a593Smuzhiyun 	case 5644800:
161*4882a593Smuzhiyun 	case 6144000:
162*4882a593Smuzhiyun 		return 0;
163*4882a593Smuzhiyun 	case 2048000:
164*4882a593Smuzhiyun 	case 2822400:
165*4882a593Smuzhiyun 	case 3072000:
166*4882a593Smuzhiyun 		return 1;
167*4882a593Smuzhiyun 	case 1024000:
168*4882a593Smuzhiyun 	case 1411200:
169*4882a593Smuzhiyun 	case 1536000:
170*4882a593Smuzhiyun 		return 2;
171*4882a593Smuzhiyun 	default:
172*4882a593Smuzhiyun 		return 1;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
samplerate_to_bit(unsigned int samplerate)176*4882a593Smuzhiyun static unsigned int samplerate_to_bit(unsigned int samplerate)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	switch (samplerate) {
179*4882a593Smuzhiyun 	case 8000:
180*4882a593Smuzhiyun 	case 11025:
181*4882a593Smuzhiyun 	case 12000:
182*4882a593Smuzhiyun 		return 0;
183*4882a593Smuzhiyun 	case 16000:
184*4882a593Smuzhiyun 	case 22050:
185*4882a593Smuzhiyun 	case 24000:
186*4882a593Smuzhiyun 		return 1;
187*4882a593Smuzhiyun 	case 32000:
188*4882a593Smuzhiyun 		return 2;
189*4882a593Smuzhiyun 	case 44100:
190*4882a593Smuzhiyun 	case 48000:
191*4882a593Smuzhiyun 		return 3;
192*4882a593Smuzhiyun 	case 64000:
193*4882a593Smuzhiyun 	case 88200:
194*4882a593Smuzhiyun 	case 96000:
195*4882a593Smuzhiyun 		return 4;
196*4882a593Smuzhiyun 	case 128000:
197*4882a593Smuzhiyun 	case 176400:
198*4882a593Smuzhiyun 	case 192000:
199*4882a593Smuzhiyun 		return 5;
200*4882a593Smuzhiyun 	default:
201*4882a593Smuzhiyun 		return 1;
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
to_info(struct snd_soc_dai * dai)205*4882a593Smuzhiyun static inline struct rk_pdm_dev *to_info(struct snd_soc_dai *dai)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	return snd_soc_dai_get_drvdata(dai);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
rockchip_pdm_rxctrl(struct rk_pdm_dev * pdm,int on)210*4882a593Smuzhiyun static void rockchip_pdm_rxctrl(struct rk_pdm_dev *pdm, int on)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	unsigned long flags;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	if (on) {
215*4882a593Smuzhiyun 		/* The PDM device need to delete some unused data
216*4882a593Smuzhiyun 		 * since the pdm of various manufacturers can not
217*4882a593Smuzhiyun 		 * be stable quickly. This is done by commit "ASoC:
218*4882a593Smuzhiyun 		 * rockchip: pdm: Fix pop noise in the beginning".
219*4882a593Smuzhiyun 		 *
220*4882a593Smuzhiyun 		 * But we do not know how many data we delete, this
221*4882a593Smuzhiyun 		 * cause channel disorder. For example, we record
222*4882a593Smuzhiyun 		 * two channel 24-bit sound, then delete some starting
223*4882a593Smuzhiyun 		 * data. Because the deleted starting data is uncertain,
224*4882a593Smuzhiyun 		 * the next data may be left or right channel and cause
225*4882a593Smuzhiyun 		 * channel disorder.
226*4882a593Smuzhiyun 		 *
227*4882a593Smuzhiyun 		 * Luckily, we can use the PDM_RX_CLR to fix this.
228*4882a593Smuzhiyun 		 * Use the PDM_RX_CLR to clear fifo written data and
229*4882a593Smuzhiyun 		 * address, but can not clear the read data and address.
230*4882a593Smuzhiyun 		 * In initial state, the read data and address are zero.
231*4882a593Smuzhiyun 		 */
232*4882a593Smuzhiyun 		local_irq_save(flags);
233*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
234*4882a593Smuzhiyun 				   PDM_RX_CLR_MASK,
235*4882a593Smuzhiyun 				   PDM_RX_CLR_WR);
236*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
237*4882a593Smuzhiyun 				   PDM_DMA_RD_MSK, PDM_DMA_RD_EN);
238*4882a593Smuzhiyun 		local_irq_restore(flags);
239*4882a593Smuzhiyun 	} else {
240*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_DMA_CTRL,
241*4882a593Smuzhiyun 				   PDM_DMA_RD_MSK, PDM_DMA_RD_DIS);
242*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_SYSCONFIG,
243*4882a593Smuzhiyun 				   PDM_RX_MASK | PDM_RX_CLR_MASK,
244*4882a593Smuzhiyun 				   PDM_RX_STOP | PDM_RX_CLR_WR);
245*4882a593Smuzhiyun 	}
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun 
rockchip_pdm_clk_set_rate(struct rk_pdm_dev * pdm,struct clk * clk,unsigned long rate,int ppm)248*4882a593Smuzhiyun static int rockchip_pdm_clk_set_rate(struct rk_pdm_dev *pdm,
249*4882a593Smuzhiyun 				     struct clk *clk, unsigned long rate,
250*4882a593Smuzhiyun 				     int ppm)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	unsigned long rate_target;
253*4882a593Smuzhiyun 	int delta, ret;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (ppm == pdm->clk_ppm)
256*4882a593Smuzhiyun 		return 0;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	ret = rockchip_pll_clk_compensation(clk, ppm);
259*4882a593Smuzhiyun 	if (ret != -ENOSYS)
260*4882a593Smuzhiyun 		goto out;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	delta = (ppm < 0) ? -1 : 1;
263*4882a593Smuzhiyun 	delta *= (int)div64_u64((uint64_t)rate * (uint64_t)abs(ppm) + 500000, 1000000);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	rate_target = rate + delta;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	if (!rate_target)
268*4882a593Smuzhiyun 		return -EINVAL;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	ret = clk_set_rate(clk, rate_target);
271*4882a593Smuzhiyun 	if (ret)
272*4882a593Smuzhiyun 		return ret;
273*4882a593Smuzhiyun out:
274*4882a593Smuzhiyun 	if (!ret)
275*4882a593Smuzhiyun 		pdm->clk_ppm = ppm;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	return ret;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
rockchip_pdm_set_samplerate(struct rk_pdm_dev * pdm,unsigned int samplerate)280*4882a593Smuzhiyun static int rockchip_pdm_set_samplerate(struct rk_pdm_dev *pdm, unsigned int samplerate)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	unsigned int val = 0, div = 0;
284*4882a593Smuzhiyun 	unsigned int clk_rate, clk_div, rate, delta;
285*4882a593Smuzhiyun 	unsigned int clk_src = 0, clk_out = 0, signoff = PDM_SIGNOFF_CLK_100M;
286*4882a593Smuzhiyun 	unsigned long m, n;
287*4882a593Smuzhiyun 	uint64_t ppm;
288*4882a593Smuzhiyun 	bool change;
289*4882a593Smuzhiyun 	int ret;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	if (pdm->version == RK_PDM_RK3588)
292*4882a593Smuzhiyun 		signoff = PDM_SIGNOFF_CLK_300M;
293*4882a593Smuzhiyun 	clk_rate = get_pdm_clk(pdm, samplerate, &clk_src, &clk_out, signoff);
294*4882a593Smuzhiyun 	if (!clk_rate)
295*4882a593Smuzhiyun 		return -EINVAL;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (pdm->clk_calibrate) {
298*4882a593Smuzhiyun 		ret = clk_set_parent(pdm->clk, pdm->clk_root);
299*4882a593Smuzhiyun 		if (ret)
300*4882a593Smuzhiyun 			return ret;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		ret = rockchip_pdm_clk_set_rate(pdm, pdm->clk_root,
303*4882a593Smuzhiyun 						pdm->clk_root_rate, 0);
304*4882a593Smuzhiyun 		if (ret)
305*4882a593Smuzhiyun 			return ret;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 		rate = pdm->clk_root_rate;
308*4882a593Smuzhiyun 		delta = abs(rate % clk_src - clk_src);
309*4882a593Smuzhiyun 		ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)rate);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 		if (ppm) {
312*4882a593Smuzhiyun 			div = DIV_ROUND_CLOSEST(pdm->clk_root_initial_rate, clk_src);
313*4882a593Smuzhiyun 			if (!div)
314*4882a593Smuzhiyun 				return -EINVAL;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 			rate = clk_src * round_up(div, 2);
317*4882a593Smuzhiyun 			ret = clk_set_rate(pdm->clk_root, rate);
318*4882a593Smuzhiyun 			if (ret)
319*4882a593Smuzhiyun 				return ret;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 			pdm->clk_root_rate = clk_get_rate(pdm->clk_root);
322*4882a593Smuzhiyun 		}
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	ret = clk_set_rate(pdm->clk, clk_src);
326*4882a593Smuzhiyun 	if (ret)
327*4882a593Smuzhiyun 		return ret;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	if (pdm->version == RK_PDM_RK3308 ||
330*4882a593Smuzhiyun 	    pdm->version == RK_PDM_RK3588 ||
331*4882a593Smuzhiyun 	    pdm->version == RK_PDM_RV1126) {
332*4882a593Smuzhiyun 		rational_best_approximation(clk_out, clk_src,
333*4882a593Smuzhiyun 					    GENMASK(16 - 1, 0),
334*4882a593Smuzhiyun 					    GENMASK(16 - 1, 0),
335*4882a593Smuzhiyun 					    &m, &n);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 		val = (m << PDM_FD_NUMERATOR_SFT) |
338*4882a593Smuzhiyun 			(n << PDM_FD_DENOMINATOR_SFT);
339*4882a593Smuzhiyun 		regmap_update_bits_check(pdm->regmap, PDM_CTRL1,
340*4882a593Smuzhiyun 					 PDM_FD_NUMERATOR_MSK |
341*4882a593Smuzhiyun 					 PDM_FD_DENOMINATOR_MSK,
342*4882a593Smuzhiyun 					 val, &change);
343*4882a593Smuzhiyun 		if (change) {
344*4882a593Smuzhiyun 			reset_control_assert(pdm->reset);
345*4882a593Smuzhiyun 			reset_control_deassert(pdm->reset);
346*4882a593Smuzhiyun 			rockchip_pdm_rxctrl(pdm, 0);
347*4882a593Smuzhiyun 		}
348*4882a593Smuzhiyun 		clk_div = n / m;
349*4882a593Smuzhiyun 		if (clk_div >= 40)
350*4882a593Smuzhiyun 			val = PDM_CLK_FD_RATIO_40;
351*4882a593Smuzhiyun 		else if (clk_div <= 35)
352*4882a593Smuzhiyun 			val = PDM_CLK_FD_RATIO_35;
353*4882a593Smuzhiyun 		else
354*4882a593Smuzhiyun 			return -EINVAL;
355*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_CLK_CTRL,
356*4882a593Smuzhiyun 				   PDM_CLK_FD_RATIO_MSK,
357*4882a593Smuzhiyun 				   val);
358*4882a593Smuzhiyun 	}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	if (pdm->version == RK_PDM_RK3588 || pdm->version == RK_PDM_RV1126) {
361*4882a593Smuzhiyun 		val = get_pdm_cic_ratio(clk_out);
362*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CIC_RATIO_MSK, val);
363*4882a593Smuzhiyun 		val = samplerate_to_bit(samplerate);
364*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_CTRL0,
365*4882a593Smuzhiyun 				   PDM_SAMPLERATE_MSK, PDM_SAMPLERATE(val));
366*4882a593Smuzhiyun 	} else {
367*4882a593Smuzhiyun 		val = get_pdm_ds_ratio(samplerate);
368*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_DS_RATIO_MSK, val);
369*4882a593Smuzhiyun 	}
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
372*4882a593Smuzhiyun 			   PDM_HPF_CF_MSK, PDM_HPF_60HZ);
373*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_HPF_CTRL,
374*4882a593Smuzhiyun 			   PDM_HPF_LE | PDM_HPF_RE, PDM_HPF_LE | PDM_HPF_RE);
375*4882a593Smuzhiyun 	return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
rockchip_pdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)378*4882a593Smuzhiyun static int rockchip_pdm_hw_params(struct snd_pcm_substream *substream,
379*4882a593Smuzhiyun 				  struct snd_pcm_hw_params *params,
380*4882a593Smuzhiyun 				  struct snd_soc_dai *dai)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
383*4882a593Smuzhiyun 	unsigned int val = 0;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
386*4882a593Smuzhiyun 		return 0;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	rockchip_pdm_set_samplerate(pdm, params_rate(params));
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	if (pdm->version != RK_PDM_RK3229)
391*4882a593Smuzhiyun 		regmap_update_bits(pdm->regmap, PDM_CTRL0,
392*4882a593Smuzhiyun 				   PDM_MODE_MSK, PDM_MODE_LJ);
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	val = 0;
395*4882a593Smuzhiyun 	switch (params_format(params)) {
396*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S8:
397*4882a593Smuzhiyun 		val |= PDM_VDW(8);
398*4882a593Smuzhiyun 		break;
399*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S16_LE:
400*4882a593Smuzhiyun 		val |= PDM_VDW(16);
401*4882a593Smuzhiyun 		break;
402*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S20_3LE:
403*4882a593Smuzhiyun 		val |= PDM_VDW(20);
404*4882a593Smuzhiyun 		break;
405*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S24_LE:
406*4882a593Smuzhiyun 		val |= PDM_VDW(24);
407*4882a593Smuzhiyun 		break;
408*4882a593Smuzhiyun 	case SNDRV_PCM_FORMAT_S32_LE:
409*4882a593Smuzhiyun 		val |= PDM_VDW(32);
410*4882a593Smuzhiyun 		break;
411*4882a593Smuzhiyun 	default:
412*4882a593Smuzhiyun 		return -EINVAL;
413*4882a593Smuzhiyun 	}
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	switch (params_channels(params)) {
416*4882a593Smuzhiyun 	case 8:
417*4882a593Smuzhiyun 		val |= PDM_PATH3_EN;
418*4882a593Smuzhiyun 		fallthrough;
419*4882a593Smuzhiyun 	case 6:
420*4882a593Smuzhiyun 		val |= PDM_PATH2_EN;
421*4882a593Smuzhiyun 		fallthrough;
422*4882a593Smuzhiyun 	case 4:
423*4882a593Smuzhiyun 		val |= PDM_PATH1_EN;
424*4882a593Smuzhiyun 		fallthrough;
425*4882a593Smuzhiyun 	case 2:
426*4882a593Smuzhiyun 		val |= PDM_PATH0_EN;
427*4882a593Smuzhiyun 		break;
428*4882a593Smuzhiyun 	default:
429*4882a593Smuzhiyun 		dev_err(pdm->dev, "invalid channel: %d\n",
430*4882a593Smuzhiyun 			params_channels(params));
431*4882a593Smuzhiyun 		return -EINVAL;
432*4882a593Smuzhiyun 	}
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_CTRL0,
435*4882a593Smuzhiyun 			   PDM_PATH_MSK | PDM_VDW_MSK,
436*4882a593Smuzhiyun 			   val);
437*4882a593Smuzhiyun 	/* all channels share the single FIFO */
438*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_DMA_CTRL, PDM_DMA_RDL_MSK,
439*4882a593Smuzhiyun 			   PDM_DMA_RDL(8 * params_channels(params)));
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun 
rockchip_pdm_set_fmt(struct snd_soc_dai * cpu_dai,unsigned int fmt)444*4882a593Smuzhiyun static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
445*4882a593Smuzhiyun 				unsigned int fmt)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(cpu_dai);
448*4882a593Smuzhiyun 	unsigned int mask = 0, val = 0;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	mask = PDM_CKP_MSK;
451*4882a593Smuzhiyun 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
452*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_NB_NF:
453*4882a593Smuzhiyun 		val = PDM_CKP_NORMAL;
454*4882a593Smuzhiyun 		break;
455*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_IB_NF:
456*4882a593Smuzhiyun 		val = PDM_CKP_INVERTED;
457*4882a593Smuzhiyun 		break;
458*4882a593Smuzhiyun 	default:
459*4882a593Smuzhiyun 		return -EINVAL;
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	pm_runtime_get_sync(cpu_dai->dev);
463*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
464*4882a593Smuzhiyun 	pm_runtime_put(cpu_dai->dev);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return 0;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
rockchip_pdm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)469*4882a593Smuzhiyun static int rockchip_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
470*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
473*4882a593Smuzhiyun 	int ret = 0;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	switch (cmd) {
476*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_START:
477*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_RESUME:
478*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
479*4882a593Smuzhiyun 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
480*4882a593Smuzhiyun 			rockchip_pdm_rxctrl(pdm, 1);
481*4882a593Smuzhiyun 		break;
482*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_SUSPEND:
483*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_STOP:
484*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
485*4882a593Smuzhiyun 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
486*4882a593Smuzhiyun 			rockchip_pdm_rxctrl(pdm, 0);
487*4882a593Smuzhiyun 		break;
488*4882a593Smuzhiyun 	default:
489*4882a593Smuzhiyun 		ret = -EINVAL;
490*4882a593Smuzhiyun 		break;
491*4882a593Smuzhiyun 	}
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	return ret;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
rockchip_pdm_start_delay_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)496*4882a593Smuzhiyun static int rockchip_pdm_start_delay_info(struct snd_kcontrol *kcontrol,
497*4882a593Smuzhiyun 					 struct snd_ctl_elem_info *uinfo)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
500*4882a593Smuzhiyun 	uinfo->count = 1;
501*4882a593Smuzhiyun 	uinfo->value.integer.min = PDM_START_DELAY_MS_MIN;
502*4882a593Smuzhiyun 	uinfo->value.integer.max = PDM_START_DELAY_MS_MAX;
503*4882a593Smuzhiyun 	uinfo->value.integer.step = 1;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	return 0;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
rockchip_pdm_start_delay_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)508*4882a593Smuzhiyun static int rockchip_pdm_start_delay_get(struct snd_kcontrol *kcontrol,
509*4882a593Smuzhiyun 					struct snd_ctl_elem_value *ucontrol)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
512*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = pdm->start_delay_ms;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	return 0;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun 
rockchip_pdm_start_delay_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)519*4882a593Smuzhiyun static int rockchip_pdm_start_delay_put(struct snd_kcontrol *kcontrol,
520*4882a593Smuzhiyun 					struct snd_ctl_elem_value *ucontrol)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
523*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	if ((ucontrol->value.integer.value[0] < PDM_START_DELAY_MS_MIN) ||
526*4882a593Smuzhiyun 	    (ucontrol->value.integer.value[0] > PDM_START_DELAY_MS_MAX))
527*4882a593Smuzhiyun 		return -EINVAL;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	pdm->start_delay_ms = ucontrol->value.integer.value[0];
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	return 1;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun 
rockchip_pdm_filter_delay_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)534*4882a593Smuzhiyun static int rockchip_pdm_filter_delay_info(struct snd_kcontrol *kcontrol,
535*4882a593Smuzhiyun 					  struct snd_ctl_elem_info *uinfo)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
538*4882a593Smuzhiyun 	uinfo->count = 1;
539*4882a593Smuzhiyun 	uinfo->value.integer.min = PDM_FILTER_DELAY_MS_MIN;
540*4882a593Smuzhiyun 	uinfo->value.integer.max = PDM_FILTER_DELAY_MS_MAX;
541*4882a593Smuzhiyun 	uinfo->value.integer.step = 1;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	return 0;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
rockchip_pdm_filter_delay_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)546*4882a593Smuzhiyun static int rockchip_pdm_filter_delay_get(struct snd_kcontrol *kcontrol,
547*4882a593Smuzhiyun 					 struct snd_ctl_elem_value *ucontrol)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
550*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = pdm->filter_delay_ms;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	return 0;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun 
rockchip_pdm_filter_delay_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)557*4882a593Smuzhiyun static int rockchip_pdm_filter_delay_put(struct snd_kcontrol *kcontrol,
558*4882a593Smuzhiyun 					 struct snd_ctl_elem_value *ucontrol)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
561*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	if ((ucontrol->value.integer.value[0] < PDM_FILTER_DELAY_MS_MIN) ||
564*4882a593Smuzhiyun 	    (ucontrol->value.integer.value[0] > PDM_FILTER_DELAY_MS_MAX))
565*4882a593Smuzhiyun 		return -EINVAL;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	pdm->filter_delay_ms = ucontrol->value.integer.value[0];
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	return 1;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun static const struct snd_kcontrol_new rockchip_pdm_controls[] = {
573*4882a593Smuzhiyun 	{
574*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
575*4882a593Smuzhiyun 		.name = "PDM Start Delay Ms",
576*4882a593Smuzhiyun 		.info = rockchip_pdm_start_delay_info,
577*4882a593Smuzhiyun 		.get = rockchip_pdm_start_delay_get,
578*4882a593Smuzhiyun 		.put = rockchip_pdm_start_delay_put,
579*4882a593Smuzhiyun 	},
580*4882a593Smuzhiyun 	{
581*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_PCM,
582*4882a593Smuzhiyun 		.name = "PDM Filter Delay Ms",
583*4882a593Smuzhiyun 		.info = rockchip_pdm_filter_delay_info,
584*4882a593Smuzhiyun 		.get = rockchip_pdm_filter_delay_get,
585*4882a593Smuzhiyun 		.put = rockchip_pdm_filter_delay_put,
586*4882a593Smuzhiyun 	},
587*4882a593Smuzhiyun };
588*4882a593Smuzhiyun 
rockchip_pdm_clk_compensation_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)589*4882a593Smuzhiyun static int rockchip_pdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
590*4882a593Smuzhiyun 					      struct snd_ctl_elem_info *uinfo)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
593*4882a593Smuzhiyun 	uinfo->count = 1;
594*4882a593Smuzhiyun 	uinfo->value.integer.min = CLK_PPM_MIN;
595*4882a593Smuzhiyun 	uinfo->value.integer.max = CLK_PPM_MAX;
596*4882a593Smuzhiyun 	uinfo->value.integer.step = 1;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 
rockchip_pdm_clk_compensation_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)602*4882a593Smuzhiyun static int rockchip_pdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
603*4882a593Smuzhiyun 					     struct snd_ctl_elem_value *ucontrol)
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
607*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = pdm->clk_ppm;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	return 0;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun 
rockchip_pdm_clk_compensation_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)614*4882a593Smuzhiyun static int rockchip_pdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
615*4882a593Smuzhiyun 					     struct snd_ctl_elem_value *ucontrol)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun 	struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
618*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = snd_soc_dai_get_drvdata(dai);
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	int ppm = ucontrol->value.integer.value[0];
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if ((ucontrol->value.integer.value[0] < CLK_PPM_MIN) ||
623*4882a593Smuzhiyun 	    (ucontrol->value.integer.value[0] > CLK_PPM_MAX))
624*4882a593Smuzhiyun 		return -EINVAL;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	return rockchip_pdm_clk_set_rate(pdm, pdm->clk_root, pdm->clk_root_rate, ppm);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun static struct snd_kcontrol_new rockchip_pdm_compensation_control = {
630*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
631*4882a593Smuzhiyun 	.name = "PDM PCM Clk Compensation In PPM",
632*4882a593Smuzhiyun 	.info = rockchip_pdm_clk_compensation_info,
633*4882a593Smuzhiyun 	.get = rockchip_pdm_clk_compensation_get,
634*4882a593Smuzhiyun 	.put = rockchip_pdm_clk_compensation_put,
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun };
637*4882a593Smuzhiyun 
rockchip_pdm_dai_probe(struct snd_soc_dai * dai)638*4882a593Smuzhiyun static int rockchip_pdm_dai_probe(struct snd_soc_dai *dai)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	dai->capture_dma_data = &pdm->capture_dma_data;
643*4882a593Smuzhiyun 	snd_soc_add_dai_controls(dai, rockchip_pdm_controls,
644*4882a593Smuzhiyun 				 ARRAY_SIZE(rockchip_pdm_controls));
645*4882a593Smuzhiyun 	if (pdm->clk_calibrate)
646*4882a593Smuzhiyun 		snd_soc_add_dai_controls(dai, &rockchip_pdm_compensation_control, 1);
647*4882a593Smuzhiyun 	return 0;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
rockchip_pdm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)650*4882a593Smuzhiyun static void rockchip_pdm_shutdown(struct snd_pcm_substream *substream,
651*4882a593Smuzhiyun 				  struct snd_soc_dai *dai)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
656*4882a593Smuzhiyun 		return;
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_MSK, PDM_CLK_DIS);
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun 
rockchip_pdm_prepare(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)661*4882a593Smuzhiyun static int rockchip_pdm_prepare(struct snd_pcm_substream *substream,
662*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
667*4882a593Smuzhiyun 		return 0;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_SYSCONFIG, PDM_RX_MASK, PDM_RX_START);
670*4882a593Smuzhiyun 	/*
671*4882a593Smuzhiyun 	 * after xfer start, a necessary delay for filter to init and will drop
672*4882a593Smuzhiyun 	 * the dirty data in the trigger-START late.
673*4882a593Smuzhiyun 	 */
674*4882a593Smuzhiyun 	usleep_range((pdm->filter_delay_ms) * 1000, (pdm->filter_delay_ms + 1) * 1000);
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 	return 0;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun 
rockchip_pdm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)679*4882a593Smuzhiyun static int rockchip_pdm_startup(struct snd_pcm_substream *substream,
680*4882a593Smuzhiyun 				struct snd_soc_dai *dai)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = to_info(dai);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
685*4882a593Smuzhiyun 		return 0;
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, PDM_CLK_MSK, PDM_CLK_EN);
688*4882a593Smuzhiyun 	/*
689*4882a593Smuzhiyun 	 * a necessary delay for dmics wake-up after clk enabled, and drop the
690*4882a593Smuzhiyun 	 * dirty data in this duration.
691*4882a593Smuzhiyun 	 */
692*4882a593Smuzhiyun 	usleep_range((pdm->start_delay_ms + 1) * 1000, (pdm->start_delay_ms + 2) * 1000);
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	return 0;
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun static const struct snd_soc_dai_ops rockchip_pdm_dai_ops = {
698*4882a593Smuzhiyun 	.startup = rockchip_pdm_startup,
699*4882a593Smuzhiyun 	.shutdown = rockchip_pdm_shutdown,
700*4882a593Smuzhiyun 	.set_fmt = rockchip_pdm_set_fmt,
701*4882a593Smuzhiyun 	.trigger = rockchip_pdm_trigger,
702*4882a593Smuzhiyun 	.prepare = rockchip_pdm_prepare,
703*4882a593Smuzhiyun 	.hw_params = rockchip_pdm_hw_params,
704*4882a593Smuzhiyun };
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun #define ROCKCHIP_PDM_RATES SNDRV_PCM_RATE_8000_192000
707*4882a593Smuzhiyun #define ROCKCHIP_PDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
708*4882a593Smuzhiyun 			      SNDRV_PCM_FMTBIT_S20_3LE | \
709*4882a593Smuzhiyun 			      SNDRV_PCM_FMTBIT_S24_LE | \
710*4882a593Smuzhiyun 			      SNDRV_PCM_FMTBIT_S32_LE)
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun static struct snd_soc_dai_driver rockchip_pdm_dai = {
713*4882a593Smuzhiyun 	.probe = rockchip_pdm_dai_probe,
714*4882a593Smuzhiyun 	.capture = {
715*4882a593Smuzhiyun 		.stream_name = "Capture",
716*4882a593Smuzhiyun 		.channels_min = 2,
717*4882a593Smuzhiyun 		.channels_max = 8,
718*4882a593Smuzhiyun 		.rates = ROCKCHIP_PDM_RATES,
719*4882a593Smuzhiyun 		.formats = ROCKCHIP_PDM_FORMATS,
720*4882a593Smuzhiyun 	},
721*4882a593Smuzhiyun 	.ops = &rockchip_pdm_dai_ops,
722*4882a593Smuzhiyun 	.symmetric_rates = 1,
723*4882a593Smuzhiyun };
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun static const struct snd_soc_component_driver rockchip_pdm_component = {
726*4882a593Smuzhiyun 	.name = "rockchip-pdm",
727*4882a593Smuzhiyun };
728*4882a593Smuzhiyun 
rockchip_pdm_pinctrl_select_clk_state(struct device * dev)729*4882a593Smuzhiyun static int rockchip_pdm_pinctrl_select_clk_state(struct device *dev)
730*4882a593Smuzhiyun {
731*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	if (IS_ERR_OR_NULL(pdm->pinctrl) || !pdm->clk_state)
734*4882a593Smuzhiyun 		return 0;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	/*
737*4882a593Smuzhiyun 	 * A necessary delay to make sure the correct
738*4882a593Smuzhiyun 	 * frac div has been applied when resume from
739*4882a593Smuzhiyun 	 * power down.
740*4882a593Smuzhiyun 	 */
741*4882a593Smuzhiyun 	udelay(10);
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	/*
744*4882a593Smuzhiyun 	 * Must disable the clk to avoid clk glitch
745*4882a593Smuzhiyun 	 * when pinctrl switch from gpio to pdm clk.
746*4882a593Smuzhiyun 	 */
747*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->clk);
748*4882a593Smuzhiyun 	pinctrl_select_state(pdm->pinctrl, pdm->clk_state);
749*4882a593Smuzhiyun 	clk_prepare_enable(pdm->clk);
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	return 0;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun 
rockchip_pdm_runtime_suspend(struct device * dev)754*4882a593Smuzhiyun static int rockchip_pdm_runtime_suspend(struct device *dev)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	regcache_cache_only(pdm->regmap, true);
759*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->clk);
760*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->hclk);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	pinctrl_pm_select_idle_state(dev);
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	return 0;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun 
rockchip_pdm_runtime_resume(struct device * dev)767*4882a593Smuzhiyun static int rockchip_pdm_runtime_resume(struct device *dev)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
770*4882a593Smuzhiyun 	int ret;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	ret = clk_prepare_enable(pdm->clk);
773*4882a593Smuzhiyun 	if (ret)
774*4882a593Smuzhiyun 		goto err_clk;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	ret = clk_prepare_enable(pdm->hclk);
777*4882a593Smuzhiyun 	if (ret)
778*4882a593Smuzhiyun 		goto err_hclk;
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	regcache_cache_only(pdm->regmap, false);
781*4882a593Smuzhiyun 	regcache_mark_dirty(pdm->regmap);
782*4882a593Smuzhiyun 	ret = regcache_sync(pdm->regmap);
783*4882a593Smuzhiyun 	if (ret)
784*4882a593Smuzhiyun 		goto err_regmap;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 	rockchip_pdm_rxctrl(pdm, 0);
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	rockchip_pdm_pinctrl_select_clk_state(dev);
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	return 0;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun err_regmap:
793*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->hclk);
794*4882a593Smuzhiyun err_hclk:
795*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->clk);
796*4882a593Smuzhiyun err_clk:
797*4882a593Smuzhiyun 	return ret;
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun 
rockchip_pdm_wr_reg(struct device * dev,unsigned int reg)800*4882a593Smuzhiyun static bool rockchip_pdm_wr_reg(struct device *dev, unsigned int reg)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun 	switch (reg) {
803*4882a593Smuzhiyun 	case PDM_SYSCONFIG:
804*4882a593Smuzhiyun 	case PDM_CTRL0:
805*4882a593Smuzhiyun 	case PDM_CTRL1:
806*4882a593Smuzhiyun 	case PDM_CLK_CTRL:
807*4882a593Smuzhiyun 	case PDM_HPF_CTRL:
808*4882a593Smuzhiyun 	case PDM_FIFO_CTRL:
809*4882a593Smuzhiyun 	case PDM_DMA_CTRL:
810*4882a593Smuzhiyun 	case PDM_INT_EN:
811*4882a593Smuzhiyun 	case PDM_INT_CLR:
812*4882a593Smuzhiyun 	case PDM_DATA_VALID:
813*4882a593Smuzhiyun 		return true;
814*4882a593Smuzhiyun 	default:
815*4882a593Smuzhiyun 		return false;
816*4882a593Smuzhiyun 	}
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun 
rockchip_pdm_rd_reg(struct device * dev,unsigned int reg)819*4882a593Smuzhiyun static bool rockchip_pdm_rd_reg(struct device *dev, unsigned int reg)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun 	switch (reg) {
822*4882a593Smuzhiyun 	case PDM_SYSCONFIG:
823*4882a593Smuzhiyun 	case PDM_CTRL0:
824*4882a593Smuzhiyun 	case PDM_CTRL1:
825*4882a593Smuzhiyun 	case PDM_CLK_CTRL:
826*4882a593Smuzhiyun 	case PDM_HPF_CTRL:
827*4882a593Smuzhiyun 	case PDM_FIFO_CTRL:
828*4882a593Smuzhiyun 	case PDM_DMA_CTRL:
829*4882a593Smuzhiyun 	case PDM_INT_EN:
830*4882a593Smuzhiyun 	case PDM_INT_CLR:
831*4882a593Smuzhiyun 	case PDM_INT_ST:
832*4882a593Smuzhiyun 	case PDM_DATA_VALID:
833*4882a593Smuzhiyun 	case PDM_RXFIFO_DATA:
834*4882a593Smuzhiyun 	case PDM_VERSION:
835*4882a593Smuzhiyun 		return true;
836*4882a593Smuzhiyun 	default:
837*4882a593Smuzhiyun 		return false;
838*4882a593Smuzhiyun 	}
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun 
rockchip_pdm_volatile_reg(struct device * dev,unsigned int reg)841*4882a593Smuzhiyun static bool rockchip_pdm_volatile_reg(struct device *dev, unsigned int reg)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun 	switch (reg) {
844*4882a593Smuzhiyun 	case PDM_SYSCONFIG:
845*4882a593Smuzhiyun 	case PDM_FIFO_CTRL:
846*4882a593Smuzhiyun 	case PDM_INT_CLR:
847*4882a593Smuzhiyun 	case PDM_INT_ST:
848*4882a593Smuzhiyun 	case PDM_RXFIFO_DATA:
849*4882a593Smuzhiyun 		return true;
850*4882a593Smuzhiyun 	default:
851*4882a593Smuzhiyun 		return false;
852*4882a593Smuzhiyun 	}
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun 
rockchip_pdm_precious_reg(struct device * dev,unsigned int reg)855*4882a593Smuzhiyun static bool rockchip_pdm_precious_reg(struct device *dev, unsigned int reg)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun 	switch (reg) {
858*4882a593Smuzhiyun 	case PDM_RXFIFO_DATA:
859*4882a593Smuzhiyun 		return true;
860*4882a593Smuzhiyun 	default:
861*4882a593Smuzhiyun 		return false;
862*4882a593Smuzhiyun 	}
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun static const struct reg_default rockchip_pdm_reg_defaults[] = {
866*4882a593Smuzhiyun 	{ PDM_CTRL0, 0x78000017 },
867*4882a593Smuzhiyun 	{ PDM_CTRL1, 0x0bb8ea60 },
868*4882a593Smuzhiyun 	{ PDM_CLK_CTRL, 0x0000e401 },
869*4882a593Smuzhiyun 	{ PDM_DMA_CTRL, 0x0000001f },
870*4882a593Smuzhiyun };
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun static const struct regmap_config rockchip_pdm_regmap_config = {
873*4882a593Smuzhiyun 	.reg_bits = 32,
874*4882a593Smuzhiyun 	.reg_stride = 4,
875*4882a593Smuzhiyun 	.val_bits = 32,
876*4882a593Smuzhiyun 	.max_register = PDM_VERSION,
877*4882a593Smuzhiyun 	.reg_defaults = rockchip_pdm_reg_defaults,
878*4882a593Smuzhiyun 	.num_reg_defaults = ARRAY_SIZE(rockchip_pdm_reg_defaults),
879*4882a593Smuzhiyun 	.writeable_reg = rockchip_pdm_wr_reg,
880*4882a593Smuzhiyun 	.readable_reg = rockchip_pdm_rd_reg,
881*4882a593Smuzhiyun 	.volatile_reg = rockchip_pdm_volatile_reg,
882*4882a593Smuzhiyun 	.precious_reg = rockchip_pdm_precious_reg,
883*4882a593Smuzhiyun 	.cache_type = REGCACHE_FLAT,
884*4882a593Smuzhiyun };
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun static const struct of_device_id rockchip_pdm_match[] __maybe_unused = {
887*4882a593Smuzhiyun 	{ .compatible = "rockchip,pdm",
888*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RK3229 },
889*4882a593Smuzhiyun 	{ .compatible = "rockchip,px30-pdm",
890*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RK3308 },
891*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk1808-pdm",
892*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RK3308 },
893*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3308-pdm",
894*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RK3308 },
895*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3568-pdm",
896*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RV1126 },
897*4882a593Smuzhiyun 	{ .compatible = "rockchip,rk3588-pdm",
898*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RK3588 },
899*4882a593Smuzhiyun 	{ .compatible = "rockchip,rv1126-pdm",
900*4882a593Smuzhiyun 	  .data = (void *)RK_PDM_RV1126 },
901*4882a593Smuzhiyun 	{},
902*4882a593Smuzhiyun };
903*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rockchip_pdm_match);
904*4882a593Smuzhiyun 
rockchip_pdm_path_parse(struct rk_pdm_dev * pdm,struct device_node * node)905*4882a593Smuzhiyun static int rockchip_pdm_path_parse(struct rk_pdm_dev *pdm, struct device_node *node)
906*4882a593Smuzhiyun {
907*4882a593Smuzhiyun 	unsigned int path[PDM_PATH_MAX];
908*4882a593Smuzhiyun 	int cnt = 0, ret = 0, i = 0, val = 0, msk = 0;
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	cnt = of_count_phandle_with_args(node, "rockchip,path-map",
911*4882a593Smuzhiyun 					 NULL);
912*4882a593Smuzhiyun 	if (cnt != PDM_PATH_MAX)
913*4882a593Smuzhiyun 		return cnt;
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	ret = of_property_read_u32_array(node, "rockchip,path-map",
916*4882a593Smuzhiyun 					 path, cnt);
917*4882a593Smuzhiyun 	if (ret)
918*4882a593Smuzhiyun 		return ret;
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	for (i = 0; i < cnt; i++) {
921*4882a593Smuzhiyun 		if (path[i] >= PDM_PATH_MAX)
922*4882a593Smuzhiyun 			return -EINVAL;
923*4882a593Smuzhiyun 		msk |= PDM_PATH_MASK(i);
924*4882a593Smuzhiyun 		val |= PDM_PATH(i, path[i]);
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun 	regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, msk, val);
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun 	return 0;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun 
rockchip_pdm_probe(struct platform_device * pdev)932*4882a593Smuzhiyun static int rockchip_pdm_probe(struct platform_device *pdev)
933*4882a593Smuzhiyun {
934*4882a593Smuzhiyun 	struct device_node *node = pdev->dev.of_node;
935*4882a593Smuzhiyun 	const struct of_device_id *match;
936*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm;
937*4882a593Smuzhiyun 	struct resource *res;
938*4882a593Smuzhiyun 	void __iomem *regs;
939*4882a593Smuzhiyun 	int ret;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	pdm = devm_kzalloc(&pdev->dev, sizeof(*pdm), GFP_KERNEL);
942*4882a593Smuzhiyun 	if (!pdm)
943*4882a593Smuzhiyun 		return -ENOMEM;
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	match = of_match_device(rockchip_pdm_match, &pdev->dev);
946*4882a593Smuzhiyun 	if (match)
947*4882a593Smuzhiyun 		pdm->version = (enum rk_pdm_version)match->data;
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	if (pdm->version == RK_PDM_RK3308) {
950*4882a593Smuzhiyun 		pdm->reset = devm_reset_control_get(&pdev->dev, "pdm-m");
951*4882a593Smuzhiyun 		if (IS_ERR(pdm->reset))
952*4882a593Smuzhiyun 			return PTR_ERR(pdm->reset);
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 	regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
956*4882a593Smuzhiyun 	if (IS_ERR(regs))
957*4882a593Smuzhiyun 		return PTR_ERR(regs);
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun 	pdm->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
960*4882a593Smuzhiyun 					    &rockchip_pdm_regmap_config);
961*4882a593Smuzhiyun 	if (IS_ERR(pdm->regmap))
962*4882a593Smuzhiyun 		return PTR_ERR(pdm->regmap);
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 	pdm->capture_dma_data.addr = res->start + PDM_RXFIFO_DATA;
965*4882a593Smuzhiyun 	pdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
966*4882a593Smuzhiyun 	pdm->capture_dma_data.maxburst = PDM_DMA_BURST_SIZE;
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	pdm->dev = &pdev->dev;
969*4882a593Smuzhiyun 	dev_set_drvdata(&pdev->dev, pdm);
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	pdm->pinctrl = devm_pinctrl_get(&pdev->dev);
972*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(pdm->pinctrl)) {
973*4882a593Smuzhiyun 		pdm->clk_state = pinctrl_lookup_state(pdm->pinctrl, "clk");
974*4882a593Smuzhiyun 		if (IS_ERR(pdm->clk_state)) {
975*4882a593Smuzhiyun 			pdm->clk_state = NULL;
976*4882a593Smuzhiyun 			dev_dbg(pdm->dev, "Have no clk pinctrl state\n");
977*4882a593Smuzhiyun 		}
978*4882a593Smuzhiyun 	}
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	pdm->start_delay_ms = PDM_START_DELAY_MS_DEFAULT;
981*4882a593Smuzhiyun 	pdm->filter_delay_ms = PDM_FILTER_DELAY_MS_MIN;
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	pdm->clk_calibrate =
984*4882a593Smuzhiyun 		of_property_read_bool(node, "rockchip,mclk-calibrate");
985*4882a593Smuzhiyun 	if (pdm->clk_calibrate) {
986*4882a593Smuzhiyun 		pdm->clk_root = devm_clk_get(&pdev->dev, "pdm_clk_root");
987*4882a593Smuzhiyun 		if (IS_ERR(pdm->clk_root))
988*4882a593Smuzhiyun 			return PTR_ERR(pdm->clk_root);
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 		pdm->clk_root_initial_rate = clk_get_rate(pdm->clk_root);
991*4882a593Smuzhiyun 		pdm->clk_root_rate = pdm->clk_root_initial_rate;
992*4882a593Smuzhiyun 	}
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun 	pdm->clk = devm_clk_get(&pdev->dev, "pdm_clk");
995*4882a593Smuzhiyun 	if (IS_ERR(pdm->clk))
996*4882a593Smuzhiyun 		return PTR_ERR(pdm->clk);
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun 	pdm->hclk = devm_clk_get(&pdev->dev, "pdm_hclk");
999*4882a593Smuzhiyun 	if (IS_ERR(pdm->hclk))
1000*4882a593Smuzhiyun 		return PTR_ERR(pdm->hclk);
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	ret = clk_prepare_enable(pdm->hclk);
1003*4882a593Smuzhiyun 	if (ret)
1004*4882a593Smuzhiyun 		return ret;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	pm_runtime_enable(&pdev->dev);
1007*4882a593Smuzhiyun 	if (!pm_runtime_enabled(&pdev->dev)) {
1008*4882a593Smuzhiyun 		ret = rockchip_pdm_runtime_resume(&pdev->dev);
1009*4882a593Smuzhiyun 		if (ret)
1010*4882a593Smuzhiyun 			goto err_pm_disable;
1011*4882a593Smuzhiyun 	}
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun 	ret = devm_snd_soc_register_component(&pdev->dev,
1014*4882a593Smuzhiyun 					      &rockchip_pdm_component,
1015*4882a593Smuzhiyun 					      &rockchip_pdm_dai, 1);
1016*4882a593Smuzhiyun 
1017*4882a593Smuzhiyun 	if (ret) {
1018*4882a593Smuzhiyun 		dev_err(&pdev->dev, "could not register dai: %d\n", ret);
1019*4882a593Smuzhiyun 		goto err_suspend;
1020*4882a593Smuzhiyun 	}
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	rockchip_pdm_set_samplerate(pdm, PDM_DEFAULT_RATE);
1023*4882a593Smuzhiyun 	rockchip_pdm_rxctrl(pdm, 0);
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 	ret = rockchip_pdm_path_parse(pdm, node);
1026*4882a593Smuzhiyun 	if (ret != 0 && ret != -ENOENT)
1027*4882a593Smuzhiyun 		goto err_suspend;
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	if (of_property_read_bool(node, "rockchip,no-dmaengine")) {
1030*4882a593Smuzhiyun 		dev_info(&pdev->dev, "Used for Multi-DAI\n");
1031*4882a593Smuzhiyun 		return 0;
1032*4882a593Smuzhiyun 	}
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun 	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
1035*4882a593Smuzhiyun 	if (ret) {
1036*4882a593Smuzhiyun 		dev_err(&pdev->dev, "could not register pcm: %d\n", ret);
1037*4882a593Smuzhiyun 		goto err_suspend;
1038*4882a593Smuzhiyun 	}
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->hclk);
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	return 0;
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun err_suspend:
1045*4882a593Smuzhiyun 	if (!pm_runtime_status_suspended(&pdev->dev))
1046*4882a593Smuzhiyun 		rockchip_pdm_runtime_suspend(&pdev->dev);
1047*4882a593Smuzhiyun err_pm_disable:
1048*4882a593Smuzhiyun 	pm_runtime_disable(&pdev->dev);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun 	clk_disable_unprepare(pdm->hclk);
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun 	return ret;
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun 
rockchip_pdm_remove(struct platform_device * pdev)1055*4882a593Smuzhiyun static int rockchip_pdm_remove(struct platform_device *pdev)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun 	pm_runtime_disable(&pdev->dev);
1058*4882a593Smuzhiyun 	if (!pm_runtime_status_suspended(&pdev->dev))
1059*4882a593Smuzhiyun 		rockchip_pdm_runtime_suspend(&pdev->dev);
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	return 0;
1062*4882a593Smuzhiyun }
1063*4882a593Smuzhiyun 
1064*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
rockchip_pdm_suspend(struct device * dev)1065*4882a593Smuzhiyun static int rockchip_pdm_suspend(struct device *dev)
1066*4882a593Smuzhiyun {
1067*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	regcache_mark_dirty(pdm->regmap);
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun 	return 0;
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun 
rockchip_pdm_resume(struct device * dev)1074*4882a593Smuzhiyun static int rockchip_pdm_resume(struct device *dev)
1075*4882a593Smuzhiyun {
1076*4882a593Smuzhiyun 	struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
1077*4882a593Smuzhiyun 	int ret;
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	ret = pm_runtime_get_sync(dev);
1080*4882a593Smuzhiyun 	if (ret < 0) {
1081*4882a593Smuzhiyun 		pm_runtime_put(dev);
1082*4882a593Smuzhiyun 		return ret;
1083*4882a593Smuzhiyun 	}
1084*4882a593Smuzhiyun 
1085*4882a593Smuzhiyun 	ret = regcache_sync(pdm->regmap);
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	pm_runtime_put(dev);
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun 	return ret;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun #endif
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun static const struct dev_pm_ops rockchip_pdm_pm_ops = {
1094*4882a593Smuzhiyun 	SET_RUNTIME_PM_OPS(rockchip_pdm_runtime_suspend,
1095*4882a593Smuzhiyun 			   rockchip_pdm_runtime_resume, NULL)
1096*4882a593Smuzhiyun 	SET_SYSTEM_SLEEP_PM_OPS(rockchip_pdm_suspend, rockchip_pdm_resume)
1097*4882a593Smuzhiyun };
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun static struct platform_driver rockchip_pdm_driver = {
1100*4882a593Smuzhiyun 	.probe  = rockchip_pdm_probe,
1101*4882a593Smuzhiyun 	.remove = rockchip_pdm_remove,
1102*4882a593Smuzhiyun 	.driver = {
1103*4882a593Smuzhiyun 		.name = "rockchip-pdm",
1104*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(rockchip_pdm_match),
1105*4882a593Smuzhiyun 		.pm = &rockchip_pdm_pm_ops,
1106*4882a593Smuzhiyun 	},
1107*4882a593Smuzhiyun };
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun module_platform_driver(rockchip_pdm_driver);
1110*4882a593Smuzhiyun 
1111*4882a593Smuzhiyun MODULE_AUTHOR("Sugar <sugar.zhang@rock-chips.com>");
1112*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip PDM Controller Driver");
1113*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1114