1 | // SPDX-License-Identifier: (GPL-2.0 OR MIT) |
2 | // |
3 | // Copyright (c) 2018 BayLibre, SAS. |
4 | // Author: Jerome Brunet <jbrunet@baylibre.com> |
5 | |
6 | #include <linux/clk.h> |
7 | #include <linux/module.h> |
8 | #include <linux/of_irq.h> |
9 | #include <linux/of_platform.h> |
10 | #include <linux/regmap.h> |
11 | #include <sound/soc.h> |
12 | #include <sound/soc-dai.h> |
13 | #include <sound/pcm_params.h> |
14 | |
15 | #define PDM_CTRL 0x00 |
16 | #define PDM_CTRL_EN BIT(31) |
17 | #define PDM_CTRL_OUT_MODE BIT(29) |
18 | #define PDM_CTRL_BYPASS_MODE BIT(28) |
19 | #define PDM_CTRL_RST_FIFO BIT(16) |
20 | #define PDM_CTRL_CHAN_RSTN_MASK GENMASK(15, 8) |
21 | #define PDM_CTRL_CHAN_RSTN(x) ((x) << 8) |
22 | #define PDM_CTRL_CHAN_EN_MASK GENMASK(7, 0) |
23 | #define PDM_CTRL_CHAN_EN(x) ((x) << 0) |
24 | #define PDM_HCIC_CTRL1 0x04 |
25 | #define PDM_FILTER_EN BIT(31) |
26 | #define PDM_HCIC_CTRL1_GAIN_SFT_MASK GENMASK(29, 24) |
27 | #define PDM_HCIC_CTRL1_GAIN_SFT(x) ((x) << 24) |
28 | #define PDM_HCIC_CTRL1_GAIN_MULT_MASK GENMASK(23, 16) |
29 | #define PDM_HCIC_CTRL1_GAIN_MULT(x) ((x) << 16) |
30 | #define PDM_HCIC_CTRL1_DSR_MASK GENMASK(8, 4) |
31 | #define PDM_HCIC_CTRL1_DSR(x) ((x) << 4) |
32 | #define PDM_HCIC_CTRL1_STAGE_NUM_MASK GENMASK(3, 0) |
33 | #define PDM_HCIC_CTRL1_STAGE_NUM(x) ((x) << 0) |
34 | #define PDM_HCIC_CTRL2 0x08 |
35 | #define PDM_F1_CTRL 0x0c |
36 | #define PDM_LPF_ROUND_MODE_MASK GENMASK(17, 16) |
37 | #define PDM_LPF_ROUND_MODE(x) ((x) << 16) |
38 | #define PDM_LPF_DSR_MASK GENMASK(15, 12) |
39 | #define PDM_LPF_DSR(x) ((x) << 12) |
40 | #define PDM_LPF_STAGE_NUM_MASK GENMASK(8, 0) |
41 | #define PDM_LPF_STAGE_NUM(x) ((x) << 0) |
42 | #define PDM_LPF_MAX_STAGE 336 |
43 | #define PDM_LPF_NUM 3 |
44 | #define PDM_F2_CTRL 0x10 |
45 | #define PDM_F3_CTRL 0x14 |
46 | #define PDM_HPF_CTRL 0x18 |
47 | #define PDM_HPF_SFT_STEPS_MASK GENMASK(20, 16) |
48 | #define PDM_HPF_SFT_STEPS(x) ((x) << 16) |
49 | #define PDM_HPF_OUT_FACTOR_MASK GENMASK(15, 0) |
50 | #define PDM_HPF_OUT_FACTOR(x) ((x) << 0) |
51 | #define PDM_CHAN_CTRL 0x1c |
52 | #define PDM_CHAN_CTRL_POINTER_WIDTH 8 |
53 | #define PDM_CHAN_CTRL_POINTER_MAX ((1 << PDM_CHAN_CTRL_POINTER_WIDTH) - 1) |
54 | #define PDM_CHAN_CTRL_NUM 4 |
55 | #define PDM_CHAN_CTRL1 0x20 |
56 | #define PDM_COEFF_ADDR 0x24 |
57 | #define PDM_COEFF_DATA 0x28 |
58 | #define PDM_CLKG_CTRL 0x2c |
59 | #define PDM_STS 0x30 |
60 | |
61 | struct axg_pdm_lpf { |
62 | unsigned int ds; |
63 | unsigned int round_mode; |
64 | const unsigned int *tap; |
65 | unsigned int tap_num; |
66 | }; |
67 | |
68 | struct axg_pdm_hcic { |
69 | unsigned int shift; |
70 | unsigned int mult; |
71 | unsigned int steps; |
72 | unsigned int ds; |
73 | }; |
74 | |
75 | struct axg_pdm_hpf { |
76 | unsigned int out_factor; |
77 | unsigned int steps; |
78 | }; |
79 | |
80 | struct axg_pdm_filters { |
81 | struct axg_pdm_hcic hcic; |
82 | struct axg_pdm_hpf hpf; |
83 | struct axg_pdm_lpf lpf[PDM_LPF_NUM]; |
84 | }; |
85 | |
86 | struct axg_pdm_cfg { |
87 | const struct axg_pdm_filters *filters; |
88 | unsigned int sys_rate; |
89 | }; |
90 | |
91 | struct axg_pdm { |
92 | const struct axg_pdm_cfg *cfg; |
93 | struct regmap *map; |
94 | struct clk *dclk; |
95 | struct clk *sysclk; |
96 | struct clk *pclk; |
97 | }; |
98 | |
99 | static void axg_pdm_enable(struct regmap *map) |
100 | { |
101 | /* Reset AFIFO */ |
102 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, PDM_CTRL_RST_FIFO); |
103 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_RST_FIFO, val: 0); |
104 | |
105 | /* Enable PDM */ |
106 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, PDM_CTRL_EN); |
107 | } |
108 | |
109 | static void axg_pdm_disable(struct regmap *map) |
110 | { |
111 | regmap_update_bits(map, PDM_CTRL, PDM_CTRL_EN, val: 0); |
112 | } |
113 | |
114 | static void axg_pdm_filters_enable(struct regmap *map, bool enable) |
115 | { |
116 | unsigned int val = enable ? PDM_FILTER_EN : 0; |
117 | |
118 | regmap_update_bits(map, PDM_HCIC_CTRL1, PDM_FILTER_EN, val); |
119 | regmap_update_bits(map, PDM_F1_CTRL, PDM_FILTER_EN, val); |
120 | regmap_update_bits(map, PDM_F2_CTRL, PDM_FILTER_EN, val); |
121 | regmap_update_bits(map, PDM_F3_CTRL, PDM_FILTER_EN, val); |
122 | regmap_update_bits(map, PDM_HPF_CTRL, PDM_FILTER_EN, val); |
123 | } |
124 | |
125 | static int axg_pdm_trigger(struct snd_pcm_substream *substream, int cmd, |
126 | struct snd_soc_dai *dai) |
127 | { |
128 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
129 | |
130 | switch (cmd) { |
131 | case SNDRV_PCM_TRIGGER_START: |
132 | case SNDRV_PCM_TRIGGER_RESUME: |
133 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
134 | axg_pdm_enable(map: priv->map); |
135 | return 0; |
136 | |
137 | case SNDRV_PCM_TRIGGER_STOP: |
138 | case SNDRV_PCM_TRIGGER_SUSPEND: |
139 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
140 | axg_pdm_disable(map: priv->map); |
141 | return 0; |
142 | |
143 | default: |
144 | return -EINVAL; |
145 | } |
146 | } |
147 | |
148 | static unsigned int axg_pdm_get_os(struct axg_pdm *priv) |
149 | { |
150 | const struct axg_pdm_filters *filters = priv->cfg->filters; |
151 | unsigned int os = filters->hcic.ds; |
152 | int i; |
153 | |
154 | /* |
155 | * The global oversampling factor is defined by the down sampling |
156 | * factor applied by each filter (HCIC and LPFs) |
157 | */ |
158 | |
159 | for (i = 0; i < PDM_LPF_NUM; i++) |
160 | os *= filters->lpf[i].ds; |
161 | |
162 | return os; |
163 | } |
164 | |
165 | static int axg_pdm_set_sysclk(struct axg_pdm *priv, unsigned int os, |
166 | unsigned int rate) |
167 | { |
168 | unsigned int sys_rate = os * 2 * rate * PDM_CHAN_CTRL_POINTER_MAX; |
169 | |
170 | /* |
171 | * Set the default system clock rate unless it is too fast for |
172 | * the requested sample rate. In this case, the sample pointer |
173 | * counter could overflow so set a lower system clock rate |
174 | */ |
175 | if (sys_rate < priv->cfg->sys_rate) |
176 | return clk_set_rate(clk: priv->sysclk, rate: sys_rate); |
177 | |
178 | return clk_set_rate(clk: priv->sysclk, rate: priv->cfg->sys_rate); |
179 | } |
180 | |
181 | static int axg_pdm_set_sample_pointer(struct axg_pdm *priv) |
182 | { |
183 | unsigned int spmax, sp, val; |
184 | int i; |
185 | |
186 | /* Max sample counter value per half period of dclk */ |
187 | spmax = DIV_ROUND_UP_ULL((u64)clk_get_rate(priv->sysclk), |
188 | clk_get_rate(priv->dclk) * 2); |
189 | |
190 | /* Check if sysclk is not too fast - should not happen */ |
191 | if (WARN_ON(spmax > PDM_CHAN_CTRL_POINTER_MAX)) |
192 | return -EINVAL; |
193 | |
194 | /* Capture the data when we are at 75% of the half period */ |
195 | sp = spmax * 3 / 4; |
196 | |
197 | for (i = 0, val = 0; i < PDM_CHAN_CTRL_NUM; i++) |
198 | val |= sp << (PDM_CHAN_CTRL_POINTER_WIDTH * i); |
199 | |
200 | regmap_write(map: priv->map, PDM_CHAN_CTRL, val); |
201 | regmap_write(map: priv->map, PDM_CHAN_CTRL1, val); |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | static void axg_pdm_set_channel_mask(struct axg_pdm *priv, |
207 | unsigned int channels) |
208 | { |
209 | unsigned int mask = GENMASK(channels - 1, 0); |
210 | |
211 | /* Put all channel in reset */ |
212 | regmap_update_bits(map: priv->map, PDM_CTRL, |
213 | PDM_CTRL_CHAN_RSTN_MASK, val: 0); |
214 | |
215 | /* Take the necessary channels out of reset and enable them */ |
216 | regmap_update_bits(map: priv->map, PDM_CTRL, |
217 | PDM_CTRL_CHAN_RSTN_MASK | |
218 | PDM_CTRL_CHAN_EN_MASK, |
219 | PDM_CTRL_CHAN_RSTN(mask) | |
220 | PDM_CTRL_CHAN_EN(mask)); |
221 | } |
222 | |
223 | static int axg_pdm_hw_params(struct snd_pcm_substream *substream, |
224 | struct snd_pcm_hw_params *params, |
225 | struct snd_soc_dai *dai) |
226 | { |
227 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
228 | unsigned int os = axg_pdm_get_os(priv); |
229 | unsigned int rate = params_rate(p: params); |
230 | unsigned int val; |
231 | int ret; |
232 | |
233 | switch (params_width(p: params)) { |
234 | case 24: |
235 | val = PDM_CTRL_OUT_MODE; |
236 | break; |
237 | case 32: |
238 | val = 0; |
239 | break; |
240 | default: |
241 | dev_err(dai->dev, "unsupported sample width\n" ); |
242 | return -EINVAL; |
243 | } |
244 | |
245 | regmap_update_bits(map: priv->map, PDM_CTRL, PDM_CTRL_OUT_MODE, val); |
246 | |
247 | ret = axg_pdm_set_sysclk(priv, os, rate); |
248 | if (ret) { |
249 | dev_err(dai->dev, "failed to set system clock\n" ); |
250 | return ret; |
251 | } |
252 | |
253 | ret = clk_set_rate(clk: priv->dclk, rate: rate * os); |
254 | if (ret) { |
255 | dev_err(dai->dev, "failed to set dclk\n" ); |
256 | return ret; |
257 | } |
258 | |
259 | ret = axg_pdm_set_sample_pointer(priv); |
260 | if (ret) { |
261 | dev_err(dai->dev, "invalid clock setting\n" ); |
262 | return ret; |
263 | } |
264 | |
265 | axg_pdm_set_channel_mask(priv, channels: params_channels(p: params)); |
266 | |
267 | return 0; |
268 | } |
269 | |
270 | static int axg_pdm_startup(struct snd_pcm_substream *substream, |
271 | struct snd_soc_dai *dai) |
272 | { |
273 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
274 | int ret; |
275 | |
276 | ret = clk_prepare_enable(clk: priv->dclk); |
277 | if (ret) { |
278 | dev_err(dai->dev, "enabling dclk failed\n" ); |
279 | return ret; |
280 | } |
281 | |
282 | /* Enable the filters */ |
283 | axg_pdm_filters_enable(map: priv->map, enable: true); |
284 | |
285 | return ret; |
286 | } |
287 | |
288 | static void axg_pdm_shutdown(struct snd_pcm_substream *substream, |
289 | struct snd_soc_dai *dai) |
290 | { |
291 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
292 | |
293 | axg_pdm_filters_enable(map: priv->map, enable: false); |
294 | clk_disable_unprepare(clk: priv->dclk); |
295 | } |
296 | |
297 | static void axg_pdm_set_hcic_ctrl(struct axg_pdm *priv) |
298 | { |
299 | const struct axg_pdm_hcic *hcic = &priv->cfg->filters->hcic; |
300 | unsigned int val; |
301 | |
302 | val = PDM_HCIC_CTRL1_STAGE_NUM(hcic->steps); |
303 | val |= PDM_HCIC_CTRL1_DSR(hcic->ds); |
304 | val |= PDM_HCIC_CTRL1_GAIN_MULT(hcic->mult); |
305 | val |= PDM_HCIC_CTRL1_GAIN_SFT(hcic->shift); |
306 | |
307 | regmap_update_bits(map: priv->map, PDM_HCIC_CTRL1, |
308 | PDM_HCIC_CTRL1_STAGE_NUM_MASK | |
309 | PDM_HCIC_CTRL1_DSR_MASK | |
310 | PDM_HCIC_CTRL1_GAIN_MULT_MASK | |
311 | PDM_HCIC_CTRL1_GAIN_SFT_MASK, |
312 | val); |
313 | } |
314 | |
315 | static void axg_pdm_set_lpf_ctrl(struct axg_pdm *priv, unsigned int index) |
316 | { |
317 | const struct axg_pdm_lpf *lpf = &priv->cfg->filters->lpf[index]; |
318 | unsigned int offset = index * regmap_get_reg_stride(map: priv->map) |
319 | + PDM_F1_CTRL; |
320 | unsigned int val; |
321 | |
322 | val = PDM_LPF_STAGE_NUM(lpf->tap_num); |
323 | val |= PDM_LPF_DSR(lpf->ds); |
324 | val |= PDM_LPF_ROUND_MODE(lpf->round_mode); |
325 | |
326 | regmap_update_bits(map: priv->map, reg: offset, |
327 | PDM_LPF_STAGE_NUM_MASK | |
328 | PDM_LPF_DSR_MASK | |
329 | PDM_LPF_ROUND_MODE_MASK, |
330 | val); |
331 | } |
332 | |
333 | static void axg_pdm_set_hpf_ctrl(struct axg_pdm *priv) |
334 | { |
335 | const struct axg_pdm_hpf *hpf = &priv->cfg->filters->hpf; |
336 | unsigned int val; |
337 | |
338 | val = PDM_HPF_OUT_FACTOR(hpf->out_factor); |
339 | val |= PDM_HPF_SFT_STEPS(hpf->steps); |
340 | |
341 | regmap_update_bits(map: priv->map, PDM_HPF_CTRL, |
342 | PDM_HPF_OUT_FACTOR_MASK | |
343 | PDM_HPF_SFT_STEPS_MASK, |
344 | val); |
345 | } |
346 | |
347 | static int axg_pdm_set_lpf_filters(struct axg_pdm *priv) |
348 | { |
349 | const struct axg_pdm_lpf *lpf = priv->cfg->filters->lpf; |
350 | unsigned int count = 0; |
351 | int i, j; |
352 | |
353 | for (i = 0; i < PDM_LPF_NUM; i++) |
354 | count += lpf[i].tap_num; |
355 | |
356 | /* Make sure the coeffs fit in the memory */ |
357 | if (count >= PDM_LPF_MAX_STAGE) |
358 | return -EINVAL; |
359 | |
360 | /* Set the initial APB bus register address */ |
361 | regmap_write(map: priv->map, PDM_COEFF_ADDR, val: 0); |
362 | |
363 | /* Set the tap filter values of all 3 filters */ |
364 | for (i = 0; i < PDM_LPF_NUM; i++) { |
365 | axg_pdm_set_lpf_ctrl(priv, index: i); |
366 | |
367 | for (j = 0; j < lpf[i].tap_num; j++) |
368 | regmap_write(map: priv->map, PDM_COEFF_DATA, val: lpf[i].tap[j]); |
369 | } |
370 | |
371 | return 0; |
372 | } |
373 | |
374 | static int axg_pdm_dai_probe(struct snd_soc_dai *dai) |
375 | { |
376 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
377 | int ret; |
378 | |
379 | ret = clk_prepare_enable(clk: priv->pclk); |
380 | if (ret) { |
381 | dev_err(dai->dev, "enabling pclk failed\n" ); |
382 | return ret; |
383 | } |
384 | |
385 | /* |
386 | * sysclk must be set and enabled as well to access the pdm registers |
387 | * Accessing the register w/o it will give a bus error. |
388 | */ |
389 | ret = clk_set_rate(clk: priv->sysclk, rate: priv->cfg->sys_rate); |
390 | if (ret) { |
391 | dev_err(dai->dev, "setting sysclk failed\n" ); |
392 | goto err_pclk; |
393 | } |
394 | |
395 | ret = clk_prepare_enable(clk: priv->sysclk); |
396 | if (ret) { |
397 | dev_err(dai->dev, "enabling sysclk failed\n" ); |
398 | goto err_pclk; |
399 | } |
400 | |
401 | /* Make sure the device is initially disabled */ |
402 | axg_pdm_disable(map: priv->map); |
403 | |
404 | /* Make sure filter bypass is disabled */ |
405 | regmap_update_bits(map: priv->map, PDM_CTRL, PDM_CTRL_BYPASS_MODE, val: 0); |
406 | |
407 | /* Load filter settings */ |
408 | axg_pdm_set_hcic_ctrl(priv); |
409 | axg_pdm_set_hpf_ctrl(priv); |
410 | |
411 | ret = axg_pdm_set_lpf_filters(priv); |
412 | if (ret) { |
413 | dev_err(dai->dev, "invalid filter configuration\n" ); |
414 | goto err_sysclk; |
415 | } |
416 | |
417 | return 0; |
418 | |
419 | err_sysclk: |
420 | clk_disable_unprepare(clk: priv->sysclk); |
421 | err_pclk: |
422 | clk_disable_unprepare(clk: priv->pclk); |
423 | return ret; |
424 | } |
425 | |
426 | static int axg_pdm_dai_remove(struct snd_soc_dai *dai) |
427 | { |
428 | struct axg_pdm *priv = snd_soc_dai_get_drvdata(dai); |
429 | |
430 | clk_disable_unprepare(clk: priv->sysclk); |
431 | clk_disable_unprepare(clk: priv->pclk); |
432 | |
433 | return 0; |
434 | } |
435 | |
436 | static const struct snd_soc_dai_ops axg_pdm_dai_ops = { |
437 | .probe = axg_pdm_dai_probe, |
438 | .remove = axg_pdm_dai_remove, |
439 | .trigger = axg_pdm_trigger, |
440 | .hw_params = axg_pdm_hw_params, |
441 | .startup = axg_pdm_startup, |
442 | .shutdown = axg_pdm_shutdown, |
443 | }; |
444 | |
445 | static struct snd_soc_dai_driver axg_pdm_dai_drv = { |
446 | .name = "PDM" , |
447 | .capture = { |
448 | .stream_name = "Capture" , |
449 | .channels_min = 1, |
450 | .channels_max = 8, |
451 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
452 | .rate_min = 5512, |
453 | .rate_max = 48000, |
454 | .formats = (SNDRV_PCM_FMTBIT_S24_LE | |
455 | SNDRV_PCM_FMTBIT_S32_LE), |
456 | }, |
457 | .ops = &axg_pdm_dai_ops, |
458 | }; |
459 | |
460 | static const struct snd_soc_component_driver axg_pdm_component_drv = { |
461 | .legacy_dai_naming = 1, |
462 | }; |
463 | |
464 | static const struct regmap_config axg_pdm_regmap_cfg = { |
465 | .reg_bits = 32, |
466 | .val_bits = 32, |
467 | .reg_stride = 4, |
468 | .max_register = PDM_STS, |
469 | }; |
470 | |
471 | static const unsigned int lpf1_default_tap[] = { |
472 | 0x000014, 0xffffb2, 0xfffed9, 0xfffdce, 0xfffd45, |
473 | 0xfffe32, 0x000147, 0x000645, 0x000b86, 0x000e21, |
474 | 0x000ae3, 0x000000, 0xffeece, 0xffdca8, 0xffd212, |
475 | 0xffd7d1, 0xfff2a7, 0x001f4c, 0x0050c2, 0x0072aa, |
476 | 0x006ff1, 0x003c32, 0xffdc4e, 0xff6a18, 0xff0fef, |
477 | 0xfefbaf, 0xff4c40, 0x000000, 0x00ebc8, 0x01c077, |
478 | 0x02209e, 0x01c1a4, 0x008e60, 0xfebe52, 0xfcd690, |
479 | 0xfb8fa5, 0xfba498, 0xfd9812, 0x0181ce, 0x06f5f3, |
480 | 0x0d112f, 0x12a958, 0x169686, 0x18000e, 0x169686, |
481 | 0x12a958, 0x0d112f, 0x06f5f3, 0x0181ce, 0xfd9812, |
482 | 0xfba498, 0xfb8fa5, 0xfcd690, 0xfebe52, 0x008e60, |
483 | 0x01c1a4, 0x02209e, 0x01c077, 0x00ebc8, 0x000000, |
484 | 0xff4c40, 0xfefbaf, 0xff0fef, 0xff6a18, 0xffdc4e, |
485 | 0x003c32, 0x006ff1, 0x0072aa, 0x0050c2, 0x001f4c, |
486 | 0xfff2a7, 0xffd7d1, 0xffd212, 0xffdca8, 0xffeece, |
487 | 0x000000, 0x000ae3, 0x000e21, 0x000b86, 0x000645, |
488 | 0x000147, 0xfffe32, 0xfffd45, 0xfffdce, 0xfffed9, |
489 | 0xffffb2, 0x000014, |
490 | }; |
491 | |
492 | static const unsigned int lpf2_default_tap[] = { |
493 | 0x00050a, 0xfff004, 0x0002c1, 0x003c12, 0xffa818, |
494 | 0xffc87d, 0x010aef, 0xff5223, 0xfebd93, 0x028f41, |
495 | 0xff5c0e, 0xfc63f8, 0x055f81, 0x000000, 0xf478a0, |
496 | 0x11c5e3, 0x2ea74d, 0x11c5e3, 0xf478a0, 0x000000, |
497 | 0x055f81, 0xfc63f8, 0xff5c0e, 0x028f41, 0xfebd93, |
498 | 0xff5223, 0x010aef, 0xffc87d, 0xffa818, 0x003c12, |
499 | 0x0002c1, 0xfff004, 0x00050a, |
500 | }; |
501 | |
502 | static const unsigned int lpf3_default_tap[] = { |
503 | 0x000000, 0x000081, 0x000000, 0xfffedb, 0x000000, |
504 | 0x00022d, 0x000000, 0xfffc46, 0x000000, 0x0005f7, |
505 | 0x000000, 0xfff6eb, 0x000000, 0x000d4e, 0x000000, |
506 | 0xffed1e, 0x000000, 0x001a1c, 0x000000, 0xffdcb0, |
507 | 0x000000, 0x002ede, 0x000000, 0xffc2d1, 0x000000, |
508 | 0x004ebe, 0x000000, 0xff9beb, 0x000000, 0x007dd7, |
509 | 0x000000, 0xff633a, 0x000000, 0x00c1d2, 0x000000, |
510 | 0xff11d5, 0x000000, 0x012368, 0x000000, 0xfe9c45, |
511 | 0x000000, 0x01b252, 0x000000, 0xfdebf6, 0x000000, |
512 | 0x0290b8, 0x000000, 0xfcca0d, 0x000000, 0x041d7c, |
513 | 0x000000, 0xfa8152, 0x000000, 0x07e9c6, 0x000000, |
514 | 0xf28fb5, 0x000000, 0x28b216, 0x3fffde, 0x28b216, |
515 | 0x000000, 0xf28fb5, 0x000000, 0x07e9c6, 0x000000, |
516 | 0xfa8152, 0x000000, 0x041d7c, 0x000000, 0xfcca0d, |
517 | 0x000000, 0x0290b8, 0x000000, 0xfdebf6, 0x000000, |
518 | 0x01b252, 0x000000, 0xfe9c45, 0x000000, 0x012368, |
519 | 0x000000, 0xff11d5, 0x000000, 0x00c1d2, 0x000000, |
520 | 0xff633a, 0x000000, 0x007dd7, 0x000000, 0xff9beb, |
521 | 0x000000, 0x004ebe, 0x000000, 0xffc2d1, 0x000000, |
522 | 0x002ede, 0x000000, 0xffdcb0, 0x000000, 0x001a1c, |
523 | 0x000000, 0xffed1e, 0x000000, 0x000d4e, 0x000000, |
524 | 0xfff6eb, 0x000000, 0x0005f7, 0x000000, 0xfffc46, |
525 | 0x000000, 0x00022d, 0x000000, 0xfffedb, 0x000000, |
526 | 0x000081, 0x000000, |
527 | }; |
528 | |
529 | /* |
530 | * These values are sane defaults for the axg platform: |
531 | * - OS = 64 |
532 | * - Latency = 38700 (?) |
533 | * |
534 | * TODO: There is a lot of different HCIC, LPFs and HPF configurations possible. |
535 | * the configuration may depend on the dmic used by the platform, the |
536 | * expected tradeoff between latency and quality, etc ... If/When other |
537 | * settings are required, we should add a fw interface to this driver to |
538 | * load new filter settings. |
539 | */ |
540 | static const struct axg_pdm_filters axg_default_filters = { |
541 | .hcic = { |
542 | .shift = 0x15, |
543 | .mult = 0x80, |
544 | .steps = 7, |
545 | .ds = 8, |
546 | }, |
547 | .hpf = { |
548 | .out_factor = 0x8000, |
549 | .steps = 13, |
550 | }, |
551 | .lpf = { |
552 | [0] = { |
553 | .ds = 2, |
554 | .round_mode = 1, |
555 | .tap = lpf1_default_tap, |
556 | .tap_num = ARRAY_SIZE(lpf1_default_tap), |
557 | }, |
558 | [1] = { |
559 | .ds = 2, |
560 | .round_mode = 0, |
561 | .tap = lpf2_default_tap, |
562 | .tap_num = ARRAY_SIZE(lpf2_default_tap), |
563 | }, |
564 | [2] = { |
565 | .ds = 2, |
566 | .round_mode = 1, |
567 | .tap = lpf3_default_tap, |
568 | .tap_num = ARRAY_SIZE(lpf3_default_tap) |
569 | }, |
570 | }, |
571 | }; |
572 | |
573 | static const struct axg_pdm_cfg axg_pdm_config = { |
574 | .filters = &axg_default_filters, |
575 | .sys_rate = 250000000, |
576 | }; |
577 | |
578 | static const struct of_device_id axg_pdm_of_match[] = { |
579 | { |
580 | .compatible = "amlogic,axg-pdm" , |
581 | .data = &axg_pdm_config, |
582 | }, {} |
583 | }; |
584 | MODULE_DEVICE_TABLE(of, axg_pdm_of_match); |
585 | |
586 | static int axg_pdm_probe(struct platform_device *pdev) |
587 | { |
588 | struct device *dev = &pdev->dev; |
589 | struct axg_pdm *priv; |
590 | void __iomem *regs; |
591 | |
592 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
593 | if (!priv) |
594 | return -ENOMEM; |
595 | platform_set_drvdata(pdev, data: priv); |
596 | |
597 | priv->cfg = of_device_get_match_data(dev); |
598 | if (!priv->cfg) { |
599 | dev_err(dev, "failed to match device\n" ); |
600 | return -ENODEV; |
601 | } |
602 | |
603 | regs = devm_platform_ioremap_resource(pdev, index: 0); |
604 | if (IS_ERR(ptr: regs)) |
605 | return PTR_ERR(ptr: regs); |
606 | |
607 | priv->map = devm_regmap_init_mmio(dev, regs, &axg_pdm_regmap_cfg); |
608 | if (IS_ERR(ptr: priv->map)) { |
609 | dev_err(dev, "failed to init regmap: %ld\n" , |
610 | PTR_ERR(priv->map)); |
611 | return PTR_ERR(ptr: priv->map); |
612 | } |
613 | |
614 | priv->pclk = devm_clk_get(dev, id: "pclk" ); |
615 | if (IS_ERR(ptr: priv->pclk)) |
616 | return dev_err_probe(dev, err: PTR_ERR(ptr: priv->pclk), fmt: "failed to get pclk\n" ); |
617 | |
618 | priv->dclk = devm_clk_get(dev, id: "dclk" ); |
619 | if (IS_ERR(ptr: priv->dclk)) |
620 | return dev_err_probe(dev, err: PTR_ERR(ptr: priv->dclk), fmt: "failed to get dclk\n" ); |
621 | |
622 | priv->sysclk = devm_clk_get(dev, id: "sysclk" ); |
623 | if (IS_ERR(ptr: priv->sysclk)) |
624 | return dev_err_probe(dev, err: PTR_ERR(ptr: priv->sysclk), fmt: "failed to get dclk\n" ); |
625 | |
626 | return devm_snd_soc_register_component(dev, component_driver: &axg_pdm_component_drv, |
627 | dai_drv: &axg_pdm_dai_drv, num_dai: 1); |
628 | } |
629 | |
630 | static struct platform_driver axg_pdm_pdrv = { |
631 | .probe = axg_pdm_probe, |
632 | .driver = { |
633 | .name = "axg-pdm" , |
634 | .of_match_table = axg_pdm_of_match, |
635 | }, |
636 | }; |
637 | module_platform_driver(axg_pdm_pdrv); |
638 | |
639 | MODULE_DESCRIPTION("Amlogic AXG PDM Input driver" ); |
640 | MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>" ); |
641 | MODULE_LICENSE("GPL v2" ); |
642 | |