1 // SPDX-License-Identifier: GPL-2.0
3 // Socionext UniPhier AIO ALSA common driver.
5 // Copyright (c) 2016-2018 Socionext Inc.
7 #include <linux/bitfield.h>
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <sound/core.h>
12 #include <sound/pcm.h>
13 #include <sound/pcm_params.h>
14 #include <sound/soc.h>
19 static u64
rb_cnt(u64 wr
, u64 rd
, u64 len
)
24 return len
- (rd
- wr
);
27 static u64
rb_cnt_to_end(u64 wr
, u64 rd
, u64 len
)
35 static u64
rb_space(u64 wr
, u64 rd
, u64 len
)
38 return len
- (wr
- rd
) - 8;
43 static u64
rb_space_to_end(u64 wr
, u64 rd
, u64 len
)
53 u64
aio_rb_cnt(struct uniphier_aio_sub
*sub
)
55 return rb_cnt(sub
->wr_offs
, sub
->rd_offs
, sub
->compr_bytes
);
58 u64
aio_rbt_cnt_to_end(struct uniphier_aio_sub
*sub
)
60 return rb_cnt_to_end(sub
->wr_offs
, sub
->rd_offs
, sub
->compr_bytes
);
63 u64
aio_rb_space(struct uniphier_aio_sub
*sub
)
65 return rb_space(sub
->wr_offs
, sub
->rd_offs
, sub
->compr_bytes
);
68 u64
aio_rb_space_to_end(struct uniphier_aio_sub
*sub
)
70 return rb_space_to_end(sub
->wr_offs
, sub
->rd_offs
, sub
->compr_bytes
);
74 * aio_iecout_set_enable - setup IEC output via SoC glue
75 * @chip: the AIO chip pointer
76 * @enable: false to stop the output, true to start
78 * Set enabled or disabled S/PDIF signal output to out of SoC via AOnIEC pins.
79 * This function need to call at driver startup.
81 * The regmap of SoC glue is specified by 'socionext,syscon' optional property
82 * of DT. This function has no effect if no property.
84 void aio_iecout_set_enable(struct uniphier_aio_chip
*chip
, bool enable
)
86 struct regmap
*r
= chip
->regmap_sg
;
91 regmap_write(r
, SG_AOUTEN
, (enable
) ? ~0 : 0);
95 * aio_chip_set_pll - set frequency to audio PLL
96 * @chip : the AIO chip pointer
98 * @freq : frequency in Hz, 0 is ignored
100 * Sets frequency of audio PLL. This function can be called anytime,
101 * but it takes time till PLL is locked.
103 * Return: Zero if successful, otherwise a negative value on error.
105 int aio_chip_set_pll(struct uniphier_aio_chip
*chip
, int pll_id
,
108 struct device
*dev
= &chip
->pdev
->dev
;
109 struct regmap
*r
= chip
->regmap
;
131 dev_err(dev
, "PLL(%d) not supported\n", pll_id
);
137 v
= A2APLLCTR1_APLLX_36MHZ
;
140 v
= A2APLLCTR1_APLLX_33MHZ
;
143 dev_err(dev
, "PLL frequency not supported(%d)\n", freq
);
146 chip
->plls
[pll_id
].freq
= freq
;
148 regmap_update_bits(r
, A2APLLCTR1
, A2APLLCTR1_APLLX_MASK
<< shift
,
155 * aio_chip_init - initialize AIO whole settings
156 * @chip: the AIO chip pointer
158 * Sets AIO fixed and whole device settings to AIO.
159 * This function need to call once at driver startup.
161 * The register area that is changed by this function is shared by all
162 * modules of AIO. But there is not race condition since this function
163 * has always set the same initialize values.
165 void aio_chip_init(struct uniphier_aio_chip
*chip
)
167 struct regmap
*r
= chip
->regmap
;
169 regmap_update_bits(r
, A2APLLCTR0
,
170 A2APLLCTR0_APLLXPOW_MASK
,
171 A2APLLCTR0_APLLXPOW_PWON
);
173 regmap_update_bits(r
, A2EXMCLKSEL0
,
174 A2EXMCLKSEL0_EXMCLK_MASK
,
175 A2EXMCLKSEL0_EXMCLK_OUTPUT
);
177 regmap_update_bits(r
, A2AIOINPUTSEL
, A2AIOINPUTSEL_RXSEL_MASK
,
178 A2AIOINPUTSEL_RXSEL_PCMI1_HDMIRX1
|
179 A2AIOINPUTSEL_RXSEL_PCMI2_SIF
|
180 A2AIOINPUTSEL_RXSEL_PCMI3_EVEA
|
181 A2AIOINPUTSEL_RXSEL_IECI1_HDMIRX1
);
183 if (chip
->chip_spec
->addr_ext
)
184 regmap_update_bits(r
, CDA2D_TEST
, CDA2D_TEST_DDR_MODE_MASK
,
185 CDA2D_TEST_DDR_MODE_EXTON0
);
187 regmap_update_bits(r
, CDA2D_TEST
, CDA2D_TEST_DDR_MODE_MASK
,
188 CDA2D_TEST_DDR_MODE_EXTOFF1
);
192 * aio_init - initialize AIO substream
193 * @sub: the AIO substream pointer
195 * Sets fixed settings of each AIO substreams.
196 * This function need to call once at substream startup.
198 * Return: Zero if successful, otherwise a negative value on error.
200 int aio_init(struct uniphier_aio_sub
*sub
)
202 struct device
*dev
= &sub
->aio
->chip
->pdev
->dev
;
203 struct regmap
*r
= sub
->aio
->chip
->regmap
;
205 regmap_write(r
, A2RBNMAPCTR0(sub
->swm
->rb
.hw
),
206 MAPCTR0_EN
| sub
->swm
->rb
.map
);
207 regmap_write(r
, A2CHNMAPCTR0(sub
->swm
->ch
.hw
),
208 MAPCTR0_EN
| sub
->swm
->ch
.map
);
210 switch (sub
->swm
->type
) {
212 case PORT_TYPE_SPDIF
:
214 if (sub
->swm
->dir
== PORT_DIR_INPUT
) {
215 regmap_write(r
, A2IIFNMAPCTR0(sub
->swm
->iif
.hw
),
216 MAPCTR0_EN
| sub
->swm
->iif
.map
);
217 regmap_write(r
, A2IPORTNMAPCTR0(sub
->swm
->iport
.hw
),
218 MAPCTR0_EN
| sub
->swm
->iport
.map
);
220 regmap_write(r
, A2OIFNMAPCTR0(sub
->swm
->oif
.hw
),
221 MAPCTR0_EN
| sub
->swm
->oif
.map
);
222 regmap_write(r
, A2OPORTNMAPCTR0(sub
->swm
->oport
.hw
),
223 MAPCTR0_EN
| sub
->swm
->oport
.map
);
227 regmap_write(r
, A2OIFNMAPCTR0(sub
->swm
->oif
.hw
),
228 MAPCTR0_EN
| sub
->swm
->oif
.map
);
229 regmap_write(r
, A2OPORTNMAPCTR0(sub
->swm
->oport
.hw
),
230 MAPCTR0_EN
| sub
->swm
->oport
.map
);
231 regmap_write(r
, A2CHNMAPCTR0(sub
->swm
->och
.hw
),
232 MAPCTR0_EN
| sub
->swm
->och
.map
);
233 regmap_write(r
, A2IIFNMAPCTR0(sub
->swm
->iif
.hw
),
234 MAPCTR0_EN
| sub
->swm
->iif
.map
);
237 dev_err(dev
, "Unknown port type %d.\n", sub
->swm
->type
);
245 * aio_port_reset - reset AIO port block
246 * @sub: the AIO substream pointer
248 * Resets the digital signal input/output port block of AIO.
250 void aio_port_reset(struct uniphier_aio_sub
*sub
)
252 struct regmap
*r
= sub
->aio
->chip
->regmap
;
254 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
255 regmap_write(r
, AOUTRSTCTR0
, BIT(sub
->swm
->oport
.map
));
256 regmap_write(r
, AOUTRSTCTR1
, BIT(sub
->swm
->oport
.map
));
258 regmap_update_bits(r
, IPORTMXRSTCTR(sub
->swm
->iport
.map
),
259 IPORTMXRSTCTR_RSTPI_MASK
,
260 IPORTMXRSTCTR_RSTPI_RESET
);
261 regmap_update_bits(r
, IPORTMXRSTCTR(sub
->swm
->iport
.map
),
262 IPORTMXRSTCTR_RSTPI_MASK
,
263 IPORTMXRSTCTR_RSTPI_RELEASE
);
268 * aio_port_set_rate - set sampling rate of LPCM
269 * @sub: the AIO substream pointer, PCM substream only
270 * @rate: Sampling rate in Hz.
272 * Set suitable I2S format settings to input/output port block of AIO.
273 * Parameter is specified by hw_params().
275 * This function may return error if non-PCM substream.
277 * Return: Zero if successful, otherwise a negative value on error.
279 int aio_port_set_rate(struct uniphier_aio_sub
*sub
, int rate
)
281 struct regmap
*r
= sub
->aio
->chip
->regmap
;
282 struct device
*dev
= &sub
->aio
->chip
->pdev
->dev
;
285 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
288 v
= OPORTMXCTR1_FSSEL_8
;
291 v
= OPORTMXCTR1_FSSEL_11_025
;
294 v
= OPORTMXCTR1_FSSEL_12
;
297 v
= OPORTMXCTR1_FSSEL_16
;
300 v
= OPORTMXCTR1_FSSEL_22_05
;
303 v
= OPORTMXCTR1_FSSEL_24
;
306 v
= OPORTMXCTR1_FSSEL_32
;
309 v
= OPORTMXCTR1_FSSEL_44_1
;
312 v
= OPORTMXCTR1_FSSEL_48
;
315 v
= OPORTMXCTR1_FSSEL_88_2
;
318 v
= OPORTMXCTR1_FSSEL_96
;
321 v
= OPORTMXCTR1_FSSEL_176_4
;
324 v
= OPORTMXCTR1_FSSEL_192
;
327 dev_err(dev
, "Rate not supported(%d)\n", rate
);
331 regmap_update_bits(r
, OPORTMXCTR1(sub
->swm
->oport
.map
),
332 OPORTMXCTR1_FSSEL_MASK
, v
);
336 v
= IPORTMXCTR1_FSSEL_8
;
339 v
= IPORTMXCTR1_FSSEL_11_025
;
342 v
= IPORTMXCTR1_FSSEL_12
;
345 v
= IPORTMXCTR1_FSSEL_16
;
348 v
= IPORTMXCTR1_FSSEL_22_05
;
351 v
= IPORTMXCTR1_FSSEL_24
;
354 v
= IPORTMXCTR1_FSSEL_32
;
357 v
= IPORTMXCTR1_FSSEL_44_1
;
360 v
= IPORTMXCTR1_FSSEL_48
;
363 v
= IPORTMXCTR1_FSSEL_88_2
;
366 v
= IPORTMXCTR1_FSSEL_96
;
369 v
= IPORTMXCTR1_FSSEL_176_4
;
372 v
= IPORTMXCTR1_FSSEL_192
;
375 dev_err(dev
, "Rate not supported(%d)\n", rate
);
379 regmap_update_bits(r
, IPORTMXCTR1(sub
->swm
->iport
.map
),
380 IPORTMXCTR1_FSSEL_MASK
, v
);
387 * aio_port_set_fmt - set format of I2S data
388 * @sub: the AIO substream pointer, PCM substream only
389 * This parameter has no effect if substream is I2S or PCM.
391 * Set suitable I2S format settings to input/output port block of AIO.
392 * Parameter is specified by set_fmt().
394 * This function may return error if non-PCM substream.
396 * Return: Zero if successful, otherwise a negative value on error.
398 int aio_port_set_fmt(struct uniphier_aio_sub
*sub
)
400 struct regmap
*r
= sub
->aio
->chip
->regmap
;
401 struct device
*dev
= &sub
->aio
->chip
->pdev
->dev
;
404 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
405 switch (sub
->aio
->fmt
) {
406 case SND_SOC_DAIFMT_LEFT_J
:
407 v
= OPORTMXCTR1_I2SLRSEL_LEFT
;
409 case SND_SOC_DAIFMT_RIGHT_J
:
410 v
= OPORTMXCTR1_I2SLRSEL_RIGHT
;
412 case SND_SOC_DAIFMT_I2S
:
413 v
= OPORTMXCTR1_I2SLRSEL_I2S
;
416 dev_err(dev
, "Format is not supported(%d)\n",
421 v
|= OPORTMXCTR1_OUTBITSEL_24
;
422 regmap_update_bits(r
, OPORTMXCTR1(sub
->swm
->oport
.map
),
423 OPORTMXCTR1_I2SLRSEL_MASK
|
424 OPORTMXCTR1_OUTBITSEL_MASK
, v
);
426 switch (sub
->aio
->fmt
) {
427 case SND_SOC_DAIFMT_LEFT_J
:
428 v
= IPORTMXCTR1_LRSEL_LEFT
;
430 case SND_SOC_DAIFMT_RIGHT_J
:
431 v
= IPORTMXCTR1_LRSEL_RIGHT
;
433 case SND_SOC_DAIFMT_I2S
:
434 v
= IPORTMXCTR1_LRSEL_I2S
;
437 dev_err(dev
, "Format is not supported(%d)\n",
442 v
|= IPORTMXCTR1_OUTBITSEL_24
|
443 IPORTMXCTR1_CHSEL_ALL
;
444 regmap_update_bits(r
, IPORTMXCTR1(sub
->swm
->iport
.map
),
445 IPORTMXCTR1_LRSEL_MASK
|
446 IPORTMXCTR1_OUTBITSEL_MASK
|
447 IPORTMXCTR1_CHSEL_MASK
, v
);
454 * aio_port_set_clk - set clock and divider of AIO port block
455 * @sub: the AIO substream pointer
457 * Set suitable PLL clock divider and relational settings to
458 * input/output port block of AIO. Parameters are specified by
459 * set_sysclk() and set_pll().
461 * Return: Zero if successful, otherwise a negative value on error.
463 int aio_port_set_clk(struct uniphier_aio_sub
*sub
)
465 struct uniphier_aio_chip
*chip
= sub
->aio
->chip
;
466 struct device
*dev
= &sub
->aio
->chip
->pdev
->dev
;
467 struct regmap
*r
= sub
->aio
->chip
->regmap
;
469 OPORTMXCTR2_ACLKSEL_A1
, OPORTMXCTR2_ACLKSEL_F1
,
470 OPORTMXCTR2_ACLKSEL_A2
, OPORTMXCTR2_ACLKSEL_F2
,
471 OPORTMXCTR2_ACLKSEL_A2PLL
,
472 OPORTMXCTR2_ACLKSEL_RX1
,
475 OPORTMXCTR2_DACCKSEL_1_2
, OPORTMXCTR2_DACCKSEL_1_3
,
476 OPORTMXCTR2_DACCKSEL_1_1
, OPORTMXCTR2_DACCKSEL_2_3
,
480 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
481 if (sub
->swm
->type
== PORT_TYPE_I2S
) {
482 if (sub
->aio
->pll_out
>= ARRAY_SIZE(v_pll
)) {
483 dev_err(dev
, "PLL(%d) is invalid\n",
487 if (sub
->aio
->plldiv
>= ARRAY_SIZE(v_div
)) {
488 dev_err(dev
, "PLL divider(%d) is invalid\n",
493 v
= v_pll
[sub
->aio
->pll_out
] |
494 OPORTMXCTR2_MSSEL_MASTER
|
495 v_div
[sub
->aio
->plldiv
];
497 switch (chip
->plls
[sub
->aio
->pll_out
].freq
) {
501 v
|= OPORTMXCTR2_EXTLSIFSSEL_36
;
504 v
|= OPORTMXCTR2_EXTLSIFSSEL_24
;
507 } else if (sub
->swm
->type
== PORT_TYPE_EVE
) {
508 v
= OPORTMXCTR2_ACLKSEL_A2PLL
|
509 OPORTMXCTR2_MSSEL_MASTER
|
510 OPORTMXCTR2_EXTLSIFSSEL_36
|
511 OPORTMXCTR2_DACCKSEL_1_2
;
512 } else if (sub
->swm
->type
== PORT_TYPE_SPDIF
) {
513 if (sub
->aio
->pll_out
>= ARRAY_SIZE(v_pll
)) {
514 dev_err(dev
, "PLL(%d) is invalid\n",
518 v
= v_pll
[sub
->aio
->pll_out
] |
519 OPORTMXCTR2_MSSEL_MASTER
|
520 OPORTMXCTR2_DACCKSEL_1_2
;
522 switch (chip
->plls
[sub
->aio
->pll_out
].freq
) {
526 v
|= OPORTMXCTR2_EXTLSIFSSEL_36
;
529 v
|= OPORTMXCTR2_EXTLSIFSSEL_24
;
533 v
= OPORTMXCTR2_ACLKSEL_A1
|
534 OPORTMXCTR2_MSSEL_MASTER
|
535 OPORTMXCTR2_EXTLSIFSSEL_36
|
536 OPORTMXCTR2_DACCKSEL_1_2
;
538 regmap_write(r
, OPORTMXCTR2(sub
->swm
->oport
.map
), v
);
540 v
= IPORTMXCTR2_ACLKSEL_A1
|
541 IPORTMXCTR2_MSSEL_SLAVE
|
542 IPORTMXCTR2_EXTLSIFSSEL_36
|
543 IPORTMXCTR2_DACCKSEL_1_2
;
544 regmap_write(r
, IPORTMXCTR2(sub
->swm
->iport
.map
), v
);
551 * aio_port_set_param - set parameters of AIO port block
552 * @sub: the AIO substream pointer
553 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
554 * This parameter has no effect if substream is I2S or PCM.
555 * @params: hardware parameters of ALSA
557 * Set suitable setting to input/output port block of AIO to process the
558 * specified in params.
560 * Return: Zero if successful, otherwise a negative value on error.
562 int aio_port_set_param(struct uniphier_aio_sub
*sub
, int pass_through
,
563 const struct snd_pcm_hw_params
*params
)
565 struct regmap
*r
= sub
->aio
->chip
->regmap
;
571 if (sub
->swm
->type
== PORT_TYPE_EVE
||
572 sub
->swm
->type
== PORT_TYPE_CONV
) {
575 rate
= params_rate(params
);
578 ret
= aio_port_set_rate(sub
, rate
);
582 ret
= aio_port_set_fmt(sub
);
587 ret
= aio_port_set_clk(sub
);
591 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
593 v
= OPORTMXCTR3_SRCSEL_STREAM
|
594 OPORTMXCTR3_VALID_STREAM
;
596 v
= OPORTMXCTR3_SRCSEL_PCM
|
597 OPORTMXCTR3_VALID_PCM
;
599 v
|= OPORTMXCTR3_IECTHUR_IECOUT
|
600 OPORTMXCTR3_PMSEL_PAUSE
|
601 OPORTMXCTR3_PMSW_MUTE_OFF
;
602 regmap_write(r
, OPORTMXCTR3(sub
->swm
->oport
.map
), v
);
604 regmap_write(r
, IPORTMXACLKSEL0EX(sub
->swm
->iport
.map
),
605 IPORTMXACLKSEL0EX_ACLKSEL0EX_INTERNAL
);
606 regmap_write(r
, IPORTMXEXNOE(sub
->swm
->iport
.map
),
607 IPORTMXEXNOE_PCMINOE_INPUT
);
614 * aio_port_set_enable - start or stop of AIO port block
615 * @sub: the AIO substream pointer
616 * @enable: zero to stop the block, otherwise to start
618 * Start or stop the signal input/output port block of AIO.
620 void aio_port_set_enable(struct uniphier_aio_sub
*sub
, int enable
)
622 struct regmap
*r
= sub
->aio
->chip
->regmap
;
624 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
625 regmap_write(r
, OPORTMXPATH(sub
->swm
->oport
.map
),
628 regmap_update_bits(r
, OPORTMXMASK(sub
->swm
->oport
.map
),
629 OPORTMXMASK_IUDXMSK_MASK
|
630 OPORTMXMASK_IUXCKMSK_MASK
|
631 OPORTMXMASK_DXMSK_MASK
|
632 OPORTMXMASK_XCKMSK_MASK
,
633 OPORTMXMASK_IUDXMSK_OFF
|
634 OPORTMXMASK_IUXCKMSK_OFF
|
635 OPORTMXMASK_DXMSK_OFF
|
636 OPORTMXMASK_XCKMSK_OFF
);
639 regmap_write(r
, AOUTENCTR0
, BIT(sub
->swm
->oport
.map
));
641 regmap_write(r
, AOUTENCTR1
, BIT(sub
->swm
->oport
.map
));
643 regmap_update_bits(r
, IPORTMXMASK(sub
->swm
->iport
.map
),
644 IPORTMXMASK_IUXCKMSK_MASK
|
645 IPORTMXMASK_XCKMSK_MASK
,
646 IPORTMXMASK_IUXCKMSK_OFF
|
647 IPORTMXMASK_XCKMSK_OFF
);
650 regmap_update_bits(r
,
651 IPORTMXCTR2(sub
->swm
->iport
.map
),
652 IPORTMXCTR2_REQEN_MASK
,
653 IPORTMXCTR2_REQEN_ENABLE
);
655 regmap_update_bits(r
,
656 IPORTMXCTR2(sub
->swm
->iport
.map
),
657 IPORTMXCTR2_REQEN_MASK
,
658 IPORTMXCTR2_REQEN_DISABLE
);
663 * aio_port_get_volume - get volume of AIO port block
664 * @sub: the AIO substream pointer
666 * Return: current volume, range is 0x0000 - 0xffff
668 int aio_port_get_volume(struct uniphier_aio_sub
*sub
)
670 struct regmap
*r
= sub
->aio
->chip
->regmap
;
673 regmap_read(r
, OPORTMXTYVOLGAINSTATUS(sub
->swm
->oport
.map
, 0), &v
);
675 return FIELD_GET(OPORTMXTYVOLGAINSTATUS_CUR_MASK
, v
);
679 * aio_port_set_volume - set volume of AIO port block
680 * @sub: the AIO substream pointer
681 * @vol: target volume, range is 0x0000 - 0xffff.
683 * Change digital volume and perfome fade-out/fade-in effect for specified
684 * output slot of port. Gained PCM value can calculate as the following:
685 * Gained = Original * vol / 0x4000
687 void aio_port_set_volume(struct uniphier_aio_sub
*sub
, int vol
)
689 struct regmap
*r
= sub
->aio
->chip
->regmap
;
690 int oport_map
= sub
->swm
->oport
.map
;
691 int cur
, diff
, slope
= 0, fs
;
693 if (sub
->swm
->dir
== PORT_DIR_INPUT
)
696 cur
= aio_port_get_volume(sub
);
697 diff
= abs(vol
- cur
);
698 fs
= params_rate(&sub
->params
);
700 slope
= diff
/ AUD_VOL_FADE_TIME
* 1000 / fs
;
701 slope
= max(1, slope
);
703 regmap_update_bits(r
, OPORTMXTYVOLPARA1(oport_map
, 0),
704 OPORTMXTYVOLPARA1_SLOPEU_MASK
, slope
<< 16);
705 regmap_update_bits(r
, OPORTMXTYVOLPARA2(oport_map
, 0),
706 OPORTMXTYVOLPARA2_TARGET_MASK
, vol
);
709 regmap_update_bits(r
, OPORTMXTYVOLPARA2(oport_map
, 0),
710 OPORTMXTYVOLPARA2_FADE_MASK
,
711 OPORTMXTYVOLPARA2_FADE_FADEIN
);
713 regmap_update_bits(r
, OPORTMXTYVOLPARA2(oport_map
, 0),
714 OPORTMXTYVOLPARA2_FADE_MASK
,
715 OPORTMXTYVOLPARA2_FADE_FADEOUT
);
717 regmap_write(r
, AOUTFADECTR0
, BIT(oport_map
));
721 * aio_if_set_param - set parameters of AIO DMA I/F block
722 * @sub: the AIO substream pointer
723 * @pass_through: Zero if sound data is LPCM, otherwise if data is not LPCM.
724 * This parameter has no effect if substream is I2S or PCM.
726 * Set suitable setting to DMA interface block of AIO to process the
727 * specified in settings.
729 * Return: Zero if successful, otherwise a negative value on error.
731 int aio_if_set_param(struct uniphier_aio_sub
*sub
, int pass_through
)
733 struct regmap
*r
= sub
->aio
->chip
->regmap
;
736 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
738 v
= PBOUTMXCTR0_ENDIAN_0123
|
739 PBOUTMXCTR0_MEMFMT_STREAM
;
741 v
= PBOUTMXCTR0_ENDIAN_3210
|
742 PBOUTMXCTR0_MEMFMT_2CH
;
744 regmap_write(r
, PBOUTMXCTR0(sub
->swm
->oif
.map
), v
);
745 regmap_write(r
, PBOUTMXCTR1(sub
->swm
->oif
.map
), 0);
747 regmap_write(r
, PBINMXCTR(sub
->swm
->iif
.map
),
748 PBINMXCTR_NCONNECT_CONNECT
|
749 PBINMXCTR_INOUTSEL_IN
|
750 (sub
->swm
->iport
.map
<< PBINMXCTR_PBINSEL_SHIFT
) |
751 PBINMXCTR_ENDIAN_3210
|
752 PBINMXCTR_MEMFMT_D0
);
759 * aio_oport_set_stream_type - set parameters of AIO playback port block
760 * @sub: the AIO substream pointer
761 * @pc: Pc type of IEC61937
763 * Set special setting to output port block of AIO to output the stream
766 * Return: Zero if successful, otherwise a negative value on error.
768 int aio_oport_set_stream_type(struct uniphier_aio_sub
*sub
,
771 struct regmap
*r
= sub
->aio
->chip
->regmap
;
772 u32 repet
= 0, pause
= OPORTMXPAUDAT_PAUSEPC_CMN
;
775 case IEC61937_PC_AC3
:
776 repet
= OPORTMXREPET_STRLENGTH_AC3
|
777 OPORTMXREPET_PMLENGTH_AC3
;
778 pause
|= OPORTMXPAUDAT_PAUSEPD_AC3
;
780 case IEC61937_PC_MPA
:
781 repet
= OPORTMXREPET_STRLENGTH_MPA
|
782 OPORTMXREPET_PMLENGTH_MPA
;
783 pause
|= OPORTMXPAUDAT_PAUSEPD_MPA
;
785 case IEC61937_PC_MP3
:
786 repet
= OPORTMXREPET_STRLENGTH_MP3
|
787 OPORTMXREPET_PMLENGTH_MP3
;
788 pause
|= OPORTMXPAUDAT_PAUSEPD_MP3
;
790 case IEC61937_PC_DTS1
:
791 repet
= OPORTMXREPET_STRLENGTH_DTS1
|
792 OPORTMXREPET_PMLENGTH_DTS1
;
793 pause
|= OPORTMXPAUDAT_PAUSEPD_DTS1
;
795 case IEC61937_PC_DTS2
:
796 repet
= OPORTMXREPET_STRLENGTH_DTS2
|
797 OPORTMXREPET_PMLENGTH_DTS2
;
798 pause
|= OPORTMXPAUDAT_PAUSEPD_DTS2
;
800 case IEC61937_PC_DTS3
:
801 repet
= OPORTMXREPET_STRLENGTH_DTS3
|
802 OPORTMXREPET_PMLENGTH_DTS3
;
803 pause
|= OPORTMXPAUDAT_PAUSEPD_DTS3
;
805 case IEC61937_PC_AAC
:
806 repet
= OPORTMXREPET_STRLENGTH_AAC
|
807 OPORTMXREPET_PMLENGTH_AAC
;
808 pause
|= OPORTMXPAUDAT_PAUSEPD_AAC
;
810 case IEC61937_PC_PAUSE
:
815 regmap_write(r
, OPORTMXREPET(sub
->swm
->oport
.map
), repet
);
816 regmap_write(r
, OPORTMXPAUDAT(sub
->swm
->oport
.map
), pause
);
822 * aio_src_reset - reset AIO SRC block
823 * @sub: the AIO substream pointer
825 * Resets the digital signal input/output port with sampling rate converter
827 * This function has no effect if substream is not supported rate converter.
829 void aio_src_reset(struct uniphier_aio_sub
*sub
)
831 struct regmap
*r
= sub
->aio
->chip
->regmap
;
833 if (sub
->swm
->dir
!= PORT_DIR_OUTPUT
)
836 regmap_write(r
, AOUTSRCRSTCTR0
, BIT(sub
->swm
->oport
.map
));
837 regmap_write(r
, AOUTSRCRSTCTR1
, BIT(sub
->swm
->oport
.map
));
841 * aio_src_set_param - set parameters of AIO SRC block
842 * @sub: the AIO substream pointer
843 * @params: hardware parameters of ALSA
845 * Set suitable setting to input/output port with sampling rate converter
846 * block of AIO to process the specified in params.
847 * This function has no effect if substream is not supported rate converter.
849 * Return: Zero if successful, otherwise a negative value on error.
851 int aio_src_set_param(struct uniphier_aio_sub
*sub
,
852 const struct snd_pcm_hw_params
*params
)
854 struct regmap
*r
= sub
->aio
->chip
->regmap
;
857 if (sub
->swm
->dir
!= PORT_DIR_OUTPUT
)
860 regmap_write(r
, OPORTMXSRC1CTR(sub
->swm
->oport
.map
),
861 OPORTMXSRC1CTR_THMODE_SRC
|
862 OPORTMXSRC1CTR_SRCPATH_CALC
|
863 OPORTMXSRC1CTR_SYNC_ASYNC
|
864 OPORTMXSRC1CTR_FSIIPSEL_INNER
|
865 OPORTMXSRC1CTR_FSISEL_ACLK
);
867 switch (params_rate(params
)) {
870 v
= OPORTMXRATE_I_ACLKSEL_APLLA1
|
871 OPORTMXRATE_I_MCKSEL_36
|
872 OPORTMXRATE_I_FSSEL_48
;
875 v
= OPORTMXRATE_I_ACLKSEL_APLLA2
|
876 OPORTMXRATE_I_MCKSEL_33
|
877 OPORTMXRATE_I_FSSEL_44_1
;
880 v
= OPORTMXRATE_I_ACLKSEL_APLLA1
|
881 OPORTMXRATE_I_MCKSEL_36
|
882 OPORTMXRATE_I_FSSEL_32
;
886 regmap_write(r
, OPORTMXRATE_I(sub
->swm
->oport
.map
),
887 v
| OPORTMXRATE_I_ACLKSRC_APLL
|
888 OPORTMXRATE_I_LRCKSTP_STOP
);
889 regmap_update_bits(r
, OPORTMXRATE_I(sub
->swm
->oport
.map
),
890 OPORTMXRATE_I_LRCKSTP_MASK
,
891 OPORTMXRATE_I_LRCKSTP_START
);
896 int aio_srcif_set_param(struct uniphier_aio_sub
*sub
)
898 struct regmap
*r
= sub
->aio
->chip
->regmap
;
900 regmap_write(r
, PBINMXCTR(sub
->swm
->iif
.map
),
901 PBINMXCTR_NCONNECT_CONNECT
|
902 PBINMXCTR_INOUTSEL_OUT
|
903 (sub
->swm
->oport
.map
<< PBINMXCTR_PBINSEL_SHIFT
) |
904 PBINMXCTR_ENDIAN_3210
|
905 PBINMXCTR_MEMFMT_D0
);
910 int aio_srcch_set_param(struct uniphier_aio_sub
*sub
)
912 struct regmap
*r
= sub
->aio
->chip
->regmap
;
914 regmap_write(r
, CDA2D_CHMXCTRL1(sub
->swm
->och
.map
),
915 CDA2D_CHMXCTRL1_INDSIZE_INFINITE
);
917 regmap_write(r
, CDA2D_CHMXSRCAMODE(sub
->swm
->och
.map
),
918 CDA2D_CHMXAMODE_ENDIAN_3210
|
919 CDA2D_CHMXAMODE_AUPDT_FIX
|
920 CDA2D_CHMXAMODE_TYPE_NORMAL
);
922 regmap_write(r
, CDA2D_CHMXDSTAMODE(sub
->swm
->och
.map
),
923 CDA2D_CHMXAMODE_ENDIAN_3210
|
924 CDA2D_CHMXAMODE_AUPDT_INC
|
925 CDA2D_CHMXAMODE_TYPE_RING
|
926 (sub
->swm
->och
.map
<< CDA2D_CHMXAMODE_RSSEL_SHIFT
));
931 void aio_srcch_set_enable(struct uniphier_aio_sub
*sub
, int enable
)
933 struct regmap
*r
= sub
->aio
->chip
->regmap
;
937 v
= CDA2D_STRT0_STOP_START
;
939 v
= CDA2D_STRT0_STOP_STOP
;
941 regmap_write(r
, CDA2D_STRT0
,
942 v
| BIT(sub
->swm
->och
.map
));
945 int aiodma_ch_set_param(struct uniphier_aio_sub
*sub
)
947 struct regmap
*r
= sub
->aio
->chip
->regmap
;
950 regmap_write(r
, CDA2D_CHMXCTRL1(sub
->swm
->ch
.map
),
951 CDA2D_CHMXCTRL1_INDSIZE_INFINITE
);
953 v
= CDA2D_CHMXAMODE_ENDIAN_3210
|
954 CDA2D_CHMXAMODE_AUPDT_INC
|
955 CDA2D_CHMXAMODE_TYPE_NORMAL
|
956 (sub
->swm
->rb
.map
<< CDA2D_CHMXAMODE_RSSEL_SHIFT
);
957 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
958 regmap_write(r
, CDA2D_CHMXSRCAMODE(sub
->swm
->ch
.map
), v
);
960 regmap_write(r
, CDA2D_CHMXDSTAMODE(sub
->swm
->ch
.map
), v
);
965 void aiodma_ch_set_enable(struct uniphier_aio_sub
*sub
, int enable
)
967 struct regmap
*r
= sub
->aio
->chip
->regmap
;
970 regmap_write(r
, CDA2D_STRT0
,
971 CDA2D_STRT0_STOP_START
| BIT(sub
->swm
->ch
.map
));
973 regmap_update_bits(r
, INTRBIM(0),
974 BIT(sub
->swm
->rb
.map
),
975 BIT(sub
->swm
->rb
.map
));
977 regmap_write(r
, CDA2D_STRT0
,
978 CDA2D_STRT0_STOP_STOP
| BIT(sub
->swm
->ch
.map
));
980 regmap_update_bits(r
, INTRBIM(0),
981 BIT(sub
->swm
->rb
.map
),
986 static u64
aiodma_rb_get_rp(struct uniphier_aio_sub
*sub
)
988 struct regmap
*r
= sub
->aio
->chip
->regmap
;
992 regmap_write(r
, CDA2D_RDPTRLOAD
,
993 CDA2D_RDPTRLOAD_LSFLAG_STORE
| BIT(sub
->swm
->rb
.map
));
995 for (i
= 0; i
< 6; i
++)
996 regmap_read(r
, CDA2D_RBMXRDPTR(sub
->swm
->rb
.map
), &pos_l
);
998 regmap_read(r
, CDA2D_RBMXRDPTR(sub
->swm
->rb
.map
), &pos_l
);
999 regmap_read(r
, CDA2D_RBMXRDPTRU(sub
->swm
->rb
.map
), &pos_u
);
1000 pos_u
= FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK
, pos_u
);
1002 return ((u64
)pos_u
<< 32) | pos_l
;
1005 static void aiodma_rb_set_rp(struct uniphier_aio_sub
*sub
, u64 pos
)
1007 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1011 regmap_write(r
, CDA2D_RBMXRDPTR(sub
->swm
->rb
.map
), (u32
)pos
);
1012 regmap_write(r
, CDA2D_RBMXRDPTRU(sub
->swm
->rb
.map
), (u32
)(pos
>> 32));
1013 regmap_write(r
, CDA2D_RDPTRLOAD
, BIT(sub
->swm
->rb
.map
));
1014 /* Wait for setup */
1015 for (i
= 0; i
< 6; i
++)
1016 regmap_read(r
, CDA2D_RBMXRDPTR(sub
->swm
->rb
.map
), &tmp
);
1019 static u64
aiodma_rb_get_wp(struct uniphier_aio_sub
*sub
)
1021 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1025 regmap_write(r
, CDA2D_WRPTRLOAD
,
1026 CDA2D_WRPTRLOAD_LSFLAG_STORE
| BIT(sub
->swm
->rb
.map
));
1027 /* Wait for setup */
1028 for (i
= 0; i
< 6; i
++)
1029 regmap_read(r
, CDA2D_RBMXWRPTR(sub
->swm
->rb
.map
), &pos_l
);
1031 regmap_read(r
, CDA2D_RBMXWRPTR(sub
->swm
->rb
.map
), &pos_l
);
1032 regmap_read(r
, CDA2D_RBMXWRPTRU(sub
->swm
->rb
.map
), &pos_u
);
1033 pos_u
= FIELD_GET(CDA2D_RBMXPTRU_PTRU_MASK
, pos_u
);
1035 return ((u64
)pos_u
<< 32) | pos_l
;
1038 static void aiodma_rb_set_wp(struct uniphier_aio_sub
*sub
, u64 pos
)
1040 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1044 regmap_write(r
, CDA2D_RBMXWRPTR(sub
->swm
->rb
.map
),
1045 lower_32_bits(pos
));
1046 regmap_write(r
, CDA2D_RBMXWRPTRU(sub
->swm
->rb
.map
),
1047 upper_32_bits(pos
));
1048 regmap_write(r
, CDA2D_WRPTRLOAD
, BIT(sub
->swm
->rb
.map
));
1049 /* Wait for setup */
1050 for (i
= 0; i
< 6; i
++)
1051 regmap_read(r
, CDA2D_RBMXWRPTR(sub
->swm
->rb
.map
), &tmp
);
1054 int aiodma_rb_set_threshold(struct uniphier_aio_sub
*sub
, u64 size
, u32 th
)
1056 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1061 regmap_write(r
, CDA2D_RBMXBTH(sub
->swm
->rb
.map
), th
);
1062 regmap_write(r
, CDA2D_RBMXRTH(sub
->swm
->rb
.map
), th
);
1067 int aiodma_rb_set_buffer(struct uniphier_aio_sub
*sub
, u64 start
, u64 end
,
1070 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1071 u64 size
= end
- start
;
1074 if (end
< start
|| period
< 0)
1077 regmap_write(r
, CDA2D_RBMXCNFG(sub
->swm
->rb
.map
), 0);
1078 regmap_write(r
, CDA2D_RBMXBGNADRS(sub
->swm
->rb
.map
),
1079 lower_32_bits(start
));
1080 regmap_write(r
, CDA2D_RBMXBGNADRSU(sub
->swm
->rb
.map
),
1081 upper_32_bits(start
));
1082 regmap_write(r
, CDA2D_RBMXENDADRS(sub
->swm
->rb
.map
),
1083 lower_32_bits(end
));
1084 regmap_write(r
, CDA2D_RBMXENDADRSU(sub
->swm
->rb
.map
),
1085 upper_32_bits(end
));
1087 regmap_write(r
, CDA2D_RBADRSLOAD
, BIT(sub
->swm
->rb
.map
));
1089 ret
= aiodma_rb_set_threshold(sub
, size
, 2 * period
);
1093 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
1094 aiodma_rb_set_rp(sub
, start
);
1095 aiodma_rb_set_wp(sub
, end
- period
);
1097 regmap_update_bits(r
, CDA2D_RBMXIE(sub
->swm
->rb
.map
),
1099 CDA2D_RBMXIX_SPACE
);
1101 aiodma_rb_set_rp(sub
, end
- period
);
1102 aiodma_rb_set_wp(sub
, start
);
1104 regmap_update_bits(r
, CDA2D_RBMXIE(sub
->swm
->rb
.map
),
1105 CDA2D_RBMXIX_REMAIN
,
1106 CDA2D_RBMXIX_REMAIN
);
1109 sub
->threshold
= 2 * period
;
1120 void aiodma_rb_sync(struct uniphier_aio_sub
*sub
, u64 start
, u64 size
,
1123 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
1124 sub
->rd_offs
= aiodma_rb_get_rp(sub
) - start
;
1126 if (sub
->use_mmap
) {
1127 sub
->threshold
= 2 * period
;
1128 aiodma_rb_set_threshold(sub
, size
, 2 * period
);
1130 sub
->wr_offs
= sub
->rd_offs
- period
;
1131 if (sub
->rd_offs
< period
)
1132 sub
->wr_offs
+= size
;
1134 aiodma_rb_set_wp(sub
, sub
->wr_offs
+ start
);
1136 sub
->wr_offs
= aiodma_rb_get_wp(sub
) - start
;
1138 if (sub
->use_mmap
) {
1139 sub
->threshold
= 2 * period
;
1140 aiodma_rb_set_threshold(sub
, size
, 2 * period
);
1142 sub
->rd_offs
= sub
->wr_offs
- period
;
1143 if (sub
->wr_offs
< period
)
1144 sub
->rd_offs
+= size
;
1146 aiodma_rb_set_rp(sub
, sub
->rd_offs
+ start
);
1149 sub
->rd_total
+= sub
->rd_offs
- sub
->rd_org
;
1150 if (sub
->rd_offs
< sub
->rd_org
)
1151 sub
->rd_total
+= size
;
1152 sub
->wr_total
+= sub
->wr_offs
- sub
->wr_org
;
1153 if (sub
->wr_offs
< sub
->wr_org
)
1154 sub
->wr_total
+= size
;
1156 sub
->rd_org
= sub
->rd_offs
;
1157 sub
->wr_org
= sub
->wr_offs
;
1160 bool aiodma_rb_is_irq(struct uniphier_aio_sub
*sub
)
1162 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1165 regmap_read(r
, CDA2D_RBMXIR(sub
->swm
->rb
.map
), &ir
);
1167 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
1168 return !!(ir
& CDA2D_RBMXIX_SPACE
);
1170 return !!(ir
& CDA2D_RBMXIX_REMAIN
);
1173 void aiodma_rb_clear_irq(struct uniphier_aio_sub
*sub
)
1175 struct regmap
*r
= sub
->aio
->chip
->regmap
;
1177 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
1178 regmap_write(r
, CDA2D_RBMXIR(sub
->swm
->rb
.map
),
1179 CDA2D_RBMXIX_SPACE
);
1181 regmap_write(r
, CDA2D_RBMXIR(sub
->swm
->rb
.map
),
1182 CDA2D_RBMXIX_REMAIN
);