treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / sound / soc / uniphier / aio-core.c
blob9bcba06ba52ea36dc06527561aef739641d99fb2
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_ch - set channels of LPCM
269 * @sub: the AIO substream pointer, PCM substream only
270 * @ch : count of channels
272 * Set suitable slot selecting to input/output port block of AIO.
274 * This function may return error if non-PCM substream.
276 * Return: Zero if successful, otherwise a negative value on error.
278 static int aio_port_set_ch(struct uniphier_aio_sub *sub)
280 struct regmap *r = sub->aio->chip->regmap;
281 u32 slotsel_2ch[] = {
282 0, 0, 0, 0, 0,
284 u32 slotsel_multi[] = {
285 OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
286 OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
287 OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
288 OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
289 OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
291 u32 mode, *slotsel;
292 int i;
294 switch (params_channels(&sub->params)) {
295 case 8:
296 case 6:
297 mode = OPORTMXTYSLOTCTR_MODE;
298 slotsel = slotsel_multi;
299 break;
300 case 2:
301 mode = 0;
302 slotsel = slotsel_2ch;
303 break;
304 default:
305 return -EINVAL;
308 for (i = 0; i < AUD_MAX_SLOTSEL; i++) {
309 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
310 OPORTMXTYSLOTCTR_MODE, mode);
311 regmap_update_bits(r, OPORTMXTYSLOTCTR(sub->swm->oport.map, i),
312 OPORTMXTYSLOTCTR_SLOTSEL_MASK, slotsel[i]);
315 return 0;
319 * aio_port_set_rate - set sampling rate of LPCM
320 * @sub: the AIO substream pointer, PCM substream only
321 * @rate: Sampling rate in Hz.
323 * Set suitable I2S format settings to input/output port block of AIO.
324 * Parameter is specified by hw_params().
326 * This function may return error if non-PCM substream.
328 * Return: Zero if successful, otherwise a negative value on error.
330 static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
332 struct regmap *r = sub->aio->chip->regmap;
333 struct device *dev = &sub->aio->chip->pdev->dev;
334 u32 v;
336 if (sub->swm->dir == PORT_DIR_OUTPUT) {
337 switch (rate) {
338 case 8000:
339 v = OPORTMXCTR1_FSSEL_8;
340 break;
341 case 11025:
342 v = OPORTMXCTR1_FSSEL_11_025;
343 break;
344 case 12000:
345 v = OPORTMXCTR1_FSSEL_12;
346 break;
347 case 16000:
348 v = OPORTMXCTR1_FSSEL_16;
349 break;
350 case 22050:
351 v = OPORTMXCTR1_FSSEL_22_05;
352 break;
353 case 24000:
354 v = OPORTMXCTR1_FSSEL_24;
355 break;
356 case 32000:
357 v = OPORTMXCTR1_FSSEL_32;
358 break;
359 case 44100:
360 v = OPORTMXCTR1_FSSEL_44_1;
361 break;
362 case 48000:
363 v = OPORTMXCTR1_FSSEL_48;
364 break;
365 case 88200:
366 v = OPORTMXCTR1_FSSEL_88_2;
367 break;
368 case 96000:
369 v = OPORTMXCTR1_FSSEL_96;
370 break;
371 case 176400:
372 v = OPORTMXCTR1_FSSEL_176_4;
373 break;
374 case 192000:
375 v = OPORTMXCTR1_FSSEL_192;
376 break;
377 default:
378 dev_err(dev, "Rate not supported(%d)\n", rate);
379 return -EINVAL;
382 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
383 OPORTMXCTR1_FSSEL_MASK, v);
384 } else {
385 switch (rate) {
386 case 8000:
387 v = IPORTMXCTR1_FSSEL_8;
388 break;
389 case 11025:
390 v = IPORTMXCTR1_FSSEL_11_025;
391 break;
392 case 12000:
393 v = IPORTMXCTR1_FSSEL_12;
394 break;
395 case 16000:
396 v = IPORTMXCTR1_FSSEL_16;
397 break;
398 case 22050:
399 v = IPORTMXCTR1_FSSEL_22_05;
400 break;
401 case 24000:
402 v = IPORTMXCTR1_FSSEL_24;
403 break;
404 case 32000:
405 v = IPORTMXCTR1_FSSEL_32;
406 break;
407 case 44100:
408 v = IPORTMXCTR1_FSSEL_44_1;
409 break;
410 case 48000:
411 v = IPORTMXCTR1_FSSEL_48;
412 break;
413 case 88200:
414 v = IPORTMXCTR1_FSSEL_88_2;
415 break;
416 case 96000:
417 v = IPORTMXCTR1_FSSEL_96;
418 break;
419 case 176400:
420 v = IPORTMXCTR1_FSSEL_176_4;
421 break;
422 case 192000:
423 v = IPORTMXCTR1_FSSEL_192;
424 break;
425 default:
426 dev_err(dev, "Rate not supported(%d)\n", rate);
427 return -EINVAL;
430 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
431 IPORTMXCTR1_FSSEL_MASK, v);
434 return 0;
438 * aio_port_set_fmt - set format of I2S data
439 * @sub: the AIO substream pointer, PCM substream only
440 * This parameter has no effect if substream is I2S or PCM.
442 * Set suitable I2S format settings to input/output port block of AIO.
443 * Parameter is specified by set_fmt().
445 * This function may return error if non-PCM substream.
447 * Return: Zero if successful, otherwise a negative value on error.
449 static int aio_port_set_fmt(struct uniphier_aio_sub *sub)
451 struct regmap *r = sub->aio->chip->regmap;
452 struct device *dev = &sub->aio->chip->pdev->dev;
453 u32 v;
455 if (sub->swm->dir == PORT_DIR_OUTPUT) {
456 switch (sub->aio->fmt) {
457 case SND_SOC_DAIFMT_LEFT_J:
458 v = OPORTMXCTR1_I2SLRSEL_LEFT;
459 break;
460 case SND_SOC_DAIFMT_RIGHT_J:
461 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
462 break;
463 case SND_SOC_DAIFMT_I2S:
464 v = OPORTMXCTR1_I2SLRSEL_I2S;
465 break;
466 default:
467 dev_err(dev, "Format is not supported(%d)\n",
468 sub->aio->fmt);
469 return -EINVAL;
472 v |= OPORTMXCTR1_OUTBITSEL_24;
473 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
474 OPORTMXCTR1_I2SLRSEL_MASK |
475 OPORTMXCTR1_OUTBITSEL_MASK, v);
476 } else {
477 switch (sub->aio->fmt) {
478 case SND_SOC_DAIFMT_LEFT_J:
479 v = IPORTMXCTR1_LRSEL_LEFT;
480 break;
481 case SND_SOC_DAIFMT_RIGHT_J:
482 v = IPORTMXCTR1_LRSEL_RIGHT;
483 break;
484 case SND_SOC_DAIFMT_I2S:
485 v = IPORTMXCTR1_LRSEL_I2S;
486 break;
487 default:
488 dev_err(dev, "Format is not supported(%d)\n",
489 sub->aio->fmt);
490 return -EINVAL;
493 v |= IPORTMXCTR1_OUTBITSEL_24 |
494 IPORTMXCTR1_CHSEL_ALL;
495 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
496 IPORTMXCTR1_LRSEL_MASK |
497 IPORTMXCTR1_OUTBITSEL_MASK |
498 IPORTMXCTR1_CHSEL_MASK, v);
501 return 0;
505 * aio_port_set_clk - set clock and divider of AIO port block
506 * @sub: the AIO substream pointer
508 * Set suitable PLL clock divider and relational settings to
509 * input/output port block of AIO. Parameters are specified by
510 * set_sysclk() and set_pll().
512 * Return: Zero if successful, otherwise a negative value on error.
514 static int aio_port_set_clk(struct uniphier_aio_sub *sub)
516 struct uniphier_aio_chip *chip = sub->aio->chip;
517 struct device *dev = &sub->aio->chip->pdev->dev;
518 struct regmap *r = sub->aio->chip->regmap;
519 u32 v_pll[] = {
520 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
521 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
522 OPORTMXCTR2_ACLKSEL_A2PLL,
523 OPORTMXCTR2_ACLKSEL_RX1,
525 u32 v_div[] = {
526 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
527 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
529 u32 v;
531 if (sub->swm->dir == PORT_DIR_OUTPUT) {
532 if (sub->swm->type == PORT_TYPE_I2S) {
533 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
534 dev_err(dev, "PLL(%d) is invalid\n",
535 sub->aio->pll_out);
536 return -EINVAL;
538 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
539 dev_err(dev, "PLL divider(%d) is invalid\n",
540 sub->aio->plldiv);
541 return -EINVAL;
544 v = v_pll[sub->aio->pll_out] |
545 OPORTMXCTR2_MSSEL_MASTER |
546 v_div[sub->aio->plldiv];
548 switch (chip->plls[sub->aio->pll_out].freq) {
549 case 0:
550 case 36864000:
551 case 33868800:
552 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
553 break;
554 default:
555 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
556 break;
558 } else if (sub->swm->type == PORT_TYPE_EVE) {
559 v = OPORTMXCTR2_ACLKSEL_A2PLL |
560 OPORTMXCTR2_MSSEL_MASTER |
561 OPORTMXCTR2_EXTLSIFSSEL_36 |
562 OPORTMXCTR2_DACCKSEL_1_2;
563 } else if (sub->swm->type == PORT_TYPE_SPDIF) {
564 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
565 dev_err(dev, "PLL(%d) is invalid\n",
566 sub->aio->pll_out);
567 return -EINVAL;
569 v = v_pll[sub->aio->pll_out] |
570 OPORTMXCTR2_MSSEL_MASTER |
571 OPORTMXCTR2_DACCKSEL_1_2;
573 switch (chip->plls[sub->aio->pll_out].freq) {
574 case 0:
575 case 36864000:
576 case 33868800:
577 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
578 break;
579 default:
580 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
581 break;
583 } else {
584 v = OPORTMXCTR2_ACLKSEL_A1 |
585 OPORTMXCTR2_MSSEL_MASTER |
586 OPORTMXCTR2_EXTLSIFSSEL_36 |
587 OPORTMXCTR2_DACCKSEL_1_2;
589 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
590 } else {
591 v = IPORTMXCTR2_ACLKSEL_A1 |
592 IPORTMXCTR2_MSSEL_SLAVE |
593 IPORTMXCTR2_EXTLSIFSSEL_36 |
594 IPORTMXCTR2_DACCKSEL_1_2;
595 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
598 return 0;
602 * aio_port_set_param - set parameters of AIO port block
603 * @sub: the AIO substream pointer
604 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
605 * This parameter has no effect if substream is I2S or PCM.
606 * @params: hardware parameters of ALSA
608 * Set suitable setting to input/output port block of AIO to process the
609 * specified in params.
611 * Return: Zero if successful, otherwise a negative value on error.
613 int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
614 const struct snd_pcm_hw_params *params)
616 struct regmap *r = sub->aio->chip->regmap;
617 unsigned int rate;
618 u32 v;
619 int ret;
621 if (!pass_through) {
622 if (sub->swm->type == PORT_TYPE_EVE ||
623 sub->swm->type == PORT_TYPE_CONV) {
624 rate = 48000;
625 } else {
626 rate = params_rate(params);
629 ret = aio_port_set_ch(sub);
630 if (ret)
631 return ret;
633 ret = aio_port_set_rate(sub, rate);
634 if (ret)
635 return ret;
637 ret = aio_port_set_fmt(sub);
638 if (ret)
639 return ret;
642 ret = aio_port_set_clk(sub);
643 if (ret)
644 return ret;
646 if (sub->swm->dir == PORT_DIR_OUTPUT) {
647 if (pass_through)
648 v = OPORTMXCTR3_SRCSEL_STREAM |
649 OPORTMXCTR3_VALID_STREAM;
650 else
651 v = OPORTMXCTR3_SRCSEL_PCM |
652 OPORTMXCTR3_VALID_PCM;
654 v |= OPORTMXCTR3_IECTHUR_IECOUT |
655 OPORTMXCTR3_PMSEL_PAUSE |
656 OPORTMXCTR3_PMSW_MUTE_OFF;
657 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
658 } else {
659 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
660 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
661 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
662 IPORTMXEXNOE_PCMINOE_INPUT);
665 return 0;
669 * aio_port_set_enable - start or stop of AIO port block
670 * @sub: the AIO substream pointer
671 * @enable: zero to stop the block, otherwise to start
673 * Start or stop the signal input/output port block of AIO.
675 void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
677 struct regmap *r = sub->aio->chip->regmap;
679 if (sub->swm->dir == PORT_DIR_OUTPUT) {
680 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
681 sub->swm->oif.map);
683 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
684 OPORTMXMASK_IUDXMSK_MASK |
685 OPORTMXMASK_IUXCKMSK_MASK |
686 OPORTMXMASK_DXMSK_MASK |
687 OPORTMXMASK_XCKMSK_MASK,
688 OPORTMXMASK_IUDXMSK_OFF |
689 OPORTMXMASK_IUXCKMSK_OFF |
690 OPORTMXMASK_DXMSK_OFF |
691 OPORTMXMASK_XCKMSK_OFF);
693 if (enable)
694 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
695 else
696 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
697 } else {
698 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
699 IPORTMXMASK_IUXCKMSK_MASK |
700 IPORTMXMASK_XCKMSK_MASK,
701 IPORTMXMASK_IUXCKMSK_OFF |
702 IPORTMXMASK_XCKMSK_OFF);
704 if (enable)
705 regmap_update_bits(r,
706 IPORTMXCTR2(sub->swm->iport.map),
707 IPORTMXCTR2_REQEN_MASK,
708 IPORTMXCTR2_REQEN_ENABLE);
709 else
710 regmap_update_bits(r,
711 IPORTMXCTR2(sub->swm->iport.map),
712 IPORTMXCTR2_REQEN_MASK,
713 IPORTMXCTR2_REQEN_DISABLE);
718 * aio_port_get_volume - get volume of AIO port block
719 * @sub: the AIO substream pointer
721 * Return: current volume, range is 0x0000 - 0xffff
723 int aio_port_get_volume(struct uniphier_aio_sub *sub)
725 struct regmap *r = sub->aio->chip->regmap;
726 u32 v;
728 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
730 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
734 * aio_port_set_volume - set volume of AIO port block
735 * @sub: the AIO substream pointer
736 * @vol: target volume, range is 0x0000 - 0xffff.
738 * Change digital volume and perfome fade-out/fade-in effect for specified
739 * output slot of port. Gained PCM value can calculate as the following:
740 * Gained = Original * vol / 0x4000
742 void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
744 struct regmap *r = sub->aio->chip->regmap;
745 int oport_map = sub->swm->oport.map;
746 int cur, diff, slope = 0, fs;
748 if (sub->swm->dir == PORT_DIR_INPUT)
749 return;
751 cur = aio_port_get_volume(sub);
752 diff = abs(vol - cur);
753 fs = params_rate(&sub->params);
754 if (fs)
755 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
756 slope = max(1, slope);
758 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
759 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
760 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
761 OPORTMXTYVOLPARA2_TARGET_MASK, vol);
763 if (cur < vol)
764 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
765 OPORTMXTYVOLPARA2_FADE_MASK,
766 OPORTMXTYVOLPARA2_FADE_FADEIN);
767 else
768 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
769 OPORTMXTYVOLPARA2_FADE_MASK,
770 OPORTMXTYVOLPARA2_FADE_FADEOUT);
772 regmap_write(r, AOUTFADECTR0, BIT(oport_map));
776 * aio_if_set_param - set parameters of AIO DMA I/F block
777 * @sub: the AIO substream pointer
778 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
779 * This parameter has no effect if substream is I2S or PCM.
781 * Set suitable setting to DMA interface block of AIO to process the
782 * specified in settings.
784 * Return: Zero if successful, otherwise a negative value on error.
786 int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
788 struct regmap *r = sub->aio->chip->regmap;
789 u32 memfmt, v;
791 if (sub->swm->dir == PORT_DIR_OUTPUT) {
792 if (pass_through) {
793 v = PBOUTMXCTR0_ENDIAN_0123 |
794 PBOUTMXCTR0_MEMFMT_STREAM;
795 } else {
796 switch (params_channels(&sub->params)) {
797 case 2:
798 memfmt = PBOUTMXCTR0_MEMFMT_2CH;
799 break;
800 case 6:
801 memfmt = PBOUTMXCTR0_MEMFMT_6CH;
802 break;
803 case 8:
804 memfmt = PBOUTMXCTR0_MEMFMT_8CH;
805 break;
806 default:
807 return -EINVAL;
809 v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
812 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
813 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
814 } else {
815 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
816 PBINMXCTR_NCONNECT_CONNECT |
817 PBINMXCTR_INOUTSEL_IN |
818 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
819 PBINMXCTR_ENDIAN_3210 |
820 PBINMXCTR_MEMFMT_D0);
823 return 0;
827 * aio_oport_set_stream_type - set parameters of AIO playback port block
828 * @sub: the AIO substream pointer
829 * @pc: Pc type of IEC61937
831 * Set special setting to output port block of AIO to output the stream
832 * via S/PDIF.
834 * Return: Zero if successful, otherwise a negative value on error.
836 int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
837 enum IEC61937_PC pc)
839 struct regmap *r = sub->aio->chip->regmap;
840 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
842 switch (pc) {
843 case IEC61937_PC_AC3:
844 repet = OPORTMXREPET_STRLENGTH_AC3 |
845 OPORTMXREPET_PMLENGTH_AC3;
846 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
847 break;
848 case IEC61937_PC_MPA:
849 repet = OPORTMXREPET_STRLENGTH_MPA |
850 OPORTMXREPET_PMLENGTH_MPA;
851 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
852 break;
853 case IEC61937_PC_MP3:
854 repet = OPORTMXREPET_STRLENGTH_MP3 |
855 OPORTMXREPET_PMLENGTH_MP3;
856 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
857 break;
858 case IEC61937_PC_DTS1:
859 repet = OPORTMXREPET_STRLENGTH_DTS1 |
860 OPORTMXREPET_PMLENGTH_DTS1;
861 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
862 break;
863 case IEC61937_PC_DTS2:
864 repet = OPORTMXREPET_STRLENGTH_DTS2 |
865 OPORTMXREPET_PMLENGTH_DTS2;
866 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
867 break;
868 case IEC61937_PC_DTS3:
869 repet = OPORTMXREPET_STRLENGTH_DTS3 |
870 OPORTMXREPET_PMLENGTH_DTS3;
871 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
872 break;
873 case IEC61937_PC_AAC:
874 repet = OPORTMXREPET_STRLENGTH_AAC |
875 OPORTMXREPET_PMLENGTH_AAC;
876 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
877 break;
878 case IEC61937_PC_PAUSE:
879 /* Do nothing */
880 break;
883 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
884 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
886 return 0;
890 * aio_src_reset - reset AIO SRC block
891 * @sub: the AIO substream pointer
893 * Resets the digital signal input/output port with sampling rate converter
894 * block of AIO.
895 * This function has no effect if substream is not supported rate converter.
897 void aio_src_reset(struct uniphier_aio_sub *sub)
899 struct regmap *r = sub->aio->chip->regmap;
901 if (sub->swm->dir != PORT_DIR_OUTPUT)
902 return;
904 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
905 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
909 * aio_src_set_param - set parameters of AIO SRC block
910 * @sub: the AIO substream pointer
911 * @params: hardware parameters of ALSA
913 * Set suitable setting to input/output port with sampling rate converter
914 * block of AIO to process the specified in params.
915 * This function has no effect if substream is not supported rate converter.
917 * Return: Zero if successful, otherwise a negative value on error.
919 int aio_src_set_param(struct uniphier_aio_sub *sub,
920 const struct snd_pcm_hw_params *params)
922 struct regmap *r = sub->aio->chip->regmap;
923 u32 v;
925 if (sub->swm->dir != PORT_DIR_OUTPUT)
926 return 0;
928 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
929 OPORTMXSRC1CTR_THMODE_SRC |
930 OPORTMXSRC1CTR_SRCPATH_CALC |
931 OPORTMXSRC1CTR_SYNC_ASYNC |
932 OPORTMXSRC1CTR_FSIIPSEL_INNER |
933 OPORTMXSRC1CTR_FSISEL_ACLK);
935 switch (params_rate(params)) {
936 default:
937 case 48000:
938 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
939 OPORTMXRATE_I_MCKSEL_36 |
940 OPORTMXRATE_I_FSSEL_48;
941 break;
942 case 44100:
943 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
944 OPORTMXRATE_I_MCKSEL_33 |
945 OPORTMXRATE_I_FSSEL_44_1;
946 break;
947 case 32000:
948 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
949 OPORTMXRATE_I_MCKSEL_36 |
950 OPORTMXRATE_I_FSSEL_32;
951 break;
954 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
955 v | OPORTMXRATE_I_ACLKSRC_APLL |
956 OPORTMXRATE_I_LRCKSTP_STOP);
957 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
958 OPORTMXRATE_I_LRCKSTP_MASK,
959 OPORTMXRATE_I_LRCKSTP_START);
961 return 0;
964 int aio_srcif_set_param(struct uniphier_aio_sub *sub)
966 struct regmap *r = sub->aio->chip->regmap;
968 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
969 PBINMXCTR_NCONNECT_CONNECT |
970 PBINMXCTR_INOUTSEL_OUT |
971 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
972 PBINMXCTR_ENDIAN_3210 |
973 PBINMXCTR_MEMFMT_D0);
975 return 0;
978 int aio_srcch_set_param(struct uniphier_aio_sub *sub)
980 struct regmap *r = sub->aio->chip->regmap;
982 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
983 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
985 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
986 CDA2D_CHMXAMODE_ENDIAN_3210 |
987 CDA2D_CHMXAMODE_AUPDT_FIX |
988 CDA2D_CHMXAMODE_TYPE_NORMAL);
990 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
991 CDA2D_CHMXAMODE_ENDIAN_3210 |
992 CDA2D_CHMXAMODE_AUPDT_INC |
993 CDA2D_CHMXAMODE_TYPE_RING |
994 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
996 return 0;
999 void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
1001 struct regmap *r = sub->aio->chip->regmap;
1002 u32 v;
1004 if (enable)
1005 v = CDA2D_STRT0_STOP_START;
1006 else
1007 v = CDA2D_STRT0_STOP_STOP;
1009 regmap_write(r, CDA2D_STRT0,
1010 v | BIT(sub->swm->och.map));
1013 int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
1015 struct regmap *r = sub->aio->chip->regmap;
1016 u32 v;
1018 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
1019 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
1021 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
1022 CDA2D_CHMXAMODE_AUPDT_INC |
1023 CDA2D_CHMXAMODE_TYPE_NORMAL |
1024 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
1025 if (sub->swm->dir == PORT_DIR_OUTPUT)
1026 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
1027 else
1028 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
1030 return 0;
1033 void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
1035 struct regmap *r = sub->aio->chip->regmap;
1037 if (enable) {
1038 regmap_write(r, CDA2D_STRT0,
1039 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
1041 regmap_update_bits(r, INTRBIM(0),
1042 BIT(sub->swm->rb.map),
1043 BIT(sub->swm->rb.map));
1044 } else {
1045 regmap_write(r, CDA2D_STRT0,
1046 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
1048 regmap_update_bits(r, INTRBIM(0),
1049 BIT(sub->swm->rb.map),
1054 static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
1056 struct regmap *r = sub->aio->chip->regmap;
1057 u32 pos_u, pos_l;
1058 int i;
1060 regmap_write(r, CDA2D_RDPTRLOAD,
1061 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1062 /* Wait for setup */
1063 for (i = 0; i < 6; i++)
1064 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1066 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1067 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1068 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1070 return ((u64)pos_u << 32) | pos_l;
1073 static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1075 struct regmap *r = sub->aio->chip->regmap;
1076 u32 tmp;
1077 int i;
1079 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1080 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1081 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1082 /* Wait for setup */
1083 for (i = 0; i < 6; i++)
1084 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1087 static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1089 struct regmap *r = sub->aio->chip->regmap;
1090 u32 pos_u, pos_l;
1091 int i;
1093 regmap_write(r, CDA2D_WRPTRLOAD,
1094 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1095 /* Wait for setup */
1096 for (i = 0; i < 6; i++)
1097 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1099 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1100 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1101 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1103 return ((u64)pos_u << 32) | pos_l;
1106 static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1108 struct regmap *r = sub->aio->chip->regmap;
1109 u32 tmp;
1110 int i;
1112 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1113 lower_32_bits(pos));
1114 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1115 upper_32_bits(pos));
1116 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1117 /* Wait for setup */
1118 for (i = 0; i < 6; i++)
1119 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1122 int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1124 struct regmap *r = sub->aio->chip->regmap;
1126 if (size <= th)
1127 return -EINVAL;
1129 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1130 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1132 return 0;
1135 int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1136 int period)
1138 struct regmap *r = sub->aio->chip->regmap;
1139 u64 size = end - start;
1140 int ret;
1142 if (end < start || period < 0)
1143 return -EINVAL;
1145 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1146 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1147 lower_32_bits(start));
1148 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1149 upper_32_bits(start));
1150 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1151 lower_32_bits(end));
1152 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1153 upper_32_bits(end));
1155 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1157 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1158 if (ret)
1159 return ret;
1161 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1162 aiodma_rb_set_rp(sub, start);
1163 aiodma_rb_set_wp(sub, end - period);
1165 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1166 CDA2D_RBMXIX_SPACE,
1167 CDA2D_RBMXIX_SPACE);
1168 } else {
1169 aiodma_rb_set_rp(sub, end - period);
1170 aiodma_rb_set_wp(sub, start);
1172 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1173 CDA2D_RBMXIX_REMAIN,
1174 CDA2D_RBMXIX_REMAIN);
1177 sub->threshold = 2 * period;
1178 sub->rd_offs = 0;
1179 sub->wr_offs = 0;
1180 sub->rd_org = 0;
1181 sub->wr_org = 0;
1182 sub->rd_total = 0;
1183 sub->wr_total = 0;
1185 return 0;
1188 void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1189 int period)
1191 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1192 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1194 if (sub->use_mmap) {
1195 sub->threshold = 2 * period;
1196 aiodma_rb_set_threshold(sub, size, 2 * period);
1198 sub->wr_offs = sub->rd_offs - period;
1199 if (sub->rd_offs < period)
1200 sub->wr_offs += size;
1202 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1203 } else {
1204 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1206 if (sub->use_mmap) {
1207 sub->threshold = 2 * period;
1208 aiodma_rb_set_threshold(sub, size, 2 * period);
1210 sub->rd_offs = sub->wr_offs - period;
1211 if (sub->wr_offs < period)
1212 sub->rd_offs += size;
1214 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1217 sub->rd_total += sub->rd_offs - sub->rd_org;
1218 if (sub->rd_offs < sub->rd_org)
1219 sub->rd_total += size;
1220 sub->wr_total += sub->wr_offs - sub->wr_org;
1221 if (sub->wr_offs < sub->wr_org)
1222 sub->wr_total += size;
1224 sub->rd_org = sub->rd_offs;
1225 sub->wr_org = sub->wr_offs;
1228 bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1230 struct regmap *r = sub->aio->chip->regmap;
1231 u32 ir;
1233 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1235 if (sub->swm->dir == PORT_DIR_OUTPUT)
1236 return !!(ir & CDA2D_RBMXIX_SPACE);
1237 else
1238 return !!(ir & CDA2D_RBMXIX_REMAIN);
1241 void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1243 struct regmap *r = sub->aio->chip->regmap;
1245 if (sub->swm->dir == PORT_DIR_OUTPUT)
1246 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1247 CDA2D_RBMXIX_SPACE);
1248 else
1249 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1250 CDA2D_RBMXIX_REMAIN);