1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright 2019 NXP |
3 | |
4 | #include <linux/atomic.h> |
5 | #include <linux/clk.h> |
6 | #include <linux/device.h> |
7 | #include <linux/dma-mapping.h> |
8 | #include <linux/firmware.h> |
9 | #include <linux/interrupt.h> |
10 | #include <linux/kobject.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/miscdevice.h> |
14 | #include <linux/of.h> |
15 | #include <linux/of_address.h> |
16 | #include <linux/of_irq.h> |
17 | #include <linux/of_platform.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/sched/signal.h> |
21 | #include <linux/sysfs.h> |
22 | #include <linux/types.h> |
23 | #include <linux/gcd.h> |
24 | #include <sound/dmaengine_pcm.h> |
25 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> |
27 | #include <sound/soc.h> |
28 | #include <sound/tlv.h> |
29 | #include <sound/core.h> |
30 | |
31 | #include "fsl_easrc.h" |
32 | #include "imx-pcm.h" |
33 | |
34 | #define FSL_EASRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
35 | SNDRV_PCM_FMTBIT_U16_LE | \ |
36 | SNDRV_PCM_FMTBIT_S24_LE | \ |
37 | SNDRV_PCM_FMTBIT_S24_3LE | \ |
38 | SNDRV_PCM_FMTBIT_U24_LE | \ |
39 | SNDRV_PCM_FMTBIT_U24_3LE | \ |
40 | SNDRV_PCM_FMTBIT_S32_LE | \ |
41 | SNDRV_PCM_FMTBIT_U32_LE | \ |
42 | SNDRV_PCM_FMTBIT_S20_3LE | \ |
43 | SNDRV_PCM_FMTBIT_U20_3LE | \ |
44 | SNDRV_PCM_FMTBIT_FLOAT_LE) |
45 | |
46 | static int fsl_easrc_iec958_put_bits(struct snd_kcontrol *kcontrol, |
47 | struct snd_ctl_elem_value *ucontrol) |
48 | { |
49 | struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); |
50 | struct fsl_asrc *easrc = snd_soc_component_get_drvdata(c: comp); |
51 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
52 | struct soc_mreg_control *mc = |
53 | (struct soc_mreg_control *)kcontrol->private_value; |
54 | unsigned int regval = ucontrol->value.integer.value[0]; |
55 | |
56 | easrc_priv->bps_iec958[mc->regbase] = regval; |
57 | |
58 | return 0; |
59 | } |
60 | |
61 | static int fsl_easrc_iec958_get_bits(struct snd_kcontrol *kcontrol, |
62 | struct snd_ctl_elem_value *ucontrol) |
63 | { |
64 | struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); |
65 | struct fsl_asrc *easrc = snd_soc_component_get_drvdata(c: comp); |
66 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
67 | struct soc_mreg_control *mc = |
68 | (struct soc_mreg_control *)kcontrol->private_value; |
69 | |
70 | ucontrol->value.enumerated.item[0] = easrc_priv->bps_iec958[mc->regbase]; |
71 | |
72 | return 0; |
73 | } |
74 | |
75 | static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol, |
76 | struct snd_ctl_elem_value *ucontrol) |
77 | { |
78 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
79 | struct soc_mreg_control *mc = |
80 | (struct soc_mreg_control *)kcontrol->private_value; |
81 | unsigned int regval; |
82 | |
83 | regval = snd_soc_component_read(component, reg: mc->regbase); |
84 | |
85 | ucontrol->value.integer.value[0] = regval; |
86 | |
87 | return 0; |
88 | } |
89 | |
90 | static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol, |
91 | struct snd_ctl_elem_value *ucontrol) |
92 | { |
93 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
94 | struct soc_mreg_control *mc = |
95 | (struct soc_mreg_control *)kcontrol->private_value; |
96 | unsigned int regval = ucontrol->value.integer.value[0]; |
97 | int ret; |
98 | |
99 | ret = snd_soc_component_write(component, reg: mc->regbase, val: regval); |
100 | if (ret < 0) |
101 | return ret; |
102 | |
103 | return 0; |
104 | } |
105 | |
106 | #define SOC_SINGLE_REG_RW(xname, xreg) \ |
107 | { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \ |
108 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ |
109 | .info = snd_soc_info_xr_sx, .get = fsl_easrc_get_reg, \ |
110 | .put = fsl_easrc_set_reg, \ |
111 | .private_value = (unsigned long)&(struct soc_mreg_control) \ |
112 | { .regbase = xreg, .regcount = 1, .nbits = 32, \ |
113 | .invert = 0, .min = 0, .max = 0xffffffff, } } |
114 | |
115 | #define SOC_SINGLE_VAL_RW(xname, xreg) \ |
116 | { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = (xname), \ |
117 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ |
118 | .info = snd_soc_info_xr_sx, .get = fsl_easrc_iec958_get_bits, \ |
119 | .put = fsl_easrc_iec958_put_bits, \ |
120 | .private_value = (unsigned long)&(struct soc_mreg_control) \ |
121 | { .regbase = xreg, .regcount = 1, .nbits = 32, \ |
122 | .invert = 0, .min = 0, .max = 2, } } |
123 | |
124 | static const struct snd_kcontrol_new fsl_easrc_snd_controls[] = { |
125 | SOC_SINGLE("Context 0 Dither Switch" , REG_EASRC_COC(0), 0, 1, 0), |
126 | SOC_SINGLE("Context 1 Dither Switch" , REG_EASRC_COC(1), 0, 1, 0), |
127 | SOC_SINGLE("Context 2 Dither Switch" , REG_EASRC_COC(2), 0, 1, 0), |
128 | SOC_SINGLE("Context 3 Dither Switch" , REG_EASRC_COC(3), 0, 1, 0), |
129 | |
130 | SOC_SINGLE("Context 0 IEC958 Validity" , REG_EASRC_COC(0), 2, 1, 0), |
131 | SOC_SINGLE("Context 1 IEC958 Validity" , REG_EASRC_COC(1), 2, 1, 0), |
132 | SOC_SINGLE("Context 2 IEC958 Validity" , REG_EASRC_COC(2), 2, 1, 0), |
133 | SOC_SINGLE("Context 3 IEC958 Validity" , REG_EASRC_COC(3), 2, 1, 0), |
134 | |
135 | SOC_SINGLE_VAL_RW("Context 0 IEC958 Bits Per Sample" , 0), |
136 | SOC_SINGLE_VAL_RW("Context 1 IEC958 Bits Per Sample" , 1), |
137 | SOC_SINGLE_VAL_RW("Context 2 IEC958 Bits Per Sample" , 2), |
138 | SOC_SINGLE_VAL_RW("Context 3 IEC958 Bits Per Sample" , 3), |
139 | |
140 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS0" , REG_EASRC_CS0(0)), |
141 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS0" , REG_EASRC_CS0(1)), |
142 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS0" , REG_EASRC_CS0(2)), |
143 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS0" , REG_EASRC_CS0(3)), |
144 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS1" , REG_EASRC_CS1(0)), |
145 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS1" , REG_EASRC_CS1(1)), |
146 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS1" , REG_EASRC_CS1(2)), |
147 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS1" , REG_EASRC_CS1(3)), |
148 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS2" , REG_EASRC_CS2(0)), |
149 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS2" , REG_EASRC_CS2(1)), |
150 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS2" , REG_EASRC_CS2(2)), |
151 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS2" , REG_EASRC_CS2(3)), |
152 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS3" , REG_EASRC_CS3(0)), |
153 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS3" , REG_EASRC_CS3(1)), |
154 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS3" , REG_EASRC_CS3(2)), |
155 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS3" , REG_EASRC_CS3(3)), |
156 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS4" , REG_EASRC_CS4(0)), |
157 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS4" , REG_EASRC_CS4(1)), |
158 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS4" , REG_EASRC_CS4(2)), |
159 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS4" , REG_EASRC_CS4(3)), |
160 | SOC_SINGLE_REG_RW("Context 0 IEC958 CS5" , REG_EASRC_CS5(0)), |
161 | SOC_SINGLE_REG_RW("Context 1 IEC958 CS5" , REG_EASRC_CS5(1)), |
162 | SOC_SINGLE_REG_RW("Context 2 IEC958 CS5" , REG_EASRC_CS5(2)), |
163 | SOC_SINGLE_REG_RW("Context 3 IEC958 CS5" , REG_EASRC_CS5(3)), |
164 | }; |
165 | |
166 | /* |
167 | * fsl_easrc_set_rs_ratio |
168 | * |
169 | * According to the resample taps, calculate the resample ratio |
170 | * ratio = in_rate / out_rate |
171 | */ |
172 | static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair *ctx) |
173 | { |
174 | struct fsl_asrc *easrc = ctx->asrc; |
175 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
176 | struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; |
177 | unsigned int in_rate = ctx_priv->in_params.norm_rate; |
178 | unsigned int out_rate = ctx_priv->out_params.norm_rate; |
179 | unsigned int frac_bits; |
180 | u64 val; |
181 | u32 *r; |
182 | |
183 | switch (easrc_priv->rs_num_taps) { |
184 | case EASRC_RS_32_TAPS: |
185 | /* integer bits = 5; */ |
186 | frac_bits = 39; |
187 | break; |
188 | case EASRC_RS_64_TAPS: |
189 | /* integer bits = 6; */ |
190 | frac_bits = 38; |
191 | break; |
192 | case EASRC_RS_128_TAPS: |
193 | /* integer bits = 7; */ |
194 | frac_bits = 37; |
195 | break; |
196 | default: |
197 | return -EINVAL; |
198 | } |
199 | |
200 | val = (u64)in_rate << frac_bits; |
201 | do_div(val, out_rate); |
202 | r = (uint32_t *)&val; |
203 | |
204 | if (r[1] & 0xFFFFF000) { |
205 | dev_err(&easrc->pdev->dev, "ratio exceed range\n" ); |
206 | return -EINVAL; |
207 | } |
208 | |
209 | regmap_write(map: easrc->regmap, REG_EASRC_RRL(ctx->index), |
210 | EASRC_RRL_RS_RL(r[0])); |
211 | regmap_write(map: easrc->regmap, REG_EASRC_RRH(ctx->index), |
212 | EASRC_RRH_RS_RH(r[1])); |
213 | |
214 | return 0; |
215 | } |
216 | |
217 | /* Normalize input and output sample rates */ |
218 | static void fsl_easrc_normalize_rates(struct fsl_asrc_pair *ctx) |
219 | { |
220 | struct fsl_easrc_ctx_priv *ctx_priv; |
221 | int a, b; |
222 | |
223 | if (!ctx) |
224 | return; |
225 | |
226 | ctx_priv = ctx->private; |
227 | |
228 | a = ctx_priv->in_params.sample_rate; |
229 | b = ctx_priv->out_params.sample_rate; |
230 | |
231 | a = gcd(a, b); |
232 | |
233 | /* Divide by gcd to normalize the rate */ |
234 | ctx_priv->in_params.norm_rate = ctx_priv->in_params.sample_rate / a; |
235 | ctx_priv->out_params.norm_rate = ctx_priv->out_params.sample_rate / a; |
236 | } |
237 | |
238 | /* Resets the pointer of the coeff memory pointers */ |
239 | static int fsl_easrc_coeff_mem_ptr_reset(struct fsl_asrc *easrc, |
240 | unsigned int ctx_id, int mem_type) |
241 | { |
242 | struct device *dev; |
243 | u32 reg, mask, val; |
244 | |
245 | if (!easrc) |
246 | return -ENODEV; |
247 | |
248 | dev = &easrc->pdev->dev; |
249 | |
250 | switch (mem_type) { |
251 | case EASRC_PF_COEFF_MEM: |
252 | /* This resets the prefilter memory pointer addr */ |
253 | if (ctx_id >= EASRC_CTX_MAX_NUM) { |
254 | dev_err(dev, "Invalid context id[%d]\n" , ctx_id); |
255 | return -EINVAL; |
256 | } |
257 | |
258 | reg = REG_EASRC_CCE1(ctx_id); |
259 | mask = EASRC_CCE1_COEF_MEM_RST_MASK; |
260 | val = EASRC_CCE1_COEF_MEM_RST; |
261 | break; |
262 | case EASRC_RS_COEFF_MEM: |
263 | /* This resets the resampling memory pointer addr */ |
264 | reg = REG_EASRC_CRCC; |
265 | mask = EASRC_CRCC_RS_CPR_MASK; |
266 | val = EASRC_CRCC_RS_CPR; |
267 | break; |
268 | default: |
269 | dev_err(dev, "Unknown memory type\n" ); |
270 | return -EINVAL; |
271 | } |
272 | |
273 | /* |
274 | * To reset the write pointer back to zero, the register field |
275 | * ASRC_CTX_CTRL_EXT1x[PF_COEFF_MEM_RST] can be toggled from |
276 | * 0x0 to 0x1 to 0x0. |
277 | */ |
278 | regmap_update_bits(map: easrc->regmap, reg, mask, val: 0); |
279 | regmap_update_bits(map: easrc->regmap, reg, mask, val); |
280 | regmap_update_bits(map: easrc->regmap, reg, mask, val: 0); |
281 | |
282 | return 0; |
283 | } |
284 | |
285 | static inline uint32_t bits_taps_to_val(unsigned int t) |
286 | { |
287 | switch (t) { |
288 | case EASRC_RS_32_TAPS: |
289 | return 32; |
290 | case EASRC_RS_64_TAPS: |
291 | return 64; |
292 | case EASRC_RS_128_TAPS: |
293 | return 128; |
294 | } |
295 | |
296 | return 0; |
297 | } |
298 | |
299 | static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) |
300 | { |
301 | struct device *dev = &easrc->pdev->dev; |
302 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
303 | struct asrc_firmware_hdr *hdr = easrc_priv->firmware_hdr; |
304 | struct interp_params *interp = easrc_priv->interp; |
305 | struct interp_params *selected_interp = NULL; |
306 | unsigned int num_coeff; |
307 | unsigned int i; |
308 | u64 *coef; |
309 | u32 *r; |
310 | int ret; |
311 | |
312 | if (!hdr) { |
313 | dev_err(dev, "firmware not loaded!\n" ); |
314 | return -ENODEV; |
315 | } |
316 | |
317 | for (i = 0; i < hdr->interp_scen; i++) { |
318 | if ((interp[i].num_taps - 1) != |
319 | bits_taps_to_val(t: easrc_priv->rs_num_taps)) |
320 | continue; |
321 | |
322 | coef = interp[i].coeff; |
323 | selected_interp = &interp[i]; |
324 | dev_dbg(dev, "Selected interp_filter: %u taps - %u phases\n" , |
325 | selected_interp->num_taps, |
326 | selected_interp->num_phases); |
327 | break; |
328 | } |
329 | |
330 | if (!selected_interp) { |
331 | dev_err(dev, "failed to get interpreter configuration\n" ); |
332 | return -EINVAL; |
333 | } |
334 | |
335 | /* |
336 | * RS_LOW - first half of center tap of the sinc function |
337 | * RS_HIGH - second half of center tap of the sinc function |
338 | * This is due to the fact the resampling function must be |
339 | * symetrical - i.e. odd number of taps |
340 | */ |
341 | r = (uint32_t *)&selected_interp->center_tap; |
342 | regmap_write(map: easrc->regmap, REG_EASRC_RCTCL, EASRC_RCTCL_RS_CL(r[0])); |
343 | regmap_write(map: easrc->regmap, REG_EASRC_RCTCH, EASRC_RCTCH_RS_CH(r[1])); |
344 | |
345 | /* |
346 | * Write Number of Resampling Coefficient Taps |
347 | * 00b - 32-Tap Resampling Filter |
348 | * 01b - 64-Tap Resampling Filter |
349 | * 10b - 128-Tap Resampling Filter |
350 | * 11b - N/A |
351 | */ |
352 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CRCC, |
353 | EASRC_CRCC_RS_TAPS_MASK, |
354 | EASRC_CRCC_RS_TAPS(easrc_priv->rs_num_taps)); |
355 | |
356 | /* Reset prefilter coefficient pointer back to 0 */ |
357 | ret = fsl_easrc_coeff_mem_ptr_reset(easrc, ctx_id: 0, EASRC_RS_COEFF_MEM); |
358 | if (ret) |
359 | return ret; |
360 | |
361 | /* |
362 | * When the filter is programmed to run in: |
363 | * 32-tap mode, 16-taps, 128-phases 4-coefficients per phase |
364 | * 64-tap mode, 32-taps, 64-phases 4-coefficients per phase |
365 | * 128-tap mode, 64-taps, 32-phases 4-coefficients per phase |
366 | * This means the number of writes is constant no matter |
367 | * the mode we are using |
368 | */ |
369 | num_coeff = 16 * 128 * 4; |
370 | |
371 | for (i = 0; i < num_coeff; i++) { |
372 | r = (uint32_t *)&coef[i]; |
373 | regmap_write(map: easrc->regmap, REG_EASRC_CRCM, |
374 | EASRC_CRCM_RS_CWD(r[0])); |
375 | regmap_write(map: easrc->regmap, REG_EASRC_CRCM, |
376 | EASRC_CRCM_RS_CWD(r[1])); |
377 | } |
378 | |
379 | return 0; |
380 | } |
381 | |
382 | /** |
383 | * fsl_easrc_normalize_filter - Scale filter coefficients (64 bits float) |
384 | * For input float32 normalized range (1.0,-1.0) -> output int[16,24,32]: |
385 | * scale it by multiplying filter coefficients by 2^31 |
386 | * For input int[16, 24, 32] -> output float32 |
387 | * scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31 |
388 | * input: |
389 | * @easrc: Structure pointer of fsl_asrc |
390 | * @infilter : Pointer to non-scaled input filter |
391 | * @shift: The multiply factor |
392 | * output: |
393 | * @outfilter: scaled filter |
394 | */ |
395 | static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc, |
396 | u64 *infilter, |
397 | u64 *outfilter, |
398 | int shift) |
399 | { |
400 | struct device *dev = &easrc->pdev->dev; |
401 | u64 coef = *infilter; |
402 | s64 exp = (coef & 0x7ff0000000000000ll) >> 52; |
403 | u64 outcoef; |
404 | |
405 | /* |
406 | * If exponent is zero (value == 0), or 7ff (value == NaNs) |
407 | * dont touch the content |
408 | */ |
409 | if (exp == 0 || exp == 0x7ff) { |
410 | *outfilter = coef; |
411 | return 0; |
412 | } |
413 | |
414 | /* coef * 2^shift ==> exp + shift */ |
415 | exp += shift; |
416 | |
417 | if ((shift > 0 && exp >= 0x7ff) || (shift < 0 && exp <= 0)) { |
418 | dev_err(dev, "coef out of range\n" ); |
419 | return -EINVAL; |
420 | } |
421 | |
422 | outcoef = (u64)(coef & 0x800FFFFFFFFFFFFFll) + ((u64)exp << 52); |
423 | *outfilter = outcoef; |
424 | |
425 | return 0; |
426 | } |
427 | |
428 | static int fsl_easrc_write_pf_coeff_mem(struct fsl_asrc *easrc, int ctx_id, |
429 | u64 *coef, int n_taps, int shift) |
430 | { |
431 | struct device *dev = &easrc->pdev->dev; |
432 | int ret = 0; |
433 | int i; |
434 | u32 *r; |
435 | u64 tmp; |
436 | |
437 | /* If STx_NUM_TAPS is set to 0x0 then return */ |
438 | if (!n_taps) |
439 | return 0; |
440 | |
441 | if (!coef) { |
442 | dev_err(dev, "coef table is NULL\n" ); |
443 | return -EINVAL; |
444 | } |
445 | |
446 | /* |
447 | * When switching between stages, the address pointer |
448 | * should be reset back to 0x0 before performing a write |
449 | */ |
450 | ret = fsl_easrc_coeff_mem_ptr_reset(easrc, ctx_id, EASRC_PF_COEFF_MEM); |
451 | if (ret) |
452 | return ret; |
453 | |
454 | for (i = 0; i < (n_taps + 1) / 2; i++) { |
455 | ret = fsl_easrc_normalize_filter(easrc, infilter: &coef[i], outfilter: &tmp, shift); |
456 | if (ret) |
457 | return ret; |
458 | |
459 | r = (uint32_t *)&tmp; |
460 | regmap_write(map: easrc->regmap, REG_EASRC_PCF(ctx_id), |
461 | EASRC_PCF_CD(r[0])); |
462 | regmap_write(map: easrc->regmap, REG_EASRC_PCF(ctx_id), |
463 | EASRC_PCF_CD(r[1])); |
464 | } |
465 | |
466 | return 0; |
467 | } |
468 | |
469 | static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc, |
470 | unsigned int ctx_id) |
471 | { |
472 | struct prefil_params *prefil, *selected_prefil = NULL; |
473 | struct fsl_easrc_ctx_priv *ctx_priv; |
474 | struct fsl_easrc_priv *easrc_priv; |
475 | struct asrc_firmware_hdr *hdr; |
476 | struct fsl_asrc_pair *ctx; |
477 | struct device *dev; |
478 | u32 inrate, outrate, offset = 0; |
479 | u32 in_s_rate, out_s_rate; |
480 | snd_pcm_format_t in_s_fmt, out_s_fmt; |
481 | int ret, i; |
482 | |
483 | if (!easrc) |
484 | return -ENODEV; |
485 | |
486 | dev = &easrc->pdev->dev; |
487 | |
488 | if (ctx_id >= EASRC_CTX_MAX_NUM) { |
489 | dev_err(dev, "Invalid context id[%d]\n" , ctx_id); |
490 | return -EINVAL; |
491 | } |
492 | |
493 | easrc_priv = easrc->private; |
494 | |
495 | ctx = easrc->pair[ctx_id]; |
496 | ctx_priv = ctx->private; |
497 | |
498 | in_s_rate = ctx_priv->in_params.sample_rate; |
499 | out_s_rate = ctx_priv->out_params.sample_rate; |
500 | in_s_fmt = ctx_priv->in_params.sample_format; |
501 | out_s_fmt = ctx_priv->out_params.sample_format; |
502 | |
503 | ctx_priv->in_filled_sample = bits_taps_to_val(t: easrc_priv->rs_num_taps) / 2; |
504 | ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * out_s_rate / in_s_rate; |
505 | |
506 | ctx_priv->st1_num_taps = 0; |
507 | ctx_priv->st2_num_taps = 0; |
508 | |
509 | regmap_write(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), val: 0); |
510 | regmap_write(map: easrc->regmap, REG_EASRC_CCE2(ctx_id), val: 0); |
511 | |
512 | /* |
513 | * The audio float point data range is (-1, 1), the asrc would output |
514 | * all zero for float point input and integer output case, that is to |
515 | * drop the fractional part of the data directly. |
516 | * |
517 | * In order to support float to int conversion or int to float |
518 | * conversion we need to do special operation on the coefficient to |
519 | * enlarge/reduce the data to the expected range. |
520 | * |
521 | * For float to int case: |
522 | * Up sampling: |
523 | * 1. Create a 1 tap filter with center tap (only tap) of 2^31 |
524 | * in 64 bits floating point. |
525 | * double value = (double)(((uint64_t)1) << 31) |
526 | * 2. Program 1 tap prefilter with center tap above. |
527 | * |
528 | * Down sampling, |
529 | * 1. If the filter is single stage filter, add "shift" to the exponent |
530 | * of stage 1 coefficients. |
531 | * 2. If the filter is two stage filter , add "shift" to the exponent |
532 | * of stage 2 coefficients. |
533 | * |
534 | * The "shift" is 31, same for int16, int24, int32 case. |
535 | * |
536 | * For int to float case: |
537 | * Up sampling: |
538 | * 1. Create a 1 tap filter with center tap (only tap) of 2^-31 |
539 | * in 64 bits floating point. |
540 | * 2. Program 1 tap prefilter with center tap above. |
541 | * |
542 | * Down sampling, |
543 | * 1. If the filter is single stage filter, subtract "shift" to the |
544 | * exponent of stage 1 coefficients. |
545 | * 2. If the filter is two stage filter , subtract "shift" to the |
546 | * exponent of stage 2 coefficients. |
547 | * |
548 | * The "shift" is 15,23,31, different for int16, int24, int32 case. |
549 | * |
550 | */ |
551 | if (out_s_rate >= in_s_rate) { |
552 | if (out_s_rate == in_s_rate) |
553 | regmap_update_bits(map: easrc->regmap, |
554 | REG_EASRC_CCE1(ctx_id), |
555 | EASRC_CCE1_RS_BYPASS_MASK, |
556 | EASRC_CCE1_RS_BYPASS); |
557 | |
558 | ctx_priv->st1_num_taps = 1; |
559 | ctx_priv->st1_coeff = &easrc_priv->const_coeff; |
560 | ctx_priv->st1_num_exp = 1; |
561 | ctx_priv->st2_num_taps = 0; |
562 | |
563 | if (in_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE && |
564 | out_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE) |
565 | ctx_priv->st1_addexp = 31; |
566 | else if (in_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE && |
567 | out_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE) |
568 | ctx_priv->st1_addexp -= ctx_priv->in_params.fmt.addexp; |
569 | } else { |
570 | inrate = ctx_priv->in_params.norm_rate; |
571 | outrate = ctx_priv->out_params.norm_rate; |
572 | |
573 | hdr = easrc_priv->firmware_hdr; |
574 | prefil = easrc_priv->prefil; |
575 | |
576 | for (i = 0; i < hdr->prefil_scen; i++) { |
577 | if (inrate == prefil[i].insr && |
578 | outrate == prefil[i].outsr) { |
579 | selected_prefil = &prefil[i]; |
580 | dev_dbg(dev, "Selected prefilter: %u insr, %u outsr, %u st1_taps, %u st2_taps\n" , |
581 | selected_prefil->insr, |
582 | selected_prefil->outsr, |
583 | selected_prefil->st1_taps, |
584 | selected_prefil->st2_taps); |
585 | break; |
586 | } |
587 | } |
588 | |
589 | if (!selected_prefil) { |
590 | dev_err(dev, "Conversion from in ratio %u(%u) to out ratio %u(%u) is not supported\n" , |
591 | in_s_rate, inrate, |
592 | out_s_rate, outrate); |
593 | return -EINVAL; |
594 | } |
595 | |
596 | /* |
597 | * In prefilter coeff array, first st1_num_taps represent the |
598 | * stage1 prefilter coefficients followed by next st2_num_taps |
599 | * representing stage 2 coefficients |
600 | */ |
601 | ctx_priv->st1_num_taps = selected_prefil->st1_taps; |
602 | ctx_priv->st1_coeff = selected_prefil->coeff; |
603 | ctx_priv->st1_num_exp = selected_prefil->st1_exp; |
604 | |
605 | offset = ((selected_prefil->st1_taps + 1) / 2); |
606 | ctx_priv->st2_num_taps = selected_prefil->st2_taps; |
607 | ctx_priv->st2_coeff = selected_prefil->coeff + offset; |
608 | |
609 | if (in_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE && |
610 | out_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE) { |
611 | /* only change stage2 coefficient for 2 stage case */ |
612 | if (ctx_priv->st2_num_taps > 0) |
613 | ctx_priv->st2_addexp = 31; |
614 | else |
615 | ctx_priv->st1_addexp = 31; |
616 | } else if (in_s_fmt != SNDRV_PCM_FORMAT_FLOAT_LE && |
617 | out_s_fmt == SNDRV_PCM_FORMAT_FLOAT_LE) { |
618 | if (ctx_priv->st2_num_taps > 0) |
619 | ctx_priv->st2_addexp -= ctx_priv->in_params.fmt.addexp; |
620 | else |
621 | ctx_priv->st1_addexp -= ctx_priv->in_params.fmt.addexp; |
622 | } |
623 | } |
624 | |
625 | ctx_priv->in_filled_sample += (ctx_priv->st1_num_taps / 2) * ctx_priv->st1_num_exp + |
626 | ctx_priv->st2_num_taps / 2; |
627 | ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * out_s_rate / in_s_rate; |
628 | |
629 | if (ctx_priv->in_filled_sample * out_s_rate % in_s_rate != 0) |
630 | ctx_priv->out_missed_sample += 1; |
631 | /* |
632 | * To modify the value of a prefilter coefficient, the user must |
633 | * perform a write to the register ASRC_PRE_COEFF_FIFOn[COEFF_DATA] |
634 | * while the respective context RUN_EN bit is set to 0b0 |
635 | */ |
636 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx_id), |
637 | EASRC_CC_EN_MASK, val: 0); |
638 | |
639 | if (ctx_priv->st1_num_taps > EASRC_MAX_PF_TAPS) { |
640 | dev_err(dev, "ST1 taps [%d] mus be lower than %d\n" , |
641 | ctx_priv->st1_num_taps, EASRC_MAX_PF_TAPS); |
642 | ret = -EINVAL; |
643 | goto ctx_error; |
644 | } |
645 | |
646 | /* Update ctx ST1_NUM_TAPS in Context Control Extended 2 register */ |
647 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE2(ctx_id), |
648 | EASRC_CCE2_ST1_TAPS_MASK, |
649 | EASRC_CCE2_ST1_TAPS(ctx_priv->st1_num_taps - 1)); |
650 | |
651 | /* Prefilter Coefficient Write Select to write in ST1 coeff */ |
652 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
653 | EASRC_CCE1_COEF_WS_MASK, |
654 | EASRC_PF_ST1_COEFF_WR << EASRC_CCE1_COEF_WS_SHIFT); |
655 | |
656 | ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id, |
657 | coef: ctx_priv->st1_coeff, |
658 | n_taps: ctx_priv->st1_num_taps, |
659 | shift: ctx_priv->st1_addexp); |
660 | if (ret) |
661 | goto ctx_error; |
662 | |
663 | if (ctx_priv->st2_num_taps > 0) { |
664 | if (ctx_priv->st2_num_taps + ctx_priv->st1_num_taps > EASRC_MAX_PF_TAPS) { |
665 | dev_err(dev, "ST2 taps [%d] mus be lower than %d\n" , |
666 | ctx_priv->st2_num_taps, EASRC_MAX_PF_TAPS); |
667 | ret = -EINVAL; |
668 | goto ctx_error; |
669 | } |
670 | |
671 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
672 | EASRC_CCE1_PF_TSEN_MASK, |
673 | EASRC_CCE1_PF_TSEN); |
674 | /* |
675 | * Enable prefilter stage1 writeback floating point |
676 | * which is used for FLOAT_LE case |
677 | */ |
678 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
679 | EASRC_CCE1_PF_ST1_WBFP_MASK, |
680 | EASRC_CCE1_PF_ST1_WBFP); |
681 | |
682 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
683 | EASRC_CCE1_PF_EXP_MASK, |
684 | EASRC_CCE1_PF_EXP(ctx_priv->st1_num_exp - 1)); |
685 | |
686 | /* Update ctx ST2_NUM_TAPS in Context Control Extended 2 reg */ |
687 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE2(ctx_id), |
688 | EASRC_CCE2_ST2_TAPS_MASK, |
689 | EASRC_CCE2_ST2_TAPS(ctx_priv->st2_num_taps - 1)); |
690 | |
691 | /* Prefilter Coefficient Write Select to write in ST2 coeff */ |
692 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
693 | EASRC_CCE1_COEF_WS_MASK, |
694 | EASRC_PF_ST2_COEFF_WR << EASRC_CCE1_COEF_WS_SHIFT); |
695 | |
696 | ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id, |
697 | coef: ctx_priv->st2_coeff, |
698 | n_taps: ctx_priv->st2_num_taps, |
699 | shift: ctx_priv->st2_addexp); |
700 | if (ret) |
701 | goto ctx_error; |
702 | } |
703 | |
704 | return 0; |
705 | |
706 | ctx_error: |
707 | return ret; |
708 | } |
709 | |
710 | static int fsl_easrc_max_ch_for_slot(struct fsl_asrc_pair *ctx, |
711 | struct fsl_easrc_slot *slot) |
712 | { |
713 | struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; |
714 | int st1_mem_alloc = 0, st2_mem_alloc = 0; |
715 | int pf_mem_alloc = 0; |
716 | int max_channels = 8 - slot->num_channel; |
717 | int channels = 0; |
718 | |
719 | if (ctx_priv->st1_num_taps > 0) { |
720 | if (ctx_priv->st2_num_taps > 0) |
721 | st1_mem_alloc = |
722 | (ctx_priv->st1_num_taps - 1) * ctx_priv->st1_num_exp + 1; |
723 | else |
724 | st1_mem_alloc = ctx_priv->st1_num_taps; |
725 | } |
726 | |
727 | if (ctx_priv->st2_num_taps > 0) |
728 | st2_mem_alloc = ctx_priv->st2_num_taps; |
729 | |
730 | pf_mem_alloc = st1_mem_alloc + st2_mem_alloc; |
731 | |
732 | if (pf_mem_alloc != 0) |
733 | channels = (6144 - slot->pf_mem_used) / pf_mem_alloc; |
734 | else |
735 | channels = 8; |
736 | |
737 | if (channels < max_channels) |
738 | max_channels = channels; |
739 | |
740 | return max_channels; |
741 | } |
742 | |
743 | static int fsl_easrc_config_one_slot(struct fsl_asrc_pair *ctx, |
744 | struct fsl_easrc_slot *slot, |
745 | unsigned int slot_ctx_idx, |
746 | unsigned int *req_channels, |
747 | unsigned int *start_channel, |
748 | unsigned int *avail_channel) |
749 | { |
750 | struct fsl_asrc *easrc = ctx->asrc; |
751 | struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; |
752 | int st1_chanxexp, st1_mem_alloc = 0, st2_mem_alloc; |
753 | unsigned int reg0, reg1, reg2, reg3; |
754 | unsigned int addr; |
755 | |
756 | if (slot->slot_index == 0) { |
757 | reg0 = REG_EASRC_DPCS0R0(slot_ctx_idx); |
758 | reg1 = REG_EASRC_DPCS0R1(slot_ctx_idx); |
759 | reg2 = REG_EASRC_DPCS0R2(slot_ctx_idx); |
760 | reg3 = REG_EASRC_DPCS0R3(slot_ctx_idx); |
761 | } else { |
762 | reg0 = REG_EASRC_DPCS1R0(slot_ctx_idx); |
763 | reg1 = REG_EASRC_DPCS1R1(slot_ctx_idx); |
764 | reg2 = REG_EASRC_DPCS1R2(slot_ctx_idx); |
765 | reg3 = REG_EASRC_DPCS1R3(slot_ctx_idx); |
766 | } |
767 | |
768 | if (*req_channels <= *avail_channel) { |
769 | slot->num_channel = *req_channels; |
770 | *req_channels = 0; |
771 | } else { |
772 | slot->num_channel = *avail_channel; |
773 | *req_channels -= *avail_channel; |
774 | } |
775 | |
776 | slot->min_channel = *start_channel; |
777 | slot->max_channel = *start_channel + slot->num_channel - 1; |
778 | slot->ctx_index = ctx->index; |
779 | slot->busy = true; |
780 | *start_channel += slot->num_channel; |
781 | |
782 | regmap_update_bits(map: easrc->regmap, reg: reg0, |
783 | EASRC_DPCS0R0_MAXCH_MASK, |
784 | EASRC_DPCS0R0_MAXCH(slot->max_channel)); |
785 | |
786 | regmap_update_bits(map: easrc->regmap, reg: reg0, |
787 | EASRC_DPCS0R0_MINCH_MASK, |
788 | EASRC_DPCS0R0_MINCH(slot->min_channel)); |
789 | |
790 | regmap_update_bits(map: easrc->regmap, reg: reg0, |
791 | EASRC_DPCS0R0_NUMCH_MASK, |
792 | EASRC_DPCS0R0_NUMCH(slot->num_channel - 1)); |
793 | |
794 | regmap_update_bits(map: easrc->regmap, reg: reg0, |
795 | EASRC_DPCS0R0_CTXNUM_MASK, |
796 | EASRC_DPCS0R0_CTXNUM(slot->ctx_index)); |
797 | |
798 | if (ctx_priv->st1_num_taps > 0) { |
799 | if (ctx_priv->st2_num_taps > 0) |
800 | st1_mem_alloc = |
801 | (ctx_priv->st1_num_taps - 1) * slot->num_channel * |
802 | ctx_priv->st1_num_exp + slot->num_channel; |
803 | else |
804 | st1_mem_alloc = ctx_priv->st1_num_taps * slot->num_channel; |
805 | |
806 | slot->pf_mem_used = st1_mem_alloc; |
807 | regmap_update_bits(map: easrc->regmap, reg: reg2, |
808 | EASRC_DPCS0R2_ST1_MA_MASK, |
809 | EASRC_DPCS0R2_ST1_MA(st1_mem_alloc)); |
810 | |
811 | if (slot->slot_index == 1) |
812 | addr = PREFILTER_MEM_LEN - st1_mem_alloc; |
813 | else |
814 | addr = 0; |
815 | |
816 | regmap_update_bits(map: easrc->regmap, reg: reg2, |
817 | EASRC_DPCS0R2_ST1_SA_MASK, |
818 | EASRC_DPCS0R2_ST1_SA(addr)); |
819 | } |
820 | |
821 | if (ctx_priv->st2_num_taps > 0) { |
822 | st1_chanxexp = slot->num_channel * (ctx_priv->st1_num_exp - 1); |
823 | |
824 | regmap_update_bits(map: easrc->regmap, reg: reg1, |
825 | EASRC_DPCS0R1_ST1_EXP_MASK, |
826 | EASRC_DPCS0R1_ST1_EXP(st1_chanxexp)); |
827 | |
828 | st2_mem_alloc = slot->num_channel * ctx_priv->st2_num_taps; |
829 | slot->pf_mem_used += st2_mem_alloc; |
830 | regmap_update_bits(map: easrc->regmap, reg: reg3, |
831 | EASRC_DPCS0R3_ST2_MA_MASK, |
832 | EASRC_DPCS0R3_ST2_MA(st2_mem_alloc)); |
833 | |
834 | if (slot->slot_index == 1) |
835 | addr = PREFILTER_MEM_LEN - st1_mem_alloc - st2_mem_alloc; |
836 | else |
837 | addr = st1_mem_alloc; |
838 | |
839 | regmap_update_bits(map: easrc->regmap, reg: reg3, |
840 | EASRC_DPCS0R3_ST2_SA_MASK, |
841 | EASRC_DPCS0R3_ST2_SA(addr)); |
842 | } |
843 | |
844 | regmap_update_bits(map: easrc->regmap, reg: reg0, |
845 | EASRC_DPCS0R0_EN_MASK, EASRC_DPCS0R0_EN); |
846 | |
847 | return 0; |
848 | } |
849 | |
850 | /* |
851 | * fsl_easrc_config_slot |
852 | * |
853 | * A single context can be split amongst any of the 4 context processing pipes |
854 | * in the design. |
855 | * The total number of channels consumed within the context processor must be |
856 | * less than or equal to 8. if a single context is configured to contain more |
857 | * than 8 channels then it must be distributed across multiple context |
858 | * processing pipe slots. |
859 | * |
860 | */ |
861 | static int fsl_easrc_config_slot(struct fsl_asrc *easrc, unsigned int ctx_id) |
862 | { |
863 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
864 | struct fsl_asrc_pair *ctx = easrc->pair[ctx_id]; |
865 | int req_channels = ctx->channels; |
866 | int start_channel = 0, avail_channel; |
867 | struct fsl_easrc_slot *slot0, *slot1; |
868 | struct fsl_easrc_slot *slota, *slotb; |
869 | int i, ret; |
870 | |
871 | if (req_channels <= 0) |
872 | return -EINVAL; |
873 | |
874 | for (i = 0; i < EASRC_CTX_MAX_NUM; i++) { |
875 | slot0 = &easrc_priv->slot[i][0]; |
876 | slot1 = &easrc_priv->slot[i][1]; |
877 | |
878 | if (slot0->busy && slot1->busy) { |
879 | continue; |
880 | } else if ((slot0->busy && slot0->ctx_index == ctx->index) || |
881 | (slot1->busy && slot1->ctx_index == ctx->index)) { |
882 | continue; |
883 | } else if (!slot0->busy) { |
884 | slota = slot0; |
885 | slotb = slot1; |
886 | slota->slot_index = 0; |
887 | } else if (!slot1->busy) { |
888 | slota = slot1; |
889 | slotb = slot0; |
890 | slota->slot_index = 1; |
891 | } |
892 | |
893 | if (!slota || !slotb) |
894 | continue; |
895 | |
896 | avail_channel = fsl_easrc_max_ch_for_slot(ctx, slot: slotb); |
897 | if (avail_channel <= 0) |
898 | continue; |
899 | |
900 | ret = fsl_easrc_config_one_slot(ctx, slot: slota, slot_ctx_idx: i, req_channels: &req_channels, |
901 | start_channel: &start_channel, avail_channel: &avail_channel); |
902 | if (ret) |
903 | return ret; |
904 | |
905 | if (req_channels > 0) |
906 | continue; |
907 | else |
908 | break; |
909 | } |
910 | |
911 | if (req_channels > 0) { |
912 | dev_err(&easrc->pdev->dev, "no avail slot.\n" ); |
913 | return -EINVAL; |
914 | } |
915 | |
916 | return 0; |
917 | } |
918 | |
919 | /* |
920 | * fsl_easrc_release_slot |
921 | * |
922 | * Clear the slot configuration |
923 | */ |
924 | static int fsl_easrc_release_slot(struct fsl_asrc *easrc, unsigned int ctx_id) |
925 | { |
926 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
927 | struct fsl_asrc_pair *ctx = easrc->pair[ctx_id]; |
928 | int i; |
929 | |
930 | for (i = 0; i < EASRC_CTX_MAX_NUM; i++) { |
931 | if (easrc_priv->slot[i][0].busy && |
932 | easrc_priv->slot[i][0].ctx_index == ctx->index) { |
933 | easrc_priv->slot[i][0].busy = false; |
934 | easrc_priv->slot[i][0].num_channel = 0; |
935 | easrc_priv->slot[i][0].pf_mem_used = 0; |
936 | /* set registers */ |
937 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS0R0(i), val: 0); |
938 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS0R1(i), val: 0); |
939 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS0R2(i), val: 0); |
940 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS0R3(i), val: 0); |
941 | } |
942 | |
943 | if (easrc_priv->slot[i][1].busy && |
944 | easrc_priv->slot[i][1].ctx_index == ctx->index) { |
945 | easrc_priv->slot[i][1].busy = false; |
946 | easrc_priv->slot[i][1].num_channel = 0; |
947 | easrc_priv->slot[i][1].pf_mem_used = 0; |
948 | /* set registers */ |
949 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS1R0(i), val: 0); |
950 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS1R1(i), val: 0); |
951 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS1R2(i), val: 0); |
952 | regmap_write(map: easrc->regmap, REG_EASRC_DPCS1R3(i), val: 0); |
953 | } |
954 | } |
955 | |
956 | return 0; |
957 | } |
958 | |
959 | /* |
960 | * fsl_easrc_config_context |
961 | * |
962 | * Configure the register relate with context. |
963 | */ |
964 | static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id) |
965 | { |
966 | struct fsl_easrc_ctx_priv *ctx_priv; |
967 | struct fsl_asrc_pair *ctx; |
968 | struct device *dev; |
969 | unsigned long lock_flags; |
970 | int ret; |
971 | |
972 | if (!easrc) |
973 | return -ENODEV; |
974 | |
975 | dev = &easrc->pdev->dev; |
976 | |
977 | if (ctx_id >= EASRC_CTX_MAX_NUM) { |
978 | dev_err(dev, "Invalid context id[%d]\n" , ctx_id); |
979 | return -EINVAL; |
980 | } |
981 | |
982 | ctx = easrc->pair[ctx_id]; |
983 | |
984 | ctx_priv = ctx->private; |
985 | |
986 | fsl_easrc_normalize_rates(ctx); |
987 | |
988 | ret = fsl_easrc_set_rs_ratio(ctx); |
989 | if (ret) |
990 | return ret; |
991 | |
992 | /* Initialize the context coeficients */ |
993 | ret = fsl_easrc_prefilter_config(easrc, ctx_id: ctx->index); |
994 | if (ret) |
995 | return ret; |
996 | |
997 | spin_lock_irqsave(&easrc->lock, lock_flags); |
998 | ret = fsl_easrc_config_slot(easrc, ctx_id: ctx->index); |
999 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
1000 | if (ret) |
1001 | return ret; |
1002 | |
1003 | /* |
1004 | * Both prefilter and resampling filters can use following |
1005 | * initialization modes: |
1006 | * 2 - zero-fil mode |
1007 | * 1 - replication mode |
1008 | * 0 - software control |
1009 | */ |
1010 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
1011 | EASRC_CCE1_RS_INIT_MASK, |
1012 | EASRC_CCE1_RS_INIT(ctx_priv->rs_init_mode)); |
1013 | |
1014 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CCE1(ctx_id), |
1015 | EASRC_CCE1_PF_INIT_MASK, |
1016 | EASRC_CCE1_PF_INIT(ctx_priv->pf_init_mode)); |
1017 | |
1018 | /* |
1019 | * Context Input FIFO Watermark |
1020 | * DMA request is generated when input FIFO < FIFO_WTMK |
1021 | */ |
1022 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx_id), |
1023 | EASRC_CC_FIFO_WTMK_MASK, |
1024 | EASRC_CC_FIFO_WTMK(ctx_priv->in_params.fifo_wtmk)); |
1025 | |
1026 | /* |
1027 | * Context Output FIFO Watermark |
1028 | * DMA request is generated when output FIFO > FIFO_WTMK |
1029 | * So we set fifo_wtmk -1 to register. |
1030 | */ |
1031 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx_id), |
1032 | EASRC_COC_FIFO_WTMK_MASK, |
1033 | EASRC_COC_FIFO_WTMK(ctx_priv->out_params.fifo_wtmk - 1)); |
1034 | |
1035 | /* Number of channels */ |
1036 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx_id), |
1037 | EASRC_CC_CHEN_MASK, |
1038 | EASRC_CC_CHEN(ctx->channels - 1)); |
1039 | return 0; |
1040 | } |
1041 | |
1042 | static int fsl_easrc_process_format(struct fsl_asrc_pair *ctx, |
1043 | struct fsl_easrc_data_fmt *fmt, |
1044 | snd_pcm_format_t raw_fmt) |
1045 | { |
1046 | struct fsl_asrc *easrc = ctx->asrc; |
1047 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
1048 | int ret; |
1049 | |
1050 | if (!fmt) |
1051 | return -EINVAL; |
1052 | |
1053 | /* |
1054 | * Context Input Floating Point Format |
1055 | * 0 - Integer Format |
1056 | * 1 - Single Precision FP Format |
1057 | */ |
1058 | fmt->floating_point = !snd_pcm_format_linear(format: raw_fmt); |
1059 | fmt->sample_pos = 0; |
1060 | fmt->iec958 = 0; |
1061 | |
1062 | /* Get the data width */ |
1063 | switch (snd_pcm_format_width(format: raw_fmt)) { |
1064 | case 16: |
1065 | fmt->width = EASRC_WIDTH_16_BIT; |
1066 | fmt->addexp = 15; |
1067 | break; |
1068 | case 20: |
1069 | fmt->width = EASRC_WIDTH_20_BIT; |
1070 | fmt->addexp = 19; |
1071 | break; |
1072 | case 24: |
1073 | fmt->width = EASRC_WIDTH_24_BIT; |
1074 | fmt->addexp = 23; |
1075 | break; |
1076 | case 32: |
1077 | fmt->width = EASRC_WIDTH_32_BIT; |
1078 | fmt->addexp = 31; |
1079 | break; |
1080 | default: |
1081 | return -EINVAL; |
1082 | } |
1083 | |
1084 | switch (raw_fmt) { |
1085 | case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: |
1086 | fmt->width = easrc_priv->bps_iec958[ctx->index]; |
1087 | fmt->iec958 = 1; |
1088 | fmt->floating_point = 0; |
1089 | if (fmt->width == EASRC_WIDTH_16_BIT) { |
1090 | fmt->sample_pos = 12; |
1091 | fmt->addexp = 15; |
1092 | } else if (fmt->width == EASRC_WIDTH_20_BIT) { |
1093 | fmt->sample_pos = 8; |
1094 | fmt->addexp = 19; |
1095 | } else if (fmt->width == EASRC_WIDTH_24_BIT) { |
1096 | fmt->sample_pos = 4; |
1097 | fmt->addexp = 23; |
1098 | } |
1099 | break; |
1100 | default: |
1101 | break; |
1102 | } |
1103 | |
1104 | /* |
1105 | * Data Endianness |
1106 | * 0 - Little-Endian |
1107 | * 1 - Big-Endian |
1108 | */ |
1109 | ret = snd_pcm_format_big_endian(format: raw_fmt); |
1110 | if (ret < 0) |
1111 | return ret; |
1112 | |
1113 | fmt->endianness = ret; |
1114 | |
1115 | /* |
1116 | * Input Data sign |
1117 | * 0b - Signed Format |
1118 | * 1b - Unsigned Format |
1119 | */ |
1120 | fmt->unsign = snd_pcm_format_unsigned(format: raw_fmt) > 0 ? 1 : 0; |
1121 | |
1122 | return 0; |
1123 | } |
1124 | |
1125 | static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx, |
1126 | snd_pcm_format_t *in_raw_format, |
1127 | snd_pcm_format_t *out_raw_format) |
1128 | { |
1129 | struct fsl_asrc *easrc = ctx->asrc; |
1130 | struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; |
1131 | struct fsl_easrc_data_fmt *in_fmt = &ctx_priv->in_params.fmt; |
1132 | struct fsl_easrc_data_fmt *out_fmt = &ctx_priv->out_params.fmt; |
1133 | int ret = 0; |
1134 | |
1135 | /* Get the bitfield values for input data format */ |
1136 | if (in_raw_format && out_raw_format) { |
1137 | ret = fsl_easrc_process_format(ctx, fmt: in_fmt, raw_fmt: *in_raw_format); |
1138 | if (ret) |
1139 | return ret; |
1140 | } |
1141 | |
1142 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1143 | EASRC_CC_BPS_MASK, |
1144 | EASRC_CC_BPS(in_fmt->width)); |
1145 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1146 | EASRC_CC_ENDIANNESS_MASK, |
1147 | val: in_fmt->endianness << EASRC_CC_ENDIANNESS_SHIFT); |
1148 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1149 | EASRC_CC_FMT_MASK, |
1150 | val: in_fmt->floating_point << EASRC_CC_FMT_SHIFT); |
1151 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1152 | EASRC_CC_INSIGN_MASK, |
1153 | val: in_fmt->unsign << EASRC_CC_INSIGN_SHIFT); |
1154 | |
1155 | /* In Sample Position */ |
1156 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1157 | EASRC_CC_SAMPLE_POS_MASK, |
1158 | EASRC_CC_SAMPLE_POS(in_fmt->sample_pos)); |
1159 | |
1160 | /* Get the bitfield values for input data format */ |
1161 | if (in_raw_format && out_raw_format) { |
1162 | ret = fsl_easrc_process_format(ctx, fmt: out_fmt, raw_fmt: *out_raw_format); |
1163 | if (ret) |
1164 | return ret; |
1165 | } |
1166 | |
1167 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1168 | EASRC_COC_BPS_MASK, |
1169 | EASRC_COC_BPS(out_fmt->width)); |
1170 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1171 | EASRC_COC_ENDIANNESS_MASK, |
1172 | val: out_fmt->endianness << EASRC_COC_ENDIANNESS_SHIFT); |
1173 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1174 | EASRC_COC_FMT_MASK, |
1175 | val: out_fmt->floating_point << EASRC_COC_FMT_SHIFT); |
1176 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1177 | EASRC_COC_OUTSIGN_MASK, |
1178 | val: out_fmt->unsign << EASRC_COC_OUTSIGN_SHIFT); |
1179 | |
1180 | /* Out Sample Position */ |
1181 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1182 | EASRC_COC_SAMPLE_POS_MASK, |
1183 | EASRC_COC_SAMPLE_POS(out_fmt->sample_pos)); |
1184 | |
1185 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1186 | EASRC_COC_IEC_EN_MASK, |
1187 | val: out_fmt->iec958 << EASRC_COC_IEC_EN_SHIFT); |
1188 | |
1189 | return ret; |
1190 | } |
1191 | |
1192 | /* |
1193 | * The ASRC provides interleaving support in hardware to ensure that a |
1194 | * variety of sample sources can be internally combined |
1195 | * to conform with this format. Interleaving parameters are accessed |
1196 | * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers |
1197 | */ |
1198 | static int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx) |
1199 | { |
1200 | struct fsl_easrc_ctx_priv *ctx_priv; |
1201 | struct fsl_asrc *easrc; |
1202 | |
1203 | if (!ctx) |
1204 | return -ENODEV; |
1205 | |
1206 | easrc = ctx->asrc; |
1207 | ctx_priv = ctx->private; |
1208 | |
1209 | /* input interleaving parameters */ |
1210 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CIA(ctx->index), |
1211 | EASRC_CIA_ITER_MASK, |
1212 | EASRC_CIA_ITER(ctx_priv->in_params.iterations)); |
1213 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CIA(ctx->index), |
1214 | EASRC_CIA_GRLEN_MASK, |
1215 | EASRC_CIA_GRLEN(ctx_priv->in_params.group_len)); |
1216 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CIA(ctx->index), |
1217 | EASRC_CIA_ACCLEN_MASK, |
1218 | EASRC_CIA_ACCLEN(ctx_priv->in_params.access_len)); |
1219 | |
1220 | /* output interleaving parameters */ |
1221 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COA(ctx->index), |
1222 | EASRC_COA_ITER_MASK, |
1223 | EASRC_COA_ITER(ctx_priv->out_params.iterations)); |
1224 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COA(ctx->index), |
1225 | EASRC_COA_GRLEN_MASK, |
1226 | EASRC_COA_GRLEN(ctx_priv->out_params.group_len)); |
1227 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COA(ctx->index), |
1228 | EASRC_COA_ACCLEN_MASK, |
1229 | EASRC_COA_ACCLEN(ctx_priv->out_params.access_len)); |
1230 | |
1231 | return 0; |
1232 | } |
1233 | |
1234 | /* |
1235 | * Request one of the available contexts |
1236 | * |
1237 | * Returns a negative number on error and >=0 as context id |
1238 | * on success |
1239 | */ |
1240 | static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx) |
1241 | { |
1242 | enum asrc_pair_index index = ASRC_INVALID_PAIR; |
1243 | struct fsl_asrc *easrc = ctx->asrc; |
1244 | struct device *dev; |
1245 | unsigned long lock_flags; |
1246 | int ret = 0; |
1247 | int i; |
1248 | |
1249 | dev = &easrc->pdev->dev; |
1250 | |
1251 | spin_lock_irqsave(&easrc->lock, lock_flags); |
1252 | |
1253 | for (i = ASRC_PAIR_A; i < EASRC_CTX_MAX_NUM; i++) { |
1254 | if (easrc->pair[i]) |
1255 | continue; |
1256 | |
1257 | index = i; |
1258 | break; |
1259 | } |
1260 | |
1261 | if (index == ASRC_INVALID_PAIR) { |
1262 | dev_err(dev, "all contexts are busy\n" ); |
1263 | ret = -EBUSY; |
1264 | } else if (channels > easrc->channel_avail) { |
1265 | dev_err(dev, "can't give the required channels: %d\n" , |
1266 | channels); |
1267 | ret = -EINVAL; |
1268 | } else { |
1269 | ctx->index = index; |
1270 | ctx->channels = channels; |
1271 | easrc->pair[index] = ctx; |
1272 | easrc->channel_avail -= channels; |
1273 | } |
1274 | |
1275 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
1276 | |
1277 | return ret; |
1278 | } |
1279 | |
1280 | /* |
1281 | * Release the context |
1282 | * |
1283 | * This funciton is mainly doing the revert thing in request context |
1284 | */ |
1285 | static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx) |
1286 | { |
1287 | unsigned long lock_flags; |
1288 | struct fsl_asrc *easrc; |
1289 | |
1290 | if (!ctx) |
1291 | return; |
1292 | |
1293 | easrc = ctx->asrc; |
1294 | |
1295 | spin_lock_irqsave(&easrc->lock, lock_flags); |
1296 | |
1297 | fsl_easrc_release_slot(easrc, ctx_id: ctx->index); |
1298 | |
1299 | easrc->channel_avail += ctx->channels; |
1300 | easrc->pair[ctx->index] = NULL; |
1301 | |
1302 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
1303 | } |
1304 | |
1305 | /* |
1306 | * Start the context |
1307 | * |
1308 | * Enable the DMA request and context |
1309 | */ |
1310 | static int fsl_easrc_start_context(struct fsl_asrc_pair *ctx) |
1311 | { |
1312 | struct fsl_asrc *easrc = ctx->asrc; |
1313 | |
1314 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1315 | EASRC_CC_FWMDE_MASK, EASRC_CC_FWMDE); |
1316 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1317 | EASRC_COC_FWMDE_MASK, EASRC_COC_FWMDE); |
1318 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1319 | EASRC_CC_EN_MASK, EASRC_CC_EN); |
1320 | return 0; |
1321 | } |
1322 | |
1323 | /* |
1324 | * Stop the context |
1325 | * |
1326 | * Disable the DMA request and context |
1327 | */ |
1328 | static int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) |
1329 | { |
1330 | struct fsl_asrc *easrc = ctx->asrc; |
1331 | int val, i; |
1332 | int size; |
1333 | int retry = 200; |
1334 | |
1335 | regmap_read(map: easrc->regmap, REG_EASRC_CC(ctx->index), val: &val); |
1336 | |
1337 | if (val & EASRC_CC_EN_MASK) { |
1338 | regmap_update_bits(map: easrc->regmap, |
1339 | REG_EASRC_CC(ctx->index), |
1340 | EASRC_CC_STOP_MASK, EASRC_CC_STOP); |
1341 | do { |
1342 | regmap_read(map: easrc->regmap, REG_EASRC_SFS(ctx->index), val: &val); |
1343 | val &= EASRC_SFS_NSGO_MASK; |
1344 | size = val >> EASRC_SFS_NSGO_SHIFT; |
1345 | |
1346 | /* Read FIFO, drop the data */ |
1347 | for (i = 0; i < size * ctx->channels; i++) |
1348 | regmap_read(map: easrc->regmap, REG_EASRC_RDFIFO(ctx->index), val: &val); |
1349 | /* Check RUN_STOP_DONE */ |
1350 | regmap_read(map: easrc->regmap, REG_EASRC_IRQF, val: &val); |
1351 | if (val & EASRC_IRQF_RSD(1 << ctx->index)) { |
1352 | /*Clear RUN_STOP_DONE*/ |
1353 | regmap_write_bits(map: easrc->regmap, |
1354 | REG_EASRC_IRQF, |
1355 | EASRC_IRQF_RSD(1 << ctx->index), |
1356 | EASRC_IRQF_RSD(1 << ctx->index)); |
1357 | break; |
1358 | } |
1359 | udelay(100); |
1360 | } while (--retry); |
1361 | |
1362 | if (retry == 0) |
1363 | dev_warn(&easrc->pdev->dev, "RUN STOP fail\n" ); |
1364 | } |
1365 | |
1366 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1367 | EASRC_CC_EN_MASK | EASRC_CC_STOP_MASK, val: 0); |
1368 | regmap_update_bits(map: easrc->regmap, REG_EASRC_CC(ctx->index), |
1369 | EASRC_CC_FWMDE_MASK, val: 0); |
1370 | regmap_update_bits(map: easrc->regmap, REG_EASRC_COC(ctx->index), |
1371 | EASRC_COC_FWMDE_MASK, val: 0); |
1372 | return 0; |
1373 | } |
1374 | |
1375 | static struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx, |
1376 | bool dir) |
1377 | { |
1378 | struct fsl_asrc *easrc = ctx->asrc; |
1379 | enum asrc_pair_index index = ctx->index; |
1380 | char name[8]; |
1381 | |
1382 | /* Example of dma name: ctx0_rx */ |
1383 | sprintf(buf: name, fmt: "ctx%c_%cx" , index + '0', dir == IN ? 'r' : 't'); |
1384 | |
1385 | return dma_request_slave_channel(dev: &easrc->pdev->dev, name); |
1386 | }; |
1387 | |
1388 | static const unsigned int easrc_rates[] = { |
1389 | 8000, 11025, 12000, 16000, |
1390 | 22050, 24000, 32000, 44100, |
1391 | 48000, 64000, 88200, 96000, |
1392 | 128000, 176400, 192000, 256000, |
1393 | 352800, 384000, 705600, 768000, |
1394 | }; |
1395 | |
1396 | static const struct snd_pcm_hw_constraint_list easrc_rate_constraints = { |
1397 | .count = ARRAY_SIZE(easrc_rates), |
1398 | .list = easrc_rates, |
1399 | }; |
1400 | |
1401 | static int fsl_easrc_startup(struct snd_pcm_substream *substream, |
1402 | struct snd_soc_dai *dai) |
1403 | { |
1404 | return snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
1405 | SNDRV_PCM_HW_PARAM_RATE, |
1406 | l: &easrc_rate_constraints); |
1407 | } |
1408 | |
1409 | static int fsl_easrc_trigger(struct snd_pcm_substream *substream, |
1410 | int cmd, struct snd_soc_dai *dai) |
1411 | { |
1412 | struct snd_pcm_runtime *runtime = substream->runtime; |
1413 | struct fsl_asrc_pair *ctx = runtime->private_data; |
1414 | int ret; |
1415 | |
1416 | switch (cmd) { |
1417 | case SNDRV_PCM_TRIGGER_START: |
1418 | case SNDRV_PCM_TRIGGER_RESUME: |
1419 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
1420 | ret = fsl_easrc_start_context(ctx); |
1421 | if (ret) |
1422 | return ret; |
1423 | break; |
1424 | case SNDRV_PCM_TRIGGER_STOP: |
1425 | case SNDRV_PCM_TRIGGER_SUSPEND: |
1426 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1427 | ret = fsl_easrc_stop_context(ctx); |
1428 | if (ret) |
1429 | return ret; |
1430 | break; |
1431 | default: |
1432 | return -EINVAL; |
1433 | } |
1434 | |
1435 | return 0; |
1436 | } |
1437 | |
1438 | static int fsl_easrc_hw_params(struct snd_pcm_substream *substream, |
1439 | struct snd_pcm_hw_params *params, |
1440 | struct snd_soc_dai *dai) |
1441 | { |
1442 | struct fsl_asrc *easrc = snd_soc_dai_get_drvdata(dai); |
1443 | struct snd_pcm_runtime *runtime = substream->runtime; |
1444 | struct device *dev = &easrc->pdev->dev; |
1445 | struct fsl_asrc_pair *ctx = runtime->private_data; |
1446 | struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; |
1447 | unsigned int channels = params_channels(p: params); |
1448 | unsigned int rate = params_rate(p: params); |
1449 | snd_pcm_format_t format = params_format(p: params); |
1450 | int ret; |
1451 | |
1452 | ret = fsl_easrc_request_context(channels, ctx); |
1453 | if (ret) { |
1454 | dev_err(dev, "failed to request context\n" ); |
1455 | return ret; |
1456 | } |
1457 | |
1458 | ctx_priv->ctx_streams |= BIT(substream->stream); |
1459 | |
1460 | /* |
1461 | * Set the input and output ratio so we can compute |
1462 | * the resampling ratio in RS_LOW/HIGH |
1463 | */ |
1464 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1465 | ctx_priv->in_params.sample_rate = rate; |
1466 | ctx_priv->in_params.sample_format = format; |
1467 | ctx_priv->out_params.sample_rate = easrc->asrc_rate; |
1468 | ctx_priv->out_params.sample_format = easrc->asrc_format; |
1469 | } else { |
1470 | ctx_priv->out_params.sample_rate = rate; |
1471 | ctx_priv->out_params.sample_format = format; |
1472 | ctx_priv->in_params.sample_rate = easrc->asrc_rate; |
1473 | ctx_priv->in_params.sample_format = easrc->asrc_format; |
1474 | } |
1475 | |
1476 | ctx->channels = channels; |
1477 | ctx_priv->in_params.fifo_wtmk = 0x20; |
1478 | ctx_priv->out_params.fifo_wtmk = 0x20; |
1479 | |
1480 | /* |
1481 | * Do only rate conversion and keep the same format for input |
1482 | * and output data |
1483 | */ |
1484 | ret = fsl_easrc_set_ctx_format(ctx, |
1485 | in_raw_format: &ctx_priv->in_params.sample_format, |
1486 | out_raw_format: &ctx_priv->out_params.sample_format); |
1487 | if (ret) { |
1488 | dev_err(dev, "failed to set format %d" , ret); |
1489 | return ret; |
1490 | } |
1491 | |
1492 | ret = fsl_easrc_config_context(easrc, ctx_id: ctx->index); |
1493 | if (ret) { |
1494 | dev_err(dev, "failed to config context\n" ); |
1495 | return ret; |
1496 | } |
1497 | |
1498 | ctx_priv->in_params.iterations = 1; |
1499 | ctx_priv->in_params.group_len = ctx->channels; |
1500 | ctx_priv->in_params.access_len = ctx->channels; |
1501 | ctx_priv->out_params.iterations = 1; |
1502 | ctx_priv->out_params.group_len = ctx->channels; |
1503 | ctx_priv->out_params.access_len = ctx->channels; |
1504 | |
1505 | ret = fsl_easrc_set_ctx_organziation(ctx); |
1506 | if (ret) { |
1507 | dev_err(dev, "failed to set fifo organization\n" ); |
1508 | return ret; |
1509 | } |
1510 | |
1511 | return 0; |
1512 | } |
1513 | |
1514 | static int fsl_easrc_hw_free(struct snd_pcm_substream *substream, |
1515 | struct snd_soc_dai *dai) |
1516 | { |
1517 | struct snd_pcm_runtime *runtime = substream->runtime; |
1518 | struct fsl_asrc_pair *ctx = runtime->private_data; |
1519 | struct fsl_easrc_ctx_priv *ctx_priv; |
1520 | |
1521 | if (!ctx) |
1522 | return -EINVAL; |
1523 | |
1524 | ctx_priv = ctx->private; |
1525 | |
1526 | if (ctx_priv->ctx_streams & BIT(substream->stream)) { |
1527 | ctx_priv->ctx_streams &= ~BIT(substream->stream); |
1528 | fsl_easrc_release_context(ctx); |
1529 | } |
1530 | |
1531 | return 0; |
1532 | } |
1533 | |
1534 | static int fsl_easrc_dai_probe(struct snd_soc_dai *cpu_dai) |
1535 | { |
1536 | struct fsl_asrc *easrc = dev_get_drvdata(dev: cpu_dai->dev); |
1537 | |
1538 | snd_soc_dai_init_dma_data(dai: cpu_dai, |
1539 | playback: &easrc->dma_params_tx, |
1540 | capture: &easrc->dma_params_rx); |
1541 | return 0; |
1542 | } |
1543 | |
1544 | static const struct snd_soc_dai_ops fsl_easrc_dai_ops = { |
1545 | .probe = fsl_easrc_dai_probe, |
1546 | .startup = fsl_easrc_startup, |
1547 | .trigger = fsl_easrc_trigger, |
1548 | .hw_params = fsl_easrc_hw_params, |
1549 | .hw_free = fsl_easrc_hw_free, |
1550 | }; |
1551 | |
1552 | static struct snd_soc_dai_driver fsl_easrc_dai = { |
1553 | .playback = { |
1554 | .stream_name = "ASRC-Playback" , |
1555 | .channels_min = 1, |
1556 | .channels_max = 32, |
1557 | .rate_min = 8000, |
1558 | .rate_max = 768000, |
1559 | .rates = SNDRV_PCM_RATE_KNOT, |
1560 | .formats = FSL_EASRC_FORMATS, |
1561 | }, |
1562 | .capture = { |
1563 | .stream_name = "ASRC-Capture" , |
1564 | .channels_min = 1, |
1565 | .channels_max = 32, |
1566 | .rate_min = 8000, |
1567 | .rate_max = 768000, |
1568 | .rates = SNDRV_PCM_RATE_KNOT, |
1569 | .formats = FSL_EASRC_FORMATS | |
1570 | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, |
1571 | }, |
1572 | .ops = &fsl_easrc_dai_ops, |
1573 | }; |
1574 | |
1575 | static const struct snd_soc_component_driver fsl_easrc_component = { |
1576 | .name = "fsl-easrc-dai" , |
1577 | .controls = fsl_easrc_snd_controls, |
1578 | .num_controls = ARRAY_SIZE(fsl_easrc_snd_controls), |
1579 | .legacy_dai_naming = 1, |
1580 | }; |
1581 | |
1582 | static const struct reg_default fsl_easrc_reg_defaults[] = { |
1583 | {REG_EASRC_WRFIFO(0), 0x00000000}, |
1584 | {REG_EASRC_WRFIFO(1), 0x00000000}, |
1585 | {REG_EASRC_WRFIFO(2), 0x00000000}, |
1586 | {REG_EASRC_WRFIFO(3), 0x00000000}, |
1587 | {REG_EASRC_RDFIFO(0), 0x00000000}, |
1588 | {REG_EASRC_RDFIFO(1), 0x00000000}, |
1589 | {REG_EASRC_RDFIFO(2), 0x00000000}, |
1590 | {REG_EASRC_RDFIFO(3), 0x00000000}, |
1591 | {REG_EASRC_CC(0), 0x00000000}, |
1592 | {REG_EASRC_CC(1), 0x00000000}, |
1593 | {REG_EASRC_CC(2), 0x00000000}, |
1594 | {REG_EASRC_CC(3), 0x00000000}, |
1595 | {REG_EASRC_CCE1(0), 0x00000000}, |
1596 | {REG_EASRC_CCE1(1), 0x00000000}, |
1597 | {REG_EASRC_CCE1(2), 0x00000000}, |
1598 | {REG_EASRC_CCE1(3), 0x00000000}, |
1599 | {REG_EASRC_CCE2(0), 0x00000000}, |
1600 | {REG_EASRC_CCE2(1), 0x00000000}, |
1601 | {REG_EASRC_CCE2(2), 0x00000000}, |
1602 | {REG_EASRC_CCE2(3), 0x00000000}, |
1603 | {REG_EASRC_CIA(0), 0x00000000}, |
1604 | {REG_EASRC_CIA(1), 0x00000000}, |
1605 | {REG_EASRC_CIA(2), 0x00000000}, |
1606 | {REG_EASRC_CIA(3), 0x00000000}, |
1607 | {REG_EASRC_DPCS0R0(0), 0x00000000}, |
1608 | {REG_EASRC_DPCS0R0(1), 0x00000000}, |
1609 | {REG_EASRC_DPCS0R0(2), 0x00000000}, |
1610 | {REG_EASRC_DPCS0R0(3), 0x00000000}, |
1611 | {REG_EASRC_DPCS0R1(0), 0x00000000}, |
1612 | {REG_EASRC_DPCS0R1(1), 0x00000000}, |
1613 | {REG_EASRC_DPCS0R1(2), 0x00000000}, |
1614 | {REG_EASRC_DPCS0R1(3), 0x00000000}, |
1615 | {REG_EASRC_DPCS0R2(0), 0x00000000}, |
1616 | {REG_EASRC_DPCS0R2(1), 0x00000000}, |
1617 | {REG_EASRC_DPCS0R2(2), 0x00000000}, |
1618 | {REG_EASRC_DPCS0R2(3), 0x00000000}, |
1619 | {REG_EASRC_DPCS0R3(0), 0x00000000}, |
1620 | {REG_EASRC_DPCS0R3(1), 0x00000000}, |
1621 | {REG_EASRC_DPCS0R3(2), 0x00000000}, |
1622 | {REG_EASRC_DPCS0R3(3), 0x00000000}, |
1623 | {REG_EASRC_DPCS1R0(0), 0x00000000}, |
1624 | {REG_EASRC_DPCS1R0(1), 0x00000000}, |
1625 | {REG_EASRC_DPCS1R0(2), 0x00000000}, |
1626 | {REG_EASRC_DPCS1R0(3), 0x00000000}, |
1627 | {REG_EASRC_DPCS1R1(0), 0x00000000}, |
1628 | {REG_EASRC_DPCS1R1(1), 0x00000000}, |
1629 | {REG_EASRC_DPCS1R1(2), 0x00000000}, |
1630 | {REG_EASRC_DPCS1R1(3), 0x00000000}, |
1631 | {REG_EASRC_DPCS1R2(0), 0x00000000}, |
1632 | {REG_EASRC_DPCS1R2(1), 0x00000000}, |
1633 | {REG_EASRC_DPCS1R2(2), 0x00000000}, |
1634 | {REG_EASRC_DPCS1R2(3), 0x00000000}, |
1635 | {REG_EASRC_DPCS1R3(0), 0x00000000}, |
1636 | {REG_EASRC_DPCS1R3(1), 0x00000000}, |
1637 | {REG_EASRC_DPCS1R3(2), 0x00000000}, |
1638 | {REG_EASRC_DPCS1R3(3), 0x00000000}, |
1639 | {REG_EASRC_COC(0), 0x00000000}, |
1640 | {REG_EASRC_COC(1), 0x00000000}, |
1641 | {REG_EASRC_COC(2), 0x00000000}, |
1642 | {REG_EASRC_COC(3), 0x00000000}, |
1643 | {REG_EASRC_COA(0), 0x00000000}, |
1644 | {REG_EASRC_COA(1), 0x00000000}, |
1645 | {REG_EASRC_COA(2), 0x00000000}, |
1646 | {REG_EASRC_COA(3), 0x00000000}, |
1647 | {REG_EASRC_SFS(0), 0x00000000}, |
1648 | {REG_EASRC_SFS(1), 0x00000000}, |
1649 | {REG_EASRC_SFS(2), 0x00000000}, |
1650 | {REG_EASRC_SFS(3), 0x00000000}, |
1651 | {REG_EASRC_RRL(0), 0x00000000}, |
1652 | {REG_EASRC_RRL(1), 0x00000000}, |
1653 | {REG_EASRC_RRL(2), 0x00000000}, |
1654 | {REG_EASRC_RRL(3), 0x00000000}, |
1655 | {REG_EASRC_RRH(0), 0x00000000}, |
1656 | {REG_EASRC_RRH(1), 0x00000000}, |
1657 | {REG_EASRC_RRH(2), 0x00000000}, |
1658 | {REG_EASRC_RRH(3), 0x00000000}, |
1659 | {REG_EASRC_RUC(0), 0x00000000}, |
1660 | {REG_EASRC_RUC(1), 0x00000000}, |
1661 | {REG_EASRC_RUC(2), 0x00000000}, |
1662 | {REG_EASRC_RUC(3), 0x00000000}, |
1663 | {REG_EASRC_RUR(0), 0x7FFFFFFF}, |
1664 | {REG_EASRC_RUR(1), 0x7FFFFFFF}, |
1665 | {REG_EASRC_RUR(2), 0x7FFFFFFF}, |
1666 | {REG_EASRC_RUR(3), 0x7FFFFFFF}, |
1667 | {REG_EASRC_RCTCL, 0x00000000}, |
1668 | {REG_EASRC_RCTCH, 0x00000000}, |
1669 | {REG_EASRC_PCF(0), 0x00000000}, |
1670 | {REG_EASRC_PCF(1), 0x00000000}, |
1671 | {REG_EASRC_PCF(2), 0x00000000}, |
1672 | {REG_EASRC_PCF(3), 0x00000000}, |
1673 | {REG_EASRC_CRCM, 0x00000000}, |
1674 | {REG_EASRC_CRCC, 0x00000000}, |
1675 | {REG_EASRC_IRQC, 0x00000FFF}, |
1676 | {REG_EASRC_IRQF, 0x00000000}, |
1677 | {REG_EASRC_CS0(0), 0x00000000}, |
1678 | {REG_EASRC_CS0(1), 0x00000000}, |
1679 | {REG_EASRC_CS0(2), 0x00000000}, |
1680 | {REG_EASRC_CS0(3), 0x00000000}, |
1681 | {REG_EASRC_CS1(0), 0x00000000}, |
1682 | {REG_EASRC_CS1(1), 0x00000000}, |
1683 | {REG_EASRC_CS1(2), 0x00000000}, |
1684 | {REG_EASRC_CS1(3), 0x00000000}, |
1685 | {REG_EASRC_CS2(0), 0x00000000}, |
1686 | {REG_EASRC_CS2(1), 0x00000000}, |
1687 | {REG_EASRC_CS2(2), 0x00000000}, |
1688 | {REG_EASRC_CS2(3), 0x00000000}, |
1689 | {REG_EASRC_CS3(0), 0x00000000}, |
1690 | {REG_EASRC_CS3(1), 0x00000000}, |
1691 | {REG_EASRC_CS3(2), 0x00000000}, |
1692 | {REG_EASRC_CS3(3), 0x00000000}, |
1693 | {REG_EASRC_CS4(0), 0x00000000}, |
1694 | {REG_EASRC_CS4(1), 0x00000000}, |
1695 | {REG_EASRC_CS4(2), 0x00000000}, |
1696 | {REG_EASRC_CS4(3), 0x00000000}, |
1697 | {REG_EASRC_CS5(0), 0x00000000}, |
1698 | {REG_EASRC_CS5(1), 0x00000000}, |
1699 | {REG_EASRC_CS5(2), 0x00000000}, |
1700 | {REG_EASRC_CS5(3), 0x00000000}, |
1701 | {REG_EASRC_DBGC, 0x00000000}, |
1702 | {REG_EASRC_DBGS, 0x00000000}, |
1703 | }; |
1704 | |
1705 | static const struct regmap_range fsl_easrc_readable_ranges[] = { |
1706 | regmap_reg_range(REG_EASRC_RDFIFO(0), REG_EASRC_RCTCH), |
1707 | regmap_reg_range(REG_EASRC_PCF(0), REG_EASRC_PCF(3)), |
1708 | regmap_reg_range(REG_EASRC_CRCC, REG_EASRC_DBGS), |
1709 | }; |
1710 | |
1711 | static const struct regmap_access_table fsl_easrc_readable_table = { |
1712 | .yes_ranges = fsl_easrc_readable_ranges, |
1713 | .n_yes_ranges = ARRAY_SIZE(fsl_easrc_readable_ranges), |
1714 | }; |
1715 | |
1716 | static const struct regmap_range fsl_easrc_writeable_ranges[] = { |
1717 | regmap_reg_range(REG_EASRC_WRFIFO(0), REG_EASRC_WRFIFO(3)), |
1718 | regmap_reg_range(REG_EASRC_CC(0), REG_EASRC_COA(3)), |
1719 | regmap_reg_range(REG_EASRC_RRL(0), REG_EASRC_RCTCH), |
1720 | regmap_reg_range(REG_EASRC_PCF(0), REG_EASRC_DBGC), |
1721 | }; |
1722 | |
1723 | static const struct regmap_access_table fsl_easrc_writeable_table = { |
1724 | .yes_ranges = fsl_easrc_writeable_ranges, |
1725 | .n_yes_ranges = ARRAY_SIZE(fsl_easrc_writeable_ranges), |
1726 | }; |
1727 | |
1728 | static const struct regmap_range fsl_easrc_volatileable_ranges[] = { |
1729 | regmap_reg_range(REG_EASRC_RDFIFO(0), REG_EASRC_RDFIFO(3)), |
1730 | regmap_reg_range(REG_EASRC_SFS(0), REG_EASRC_SFS(3)), |
1731 | regmap_reg_range(REG_EASRC_IRQF, REG_EASRC_IRQF), |
1732 | regmap_reg_range(REG_EASRC_DBGS, REG_EASRC_DBGS), |
1733 | }; |
1734 | |
1735 | static const struct regmap_access_table fsl_easrc_volatileable_table = { |
1736 | .yes_ranges = fsl_easrc_volatileable_ranges, |
1737 | .n_yes_ranges = ARRAY_SIZE(fsl_easrc_volatileable_ranges), |
1738 | }; |
1739 | |
1740 | static const struct regmap_config fsl_easrc_regmap_config = { |
1741 | .reg_bits = 32, |
1742 | .reg_stride = 4, |
1743 | .val_bits = 32, |
1744 | |
1745 | .max_register = REG_EASRC_DBGS, |
1746 | .reg_defaults = fsl_easrc_reg_defaults, |
1747 | .num_reg_defaults = ARRAY_SIZE(fsl_easrc_reg_defaults), |
1748 | .rd_table = &fsl_easrc_readable_table, |
1749 | .wr_table = &fsl_easrc_writeable_table, |
1750 | .volatile_table = &fsl_easrc_volatileable_table, |
1751 | .cache_type = REGCACHE_RBTREE, |
1752 | }; |
1753 | |
1754 | #ifdef DEBUG |
1755 | static void fsl_easrc_dump_firmware(struct fsl_asrc *easrc) |
1756 | { |
1757 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
1758 | struct asrc_firmware_hdr *firm = easrc_priv->firmware_hdr; |
1759 | struct interp_params *interp = easrc_priv->interp; |
1760 | struct prefil_params *prefil = easrc_priv->prefil; |
1761 | struct device *dev = &easrc->pdev->dev; |
1762 | int i; |
1763 | |
1764 | if (firm->magic != FIRMWARE_MAGIC) { |
1765 | dev_err(dev, "Wrong magic. Something went wrong!" ); |
1766 | return; |
1767 | } |
1768 | |
1769 | dev_dbg(dev, "Firmware v%u dump:\n" , firm->firmware_version); |
1770 | dev_dbg(dev, "Num prefilter scenarios: %u\n" , firm->prefil_scen); |
1771 | dev_dbg(dev, "Num interpolation scenarios: %u\n" , firm->interp_scen); |
1772 | dev_dbg(dev, "\nInterpolation scenarios:\n" ); |
1773 | |
1774 | for (i = 0; i < firm->interp_scen; i++) { |
1775 | if (interp[i].magic != FIRMWARE_MAGIC) { |
1776 | dev_dbg(dev, "%d. wrong interp magic: %x\n" , |
1777 | i, interp[i].magic); |
1778 | continue; |
1779 | } |
1780 | dev_dbg(dev, "%d. taps: %u, phases: %u, center: %llu\n" , i, |
1781 | interp[i].num_taps, interp[i].num_phases, |
1782 | interp[i].center_tap); |
1783 | } |
1784 | |
1785 | for (i = 0; i < firm->prefil_scen; i++) { |
1786 | if (prefil[i].magic != FIRMWARE_MAGIC) { |
1787 | dev_dbg(dev, "%d. wrong prefil magic: %x\n" , |
1788 | i, prefil[i].magic); |
1789 | continue; |
1790 | } |
1791 | dev_dbg(dev, "%d. insr: %u, outsr: %u, st1: %u, st2: %u\n" , i, |
1792 | prefil[i].insr, prefil[i].outsr, |
1793 | prefil[i].st1_taps, prefil[i].st2_taps); |
1794 | } |
1795 | |
1796 | dev_dbg(dev, "end of firmware dump\n" ); |
1797 | } |
1798 | #endif |
1799 | |
1800 | static int fsl_easrc_get_firmware(struct fsl_asrc *easrc) |
1801 | { |
1802 | struct fsl_easrc_priv *easrc_priv; |
1803 | const struct firmware **fw_p; |
1804 | u32 pnum, inum, offset; |
1805 | const u8 *data; |
1806 | int ret; |
1807 | |
1808 | if (!easrc) |
1809 | return -EINVAL; |
1810 | |
1811 | easrc_priv = easrc->private; |
1812 | fw_p = &easrc_priv->fw; |
1813 | |
1814 | ret = request_firmware(fw: fw_p, name: easrc_priv->fw_name, device: &easrc->pdev->dev); |
1815 | if (ret) |
1816 | return ret; |
1817 | |
1818 | data = easrc_priv->fw->data; |
1819 | |
1820 | easrc_priv->firmware_hdr = (struct asrc_firmware_hdr *)data; |
1821 | pnum = easrc_priv->firmware_hdr->prefil_scen; |
1822 | inum = easrc_priv->firmware_hdr->interp_scen; |
1823 | |
1824 | if (inum) { |
1825 | offset = sizeof(struct asrc_firmware_hdr); |
1826 | easrc_priv->interp = (struct interp_params *)(data + offset); |
1827 | } |
1828 | |
1829 | if (pnum) { |
1830 | offset = sizeof(struct asrc_firmware_hdr) + |
1831 | inum * sizeof(struct interp_params); |
1832 | easrc_priv->prefil = (struct prefil_params *)(data + offset); |
1833 | } |
1834 | |
1835 | #ifdef DEBUG |
1836 | fsl_easrc_dump_firmware(easrc); |
1837 | #endif |
1838 | |
1839 | return 0; |
1840 | } |
1841 | |
1842 | static irqreturn_t fsl_easrc_isr(int irq, void *dev_id) |
1843 | { |
1844 | struct fsl_asrc *easrc = (struct fsl_asrc *)dev_id; |
1845 | struct device *dev = &easrc->pdev->dev; |
1846 | int val; |
1847 | |
1848 | regmap_read(map: easrc->regmap, REG_EASRC_IRQF, val: &val); |
1849 | |
1850 | if (val & EASRC_IRQF_OER_MASK) |
1851 | dev_dbg(dev, "output FIFO underflow\n" ); |
1852 | |
1853 | if (val & EASRC_IRQF_IFO_MASK) |
1854 | dev_dbg(dev, "input FIFO overflow\n" ); |
1855 | |
1856 | return IRQ_HANDLED; |
1857 | } |
1858 | |
1859 | static int fsl_easrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) |
1860 | { |
1861 | return REG_EASRC_FIFO(dir, index); |
1862 | } |
1863 | |
1864 | static const struct of_device_id fsl_easrc_dt_ids[] = { |
1865 | { .compatible = "fsl,imx8mn-easrc" ,}, |
1866 | {} |
1867 | }; |
1868 | MODULE_DEVICE_TABLE(of, fsl_easrc_dt_ids); |
1869 | |
1870 | static int fsl_easrc_probe(struct platform_device *pdev) |
1871 | { |
1872 | struct fsl_easrc_priv *easrc_priv; |
1873 | struct device *dev = &pdev->dev; |
1874 | struct fsl_asrc *easrc; |
1875 | struct resource *res; |
1876 | struct device_node *np; |
1877 | void __iomem *regs; |
1878 | u32 asrc_fmt = 0; |
1879 | int ret, irq; |
1880 | |
1881 | easrc = devm_kzalloc(dev, size: sizeof(*easrc), GFP_KERNEL); |
1882 | if (!easrc) |
1883 | return -ENOMEM; |
1884 | |
1885 | easrc_priv = devm_kzalloc(dev, size: sizeof(*easrc_priv), GFP_KERNEL); |
1886 | if (!easrc_priv) |
1887 | return -ENOMEM; |
1888 | |
1889 | easrc->pdev = pdev; |
1890 | easrc->private = easrc_priv; |
1891 | np = dev->of_node; |
1892 | |
1893 | regs = devm_platform_get_and_ioremap_resource(pdev, index: 0, res: &res); |
1894 | if (IS_ERR(ptr: regs)) |
1895 | return PTR_ERR(ptr: regs); |
1896 | |
1897 | easrc->paddr = res->start; |
1898 | |
1899 | easrc->regmap = devm_regmap_init_mmio(dev, regs, &fsl_easrc_regmap_config); |
1900 | if (IS_ERR(ptr: easrc->regmap)) { |
1901 | dev_err(dev, "failed to init regmap" ); |
1902 | return PTR_ERR(ptr: easrc->regmap); |
1903 | } |
1904 | |
1905 | irq = platform_get_irq(pdev, 0); |
1906 | if (irq < 0) |
1907 | return irq; |
1908 | |
1909 | ret = devm_request_irq(dev: &pdev->dev, irq, handler: fsl_easrc_isr, irqflags: 0, |
1910 | devname: dev_name(dev), dev_id: easrc); |
1911 | if (ret) { |
1912 | dev_err(dev, "failed to claim irq %u: %d\n" , irq, ret); |
1913 | return ret; |
1914 | } |
1915 | |
1916 | easrc->mem_clk = devm_clk_get(dev, id: "mem" ); |
1917 | if (IS_ERR(ptr: easrc->mem_clk)) { |
1918 | dev_err(dev, "failed to get mem clock\n" ); |
1919 | return PTR_ERR(ptr: easrc->mem_clk); |
1920 | } |
1921 | |
1922 | /* Set default value */ |
1923 | easrc->channel_avail = 32; |
1924 | easrc->get_dma_channel = fsl_easrc_get_dma_channel; |
1925 | easrc->request_pair = fsl_easrc_request_context; |
1926 | easrc->release_pair = fsl_easrc_release_context; |
1927 | easrc->get_fifo_addr = fsl_easrc_get_fifo_addr; |
1928 | easrc->pair_priv_size = sizeof(struct fsl_easrc_ctx_priv); |
1929 | |
1930 | easrc_priv->rs_num_taps = EASRC_RS_32_TAPS; |
1931 | easrc_priv->const_coeff = 0x3FF0000000000000; |
1932 | |
1933 | ret = of_property_read_u32(np, propname: "fsl,asrc-rate" , out_value: &easrc->asrc_rate); |
1934 | if (ret) { |
1935 | dev_err(dev, "failed to asrc rate\n" ); |
1936 | return ret; |
1937 | } |
1938 | |
1939 | ret = of_property_read_u32(np, propname: "fsl,asrc-format" , out_value: &asrc_fmt); |
1940 | easrc->asrc_format = (__force snd_pcm_format_t)asrc_fmt; |
1941 | if (ret) { |
1942 | dev_err(dev, "failed to asrc format\n" ); |
1943 | return ret; |
1944 | } |
1945 | |
1946 | if (!(FSL_EASRC_FORMATS & (pcm_format_to_bits(pcm_format: easrc->asrc_format)))) { |
1947 | dev_warn(dev, "unsupported format, switching to S24_LE\n" ); |
1948 | easrc->asrc_format = SNDRV_PCM_FORMAT_S24_LE; |
1949 | } |
1950 | |
1951 | ret = of_property_read_string(np, propname: "firmware-name" , |
1952 | out_string: &easrc_priv->fw_name); |
1953 | if (ret) { |
1954 | dev_err(dev, "failed to get firmware name\n" ); |
1955 | return ret; |
1956 | } |
1957 | |
1958 | platform_set_drvdata(pdev, data: easrc); |
1959 | pm_runtime_enable(dev); |
1960 | |
1961 | spin_lock_init(&easrc->lock); |
1962 | |
1963 | regcache_cache_only(map: easrc->regmap, enable: true); |
1964 | |
1965 | ret = devm_snd_soc_register_component(dev, component_driver: &fsl_easrc_component, |
1966 | dai_drv: &fsl_easrc_dai, num_dai: 1); |
1967 | if (ret) { |
1968 | dev_err(dev, "failed to register ASoC DAI\n" ); |
1969 | goto err_pm_disable; |
1970 | } |
1971 | |
1972 | ret = devm_snd_soc_register_component(dev, component_driver: &fsl_asrc_component, |
1973 | NULL, num_dai: 0); |
1974 | if (ret) { |
1975 | dev_err(&pdev->dev, "failed to register ASoC platform\n" ); |
1976 | goto err_pm_disable; |
1977 | } |
1978 | |
1979 | return 0; |
1980 | |
1981 | err_pm_disable: |
1982 | pm_runtime_disable(dev: &pdev->dev); |
1983 | return ret; |
1984 | } |
1985 | |
1986 | static void fsl_easrc_remove(struct platform_device *pdev) |
1987 | { |
1988 | pm_runtime_disable(dev: &pdev->dev); |
1989 | } |
1990 | |
1991 | static __maybe_unused int fsl_easrc_runtime_suspend(struct device *dev) |
1992 | { |
1993 | struct fsl_asrc *easrc = dev_get_drvdata(dev); |
1994 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
1995 | unsigned long lock_flags; |
1996 | |
1997 | regcache_cache_only(map: easrc->regmap, enable: true); |
1998 | |
1999 | clk_disable_unprepare(clk: easrc->mem_clk); |
2000 | |
2001 | spin_lock_irqsave(&easrc->lock, lock_flags); |
2002 | easrc_priv->firmware_loaded = 0; |
2003 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
2004 | |
2005 | return 0; |
2006 | } |
2007 | |
2008 | static __maybe_unused int fsl_easrc_runtime_resume(struct device *dev) |
2009 | { |
2010 | struct fsl_asrc *easrc = dev_get_drvdata(dev); |
2011 | struct fsl_easrc_priv *easrc_priv = easrc->private; |
2012 | struct fsl_easrc_ctx_priv *ctx_priv; |
2013 | struct fsl_asrc_pair *ctx; |
2014 | unsigned long lock_flags; |
2015 | int ret; |
2016 | int i; |
2017 | |
2018 | ret = clk_prepare_enable(clk: easrc->mem_clk); |
2019 | if (ret) |
2020 | return ret; |
2021 | |
2022 | regcache_cache_only(map: easrc->regmap, enable: false); |
2023 | regcache_mark_dirty(map: easrc->regmap); |
2024 | regcache_sync(map: easrc->regmap); |
2025 | |
2026 | spin_lock_irqsave(&easrc->lock, lock_flags); |
2027 | if (easrc_priv->firmware_loaded) { |
2028 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
2029 | goto skip_load; |
2030 | } |
2031 | easrc_priv->firmware_loaded = 1; |
2032 | spin_unlock_irqrestore(lock: &easrc->lock, flags: lock_flags); |
2033 | |
2034 | ret = fsl_easrc_get_firmware(easrc); |
2035 | if (ret) { |
2036 | dev_err(dev, "failed to get firmware\n" ); |
2037 | goto disable_mem_clk; |
2038 | } |
2039 | |
2040 | /* |
2041 | * Write Resampling Coefficients |
2042 | * The coefficient RAM must be configured prior to beginning of |
2043 | * any context processing within the ASRC |
2044 | */ |
2045 | ret = fsl_easrc_resampler_config(easrc); |
2046 | if (ret) { |
2047 | dev_err(dev, "resampler config failed\n" ); |
2048 | goto disable_mem_clk; |
2049 | } |
2050 | |
2051 | for (i = ASRC_PAIR_A; i < EASRC_CTX_MAX_NUM; i++) { |
2052 | ctx = easrc->pair[i]; |
2053 | if (!ctx) |
2054 | continue; |
2055 | |
2056 | ctx_priv = ctx->private; |
2057 | fsl_easrc_set_rs_ratio(ctx); |
2058 | ctx_priv->out_missed_sample = ctx_priv->in_filled_sample * |
2059 | ctx_priv->out_params.sample_rate / |
2060 | ctx_priv->in_params.sample_rate; |
2061 | if (ctx_priv->in_filled_sample * ctx_priv->out_params.sample_rate |
2062 | % ctx_priv->in_params.sample_rate != 0) |
2063 | ctx_priv->out_missed_sample += 1; |
2064 | |
2065 | ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id: i, |
2066 | coef: ctx_priv->st1_coeff, |
2067 | n_taps: ctx_priv->st1_num_taps, |
2068 | shift: ctx_priv->st1_addexp); |
2069 | if (ret) |
2070 | goto disable_mem_clk; |
2071 | |
2072 | ret = fsl_easrc_write_pf_coeff_mem(easrc, ctx_id: i, |
2073 | coef: ctx_priv->st2_coeff, |
2074 | n_taps: ctx_priv->st2_num_taps, |
2075 | shift: ctx_priv->st2_addexp); |
2076 | if (ret) |
2077 | goto disable_mem_clk; |
2078 | } |
2079 | |
2080 | skip_load: |
2081 | return 0; |
2082 | |
2083 | disable_mem_clk: |
2084 | clk_disable_unprepare(clk: easrc->mem_clk); |
2085 | return ret; |
2086 | } |
2087 | |
2088 | static const struct dev_pm_ops fsl_easrc_pm_ops = { |
2089 | SET_RUNTIME_PM_OPS(fsl_easrc_runtime_suspend, |
2090 | fsl_easrc_runtime_resume, |
2091 | NULL) |
2092 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
2093 | pm_runtime_force_resume) |
2094 | }; |
2095 | |
2096 | static struct platform_driver fsl_easrc_driver = { |
2097 | .probe = fsl_easrc_probe, |
2098 | .remove_new = fsl_easrc_remove, |
2099 | .driver = { |
2100 | .name = "fsl-easrc" , |
2101 | .pm = &fsl_easrc_pm_ops, |
2102 | .of_match_table = fsl_easrc_dt_ids, |
2103 | }, |
2104 | }; |
2105 | module_platform_driver(fsl_easrc_driver); |
2106 | |
2107 | MODULE_DESCRIPTION("NXP Enhanced Asynchronous Sample Rate (eASRC) driver" ); |
2108 | MODULE_LICENSE("GPL v2" ); |
2109 | |