aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatsuhiro Suzuki <suzuki.katsuhiro@socionext.com>2018-01-19 04:25:29 -0500
committerMark Brown <broonie@kernel.org>2018-02-12 07:49:51 -0500
commitf37fe2f9987b0460f25a87b1380f8e97a5959121 (patch)
tree6a519d9edcfa199017659feac88c82e85503b9b5
parent28fb53de064b24eed55540ddeccab517e4babca3 (diff)
ASoC: uniphier: add support for UniPhier AIO common driver
This patch adds common functions for UniPhier AIO audio sound system. This provides commonly used APIs for input/output control registers for UniPhier AIO. This module provides all sound devices for I2S, S/PDIF and so on. Since the AIO has mixed register map for those I/Os, it is hard to split register areas for each sound devices. Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/uniphier/Kconfig10
-rw-r--r--sound/soc/uniphier/Makefile4
-rw-r--r--sound/soc/uniphier/aio-core.c1104
-rw-r--r--sound/soc/uniphier/aio-reg.h462
-rw-r--r--sound/soc/uniphier/aio.h343
5 files changed, 1923 insertions, 0 deletions
diff --git a/sound/soc/uniphier/Kconfig b/sound/soc/uniphier/Kconfig
index 02886a457eaf..78ce101d2cc2 100644
--- a/sound/soc/uniphier/Kconfig
+++ b/sound/soc/uniphier/Kconfig
@@ -8,6 +8,16 @@ config SND_SOC_UNIPHIER
8 audio interfaces to support below. 8 audio interfaces to support below.
9 If unsure select "N". 9 If unsure select "N".
10 10
11config SND_SOC_UNIPHIER_AIO
12 tristate "UniPhier AIO DAI Driver"
13 select REGMAP_MMIO
14 depends on SND_SOC_UNIPHIER
15 help
16 This adds ASoC driver support for Socionext UniPhier
17 'AIO' Audio Input/Output subsystem.
18 Select Y if you use such device.
19 If unsure select "N".
20
11config SND_SOC_UNIPHIER_EVEA_CODEC 21config SND_SOC_UNIPHIER_EVEA_CODEC
12 tristate "UniPhier SoC internal audio codec" 22 tristate "UniPhier SoC internal audio codec"
13 depends on SND_SOC_UNIPHIER 23 depends on SND_SOC_UNIPHIER
diff --git a/sound/soc/uniphier/Makefile b/sound/soc/uniphier/Makefile
index 3be00d72f5e5..f3b36aba4879 100644
--- a/sound/soc/uniphier/Makefile
+++ b/sound/soc/uniphier/Makefile
@@ -1,3 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2snd-soc-uniphier-aio-cpu-objs := aio-core.o
3
4obj-$(CONFIG_SND_SOC_UNIPHIER_AIO) += snd-soc-uniphier-aio-cpu.o
5
2snd-soc-uniphier-evea-objs := evea.o 6snd-soc-uniphier-evea-objs := evea.o
3obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o 7obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o
diff --git a/sound/soc/uniphier/aio-core.c b/sound/soc/uniphier/aio-core.c
new file mode 100644
index 000000000000..7e9451ca24af
--- /dev/null
+++ b/sound/soc/uniphier/aio-core.c
@@ -0,0 +1,1104 @@
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
32static 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
40static 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
48static 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
56static 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
66u64 aio_rb_cnt(struct uniphier_aio_sub *sub)
67{
68 return rb_cnt(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
69}
70
71u64 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
76u64 aio_rb_space(struct uniphier_aio_sub *sub)
77{
78 return rb_space(sub->wr_offs, sub->rd_offs, sub->compr_bytes);
79}
80
81u64 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_chip_set_pll - set frequency to audio PLL
88 * @chip : the AIO chip pointer
89 * @source: PLL
90 * @freq : frequency in Hz, 0 is ignored
91 *
92 * Sets frequency of audio PLL. This function can be called anytime,
93 * but it takes time till PLL is locked.
94 *
95 * Return: Zero if successful, otherwise a negative value on error.
96 */
97int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
98 unsigned int freq)
99{
100 struct device *dev = &chip->pdev->dev;
101 struct regmap *r = chip->regmap;
102 int shift;
103 u32 v;
104
105 /* Not change */
106 if (freq == 0)
107 return 0;
108
109 switch (pll_id) {
110 case AUD_PLL_A1:
111 shift = 0;
112 break;
113 case AUD_PLL_F1:
114 shift = 1;
115 break;
116 case AUD_PLL_A2:
117 shift = 2;
118 break;
119 case AUD_PLL_F2:
120 shift = 3;
121 break;
122 default:
123 dev_err(dev, "PLL(%d) not supported\n", pll_id);
124 return -EINVAL;
125 }
126
127 switch (freq) {
128 case 36864000:
129 v = A2APLLCTR1_APLLX_36MHZ;
130 break;
131 case 33868800:
132 v = A2APLLCTR1_APLLX_33MHZ;
133 break;
134 default:
135 dev_err(dev, "PLL frequency not supported(%d)\n", freq);
136 return -EINVAL;
137 }
138 chip->plls[pll_id].freq = freq;
139
140 regmap_update_bits(r, A2APLLCTR1, A2APLLCTR1_APLLX_MASK << shift,
141 v << shift);
142
143 return 0;
144}
145
146/**
147 * aio_chip_init - initialize AIO whole settings
148 * @chip: the AIO chip pointer
149 *
150 * Sets AIO fixed and whole device settings to AIO.
151 * This function need to call once at driver startup.
152 *
153 * The register area that is changed by this function is shared by all
154 * modules of AIO. But there is not race condition since this function
155 * has always set the same initialize values.
156 */
157void aio_chip_init(struct uniphier_aio_chip *chip)
158{
159 struct regmap *r = chip->regmap;
160
161 regmap_update_bits(r, A2APLLCTR0,
162 A2APLLCTR0_APLLXPOW_MASK,
163 A2APLLCTR0_APLLXPOW_PWON);
164
165 regmap_update_bits(r, A2EXMCLKSEL0,
166 A2EXMCLKSEL0_EXMCLK_MASK,
167 A2EXMCLKSEL0_EXMCLK_OUTPUT);
168
169 regmap_update_bits(r, A2AIOINPUTSEL, A2AIOINPUTSEL_RXSEL_MASK,
170 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 |
171 A2AIOINPUTSEL_RXSEL_PCMI2_SIF |
172 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA |
173 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1);
174
175 if (chip->chip_spec->addr_ext)
176 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
177 CDA2D_TEST_DDR_MODE_EXTON0);
178 else
179 regmap_update_bits(r, CDA2D_TEST, CDA2D_TEST_DDR_MODE_MASK,
180 CDA2D_TEST_DDR_MODE_EXTOFF1);
181}
182
183/**
184 * aio_init - initialize AIO substream
185 * @sub: the AIO substream pointer
186 *
187 * Sets fixed settings of each AIO substreams.
188 * This function need to call once at substream startup.
189 *
190 * Return: Zero if successful, otherwise a negative value on error.
191 */
192int aio_init(struct uniphier_aio_sub *sub)
193{
194 struct device *dev = &sub->aio->chip->pdev->dev;
195 struct regmap *r = sub->aio->chip->regmap;
196
197 regmap_write(r, A2RBNMAPCTR0(sub->swm->rb.hw),
198 MAPCTR0_EN | sub->swm->rb.map);
199 regmap_write(r, A2CHNMAPCTR0(sub->swm->ch.hw),
200 MAPCTR0_EN | sub->swm->ch.map);
201
202 switch (sub->swm->type) {
203 case PORT_TYPE_I2S:
204 case PORT_TYPE_SPDIF:
205 case PORT_TYPE_EVE:
206 if (sub->swm->dir == PORT_DIR_INPUT) {
207 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
208 MAPCTR0_EN | sub->swm->iif.map);
209 regmap_write(r, A2IPORTNMAPCTR0(sub->swm->iport.hw),
210 MAPCTR0_EN | sub->swm->iport.map);
211 } else {
212 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
213 MAPCTR0_EN | sub->swm->oif.map);
214 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
215 MAPCTR0_EN | sub->swm->oport.map);
216 }
217 break;
218 case PORT_TYPE_CONV:
219 regmap_write(r, A2OIFNMAPCTR0(sub->swm->oif.hw),
220 MAPCTR0_EN | sub->swm->oif.map);
221 regmap_write(r, A2OPORTNMAPCTR0(sub->swm->oport.hw),
222 MAPCTR0_EN | sub->swm->oport.map);
223 regmap_write(r, A2CHNMAPCTR0(sub->swm->och.hw),
224 MAPCTR0_EN | sub->swm->och.map);
225 regmap_write(r, A2IIFNMAPCTR0(sub->swm->iif.hw),
226 MAPCTR0_EN | sub->swm->iif.map);
227 break;
228 default:
229 dev_err(dev, "Unknown port type %d.\n", sub->swm->type);
230 return -EINVAL;
231 }
232
233 return 0;
234}
235
236/**
237 * aio_port_reset - reset AIO port block
238 * @sub: the AIO substream pointer
239 *
240 * Resets the digital signal input/output port block of AIO.
241 */
242void aio_port_reset(struct uniphier_aio_sub *sub)
243{
244 struct regmap *r = sub->aio->chip->regmap;
245
246 if (sub->swm->dir == PORT_DIR_OUTPUT) {
247 regmap_write(r, AOUTRSTCTR0, BIT(sub->swm->oport.map));
248 regmap_write(r, AOUTRSTCTR1, BIT(sub->swm->oport.map));
249 } else {
250 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
251 IPORTMXRSTCTR_RSTPI_MASK,
252 IPORTMXRSTCTR_RSTPI_RESET);
253 regmap_update_bits(r, IPORTMXRSTCTR(sub->swm->iport.map),
254 IPORTMXRSTCTR_RSTPI_MASK,
255 IPORTMXRSTCTR_RSTPI_RELEASE);
256 }
257}
258
259/**
260 * aio_port_set_rate - set sampling rate of LPCM
261 * @sub: the AIO substream pointer, PCM substream only
262 * @rate: Sampling rate in Hz.
263 *
264 * Set suitable I2S format settings to input/output port block of AIO.
265 * Parameter is specified by hw_params().
266 *
267 * This function may return error if non-PCM substream.
268 *
269 * Return: Zero if successful, otherwise a negative value on error.
270 */
271int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate)
272{
273 struct regmap *r = sub->aio->chip->regmap;
274 struct device *dev = &sub->aio->chip->pdev->dev;
275 u32 v;
276
277 if (sub->swm->dir == PORT_DIR_OUTPUT) {
278 switch (rate) {
279 case 8000:
280 v = OPORTMXCTR1_FSSEL_8;
281 break;
282 case 11025:
283 v = OPORTMXCTR1_FSSEL_11_025;
284 break;
285 case 12000:
286 v = OPORTMXCTR1_FSSEL_12;
287 break;
288 case 16000:
289 v = OPORTMXCTR1_FSSEL_16;
290 break;
291 case 22050:
292 v = OPORTMXCTR1_FSSEL_22_05;
293 break;
294 case 24000:
295 v = OPORTMXCTR1_FSSEL_24;
296 break;
297 case 32000:
298 v = OPORTMXCTR1_FSSEL_32;
299 break;
300 case 44100:
301 v = OPORTMXCTR1_FSSEL_44_1;
302 break;
303 case 48000:
304 v = OPORTMXCTR1_FSSEL_48;
305 break;
306 case 88200:
307 v = OPORTMXCTR1_FSSEL_88_2;
308 break;
309 case 96000:
310 v = OPORTMXCTR1_FSSEL_96;
311 break;
312 case 176400:
313 v = OPORTMXCTR1_FSSEL_176_4;
314 break;
315 case 192000:
316 v = OPORTMXCTR1_FSSEL_192;
317 break;
318 default:
319 dev_err(dev, "Rate not supported(%d)\n", rate);
320 return -EINVAL;
321 }
322
323 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
324 OPORTMXCTR1_FSSEL_MASK, v);
325 } else {
326 switch (rate) {
327 case 8000:
328 v = IPORTMXCTR1_FSSEL_8;
329 break;
330 case 11025:
331 v = IPORTMXCTR1_FSSEL_11_025;
332 break;
333 case 12000:
334 v = IPORTMXCTR1_FSSEL_12;
335 break;
336 case 16000:
337 v = IPORTMXCTR1_FSSEL_16;
338 break;
339 case 22050:
340 v = IPORTMXCTR1_FSSEL_22_05;
341 break;
342 case 24000:
343 v = IPORTMXCTR1_FSSEL_24;
344 break;
345 case 32000:
346 v = IPORTMXCTR1_FSSEL_32;
347 break;
348 case 44100:
349 v = IPORTMXCTR1_FSSEL_44_1;
350 break;
351 case 48000:
352 v = IPORTMXCTR1_FSSEL_48;
353 break;
354 case 88200:
355 v = IPORTMXCTR1_FSSEL_88_2;
356 break;
357 case 96000:
358 v = IPORTMXCTR1_FSSEL_96;
359 break;
360 case 176400:
361 v = IPORTMXCTR1_FSSEL_176_4;
362 break;
363 case 192000:
364 v = IPORTMXCTR1_FSSEL_192;
365 break;
366 default:
367 dev_err(dev, "Rate not supported(%d)\n", rate);
368 return -EINVAL;
369 }
370
371 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
372 IPORTMXCTR1_FSSEL_MASK, v);
373 }
374
375 return 0;
376}
377
378/**
379 * aio_port_set_fmt - set format of I2S data
380 * @sub: the AIO substream pointer, PCM substream only
381 * This parameter has no effect if substream is I2S or PCM.
382 *
383 * Set suitable I2S format settings to input/output port block of AIO.
384 * Parameter is specified by set_fmt().
385 *
386 * This function may return error if non-PCM substream.
387 *
388 * Return: Zero if successful, otherwise a negative value on error.
389 */
390int aio_port_set_fmt(struct uniphier_aio_sub *sub)
391{
392 struct regmap *r = sub->aio->chip->regmap;
393 struct device *dev = &sub->aio->chip->pdev->dev;
394 u32 v;
395
396 if (sub->swm->dir == PORT_DIR_OUTPUT) {
397 switch (sub->aio->fmt) {
398 case SND_SOC_DAIFMT_LEFT_J:
399 v = OPORTMXCTR1_I2SLRSEL_LEFT;
400 break;
401 case SND_SOC_DAIFMT_RIGHT_J:
402 v = OPORTMXCTR1_I2SLRSEL_RIGHT;
403 break;
404 case SND_SOC_DAIFMT_I2S:
405 v = OPORTMXCTR1_I2SLRSEL_I2S;
406 break;
407 default:
408 dev_err(dev, "Format is not supported(%d)\n",
409 sub->aio->fmt);
410 return -EINVAL;
411 }
412
413 v |= OPORTMXCTR1_OUTBITSEL_24;
414 regmap_update_bits(r, OPORTMXCTR1(sub->swm->oport.map),
415 OPORTMXCTR1_I2SLRSEL_MASK |
416 OPORTMXCTR1_OUTBITSEL_MASK, v);
417 } else {
418 switch (sub->aio->fmt) {
419 case SND_SOC_DAIFMT_LEFT_J:
420 v = IPORTMXCTR1_LRSEL_LEFT;
421 break;
422 case SND_SOC_DAIFMT_RIGHT_J:
423 v = IPORTMXCTR1_LRSEL_RIGHT;
424 break;
425 case SND_SOC_DAIFMT_I2S:
426 v = IPORTMXCTR1_LRSEL_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 |= IPORTMXCTR1_OUTBITSEL_24 |
435 IPORTMXCTR1_CHSEL_ALL;
436 regmap_update_bits(r, IPORTMXCTR1(sub->swm->iport.map),
437 IPORTMXCTR1_LRSEL_MASK |
438 IPORTMXCTR1_OUTBITSEL_MASK |
439 IPORTMXCTR1_CHSEL_MASK, v);
440 }
441
442 return 0;
443}
444
445/**
446 * aio_port_set_clk - set clock and divider of AIO port block
447 * @sub: the AIO substream pointer
448 *
449 * Set suitable PLL clock divider and relational settings to
450 * input/output port block of AIO. Parameters are specified by
451 * set_sysclk() and set_pll().
452 *
453 * Return: Zero if successful, otherwise a negative value on error.
454 */
455int aio_port_set_clk(struct uniphier_aio_sub *sub)
456{
457 struct uniphier_aio_chip *chip = sub->aio->chip;
458 struct device *dev = &sub->aio->chip->pdev->dev;
459 struct regmap *r = sub->aio->chip->regmap;
460 u32 v_pll[] = {
461 OPORTMXCTR2_ACLKSEL_A1, OPORTMXCTR2_ACLKSEL_F1,
462 OPORTMXCTR2_ACLKSEL_A2, OPORTMXCTR2_ACLKSEL_F2,
463 OPORTMXCTR2_ACLKSEL_A2PLL,
464 OPORTMXCTR2_ACLKSEL_RX1,
465 };
466 u32 v_div[] = {
467 OPORTMXCTR2_DACCKSEL_1_2, OPORTMXCTR2_DACCKSEL_1_3,
468 OPORTMXCTR2_DACCKSEL_1_1, OPORTMXCTR2_DACCKSEL_2_3,
469 };
470 u32 v;
471
472 if (sub->swm->dir == PORT_DIR_OUTPUT) {
473 if (sub->swm->type == PORT_TYPE_I2S) {
474 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
475 dev_err(dev, "PLL(%d) is invalid\n",
476 sub->aio->pll_out);
477 return -EINVAL;
478 }
479 if (sub->aio->plldiv >= ARRAY_SIZE(v_div)) {
480 dev_err(dev, "PLL divider(%d) is invalid\n",
481 sub->aio->plldiv);
482 return -EINVAL;
483 }
484
485 v = v_pll[sub->aio->pll_out] |
486 OPORTMXCTR2_MSSEL_MASTER |
487 v_div[sub->aio->plldiv];
488
489 switch (chip->plls[sub->aio->pll_out].freq) {
490 case 0:
491 case 36864000:
492 case 33868800:
493 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
494 break;
495 default:
496 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
497 break;
498 }
499 } else if (sub->swm->type == PORT_TYPE_EVE) {
500 v = OPORTMXCTR2_ACLKSEL_A2PLL |
501 OPORTMXCTR2_MSSEL_MASTER |
502 OPORTMXCTR2_EXTLSIFSSEL_36 |
503 OPORTMXCTR2_DACCKSEL_1_2;
504 } else {
505 if (sub->aio->pll_out >= ARRAY_SIZE(v_pll)) {
506 dev_err(dev, "PLL(%d) is invalid\n",
507 sub->aio->pll_out);
508 return -EINVAL;
509 }
510 v = v_pll[sub->aio->pll_out] |
511 OPORTMXCTR2_MSSEL_MASTER |
512 OPORTMXCTR2_DACCKSEL_1_2;
513
514 switch (chip->plls[sub->aio->pll_out].freq) {
515 case 0:
516 case 36864000:
517 case 33868800:
518 v |= OPORTMXCTR2_EXTLSIFSSEL_36;
519 break;
520 default:
521 v |= OPORTMXCTR2_EXTLSIFSSEL_24;
522 break;
523 }
524 }
525 regmap_write(r, OPORTMXCTR2(sub->swm->oport.map), v);
526 } else {
527 v = IPORTMXCTR2_ACLKSEL_A1 |
528 IPORTMXCTR2_MSSEL_SLAVE |
529 IPORTMXCTR2_EXTLSIFSSEL_36 |
530 IPORTMXCTR2_DACCKSEL_1_2;
531 regmap_write(r, IPORTMXCTR2(sub->swm->iport.map), v);
532 }
533
534 return 0;
535}
536
537/**
538 * aio_port_set_param - set parameters of AIO port block
539 * @sub: the AIO substream pointer
540 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
541 * This parameter has no effect if substream is I2S or PCM.
542 * @params: hardware parameters of ALSA
543 *
544 * Set suitable setting to input/output port block of AIO to process the
545 * specified in params.
546 *
547 * Return: Zero if successful, otherwise a negative value on error.
548 */
549int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
550 const struct snd_pcm_hw_params *params)
551{
552 struct regmap *r = sub->aio->chip->regmap;
553 u32 v;
554 int ret;
555
556 if (!pass_through) {
557 ret = aio_port_set_rate(sub, params_rate(params));
558 if (ret)
559 return ret;
560
561 ret = aio_port_set_fmt(sub);
562 if (ret)
563 return ret;
564 }
565
566 ret = aio_port_set_clk(sub);
567 if (ret)
568 return ret;
569
570 if (sub->swm->dir == PORT_DIR_OUTPUT) {
571 if (pass_through)
572 v = OPORTMXCTR3_SRCSEL_STREAM |
573 OPORTMXCTR3_VALID_STREAM;
574 else
575 v = OPORTMXCTR3_SRCSEL_PCM |
576 OPORTMXCTR3_VALID_PCM;
577
578 v |= OPORTMXCTR3_IECTHUR_IECOUT |
579 OPORTMXCTR3_PMSEL_PAUSE |
580 OPORTMXCTR3_PMSW_MUTE_OFF;
581 regmap_write(r, OPORTMXCTR3(sub->swm->oport.map), v);
582 } else {
583 regmap_write(r, IPORTMXACLKSEL0EX(sub->swm->iport.map),
584 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL);
585 regmap_write(r, IPORTMXEXNOE(sub->swm->iport.map),
586 IPORTMXEXNOE_PCMINOE_INPUT);
587 }
588
589 return 0;
590}
591
592/**
593 * aio_port_set_enable - start or stop of AIO port block
594 * @sub: the AIO substream pointer
595 * @enable: zero to stop the block, otherwise to start
596 *
597 * Start or stop the signal input/output port block of AIO.
598 */
599void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable)
600{
601 struct regmap *r = sub->aio->chip->regmap;
602
603 if (sub->swm->dir == PORT_DIR_OUTPUT) {
604 regmap_write(r, OPORTMXPATH(sub->swm->oport.map),
605 sub->swm->oif.map);
606
607 regmap_update_bits(r, OPORTMXMASK(sub->swm->oport.map),
608 OPORTMXMASK_IUDXMSK_MASK |
609 OPORTMXMASK_IUXCKMSK_MASK |
610 OPORTMXMASK_DXMSK_MASK |
611 OPORTMXMASK_XCKMSK_MASK,
612 OPORTMXMASK_IUDXMSK_OFF |
613 OPORTMXMASK_IUXCKMSK_OFF |
614 OPORTMXMASK_DXMSK_OFF |
615 OPORTMXMASK_XCKMSK_OFF);
616
617 if (enable)
618 regmap_write(r, AOUTENCTR0, BIT(sub->swm->oport.map));
619 else
620 regmap_write(r, AOUTENCTR1, BIT(sub->swm->oport.map));
621 } else {
622 regmap_update_bits(r, IPORTMXMASK(sub->swm->iport.map),
623 IPORTMXMASK_IUXCKMSK_MASK |
624 IPORTMXMASK_XCKMSK_MASK,
625 IPORTMXMASK_IUXCKMSK_OFF |
626 IPORTMXMASK_XCKMSK_OFF);
627
628 if (enable)
629 regmap_update_bits(r,
630 IPORTMXCTR2(sub->swm->iport.map),
631 IPORTMXCTR2_REQEN_MASK,
632 IPORTMXCTR2_REQEN_ENABLE);
633 else
634 regmap_update_bits(r,
635 IPORTMXCTR2(sub->swm->iport.map),
636 IPORTMXCTR2_REQEN_MASK,
637 IPORTMXCTR2_REQEN_DISABLE);
638 }
639}
640
641/**
642 * aio_if_set_param - set parameters of AIO DMA I/F block
643 * @sub: the AIO substream pointer
644 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
645 * This parameter has no effect if substream is I2S or PCM.
646 *
647 * Set suitable setting to DMA interface block of AIO to process the
648 * specified in settings.
649 *
650 * Return: Zero if successful, otherwise a negative value on error.
651 */
652int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through)
653{
654 struct regmap *r = sub->aio->chip->regmap;
655 u32 v;
656
657 if (sub->swm->dir == PORT_DIR_OUTPUT) {
658 if (pass_through)
659 v = PBOUTMXCTR0_ENDIAN_0123 |
660 PBOUTMXCTR0_MEMFMT_STREAM;
661 else
662 v = PBOUTMXCTR0_ENDIAN_3210 |
663 PBOUTMXCTR0_MEMFMT_2CH;
664
665 regmap_write(r, PBOUTMXCTR0(sub->swm->oif.map), v);
666 regmap_write(r, PBOUTMXCTR1(sub->swm->oif.map), 0);
667 } else {
668 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
669 PBINMXCTR_NCONNECT_CONNECT |
670 PBINMXCTR_INOUTSEL_IN |
671 (sub->swm->iport.map << PBINMXCTR_PBINSEL_SHIFT) |
672 PBINMXCTR_ENDIAN_3210 |
673 PBINMXCTR_MEMFMT_D0);
674 }
675
676 return 0;
677}
678
679/**
680 * aio_oport_set_stream_type - set parameters of AIO playback port block
681 * @sub: the AIO substream pointer
682 * @pc: Pc type of IEC61937
683 *
684 * Set special setting to output port block of AIO to output the stream
685 * via S/PDIF.
686 *
687 * Return: Zero if successful, otherwise a negative value on error.
688 */
689int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
690 enum IEC61937_PC pc)
691{
692 struct regmap *r = sub->aio->chip->regmap;
693 u32 repet = 0, pause = OPORTMXPAUDAT_PAUSEPC_CMN;
694
695 switch (pc) {
696 case IEC61937_PC_AC3:
697 repet = OPORTMXREPET_STRLENGTH_AC3 |
698 OPORTMXREPET_PMLENGTH_AC3;
699 pause |= OPORTMXPAUDAT_PAUSEPD_AC3;
700 break;
701 case IEC61937_PC_MPA:
702 repet = OPORTMXREPET_STRLENGTH_MPA |
703 OPORTMXREPET_PMLENGTH_MPA;
704 pause |= OPORTMXPAUDAT_PAUSEPD_MPA;
705 break;
706 case IEC61937_PC_MP3:
707 repet = OPORTMXREPET_STRLENGTH_MP3 |
708 OPORTMXREPET_PMLENGTH_MP3;
709 pause |= OPORTMXPAUDAT_PAUSEPD_MP3;
710 break;
711 case IEC61937_PC_DTS1:
712 repet = OPORTMXREPET_STRLENGTH_DTS1 |
713 OPORTMXREPET_PMLENGTH_DTS1;
714 pause |= OPORTMXPAUDAT_PAUSEPD_DTS1;
715 break;
716 case IEC61937_PC_DTS2:
717 repet = OPORTMXREPET_STRLENGTH_DTS2 |
718 OPORTMXREPET_PMLENGTH_DTS2;
719 pause |= OPORTMXPAUDAT_PAUSEPD_DTS2;
720 break;
721 case IEC61937_PC_DTS3:
722 repet = OPORTMXREPET_STRLENGTH_DTS3 |
723 OPORTMXREPET_PMLENGTH_DTS3;
724 pause |= OPORTMXPAUDAT_PAUSEPD_DTS3;
725 break;
726 case IEC61937_PC_AAC:
727 repet = OPORTMXREPET_STRLENGTH_AAC |
728 OPORTMXREPET_PMLENGTH_AAC;
729 pause |= OPORTMXPAUDAT_PAUSEPD_AAC;
730 break;
731 case IEC61937_PC_PAUSE:
732 /* Do nothing */
733 break;
734 }
735
736 regmap_write(r, OPORTMXREPET(sub->swm->oport.map), repet);
737 regmap_write(r, OPORTMXPAUDAT(sub->swm->oport.map), pause);
738
739 return 0;
740}
741
742/**
743 * aio_src_reset - reset AIO SRC block
744 * @sub: the AIO substream pointer
745 *
746 * Resets the digital signal input/output port with sampling rate converter
747 * block of AIO.
748 * This function has no effect if substream is not supported rate converter.
749 */
750void aio_src_reset(struct uniphier_aio_sub *sub)
751{
752 struct regmap *r = sub->aio->chip->regmap;
753
754 if (sub->swm->dir != PORT_DIR_OUTPUT)
755 return;
756
757 regmap_write(r, AOUTSRCRSTCTR0, BIT(sub->swm->oport.map));
758 regmap_write(r, AOUTSRCRSTCTR1, BIT(sub->swm->oport.map));
759}
760
761/**
762 * aio_src_set_param - set parameters of AIO SRC block
763 * @sub: the AIO substream pointer
764 * @params: hardware parameters of ALSA
765 *
766 * Set suitable setting to input/output port with sampling rate converter
767 * block of AIO to process the specified in params.
768 * This function has no effect if substream is not supported rate converter.
769 *
770 * Return: Zero if successful, otherwise a negative value on error.
771 */
772int aio_src_set_param(struct uniphier_aio_sub *sub,
773 const struct snd_pcm_hw_params *params)
774{
775 struct regmap *r = sub->aio->chip->regmap;
776 u32 v;
777
778 if (sub->swm->dir != PORT_DIR_OUTPUT)
779 return 0;
780
781 regmap_write(r, OPORTMXSRC1CTR(sub->swm->oport.map),
782 OPORTMXSRC1CTR_THMODE_SRC |
783 OPORTMXSRC1CTR_SRCPATH_CALC |
784 OPORTMXSRC1CTR_SYNC_ASYNC |
785 OPORTMXSRC1CTR_FSIIPSEL_INNER |
786 OPORTMXSRC1CTR_FSISEL_ACLK);
787
788 switch (params_rate(params)) {
789 default:
790 case 48000:
791 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
792 OPORTMXRATE_I_MCKSEL_36 |
793 OPORTMXRATE_I_FSSEL_48;
794 break;
795 case 44100:
796 v = OPORTMXRATE_I_ACLKSEL_APLLA2 |
797 OPORTMXRATE_I_MCKSEL_33 |
798 OPORTMXRATE_I_FSSEL_44_1;
799 break;
800 case 32000:
801 v = OPORTMXRATE_I_ACLKSEL_APLLA1 |
802 OPORTMXRATE_I_MCKSEL_36 |
803 OPORTMXRATE_I_FSSEL_32;
804 break;
805 }
806
807 regmap_write(r, OPORTMXRATE_I(sub->swm->oport.map),
808 v | OPORTMXRATE_I_ACLKSRC_APLL |
809 OPORTMXRATE_I_LRCKSTP_STOP);
810 regmap_update_bits(r, OPORTMXRATE_I(sub->swm->oport.map),
811 OPORTMXRATE_I_LRCKSTP_MASK,
812 OPORTMXRATE_I_LRCKSTP_START);
813
814 return 0;
815}
816
817int aio_srcif_set_param(struct uniphier_aio_sub *sub)
818{
819 struct regmap *r = sub->aio->chip->regmap;
820
821 regmap_write(r, PBINMXCTR(sub->swm->iif.map),
822 PBINMXCTR_NCONNECT_CONNECT |
823 PBINMXCTR_INOUTSEL_OUT |
824 (sub->swm->oport.map << PBINMXCTR_PBINSEL_SHIFT) |
825 PBINMXCTR_ENDIAN_3210 |
826 PBINMXCTR_MEMFMT_D0);
827
828 return 0;
829}
830
831int aio_srcch_set_param(struct uniphier_aio_sub *sub)
832{
833 struct regmap *r = sub->aio->chip->regmap;
834
835 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->och.map),
836 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
837
838 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->och.map),
839 CDA2D_CHMXAMODE_ENDIAN_3210 |
840 CDA2D_CHMXAMODE_AUPDT_FIX |
841 CDA2D_CHMXAMODE_TYPE_NORMAL);
842
843 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->och.map),
844 CDA2D_CHMXAMODE_ENDIAN_3210 |
845 CDA2D_CHMXAMODE_AUPDT_INC |
846 CDA2D_CHMXAMODE_TYPE_RING |
847 (sub->swm->och.map << CDA2D_CHMXAMODE_RSSEL_SHIFT));
848
849 return 0;
850}
851
852void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable)
853{
854 struct regmap *r = sub->aio->chip->regmap;
855 u32 v;
856
857 if (enable)
858 v = CDA2D_STRT0_STOP_START;
859 else
860 v = CDA2D_STRT0_STOP_STOP;
861
862 regmap_write(r, CDA2D_STRT0,
863 v | BIT(sub->swm->och.map));
864}
865
866int aiodma_ch_set_param(struct uniphier_aio_sub *sub)
867{
868 struct regmap *r = sub->aio->chip->regmap;
869 u32 v;
870
871 regmap_write(r, CDA2D_CHMXCTRL1(sub->swm->ch.map),
872 CDA2D_CHMXCTRL1_INDSIZE_INFINITE);
873
874 v = CDA2D_CHMXAMODE_ENDIAN_3210 |
875 CDA2D_CHMXAMODE_AUPDT_INC |
876 CDA2D_CHMXAMODE_TYPE_NORMAL |
877 (sub->swm->rb.map << CDA2D_CHMXAMODE_RSSEL_SHIFT);
878 if (sub->swm->dir == PORT_DIR_OUTPUT)
879 regmap_write(r, CDA2D_CHMXSRCAMODE(sub->swm->ch.map), v);
880 else
881 regmap_write(r, CDA2D_CHMXDSTAMODE(sub->swm->ch.map), v);
882
883 return 0;
884}
885
886void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable)
887{
888 struct regmap *r = sub->aio->chip->regmap;
889
890 if (enable) {
891 regmap_write(r, CDA2D_STRT0,
892 CDA2D_STRT0_STOP_START | BIT(sub->swm->ch.map));
893
894 regmap_update_bits(r, INTRBIM(0),
895 BIT(sub->swm->rb.map),
896 BIT(sub->swm->rb.map));
897 } else {
898 regmap_write(r, CDA2D_STRT0,
899 CDA2D_STRT0_STOP_STOP | BIT(sub->swm->ch.map));
900
901 regmap_update_bits(r, INTRBIM(0),
902 BIT(sub->swm->rb.map),
903 0);
904 }
905}
906
907u64 aiodma_rb_get_rp(struct uniphier_aio_sub *sub)
908{
909 struct regmap *r = sub->aio->chip->regmap;
910 u32 pos_u, pos_l;
911 int i;
912
913 regmap_write(r, CDA2D_RDPTRLOAD,
914 CDA2D_RDPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
915 /* Wait for setup */
916 for (i = 0; i < 6; i++)
917 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
918
919 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &pos_l);
920 regmap_read(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), &pos_u);
921 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
922
923 return ((u64)pos_u << 32) | pos_l;
924}
925
926static void aiodma_rb_set_rp(struct uniphier_aio_sub *sub, u64 pos)
927{
928 struct regmap *r = sub->aio->chip->regmap;
929 u32 tmp;
930 int i;
931
932 regmap_write(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), (u32)pos);
933 regmap_write(r, CDA2D_RBMXRDPTRU(sub->swm->rb.map), (u32)(pos >> 32));
934 regmap_write(r, CDA2D_RDPTRLOAD, BIT(sub->swm->rb.map));
935 /* Wait for setup */
936 for (i = 0; i < 6; i++)
937 regmap_read(r, CDA2D_RBMXRDPTR(sub->swm->rb.map), &tmp);
938}
939
940static u64 aiodma_rb_get_wp(struct uniphier_aio_sub *sub)
941{
942 struct regmap *r = sub->aio->chip->regmap;
943 u32 pos_u, pos_l;
944 int i;
945
946 regmap_write(r, CDA2D_WRPTRLOAD,
947 CDA2D_WRPTRLOAD_LSFLAG_STORE | BIT(sub->swm->rb.map));
948 /* Wait for setup */
949 for (i = 0; i < 6; i++)
950 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
951
952 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &pos_l);
953 regmap_read(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map), &pos_u);
954 pos_u = FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK, pos_u);
955
956 return ((u64)pos_u << 32) | pos_l;
957}
958
959static void aiodma_rb_set_wp(struct uniphier_aio_sub *sub, u64 pos)
960{
961 struct regmap *r = sub->aio->chip->regmap;
962 u32 tmp;
963 int i;
964
965 regmap_write(r, CDA2D_RBMXWRPTR(sub->swm->rb.map),
966 lower_32_bits(pos));
967 regmap_write(r, CDA2D_RBMXWRPTRU(sub->swm->rb.map),
968 upper_32_bits(pos));
969 regmap_write(r, CDA2D_WRPTRLOAD, BIT(sub->swm->rb.map));
970 /* Wait for setup */
971 for (i = 0; i < 6; i++)
972 regmap_read(r, CDA2D_RBMXWRPTR(sub->swm->rb.map), &tmp);
973}
974
975int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th)
976{
977 struct regmap *r = sub->aio->chip->regmap;
978
979 if (size <= th)
980 return -EINVAL;
981
982 regmap_write(r, CDA2D_RBMXBTH(sub->swm->rb.map), th);
983 regmap_write(r, CDA2D_RBMXRTH(sub->swm->rb.map), th);
984
985 return 0;
986}
987
988int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
989 int period)
990{
991 struct regmap *r = sub->aio->chip->regmap;
992 u64 size = end - start;
993 int ret;
994
995 if (end < start || period < 0)
996 return -EINVAL;
997
998 regmap_write(r, CDA2D_RBMXCNFG(sub->swm->rb.map), 0);
999 regmap_write(r, CDA2D_RBMXBGNADRS(sub->swm->rb.map),
1000 lower_32_bits(start));
1001 regmap_write(r, CDA2D_RBMXBGNADRSU(sub->swm->rb.map),
1002 upper_32_bits(start));
1003 regmap_write(r, CDA2D_RBMXENDADRS(sub->swm->rb.map),
1004 lower_32_bits(end));
1005 regmap_write(r, CDA2D_RBMXENDADRSU(sub->swm->rb.map),
1006 upper_32_bits(end));
1007
1008 regmap_write(r, CDA2D_RBADRSLOAD, BIT(sub->swm->rb.map));
1009
1010 ret = aiodma_rb_set_threshold(sub, size, 2 * period);
1011 if (ret)
1012 return ret;
1013
1014 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1015 aiodma_rb_set_rp(sub, start);
1016 aiodma_rb_set_wp(sub, end - period);
1017
1018 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1019 CDA2D_RBMXIX_SPACE,
1020 CDA2D_RBMXIX_SPACE);
1021 } else {
1022 aiodma_rb_set_rp(sub, end - period);
1023 aiodma_rb_set_wp(sub, start);
1024
1025 regmap_update_bits(r, CDA2D_RBMXIE(sub->swm->rb.map),
1026 CDA2D_RBMXIX_REMAIN,
1027 CDA2D_RBMXIX_REMAIN);
1028 }
1029
1030 sub->threshold = 2 * period;
1031 sub->rd_offs = 0;
1032 sub->wr_offs = 0;
1033 sub->rd_org = 0;
1034 sub->wr_org = 0;
1035 sub->rd_total = 0;
1036 sub->wr_total = 0;
1037
1038 return 0;
1039}
1040
1041void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
1042 int period)
1043{
1044 if (sub->swm->dir == PORT_DIR_OUTPUT) {
1045 sub->rd_offs = aiodma_rb_get_rp(sub) - start;
1046
1047 if (sub->use_mmap) {
1048 sub->threshold = 2 * period;
1049 aiodma_rb_set_threshold(sub, size, 2 * period);
1050
1051 sub->wr_offs = sub->rd_offs - period;
1052 if (sub->rd_offs < period)
1053 sub->wr_offs += size;
1054 }
1055 aiodma_rb_set_wp(sub, sub->wr_offs + start);
1056 } else {
1057 sub->wr_offs = aiodma_rb_get_wp(sub) - start;
1058
1059 if (sub->use_mmap) {
1060 sub->threshold = 2 * period;
1061 aiodma_rb_set_threshold(sub, size, 2 * period);
1062
1063 sub->rd_offs = sub->wr_offs - period;
1064 if (sub->wr_offs < period)
1065 sub->rd_offs += size;
1066 }
1067 aiodma_rb_set_rp(sub, sub->rd_offs + start);
1068 }
1069
1070 sub->rd_total += sub->rd_offs - sub->rd_org;
1071 if (sub->rd_offs < sub->rd_org)
1072 sub->rd_total += size;
1073 sub->wr_total += sub->wr_offs - sub->wr_org;
1074 if (sub->wr_offs < sub->wr_org)
1075 sub->wr_total += size;
1076
1077 sub->rd_org = sub->rd_offs;
1078 sub->wr_org = sub->wr_offs;
1079}
1080
1081bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub)
1082{
1083 struct regmap *r = sub->aio->chip->regmap;
1084 u32 ir;
1085
1086 regmap_read(r, CDA2D_RBMXIR(sub->swm->rb.map), &ir);
1087
1088 if (sub->swm->dir == PORT_DIR_OUTPUT)
1089 return !!(ir & CDA2D_RBMXIX_SPACE);
1090 else
1091 return !!(ir & CDA2D_RBMXIX_REMAIN);
1092}
1093
1094void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub)
1095{
1096 struct regmap *r = sub->aio->chip->regmap;
1097
1098 if (sub->swm->dir == PORT_DIR_OUTPUT)
1099 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1100 CDA2D_RBMXIX_SPACE);
1101 else
1102 regmap_write(r, CDA2D_RBMXIR(sub->swm->rb.map),
1103 CDA2D_RBMXIX_REMAIN);
1104}
diff --git a/sound/soc/uniphier/aio-reg.h b/sound/soc/uniphier/aio-reg.h
new file mode 100644
index 000000000000..eaf2c65acf14
--- /dev/null
+++ b/sound/soc/uniphier/aio-reg.h
@@ -0,0 +1,462 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Socionext UniPhier AIO ALSA 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
21#ifndef SND_UNIPHIER_AIO_REG_H__
22#define SND_UNIPHIER_AIO_REG_H__
23
24#include <linux/bitops.h>
25
26/* SW view */
27#define A2CHNMAPCTR0(n) (0x00000 + 0x40 * (n))
28#define A2RBNMAPCTR0(n) (0x01000 + 0x40 * (n))
29#define A2IPORTNMAPCTR0(n) (0x02000 + 0x40 * (n))
30#define A2IPORTNMAPCTR1(n) (0x02004 + 0x40 * (n))
31#define A2IIFNMAPCTR0(n) (0x03000 + 0x40 * (n))
32#define A2OPORTNMAPCTR0(n) (0x04000 + 0x40 * (n))
33#define A2OPORTNMAPCTR1(n) (0x04004 + 0x40 * (n))
34#define A2OPORTNMAPCTR2(n) (0x04008 + 0x40 * (n))
35#define A2OIFNMAPCTR0(n) (0x05000 + 0x40 * (n))
36#define A2ATNMAPCTR0(n) (0x06000 + 0x40 * (n))
37
38#define MAPCTR0_EN 0x80000000
39
40/* CTL */
41#define A2APLLCTR0 0x07000
42#define A2APLLCTR0_APLLXPOW_MASK GENMASK(3, 0)
43#define A2APLLCTR0_APLLXPOW_PWOFF (0x0 << 0)
44#define A2APLLCTR0_APLLXPOW_PWON (0xf << 0)
45#define A2APLLCTR1 0x07004
46#define A2APLLCTR1_APLLX_MASK 0x00010101
47#define A2APLLCTR1_APLLX_36MHZ 0x00000000
48#define A2APLLCTR1_APLLX_33MHZ 0x00000001
49#define A2EXMCLKSEL0 0x07030
50#define A2EXMCLKSEL0_EXMCLK_MASK GENMASK(2, 0)
51#define A2EXMCLKSEL0_EXMCLK_OUTPUT (0x0 << 0)
52#define A2EXMCLKSEL0_EXMCLK_INPUT (0x7 << 0)
53#define A2SSIFSW 0x07050
54#define A2CH22_2CTR 0x07054
55#define A2AIOINPUTSEL 0x070e0
56#define A2AIOINPUTSEL_RXSEL_PCMI1_MASK GENMASK(2, 0)
57#define A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1 (0x2 << 0)
58#define A2AIOINPUTSEL_RXSEL_PCMI2_MASK GENMASK(6, 4)
59#define A2AIOINPUTSEL_RXSEL_PCMI2_SIF (0x7 << 4)
60#define A2AIOINPUTSEL_RXSEL_PCMI3_MASK GENMASK(10, 8)
61#define A2AIOINPUTSEL_RXSEL_PCMI3_EVEA (0x1 << 8)
62#define A2AIOINPUTSEL_RXSEL_IECI1_MASK GENMASK(14, 12)
63#define A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1 (0x2 << 12)
64#define A2AIOINPUTSEL_RXSEL_MASK (A2AIOINPUTSEL_RXSEL_PCMI1_MASK | \
65 A2AIOINPUTSEL_RXSEL_PCMI2_MASK | \
66 A2AIOINPUTSEL_RXSEL_PCMI3_MASK | \
67 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1)
68
69/* INTC */
70#define INTCHIM(m) (0x9028 + 0x80 * (m))
71#define INTRBIM(m) (0x9030 + 0x80 * (m))
72#define INTCHID(m) (0xa028 + 0x80 * (m))
73#define INTRBID(m) (0xa030 + 0x80 * (m))
74
75/* AIN(PCMINN) */
76#define IPORTMXCTR1(n) (0x22000 + 0x400 * (n))
77#define IPORTMXCTR1_LRSEL_MASK GENMASK(11, 10)
78#define IPORTMXCTR1_LRSEL_RIGHT (0x0 << 10)
79#define IPORTMXCTR1_LRSEL_LEFT (0x1 << 10)
80#define IPORTMXCTR1_LRSEL_I2S (0x2 << 10)
81#define IPORTMXCTR1_OUTBITSEL_MASK (0x800003U << 8)
82#define IPORTMXCTR1_OUTBITSEL_32 (0x800000U << 8)
83#define IPORTMXCTR1_OUTBITSEL_24 (0x000000U << 8)
84#define IPORTMXCTR1_OUTBITSEL_20 (0x000001U << 8)
85#define IPORTMXCTR1_OUTBITSEL_16 (0x000002U << 8)
86#define IPORTMXCTR1_CHSEL_MASK GENMASK(6, 4)
87#define IPORTMXCTR1_CHSEL_ALL (0x0 << 4)
88#define IPORTMXCTR1_CHSEL_D0_D2 (0x1 << 4)
89#define IPORTMXCTR1_CHSEL_D0 (0x2 << 4)
90#define IPORTMXCTR1_CHSEL_D1 (0x3 << 4)
91#define IPORTMXCTR1_CHSEL_D2 (0x4 << 4)
92#define IPORTMXCTR1_CHSEL_DMIX (0x5 << 4)
93#define IPORTMXCTR1_FSSEL_MASK GENMASK(3, 0)
94#define IPORTMXCTR1_FSSEL_48 (0x0 << 0)
95#define IPORTMXCTR1_FSSEL_96 (0x1 << 0)
96#define IPORTMXCTR1_FSSEL_192 (0x2 << 0)
97#define IPORTMXCTR1_FSSEL_32 (0x3 << 0)
98#define IPORTMXCTR1_FSSEL_44_1 (0x4 << 0)
99#define IPORTMXCTR1_FSSEL_88_2 (0x5 << 0)
100#define IPORTMXCTR1_FSSEL_176_4 (0x6 << 0)
101#define IPORTMXCTR1_FSSEL_16 (0x8 << 0)
102#define IPORTMXCTR1_FSSEL_22_05 (0x9 << 0)
103#define IPORTMXCTR1_FSSEL_24 (0xa << 0)
104#define IPORTMXCTR1_FSSEL_8 (0xb << 0)
105#define IPORTMXCTR1_FSSEL_11_025 (0xc << 0)
106#define IPORTMXCTR1_FSSEL_12 (0xd << 0)
107#define IPORTMXCTR2(n) (0x22004 + 0x400 * (n))
108#define IPORTMXCTR2_ACLKSEL_MASK GENMASK(19, 16)
109#define IPORTMXCTR2_ACLKSEL_A1 (0x0 << 16)
110#define IPORTMXCTR2_ACLKSEL_F1 (0x1 << 16)
111#define IPORTMXCTR2_ACLKSEL_A2 (0x2 << 16)
112#define IPORTMXCTR2_ACLKSEL_F2 (0x3 << 16)
113#define IPORTMXCTR2_ACLKSEL_A2PLL (0x4 << 16)
114#define IPORTMXCTR2_ACLKSEL_RX1 (0x5 << 16)
115#define IPORTMXCTR2_ACLKSEL_RX2 (0x6 << 16)
116#define IPORTMXCTR2_MSSEL_MASK BIT(15)
117#define IPORTMXCTR2_MSSEL_SLAVE (0x0 << 15)
118#define IPORTMXCTR2_MSSEL_MASTER (0x1 << 15)
119#define IPORTMXCTR2_EXTLSIFSSEL_MASK BIT(14)
120#define IPORTMXCTR2_EXTLSIFSSEL_36 (0x0 << 14)
121#define IPORTMXCTR2_EXTLSIFSSEL_24 (0x1 << 14)
122#define IPORTMXCTR2_DACCKSEL_MASK GENMASK(9, 8)
123#define IPORTMXCTR2_DACCKSEL_1_2 (0x0 << 8)
124#define IPORTMXCTR2_DACCKSEL_1_3 (0x1 << 8)
125#define IPORTMXCTR2_DACCKSEL_1_1 (0x2 << 8)
126#define IPORTMXCTR2_DACCKSEL_2_3 (0x3 << 8)
127#define IPORTMXCTR2_REQEN_MASK BIT(0)
128#define IPORTMXCTR2_REQEN_DISABLE (0x0 << 0)
129#define IPORTMXCTR2_REQEN_ENABLE (0x1 << 0)
130#define IPORTMXCNTCTR(n) (0x22010 + 0x400 * (n))
131#define IPORTMXCOUNTER(n) (0x22014 + 0x400 * (n))
132#define IPORTMXCNTMONI(n) (0x22018 + 0x400 * (n))
133#define IPORTMXACLKSEL0EX(n) (0x22020 + 0x400 * (n))
134#define IPORTMXACLKSEL0EX_ACLKSEL0EX_MASK GENMASK(3, 0)
135#define IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL (0x0 << 0)
136#define IPORTMXACLKSEL0EX_ACLKSEL0EX_EXTERNAL (0xf << 0)
137#define IPORTMXEXNOE(n) (0x22070 + 0x400 * (n))
138#define IPORTMXEXNOE_PCMINOE_MASK BIT(0)
139#define IPORTMXEXNOE_PCMINOE_OUTPUT (0x0 << 0)
140#define IPORTMXEXNOE_PCMINOE_INPUT (0x1 << 0)
141#define IPORTMXMASK(n) (0x22078 + 0x400 * (n))
142#define IPORTMXMASK_IUXCKMSK_MASK GENMASK(18, 16)
143#define IPORTMXMASK_IUXCKMSK_ON (0x0 << 16)
144#define IPORTMXMASK_IUXCKMSK_OFF (0x7 << 16)
145#define IPORTMXMASK_XCKMSK_MASK GENMASK(2, 0)
146#define IPORTMXMASK_XCKMSK_ON (0x0 << 0)
147#define IPORTMXMASK_XCKMSK_OFF (0x7 << 0)
148#define IPORTMXRSTCTR(n) (0x2207c + 0x400 * (n))
149#define IPORTMXRSTCTR_RSTPI_MASK BIT(7)
150#define IPORTMXRSTCTR_RSTPI_RELEASE (0x0 << 7)
151#define IPORTMXRSTCTR_RSTPI_RESET (0x1 << 7)
152
153/* AIN(PBinMX) */
154#define PBINMXCTR(n) (0x20200 + 0x40 * (n))
155#define PBINMXCTR_NCONNECT_MASK BIT(15)
156#define PBINMXCTR_NCONNECT_CONNECT (0x0 << 15)
157#define PBINMXCTR_NCONNECT_DISCONNECT (0x1 << 15)
158#define PBINMXCTR_INOUTSEL_MASK BIT(14)
159#define PBINMXCTR_INOUTSEL_IN (0x0 << 14)
160#define PBINMXCTR_INOUTSEL_OUT (0x1 << 14)
161#define PBINMXCTR_PBINSEL_SHIFT (8)
162#define PBINMXCTR_ENDIAN_MASK GENMASK(5, 4)
163#define PBINMXCTR_ENDIAN_3210 (0x0 << 4)
164#define PBINMXCTR_ENDIAN_0123 (0x1 << 4)
165#define PBINMXCTR_ENDIAN_1032 (0x2 << 4)
166#define PBINMXCTR_ENDIAN_2301 (0x3 << 4)
167#define PBINMXCTR_MEMFMT_MASK GENMASK(3, 0)
168#define PBINMXCTR_MEMFMT_D0 (0x0 << 0)
169#define PBINMXCTR_MEMFMT_5_1CH_DMIX (0x1 << 0)
170#define PBINMXCTR_MEMFMT_6CH (0x2 << 0)
171#define PBINMXCTR_MEMFMT_4CH (0x3 << 0)
172#define PBINMXCTR_MEMFMT_DMIX (0x4 << 0)
173#define PBINMXCTR_MEMFMT_1CH (0x5 << 0)
174#define PBINMXCTR_MEMFMT_16LR (0x6 << 0)
175#define PBINMXCTR_MEMFMT_7_1CH (0x7 << 0)
176#define PBINMXCTR_MEMFMT_7_1CH_DMIX (0x8 << 0)
177#define PBINMXCTR_MEMFMT_STREAM (0xf << 0)
178#define PBINMXPAUSECTR0(n) (0x20204 + 0x40 * (n))
179#define PBINMXPAUSECTR1(n) (0x20208 + 0x40 * (n))
180
181/* AOUT */
182#define AOUTENCTR0 0x40040
183#define AOUTENCTR1 0x40044
184#define AOUTENCTR2 0x40048
185#define AOUTRSTCTR0 0x40060
186#define AOUTRSTCTR1 0x40064
187#define AOUTRSTCTR2 0x40068
188#define AOUTSRCRSTCTR0 0x400c0
189#define AOUTSRCRSTCTR1 0x400c4
190#define AOUTSRCRSTCTR2 0x400c8
191
192/* AOUT(PCMOUTN) */
193#define OPORTMXCTR1(n) (0x42000 + 0x400 * (n))
194#define OPORTMXCTR1_I2SLRSEL_MASK (0x11 << 10)
195#define OPORTMXCTR1_I2SLRSEL_RIGHT (0x00 << 10)
196#define OPORTMXCTR1_I2SLRSEL_LEFT (0x01 << 10)
197#define OPORTMXCTR1_I2SLRSEL_I2S (0x11 << 10)
198#define OPORTMXCTR1_OUTBITSEL_MASK (0x800003U << 8)
199#define OPORTMXCTR1_OUTBITSEL_32 (0x800000U << 8)
200#define OPORTMXCTR1_OUTBITSEL_24 (0x000000U << 8)
201#define OPORTMXCTR1_OUTBITSEL_20 (0x000001U << 8)
202#define OPORTMXCTR1_OUTBITSEL_16 (0x000002U << 8)
203#define OPORTMXCTR1_FSSEL_MASK GENMASK(3, 0)
204#define OPORTMXCTR1_FSSEL_48 (0x0 << 0)
205#define OPORTMXCTR1_FSSEL_96 (0x1 << 0)
206#define OPORTMXCTR1_FSSEL_192 (0x2 << 0)
207#define OPORTMXCTR1_FSSEL_32 (0x3 << 0)
208#define OPORTMXCTR1_FSSEL_44_1 (0x4 << 0)
209#define OPORTMXCTR1_FSSEL_88_2 (0x5 << 0)
210#define OPORTMXCTR1_FSSEL_176_4 (0x6 << 0)
211#define OPORTMXCTR1_FSSEL_16 (0x8 << 0)
212#define OPORTMXCTR1_FSSEL_22_05 (0x9 << 0)
213#define OPORTMXCTR1_FSSEL_24 (0xa << 0)
214#define OPORTMXCTR1_FSSEL_8 (0xb << 0)
215#define OPORTMXCTR1_FSSEL_11_025 (0xc << 0)
216#define OPORTMXCTR1_FSSEL_12 (0xd << 0)
217#define OPORTMXCTR2(n) (0x42004 + 0x400 * (n))
218#define OPORTMXCTR2_ACLKSEL_MASK GENMASK(19, 16)
219#define OPORTMXCTR2_ACLKSEL_A1 (0x0 << 16)
220#define OPORTMXCTR2_ACLKSEL_F1 (0x1 << 16)
221#define OPORTMXCTR2_ACLKSEL_A2 (0x2 << 16)
222#define OPORTMXCTR2_ACLKSEL_F2 (0x3 << 16)
223#define OPORTMXCTR2_ACLKSEL_A2PLL (0x4 << 16)
224#define OPORTMXCTR2_ACLKSEL_RX1 (0x5 << 16)
225#define OPORTMXCTR2_ACLKSEL_RX2 (0x6 << 16)
226#define OPORTMXCTR2_MSSEL_MASK BIT(15)
227#define OPORTMXCTR2_MSSEL_SLAVE (0x0 << 15)
228#define OPORTMXCTR2_MSSEL_MASTER (0x1 << 15)
229#define OPORTMXCTR2_EXTLSIFSSEL_MASK BIT(14)
230#define OPORTMXCTR2_EXTLSIFSSEL_36 (0x0 << 14)
231#define OPORTMXCTR2_EXTLSIFSSEL_24 (0x1 << 14)
232#define OPORTMXCTR2_DACCKSEL_MASK GENMASK(9, 8)
233#define OPORTMXCTR2_DACCKSEL_1_2 (0x0 << 8)
234#define OPORTMXCTR2_DACCKSEL_1_3 (0x1 << 8)
235#define OPORTMXCTR2_DACCKSEL_1_1 (0x2 << 8)
236#define OPORTMXCTR2_DACCKSEL_2_3 (0x3 << 8)
237#define OPORTMXCTR3(n) (0x42008 + 0x400 * (n))
238#define OPORTMXCTR3_IECTHUR_MASK BIT(19)
239#define OPORTMXCTR3_IECTHUR_IECOUT (0x0 << 19)
240#define OPORTMXCTR3_IECTHUR_IECIN (0x1 << 19)
241#define OPORTMXCTR3_SRCSEL_MASK GENMASK(18, 16)
242#define OPORTMXCTR3_SRCSEL_PCM (0x0 << 16)
243#define OPORTMXCTR3_SRCSEL_STREAM (0x1 << 16)
244#define OPORTMXCTR3_SRCSEL_CDDTS (0x2 << 16)
245#define OPORTMXCTR3_VALID_MASK BIT(12)
246#define OPORTMXCTR3_VALID_PCM (0x0 << 12)
247#define OPORTMXCTR3_VALID_STREAM (0x1 << 12)
248#define OPORTMXCTR3_PMSEL_MASK BIT(3)
249#define OPORTMXCTR3_PMSEL_MUTE (0x0 << 3)
250#define OPORTMXCTR3_PMSEL_PAUSE (0x1 << 3)
251#define OPORTMXCTR3_PMSW_MASK BIT(2)
252#define OPORTMXCTR3_PMSW_MUTE_OFF (0x0 << 2)
253#define OPORTMXCTR3_PMSW_MUTE_ON (0x1 << 2)
254#define OPORTMXSRC1CTR(n) (0x4200c + 0x400 * (n))
255#define OPORTMXSRC1CTR_FSIIPNUM_SHIFT (24)
256#define OPORTMXSRC1CTR_THMODE_MASK BIT(23)
257#define OPORTMXSRC1CTR_THMODE_SRC (0x0 << 23)
258#define OPORTMXSRC1CTR_THMODE_BYPASS (0x1 << 23)
259#define OPORTMXSRC1CTR_LOCK_MASK BIT(16)
260#define OPORTMXSRC1CTR_LOCK_UNLOCK (0x0 << 16)
261#define OPORTMXSRC1CTR_LOCK_LOCK (0x1 << 16)
262#define OPORTMXSRC1CTR_SRCPATH_MASK BIT(15)
263#define OPORTMXSRC1CTR_SRCPATH_BYPASS (0x0 << 15)
264#define OPORTMXSRC1CTR_SRCPATH_CALC (0x1 << 15)
265#define OPORTMXSRC1CTR_SYNC_MASK BIT(14)
266#define OPORTMXSRC1CTR_SYNC_ASYNC (0x0 << 14)
267#define OPORTMXSRC1CTR_SYNC_SYNC (0x1 << 14)
268#define OPORTMXSRC1CTR_FSOCK_MASK GENMASK(11, 10)
269#define OPORTMXSRC1CTR_FSOCK_44_1 (0x0 << 10)
270#define OPORTMXSRC1CTR_FSOCK_48 (0x1 << 10)
271#define OPORTMXSRC1CTR_FSOCK_32 (0x2 << 10)
272#define OPORTMXSRC1CTR_FSICK_MASK GENMASK(9, 8)
273#define OPORTMXSRC1CTR_FSICK_44_1 (0x0 << 8)
274#define OPORTMXSRC1CTR_FSICK_48 (0x1 << 8)
275#define OPORTMXSRC1CTR_FSICK_32 (0x2 << 8)
276#define OPORTMXSRC1CTR_FSIIPSEL_MASK GENMASK(5, 4)
277#define OPORTMXSRC1CTR_FSIIPSEL_INNER (0x0 << 4)
278#define OPORTMXSRC1CTR_FSIIPSEL_OUTER (0x1 << 4)
279#define OPORTMXSRC1CTR_FSISEL_MASK GENMASK(3, 0)
280#define OPORTMXSRC1CTR_FSISEL_ACLK (0x0 << 0)
281#define OPORTMXSRC1CTR_FSISEL_DD (0x1 << 0)
282#define OPORTMXDSDMUTEDAT(n) (0x42020 + 0x400 * (n))
283#define OPORTMXDXDFREQMODE(n) (0x42024 + 0x400 * (n))
284#define OPORTMXDSDSEL(n) (0x42028 + 0x400 * (n))
285#define OPORTMXDSDPORT(n) (0x4202c + 0x400 * (n))
286#define OPORTMXACLKSEL0EX(n) (0x42030 + 0x400 * (n))
287#define OPORTMXPATH(n) (0x42040 + 0x400 * (n))
288#define OPORTMXSYNC(n) (0x42044 + 0x400 * (n))
289#define OPORTMXREPET(n) (0x42050 + 0x400 * (n))
290#define OPORTMXREPET_STRLENGTH_AC3 SBF_(IEC61937_FRM_STR_AC3, 16)
291#define OPORTMXREPET_STRLENGTH_MPA SBF_(IEC61937_FRM_STR_MPA, 16)
292#define OPORTMXREPET_STRLENGTH_MP3 SBF_(IEC61937_FRM_STR_MP3, 16)
293#define OPORTMXREPET_STRLENGTH_DTS1 SBF_(IEC61937_FRM_STR_DTS1, 16)
294#define OPORTMXREPET_STRLENGTH_DTS2 SBF_(IEC61937_FRM_STR_DTS2, 16)
295#define OPORTMXREPET_STRLENGTH_DTS3 SBF_(IEC61937_FRM_STR_DTS3, 16)
296#define OPORTMXREPET_STRLENGTH_AAC SBF_(IEC61937_FRM_STR_AAC, 16)
297#define OPORTMXREPET_PMLENGTH_AC3 SBF_(IEC61937_FRM_PAU_AC3, 0)
298#define OPORTMXREPET_PMLENGTH_MPA SBF_(IEC61937_FRM_PAU_MPA, 0)
299#define OPORTMXREPET_PMLENGTH_MP3 SBF_(IEC61937_FRM_PAU_MP3, 0)
300#define OPORTMXREPET_PMLENGTH_DTS1 SBF_(IEC61937_FRM_PAU_DTS1, 0)
301#define OPORTMXREPET_PMLENGTH_DTS2 SBF_(IEC61937_FRM_PAU_DTS2, 0)
302#define OPORTMXREPET_PMLENGTH_DTS3 SBF_(IEC61937_FRM_PAU_DTS3, 0)
303#define OPORTMXREPET_PMLENGTH_AAC SBF_(IEC61937_FRM_PAU_AAC, 0)
304#define OPORTMXPAUDAT(n) (0x42054 + 0x400 * (n))
305#define OPORTMXPAUDAT_PAUSEPC_CMN (IEC61937_PC_PAUSE << 16)
306#define OPORTMXPAUDAT_PAUSEPD_AC3 (IEC61937_FRM_PAU_AC3 * 4)
307#define OPORTMXPAUDAT_PAUSEPD_MPA (IEC61937_FRM_PAU_MPA * 4)
308#define OPORTMXPAUDAT_PAUSEPD_MP3 (IEC61937_FRM_PAU_MP3 * 4)
309#define OPORTMXPAUDAT_PAUSEPD_DTS1 (IEC61937_FRM_PAU_DTS1 * 4)
310#define OPORTMXPAUDAT_PAUSEPD_DTS2 (IEC61937_FRM_PAU_DTS2 * 4)
311#define OPORTMXPAUDAT_PAUSEPD_DTS3 (IEC61937_FRM_PAU_DTS3 * 4)
312#define OPORTMXPAUDAT_PAUSEPD_AAC (IEC61937_FRM_PAU_AAC * 4)
313#define OPORTMXRATE_I(n) (0x420e4 + 0x400 * (n))
314#define OPORTMXRATE_I_EQU_MASK BIT(31)
315#define OPORTMXRATE_I_EQU_NOTEQUAL (0x0 << 31)
316#define OPORTMXRATE_I_EQU_EQUAL (0x1 << 31)
317#define OPORTMXRATE_I_SRCBPMD_MASK BIT(29)
318#define OPORTMXRATE_I_SRCBPMD_BYPASS (0x0 << 29)
319#define OPORTMXRATE_I_SRCBPMD_SRC (0x1 << 29)
320#define OPORTMXRATE_I_LRCKSTP_MASK BIT(24)
321#define OPORTMXRATE_I_LRCKSTP_START (0x0 << 24)
322#define OPORTMXRATE_I_LRCKSTP_STOP (0x1 << 24)
323#define OPORTMXRATE_I_ACLKSRC_MASK GENMASK(15, 12)
324#define OPORTMXRATE_I_ACLKSRC_APLL (0x0 << 12)
325#define OPORTMXRATE_I_ACLKSRC_USB (0x1 << 12)
326#define OPORTMXRATE_I_ACLKSRC_HSC (0x3 << 12)
327/* if OPORTMXRATE_I_ACLKSRC_APLL */
328#define OPORTMXRATE_I_ACLKSEL_MASK GENMASK(11, 8)
329#define OPORTMXRATE_I_ACLKSEL_APLLA1 (0x0 << 8)
330#define OPORTMXRATE_I_ACLKSEL_APLLF1 (0x1 << 8)
331#define OPORTMXRATE_I_ACLKSEL_APLLA2 (0x2 << 8)
332#define OPORTMXRATE_I_ACLKSEL_APLLF2 (0x3 << 8)
333#define OPORTMXRATE_I_ACLKSEL_APLL (0x4 << 8)
334#define OPORTMXRATE_I_ACLKSEL_HDMI1 (0x5 << 8)
335#define OPORTMXRATE_I_ACLKSEL_HDMI2 (0x6 << 8)
336#define OPORTMXRATE_I_ACLKSEL_AI1ADCCK (0xc << 8)
337#define OPORTMXRATE_I_ACLKSEL_AI2ADCCK (0xd << 8)
338#define OPORTMXRATE_I_ACLKSEL_AI3ADCCK (0xe << 8)
339#define OPORTMXRATE_I_MCKSEL_MASK GENMASK(7, 4)
340#define OPORTMXRATE_I_MCKSEL_36 (0x0 << 4)
341#define OPORTMXRATE_I_MCKSEL_33 (0x1 << 4)
342#define OPORTMXRATE_I_MCKSEL_HSC27 (0xb << 4)
343#define OPORTMXRATE_I_FSSEL_MASK GENMASK(3, 0)
344#define OPORTMXRATE_I_FSSEL_48 (0x0 << 0)
345#define OPORTMXRATE_I_FSSEL_96 (0x1 << 0)
346#define OPORTMXRATE_I_FSSEL_192 (0x2 << 0)
347#define OPORTMXRATE_I_FSSEL_32 (0x3 << 0)
348#define OPORTMXRATE_I_FSSEL_44_1 (0x4 << 0)
349#define OPORTMXRATE_I_FSSEL_88_2 (0x5 << 0)
350#define OPORTMXRATE_I_FSSEL_176_4 (0x6 << 0)
351#define OPORTMXRATE_I_FSSEL_16 (0x8 << 0)
352#define OPORTMXRATE_I_FSSEL_22_05 (0x9 << 0)
353#define OPORTMXRATE_I_FSSEL_24 (0xa << 0)
354#define OPORTMXRATE_I_FSSEL_8 (0xb << 0)
355#define OPORTMXRATE_I_FSSEL_11_025 (0xc << 0)
356#define OPORTMXRATE_I_FSSEL_12 (0xd << 0)
357#define OPORTMXEXNOE(n) (0x420f0 + 0x400 * (n))
358#define OPORTMXMASK(n) (0x420f8 + 0x400 * (n))
359#define OPORTMXMASK_IUDXMSK_MASK GENMASK(28, 24)
360#define OPORTMXMASK_IUDXMSK_ON (0x00 << 24)
361#define OPORTMXMASK_IUDXMSK_OFF (0x1f << 24)
362#define OPORTMXMASK_IUXCKMSK_MASK GENMASK(18, 16)
363#define OPORTMXMASK_IUXCKMSK_ON (0x0 << 16)
364#define OPORTMXMASK_IUXCKMSK_OFF (0x7 << 16)
365#define OPORTMXMASK_DXMSK_MASK GENMASK(12, 8)
366#define OPORTMXMASK_DXMSK_ON (0x00 << 8)
367#define OPORTMXMASK_DXMSK_OFF (0x1f << 8)
368#define OPORTMXMASK_XCKMSK_MASK GENMASK(2, 0)
369#define OPORTMXMASK_XCKMSK_ON (0x0 << 0)
370#define OPORTMXMASK_XCKMSK_OFF (0x7 << 0)
371#define OPORTMXDEBUG(n) (0x420fc + 0x400 * (n))
372#define OPORTMXT0RSTCTR(n) (0x4211c + 0x400 * (n))
373#define OPORTMXT1RSTCTR(n) (0x4213c + 0x400 * (n))
374#define OPORTMXT2RSTCTR(n) (0x4215c + 0x400 * (n))
375#define OPORTMXT3RSTCTR(n) (0x4217c + 0x400 * (n))
376#define OPORTMXT4RSTCTR(n) (0x4219c + 0x400 * (n))
377
378#define SBF_(frame, shift) (((frame) * 2 - 1) << shift)
379
380/* AOUT(PBoutMX) */
381#define PBOUTMXCTR0(n) (0x40200 + 0x40 * (n))
382#define PBOUTMXCTR0_ENDIAN_MASK GENMASK(5, 4)
383#define PBOUTMXCTR0_ENDIAN_3210 (0x0 << 4)
384#define PBOUTMXCTR0_ENDIAN_0123 (0x1 << 4)
385#define PBOUTMXCTR0_ENDIAN_1032 (0x2 << 4)
386#define PBOUTMXCTR0_ENDIAN_2301 (0x3 << 4)
387#define PBOUTMXCTR0_MEMFMT_MASK GENMASK(3, 0)
388#define PBOUTMXCTR0_MEMFMT_10CH (0x0 << 0)
389#define PBOUTMXCTR0_MEMFMT_8CH (0x1 << 0)
390#define PBOUTMXCTR0_MEMFMT_6CH (0x2 << 0)
391#define PBOUTMXCTR0_MEMFMT_4CH (0x3 << 0)
392#define PBOUTMXCTR0_MEMFMT_2CH (0x4 << 0)
393#define PBOUTMXCTR0_MEMFMT_STREAM (0x5 << 0)
394#define PBOUTMXCTR0_MEMFMT_1CH (0x6 << 0)
395#define PBOUTMXCTR1(n) (0x40204 + 0x40 * (n))
396#define PBOUTMXINTCTR(n) (0x40208 + 0x40 * (n))
397
398/* A2D(subsystem) */
399#define CDA2D_STRT0 0x10000
400#define CDA2D_STRT0_STOP_MASK BIT(31)
401#define CDA2D_STRT0_STOP_START (0x0 << 31)
402#define CDA2D_STRT0_STOP_STOP (0x1 << 31)
403#define CDA2D_STAT0 0x10020
404#define CDA2D_TEST 0x100a0
405#define CDA2D_TEST_DDR_MODE_MASK GENMASK(3, 2)
406#define CDA2D_TEST_DDR_MODE_EXTON0 (0x0 << 2)
407#define CDA2D_TEST_DDR_MODE_EXTOFF1 (0x3 << 2)
408#define CDA2D_STRTADRSLOAD 0x100b0
409
410#define CDA2D_CHMXCTRL1(n) (0x12000 + 0x80 * (n))
411#define CDA2D_CHMXCTRL1_INDSIZE_MASK BIT(0)
412#define CDA2D_CHMXCTRL1_INDSIZE_FINITE (0x0 << 0)
413#define CDA2D_CHMXCTRL1_INDSIZE_INFINITE (0x1 << 0)
414#define CDA2D_CHMXCTRL2(n) (0x12004 + 0x80 * (n))
415#define CDA2D_CHMXSRCAMODE(n) (0x12020 + 0x80 * (n))
416#define CDA2D_CHMXDSTAMODE(n) (0x12024 + 0x80 * (n))
417#define CDA2D_CHMXAMODE_ENDIAN_MASK GENMASK(17, 16)
418#define CDA2D_CHMXAMODE_ENDIAN_3210 (0x0 << 16)
419#define CDA2D_CHMXAMODE_ENDIAN_0123 (0x1 << 16)
420#define CDA2D_CHMXAMODE_ENDIAN_1032 (0x2 << 16)
421#define CDA2D_CHMXAMODE_ENDIAN_2301 (0x3 << 16)
422#define CDA2D_CHMXAMODE_RSSEL_SHIFT (8)
423#define CDA2D_CHMXAMODE_AUPDT_MASK GENMASK(5, 4)
424#define CDA2D_CHMXAMODE_AUPDT_INC (0x0 << 4)
425#define CDA2D_CHMXAMODE_AUPDT_FIX (0x2 << 4)
426#define CDA2D_CHMXAMODE_TYPE_MASK GENMASK(3, 2)
427#define CDA2D_CHMXAMODE_TYPE_NORMAL (0x0 << 2)
428#define CDA2D_CHMXAMODE_TYPE_RING (0x1 << 2)
429#define CDA2D_CHMXSRCSTRTADRS(n) (0x12030 + 0x80 * (n))
430#define CDA2D_CHMXSRCSTRTADRSU(n) (0x12034 + 0x80 * (n))
431#define CDA2D_CHMXDSTSTRTADRS(n) (0x12038 + 0x80 * (n))
432#define CDA2D_CHMXDSTSTRTADRSU(n) (0x1203c + 0x80 * (n))
433
434/* A2D(ring buffer) */
435#define CDA2D_RBFLUSH0 0x10040
436#define CDA2D_RBADRSLOAD 0x100b4
437#define CDA2D_RDPTRLOAD 0x100b8
438#define CDA2D_RDPTRLOAD_LSFLAG_LOAD (0x0 << 31)
439#define CDA2D_RDPTRLOAD_LSFLAG_STORE (0x1 << 31)
440#define CDA2D_WRPTRLOAD 0x100bc
441#define CDA2D_WRPTRLOAD_LSFLAG_LOAD (0x0 << 31)
442#define CDA2D_WRPTRLOAD_LSFLAG_STORE (0x1 << 31)
443
444#define CDA2D_RBMXBGNADRS(n) (0x14000 + 0x80 * (n))
445#define CDA2D_RBMXBGNADRSU(n) (0x14004 + 0x80 * (n))
446#define CDA2D_RBMXENDADRS(n) (0x14008 + 0x80 * (n))
447#define CDA2D_RBMXENDADRSU(n) (0x1400c + 0x80 * (n))
448#define CDA2D_RBMXBTH(n) (0x14038 + 0x80 * (n))
449#define CDA2D_RBMXRTH(n) (0x1403c + 0x80 * (n))
450#define CDA2D_RBMXRDPTR(n) (0x14020 + 0x80 * (n))
451#define CDA2D_RBMXRDPTRU(n) (0x14024 + 0x80 * (n))
452#define CDA2D_RBMXWRPTR(n) (0x14028 + 0x80 * (n))
453#define CDA2D_RBMXWRPTRU(n) (0x1402c + 0x80 * (n))
454#define CDA2D_RBMXPTRU_PTRU_MASK GENMASK(1, 0)
455#define CDA2D_RBMXCNFG(n) (0x14030 + 0x80 * (n))
456#define CDA2D_RBMXIR(n) (0x14014 + 0x80 * (n))
457#define CDA2D_RBMXIE(n) (0x14018 + 0x80 * (n))
458#define CDA2D_RBMXID(n) (0x1401c + 0x80 * (n))
459#define CDA2D_RBMXIX_SPACE BIT(3)
460#define CDA2D_RBMXIX_REMAIN BIT(4)
461
462#endif /* SND_UNIPHIER_AIO_REG_H__ */
diff --git a/sound/soc/uniphier/aio.h b/sound/soc/uniphier/aio.h
new file mode 100644
index 000000000000..774abae28028
--- /dev/null
+++ b/sound/soc/uniphier/aio.h
@@ -0,0 +1,343 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Socionext UniPhier AIO ALSA 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
21#ifndef SND_UNIPHIER_AIO_H__
22#define SND_UNIPHIER_AIO_H__
23
24#include <linux/spinlock.h>
25#include <linux/types.h>
26#include <sound/pcm.h>
27#include <sound/soc.h>
28#include <sound/soc-dai.h>
29
30struct platform_device;
31
32enum ID_PORT_TYPE {
33 PORT_TYPE_UNKNOWN,
34 PORT_TYPE_I2S,
35 PORT_TYPE_SPDIF,
36 PORT_TYPE_EVE,
37 PORT_TYPE_CONV,
38};
39
40enum ID_PORT_DIR {
41 PORT_DIR_OUTPUT,
42 PORT_DIR_INPUT,
43};
44
45enum IEC61937_PC {
46 IEC61937_PC_AC3 = 0x0001,
47 IEC61937_PC_PAUSE = 0x0003,
48 IEC61937_PC_MPA = 0x0004,
49 IEC61937_PC_MP3 = 0x0005,
50 IEC61937_PC_DTS1 = 0x000b,
51 IEC61937_PC_DTS2 = 0x000c,
52 IEC61937_PC_DTS3 = 0x000d,
53 IEC61937_PC_AAC = 0x0007,
54};
55
56/* IEC61937 Repetition period of data-burst in IEC60958 frames */
57#define IEC61937_FRM_STR_AC3 1536
58#define IEC61937_FRM_STR_MPA 1152
59#define IEC61937_FRM_STR_MP3 1152
60#define IEC61937_FRM_STR_DTS1 512
61#define IEC61937_FRM_STR_DTS2 1024
62#define IEC61937_FRM_STR_DTS3 2048
63#define IEC61937_FRM_STR_AAC 1024
64
65/* IEC61937 Repetition period of Pause data-burst in IEC60958 frames */
66#define IEC61937_FRM_PAU_AC3 3
67#define IEC61937_FRM_PAU_MPA 32
68#define IEC61937_FRM_PAU_MP3 32
69#define IEC61937_FRM_PAU_DTS1 3
70#define IEC61937_FRM_PAU_DTS2 3
71#define IEC61937_FRM_PAU_DTS3 3
72#define IEC61937_FRM_PAU_AAC 32
73
74/* IEC61937 Pa and Pb */
75#define IEC61937_HEADER_SIGN 0x1f4e72f8
76
77#define AUD_HW_PCMIN1 0
78#define AUD_HW_PCMIN2 1
79#define AUD_HW_PCMIN3 2
80#define AUD_HW_IECIN1 3
81#define AUD_HW_DIECIN1 4
82
83#define AUD_NAME_PCMIN1 "aio-pcmin1"
84#define AUD_NAME_PCMIN2 "aio-pcmin2"
85#define AUD_NAME_PCMIN3 "aio-pcmin3"
86#define AUD_NAME_IECIN1 "aio-iecin1"
87#define AUD_NAME_DIECIN1 "aio-diecin1"
88
89#define AUD_HW_HPCMOUT1 0
90#define AUD_HW_PCMOUT1 1
91#define AUD_HW_PCMOUT2 2
92#define AUD_HW_PCMOUT3 3
93#define AUD_HW_EPCMOUT1 4
94#define AUD_HW_EPCMOUT2 5
95#define AUD_HW_EPCMOUT3 6
96#define AUD_HW_EPCMOUT6 9
97#define AUD_HW_HIECOUT1 10
98#define AUD_HW_IECOUT1 11
99#define AUD_HW_CMASTER 31
100
101#define AUD_NAME_HPCMOUT1 "aio-hpcmout1"
102#define AUD_NAME_PCMOUT1 "aio-pcmout1"
103#define AUD_NAME_PCMOUT2 "aio-pcmout2"
104#define AUD_NAME_PCMOUT3 "aio-pcmout3"
105#define AUD_NAME_EPCMOUT1 "aio-epcmout1"
106#define AUD_NAME_EPCMOUT2 "aio-epcmout2"
107#define AUD_NAME_EPCMOUT3 "aio-epcmout3"
108#define AUD_NAME_EPCMOUT6 "aio-epcmout6"
109#define AUD_NAME_HIECOUT1 "aio-hiecout1"
110#define AUD_NAME_IECOUT1 "aio-iecout1"
111#define AUD_NAME_CMASTER "aio-cmaster"
112#define AUD_NAME_HIECCOMPOUT1 "aio-hieccompout1"
113
114#define AUD_GNAME_HDMI "aio-hdmi"
115#define AUD_GNAME_LINE "aio-line"
116#define AUD_GNAME_IEC "aio-iec"
117
118#define AUD_CLK_IO 0
119#define AUD_CLK_A1 1
120#define AUD_CLK_F1 2
121#define AUD_CLK_A2 3
122#define AUD_CLK_F2 4
123#define AUD_CLK_A 5
124#define AUD_CLK_F 6
125#define AUD_CLK_APLL 7
126#define AUD_CLK_RX0 8
127#define AUD_CLK_USB0 9
128#define AUD_CLK_HSC0 10
129
130#define AUD_PLL_A1 0
131#define AUD_PLL_F1 1
132#define AUD_PLL_A2 2
133#define AUD_PLL_F2 3
134#define AUD_PLL_APLL 4
135#define AUD_PLL_RX0 5
136#define AUD_PLL_USB0 6
137#define AUD_PLL_HSC0 7
138
139#define AUD_PLLDIV_1_2 0
140#define AUD_PLLDIV_1_3 1
141#define AUD_PLLDIV_1_1 2
142#define AUD_PLLDIV_2_3 3
143
144#define AUD_RING_SIZE (128 * 1024)
145
146#define AUD_MIN_FRAGMENT 4
147#define AUD_MAX_FRAGMENT 8
148#define AUD_MIN_FRAGMENT_SIZE (4 * 1024)
149#define AUD_MAX_FRAGMENT_SIZE (16 * 1024)
150
151/*
152 * This is a selector for virtual register map of AIO.
153 *
154 * map: Specify the index of virtual register map.
155 * hw : Specify the ID of real register map, selector uses this value.
156 * A meaning of this value depends specification of SoC.
157 */
158struct uniphier_aio_selector {
159 int map;
160 int hw;
161};
162
163/**
164 * 'SoftWare MAPping' setting of UniPhier AIO registers.
165 *
166 * We have to setup 'virtual' register maps to access 'real' registers of AIO.
167 * This feature is legacy and meaningless but AIO needs this to work.
168 *
169 * Each hardware blocks have own virtual register maps as following:
170 *
171 * Address Virtual Real
172 * ------- --------- ---------------
173 * 0x12000 DMAC map0 --> [selector] --> DMAC hardware 3
174 * 0x12080 DMAC map1 --> [selector] --> DMAC hardware 1
175 * ...
176 * 0x42000 Port map0 --> [selector] --> Port hardware 1
177 * 0x42400 Port map1 --> [selector] --> Port hardware 2
178 * ...
179 *
180 * ch : Input or output channel of DMAC
181 * rb : Ring buffer
182 * iport: PCM input port
183 * iif : Input interface
184 * oport: PCM output port
185 * oif : Output interface
186 * och : Output channel of DMAC for sampling rate converter
187 *
188 * These are examples for sound data paths:
189 *
190 * For caputure device:
191 * (outer of AIO) -> iport -> iif -> ch -> rb -> (CPU)
192 * For playback device:
193 * (CPU) -> rb -> ch -> oif -> oport -> (outer of AIO)
194 * For sampling rate converter device:
195 * (CPU) -> rb -> ch -> oif -> (HW SRC) -> iif -> och -> orb -> (CPU)
196 */
197struct uniphier_aio_swmap {
198 int type;
199 int dir;
200
201 struct uniphier_aio_selector ch;
202 struct uniphier_aio_selector rb;
203 struct uniphier_aio_selector iport;
204 struct uniphier_aio_selector iif;
205 struct uniphier_aio_selector oport;
206 struct uniphier_aio_selector oif;
207 struct uniphier_aio_selector och;
208};
209
210struct uniphier_aio_spec {
211 const char *name;
212 const char *gname;
213 struct uniphier_aio_swmap swm;
214};
215
216struct uniphier_aio_pll {
217 bool enable;
218 unsigned int freq;
219};
220
221struct uniphier_aio_chip_spec {
222 const struct uniphier_aio_spec *specs;
223 int num_specs;
224 const struct uniphier_aio_pll *plls;
225 int num_plls;
226 struct snd_soc_dai_driver *dais;
227 int num_dais;
228
229 /* DMA access mode, this is workaround for DMA hungup */
230 int addr_ext;
231};
232
233struct uniphier_aio_sub {
234 struct uniphier_aio *aio;
235
236 /* Guard sub->rd_offs and wr_offs from IRQ handler. */
237 spinlock_t lock;
238
239 const struct uniphier_aio_swmap *swm;
240 const struct uniphier_aio_spec *spec;
241
242 /* For PCM audio */
243 struct snd_pcm_substream *substream;
244 struct snd_pcm_hw_params params;
245
246 /* For compress audio */
247 struct snd_compr_stream *cstream;
248 struct snd_compr_params cparams;
249 unsigned char *compr_area;
250 dma_addr_t compr_addr;
251 size_t compr_bytes;
252 int pass_through;
253 enum IEC61937_PC iec_pc;
254 bool iec_header;
255
256 /* Both PCM and compress audio */
257 bool use_mmap;
258 int setting;
259 int running;
260 u64 rd_offs;
261 u64 wr_offs;
262 u32 threshold;
263 u64 rd_org;
264 u64 wr_org;
265 u64 rd_total;
266 u64 wr_total;
267};
268
269struct uniphier_aio {
270 struct uniphier_aio_chip *chip;
271
272 struct uniphier_aio_sub sub[2];
273
274 unsigned int fmt;
275 /* Set one of AUD_CLK_X */
276 int clk_in;
277 int clk_out;
278 /* Set one of AUD_PLL_X */
279 int pll_in;
280 int pll_out;
281 /* Set one of AUD_PLLDIV_X */
282 int plldiv;
283};
284
285struct uniphier_aio_chip {
286 struct platform_device *pdev;
287 const struct uniphier_aio_chip_spec *chip_spec;
288
289 struct uniphier_aio *aios;
290 int num_aios;
291 struct uniphier_aio_pll *plls;
292 int num_plls;
293
294 struct clk *clk;
295 struct reset_control *rst;
296 struct regmap *regmap;
297 int active;
298};
299
300static inline struct uniphier_aio *uniphier_priv(struct snd_soc_dai *dai)
301{
302 struct uniphier_aio_chip *chip = snd_soc_dai_get_drvdata(dai);
303
304 return &chip->aios[dai->id];
305}
306
307u64 aio_rb_cnt(struct uniphier_aio_sub *sub);
308u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub);
309u64 aio_rb_space(struct uniphier_aio_sub *sub);
310u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub);
311
312int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id,
313 unsigned int freq);
314void aio_chip_init(struct uniphier_aio_chip *chip);
315int aio_init(struct uniphier_aio_sub *sub);
316void aio_port_reset(struct uniphier_aio_sub *sub);
317int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate);
318int aio_port_set_fmt(struct uniphier_aio_sub *sub);
319int aio_port_set_clk(struct uniphier_aio_sub *sub);
320int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through,
321 const struct snd_pcm_hw_params *params);
322void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable);
323int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through);
324int aio_oport_set_stream_type(struct uniphier_aio_sub *sub,
325 enum IEC61937_PC pc);
326void aio_src_reset(struct uniphier_aio_sub *sub);
327int aio_src_set_param(struct uniphier_aio_sub *sub,
328 const struct snd_pcm_hw_params *params);
329int aio_srcif_set_param(struct uniphier_aio_sub *sub);
330int aio_srcch_set_param(struct uniphier_aio_sub *sub);
331void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable);
332
333int aiodma_ch_set_param(struct uniphier_aio_sub *sub);
334void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable);
335int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th);
336int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end,
337 int period);
338void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size,
339 int period);
340bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub);
341void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub);
342
343#endif /* SND_UNIPHIER_AIO_H__ */