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