Linux 4.18.10
[linux/fpc-iii.git] / sound / soc / uniphier / aio-core.c
blob638cb3fc5f7b1dee22367c52ec3c7c0622459111
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Socionext UniPhier AIO ALSA common driver.
4 //
5 // Copyright (c) 2016-2018 Socionext Inc.
7 #include <linux/bitfield.h>
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <sound/core.h>
12 #include <sound/pcm.h>
13 #include <sound/pcm_params.h>
14 #include <sound/soc.h>
16 #include "aio.h"
17 #include "aio-reg.h"
19 static u64 rb_cnt(u64 wr, u64 rd, u64 len)
21 if (rd <= wr)
22 return wr - rd;
23 else
24 return len - (rd - wr);
27 static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
29 if (rd <= wr)
30 return wr - rd;
31 else
32 return len - rd;
35 static u64 rb_space(u64 wr, u64 rd, u64 len)
37 if (rd <= wr)
38 return len - (wr - rd) - 8;
39 else
40 return rd - wr - 8;
43 static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
45 if (rd > wr)
46 return rd - wr - 8;
47 else if (rd > 0)
48 return len - wr;
49 else
50 return len - wr - 8;
53 u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
55 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
58 u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
60 return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
63 u64 aio_rb_space(struct uniphier_aio_sub *sub)
65 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
68 u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
70 return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
73 /**
74 * aio_iecout_set_enable - setup IEC output via SoC glue
75 * @chip: the AIO chip pointer
76 * @enable: false to stop the output, true to start
78 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins.
79 * This function need to call at driver startup.
81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
82 * of DT. This function has no effect if no property.
84 void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
86 struct regmap *r = chip->regmap_sg;
88 if (!r)
89 return;
91 regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
94 /**
95 * aio_chip_set_pll - set frequency to audio PLL
96 * @chip : the AIO chip pointer
97 * @source: PLL
98 * @freq : frequency in Hz, 0 is ignored
100 * Sets frequency of audio PLL. This function can be called anytime,
101 * but it takes time till PLL is locked.
103 * Return: Zero if successful, otherwise a negative value on error.
105 int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
106 unsigned int freq)
108 struct device *dev = &chip->pdev->dev;
109 struct regmap *r = chip->regmap;
110 int shift;
111 u32 v;
113 /* Not change */
114 if (freq == 0)
115 return 0;
117 switch (pll_id) {
118 case AUD_PLL_A1:
119 shift = 0;
120 break;
121 case AUD_PLL_F1:
122 shift = 1;
123 break;
124 case AUD_PLL_A2:
125 shift = 2;
126 break;
127 case AUD_PLL_F2:
128 shift = 3;
129 break;
130 default:
131 dev_err(dev, "PLL(%d) not supported\n", pll_id);
132 return -EINVAL;
135 switch (freq) {
136 case 36864000:
137 v = A2APLLCTR1_APLLX_36MHZ;
138 break;
139 case 33868800:
140 v = A2APLLCTR1_APLLX_33MHZ;
141 break;
142 default:
143 dev_err(dev, "PLL frequency not supported(%d)\n", freq);
144 return -EINVAL;
146 chip->plls[pll_id].freq = freq;
148 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
149 v << shift);
151 return 0;
155 * aio_chip_init - initialize AIO whole settings
156 * @chip: the AIO chip pointer
158 * Sets AIO fixed and whole device settings to AIO.
159 * This function need to call once at driver startup.
161 * The register area that is changed by this function is shared by all
162 * modules of AIO. But there is not race condition since this function
163 * has always set the same initialize values.
165 void aio_chip_init(struct uniphier_aio_chip *chip)
167 struct regmap *r = chip->regmap;
169 regmap_update_bits(r, A2APLLCTR0,
170 A2APLLCTR0_APLLXPOW_MASK,
171 A2APLLCTR0_APLLXPOW_PWON);
173 regmap_update_bits(r, A2EXMCLKSEL0,
174 A2EXMCLKSEL0_EXMCLK_MASK,
175 A2EXMCLKSEL0_EXMCLK_OUTPUT);
177 regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
178 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
179 A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
180 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
181 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
183 if (chip->chip_spec->addr_ext)
184 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
185 CDA2D_TEST_DDR_MODE_EXTON0);
186 else
187 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
188 CDA2D_TEST_DDR_MODE_EXTOFF1);
192 * aio_init - initialize AIO substream
193 * @sub: the AIO substream pointer
195 * Sets fixed settings of each AIO substreams.
196 * This function need to call once at substream startup.
198 * Return: Zero if successful, otherwise a negative value on error.
200 int aio_init(struct uniphier_aio_sub *sub)
202 struct device *dev = &sub->aio->chip->pdev->dev;
203 struct regmap *r = sub->aio->chip->regmap;
205 regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
206 MAPCTR0_EN | sub->swm->rb.map);
207 regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
208 MAPCTR0_EN | sub->swm->ch.map);
210 switch (sub->swm->type) {
211 case PORT_TYPE_I2S:
212 case PORT_TYPE_SPDIF:
213 case PORT_TYPE_EVE:
214 if (sub->swm->dir == PORT_DIR_INPUT) {
215 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
216 MAPCTR0_EN | sub->swm->iif.map);
217 regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
218 MAPCTR0_EN | sub->swm->iport.map);
219 } else {
220 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
221 MAPCTR0_EN | sub->swm->oif.map);
222 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
223 MAPCTR0_EN | sub->swm->oport.map);
225 break;
226 case PORT_TYPE_CONV:
227 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
228 MAPCTR0_EN | sub->swm->oif.map);
229 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
230 MAPCTR0_EN | sub->swm->oport.map);
231 regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
232 MAPCTR0_EN | sub->swm->och.map);
233 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
234 MAPCTR0_EN | sub->swm->iif.map);
235 break;
236 default:
237 dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
238 return -EINVAL;
241 return 0;
245 * aio_port_reset - reset AIO port block
246 * @sub: the AIO substream pointer
248 * Resets the digital signal input/output port block of AIO.
250 void aio_port_reset(struct uniphier_aio_sub *sub)
252 struct regmap *r = sub->aio->chip->regmap;
254 if (sub->swm->dir == PORT_DIR_OUTPUT) {
255 regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
256 regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
257 } else {
258 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
259 IPORTMXRSTCTR_RSTPI_MASK,
260 IPORTMXRSTCTR_RSTPI_RESET);
261 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
262 IPORTMXRSTCTR_RSTPI_MASK,
263 IPORTMXRSTCTR_RSTPI_RELEASE);
268 * aio_port_set_rate - set sampling rate of LPCM
269 * @sub: the AIO substream pointer, PCM substream only
270 * @rate: Sampling rate in Hz.
272 * Set suitable I2S format settings to input/output port block of AIO.
273 * Parameter is specified by hw_params().
275 * This function may return error if non-PCM substream.
277 * Return: Zero if successful, otherwise a negative value on error.
279 int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
281 struct regmap *r = sub->aio->chip->regmap;
282 struct device *dev = &sub->aio->chip->pdev->dev;
283 u32 v;
285 if (sub->swm->dir == PORT_DIR_OUTPUT) {
286 switch (rate) {
287 case 8000:
288 v = OPORTMXCTR1_FSSEL_8;
289 break;
290 case 11025:
291 v = OPORTMXCTR1_FSSEL_11_025;
292 break;
293 case 12000:
294 v = OPORTMXCTR1_FSSEL_12;
295 break;
296 case 16000:
297 v = OPORTMXCTR1_FSSEL_16;
298 break;
299 case 22050:
300 v = OPORTMXCTR1_FSSEL_22_05;
301 break;
302 case 24000:
303 v = OPORTMXCTR1_FSSEL_24;
304 break;
305 case 32000:
306 v = OPORTMXCTR1_FSSEL_32;
307 break;
308 case 44100:
309 v = OPORTMXCTR1_FSSEL_44_1;
310 break;
311 case 48000:
312 v = OPORTMXCTR1_FSSEL_48;
313 break;
314 case 88200:
315 v = OPORTMXCTR1_FSSEL_88_2;
316 break;
317 case 96000:
318 v = OPORTMXCTR1_FSSEL_96;
319 break;
320 case 176400:
321 v = OPORTMXCTR1_FSSEL_176_4;
322 break;
323 case 192000:
324 v = OPORTMXCTR1_FSSEL_192;
325 break;
326 default:
327 dev_err(dev, "Rate not supported(%d)\n", rate);
328 return -EINVAL;
331 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
332 OPORTMXCTR1_FSSEL_MASK, v);
333 } else {
334 switch (rate) {
335 case 8000:
336 v = IPORTMXCTR1_FSSEL_8;
337 break;
338 case 11025:
339 v = IPORTMXCTR1_FSSEL_11_025;
340 break;
341 case 12000:
342 v = IPORTMXCTR1_FSSEL_12;
343 break;
344 case 16000:
345 v = IPORTMXCTR1_FSSEL_16;
346 break;
347 case 22050:
348 v = IPORTMXCTR1_FSSEL_22_05;
349 break;
350 case 24000:
351 v = IPORTMXCTR1_FSSEL_24;
352 break;
353 case 32000:
354 v = IPORTMXCTR1_FSSEL_32;
355 break;
356 case 44100:
357 v = IPORTMXCTR1_FSSEL_44_1;
358 break;
359 case 48000:
360 v = IPORTMXCTR1_FSSEL_48;
361 break;
362 case 88200:
363 v = IPORTMXCTR1_FSSEL_88_2;
364 break;
365 case 96000:
366 v = IPORTMXCTR1_FSSEL_96;
367 break;
368 case 176400:
369 v = IPORTMXCTR1_FSSEL_176_4;
370 break;
371 case 192000:
372 v = IPORTMXCTR1_FSSEL_192;
373 break;
374 default:
375 dev_err(dev, "Rate not supported(%d)\n", rate);
376 return -EINVAL;
379 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
380 IPORTMXCTR1_FSSEL_MASK, v);
383 return 0;
387 * aio_port_set_fmt - set format of I2S data
388 * @sub: the AIO substream pointer, PCM substream only
389 * This parameter has no effect if substream is I2S or PCM.
391 * Set suitable I2S format settings to input/output port block of AIO.
392 * Parameter is specified by set_fmt().
394 * This function may return error if non-PCM substream.
396 * Return: Zero if successful, otherwise a negative value on error.
398 int aio_port_set_fmt(struct uniphier_aio_sub *sub)
400 struct regmap *r = sub->aio->chip->regmap;
401 struct device *dev = &sub->aio->chip->pdev->dev;
402 u32 v;
404 if (sub->swm->dir == PORT_DIR_OUTPUT) {
405 switch (sub->aio->fmt) {
406 case SND_SOC_DAIFMT_LEFT_J:
407 v = OPORTMXCTR1_I2SLRSEL_LEFT;
408 break;
409 case SND_SOC_DAIFMT_RIGHT_J:
410 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
411 break;
412 case SND_SOC_DAIFMT_I2S:
413 v = OPORTMXCTR1_I2SLRSEL_I2S;
414 break;
415 default:
416 dev_err(dev, "Format is not supported(%d)\n",
417 sub->aio->fmt);
418 return -EINVAL;
421 v |= OPORTMXCTR1_OUTBITSEL_24;
422 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
423 OPORTMXCTR1_I2SLRSEL_MASK |
424 OPORTMXCTR1_OUTBITSEL_MASK, v);
425 } else {
426 switch (sub->aio->fmt) {
427 case SND_SOC_DAIFMT_LEFT_J:
428 v = IPORTMXCTR1_LRSEL_LEFT;
429 break;
430 case SND_SOC_DAIFMT_RIGHT_J:
431 v = IPORTMXCTR1_LRSEL_RIGHT;
432 break;
433 case SND_SOC_DAIFMT_I2S:
434 v = IPORTMXCTR1_LRSEL_I2S;
435 break;
436 default:
437 dev_err(dev, "Format is not supported(%d)\n",
438 sub->aio->fmt);
439 return -EINVAL;
442 v |= IPORTMXCTR1_OUTBITSEL_24 |
443 IPORTMXCTR1_CHSEL_ALL;
444 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
445 IPORTMXCTR1_LRSEL_MASK |
446 IPORTMXCTR1_OUTBITSEL_MASK |
447 IPORTMXCTR1_CHSEL_MASK, v);
450 return 0;
454 * aio_port_set_clk - set clock and divider of AIO port block
455 * @sub: the AIO substream pointer
457 * Set suitable PLL clock divider and relational settings to
458 * input/output port block of AIO. Parameters are specified by
459 * set_sysclk() and set_pll().
461 * Return: Zero if successful, otherwise a negative value on error.
463 int aio_port_set_clk(struct uniphier_aio_sub *sub)
465 struct uniphier_aio_chip *chip = sub->aio->chip;
466 struct device *dev = &sub->aio->chip->pdev->dev;
467 struct regmap *r = sub->aio->chip->regmap;
468 u32 v_pll[] = {
469 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
470 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
471 OPORTMXCTR2_ACLKSEL_A2PLL,
472 OPORTMXCTR2_ACLKSEL_RX1,
474 u32 v_div[] = {
475 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
476 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
478 u32 v;
480 if (sub->swm->dir == PORT_DIR_OUTPUT) {
481 if (sub->swm->type == PORT_TYPE_I2S) {
482 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
483 dev_err(dev, "PLL(%d) is invalid\n",
484 sub->aio->pll_out);
485 return -EINVAL;
487 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
488 dev_err(dev, "PLL divider(%d) is invalid\n",
489 sub->aio->plldiv);
490 return -EINVAL;
493 v = v_pll[sub->aio->pll_out] |
494 OPORTMXCTR2_MSSEL_MASTER |
495 v_div[sub->aio->plldiv];
497 switch (chip->plls[sub->aio->pll_out].freq) {
498 case 0:
499 case 36864000:
500 case 33868800:
501 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
502 break;
503 default:
504 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
505 break;
507 } else if (sub->swm->type == PORT_TYPE_EVE) {
508 v = OPORTMXCTR2_ACLKSEL_A2PLL |
509 OPORTMXCTR2_MSSEL_MASTER |
510 OPORTMXCTR2_EXTLSIFSSEL_36 |
511 OPORTMXCTR2_DACCKSEL_1_2;
512 } else if (sub->swm->type == PORT_TYPE_SPDIF) {
513 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
514 dev_err(dev, "PLL(%d) is invalid\n",
515 sub->aio->pll_out);
516 return -EINVAL;
518 v = v_pll[sub->aio->pll_out] |
519 OPORTMXCTR2_MSSEL_MASTER |
520 OPORTMXCTR2_DACCKSEL_1_2;
522 switch (chip->plls[sub->aio->pll_out].freq) {
523 case 0:
524 case 36864000:
525 case 33868800:
526 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
527 break;
528 default:
529 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
530 break;
532 } else {
533 v = OPORTMXCTR2_ACLKSEL_A1 |
534 OPORTMXCTR2_MSSEL_MASTER |
535 OPORTMXCTR2_EXTLSIFSSEL_36 |
536 OPORTMXCTR2_DACCKSEL_1_2;
538 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
539 } else {
540 v = IPORTMXCTR2_ACLKSEL_A1 |
541 IPORTMXCTR2_MSSEL_SLAVE |
542 IPORTMXCTR2_EXTLSIFSSEL_36 |
543 IPORTMXCTR2_DACCKSEL_1_2;
544 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
547 return 0;
551 * aio_port_set_param - set parameters of AIO port block
552 * @sub: the AIO substream pointer
553 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
554 * This parameter has no effect if substream is I2S or PCM.
555 * @params: hardware parameters of ALSA
557 * Set suitable setting to input/output port block of AIO to process the
558 * specified in params.
560 * Return: Zero if successful, otherwise a negative value on error.
562 int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
563 const struct snd_pcm_hw_params *params)
565 struct regmap *r = sub->aio->chip->regmap;
566 unsigned int rate;
567 u32 v;
568 int ret;
570 if (!pass_through) {
571 if (sub->swm->type == PORT_TYPE_EVE ||
572 sub->swm->type == PORT_TYPE_CONV) {
573 rate = 48000;
574 } else {
575 rate = params_rate(params);
578 ret = aio_port_set_rate(sub, rate);
579 if (ret)
580 return ret;
582 ret = aio_port_set_fmt(sub);
583 if (ret)
584 return ret;
587 ret = aio_port_set_clk(sub);
588 if (ret)
589 return ret;
591 if (sub->swm->dir == PORT_DIR_OUTPUT) {
592 if (pass_through)
593 v = OPORTMXCTR3_SRCSEL_STREAM |
594 OPORTMXCTR3_VALID_STREAM;
595 else
596 v = OPORTMXCTR3_SRCSEL_PCM |
597 OPORTMXCTR3_VALID_PCM;
599 v |= OPORTMXCTR3_IECTHUR_IECOUT |
600 OPORTMXCTR3_PMSEL_PAUSE |
601 OPORTMXCTR3_PMSW_MUTE_OFF;
602 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
603 } else {
604 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
605 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
606 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
607 IPORTMXEXNOE_PCMINOE_INPUT);
610 return 0;
614 * aio_port_set_enable - start or stop of AIO port block
615 * @sub: the AIO substream pointer
616 * @enable: zero to stop the block, otherwise to start
618 * Start or stop the signal input/output port block of AIO.
620 void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
622 struct regmap *r = sub->aio->chip->regmap;
624 if (sub->swm->dir == PORT_DIR_OUTPUT) {
625 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
626 sub->swm->oif.map);
628 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
629 OPORTMXMASK_IUDXMSK_MASK |
630 OPORTMXMASK_IUXCKMSK_MASK |
631 OPORTMXMASK_DXMSK_MASK |
632 OPORTMXMASK_XCKMSK_MASK,
633 OPORTMXMASK_IUDXMSK_OFF |
634 OPORTMXMASK_IUXCKMSK_OFF |
635 OPORTMXMASK_DXMSK_OFF |
636 OPORTMXMASK_XCKMSK_OFF);
638 if (enable)
639 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
640 else
641 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
642 } else {
643 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
644 IPORTMXMASK_IUXCKMSK_MASK |
645 IPORTMXMASK_XCKMSK_MASK,
646 IPORTMXMASK_IUXCKMSK_OFF |
647 IPORTMXMASK_XCKMSK_OFF);
649 if (enable)
650 regmap_update_bits(r,
651 IPORTMXCTR2(sub->swm->iport.map),
652 IPORTMXCTR2_REQEN_MASK,
653 IPORTMXCTR2_REQEN_ENABLE);
654 else
655 regmap_update_bits(r,
656 IPORTMXCTR2(sub->swm->iport.map),
657 IPORTMXCTR2_REQEN_MASK,
658 IPORTMXCTR2_REQEN_DISABLE);
663 * aio_port_get_volume - get volume of AIO port block
664 * @sub: the AIO substream pointer
666 * Return: current volume, range is 0x0000 - 0xffff
668 int aio_port_get_volume(struct uniphier_aio_sub *sub)
670 struct regmap *r = sub->aio->chip->regmap;
671 u32 v;
673 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
675 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
679 * aio_port_set_volume - set volume of AIO port block
680 * @sub: the AIO substream pointer
681 * @vol: target volume, range is 0x0000 - 0xffff.
683 * Change digital volume and perfome fade-out/fade-in effect for specified
684 * output slot of port. Gained PCM value can calculate as the following:
685 * Gained = Original * vol / 0x4000
687 void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
689 struct regmap *r = sub->aio->chip->regmap;
690 int oport_map = sub->swm->oport.map;
691 int cur, diff, slope = 0, fs;
693 if (sub->swm->dir == PORT_DIR_INPUT)
694 return;
696 cur = aio_port_get_volume(sub);
697 diff = abs(vol - cur);
698 fs = params_rate(&sub->params);
699 if (fs)
700 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
701 slope = max(1, slope);
703 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
704 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
705 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
706 OPORTMXTYVOLPARA2_TARGET_MASK, vol);
708 if (cur < vol)
709 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
710 OPORTMXTYVOLPARA2_FADE_MASK,
711 OPORTMXTYVOLPARA2_FADE_FADEIN);
712 else
713 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
714 OPORTMXTYVOLPARA2_FADE_MASK,
715 OPORTMXTYVOLPARA2_FADE_FADEOUT);
717 regmap_write(r, AOUTFADECTR0, BIT(oport_map));
721 * aio_if_set_param - set parameters of AIO DMA I/F block
722 * @sub: the AIO substream pointer
723 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
724 * This parameter has no effect if substream is I2S or PCM.
726 * Set suitable setting to DMA interface block of AIO to process the
727 * specified in settings.
729 * Return: Zero if successful, otherwise a negative value on error.
731 int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
733 struct regmap *r = sub->aio->chip->regmap;
734 u32 v;
736 if (sub->swm->dir == PORT_DIR_OUTPUT) {
737 if (pass_through)
738 v = PBOUTMXCTR0_ENDIAN_0123 |
739 PBOUTMXCTR0_MEMFMT_STREAM;
740 else
741 v = PBOUTMXCTR0_ENDIAN_3210 |
742 PBOUTMXCTR0_MEMFMT_2CH;
744 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
745 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
746 } else {
747 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
748 PBINMXCTR_NCONNECT_CONNECT |
749 PBINMXCTR_INOUTSEL_IN |
750 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
751 PBINMXCTR_ENDIAN_3210 |
752 PBINMXCTR_MEMFMT_D0);
755 return 0;
759 * aio_oport_set_stream_type - set parameters of AIO playback port block
760 * @sub: the AIO substream pointer
761 * @pc: Pc type of IEC61937
763 * Set special setting to output port block of AIO to output the stream
764 * via S/PDIF.
766 * Return: Zero if successful, otherwise a negative value on error.
768 int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
769 enum IEC61937_PC pc)
771 struct regmap *r = sub->aio->chip->regmap;
772 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
774 switch (pc) {
775 case IEC61937_PC_AC3:
776 repet = OPORTMXREPET_STRLENGTH_AC3 |
777 OPORTMXREPET_PMLENGTH_AC3;
778 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
779 break;
780 case IEC61937_PC_MPA:
781 repet = OPORTMXREPET_STRLENGTH_MPA |
782 OPORTMXREPET_PMLENGTH_MPA;
783 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
784 break;
785 case IEC61937_PC_MP3:
786 repet = OPORTMXREPET_STRLENGTH_MP3 |
787 OPORTMXREPET_PMLENGTH_MP3;
788 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
789 break;
790 case IEC61937_PC_DTS1:
791 repet = OPORTMXREPET_STRLENGTH_DTS1 |
792 OPORTMXREPET_PMLENGTH_DTS1;
793 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
794 break;
795 case IEC61937_PC_DTS2:
796 repet = OPORTMXREPET_STRLENGTH_DTS2 |
797 OPORTMXREPET_PMLENGTH_DTS2;
798 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
799 break;
800 case IEC61937_PC_DTS3:
801 repet = OPORTMXREPET_STRLENGTH_DTS3 |
802 OPORTMXREPET_PMLENGTH_DTS3;
803 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
804 break;
805 case IEC61937_PC_AAC:
806 repet = OPORTMXREPET_STRLENGTH_AAC |
807 OPORTMXREPET_PMLENGTH_AAC;
808 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
809 break;
810 case IEC61937_PC_PAUSE:
811 /* Do nothing */
812 break;
815 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
816 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
818 return 0;
822 * aio_src_reset - reset AIO SRC block
823 * @sub: the AIO substream pointer
825 * Resets the digital signal input/output port with sampling rate converter
826 * block of AIO.
827 * This function has no effect if substream is not supported rate converter.
829 void aio_src_reset(struct uniphier_aio_sub *sub)
831 struct regmap *r = sub->aio->chip->regmap;
833 if (sub->swm->dir != PORT_DIR_OUTPUT)
834 return;
836 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
837 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
841 * aio_src_set_param - set parameters of AIO SRC block
842 * @sub: the AIO substream pointer
843 * @params: hardware parameters of ALSA
845 * Set suitable setting to input/output port with sampling rate converter
846 * block of AIO to process the specified in params.
847 * This function has no effect if substream is not supported rate converter.
849 * Return: Zero if successful, otherwise a negative value on error.
851 int aio_src_set_param(struct uniphier_aio_sub *sub,
852 const struct snd_pcm_hw_params *params)
854 struct regmap *r = sub->aio->chip->regmap;
855 u32 v;
857 if (sub->swm->dir != PORT_DIR_OUTPUT)
858 return 0;
860 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
861 OPORTMXSRC1CTR_THMODE_SRC |
862 OPORTMXSRC1CTR_SRCPATH_CALC |
863 OPORTMXSRC1CTR_SYNC_ASYNC |
864 OPORTMXSRC1CTR_FSIIPSEL_INNER |
865 OPORTMXSRC1CTR_FSISEL_ACLK);
867 switch (params_rate(params)) {
868 default:
869 case 48000:
870 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
871 OPORTMXRATE_I_MCKSEL_36 |
872 OPORTMXRATE_I_FSSEL_48;
873 break;
874 case 44100:
875 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
876 OPORTMXRATE_I_MCKSEL_33 |
877 OPORTMXRATE_I_FSSEL_44_1;
878 break;
879 case 32000:
880 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
881 OPORTMXRATE_I_MCKSEL_36 |
882 OPORTMXRATE_I_FSSEL_32;
883 break;
886 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
887 v | OPORTMXRATE_I_ACLKSRC_APLL |
888 OPORTMXRATE_I_LRCKSTP_STOP);
889 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
890 OPORTMXRATE_I_LRCKSTP_MASK,
891 OPORTMXRATE_I_LRCKSTP_START);
893 return 0;
896 int aio_srcif_set_param(struct uniphier_aio_sub *sub)
898 struct regmap *r = sub->aio->chip->regmap;
900 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
901 PBINMXCTR_NCONNECT_CONNECT |
902 PBINMXCTR_INOUTSEL_OUT |
903 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
904 PBINMXCTR_ENDIAN_3210 |
905 PBINMXCTR_MEMFMT_D0);
907 return 0;
910 int aio_srcch_set_param(struct uniphier_aio_sub *sub)
912 struct regmap *r = sub->aio->chip->regmap;
914 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
915 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
917 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
918 CDA2D_CHMXAMODE_ENDIAN_3210 |
919 CDA2D_CHMXAMODE_AUPDT_FIX |
920 CDA2D_CHMXAMODE_TYPE_NORMAL);
922 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
923 CDA2D_CHMXAMODE_ENDIAN_3210 |
924 CDA2D_CHMXAMODE_AUPDT_INC |
925 CDA2D_CHMXAMODE_TYPE_RING |
926 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
928 return 0;
931 void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
933 struct regmap *r = sub->aio->chip->regmap;
934 u32 v;
936 if (enable)
937 v = CDA2D_STRT0_STOP_START;
938 else
939 v = CDA2D_STRT0_STOP_STOP;
941 regmap_write(r, CDA2D_STRT0,
942 v | BIT(sub->swm->och.map));
945 int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
947 struct regmap *r = sub->aio->chip->regmap;
948 u32 v;
950 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
951 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
953 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
954 CDA2D_CHMXAMODE_AUPDT_INC |
955 CDA2D_CHMXAMODE_TYPE_NORMAL |
956 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
957 if (sub->swm->dir == PORT_DIR_OUTPUT)
958 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
959 else
960 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
962 return 0;
965 void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
967 struct regmap *r = sub->aio->chip->regmap;
969 if (enable) {
970 regmap_write(r, CDA2D_STRT0,
971 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
973 regmap_update_bits(r, INTRBIM(0),
974 BIT(sub->swm->rb.map),
975 BIT(sub->swm->rb.map));
976 } else {
977 regmap_write(r, CDA2D_STRT0,
978 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
980 regmap_update_bits(r, INTRBIM(0),
981 BIT(sub->swm->rb.map),
986 static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
988 struct regmap *r = sub->aio->chip->regmap;
989 u32 pos_u, pos_l;
990 int i;
992 regmap_write(r, CDA2D_RDPTRLOAD,
993 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
994 /* Wait for setup */
995 for (i = 0; i < 6; i++)
996 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
998 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
999 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1000 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1002 return ((u64)pos_u << 32) | pos_l;
1005 static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1007 struct regmap *r = sub->aio->chip->regmap;
1008 u32 tmp;
1009 int i;
1011 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1012 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1013 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1014 /* Wait for setup */
1015 for (i = 0; i < 6; i++)
1016 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1019 static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1021 struct regmap *r = sub->aio->chip->regmap;
1022 u32 pos_u, pos_l;
1023 int i;
1025 regmap_write(r, CDA2D_WRPTRLOAD,
1026 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1027 /* Wait for setup */
1028 for (i = 0; i < 6; i++)
1029 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1031 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1032 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1033 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1035 return ((u64)pos_u << 32) | pos_l;
1038 static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1040 struct regmap *r = sub->aio->chip->regmap;
1041 u32 tmp;
1042 int i;
1044 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1045 lower_32_bits(pos));
1046 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1047 upper_32_bits(pos));
1048 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1049 /* Wait for setup */
1050 for (i = 0; i < 6; i++)
1051 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1054 int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1056 struct regmap *r = sub->aio->chip->regmap;
1058 if (size <= th)
1059 return -EINVAL;
1061 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1062 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1064 return 0;
1067 int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1068 int period)
1070 struct regmap *r = sub->aio->chip->regmap;
1071 u64 size = end - start;
1072 int ret;
1074 if (end < start || period < 0)
1075 return -EINVAL;
1077 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1078 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1079 lower_32_bits(start));
1080 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1081 upper_32_bits(start));
1082 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1083 lower_32_bits(end));
1084 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1085 upper_32_bits(end));
1087 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1089 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1090 if (ret)
1091 return ret;
1093 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1094 aiodma_rb_set_rp(sub, start);
1095 aiodma_rb_set_wp(sub, end - period);
1097 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1098 CDA2D_RBMXIX_SPACE,
1099 CDA2D_RBMXIX_SPACE);
1100 } else {
1101 aiodma_rb_set_rp(sub, end - period);
1102 aiodma_rb_set_wp(sub, start);
1104 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1105 CDA2D_RBMXIX_REMAIN,
1106 CDA2D_RBMXIX_REMAIN);
1109 sub->threshold = 2 * period;
1110 sub->rd_offs = 0;
1111 sub->wr_offs = 0;
1112 sub->rd_org = 0;
1113 sub->wr_org = 0;
1114 sub->rd_total = 0;
1115 sub->wr_total = 0;
1117 return 0;
1120 void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1121 int period)
1123 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1124 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1126 if (sub->use_mmap) {
1127 sub->threshold = 2 * period;
1128 aiodma_rb_set_threshold(sub, size, 2 * period);
1130 sub->wr_offs = sub->rd_offs - period;
1131 if (sub->rd_offs < period)
1132 sub->wr_offs += size;
1134 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1135 } else {
1136 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1138 if (sub->use_mmap) {
1139 sub->threshold = 2 * period;
1140 aiodma_rb_set_threshold(sub, size, 2 * period);
1142 sub->rd_offs = sub->wr_offs - period;
1143 if (sub->wr_offs < period)
1144 sub->rd_offs += size;
1146 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1149 sub->rd_total += sub->rd_offs - sub->rd_org;
1150 if (sub->rd_offs < sub->rd_org)
1151 sub->rd_total += size;
1152 sub->wr_total += sub->wr_offs - sub->wr_org;
1153 if (sub->wr_offs < sub->wr_org)
1154 sub->wr_total += size;
1156 sub->rd_org = sub->rd_offs;
1157 sub->wr_org = sub->wr_offs;
1160 bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1162 struct regmap *r = sub->aio->chip->regmap;
1163 u32 ir;
1165 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1167 if (sub->swm->dir == PORT_DIR_OUTPUT)
1168 return !!(ir & CDA2D_RBMXIX_SPACE);
1169 else
1170 return !!(ir & CDA2D_RBMXIX_REMAIN);
1173 void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1175 struct regmap *r = sub->aio->chip->regmap;
1177 if (sub->swm->dir == PORT_DIR_OUTPUT)
1178 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1179 CDA2D_RBMXIX_SPACE);
1180 else
1181 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1182 CDA2D_RBMXIX_REMAIN);