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