xref: /openbmc/linux/sound/soc/uniphier/aio-core.c (revision bc33f5e5)
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 
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 
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 
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 
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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