1
2
3
4
5
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
75
76
77
78
79
80
81
82
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
96
97
98
99
100
101
102
103
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
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
156
157
158
159
160
161
162
163
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
193
194
195
196
197
198
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
246
247
248
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
269
270
271
272
273
274
275
276
277
278
279int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
280{
281 struct regmap *r = sub->aio->chip->regmap;
282 struct device *dev = &sub->aio->chip->pdev->dev;
283 u32 v;
284
285 if (sub->swm->dir == PORT_DIR_OUTPUT) {
286 switch (rate) {
287 case 8000:
288 v = OPORTMXCTR1_FSSEL_8;
289 break;
290 case 11025:
291 v = OPORTMXCTR1_FSSEL_11_025;
292 break;
293 case 12000:
294 v = OPORTMXCTR1_FSSEL_12;
295 break;
296 case 16000:
297 v = OPORTMXCTR1_FSSEL_16;
298 break;
299 case 22050:
300 v = OPORTMXCTR1_FSSEL_22_05;
301 break;
302 case 24000:
303 v = OPORTMXCTR1_FSSEL_24;
304 break;
305 case 32000:
306 v = OPORTMXCTR1_FSSEL_32;
307 break;
308 case 44100:
309 v = OPORTMXCTR1_FSSEL_44_1;
310 break;
311 case 48000:
312 v = OPORTMXCTR1_FSSEL_48;
313 break;
314 case 88200:
315 v = OPORTMXCTR1_FSSEL_88_2;
316 break;
317 case 96000:
318 v = OPORTMXCTR1_FSSEL_96;
319 break;
320 case 176400:
321 v = OPORTMXCTR1_FSSEL_176_4;
322 break;
323 case 192000:
324 v = OPORTMXCTR1_FSSEL_192;
325 break;
326 default:
327 dev_err(dev, "Rate not supported(%d)\n", rate);
328 return -EINVAL;
329 }
330
331 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
332 OPORTMXCTR1_FSSEL_MASK, v);
333 } else {
334 switch (rate) {
335 case 8000:
336 v = IPORTMXCTR1_FSSEL_8;
337 break;
338 case 11025:
339 v = IPORTMXCTR1_FSSEL_11_025;
340 break;
341 case 12000:
342 v = IPORTMXCTR1_FSSEL_12;
343 break;
344 case 16000:
345 v = IPORTMXCTR1_FSSEL_16;
346 break;
347 case 22050:
348 v = IPORTMXCTR1_FSSEL_22_05;
349 break;
350 case 24000:
351 v = IPORTMXCTR1_FSSEL_24;
352 break;
353 case 32000:
354 v = IPORTMXCTR1_FSSEL_32;
355 break;
356 case 44100:
357 v = IPORTMXCTR1_FSSEL_44_1;
358 break;
359 case 48000:
360 v = IPORTMXCTR1_FSSEL_48;
361 break;
362 case 88200:
363 v = IPORTMXCTR1_FSSEL_88_2;
364 break;
365 case 96000:
366 v = IPORTMXCTR1_FSSEL_96;
367 break;
368 case 176400:
369 v = IPORTMXCTR1_FSSEL_176_4;
370 break;
371 case 192000:
372 v = IPORTMXCTR1_FSSEL_192;
373 break;
374 default:
375 dev_err(dev, "Rate not supported(%d)\n", rate);
376 return -EINVAL;
377 }
378
379 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
380 IPORTMXCTR1_FSSEL_MASK, v);
381 }
382
383 return 0;
384}
385
386
387
388
389
390
391
392
393
394
395
396
397
398int aio_port_set_fmt(struct uniphier_aio_sub *sub)
399{
400 struct regmap *r = sub->aio->chip->regmap;
401 struct device *dev = &sub->aio->chip->pdev->dev;
402 u32 v;
403
404 if (sub->swm->dir == PORT_DIR_OUTPUT) {
405 switch (sub->aio->fmt) {
406 case SND_SOC_DAIFMT_LEFT_J:
407 v = OPORTMXCTR1_I2SLRSEL_LEFT;
408 break;
409 case SND_SOC_DAIFMT_RIGHT_J:
410 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
411 break;
412 case SND_SOC_DAIFMT_I2S:
413 v = OPORTMXCTR1_I2SLRSEL_I2S;
414 break;
415 default:
416 dev_err(dev, "Format is not supported(%d)\n",
417 sub->aio->fmt);
418 return -EINVAL;
419 }
420
421 v |= OPORTMXCTR1_OUTBITSEL_24;
422 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
423 OPORTMXCTR1_I2SLRSEL_MASK |
424 OPORTMXCTR1_OUTBITSEL_MASK, v);
425 } else {
426 switch (sub->aio->fmt) {
427 case SND_SOC_DAIFMT_LEFT_J:
428 v = IPORTMXCTR1_LRSEL_LEFT;
429 break;
430 case SND_SOC_DAIFMT_RIGHT_J:
431 v = IPORTMXCTR1_LRSEL_RIGHT;
432 break;
433 case SND_SOC_DAIFMT_I2S:
434 v = IPORTMXCTR1_LRSEL_I2S;
435 break;
436 default:
437 dev_err(dev, "Format is not supported(%d)\n",
438 sub->aio->fmt);
439 return -EINVAL;
440 }
441
442 v |= IPORTMXCTR1_OUTBITSEL_24 |
443 IPORTMXCTR1_CHSEL_ALL;
444 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
445 IPORTMXCTR1_LRSEL_MASK |
446 IPORTMXCTR1_OUTBITSEL_MASK |
447 IPORTMXCTR1_CHSEL_MASK, v);
448 }
449
450 return 0;
451}
452
453
454
455
456
457
458
459
460
461
462
463int aio_port_set_clk(struct uniphier_aio_sub *sub)
464{
465 struct uniphier_aio_chip *chip = sub->aio->chip;
466 struct device *dev = &sub->aio->chip->pdev->dev;
467 struct regmap *r = sub->aio->chip->regmap;
468 u32 v_pll[] = {
469 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
470 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
471 OPORTMXCTR2_ACLKSEL_A2PLL,
472 OPORTMXCTR2_ACLKSEL_RX1,
473 };
474 u32 v_div[] = {
475 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
476 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
477 };
478 u32 v;
479
480 if (sub->swm->dir == PORT_DIR_OUTPUT) {
481 if (sub->swm->type == PORT_TYPE_I2S) {
482 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
483 dev_err(dev, "PLL(%d) is invalid\n",
484 sub->aio->pll_out);
485 return -EINVAL;
486 }
487 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
488 dev_err(dev, "PLL divider(%d) is invalid\n",
489 sub->aio->plldiv);
490 return -EINVAL;
491 }
492
493 v = v_pll[sub->aio->pll_out] |
494 OPORTMXCTR2_MSSEL_MASTER |
495 v_div[sub->aio->plldiv];
496
497 switch (chip->plls[sub->aio->pll_out].freq) {
498 case 0:
499 case 36864000:
500 case 33868800:
501 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
502 break;
503 default:
504 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
505 break;
506 }
507 } else if (sub->swm->type == PORT_TYPE_EVE) {
508 v = OPORTMXCTR2_ACLKSEL_A2PLL |
509 OPORTMXCTR2_MSSEL_MASTER |
510 OPORTMXCTR2_EXTLSIFSSEL_36 |
511 OPORTMXCTR2_DACCKSEL_1_2;
512 } else if (sub->swm->type == PORT_TYPE_SPDIF) {
513 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
514 dev_err(dev, "PLL(%d) is invalid\n",
515 sub->aio->pll_out);
516 return -EINVAL;
517 }
518 v = v_pll[sub->aio->pll_out] |
519 OPORTMXCTR2_MSSEL_MASTER |
520 OPORTMXCTR2_DACCKSEL_1_2;
521
522 switch (chip->plls[sub->aio->pll_out].freq) {
523 case 0:
524 case 36864000:
525 case 33868800:
526 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
527 break;
528 default:
529 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
530 break;
531 }
532 } else {
533 v = OPORTMXCTR2_ACLKSEL_A1 |
534 OPORTMXCTR2_MSSEL_MASTER |
535 OPORTMXCTR2_EXTLSIFSSEL_36 |
536 OPORTMXCTR2_DACCKSEL_1_2;
537 }
538 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
539 } else {
540 v = IPORTMXCTR2_ACLKSEL_A1 |
541 IPORTMXCTR2_MSSEL_SLAVE |
542 IPORTMXCTR2_EXTLSIFSSEL_36 |
543 IPORTMXCTR2_DACCKSEL_1_2;
544 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
545 }
546
547 return 0;
548}
549
550
551
552
553
554
555
556
557
558
559
560
561
562int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
563 const struct snd_pcm_hw_params *params)
564{
565 struct regmap *r = sub->aio->chip->regmap;
566 unsigned int rate;
567 u32 v;
568 int ret;
569
570 if (!pass_through) {
571 if (sub->swm->type == PORT_TYPE_EVE ||
572 sub->swm->type == PORT_TYPE_CONV) {
573 rate = 48000;
574 } else {
575 rate = params_rate(params);
576 }
577
578 ret = aio_port_set_rate(sub, rate);
579 if (ret)
580 return ret;
581
582 ret = aio_port_set_fmt(sub);
583 if (ret)
584 return ret;
585 }
586
587 ret = aio_port_set_clk(sub);
588 if (ret)
589 return ret;
590
591 if (sub->swm->dir == PORT_DIR_OUTPUT) {
592 if (pass_through)
593 v = OPORTMXCTR3_SRCSEL_STREAM |
594 OPORTMXCTR3_VALID_STREAM;
595 else
596 v = OPORTMXCTR3_SRCSEL_PCM |
597 OPORTMXCTR3_VALID_PCM;
598
599 v |= OPORTMXCTR3_IECTHUR_IECOUT |
600 OPORTMXCTR3_PMSEL_PAUSE |
601 OPORTMXCTR3_PMSW_MUTE_OFF;
602 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
603 } else {
604 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
605 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
606 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
607 IPORTMXEXNOE_PCMINOE_INPUT);
608 }
609
610 return 0;
611}
612
613
614
615
616
617
618
619
620void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
621{
622 struct regmap *r = sub->aio->chip->regmap;
623
624 if (sub->swm->dir == PORT_DIR_OUTPUT) {
625 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
626 sub->swm->oif.map);
627
628 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
629 OPORTMXMASK_IUDXMSK_MASK |
630 OPORTMXMASK_IUXCKMSK_MASK |
631 OPORTMXMASK_DXMSK_MASK |
632 OPORTMXMASK_XCKMSK_MASK,
633 OPORTMXMASK_IUDXMSK_OFF |
634 OPORTMXMASK_IUXCKMSK_OFF |
635 OPORTMXMASK_DXMSK_OFF |
636 OPORTMXMASK_XCKMSK_OFF);
637
638 if (enable)
639 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
640 else
641 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
642 } else {
643 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
644 IPORTMXMASK_IUXCKMSK_MASK |
645 IPORTMXMASK_XCKMSK_MASK,
646 IPORTMXMASK_IUXCKMSK_OFF |
647 IPORTMXMASK_XCKMSK_OFF);
648
649 if (enable)
650 regmap_update_bits(r,
651 IPORTMXCTR2(sub->swm->iport.map),
652 IPORTMXCTR2_REQEN_MASK,
653 IPORTMXCTR2_REQEN_ENABLE);
654 else
655 regmap_update_bits(r,
656 IPORTMXCTR2(sub->swm->iport.map),
657 IPORTMXCTR2_REQEN_MASK,
658 IPORTMXCTR2_REQEN_DISABLE);
659 }
660}
661
662
663
664
665
666
667
668int aio_port_get_volume(struct uniphier_aio_sub *sub)
669{
670 struct regmap *r = sub->aio->chip->regmap;
671 u32 v;
672
673 regmap_read(r, OPORTMXTYVOLGAINSTATUS(sub->swm->oport.map, 0), &v);
674
675 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK, v);
676}
677
678
679
680
681
682
683
684
685
686
687void aio_port_set_volume(struct uniphier_aio_sub *sub, int vol)
688{
689 struct regmap *r = sub->aio->chip->regmap;
690 int oport_map = sub->swm->oport.map;
691 int cur, diff, slope = 0, fs;
692
693 if (sub->swm->dir == PORT_DIR_INPUT)
694 return;
695
696 cur = aio_port_get_volume(sub);
697 diff = abs(vol - cur);
698 fs = params_rate(&sub->params);
699 if (fs)
700 slope = diff / AUD_VOL_FADE_TIME * 1000 / fs;
701 slope = max(1, slope);
702
703 regmap_update_bits(r, OPORTMXTYVOLPARA1(oport_map, 0),
704 OPORTMXTYVOLPARA1_SLOPEU_MASK, slope << 16);
705 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
706 OPORTMXTYVOLPARA2_TARGET_MASK, vol);
707
708 if (cur < vol)
709 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
710 OPORTMXTYVOLPARA2_FADE_MASK,
711 OPORTMXTYVOLPARA2_FADE_FADEIN);
712 else
713 regmap_update_bits(r, OPORTMXTYVOLPARA2(oport_map, 0),
714 OPORTMXTYVOLPARA2_FADE_MASK,
715 OPORTMXTYVOLPARA2_FADE_FADEOUT);
716
717 regmap_write(r, AOUTFADECTR0, BIT(oport_map));
718}
719
720
721
722
723
724
725
726
727
728
729
730
731int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
732{
733 struct regmap *r = sub->aio->chip->regmap;
734 u32 v;
735
736 if (sub->swm->dir == PORT_DIR_OUTPUT) {
737 if (pass_through)
738 v = PBOUTMXCTR0_ENDIAN_0123 |
739 PBOUTMXCTR0_MEMFMT_STREAM;
740 else
741 v = PBOUTMXCTR0_ENDIAN_3210 |
742 PBOUTMXCTR0_MEMFMT_2CH;
743
744 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
745 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
746 } else {
747 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
748 PBINMXCTR_NCONNECT_CONNECT |
749 PBINMXCTR_INOUTSEL_IN |
750 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
751 PBINMXCTR_ENDIAN_3210 |
752 PBINMXCTR_MEMFMT_D0);
753 }
754
755 return 0;
756}
757
758
759
760
761
762
763
764
765
766
767
768int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
769 enum IEC61937_PC pc)
770{
771 struct regmap *r = sub->aio->chip->regmap;
772 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
773
774 switch (pc) {
775 case IEC61937_PC_AC3:
776 repet = OPORTMXREPET_STRLENGTH_AC3 |
777 OPORTMXREPET_PMLENGTH_AC3;
778 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
779 break;
780 case IEC61937_PC_MPA:
781 repet = OPORTMXREPET_STRLENGTH_MPA |
782 OPORTMXREPET_PMLENGTH_MPA;
783 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
784 break;
785 case IEC61937_PC_MP3:
786 repet = OPORTMXREPET_STRLENGTH_MP3 |
787 OPORTMXREPET_PMLENGTH_MP3;
788 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
789 break;
790 case IEC61937_PC_DTS1:
791 repet = OPORTMXREPET_STRLENGTH_DTS1 |
792 OPORTMXREPET_PMLENGTH_DTS1;
793 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
794 break;
795 case IEC61937_PC_DTS2:
796 repet = OPORTMXREPET_STRLENGTH_DTS2 |
797 OPORTMXREPET_PMLENGTH_DTS2;
798 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
799 break;
800 case IEC61937_PC_DTS3:
801 repet = OPORTMXREPET_STRLENGTH_DTS3 |
802 OPORTMXREPET_PMLENGTH_DTS3;
803 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
804 break;
805 case IEC61937_PC_AAC:
806 repet = OPORTMXREPET_STRLENGTH_AAC |
807 OPORTMXREPET_PMLENGTH_AAC;
808 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
809 break;
810 case IEC61937_PC_PAUSE:
811
812 break;
813 }
814
815 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
816 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
817
818 return 0;
819}
820
821
822
823
824
825
826
827
828
829void aio_src_reset(struct uniphier_aio_sub *sub)
830{
831 struct regmap *r = sub->aio->chip->regmap;
832
833 if (sub->swm->dir != PORT_DIR_OUTPUT)
834 return;
835
836 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
837 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
838}
839
840
841
842
843
844
845
846
847
848
849
850
851int aio_src_set_param(struct uniphier_aio_sub *sub,
852 const struct snd_pcm_hw_params *params)
853{
854 struct regmap *r = sub->aio->chip->regmap;
855 u32 v;
856
857 if (sub->swm->dir != PORT_DIR_OUTPUT)
858 return 0;
859
860 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
861 OPORTMXSRC1CTR_THMODE_SRC |
862 OPORTMXSRC1CTR_SRCPATH_CALC |
863 OPORTMXSRC1CTR_SYNC_ASYNC |
864 OPORTMXSRC1CTR_FSIIPSEL_INNER |
865 OPORTMXSRC1CTR_FSISEL_ACLK);
866
867 switch (params_rate(params)) {
868 default:
869 case 48000:
870 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
871 OPORTMXRATE_I_MCKSEL_36 |
872 OPORTMXRATE_I_FSSEL_48;
873 break;
874 case 44100:
875 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
876 OPORTMXRATE_I_MCKSEL_33 |
877 OPORTMXRATE_I_FSSEL_44_1;
878 break;
879 case 32000:
880 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
881 OPORTMXRATE_I_MCKSEL_36 |
882 OPORTMXRATE_I_FSSEL_32;
883 break;
884 }
885
886 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
887 v | OPORTMXRATE_I_ACLKSRC_APLL |
888 OPORTMXRATE_I_LRCKSTP_STOP);
889 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
890 OPORTMXRATE_I_LRCKSTP_MASK,
891 OPORTMXRATE_I_LRCKSTP_START);
892
893 return 0;
894}
895
896int aio_srcif_set_param(struct uniphier_aio_sub *sub)
897{
898 struct regmap *r = sub->aio->chip->regmap;
899
900 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
901 PBINMXCTR_NCONNECT_CONNECT |
902 PBINMXCTR_INOUTSEL_OUT |
903 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
904 PBINMXCTR_ENDIAN_3210 |
905 PBINMXCTR_MEMFMT_D0);
906
907 return 0;
908}
909
910int aio_srcch_set_param(struct uniphier_aio_sub *sub)
911{
912 struct regmap *r = sub->aio->chip->regmap;
913
914 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
915 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
916
917 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
918 CDA2D_CHMXAMODE_ENDIAN_3210 |
919 CDA2D_CHMXAMODE_AUPDT_FIX |
920 CDA2D_CHMXAMODE_TYPE_NORMAL);
921
922 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
923 CDA2D_CHMXAMODE_ENDIAN_3210 |
924 CDA2D_CHMXAMODE_AUPDT_INC |
925 CDA2D_CHMXAMODE_TYPE_RING |
926 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
927
928 return 0;
929}
930
931void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
932{
933 struct regmap *r = sub->aio->chip->regmap;
934 u32 v;
935
936 if (enable)
937 v = CDA2D_STRT0_STOP_START;
938 else
939 v = CDA2D_STRT0_STOP_STOP;
940
941 regmap_write(r, CDA2D_STRT0,
942 v | BIT(sub->swm->och.map));
943}
944
945int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
946{
947 struct regmap *r = sub->aio->chip->regmap;
948 u32 v;
949
950 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
951 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
952
953 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
954 CDA2D_CHMXAMODE_AUPDT_INC |
955 CDA2D_CHMXAMODE_TYPE_NORMAL |
956 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
957 if (sub->swm->dir == PORT_DIR_OUTPUT)
958 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
959 else
960 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
961
962 return 0;
963}
964
965void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
966{
967 struct regmap *r = sub->aio->chip->regmap;
968
969 if (enable) {
970 regmap_write(r, CDA2D_STRT0,
971 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
972
973 regmap_update_bits(r, INTRBIM(0),
974 BIT(sub->swm->rb.map),
975 BIT(sub->swm->rb.map));
976 } else {
977 regmap_write(r, CDA2D_STRT0,
978 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
979
980 regmap_update_bits(r, INTRBIM(0),
981 BIT(sub->swm->rb.map),
982 0);
983 }
984}
985
986static u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
987{
988 struct regmap *r = sub->aio->chip->regmap;
989 u32 pos_u, pos_l;
990 int i;
991
992 regmap_write(r, CDA2D_RDPTRLOAD,
993 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
994
995 for (i = 0; i < 6; i++)
996 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
997
998 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
999 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
1000 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1001
1002 return ((u64)pos_u << 32) | pos_l;
1003}
1004
1005static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
1006{
1007 struct regmap *r = sub->aio->chip->regmap;
1008 u32 tmp;
1009 int i;
1010
1011 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
1012 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
1013 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
1014
1015 for (i = 0; i < 6; i++)
1016 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
1017}
1018
1019static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
1020{
1021 struct regmap *r = sub->aio->chip->regmap;
1022 u32 pos_u, pos_l;
1023 int i;
1024
1025 regmap_write(r, CDA2D_WRPTRLOAD,
1026 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
1027
1028 for (i = 0; i < 6; i++)
1029 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1030
1031 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
1032 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
1033 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
1034
1035 return ((u64)pos_u << 32) | pos_l;
1036}
1037
1038static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
1039{
1040 struct regmap *r = sub->aio->chip->regmap;
1041 u32 tmp;
1042 int i;
1043
1044 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
1045 lower_32_bits(pos));
1046 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
1047 upper_32_bits(pos));
1048 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
1049
1050 for (i = 0; i < 6; i++)
1051 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
1052}
1053
1054int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
1055{
1056 struct regmap *r = sub->aio->chip->regmap;
1057
1058 if (size <= th)
1059 return -EINVAL;
1060
1061 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
1062 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
1063
1064 return 0;
1065}
1066
1067int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
1068 int period)
1069{
1070 struct regmap *r = sub->aio->chip->regmap;
1071 u64 size = end - start;
1072 int ret;
1073
1074 if (end < start || period < 0)
1075 return -EINVAL;
1076
1077 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
1078 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1079 lower_32_bits(start));
1080 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1081 upper_32_bits(start));
1082 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1083 lower_32_bits(end));
1084 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1085 upper_32_bits(end));
1086
1087 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1088
1089 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1090 if (ret)
1091 return ret;
1092
1093 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1094 aiodma_rb_set_rp(sub, start);
1095 aiodma_rb_set_wp(sub, end - period);
1096
1097 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1098 CDA2D_RBMXIX_SPACE,
1099 CDA2D_RBMXIX_SPACE);
1100 } else {
1101 aiodma_rb_set_rp(sub, end - period);
1102 aiodma_rb_set_wp(sub, start);
1103
1104 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1105 CDA2D_RBMXIX_REMAIN,
1106 CDA2D_RBMXIX_REMAIN);
1107 }
1108
1109 sub->threshold = 2 * period;
1110 sub->rd_offs = 0;
1111 sub->wr_offs = 0;
1112 sub->rd_org = 0;
1113 sub->wr_org = 0;
1114 sub->rd_total = 0;
1115 sub->wr_total = 0;
1116
1117 return 0;
1118}
1119
1120void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1121 int period)
1122{
1123 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1124 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1125
1126 if (sub->use_mmap) {
1127 sub->threshold = 2 * period;
1128 aiodma_rb_set_threshold(sub, size, 2 * period);
1129
1130 sub->wr_offs = sub->rd_offs - period;
1131 if (sub->rd_offs < period)
1132 sub->wr_offs += size;
1133 }
1134 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1135 } else {
1136 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1137
1138 if (sub->use_mmap) {
1139 sub->threshold = 2 * period;
1140 aiodma_rb_set_threshold(sub, size, 2 * period);
1141
1142 sub->rd_offs = sub->wr_offs - period;
1143 if (sub->wr_offs < period)
1144 sub->rd_offs += size;
1145 }
1146 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1147 }
1148
1149 sub->rd_total += sub->rd_offs - sub->rd_org;
1150 if (sub->rd_offs < sub->rd_org)
1151 sub->rd_total += size;
1152 sub->wr_total += sub->wr_offs - sub->wr_org;
1153 if (sub->wr_offs < sub->wr_org)
1154 sub->wr_total += size;
1155
1156 sub->rd_org = sub->rd_offs;
1157 sub->wr_org = sub->wr_offs;
1158}
1159
1160bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1161{
1162 struct regmap *r = sub->aio->chip->regmap;
1163 u32 ir;
1164
1165 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1166
1167 if (sub->swm->dir == PORT_DIR_OUTPUT)
1168 return !!(ir & CDA2D_RBMXIX_SPACE);
1169 else
1170 return !!(ir & CDA2D_RBMXIX_REMAIN);
1171}
1172
1173void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1174{
1175 struct regmap *r = sub->aio->chip->regmap;
1176
1177 if (sub->swm->dir == PORT_DIR_OUTPUT)
1178 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1179 CDA2D_RBMXIX_SPACE);
1180 else
1181 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1182 CDA2D_RBMXIX_REMAIN);
1183}
1184