Loading...
1// SPDX-License-Identifier: GPL-2.0
2//
3// Socionext UniPhier AIO ALSA common driver.
4//
5// Copyright (c) 2016-2018 Socionext Inc.
6
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>
15
16#include "aio.h"
17#include "aio-reg.h"
18
19static u64 rb_cnt(u64 wr, u64 rd, u64 len)
20{
21 if (rd <= wr)
22 return wr - rd;
23 else
24 return len - (rd - wr);
25}
26
27static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
28{
29 if (rd <= wr)
30 return wr - rd;
31 else
32 return len - rd;
33}
34
35static u64 rb_space(u64 wr, u64 rd, u64 len)
36{
37 if (rd <= wr)
38 return len - (wr - rd) - 8;
39 else
40 return rd - wr - 8;
41}
42
43static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
44{
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;
51}
52
53u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
54{
55 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
56}
57
58u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
59{
60 return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
61}
62
63u64 aio_rb_space(struct uniphier_aio_sub *sub)
64{
65 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
66}
67
68u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
69{
70 return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
71}
72
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
77 *
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.
80 *
81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
82 * of DT. This function has no effect if no property.
83 */
84void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
85{
86 struct regmap *r = chip->regmap_sg;
87
88 if (!r)
89 return;
90
91 regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
92}
93
94/**
95 * aio_chip_set_pll - set frequency to audio PLL
96 * @chip: the AIO chip pointer
97 * @pll_id: PLL
98 * @freq: frequency in Hz, 0 is ignored
99 *
100 * Sets frequency of audio PLL. This function can be called anytime,
101 * but it takes time till PLL is locked.
102 *
103 * Return: Zero if successful, otherwise a negative value on error.
104 */
105int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
106 unsigned int freq)
107{
108 struct device *dev = &chip->pdev->dev;
109 struct regmap *r = chip->regmap;
110 int shift;
111 u32 v;
112
113 /* Not change */
114 if (freq == 0)
115 return 0;
116
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;
133 }
134
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;
145 }
146 chip->plls[pll_id].freq = freq;
147
148 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
149 v << shift);
150
151 return 0;
152}
153
154/**
155 * aio_chip_init - initialize AIO whole settings
156 * @chip: the AIO chip pointer
157 *
158 * Sets AIO fixed and whole device settings to AIO.
159 * This function need to call once at driver startup.
160 *
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.
164 */
165void aio_chip_init(struct uniphier_aio_chip *chip)
166{
167 struct regmap *r = chip->regmap;
168
169 regmap_update_bits(r, A2APLLCTR0,
170 A2APLLCTR0_APLLXPOW_MASK,
171 A2APLLCTR0_APLLXPOW_PWON);
172
173 regmap_update_bits(r, A2EXMCLKSEL0,
174 A2EXMCLKSEL0_EXMCLK_MASK,
175 A2EXMCLKSEL0_EXMCLK_OUTPUT);
176
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);
182
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);
189}
190
191/**
192 * aio_init - initialize AIO substream
193 * @sub: the AIO substream pointer
194 *
195 * Sets fixed settings of each AIO substreams.
196 * This function need to call once at substream startup.
197 *
198 * Return: Zero if successful, otherwise a negative value on error.
199 */
200int aio_init(struct uniphier_aio_sub *sub)
201{
202 struct device *dev = &sub->aio->chip->pdev->dev;
203 struct regmap *r = sub->aio->chip->regmap;
204
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);
209
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);
224 }
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;
239 }
240
241 return 0;
242}
243
244/**
245 * aio_port_reset - reset AIO port block
246 * @sub: the AIO substream pointer
247 *
248 * Resets the digital signal input/output port block of AIO.
249 */
250void aio_port_reset(struct uniphier_aio_sub *sub)
251{
252 struct regmap *r = sub->aio->chip->regmap;
253
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);
264 }
265}
266
267/**
268 * aio_port_set_ch - set channels of LPCM
269 * @sub: the AIO substream pointer, PCM substream only
270 *
271 * Set suitable slot selecting to input/output port block of AIO.
272 *
273 * This function may return error if non-PCM substream.
274 *
275 * Return: Zero if successful, otherwise a negative value on error.
276 */
277static int aio_port_set_ch(struct uniphier_aio_sub *sub)
278{
279 struct regmap *r = sub->aio->chip->regmap;
280 static const u32 slotsel_2ch[] = {
281 0, 0, 0, 0, 0,
282 };
283 static const u32 slotsel_multi[] = {
284 OPORTMXTYSLOTCTR_SLOTSEL_SLOT0,
285 OPORTMXTYSLOTCTR_SLOTSEL_SLOT1,
286 OPORTMXTYSLOTCTR_SLOTSEL_SLOT2,
287 OPORTMXTYSLOTCTR_SLOTSEL_SLOT3,
288 OPORTMXTYSLOTCTR_SLOTSEL_SLOT4,
289 };
290 u32 mode;
291 const u32 *slotsel;
292 int i;
293
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;
306 }
307
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]);
313 }
314
315 return 0;
316}
317
318/**
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.
322 *
323 * Set suitable I2S format settings to input/output port block of AIO.
324 * Parameter is specified by hw_params().
325 *
326 * This function may return error if non-PCM substream.
327 *
328 * Return: Zero if successful, otherwise a negative value on error.
329 */
330static int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
331{
332 struct regmap *r = sub->aio->chip->regmap;
333 struct device *dev = &sub->aio->chip->pdev->dev;
334 u32 v;
335
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;
380 }
381
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;
428 }
429
430 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
431 IPORTMXCTR1_FSSEL_MASK, v);
432 }
433
434 return 0;
435}
436
437/**
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.
441 *
442 * Set suitable I2S format settings to input/output port block of AIO.
443 * Parameter is specified by set_fmt().
444 *
445 * This function may return error if non-PCM substream.
446 *
447 * Return: Zero if successful, otherwise a negative value on error.
448 */
449static int aio_port_set_fmt(struct uniphier_aio_sub *sub)
450{
451 struct regmap *r = sub->aio->chip->regmap;
452 struct device *dev = &sub->aio->chip->pdev->dev;
453 u32 v;
454
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;
470 }
471
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;
491 }
492
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);
499 }
500
501 return 0;
502}
503
504/**
505 * aio_port_set_clk - set clock and divider of AIO port block
506 * @sub: the AIO substream pointer
507 *
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().
511 *
512 * Return: Zero if successful, otherwise a negative value on error.
513 */
514static int aio_port_set_clk(struct uniphier_aio_sub *sub)
515{
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 static const 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,
524 };
525 static const u32 v_div[] = {
526 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
527 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
528 };
529 u32 v;
530
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;
537 }
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;
542 }
543
544 v = v_pll[sub->aio->pll_out] |
545 OPORTMXCTR2_MSSEL_MASTER |
546 v_div[sub->aio->plldiv];
547
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;
557 }
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;
568 }
569 v = v_pll[sub->aio->pll_out] |
570 OPORTMXCTR2_MSSEL_MASTER |
571 OPORTMXCTR2_DACCKSEL_1_2;
572
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;
582 }
583 } else {
584 v = OPORTMXCTR2_ACLKSEL_A1 |
585 OPORTMXCTR2_MSSEL_MASTER |
586 OPORTMXCTR2_EXTLSIFSSEL_36 |
587 OPORTMXCTR2_DACCKSEL_1_2;
588 }
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);
596 }
597
598 return 0;
599}
600
601/**
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
607 *
608 * Set suitable setting to input/output port block of AIO to process the
609 * specified in params.
610 *
611 * Return: Zero if successful, otherwise a negative value on error.
612 */
613int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
614 const struct snd_pcm_hw_params *params)
615{
616 struct regmap *r = sub->aio->chip->regmap;
617 unsigned int rate;
618 u32 v;
619 int ret;
620
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);
627 }
628
629 ret = aio_port_set_ch(sub);
630 if (ret)
631 return ret;
632
633 ret = aio_port_set_rate(sub, rate);
634 if (ret)
635 return ret;
636
637 ret = aio_port_set_fmt(sub);
638 if (ret)
639 return ret;
640 }
641
642 ret = aio_port_set_clk(sub);
643 if (ret)
644 return ret;
645
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;
653
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);
663 }
664
665 return 0;
666}
667
668/**
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
672 *
673 * Start or stop the signal input/output port block of AIO.
674 */
675void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
676{
677 struct regmap *r = sub->aio->chip->regmap;
678
679 if (sub->swm->dir == PORT_DIR_OUTPUT) {
680 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
681 sub->swm->oif.map);
682
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);
692
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);
703
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);
714 }
715}
716
717/**
718 * aio_port_get_volume - get volume of AIO port block
719 * @sub: the AIO substream pointer
720 *
721 * Return: current volume, range is 0x0000 - 0xffff
722 */
723int aio_port_get_volume(struct uniphier_aio_sub *sub)
724{
725 struct regmap *r = sub->aio->chip->regmap;
726 u32 v;
727
728 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
729
730 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
731}
732
733/**
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.
737 *
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
741 */
742void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
743{
744 struct regmap *r = sub->aio->chip->regmap;
745 int oport_map = sub->swm->oport.map;
746 int cur, diff, slope = 0, fs;
747
748 if (sub->swm->dir == PORT_DIR_INPUT)
749 return;
750
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);
757
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);
762
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);
771
772 regmap_write(r, AOUTFADECTR0, BIT(oport_map));
773}
774
775/**
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.
780 *
781 * Set suitable setting to DMA interface block of AIO to process the
782 * specified in settings.
783 *
784 * Return: Zero if successful, otherwise a negative value on error.
785 */
786int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
787{
788 struct regmap *r = sub->aio->chip->regmap;
789 u32 memfmt, v;
790
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;
808 }
809 v = PBOUTMXCTR0_ENDIAN_3210 | memfmt;
810 }
811
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);
821 }
822
823 return 0;
824}
825
826/**
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
830 *
831 * Set special setting to output port block of AIO to output the stream
832 * via S/PDIF.
833 *
834 * Return: Zero if successful, otherwise a negative value on error.
835 */
836int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
837 enum IEC61937_PC pc)
838{
839 struct regmap *r = sub->aio->chip->regmap;
840 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
841 int ret;
842
843 switch (pc) {
844 case IEC61937_PC_AC3:
845 repet = OPORTMXREPET_STRLENGTH_AC3 |
846 OPORTMXREPET_PMLENGTH_AC3;
847 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
848 break;
849 case IEC61937_PC_MPA:
850 repet = OPORTMXREPET_STRLENGTH_MPA |
851 OPORTMXREPET_PMLENGTH_MPA;
852 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
853 break;
854 case IEC61937_PC_MP3:
855 repet = OPORTMXREPET_STRLENGTH_MP3 |
856 OPORTMXREPET_PMLENGTH_MP3;
857 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
858 break;
859 case IEC61937_PC_DTS1:
860 repet = OPORTMXREPET_STRLENGTH_DTS1 |
861 OPORTMXREPET_PMLENGTH_DTS1;
862 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
863 break;
864 case IEC61937_PC_DTS2:
865 repet = OPORTMXREPET_STRLENGTH_DTS2 |
866 OPORTMXREPET_PMLENGTH_DTS2;
867 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
868 break;
869 case IEC61937_PC_DTS3:
870 repet = OPORTMXREPET_STRLENGTH_DTS3 |
871 OPORTMXREPET_PMLENGTH_DTS3;
872 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
873 break;
874 case IEC61937_PC_AAC:
875 repet = OPORTMXREPET_STRLENGTH_AAC |
876 OPORTMXREPET_PMLENGTH_AAC;
877 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
878 break;
879 case IEC61937_PC_PAUSE:
880 /* Do nothing */
881 break;
882 }
883
884 ret = regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
885 if (ret)
886 return ret;
887
888 ret = regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
889 if (ret)
890 return ret;
891
892 return 0;
893}
894
895/**
896 * aio_src_reset - reset AIO SRC block
897 * @sub: the AIO substream pointer
898 *
899 * Resets the digital signal input/output port with sampling rate converter
900 * block of AIO.
901 * This function has no effect if substream is not supported rate converter.
902 */
903void aio_src_reset(struct uniphier_aio_sub *sub)
904{
905 struct regmap *r = sub->aio->chip->regmap;
906
907 if (sub->swm->dir != PORT_DIR_OUTPUT)
908 return;
909
910 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
911 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
912}
913
914/**
915 * aio_src_set_param - set parameters of AIO SRC block
916 * @sub: the AIO substream pointer
917 * @params: hardware parameters of ALSA
918 *
919 * Set suitable setting to input/output port with sampling rate converter
920 * block of AIO to process the specified in params.
921 * This function has no effect if substream is not supported rate converter.
922 *
923 * Return: Zero if successful, otherwise a negative value on error.
924 */
925int aio_src_set_param(struct uniphier_aio_sub *sub,
926 const struct snd_pcm_hw_params *params)
927{
928 struct regmap *r = sub->aio->chip->regmap;
929 u32 v;
930 int ret;
931
932 if (sub->swm->dir != PORT_DIR_OUTPUT)
933 return 0;
934
935 ret = regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
936 OPORTMXSRC1CTR_THMODE_SRC |
937 OPORTMXSRC1CTR_SRCPATH_CALC |
938 OPORTMXSRC1CTR_SYNC_ASYNC |
939 OPORTMXSRC1CTR_FSIIPSEL_INNER |
940 OPORTMXSRC1CTR_FSISEL_ACLK);
941 if (ret)
942 return ret;
943
944 switch (params_rate(params)) {
945 default:
946 case 48000:
947 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
948 OPORTMXRATE_I_MCKSEL_36 |
949 OPORTMXRATE_I_FSSEL_48;
950 break;
951 case 44100:
952 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
953 OPORTMXRATE_I_MCKSEL_33 |
954 OPORTMXRATE_I_FSSEL_44_1;
955 break;
956 case 32000:
957 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
958 OPORTMXRATE_I_MCKSEL_36 |
959 OPORTMXRATE_I_FSSEL_32;
960 break;
961 }
962
963
964 ret = regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
965 v | OPORTMXRATE_I_ACLKSRC_APLL |
966 OPORTMXRATE_I_LRCKSTP_STOP);
967 if (ret)
968 return ret;
969
970 ret = regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
971 OPORTMXRATE_I_LRCKSTP_MASK,
972 OPORTMXRATE_I_LRCKSTP_START);
973 if (ret)
974 return ret;
975
976 return 0;
977}
978
979int aio_srcif_set_param(struct uniphier_aio_sub *sub)
980{
981 struct regmap *r = sub->aio->chip->regmap;
982
983 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
984 PBINMXCTR_NCONNECT_CONNECT |
985 PBINMXCTR_INOUTSEL_OUT |
986 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
987 PBINMXCTR_ENDIAN_3210 |
988 PBINMXCTR_MEMFMT_D0);
989
990 return 0;
991}
992
993int aio_srcch_set_param(struct uniphier_aio_sub *sub)
994{
995 struct regmap *r = sub->aio->chip->regmap;
996
997 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
998 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
999
1000 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
1001 CDA2D_CHMXAMODE_ENDIAN_3210 |
1002 CDA2D_CHMXAMODE_AUPDT_FIX |
1003 CDA2D_CHMXAMODE_TYPE_NORMAL);
1004
1005 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
1006 CDA2D_CHMXAMODE_ENDIAN_3210 |
1007 CDA2D_CHMXAMODE_AUPDT_INC |
1008 CDA2D_CHMXAMODE_TYPE_RING |
1009 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
1010
1011 return 0;
1012}
1013
1014void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
1015{
1016 struct regmap *r = sub->aio->chip->regmap;
1017 u32 v;
1018
1019 if (enable)
1020 v = CDA2D_STRT0_STOP_START;
1021 else
1022 v = CDA2D_STRT0_STOP_STOP;
1023
1024 regmap_write(r, CDA2D_STRT0,
1025 v | BIT(sub->swm->och.map));
1026}
1027
1028int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
1029{
1030 struct regmap *r = sub->aio->chip->regmap;
1031 u32 v;
1032
1033 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
1034 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
1035
1036 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
1037 CDA2D_CHMXAMODE_AUPDT_INC |
1038 CDA2D_CHMXAMODE_TYPE_NORMAL |
1039 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
1040 if (sub->swm->dir == PORT_DIR_OUTPUT)
1041 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
1042 else
1043 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
1044
1045 return 0;
1046}
1047
1048void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
1049{
1050 struct regmap *r = sub->aio->chip->regmap;
1051
1052 if (enable) {
1053 regmap_write(r, CDA2D_STRT0,
1054 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
1055
1056 regmap_update_bits(r, INTRBIM(0),
1057 BIT(sub->swm->rb.map),
1058 BIT(sub->swm->rb.map));
1059 } else {
1060 regmap_write(r, CDA2D_STRT0,
1061 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
1062
1063 regmap_update_bits(r, INTRBIM(0),
1064 BIT(sub->swm->rb.map),
1065 0);
1066 }
1067}
1068
1069static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
1070{
1071 struct regmap *r = sub->aio->chip->regmap;
1072 u32 pos_u, pos_l;
1073 int i;
1074
1075 regmap_write(r, CDA2D_RDPTRLOAD,
1076 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1077 /* Wait for setup */
1078 for (i = 0; i < 6; i++)
1079 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1080
1081 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
1082 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1083 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1084
1085 return ((u64)pos_u << 32) | pos_l;
1086}
1087
1088static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1089{
1090 struct regmap *r = sub->aio->chip->regmap;
1091 u32 tmp;
1092 int i;
1093
1094 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1095 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1096 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1097 /* Wait for setup */
1098 for (i = 0; i < 6; i++)
1099 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1100}
1101
1102static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1103{
1104 struct regmap *r = sub->aio->chip->regmap;
1105 u32 pos_u, pos_l;
1106 int i;
1107
1108 regmap_write(r, CDA2D_WRPTRLOAD,
1109 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1110 /* Wait for setup */
1111 for (i = 0; i < 6; i++)
1112 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1113
1114 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1115 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1116 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1117
1118 return ((u64)pos_u << 32) | pos_l;
1119}
1120
1121static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1122{
1123 struct regmap *r = sub->aio->chip->regmap;
1124 u32 tmp;
1125 int i;
1126
1127 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1128 lower_32_bits(pos));
1129 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1130 upper_32_bits(pos));
1131 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1132 /* Wait for setup */
1133 for (i = 0; i < 6; i++)
1134 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1135}
1136
1137int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1138{
1139 struct regmap *r = sub->aio->chip->regmap;
1140
1141 if (size <= th)
1142 return -EINVAL;
1143
1144 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1145 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1146
1147 return 0;
1148}
1149
1150int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1151 int period)
1152{
1153 struct regmap *r = sub->aio->chip->regmap;
1154 u64 size = end - start;
1155 int ret;
1156
1157 if (end < start || period < 0)
1158 return -EINVAL;
1159
1160 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1161 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1162 lower_32_bits(start));
1163 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1164 upper_32_bits(start));
1165 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1166 lower_32_bits(end));
1167 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1168 upper_32_bits(end));
1169
1170 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1171
1172 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1173 if (ret)
1174 return ret;
1175
1176 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1177 aiodma_rb_set_rp(sub, start);
1178 aiodma_rb_set_wp(sub, end - period);
1179
1180 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1181 CDA2D_RBMXIX_SPACE,
1182 CDA2D_RBMXIX_SPACE);
1183 } else {
1184 aiodma_rb_set_rp(sub, end - period);
1185 aiodma_rb_set_wp(sub, start);
1186
1187 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1188 CDA2D_RBMXIX_REMAIN,
1189 CDA2D_RBMXIX_REMAIN);
1190 }
1191
1192 sub->threshold = 2 * period;
1193 sub->rd_offs = 0;
1194 sub->wr_offs = 0;
1195 sub->rd_org = 0;
1196 sub->wr_org = 0;
1197 sub->rd_total = 0;
1198 sub->wr_total = 0;
1199
1200 return 0;
1201}
1202
1203void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1204 int period)
1205{
1206 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1207 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1208
1209 if (sub->use_mmap) {
1210 sub->threshold = 2 * period;
1211 aiodma_rb_set_threshold(sub, size, 2 * period);
1212
1213 sub->wr_offs = sub->rd_offs - period;
1214 if (sub->rd_offs < period)
1215 sub->wr_offs += size;
1216 }
1217 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1218 } else {
1219 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1220
1221 if (sub->use_mmap) {
1222 sub->threshold = 2 * period;
1223 aiodma_rb_set_threshold(sub, size, 2 * period);
1224
1225 sub->rd_offs = sub->wr_offs - period;
1226 if (sub->wr_offs < period)
1227 sub->rd_offs += size;
1228 }
1229 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1230 }
1231
1232 sub->rd_total += sub->rd_offs - sub->rd_org;
1233 if (sub->rd_offs < sub->rd_org)
1234 sub->rd_total += size;
1235 sub->wr_total += sub->wr_offs - sub->wr_org;
1236 if (sub->wr_offs < sub->wr_org)
1237 sub->wr_total += size;
1238
1239 sub->rd_org = sub->rd_offs;
1240 sub->wr_org = sub->wr_offs;
1241}
1242
1243bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1244{
1245 struct regmap *r = sub->aio->chip->regmap;
1246 u32 ir;
1247
1248 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1249
1250 if (sub->swm->dir == PORT_DIR_OUTPUT)
1251 return !!(ir & CDA2D_RBMXIX_SPACE);
1252 else
1253 return !!(ir & CDA2D_RBMXIX_REMAIN);
1254}
1255
1256void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1257{
1258 struct regmap *r = sub->aio->chip->regmap;
1259
1260 if (sub->swm->dir == PORT_DIR_OUTPUT)
1261 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1262 CDA2D_RBMXIX_SPACE);
1263 else
1264 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1265 CDA2D_RBMXIX_REMAIN);
1266}
1// SPDX-License-Identifier: GPL-2.0
2//
3// Socionext UniPhier AIO ALSA common driver.
4//
5// Copyright (c) 2016-2018 Socionext Inc.
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; version 2
10// of the License.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20#include <linux/bitfield.h>
21#include <linux/errno.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/pcm_params.h>
27#include <sound/soc.h>
28
29#include "aio.h"
30#include "aio-reg.h"
31
32static u64 rb_cnt(u64 wr, u64 rd, u64 len)
33{
34 if (rd <= wr)
35 return wr - rd;
36 else
37 return len - (rd - wr);
38}
39
40static u64 rb_cnt_to_end(u64 wr, u64 rd, u64 len)
41{
42 if (rd <= wr)
43 return wr - rd;
44 else
45 return len - rd;
46}
47
48static u64 rb_space(u64 wr, u64 rd, u64 len)
49{
50 if (rd <= wr)
51 return len - (wr - rd) - 8;
52 else
53 return rd - wr - 8;
54}
55
56static u64 rb_space_to_end(u64 wr, u64 rd, u64 len)
57{
58 if (rd > wr)
59 return rd - wr - 8;
60 else if (rd > 0)
61 return len - wr;
62 else
63 return len - wr - 8;
64}
65
66u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
67{
68 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
69}
70
71u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub)
72{
73 return rb_cnt_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
74}
75
76u64 aio_rb_space(struct uniphier_aio_sub *sub)
77{
78 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
79}
80
81u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub)
82{
83 return rb_space_to_end(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
84}
85
86/**
87 * aio_iecout_set_enable - setup IEC output via SoC glue
88 * @chip: the AIO chip pointer
89 * @enable: false to stop the output, true to start
90 *
91 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins.
92 * This function need to call at driver startup.
93 *
94 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
95 * of DT. This function has no effect if no property.
96 */
97void aio_iecout_set_enable(struct uniphier_aio_chip *chip, bool enable)
98{
99 struct regmap *r = chip->regmap_sg;
100
101 if (!r)
102 return;
103
104 regmap_write(r, SG_AOUTEN, (enable) ? ~0 : 0);
105}
106
107/**
108 * aio_chip_set_pll - set frequency to audio PLL
109 * @chip : the AIO chip pointer
110 * @source: PLL
111 * @freq : frequency in Hz, 0 is ignored
112 *
113 * Sets frequency of audio PLL. This function can be called anytime,
114 * but it takes time till PLL is locked.
115 *
116 * Return: Zero if successful, otherwise a negative value on error.
117 */
118int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
119 unsigned int freq)
120{
121 struct device *dev = &chip->pdev->dev;
122 struct regmap *r = chip->regmap;
123 int shift;
124 u32 v;
125
126 /* Not change */
127 if (freq == 0)
128 return 0;
129
130 switch (pll_id) {
131 case AUD_PLL_A1:
132 shift = 0;
133 break;
134 case AUD_PLL_F1:
135 shift = 1;
136 break;
137 case AUD_PLL_A2:
138 shift = 2;
139 break;
140 case AUD_PLL_F2:
141 shift = 3;
142 break;
143 default:
144 dev_err(dev, "PLL(%d) not supported\n", pll_id);
145 return -EINVAL;
146 }
147
148 switch (freq) {
149 case 36864000:
150 v = A2APLLCTR1_APLLX_36MHZ;
151 break;
152 case 33868800:
153 v = A2APLLCTR1_APLLX_33MHZ;
154 break;
155 default:
156 dev_err(dev, "PLL frequency not supported(%d)\n", freq);
157 return -EINVAL;
158 }
159 chip->plls[pll_id].freq = freq;
160
161 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
162 v << shift);
163
164 return 0;
165}
166
167/**
168 * aio_chip_init - initialize AIO whole settings
169 * @chip: the AIO chip pointer
170 *
171 * Sets AIO fixed and whole device settings to AIO.
172 * This function need to call once at driver startup.
173 *
174 * The register area that is changed by this function is shared by all
175 * modules of AIO. But there is not race condition since this function
176 * has always set the same initialize values.
177 */
178void aio_chip_init(struct uniphier_aio_chip *chip)
179{
180 struct regmap *r = chip->regmap;
181
182 regmap_update_bits(r, A2APLLCTR0,
183 A2APLLCTR0_APLLXPOW_MASK,
184 A2APLLCTR0_APLLXPOW_PWON);
185
186 regmap_update_bits(r, A2EXMCLKSEL0,
187 A2EXMCLKSEL0_EXMCLK_MASK,
188 A2EXMCLKSEL0_EXMCLK_OUTPUT);
189
190 regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
191 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
192 A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
193 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
194 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
195
196 if (chip->chip_spec->addr_ext)
197 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
198 CDA2D_TEST_DDR_MODE_EXTON0);
199 else
200 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
201 CDA2D_TEST_DDR_MODE_EXTOFF1);
202}
203
204/**
205 * aio_init - initialize AIO substream
206 * @sub: the AIO substream pointer
207 *
208 * Sets fixed settings of each AIO substreams.
209 * This function need to call once at substream startup.
210 *
211 * Return: Zero if successful, otherwise a negative value on error.
212 */
213int aio_init(struct uniphier_aio_sub *sub)
214{
215 struct device *dev = &sub->aio->chip->pdev->dev;
216 struct regmap *r = sub->aio->chip->regmap;
217
218 regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
219 MAPCTR0_EN | sub->swm->rb.map);
220 regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
221 MAPCTR0_EN | sub->swm->ch.map);
222
223 switch (sub->swm->type) {
224 case PORT_TYPE_I2S:
225 case PORT_TYPE_SPDIF:
226 case PORT_TYPE_EVE:
227 if (sub->swm->dir == PORT_DIR_INPUT) {
228 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
229 MAPCTR0_EN | sub->swm->iif.map);
230 regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
231 MAPCTR0_EN | sub->swm->iport.map);
232 } else {
233 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
234 MAPCTR0_EN | sub->swm->oif.map);
235 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
236 MAPCTR0_EN | sub->swm->oport.map);
237 }
238 break;
239 case PORT_TYPE_CONV:
240 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
241 MAPCTR0_EN | sub->swm->oif.map);
242 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
243 MAPCTR0_EN | sub->swm->oport.map);
244 regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
245 MAPCTR0_EN | sub->swm->och.map);
246 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
247 MAPCTR0_EN | sub->swm->iif.map);
248 break;
249 default:
250 dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
251 return -EINVAL;
252 }
253
254 return 0;
255}
256
257/**
258 * aio_port_reset - reset AIO port block
259 * @sub: the AIO substream pointer
260 *
261 * Resets the digital signal input/output port block of AIO.
262 */
263void aio_port_reset(struct uniphier_aio_sub *sub)
264{
265 struct regmap *r = sub->aio->chip->regmap;
266
267 if (sub->swm->dir == PORT_DIR_OUTPUT) {
268 regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
269 regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
270 } else {
271 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
272 IPORTMXRSTCTR_RSTPI_MASK,
273 IPORTMXRSTCTR_RSTPI_RESET);
274 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
275 IPORTMXRSTCTR_RSTPI_MASK,
276 IPORTMXRSTCTR_RSTPI_RELEASE);
277 }
278}
279
280/**
281 * aio_port_set_rate - set sampling rate of LPCM
282 * @sub: the AIO substream pointer, PCM substream only
283 * @rate: Sampling rate in Hz.
284 *
285 * Set suitable I2S format settings to input/output port block of AIO.
286 * Parameter is specified by hw_params().
287 *
288 * This function may return error if non-PCM substream.
289 *
290 * Return: Zero if successful, otherwise a negative value on error.
291 */
292int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
293{
294 struct regmap *r = sub->aio->chip->regmap;
295 struct device *dev = &sub->aio->chip->pdev->dev;
296 u32 v;
297
298 if (sub->swm->dir == PORT_DIR_OUTPUT) {
299 switch (rate) {
300 case 8000:
301 v = OPORTMXCTR1_FSSEL_8;
302 break;
303 case 11025:
304 v = OPORTMXCTR1_FSSEL_11_025;
305 break;
306 case 12000:
307 v = OPORTMXCTR1_FSSEL_12;
308 break;
309 case 16000:
310 v = OPORTMXCTR1_FSSEL_16;
311 break;
312 case 22050:
313 v = OPORTMXCTR1_FSSEL_22_05;
314 break;
315 case 24000:
316 v = OPORTMXCTR1_FSSEL_24;
317 break;
318 case 32000:
319 v = OPORTMXCTR1_FSSEL_32;
320 break;
321 case 44100:
322 v = OPORTMXCTR1_FSSEL_44_1;
323 break;
324 case 48000:
325 v = OPORTMXCTR1_FSSEL_48;
326 break;
327 case 88200:
328 v = OPORTMXCTR1_FSSEL_88_2;
329 break;
330 case 96000:
331 v = OPORTMXCTR1_FSSEL_96;
332 break;
333 case 176400:
334 v = OPORTMXCTR1_FSSEL_176_4;
335 break;
336 case 192000:
337 v = OPORTMXCTR1_FSSEL_192;
338 break;
339 default:
340 dev_err(dev, "Rate not supported(%d)\n", rate);
341 return -EINVAL;
342 }
343
344 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
345 OPORTMXCTR1_FSSEL_MASK, v);
346 } else {
347 switch (rate) {
348 case 8000:
349 v = IPORTMXCTR1_FSSEL_8;
350 break;
351 case 11025:
352 v = IPORTMXCTR1_FSSEL_11_025;
353 break;
354 case 12000:
355 v = IPORTMXCTR1_FSSEL_12;
356 break;
357 case 16000:
358 v = IPORTMXCTR1_FSSEL_16;
359 break;
360 case 22050:
361 v = IPORTMXCTR1_FSSEL_22_05;
362 break;
363 case 24000:
364 v = IPORTMXCTR1_FSSEL_24;
365 break;
366 case 32000:
367 v = IPORTMXCTR1_FSSEL_32;
368 break;
369 case 44100:
370 v = IPORTMXCTR1_FSSEL_44_1;
371 break;
372 case 48000:
373 v = IPORTMXCTR1_FSSEL_48;
374 break;
375 case 88200:
376 v = IPORTMXCTR1_FSSEL_88_2;
377 break;
378 case 96000:
379 v = IPORTMXCTR1_FSSEL_96;
380 break;
381 case 176400:
382 v = IPORTMXCTR1_FSSEL_176_4;
383 break;
384 case 192000:
385 v = IPORTMXCTR1_FSSEL_192;
386 break;
387 default:
388 dev_err(dev, "Rate not supported(%d)\n", rate);
389 return -EINVAL;
390 }
391
392 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
393 IPORTMXCTR1_FSSEL_MASK, v);
394 }
395
396 return 0;
397}
398
399/**
400 * aio_port_set_fmt - set format of I2S data
401 * @sub: the AIO substream pointer, PCM substream only
402 * This parameter has no effect if substream is I2S or PCM.
403 *
404 * Set suitable I2S format settings to input/output port block of AIO.
405 * Parameter is specified by set_fmt().
406 *
407 * This function may return error if non-PCM substream.
408 *
409 * Return: Zero if successful, otherwise a negative value on error.
410 */
411int aio_port_set_fmt(struct uniphier_aio_sub *sub)
412{
413 struct regmap *r = sub->aio->chip->regmap;
414 struct device *dev = &sub->aio->chip->pdev->dev;
415 u32 v;
416
417 if (sub->swm->dir == PORT_DIR_OUTPUT) {
418 switch (sub->aio->fmt) {
419 case SND_SOC_DAIFMT_LEFT_J:
420 v = OPORTMXCTR1_I2SLRSEL_LEFT;
421 break;
422 case SND_SOC_DAIFMT_RIGHT_J:
423 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
424 break;
425 case SND_SOC_DAIFMT_I2S:
426 v = OPORTMXCTR1_I2SLRSEL_I2S;
427 break;
428 default:
429 dev_err(dev, "Format is not supported(%d)\n",
430 sub->aio->fmt);
431 return -EINVAL;
432 }
433
434 v |= OPORTMXCTR1_OUTBITSEL_24;
435 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
436 OPORTMXCTR1_I2SLRSEL_MASK |
437 OPORTMXCTR1_OUTBITSEL_MASK, v);
438 } else {
439 switch (sub->aio->fmt) {
440 case SND_SOC_DAIFMT_LEFT_J:
441 v = IPORTMXCTR1_LRSEL_LEFT;
442 break;
443 case SND_SOC_DAIFMT_RIGHT_J:
444 v = IPORTMXCTR1_LRSEL_RIGHT;
445 break;
446 case SND_SOC_DAIFMT_I2S:
447 v = IPORTMXCTR1_LRSEL_I2S;
448 break;
449 default:
450 dev_err(dev, "Format is not supported(%d)\n",
451 sub->aio->fmt);
452 return -EINVAL;
453 }
454
455 v |= IPORTMXCTR1_OUTBITSEL_24 |
456 IPORTMXCTR1_CHSEL_ALL;
457 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
458 IPORTMXCTR1_LRSEL_MASK |
459 IPORTMXCTR1_OUTBITSEL_MASK |
460 IPORTMXCTR1_CHSEL_MASK, v);
461 }
462
463 return 0;
464}
465
466/**
467 * aio_port_set_clk - set clock and divider of AIO port block
468 * @sub: the AIO substream pointer
469 *
470 * Set suitable PLL clock divider and relational settings to
471 * input/output port block of AIO. Parameters are specified by
472 * set_sysclk() and set_pll().
473 *
474 * Return: Zero if successful, otherwise a negative value on error.
475 */
476int aio_port_set_clk(struct uniphier_aio_sub *sub)
477{
478 struct uniphier_aio_chip *chip = sub->aio->chip;
479 struct device *dev = &sub->aio->chip->pdev->dev;
480 struct regmap *r = sub->aio->chip->regmap;
481 u32 v_pll[] = {
482 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
483 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
484 OPORTMXCTR2_ACLKSEL_A2PLL,
485 OPORTMXCTR2_ACLKSEL_RX1,
486 };
487 u32 v_div[] = {
488 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
489 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
490 };
491 u32 v;
492
493 if (sub->swm->dir == PORT_DIR_OUTPUT) {
494 if (sub->swm->type == PORT_TYPE_I2S) {
495 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
496 dev_err(dev, "PLL(%d) is invalid\n",
497 sub->aio->pll_out);
498 return -EINVAL;
499 }
500 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
501 dev_err(dev, "PLL divider(%d) is invalid\n",
502 sub->aio->plldiv);
503 return -EINVAL;
504 }
505
506 v = v_pll[sub->aio->pll_out] |
507 OPORTMXCTR2_MSSEL_MASTER |
508 v_div[sub->aio->plldiv];
509
510 switch (chip->plls[sub->aio->pll_out].freq) {
511 case 0:
512 case 36864000:
513 case 33868800:
514 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
515 break;
516 default:
517 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
518 break;
519 }
520 } else if (sub->swm->type == PORT_TYPE_EVE) {
521 v = OPORTMXCTR2_ACLKSEL_A2PLL |
522 OPORTMXCTR2_MSSEL_MASTER |
523 OPORTMXCTR2_EXTLSIFSSEL_36 |
524 OPORTMXCTR2_DACCKSEL_1_2;
525 } else if (sub->swm->type == PORT_TYPE_SPDIF) {
526 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
527 dev_err(dev, "PLL(%d) is invalid\n",
528 sub->aio->pll_out);
529 return -EINVAL;
530 }
531 v = v_pll[sub->aio->pll_out] |
532 OPORTMXCTR2_MSSEL_MASTER |
533 OPORTMXCTR2_DACCKSEL_1_2;
534
535 switch (chip->plls[sub->aio->pll_out].freq) {
536 case 0:
537 case 36864000:
538 case 33868800:
539 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
540 break;
541 default:
542 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
543 break;
544 }
545 } else {
546 v = OPORTMXCTR2_ACLKSEL_A1 |
547 OPORTMXCTR2_MSSEL_MASTER |
548 OPORTMXCTR2_EXTLSIFSSEL_36 |
549 OPORTMXCTR2_DACCKSEL_1_2;
550 }
551 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
552 } else {
553 v = IPORTMXCTR2_ACLKSEL_A1 |
554 IPORTMXCTR2_MSSEL_SLAVE |
555 IPORTMXCTR2_EXTLSIFSSEL_36 |
556 IPORTMXCTR2_DACCKSEL_1_2;
557 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
558 }
559
560 return 0;
561}
562
563/**
564 * aio_port_set_param - set parameters of AIO port block
565 * @sub: the AIO substream pointer
566 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
567 * This parameter has no effect if substream is I2S or PCM.
568 * @params: hardware parameters of ALSA
569 *
570 * Set suitable setting to input/output port block of AIO to process the
571 * specified in params.
572 *
573 * Return: Zero if successful, otherwise a negative value on error.
574 */
575int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
576 const struct snd_pcm_hw_params *params)
577{
578 struct regmap *r = sub->aio->chip->regmap;
579 unsigned int rate;
580 u32 v;
581 int ret;
582
583 if (!pass_through) {
584 if (sub->swm->type == PORT_TYPE_EVE ||
585 sub->swm->type == PORT_TYPE_CONV) {
586 rate = 48000;
587 } else {
588 rate = params_rate(params);
589 }
590
591 ret = aio_port_set_rate(sub, rate);
592 if (ret)
593 return ret;
594
595 ret = aio_port_set_fmt(sub);
596 if (ret)
597 return ret;
598 }
599
600 ret = aio_port_set_clk(sub);
601 if (ret)
602 return ret;
603
604 if (sub->swm->dir == PORT_DIR_OUTPUT) {
605 if (pass_through)
606 v = OPORTMXCTR3_SRCSEL_STREAM |
607 OPORTMXCTR3_VALID_STREAM;
608 else
609 v = OPORTMXCTR3_SRCSEL_PCM |
610 OPORTMXCTR3_VALID_PCM;
611
612 v |= OPORTMXCTR3_IECTHUR_IECOUT |
613 OPORTMXCTR3_PMSEL_PAUSE |
614 OPORTMXCTR3_PMSW_MUTE_OFF;
615 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
616 } else {
617 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
618 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
619 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
620 IPORTMXEXNOE_PCMINOE_INPUT);
621 }
622
623 return 0;
624}
625
626/**
627 * aio_port_set_enable - start or stop of AIO port block
628 * @sub: the AIO substream pointer
629 * @enable: zero to stop the block, otherwise to start
630 *
631 * Start or stop the signal input/output port block of AIO.
632 */
633void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
634{
635 struct regmap *r = sub->aio->chip->regmap;
636
637 if (sub->swm->dir == PORT_DIR_OUTPUT) {
638 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
639 sub->swm->oif.map);
640
641 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
642 OPORTMXMASK_IUDXMSK_MASK |
643 OPORTMXMASK_IUXCKMSK_MASK |
644 OPORTMXMASK_DXMSK_MASK |
645 OPORTMXMASK_XCKMSK_MASK,
646 OPORTMXMASK_IUDXMSK_OFF |
647 OPORTMXMASK_IUXCKMSK_OFF |
648 OPORTMXMASK_DXMSK_OFF |
649 OPORTMXMASK_XCKMSK_OFF);
650
651 if (enable)
652 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
653 else
654 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
655 } else {
656 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
657 IPORTMXMASK_IUXCKMSK_MASK |
658 IPORTMXMASK_XCKMSK_MASK,
659 IPORTMXMASK_IUXCKMSK_OFF |
660 IPORTMXMASK_XCKMSK_OFF);
661
662 if (enable)
663 regmap_update_bits(r,
664 IPORTMXCTR2(sub->swm->iport.map),
665 IPORTMXCTR2_REQEN_MASK,
666 IPORTMXCTR2_REQEN_ENABLE);
667 else
668 regmap_update_bits(r,
669 IPORTMXCTR2(sub->swm->iport.map),
670 IPORTMXCTR2_REQEN_MASK,
671 IPORTMXCTR2_REQEN_DISABLE);
672 }
673}
674
675/**
676 * aio_if_set_param - set parameters of AIO DMA I/F block
677 * @sub: the AIO substream pointer
678 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
679 * This parameter has no effect if substream is I2S or PCM.
680 *
681 * Set suitable setting to DMA interface block of AIO to process the
682 * specified in settings.
683 *
684 * Return: Zero if successful, otherwise a negative value on error.
685 */
686int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
687{
688 struct regmap *r = sub->aio->chip->regmap;
689 u32 v;
690
691 if (sub->swm->dir == PORT_DIR_OUTPUT) {
692 if (pass_through)
693 v = PBOUTMXCTR0_ENDIAN_0123 |
694 PBOUTMXCTR0_MEMFMT_STREAM;
695 else
696 v = PBOUTMXCTR0_ENDIAN_3210 |
697 PBOUTMXCTR0_MEMFMT_2CH;
698
699 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
700 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
701 } else {
702 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
703 PBINMXCTR_NCONNECT_CONNECT |
704 PBINMXCTR_INOUTSEL_IN |
705 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
706 PBINMXCTR_ENDIAN_3210 |
707 PBINMXCTR_MEMFMT_D0);
708 }
709
710 return 0;
711}
712
713/**
714 * aio_oport_set_stream_type - set parameters of AIO playback port block
715 * @sub: the AIO substream pointer
716 * @pc: Pc type of IEC61937
717 *
718 * Set special setting to output port block of AIO to output the stream
719 * via S/PDIF.
720 *
721 * Return: Zero if successful, otherwise a negative value on error.
722 */
723int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
724 enum IEC61937_PC pc)
725{
726 struct regmap *r = sub->aio->chip->regmap;
727 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
728
729 switch (pc) {
730 case IEC61937_PC_AC3:
731 repet = OPORTMXREPET_STRLENGTH_AC3 |
732 OPORTMXREPET_PMLENGTH_AC3;
733 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
734 break;
735 case IEC61937_PC_MPA:
736 repet = OPORTMXREPET_STRLENGTH_MPA |
737 OPORTMXREPET_PMLENGTH_MPA;
738 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
739 break;
740 case IEC61937_PC_MP3:
741 repet = OPORTMXREPET_STRLENGTH_MP3 |
742 OPORTMXREPET_PMLENGTH_MP3;
743 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
744 break;
745 case IEC61937_PC_DTS1:
746 repet = OPORTMXREPET_STRLENGTH_DTS1 |
747 OPORTMXREPET_PMLENGTH_DTS1;
748 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
749 break;
750 case IEC61937_PC_DTS2:
751 repet = OPORTMXREPET_STRLENGTH_DTS2 |
752 OPORTMXREPET_PMLENGTH_DTS2;
753 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
754 break;
755 case IEC61937_PC_DTS3:
756 repet = OPORTMXREPET_STRLENGTH_DTS3 |
757 OPORTMXREPET_PMLENGTH_DTS3;
758 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
759 break;
760 case IEC61937_PC_AAC:
761 repet = OPORTMXREPET_STRLENGTH_AAC |
762 OPORTMXREPET_PMLENGTH_AAC;
763 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
764 break;
765 case IEC61937_PC_PAUSE:
766 /* Do nothing */
767 break;
768 }
769
770 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
771 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
772
773 return 0;
774}
775
776/**
777 * aio_src_reset - reset AIO SRC block
778 * @sub: the AIO substream pointer
779 *
780 * Resets the digital signal input/output port with sampling rate converter
781 * block of AIO.
782 * This function has no effect if substream is not supported rate converter.
783 */
784void aio_src_reset(struct uniphier_aio_sub *sub)
785{
786 struct regmap *r = sub->aio->chip->regmap;
787
788 if (sub->swm->dir != PORT_DIR_OUTPUT)
789 return;
790
791 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
792 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
793}
794
795/**
796 * aio_src_set_param - set parameters of AIO SRC block
797 * @sub: the AIO substream pointer
798 * @params: hardware parameters of ALSA
799 *
800 * Set suitable setting to input/output port with sampling rate converter
801 * block of AIO to process the specified in params.
802 * This function has no effect if substream is not supported rate converter.
803 *
804 * Return: Zero if successful, otherwise a negative value on error.
805 */
806int aio_src_set_param(struct uniphier_aio_sub *sub,
807 const struct snd_pcm_hw_params *params)
808{
809 struct regmap *r = sub->aio->chip->regmap;
810 u32 v;
811
812 if (sub->swm->dir != PORT_DIR_OUTPUT)
813 return 0;
814
815 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
816 OPORTMXSRC1CTR_THMODE_SRC |
817 OPORTMXSRC1CTR_SRCPATH_CALC |
818 OPORTMXSRC1CTR_SYNC_ASYNC |
819 OPORTMXSRC1CTR_FSIIPSEL_INNER |
820 OPORTMXSRC1CTR_FSISEL_ACLK);
821
822 switch (params_rate(params)) {
823 default:
824 case 48000:
825 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
826 OPORTMXRATE_I_MCKSEL_36 |
827 OPORTMXRATE_I_FSSEL_48;
828 break;
829 case 44100:
830 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
831 OPORTMXRATE_I_MCKSEL_33 |
832 OPORTMXRATE_I_FSSEL_44_1;
833 break;
834 case 32000:
835 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
836 OPORTMXRATE_I_MCKSEL_36 |
837 OPORTMXRATE_I_FSSEL_32;
838 break;
839 }
840
841 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
842 v | OPORTMXRATE_I_ACLKSRC_APLL |
843 OPORTMXRATE_I_LRCKSTP_STOP);
844 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
845 OPORTMXRATE_I_LRCKSTP_MASK,
846 OPORTMXRATE_I_LRCKSTP_START);
847
848 return 0;
849}
850
851int aio_srcif_set_param(struct uniphier_aio_sub *sub)
852{
853 struct regmap *r = sub->aio->chip->regmap;
854
855 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
856 PBINMXCTR_NCONNECT_CONNECT |
857 PBINMXCTR_INOUTSEL_OUT |
858 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
859 PBINMXCTR_ENDIAN_3210 |
860 PBINMXCTR_MEMFMT_D0);
861
862 return 0;
863}
864
865int aio_srcch_set_param(struct uniphier_aio_sub *sub)
866{
867 struct regmap *r = sub->aio->chip->regmap;
868
869 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
870 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
871
872 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
873 CDA2D_CHMXAMODE_ENDIAN_3210 |
874 CDA2D_CHMXAMODE_AUPDT_FIX |
875 CDA2D_CHMXAMODE_TYPE_NORMAL);
876
877 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
878 CDA2D_CHMXAMODE_ENDIAN_3210 |
879 CDA2D_CHMXAMODE_AUPDT_INC |
880 CDA2D_CHMXAMODE_TYPE_RING |
881 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
882
883 return 0;
884}
885
886void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
887{
888 struct regmap *r = sub->aio->chip->regmap;
889 u32 v;
890
891 if (enable)
892 v = CDA2D_STRT0_STOP_START;
893 else
894 v = CDA2D_STRT0_STOP_STOP;
895
896 regmap_write(r, CDA2D_STRT0,
897 v | BIT(sub->swm->och.map));
898}
899
900int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
901{
902 struct regmap *r = sub->aio->chip->regmap;
903 u32 v;
904
905 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
906 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
907
908 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
909 CDA2D_CHMXAMODE_AUPDT_INC |
910 CDA2D_CHMXAMODE_TYPE_NORMAL |
911 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
912 if (sub->swm->dir == PORT_DIR_OUTPUT)
913 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
914 else
915 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
916
917 return 0;
918}
919
920void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
921{
922 struct regmap *r = sub->aio->chip->regmap;
923
924 if (enable) {
925 regmap_write(r, CDA2D_STRT0,
926 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
927
928 regmap_update_bits(r, INTRBIM(0),
929 BIT(sub->swm->rb.map),
930 BIT(sub->swm->rb.map));
931 } else {
932 regmap_write(r, CDA2D_STRT0,
933 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
934
935 regmap_update_bits(r, INTRBIM(0),
936 BIT(sub->swm->rb.map),
937 0);
938 }
939}
940
941static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
942{
943 struct regmap *r = sub->aio->chip->regmap;
944 u32 pos_u, pos_l;
945 int i;
946
947 regmap_write(r, CDA2D_RDPTRLOAD,
948 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
949 /* Wait for setup */
950 for (i = 0; i < 6; i++)
951 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
952
953 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
954 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
955 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
956
957 return ((u64)pos_u << 32) | pos_l;
958}
959
960static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
961{
962 struct regmap *r = sub->aio->chip->regmap;
963 u32 tmp;
964 int i;
965
966 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
967 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
968 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
969 /* Wait for setup */
970 for (i = 0; i < 6; i++)
971 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
972}
973
974static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
975{
976 struct regmap *r = sub->aio->chip->regmap;
977 u32 pos_u, pos_l;
978 int i;
979
980 regmap_write(r, CDA2D_WRPTRLOAD,
981 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
982 /* Wait for setup */
983 for (i = 0; i < 6; i++)
984 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
985
986 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
987 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
988 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
989
990 return ((u64)pos_u << 32) | pos_l;
991}
992
993static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
994{
995 struct regmap *r = sub->aio->chip->regmap;
996 u32 tmp;
997 int i;
998
999 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1000 lower_32_bits(pos));
1001 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1002 upper_32_bits(pos));
1003 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1004 /* Wait for setup */
1005 for (i = 0; i < 6; i++)
1006 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1007}
1008
1009int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1010{
1011 struct regmap *r = sub->aio->chip->regmap;
1012
1013 if (size <= th)
1014 return -EINVAL;
1015
1016 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1017 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1018
1019 return 0;
1020}
1021
1022int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1023 int period)
1024{
1025 struct regmap *r = sub->aio->chip->regmap;
1026 u64 size = end - start;
1027 int ret;
1028
1029 if (end < start || period < 0)
1030 return -EINVAL;
1031
1032 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1033 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1034 lower_32_bits(start));
1035 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1036 upper_32_bits(start));
1037 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1038 lower_32_bits(end));
1039 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1040 upper_32_bits(end));
1041
1042 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1043
1044 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1045 if (ret)
1046 return ret;
1047
1048 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1049 aiodma_rb_set_rp(sub, start);
1050 aiodma_rb_set_wp(sub, end - period);
1051
1052 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1053 CDA2D_RBMXIX_SPACE,
1054 CDA2D_RBMXIX_SPACE);
1055 } else {
1056 aiodma_rb_set_rp(sub, end - period);
1057 aiodma_rb_set_wp(sub, start);
1058
1059 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1060 CDA2D_RBMXIX_REMAIN,
1061 CDA2D_RBMXIX_REMAIN);
1062 }
1063
1064 sub->threshold = 2 * period;
1065 sub->rd_offs = 0;
1066 sub->wr_offs = 0;
1067 sub->rd_org = 0;
1068 sub->wr_org = 0;
1069 sub->rd_total = 0;
1070 sub->wr_total = 0;
1071
1072 return 0;
1073}
1074
1075void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1076 int period)
1077{
1078 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1079 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1080
1081 if (sub->use_mmap) {
1082 sub->threshold = 2 * period;
1083 aiodma_rb_set_threshold(sub, size, 2 * period);
1084
1085 sub->wr_offs = sub->rd_offs - period;
1086 if (sub->rd_offs < period)
1087 sub->wr_offs += size;
1088 }
1089 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1090 } else {
1091 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1092
1093 if (sub->use_mmap) {
1094 sub->threshold = 2 * period;
1095 aiodma_rb_set_threshold(sub, size, 2 * period);
1096
1097 sub->rd_offs = sub->wr_offs - period;
1098 if (sub->wr_offs < period)
1099 sub->rd_offs += size;
1100 }
1101 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1102 }
1103
1104 sub->rd_total += sub->rd_offs - sub->rd_org;
1105 if (sub->rd_offs < sub->rd_org)
1106 sub->rd_total += size;
1107 sub->wr_total += sub->wr_offs - sub->wr_org;
1108 if (sub->wr_offs < sub->wr_org)
1109 sub->wr_total += size;
1110
1111 sub->rd_org = sub->rd_offs;
1112 sub->wr_org = sub->wr_offs;
1113}
1114
1115bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1116{
1117 struct regmap *r = sub->aio->chip->regmap;
1118 u32 ir;
1119
1120 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1121
1122 if (sub->swm->dir == PORT_DIR_OUTPUT)
1123 return !!(ir & CDA2D_RBMXIX_SPACE);
1124 else
1125 return !!(ir & CDA2D_RBMXIX_REMAIN);
1126}
1127
1128void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1129{
1130 struct regmap *r = sub->aio->chip->regmap;
1131
1132 if (sub->swm->dir == PORT_DIR_OUTPUT)
1133 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1134 CDA2D_RBMXIX_SPACE);
1135 else
1136 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1137 CDA2D_RBMXIX_REMAIN);
1138}