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