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