diff options
author | Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> | 2018-01-19 04:25:29 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-02-12 07:49:51 -0500 |
commit | f37fe2f9987b0460f25a87b1380f8e97a5959121 (patch) | |
tree | 6a519d9edcfa199017659feac88c82e85503b9b5 | |
parent | 28fb53de064b24eed55540ddeccab517e4babca3 (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/Kconfig | 10 | ||||
-rw-r--r-- | sound/soc/uniphier/Makefile | 4 | ||||
-rw-r--r-- | sound/soc/uniphier/aio-core.c | 1104 | ||||
-rw-r--r-- | sound/soc/uniphier/aio-reg.h | 462 | ||||
-rw-r--r-- | sound/soc/uniphier/aio.h | 343 |
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 | ||
11 | config 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 | |||
11 | config SND_SOC_UNIPHIER_EVEA_CODEC | 21 | config 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 |
2 | snd-soc-uniphier-aio-cpu-objs := aio-core.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SOC_UNIPHIER_AIO) += snd-soc-uniphier-aio-cpu.o | ||
5 | |||
2 | snd-soc-uniphier-evea-objs := evea.o | 6 | snd-soc-uniphier-evea-objs := evea.o |
3 | obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o | 7 | obj-$(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 | |||
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_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 | */ | ||
97 | int 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 | */ | ||
157 | void 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 | */ | ||
192 | int 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 | */ | ||
242 | void 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 | */ | ||
271 | int 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 | */ | ||
390 | int 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 | */ | ||
455 | int 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 | */ | ||
549 | int 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 | */ | ||
599 | void 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 | */ | ||
652 | int 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 | */ | ||
689 | int 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 | */ | ||
750 | void 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 | */ | ||
772 | int 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 | |||
817 | int 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 | |||
831 | int 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 | |||
852 | void 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 | |||
866 | int 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 | |||
886 | void 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 | |||
907 | u64 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 | |||
926 | static 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 | |||
940 | static 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 | |||
959 | static 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 | |||
975 | int 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 | |||
988 | int 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 | |||
1041 | void 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 | |||
1081 | bool 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 | |||
1094 | void 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 | |||
30 | struct platform_device; | ||
31 | |||
32 | enum 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 | |||
40 | enum ID_PORT_DIR { | ||
41 | PORT_DIR_OUTPUT, | ||
42 | PORT_DIR_INPUT, | ||
43 | }; | ||
44 | |||
45 | enum 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 | */ | ||
158 | struct 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 | */ | ||
197 | struct 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 | |||
210 | struct uniphier_aio_spec { | ||
211 | const char *name; | ||
212 | const char *gname; | ||
213 | struct uniphier_aio_swmap swm; | ||
214 | }; | ||
215 | |||
216 | struct uniphier_aio_pll { | ||
217 | bool enable; | ||
218 | unsigned int freq; | ||
219 | }; | ||
220 | |||
221 | struct 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 | |||
233 | struct 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 | |||
269 | struct 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 | |||
285 | struct 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 | |||
300 | static 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 | |||
307 | u64 aio_rb_cnt(struct uniphier_aio_sub *sub); | ||
308 | u64 aio_rbt_cnt_to_end(struct uniphier_aio_sub *sub); | ||
309 | u64 aio_rb_space(struct uniphier_aio_sub *sub); | ||
310 | u64 aio_rb_space_to_end(struct uniphier_aio_sub *sub); | ||
311 | |||
312 | int aio_chip_set_pll(struct uniphier_aio_chip *chip, int pll_id, | ||
313 | unsigned int freq); | ||
314 | void aio_chip_init(struct uniphier_aio_chip *chip); | ||
315 | int aio_init(struct uniphier_aio_sub *sub); | ||
316 | void aio_port_reset(struct uniphier_aio_sub *sub); | ||
317 | int aio_port_set_rate(struct uniphier_aio_sub *sub, int rate); | ||
318 | int aio_port_set_fmt(struct uniphier_aio_sub *sub); | ||
319 | int aio_port_set_clk(struct uniphier_aio_sub *sub); | ||
320 | int aio_port_set_param(struct uniphier_aio_sub *sub, int pass_through, | ||
321 | const struct snd_pcm_hw_params *params); | ||
322 | void aio_port_set_enable(struct uniphier_aio_sub *sub, int enable); | ||
323 | int aio_if_set_param(struct uniphier_aio_sub *sub, int pass_through); | ||
324 | int aio_oport_set_stream_type(struct uniphier_aio_sub *sub, | ||
325 | enum IEC61937_PC pc); | ||
326 | void aio_src_reset(struct uniphier_aio_sub *sub); | ||
327 | int aio_src_set_param(struct uniphier_aio_sub *sub, | ||
328 | const struct snd_pcm_hw_params *params); | ||
329 | int aio_srcif_set_param(struct uniphier_aio_sub *sub); | ||
330 | int aio_srcch_set_param(struct uniphier_aio_sub *sub); | ||
331 | void aio_srcch_set_enable(struct uniphier_aio_sub *sub, int enable); | ||
332 | |||
333 | int aiodma_ch_set_param(struct uniphier_aio_sub *sub); | ||
334 | void aiodma_ch_set_enable(struct uniphier_aio_sub *sub, int enable); | ||
335 | int aiodma_rb_set_threshold(struct uniphier_aio_sub *sub, u64 size, u32 th); | ||
336 | int aiodma_rb_set_buffer(struct uniphier_aio_sub *sub, u64 start, u64 end, | ||
337 | int period); | ||
338 | void aiodma_rb_sync(struct uniphier_aio_sub *sub, u64 start, u64 size, | ||
339 | int period); | ||
340 | bool aiodma_rb_is_irq(struct uniphier_aio_sub *sub); | ||
341 | void aiodma_rb_clear_irq(struct uniphier_aio_sub *sub); | ||
342 | |||
343 | #endif /* SND_UNIPHIER_AIO_H__ */ | ||