xref: /openbmc/linux/sound/soc/uniphier/aio-core.c (revision cb870fdc)
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 	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  */
aio_port_set_rate(struct uniphier_aio_sub * sub,int rate)330 static 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  */
aio_port_set_fmt(struct uniphier_aio_sub * sub)449 static 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  */
aio_port_set_clk(struct uniphier_aio_sub * sub)514 static 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  */
aio_port_set_param(struct uniphier_aio_sub * sub,int pass_through,const struct snd_pcm_hw_params * params)613 int 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  */
aio_port_set_enable(struct uniphier_aio_sub * sub,int enable)675 void 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  */
aio_port_get_volume(struct uniphier_aio_sub * sub)723 int 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  */
aio_port_set_volume(struct uniphier_aio_sub * sub,int vol)742 void 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  */
aio_if_set_param(struct uniphier_aio_sub * sub,int pass_through)786 int 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  */
aio_oport_set_stream_type(struct uniphier_aio_sub * sub,enum IEC61937_PC pc)836 int 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  */
aio_src_reset(struct uniphier_aio_sub * sub)897 void 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  */
aio_src_set_param(struct uniphier_aio_sub * sub,const struct snd_pcm_hw_params * params)919 int 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 
aio_srcif_set_param(struct uniphier_aio_sub * sub)964 int 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 
aio_srcch_set_param(struct uniphier_aio_sub * sub)978 int 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 
aio_srcch_set_enable(struct uniphier_aio_sub * sub,int enable)999 void 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 
aiodma_ch_set_param(struct uniphier_aio_sub * sub)1013 int 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 
aiodma_ch_set_enable(struct uniphier_aio_sub * sub,int enable)1033 void 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 
aiodma_rb_get_rp(struct uniphier_aio_sub * sub)1054 static 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 
aiodma_rb_set_rp(struct uniphier_aio_sub * sub,u64 pos)1073 static 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 
aiodma_rb_get_wp(struct uniphier_aio_sub * sub)1087 static 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 
aiodma_rb_set_wp(struct uniphier_aio_sub * sub,u64 pos)1106 static 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 
aiodma_rb_set_threshold(struct uniphier_aio_sub * sub,u64 size,u32 th)1122 int 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 
aiodma_rb_set_buffer(struct uniphier_aio_sub * sub,u64 start,u64 end,int period)1135 int 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 
aiodma_rb_sync(struct uniphier_aio_sub * sub,u64 start,u64 size,int period)1188 void 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 
aiodma_rb_is_irq(struct uniphier_aio_sub * sub)1228 bool 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 
aiodma_rb_clear_irq(struct uniphier_aio_sub * sub)1241 void 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