audio: auge: add loopback driver [1/1]

PD#SWPL-7240

Problem:
limit of current loopback
add loopback b for tl1
add tdmin_lb

Solution:
1. merge sm1, tm2 audio bringup code
2. optimize loopback driver

Verify:
s400, u200, x301, ac200, ab301

Change-Id: I0b01208fe8a213766e5563fa91b66e93c748d843
Signed-off-by: Lei Qian <lei.qian@amlogic.com>
This commit is contained in:
Lei Qian
2019-05-07 20:05:02 +08:00
committed by Luke Go
parent b1a7ff5adb
commit 081b08ffbb
28 changed files with 3744 additions and 1362 deletions

View File

@@ -319,6 +319,51 @@
sound-dai = <&dummy_codec>;
};
};
#if 0
aml-audio-card,dai-link@7 {
format = "i2s";
mclk-fs = <256>;
//continuous-clock;
//bitclock-inversion;
//frame-inversion;
bitclock-master = <&tdmlb>;
frame-master = <&tdmlb>;
cpu {
sound-dai = <&tdmlb>;
dai-tdm-slot-rx-mask = <1 1>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <32>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
#endif
aml-audio-card,dai-link@8 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
aml-audio-card,dai-link@9 {
mclk-fs = <256>;
suffix-name = "alsaPORT-loopbackb";
cpu {
sound-dai = <&loopbackb>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -975,6 +1020,8 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
/* !!!For --TV platform-- ONLY */
@@ -996,6 +1043,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1014,6 +1063,57 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "okay";
};
@@ -1209,10 +1309,120 @@
* 0: in user space
* 1: in kernel space
*/
level = <0>;
level = <1>;
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -423,6 +423,29 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
aml-audio-card,dai-link@8 {
mclk-fs = <256>;
suffix-name = "alsaPORT-loopbackb";
cpu {
sound-dai = <&loopbackb>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -1273,6 +1296,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -1295,6 +1319,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1313,9 +1339,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1475,6 +1552,151 @@
status = "disabled";
};
vad:vad {
compatible = "amlogic, snd-vad";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD
&clkc CLKID_FCLK_DIV5
&clkaudio CLKID_AUDIO_VAD>;
clock-names = "gate", "pll", "clk";
interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING
GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "irq_wakeup", "irq_frame_sync";
/*
* Data src sel:
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
* 5: loopback_b;
* 6: tdmin_lb;
* 7: loopback_a;
*/
src = <4>;
/*
* deal with hot word in user space or kernel space
* 0: in user space
* 1: in kernel space
*/
level = <1>;
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -323,6 +323,18 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -977,6 +989,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -999,6 +1012,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1017,9 +1032,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1213,6 +1279,116 @@
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "disabled";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -443,6 +443,18 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -1542,6 +1554,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -1564,6 +1577,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1582,9 +1597,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1777,6 +1843,116 @@
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "disabled";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -433,6 +433,29 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
aml-audio-card,dai-link@8 {
mclk-fs = <256>;
suffix-name = "alsaPORT-loopbackb";
cpu {
sound-dai = <&loopbackb>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -1464,6 +1487,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -1486,6 +1510,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1504,9 +1530,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1665,6 +1742,151 @@
status = "disabled";
};
vad:vad {
compatible = "amlogic, snd-vad";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD
&clkc CLKID_FCLK_DIV5
&clkaudio CLKID_AUDIO_VAD>;
clock-names = "gate", "pll", "clk";
interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING
GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "irq_wakeup", "irq_frame_sync";
/*
* Data src sel:
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
* 5: loopback_b;
* 6: tdmin_lb;
* 7: loopback_a;
*/
src = <4>;
/*
* deal with hot word in user space or kernel space
* 0: in user space
* 1: in kernel space
*/
level = <1>;
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -440,6 +440,18 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -1350,6 +1362,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -1372,6 +1385,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1390,9 +1405,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1550,6 +1616,151 @@
status = "disabled";
};
vad:vad {
compatible = "amlogic, snd-vad";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD
&clkc CLKID_FCLK_DIV5
&clkaudio CLKID_AUDIO_VAD>;
clock-names = "gate", "pll", "clk";
interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING
GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "irq_wakeup", "irq_frame_sync";
/*
* Data src sel:
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
* 5: loopback_b;
* 6: tdmin_lb;
* 7: loopback_a;
*/
src = <4>;
/*
* deal with hot word in user space or kernel space
* 0: in user space
* 1: in kernel space
*/
level = <1>;
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "disabled";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -434,6 +434,18 @@
};
};
aml-audio-card,dai-link@7 {
mclk-fs = <256>;
continuous-clock;
suffix-name = "alsaPORT-loopback";
cpu {
sound-dai = <&loopbacka>;
system-clock-frequency = <12288000>;
};
codec {
sound-dai = <&dummy_codec>;
};
};
};
/* Audio Related end */
@@ -1344,6 +1356,7 @@
/* In for ACODEC_ADC */
acodec_adc = <1>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
@@ -1366,6 +1379,8 @@
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
@@ -1384,9 +1399,60 @@
pinctrl-names = "tdm_pins";
pinctrl-0 = <&tdmout_c &tdmin_c>;
mclk_pad = <0>; /* 0: mclk_0; 1: mclk_1 */
status = "okay";
};
tdmlb:tdm@3 {
compatible = "amlogic, tl1-snd-tdmlb";
#sound-dai-cells = <0>;
dai-tdm-lane-lb-slot-mask-in = <1 0 0 0>;
dai-tdm-clk-sel = <1>;
clocks = <&clkaudio CLKID_AUDIO_MCLK_B
&clkc CLKID_MPLL1>;
clock-names = "mclk", "clk_srcpll";
/*
* select tdmin_lb src;
* AXG
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA
* 4: PAD_TDMINB
* 5: PAD_TDMINC
*
* G12A/G12B
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*, oe pin
* 7: PAD_TDMINB_D*, oe pin
*
* TL1
* 0: TDMOUTA
* 1: TDMOUTB
* 2: TDMOUTC
* 3: PAD_TDMINA_DIN*
* 4: PAD_TDMINB_DIN*
* 5: PAD_TDMINC_DIN*
* 6: PAD_TDMINA_D*
* 7: PAD_TDMINB_D*
* 8: PAD_TDMINC_D*
* 9: HDMIRX_I2S
* 10: ACODEC_ADC
*/
lb-src-sel = <1>;
status = "disabled";
};
spdifa:spdif@0 {
compatible = "amlogic, tl1-snd-spdif-a";
#sound-dai-cells = <0>;
@@ -1545,6 +1611,151 @@
status = "disabled";
};
vad:vad {
compatible = "amlogic, snd-vad";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_TOVAD
&clkc CLKID_FCLK_DIV5
&clkaudio CLKID_AUDIO_VAD>;
clock-names = "gate", "pll", "clk";
interrupts = <GIC_SPI 155 IRQ_TYPE_EDGE_RISING
GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "irq_wakeup", "irq_frame_sync";
/*
* Data src sel:
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
* 5: loopback_b;
* 6: tdmin_lb;
* 7: loopback_a;
*/
src = <4>;
/*
* deal with hot word in user space or kernel space
* 0: in user space
* 1: in kernel space
*/
level = <1>;
status = "disabled";
};
loopbacka:loopback@0 {
compatible = "amlogic, tl1-loopbacka";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* calc mclk for datalb */
mclk-fs = <256>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <0>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "okay";
};
loopbackb:loopback@1 {
compatible = "amlogic, tl1-loopbackb";
#sound-dai-cells = <0>;
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
&clkc CLKID_FCLK_DIV3
&clkc CLKID_MPLL3
&clkaudio CLKID_AUDIO_PDMIN0
&clkaudio CLKID_AUDIO_PDMIN1
&clkc CLKID_MPLL0
&clkaudio CLKID_AUDIO_MCLK_A>;
clock-names = "pdm_gate",
"pdm_sysclk_srcpll",
"pdm_dclk_srcpll",
"pdm_dclk",
"pdm_sysclk",
"tdminlb_mpll",
"tdminlb_mclk";
/* calc mclk for datain_lb */
mclk-fs = <256>;
/* datain src
* 0: tdmin_a;
* 1: tdmin_b;
* 2: tdmin_c;
* 3: spdifin;
* 4: pdmin;
*/
datain_src = <4>;
datain_chnum = <4>;
datain_chmask = <0xf>;
/* config which data pin for loopback */
datain-lane-mask-in = <1 0 1 0>;
/* tdmin_lb src
* 0: tdmoutA
* 1: tdmoutB
* 2: tdmoutC
* 3: PAD_TDMINA_DIN*, refer to core pinmux
* 4: PAD_TDMINB_DIN*, refer to core pinmux
* 5: PAD_TDMINC_DIN*, refer to core pinmux
* 6: PAD_TDMINA_D*, oe, refer to core pinmux
* 7: PAD_TDMINB_D*, oe, refer to core pinmux
*/
/* if tdmin_lb >= 3, use external loopback */
datalb_src = <1>;
datalb_chnum = <2>;
datalb_chmask = <0x3>;
/* config which data pin as loopback */
datalb-lane-mask-in = <1 0 0 0>;
status = "disabled";
};
}; /* end of audiobus */
&pinctrl_periphs {

View File

@@ -17,6 +17,7 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \
pdm_hw_coeff.o \
iomap.o \
ddr_mngr.o \
loopback.o \
loopback_hw.o \
audio_utils.o \
locker.o \

View File

@@ -14,24 +14,18 @@
* more details.
*
*/
#include "audio_utils.h"
#include "regs.h"
#include "iomap.h"
#include "loopback_hw.h"
#include "spdif_hw.h"
#include "pdm_hw.h"
#include "tdm_hw.h"
#include "ddr_mngr.h"
#include "resample.h"
#include "effects_v2.h"
#include "vad.h"
#include "ddr_mngr.h"
#include <linux/amlogic/iomap.h>
#include <linux/amlogic/media/sound/auge_utils.h>
#include <linux/of_platform.h>
struct snd_elem_info {
struct soc_enum *ee;
int reg;
@@ -39,132 +33,8 @@ struct snd_elem_info {
u32 mask;
};
static unsigned int loopback_enable;
static unsigned int loopback_is_running;
static unsigned int datain_datalb_total;
static unsigned int audio_inskew;
static const char *const loopback_enable_texts[] = {
"Disable",
"Enable",
};
static const struct soc_enum loopback_enable_enum =
SOC_ENUM_SINGLE(EE_AUDIO_LB_CTRL0,
31,
ARRAY_SIZE(loopback_enable_texts),
loopback_enable_texts);
static int loopback_enable_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = loopback_enable;
return 0;
}
static int loopback_enable_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
loopback_enable = ucontrol->value.enumerated.item[0];
return 0;
}
static int datain_datalb_total_get_param(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.bytes.data[0] = datain_datalb_total;
return 0;
}
static int datain_datalb_total_set_param(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
datain_datalb_total = ucontrol->value.bytes.data[0];
return 0;
}
static unsigned int loopback_datain;
static const char *const loopback_datain_texts[] = {
"TDMIN_A",
"TDMIN_B",
"TDMIN_C",
"SPDIFIN",
"PDMIN",
};
static const struct soc_enum loopback_datain_enum =
SOC_ENUM_SINGLE(EE_AUDIO_LB_CTRL0, 0, ARRAY_SIZE(loopback_datain_texts),
loopback_datain_texts);
static int loopback_datain_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = loopback_datain;
return 0;
}
static int loopback_datain_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
loopback_datain = ucontrol->value.enumerated.item[0];
audiobus_update_bits(EE_AUDIO_LB_CTRL0, 0, loopback_datain);
return 0;
}
static unsigned int loopback_tdminlb;
static const char *const loopback_tdminlb_texts[] = {
"TDMOUT_A",
"TDMOUT_B",
"TDMOUT_C",
"TDMIN_A",
"TDMIN_B",
"TDMIN_C",
};
static const struct soc_enum loopback_tdminlb_enum =
SOC_ENUM_SINGLE(EE_AUDIO_TDMIN_LB_CTRL,
20,
ARRAY_SIZE(loopback_tdminlb_texts),
loopback_tdminlb_texts);
static int loopback_tdminlb_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = loopback_tdminlb;
return 0;
}
static int loopback_tdminlb_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
loopback_tdminlb = ucontrol->value.enumerated.item[0];
audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL,
0xf << 20,
loopback_datain);
return 0;
}
#if 0
static int snd_int_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
@@ -726,27 +596,6 @@ static int tdmout_c_binv_set_enum(
SND_BYTE(xname, type, func, xshift, xmask)
static const struct snd_kcontrol_new snd_auge_controls[] = {
/* loopback enable */
SOC_ENUM_EXT("Loopback Enable",
loopback_enable_enum,
loopback_enable_get_enum,
loopback_enable_set_enum),
SND_SOC_BYTES_EXT("datain_datalb_total", 1,
datain_datalb_total_get_param,
datain_datalb_total_set_param),
/* loopback data in source */
SOC_ENUM_EXT("Loopback datain source",
loopback_datain_enum,
loopback_datain_get_enum,
loopback_datain_set_enum),
/* loopback data tdmin lb */
SOC_ENUM_EXT("Loopback tmdin lb source",
loopback_tdminlb_enum,
loopback_tdminlb_get_enum,
loopback_tdminlb_set_enum),
#if 0
/*TDMIN_A swap*/
SND_SWAP("TDMIN_A Ch0 Swap", TDMIN_A, in_swap_channel_enum, 0, 0x7),
@@ -1058,519 +907,6 @@ int snd_card_add_kcontrols(struct snd_soc_card *card)
}
int loopback_parse_of(struct device_node *node,
struct loopback_cfg *lb_cfg)
{
struct platform_device *pdev;
const __be32 *of_slot_mask;
unsigned int lane_mask = 0;
int i, ret, set_num = 0;
u32 val;
pdev = of_find_device_by_node(node);
if (!pdev) {
dev_err(&pdev->dev, "failed to find platform device\n");
ret = -EINVAL;
goto fail;
}
/*mpll used for tdmin*/
lb_cfg->tdmin_mpll = devm_clk_get(&pdev->dev, "datalb_mpll");
if (IS_ERR(lb_cfg->tdmin_mpll)) {
dev_err(&pdev->dev,
"Can't retrieve tdmin_mpll clock\n");
lb_cfg->tdmin_mpll = NULL;
}
ret = of_property_read_u32(node, "lb_mode",
&lb_cfg->lb_mode);
if (ret) {
pr_err("failed to get lb_mode, set it default\n");
lb_cfg->lb_mode = 0;
ret = 0;
}
ret = of_property_read_u32(node, "datain_src",
&lb_cfg->datain_src);
if (ret) {
pr_err("failed to get datain_src\n");
ret = -EINVAL;
goto fail;
}
ret = of_property_read_u32(node, "datain_chnum",
&lb_cfg->datain_chnum);
if (ret) {
pr_err("failed to get datain_chnum\n");
ret = -EINVAL;
goto fail;
}
ret = of_property_read_u32(node, "datain_chmask",
&lb_cfg->datain_chmask);
if (ret) {
pr_err("failed to get datain_chmask\n");
ret = -EINVAL;
goto fail;
}
ret = of_property_read_u32(node, "datalb_src",
&lb_cfg->datalb_src);
if (ret) {
pr_err("failed to get datalb_src\n");
ret = -EINVAL;
goto fail;
}
ret = of_property_read_u32(node, "datalb_chnum",
&lb_cfg->datalb_chnum);
if (ret) {
pr_err("failed to get datalb_chnum\n");
ret = -EINVAL;
goto fail;
}
ret = of_property_read_u32(node, "datalb_chmask",
&lb_cfg->datalb_chmask);
if (ret) {
pr_err("failed to get datalb_chmask\n");
ret = -EINVAL;
goto fail;
}
of_slot_mask = of_get_property(node, "datalb-lane-mask-in", &val);
if (!of_slot_mask) {
pr_err("if use extern loopback, pls set datalb-lane-mask-in\n");
} else {
val /= sizeof(u32);
for (i = 0; i < val; i++)
if (be32_to_cpup(&of_slot_mask[i]))
lane_mask |= (1 << i);
for (i = 0; i < 4; i++) {
if ((1 << i) & lane_mask) {
/*each lane only L/R masked*/
lb_cfg->datalb_chswap |=
(i * 2) << (set_num++ * 4);
lb_cfg->datalb_chswap |=
(i * 2 + 1) << (set_num++ * 4);
}
}
}
ret = of_property_read_u32(node, "datalb_clk",
&lb_cfg->datalb_clk);
if (ret) {
pr_err("if no datalb_clk on dts, it equal is datalb_src\n");
lb_cfg->datalb_clk = lb_cfg->datalb_src;
}
ret = of_property_read_u32(node, "datain_datalb_total",
&lb_cfg->datain_datalb_total);
if (ret) {
pr_err("no register datain_datalb_total,it also can work\n");
lb_cfg->datain_datalb_total = 0;
} else {
if (lb_cfg->datain_datalb_total > 8) {
lb_cfg->datain_chnum = 8;
lb_cfg->datain_chmask = 0xff;
lb_cfg->datalb_chnum = 8;
lb_cfg->datalb_chmask = 0xff;
lb_cfg->datalb_chswap = 0x76543210;
}
}
datain_datalb_total = lb_cfg->datain_datalb_total;
loopback_datain = lb_cfg->datain_src;
loopback_tdminlb = lb_cfg->datalb_src;
pr_info("parse loopback:, \tlb mode:%d\n",
lb_cfg->lb_mode);
pr_info("\tdatain_src:%d, datain_chnum:%d, datain_chumask:%x\n",
lb_cfg->datain_src,
lb_cfg->datain_chnum,
lb_cfg->datain_chmask);
pr_info("\tdatalb_src:%d, datalb_chnum:%d\n",
lb_cfg->datalb_src,
lb_cfg->datalb_chnum);
pr_info("\tdatalb_chswap:0x%x,datalb_chmask:%x\n",
lb_cfg->datalb_chswap,
lb_cfg->datalb_chmask);
fail:
return ret;
}
int loopback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct loopback_cfg *lb_cfg,
unsigned int mclk)
{
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int bclk_sel, fsclk_sel;
int bit_depth;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return 0;
bit_depth = snd_pcm_format_width(runtime->format);
if (lb_cfg->datalb_src >= 3) {
/*tdm in*/
/*for i2s mode*/
unsigned int sclk_div = 4 - 1;
unsigned int ratio = params_channels(params) * bit_depth - 1;
unsigned int fsclk_hi;
unsigned int clk_id = lb_cfg->datalb_src - 3;
unsigned int mul = 2;
unsigned int mpll_freq, offset, reg;
/*lrclk sclk depend on default 8ch setting,*/
/* so if num of channels is 4, to change ratio*/
if (params_channels(params) == 4)
ratio = ratio*2;
fsclk_hi = ratio/2;
pr_info("%s, channels:%d, format:%d, ratio:%d\n",
__func__,
params_channels(params),
bit_depth,
ratio);
bclk_sel = clk_id;
fsclk_sel = clk_id;
/*mclk*/
mpll_freq = mclk * mul;
clk_set_rate(lb_cfg->tdmin_mpll, mpll_freq);
pr_info("mpll freq:%d, %lu\n", mpll_freq,
clk_get_rate(lb_cfg->tdmin_mpll));
offset = EE_AUDIO_MCLK_B_CTRL(0) - EE_AUDIO_MCLK_A_CTRL(0);
reg = EE_AUDIO_MCLK_A_CTRL(0) + offset * clk_id;
audiobus_write(reg,
1 << 31 | /*clk enable*/
clk_id << 24 | /*clk src*/
(mul - 1)); /*clk_div mclk*/
/*sclk, lrclk*/
offset = EE_AUDIO_MST_B_SCLK_CTRL0 - EE_AUDIO_MST_A_SCLK_CTRL0;
reg = EE_AUDIO_MST_A_SCLK_CTRL0 + offset * clk_id;
audiobus_update_bits(reg,
0x3 << 30 | 0x3ff << 20 | 0x3ff<<10 | 0x3ff,
0x3 << 30 | sclk_div << 20 | fsclk_hi << 10
| ratio);
audiobus_update_bits(
EE_AUDIO_CLK_TDMIN_LB_CTRL,
0x3 << 30 | 1 << 29 | 0xf << 24 | 0xf << 20,
0x3 << 30 | 1 << 29 | bclk_sel << 24 | fsclk_sel << 20);
}
return 0;
}
int loopback_prepare(
struct snd_pcm_substream *substream,
struct loopback_cfg *lb_cfg)
{
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int bitwidth;
unsigned int datain_toddr_type, datalb_toddr_type;
unsigned int datain_msb, datain_lsb, datalb_msb, datalb_lsb;
struct lb_cfg datain_cfg;
struct lb_cfg datalb_cfg;
struct audio_data ddrdata;
struct data_in datain;
struct data_lb datalb;
if (!lb_cfg)
return -EINVAL;
pr_info("%s\n", __func__);
bitwidth = snd_pcm_format_width(runtime->format);
switch (lb_cfg->datain_src) {
case DATAIN_TDMA:
case DATAIN_TDMB:
case DATAIN_TDMC:
case DATAIN_PDM:
datain_toddr_type = 0;
datain_msb = 32 - 1;
datain_lsb = 0;
break;
case DATAIN_SPDIF:
datain_toddr_type = 3;
datain_msb = 27;
datain_lsb = 4;
if (bitwidth <= 24)
datain_lsb = 28 - bitwidth;
else
datain_lsb = 4;
break;
default:
pr_err("unsupport data in source:%d\n",
lb_cfg->datain_src);
return -EINVAL;
}
switch (lb_cfg->datalb_src) {
case TDMINLB_TDMOUTA:
case TDMINLB_TDMOUTB:
case TDMINLB_TDMOUTC:
case TDMINLB_PAD_TDMINA:
case TDMINLB_PAD_TDMINB:
case TDMINLB_PAD_TDMINC:
if (bitwidth == 24) {
datalb_toddr_type = 4;
datalb_msb = 32 - 1;
datalb_lsb = 32 - bitwidth;
} else {
datalb_toddr_type = 0;
datalb_msb = 32 - 1;
datalb_lsb = 0;
}
break;
default:
pr_err("unsupport data lb source:%d\n",
lb_cfg->datalb_src);
return -EINVAL;
}
datain_cfg.ext_signed = 0;
datain_cfg.chnum = lb_cfg->datain_chnum;
datain_cfg.chmask = lb_cfg->datain_chmask;
ddrdata.combined_type = datain_toddr_type;
ddrdata.msb = datain_msb;
ddrdata.lsb = datain_lsb;
ddrdata.src = lb_cfg->datain_src;
datain.config = &datain_cfg;
datain.ddrdata = &ddrdata;
datalb_cfg.ext_signed = 0;
datalb_cfg.chnum = lb_cfg->datalb_chnum;
datalb_cfg.chmask = lb_cfg->datalb_chmask;
datalb.config = &datalb_cfg;
datalb.ddr_type = datalb_toddr_type;
datalb.msb = datalb_msb;
datalb.lsb = datalb_lsb;
datain_config(&datain);
datalb_config(&datalb);
lb_cfg->datain_datalb_total = datain_datalb_total;
if (lb_cfg->datain_datalb_total > 8) {
lb_cfg->datain_chnum = 8;
lb_cfg->datain_chmask = 0xff;
lb_cfg->datalb_chnum = 8;
lb_cfg->datalb_chmask = 0xff;
lb_cfg->datalb_chswap = 0x76543210;
}
datalb_ctrl(lb_cfg);
lb_mode(lb_cfg->lb_mode);
return 0;
}
void toddr_enable(int is_enable, int toddr_index)
{
int offset = EE_AUDIO_TODDR_B_CTRL0 - EE_AUDIO_TODDR_A_CTRL0;
int reg = EE_AUDIO_TODDR_A_CTRL0 + offset * toddr_index;
audiobus_update_bits(
reg,
0x1 << 31,
is_enable << 31);
}
void frddr_enable(int is_enable, int frddr_index)
{
int offset = EE_AUDIO_FRDDR_B_CTRL0 - EE_AUDIO_FRDDR_A_CTRL0;
int reg = EE_AUDIO_FRDDR_A_CTRL0 + offset * frddr_index;
audiobus_update_bits(
reg,
0x1 << 31,
is_enable << 31);
}
static void loopback_modules_disable(
struct loopback_cfg *lb_cfg,
int tdm_index,
int frddr_index, int toddr_index)
{
/* tdminLB */
tdmin_lb_fifo_enable(0);
tdmin_lb_enable(tdm_index, 0);
/* datain src */
switch (lb_cfg->datain_src) {
case 0:
case 1:
case 2:
/*tdm in*/
break;
case 3:
/*spdif in*/
break;
case 4:
/*pdm in*/
pdm_enable(0);
break;
default:
pr_err("unsupport datain source!!\n");
return;
}
/* loopback */
lb_enable(0);
/* toddr */
if (toddr_index >= 0)
toddr_enable(0, toddr_index);
/* frddr */
if (frddr_index >= 3)
toddr_enable(0, frddr_index - 3);
else if (frddr_index >= 0)
frddr_enable(0, frddr_index);
/* tdmout */
if (frddr_index >= 0) {
tdm_fifo_enable(tdm_index, 0);
tdm_enable(tdm_index, 0);
}
}
static void loopback_modules_enable(
struct loopback_cfg *lb_cfg,
int tdm_index,
int frddr_index, int toddr_index)
{
/*
* Loopback enable in sequence:
* tdmout->frddr->toddr->loopback->pdmin->tdminLB
*/
/* tdmout */
if (frddr_index >= 0) {
tdm_fifo_enable(tdm_index, 1);
tdm_enable(tdm_index, 1);
}
/* frddr */
if (frddr_index >= 3)
toddr_enable(1, frddr_index - 3);
else if (frddr_index >= 0)
frddr_enable(1, frddr_index);
tdm_fifo_enable(tdm_index, 1);
tdm_enable(tdm_index, 1);
frddr_enable(1, frddr_index);
/* toddr */
if (toddr_index >= 0)
toddr_enable(1, toddr_index);
/* loopback */
lb_enable(1);
/* datain src */
switch (lb_cfg->datain_src) {
case 0:
case 1:
case 2:
/*tdm in*/
break;
case 3:
/*spdif in*/
break;
case 4:
/*pdm in*/
pdm_enable(1);
break;
default:
pr_err("unsupport datain source!!\n");
return;
}
/*tdminLB*/
tdmin_lb_fifo_enable(1);
tdmin_lb_enable(tdm_index, 1);
}
int loopback_trigger(
struct snd_pcm_substream *substream,
int cmd,
struct loopback_cfg *lb_cfg)
{
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (loopback_enable && loopback_is_running) {
pr_info("loopback enable\n");
/*
* toddr/frdd is selected in dai_prepare already.
* check toddr index of datain
* check frddr index of datalb
*/
lb_cfg->toddr_index = fetch_toddr_index_by_src(
lb_cfg->datain_src);
/* check datalb is from tdmout or tdmin */
if (lb_cfg->datalb_src >= 3)
lb_cfg->frddr_index = fetch_toddr_index_by_src(
lb_cfg->datalb_src - 3);
else
lb_cfg->frddr_index = fetch_frddr_index_by_src(
lb_cfg->datalb_src);
pr_info("loopback toddr index:%d, frddr index:%d\n",
lb_cfg->toddr_index,
lb_cfg->frddr_index);
pr_info("loopback modules in sequence!\n");
/*if pdm overrun, re-set up the sequence*/
if (lb_cfg->frddr_index >= 0)
loopback_modules_disable(
lb_cfg,
lb_cfg->datalb_src,
lb_cfg->frddr_index,
lb_cfg->toddr_index);
loopback_modules_enable(
lb_cfg,
lb_cfg->datalb_src,
lb_cfg->frddr_index,
lb_cfg->toddr_index);
}
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
if (loopback_enable) {
pr_info("loopback disable\n");
lb_enable(0);
tdmin_lb_enable(lb_cfg->datalb_src, 0);
}
}
break;
default:
return -EINVAL;
}
return 0;
}
void loopback_set_status(int is_running)
{
loopback_is_running = is_running;
}
int loopback_is_enable(void)
{
return (loopback_enable == 1);
}
int loopback_check_enable(int src)
{
return (src <= PDMIN)
&& (loopback_datain == src)
&& (loopback_enable == 1);
}
void auge_acodec_reset(void)
{
audioreset_update_bits(EE_RESET1, 1 << 29, 1 << 29);

View File

@@ -18,144 +18,10 @@
#ifndef __AML_AUDIO_UTILS_H__
#define __AML_AUDIO_UTILS_H__
#include <linux/clk.h>
#include <linux/types.h>
#include <sound/soc.h>
#include <sound/tlv.h>
/* datain src
* [4]: pdmin;
* [3]: spdifin;
* [2]: tdmin_c;
* [1]: tdmin_b;
* [0]: tdmin_a;
*/
enum datain_src {
DATAIN_TDMA = 0,
DATAIN_TDMB,
DATAIN_TDMC,
DATAIN_SPDIF,
DATAIN_PDM,
};
/* datalb src/tdmlb src
* [0]: tdmoutA
* [1]: tdmoutB
* [2]: tdmoutC
* [3]: PAD_tdminA
* [4]: PAD_tdminB
* [5]: PAD_tdminC
*/
enum tdmin_lb_src {
TDMINLB_TDMOUTA = 0,
TDMINLB_TDMOUTB,
TDMINLB_TDMOUTC,
TDMINLB_PAD_TDMINA,
TDMINLB_PAD_TDMINB,
TDMINLB_PAD_TDMINC,
};
/* toddr_src_sel
* [7]: loopback;
* [6]: tdmin_lb;
* [5]: reserved;
* [4]: pdmin;
* [3]: spdifin;
* [2]: tdmin_c;
* [1]: tdmin_b;
* [0]: tdmin_a;
*/
enum fifoin_src {
FIFOIN_TDMINA = 0,
FIFOIN_TDMINB = 1,
FIFOIN_TDMINC = 2,
FIFOIN_SPDIF = 3,
FIFOIN_PDM = 4,
FIFOIN_TDMINLB = 6,
FIFOIN_LOOPBACK = 7
};
/* audio data selected to ddr */
struct audio_data {
unsigned int resample;
/* reg_dat_sel
* 0: combined data[m:n] without gap;
* like S0[m:n],S1[m:n],S2[m:n],
* 1: combined data[m:n] as 16bits;
* like {S0[11:0],4'd0},{S1[11:0],4'd0}
* 2: combined data[m:n] as 16bits;
* like {4'd0,S0[11:0]},{4'd0,{S1[11:0]}
* 3: combined data[m:n] as 32bits;
* like {S0[27:4],8'd0},{S1[27:4],8'd0}
* 4: combined data[m:n] as 32bits;
* like {8'd0,S0[27:4]},{8'd0,{S1[27:4]}
*/
unsigned int combined_type;
/* the msb positioin in data */
unsigned int msb;
/* the lsb position in data */
unsigned int lsb;
/* toddr_src_sel
* [7]: loopback;
* [6]: tdmin_lb;
* [5]: reserved;
* [4]: pdmin;
* [3]: spdifin;
* [2]: tdmin_c;
* [1]: tdmin_b;
* [0]: tdmin_a;
*/
unsigned int src;
};
/**/
struct loopback_cfg {
struct clk *tdmin_mpll;
/* lb_mode
* 0: out rate = in data rate;
* 1: out rate = loopback data rate;
*/
unsigned int lb_mode;
enum datain_src datain_src;
unsigned int datain_chnum;
unsigned int datain_chmask;
int toddr_index;
enum tdmin_lb_src datalb_src;
enum tdmin_lb_src datalb_clk;
unsigned int datalb_chnum;
unsigned int datalb_chswap;
unsigned int datalb_chmask;
int frddr_index;
unsigned int datain_datalb_total;
};
extern void loopback_set_status(int is_running);
extern int loopback_is_enable(void);
extern int loopback_check_enable(int src);
extern int snd_card_add_kcontrols(struct snd_soc_card *card);
extern int loopback_parse_of(struct device_node *node,
struct loopback_cfg *lb_cfg);
extern int loopback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct loopback_cfg *lb_cfg,
unsigned int mclk);
extern int loopback_prepare(
struct snd_pcm_substream *substream,
struct loopback_cfg *lb_cfg);
extern int loopback_trigger(
struct snd_pcm_substream *substream,
int cmd,
struct loopback_cfg *lb_cfg);
extern void audio_locker_set(int enable);
extern int audio_locker_get(void);

View File

@@ -69,7 +69,6 @@ struct aml_card_data {
int spk_mute_gpio;
bool spk_mute_active_low;
struct gpio_desc *avout_mute_desc;
struct loopback_cfg lb_cfg;
struct timer_list timer;
struct work_struct work;
struct work_struct init_work;
@@ -466,8 +465,6 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream,
goto err;
}
if (loopback_is_enable() && mclk)
loopback_hw_params(substream, params, &priv->lb_cfg, mclk);
return 0;
err:
return ret;
@@ -475,23 +472,11 @@ err:
int aml_card_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct aml_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
if (loopback_is_enable())
loopback_prepare(substream, &priv->lb_cfg);
return 0;
}
int aml_card_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct aml_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
if (loopback_is_enable())
loopback_trigger(substream, cmd, &priv->lb_cfg);
return 0;
}
@@ -802,7 +787,6 @@ static int aml_card_parse_of(struct device_node *node,
{
struct device *dev = aml_priv_to_dev(priv);
struct device_node *dai_link;
struct device_node *lb_link;
int ret;
if (!node)
@@ -829,14 +813,6 @@ static int aml_card_parse_of(struct device_node *node,
/* Factor to mclk, used in hw_params() */
of_property_read_u32(node, PREFIX "mclk-fs", &priv->mclk_fs);
/* Loopback */
lb_link = of_parse_phandle(node, PREFIX "loopback", 0);
if (lb_link) {
ret = loopback_parse_of(lb_link, &priv->lb_cfg);
if (ret < 0)
pr_err("failed parse loopback, ignore it\n");
}
/* Single/Muti DAI link(s) & New style of DT node */
if (dai_link) {
struct device_node *np = NULL;
@@ -867,12 +843,10 @@ static int aml_card_parse_of(struct device_node *node,
card_parse_end:
of_node_put(dai_link);
of_node_put(lb_link);
return ret;
}
static struct aml_chipset_info g12a_chipset_info = {
.spdif_b = true,
.eqdrc_fn = true,
@@ -922,6 +896,13 @@ static int aml_card_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
/* chipset related */
priv->chipinfo = (struct aml_chipset_info *)
of_device_get_match_data(&pdev->dev);
if (!priv->chipinfo)
pr_warn_once("check whether to update sound card init data\n");
dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
if (!dai_props || !dai_link)
@@ -979,13 +960,6 @@ static int aml_card_probe(struct platform_device *pdev)
sizeof(priv->dai_props->codec_dai));
}
priv->chipinfo = (struct aml_chipset_info *)
of_device_get_match_data(&pdev->dev);
if (!priv->chipinfo)
pr_warn_once("check whether to update sound card init data\n");
snd_soc_card_set_drvdata(&priv->snd_card, priv);
ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);

View File

@@ -29,7 +29,6 @@
#include "regs.h"
#include "ddr_mngr.h"
#include "audio_utils.h"
#include "resample.h"
#include "resample_hw.h"
@@ -134,12 +133,6 @@ static int unregister_toddr_l(struct device *dev, void *data)
to = &toddrs[i];
/* check for loopback */
if (to->is_lb) {
loopback_set_status(0);
to->is_lb = 0;
}
/* disable audio ddr arb */
mask_bit = i;
actrl = to->actrl;
@@ -366,13 +359,6 @@ void aml_toddr_select_src(struct toddr *to, enum toddr_src src)
/* store to check toddr num */
to->src = src;
/* check whether loopback enable */
if (loopback_check_enable(src)) {
loopback_set_status(1);
to->is_lb = 1; /* in loopback */
src = LOOPBACK_A;
}
if (to->chipinfo
&& to->chipinfo->src_sel_ctrl) {
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
@@ -456,6 +442,29 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
fmt->msb << 8 | fmt->lsb << 3);
}
unsigned int aml_toddr_get_status(struct toddr *to)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_STATUS1, reg_base);
return aml_audiobus_read(actrl, reg);
}
void aml_toddr_ack_irq(struct toddr *to, int status)
{
struct aml_audio_controller *actrl = to->actrl;
unsigned int reg_base = to->reg_base;
unsigned int reg;
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
aml_audiobus_update_bits(actrl, reg, MEMIF_INT_MASK, status);
aml_audiobus_update_bits(actrl, reg, MEMIF_INT_MASK, 0);
}
void aml_toddr_insert_chanum(struct toddr *to)
{
struct aml_audio_controller *actrl = to->actrl;

View File

@@ -23,6 +23,14 @@
#include <sound/soc.h>
#include "audio_io.h"
#define MEMIF_INT_ADDR_FINISH BIT(0)
#define MEMIF_INT_ADDR_INT BIT(1)
#define MEMIF_INT_COUNT_REPEAT BIT(2)
#define MEMIF_INT_COUNT_ONCE BIT(3)
#define MEMIF_INT_FIFO_ZERO BIT(4)
#define MEMIF_INT_FIFO_DEPTH BIT(5)
#define MEMIF_INT_MASK GENMASK(7, 0)
enum ddr_num {
DDR_A,
DDR_B,
@@ -104,27 +112,6 @@ struct toddr_fmt {
unsigned int rate;
};
#if 0
struct ddr_desc {
/* start address of DDR */
unsigned int start;
/* finish address of DDR */
unsigned int finish;
/* interrupt address or counts of DDR blocks */
unsigned int intrpt;
/* fifo total counts */
unsigned int fifo_depth;
/* fifo start threshold */
unsigned int fifo_thr;
enum ddr_types data_type;
unsigned int edian;
unsigned int pp_mode;
//unsigned int reg_base;
struct clk *ddr;
struct clk *ddr_arb;
};
#endif
struct ddr_chipinfo {
/* INT and Start address is same or separated */
bool int_start_same_addr;
@@ -170,7 +157,6 @@ struct ddr_chipinfo {
};
struct toddr {
//struct ddr_desc dscrpt;
struct device *dev;
unsigned int resample: 1;
unsigned int ext_signed: 1;
@@ -222,7 +208,6 @@ struct frddr_attach {
};
struct frddr {
//struct ddr_desc dscrpt;
struct device *dev;
enum frddr_dest dest;
@@ -244,7 +229,6 @@ struct frddr {
};
/* to ddrs */
int fetch_toddr_index_by_src(int toddr_src);
struct toddr *fetch_toddr_by_src(int toddr_src);
struct toddr *aml_audio_register_toddr(struct device *dev,
struct aml_audio_controller *actrl,
@@ -264,6 +248,10 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh);
void aml_toddr_update_fifos_rd_th(struct toddr *to, int th);
void aml_toddr_force_finish(struct toddr *to);
void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt);
unsigned int aml_toddr_get_status(struct toddr *to);
void aml_toddr_ack_irq(struct toddr *to, int status);
void aml_toddr_insert_chanum(struct toddr *to);
unsigned int aml_toddr_read(struct toddr *to);
void aml_toddr_write(struct toddr *to, unsigned int val);
@@ -280,7 +268,6 @@ void aml_pwrdet_enable(bool enable, int pwrdet_module);
void aml_set_vad(bool enable, int module);
/* from ddrs */
int fetch_frddr_index_by_src(int frddr_src);
struct frddr *fetch_frddr_by_src(int frddr_src);
struct frddr *aml_audio_register_frddr(struct device *dev,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/*
* sound/soc/amlogic/auge/loopback.h
*
* Copyright (C) 2018 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef __AML_AUDIO_LOOPBACK_H__
#define __AML_AUDIO_LOOPBACK_H__
#include <sound/soc.h>
#include <sound/tlv.h>
/* datain src
* [4]: pdmin;
* [3]: spdifin;
* [2]: tdmin_c;
* [1]: tdmin_b;
* [0]: tdmin_a;
*/
enum datain_src {
DATAIN_TDMA = 0,
DATAIN_TDMB,
DATAIN_TDMC,
DATAIN_SPDIF,
DATAIN_PDM,
DATAIN_LOOPBACK,
};
/* datalb src
* /tdmin_lb src
* [0]: tdmoutA
* [1]: tdmoutB
* [2]: tdmoutC
* [3]: PAD_tdminA
* [4]: PAD_tdminB
* [5]: PAD_tdminC
* /spdifin_lb src
* spdifout_a
* spdifout_b
*/
enum datalb_src {
TDMINLB_TDMOUTA = 0,
TDMINLB_TDMOUTB,
TDMINLB_TDMOUTC,
TDMINLB_PAD_TDMINA,
TDMINLB_PAD_TDMINB,
TDMINLB_PAD_TDMINC,
SPDIFINLB_SPDIFOUTA,
SPDIFINLB_SPDIFOUTB,
};
#endif

View File

@@ -14,193 +14,80 @@
* more details.
*
*/
#include <sound/soc.h>
#define DEBUG
#include "linux/kernel.h"
#include "regs.h"
#include "loopback_hw.h"
#include "regs.h"
#include "iomap.h"
void datain_config(struct data_in *datain)
{
audiobus_update_bits(
EE_AUDIO_LB_CTRL0,
1 << 29 | 0x7 << 24 | 0xff << 16 |
0x7 << 13 | 0x1f << 8 | 0x1f << 3 |
0x7 << 0,
datain->config->ext_signed << 29 |
(datain->config->chnum - 1) << 24 |
datain->config->chmask << 16 |
datain->ddrdata->combined_type << 13 |
datain->ddrdata->msb << 8 |
datain->ddrdata->lsb << 3 |
datain->ddrdata->src << 0
);
}
void datalb_config(struct data_lb *datalb)
void tdminlb_set_clk(int datatlb_src, int sclk_div, int ratio, bool enable)
{
audiobus_write(
EE_AUDIO_LB_CTRL1,
datalb->config->ext_signed << 29 |
(datalb->config->chnum - 1) << 24 |
datalb->config->chmask << 16 |
datalb->ddr_type << 13 |
datalb->msb << 8 |
datalb->lsb << 3
);
}
unsigned int bclk_sel, fsclk_sel;
unsigned int tdmin_src;
void datalb_ctrl(struct loopback_cfg *lb_cfg)
{
int id = lb_cfg->datalb_src;
int offset = 0;
int reg, reg_base;
/* config for external codec */
if (datatlb_src >= 3) {
unsigned int clk_id = datatlb_src - 3;
unsigned int offset, reg;
unsigned int fsclk_hi;
fsclk_hi = ratio / 2;
bclk_sel = clk_id;
fsclk_sel = clk_id;
/*sclk, lrclk*/
offset = EE_AUDIO_MST_B_SCLK_CTRL0 - EE_AUDIO_MST_A_SCLK_CTRL0;
reg = EE_AUDIO_MST_A_SCLK_CTRL0 + offset * clk_id;
audiobus_update_bits(reg,
0x3 << 30 | 0x3ff << 20 | 0x3ff<<10 | 0x3ff,
(enable ? 0x3 : 0x0) << 30
| sclk_div << 20 | fsclk_hi << 10
| ratio);
tdmin_src = datatlb_src - 3;
} else
tdmin_src = datatlb_src;
audiobus_update_bits(
EE_AUDIO_TDMIN_LB_CTRL,
0xf << 28 | 0xf << 20 | 0x7 << 16 | 0x1f << 0,
1 << 31 |
/*0:tdm mode; 1: i2s mode;*/
1 << 30 |
1 << 29 |
1 << 28 |
lb_cfg->datalb_src << 20 |
3 << 16|
31 << 0
);
if (id >= 0 && id <= 2) {
/* tdmout_a, tdmout_b, tdmout_c */
reg_base = EE_AUDIO_TDMOUT_A_SWAP0;
offset = EE_AUDIO_TDMOUT_B_SWAP0 - EE_AUDIO_TDMOUT_A_SWAP0;
} else if (id < 6) {
/*lb_cfg->datalb_src for pad tdm in,
*pad from tdmin_a, tdmin_b, tdmin_c
*/
/* id offset from tdmin_a */
id -= 3;
reg_base = EE_AUDIO_TDMIN_A_CTRL;
offset = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg = reg_base + offset * id;
audiobus_update_bits(reg, 3<<28, 0);
audiobus_update_bits(reg, 1<<29, 1<<29);
audiobus_update_bits(reg, 1<<28, 1<<28);
/* just assume lb from tdm in is i2s mode */
audiobus_update_bits(
reg,
0xf << 28 | 0xf << 20 | 0x7 << 16 | 0x1f << 0,
1 << 31 |
/* 0:tdm mode; 1: i2s mode */
1 << 30 |
1 << 29 |
1 << 28 |
id << 20 |
3 << 16|
31 << 0
);
pr_info("reg:0x%x, EE_AUDIO_TDMIN_A_CTRL:0x%x\n",
reg,
audiobus_read(EE_AUDIO_TDMIN_A_CTRL));
/* swap */
reg += 1;
audiobus_write(
reg,
lb_cfg->datalb_chswap);
/* mask 0 */
reg += 1;
audiobus_write(
reg,
lb_cfg->datalb_chmask);
reg_base = EE_AUDIO_TDMIN_A_SWAP0;
offset = EE_AUDIO_TDMIN_B_SWAP0 - EE_AUDIO_TDMIN_A_SWAP0;
} else {
pr_err("unsupport datalb_src\n");
return;
}
if (lb_cfg->datain_datalb_total > 8) {
audiobus_write(
EE_AUDIO_TDMIN_LB_SWAP0,
lb_cfg->datalb_chswap);
audiobus_write(EE_AUDIO_TDMIN_LB_MASK0, 3);
audiobus_write(EE_AUDIO_TDMIN_LB_MASK1, 3);
audiobus_write(EE_AUDIO_TDMIN_LB_MASK2, 3);
audiobus_write(EE_AUDIO_TDMIN_LB_MASK3, 3);
} else {
/*swap same as tdmout */
reg = reg_base + offset * id;
audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0,
audiobus_read(reg));
/*mask same as datalb*/
/* mask 0 */
reg += 1;
audiobus_write(
EE_AUDIO_TDMIN_LB_MASK0,
audiobus_read(reg));
/* mask 1 */
reg += 1;
audiobus_write(
EE_AUDIO_TDMIN_LB_MASK1,
audiobus_read(reg));
/* mask 2 */
reg += 1;
audiobus_write(
EE_AUDIO_TDMIN_LB_MASK2,
audiobus_read(reg));
/* mask 3 */
reg += 1;
audiobus_write(
EE_AUDIO_TDMIN_LB_MASK3,
audiobus_read(reg));
}
EE_AUDIO_CLK_TDMIN_LB_CTRL,
0x3 << 30 | 1 << 29 | 0xf << 24 | 0xf << 20,
(enable ? 0x3 : 0x0) << 30 |
1 << 29 | tdmin_src << 24 | tdmin_src << 20
);
}
void lb_mode(int mode)
void tdminlb_enable(int tdm_index, int is_enable)
{
// TODO:
return;
#if 0
audiobus_update_bits(
EE_AUDIO_LB_CTRL0,
0x1 << 30,
mode << 30
);
#endif
}
static void tdmin_lb_clk_enalbe(int tdm_src, int is_enable)
{
if (tdm_src <= 2)
audiobus_update_bits(
EE_AUDIO_CLK_TDMIN_LB_CTRL,
0x3 << 30 | 1 << 29 | 0xf << 24 | 0xf << 20,
0x3 << 30 | 1 << 29 | tdm_src << 24 | tdm_src << 20
);
else
pr_warn_once("pad from tdmin_a, tdmin_b, tdmin_c needs clks\n");
}
void tdmin_lb_enable(int tdm_index, int is_enable)
{
if (is_enable)
tdmin_lb_clk_enalbe(tdm_index, is_enable);
audiobus_update_bits(
EE_AUDIO_TDMIN_LB_CTRL,
0x1 << 31,
is_enable << 31);
}
void tdmin_lb_fifo_enable(int is_enable)
void tdminlb_set_format(int i2s_fmt)
{
audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL,
0x1 << 30,
i2s_fmt << 30 /* 0:tdm mode; 1: i2s mode; */
);
}
void tdminlb_set_ctrl(int src)
{
audiobus_update_bits(
EE_AUDIO_TDMIN_LB_CTRL,
0xf << 20 | 0x7 << 16 | 0x1f << 0,
src << 20 | /* in src */
3 << 16 | /* skew */
31 << 0 /* bit width */
);
}
void tdminlb_fifo_enable(int is_enable)
{
if (is_enable) {
audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL, 1<<29, 1<<29);
@@ -209,39 +96,123 @@ void tdmin_lb_fifo_enable(int is_enable)
audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL, 3<<28, 0);
}
void lb_set_datain_src(int src)
static void tdminlb_set_lane_mask(int lane, int mask)
{
audiobus_write(EE_AUDIO_TDMIN_LB_MASK0 + lane, mask);
}
void lb_set_tdminlb_src(int src)
void tdminlb_set_lanemask_and_chswap(int swap, int lane_mask)
{
unsigned int mask;
unsigned int i;
pr_debug("tdmin_lb lane swap:0x%x mask:0x%x\n", swap, lane_mask);
mask = 0x3; /* i2s format */
/* channel swap */
audiobus_write(EE_AUDIO_TDMIN_LB_SWAP0, swap);
/* lane mask */
for (i = 0; i < 4; i++)
if ((1 << i) & lane_mask)
tdminlb_set_lane_mask(i, mask);
}
void lb_set_tdminlb_enable(bool is_enable)
void tdminlb_set_src(int src)
{
audiobus_update_bits(EE_AUDIO_TDMIN_LB_CTRL, 0xf << 20, src);
}
int lb_is_enable(void)
void lb_set_datain_src(int id, int src)
{
return (audiobus_read(EE_AUDIO_LB_CTRL0) & 0x80000000) >> 31;
int offset = EE_AUDIO_LB_B_CTRL0 - EE_AUDIO_LB_A_CTRL0;
int reg = EE_AUDIO_LB_A_CTRL0 + offset * id;
audiobus_update_bits(reg, 0x7 << 0, src);
}
void lb_enable(bool is_enable)
void lb_set_datain_cfg(int id, struct data_cfg *datain_cfg)
{
audiobus_update_bits(
EE_AUDIO_LB_CTRL0,
0x1 << 31,
is_enable << 31
int offset = EE_AUDIO_LB_B_CTRL0 - EE_AUDIO_LB_A_CTRL0;
int reg = EE_AUDIO_LB_A_CTRL0 + offset * id;
if (!datain_cfg)
return;
if (datain_cfg->ch_ctrl_switch) {
audiobus_update_bits(reg,
1 << 29 | 0x7 << 13 | 0x1f << 8 | 0x1f << 3 | 0x7 << 0,
datain_cfg->ext_signed << 29 |
datain_cfg->type << 13 |
datain_cfg->m << 8 |
datain_cfg->n << 3 |
datain_cfg->src << 0
);
/* channel and mask */
offset = EE_AUDIO_LB_B_CTRL2 - EE_AUDIO_LB_A_CTRL2;
reg = EE_AUDIO_LB_A_CTRL2 + offset * id;
audiobus_write(reg,
(datain_cfg->chnum - 1) << 16 |
datain_cfg->chmask << 0
);
} else
audiobus_update_bits(reg,
1 << 29 | 0x7 << 24 | 0xff << 16 |
0x7 << 13 | 0x1f << 8 | 0x1f << 3 |
0x7 << 0,
datain_cfg->ext_signed << 29 |
(datain_cfg->chnum - 1) << 24 |
datain_cfg->chmask << 16 |
datain_cfg->type << 13 |
datain_cfg->m << 8 |
datain_cfg->n << 3 |
datain_cfg->src << 0
);
}
void lb_set_mode(int mode)
void lb_set_datalb_cfg(int id, struct data_cfg *datalb_cfg)
{
audiobus_update_bits(
EE_AUDIO_LB_CTRL0,
0x1 << 30,
mode << 30
int offset = EE_AUDIO_LB_B_CTRL1 - EE_AUDIO_LB_A_CTRL1;
int reg = EE_AUDIO_LB_A_CTRL1 + offset * id;
if (!datalb_cfg)
return;
if (datalb_cfg->ch_ctrl_switch) {
audiobus_update_bits(reg,
0x1 << 29 | 0x7 << 13 | 0x1f << 8
| 0x1f << 3 | 0x1 << 1,
datalb_cfg->ext_signed << 29 |
datalb_cfg->type << 13 |
datalb_cfg->m << 8 |
datalb_cfg->n << 3 |
datalb_cfg->datalb_src << 0
);
/* channel and mask */
offset = EE_AUDIO_LB_B_CTRL3 - EE_AUDIO_LB_A_CTRL3;
reg = EE_AUDIO_LB_A_CTRL3 + offset * id;
audiobus_write(reg,
(datalb_cfg->chnum - 1) << 16 |
datalb_cfg->chmask << 0
);
} else
audiobus_write(reg,
datalb_cfg->ext_signed << 29 |
(datalb_cfg->chnum - 1) << 24 |
datalb_cfg->chmask << 16 |
datalb_cfg->type << 13 |
datalb_cfg->m << 8 |
datalb_cfg->n << 3
);
}
void lb_enable(int id, bool enable)
{
int offset = EE_AUDIO_LB_B_CTRL0 - EE_AUDIO_LB_A_CTRL0;
int reg = EE_AUDIO_LB_A_CTRL0 + offset * id;
audiobus_update_bits(reg, 0x1 << 31, enable << 31);
}

View File

@@ -18,54 +18,55 @@
#ifndef __AML_LOOPBACK_HW_H__
#define __AML_LOOPBACK_HW_H__
#include "audio_utils.h"
#include <linux/types.h>
struct lb_cfg {
struct data_cfg {
/*
* 0: extend bits as "0"
* 1: extend bits as "msb"
*/
unsigned int ext_signed;
/* total channel number */
/* channel number */
unsigned int chnum;
/* which channel is selected for loopback */
/* channel selected */
unsigned int chmask;
/* combined data */
unsigned int type;
/* the msb positioin in data */
unsigned int m;
/* the lsb position in data */
unsigned int n;
/* loopback datalb src */
unsigned int src;
unsigned int datalb_src;
/* channel and mask in new ctrol register */
bool ch_ctrl_switch;
};
struct data_in {
struct lb_cfg *config;
struct audio_data *ddrdata;
};
extern void tdminlb_set_clk(int datatlb_src,
int sclk_div, int ratio, bool enable);
struct data_lb {
struct lb_cfg *config;
unsigned int ddr_type;
unsigned int msb;
unsigned int lsb;
};
extern void tdminlb_set_format(int i2s_fmt);
struct loopback {
struct device *dev;
unsigned int lb_mode;
extern void tdminlb_set_ctrl(int src);
struct data_in *datain;
struct data_lb *datalb;
};
extern void tdminlb_enable(int tdm_index, int in_enable);
extern void tdminlb_fifo_enable(int is_enable);
extern void tdminlb_set_format(int i2s_fmt);
extern void tdminlb_set_lanemask_and_chswap(int swap, int lane_mask);
extern void datain_config(struct data_in *datain);
extern void tdminlb_set_src(int src);
extern void lb_set_datain_src(int id, int src);
extern void datalb_config(struct data_lb *datalb);
extern void lb_set_datain_cfg(int id, struct data_cfg *datain_cfg);
extern void lb_set_datalb_cfg(int id, struct data_cfg *datalb_cfg);
extern void datalb_ctrl(struct loopback_cfg *lb_cfg);
extern void lb_enable(int id, bool enable);
extern int lb_is_enable(void);
extern void lb_enable(bool is_enable);
extern void lb_mode(int mode);
extern void tdmin_lb_enable(int tdm_index, int in_enable);
extern void tdmin_lb_fifo_enable(int is_enable);
#endif

View File

@@ -0,0 +1,104 @@
/*
* sound/soc/amlogic/auge/loopback_match_table.c
*
* Copyright (C) 2019 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#define LOOPBACKA 0
#define LOOPBACKB 1
struct loopback_chipinfo {
unsigned int id;
/* reset all modules, after g12a
* it has reset bits control for modules
*/
bool is_reset_all;
/* channel and mask switch to ctrl2, ctrl3 from tl1
* for datain, 0: channel and mask is controlled by ctrl0
* 1: channel and mask is controlled by ctrl2
* for datalb, 0: channel and mask is controlled by ctrl1
* 1: channel and mask is controlled by ctrl3
*/
bool ch_ctrl;
};
static struct loopback_chipinfo tl1_loopbacka_chipinfo = {
.id = LOOPBACKA,
.ch_ctrl = true,
};
static struct loopback_chipinfo tl1_loopbackb_chipinfo = {
.id = LOOPBACKB,
.ch_ctrl = true,
};
static struct loopback_chipinfo sm1_loopbacka_chipinfo = {
.id = LOOPBACKA,
.ch_ctrl = true,
};
static struct loopback_chipinfo sm1_loopbackb_chipinfo = {
.id = LOOPBACKB,
.ch_ctrl = true,
};
static struct loopback_chipinfo tm2_loopbacka_chipinfo = {
.id = LOOPBACKA,
.ch_ctrl = true,
};
static struct loopback_chipinfo tm2_loopbackb_chipinfo = {
.id = LOOPBACKB,
.ch_ctrl = true,
};
static const struct of_device_id loopback_device_id[] = {
{
.compatible = "amlogic, snd-loopback",
},
{
.compatible = "amlogic, axg-loopback",
},
{
.compatible = "amlogic, g12a-loopback",
},
{
.compatible = "amlogic, tl1-loopbacka",
.data = &tl1_loopbacka_chipinfo,
},
{
.compatible = "amlogic, tl1-loopbackb",
.data = &tl1_loopbackb_chipinfo,
},
{
.compatible = "amlogic, sm1-loopbacka",
.data = &sm1_loopbacka_chipinfo,
},
{
.compatible = "amlogic, sm1-loopbackb",
.data = &sm1_loopbackb_chipinfo,
},
{
.compatible = "amlogic, tm2-loopbacka",
.data = &tm2_loopbacka_chipinfo,
},
{
.compatible = "amlogic, tm2-loopbackb",
.data = &tm2_loopbackb_chipinfo,
},
{}
};
MODULE_DEVICE_TABLE(of, loopback_device_id);

View File

@@ -76,8 +76,6 @@ static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
.mask = 0
};
static int s_pdm_filter_mode;
static const char *const pdm_filter_mode_texts[] = {
"Filter Mode 0",
"Filter Mode 1",
@@ -94,7 +92,13 @@ static int aml_pdm_filter_mode_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = s_pdm_filter_mode;
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
ucontrol->value.enumerated.item[0] = p_pdm->filter_mode;
return 0;
}
@@ -103,7 +107,13 @@ static int aml_pdm_filter_mode_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
s_pdm_filter_mode = ucontrol->value.enumerated.item[0];
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
p_pdm->filter_mode = ucontrol->value.enumerated.item[0];
return 0;
}
@@ -137,8 +147,6 @@ static int pdm_hcic_shift_gain_set_enum(
return 0;
}
int pdm_dclk;
static const char *const pdm_dclk_texts[] = {
"PDM Dclk 3.072m, support 8k/16k/32k/48k/64k/96k",
"PDM Dclk 1.024m, support 8k/16k",
@@ -153,7 +161,13 @@ static int pdm_dclk_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = pdm_dclk;
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
ucontrol->value.enumerated.item[0] = p_pdm->dclk_idx;
return 0;
}
@@ -162,7 +176,56 @@ static int pdm_dclk_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pdm_dclk = ucontrol->value.enumerated.item[0];
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
p_pdm->dclk_idx = ucontrol->value.enumerated.item[0];
return 0;
}
static const char *const pdm_bypass_texts[] = {
"PCM Data",
"Raw Data/Bypass Data",
};
static const struct soc_enum pdm_bypass_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pdm_bypass_texts),
pdm_bypass_texts);
static int pdm_bypass_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
ucontrol->value.enumerated.item[0] = p_pdm->bypass;
return 0;
}
static int pdm_bypass_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
p_pdm->bypass = ucontrol->value.enumerated.item[0];
if (p_pdm->clk_on)
pdm_set_bypass_data((bool)p_pdm->bypass);
return 0;
}
@@ -180,8 +243,11 @@ static int pdm_train_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm)
return 0;
ucontrol->value.enumerated.item[0] = p_pdm->train_en;
@@ -192,10 +258,11 @@ static int pdm_train_set_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
if (!p_pdm->chipinfo ||
if (!p_pdm ||
!p_pdm->chipinfo ||
!p_pdm->chipinfo->train ||
(p_pdm->train_en == ucontrol->value.enumerated.item[0]))
return 0;
@@ -230,6 +297,11 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = {
pdm_train_enum,
pdm_train_get_enum,
pdm_train_set_enum),
SOC_ENUM_EXT("PDM Bypass",
pdm_bypass_enum,
pdm_bypass_get_enum,
pdm_bypass_set_enum),
};
#if 0
@@ -252,7 +324,7 @@ static int pdm_mute_val_get(struct snd_kcontrol *kcontrol,
val = pdm_get_mute_value();
ucontrol->value.integer.value[0] = val;
pr_info("%s:get mute_val:0x%x\n",
pr_info("%s, get mute_val:0x%x\n",
__func__,
val);
@@ -264,7 +336,7 @@ static int pdm_mute_val_set(struct snd_kcontrol *kcontrol,
{
int val = (int)ucontrol->value.integer.value[0];
pr_info("%s:set mute_val:0x%x\n",
pr_info("%s, set mute_val:0x%x\n",
__func__,
val);
@@ -302,7 +374,7 @@ static int pdm_mute_chmask_get(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = val;
pr_info("%s:get pdm channel mask val:0x%x\n",
pr_info("%s, get pdm channel mask val:0x%x\n",
__func__,
val);
@@ -319,7 +391,7 @@ static int pdm_mute_chmask_set(struct snd_kcontrol *kcontrol,
if (val > 255)
val = 255;
pr_info("%s:set pdm channel mask val:0x%x\n",
pr_info("%s, set pdm channel mask val:0x%x\n",
__func__,
val);
@@ -379,11 +451,25 @@ static irqreturn_t aml_pdm_isr_handler(int irq, void *data)
{
struct snd_pcm_substream *substream =
(struct snd_pcm_substream *)data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->platform->dev;
struct aml_pdm *p_pdm = (struct aml_pdm *)dev_get_drvdata(dev);
unsigned int status;
int train_sts = pdm_train_sts();
pr_debug("%s\n", __func__);
snd_pcm_period_elapsed(substream);
if (!snd_pcm_running(substream))
return IRQ_NONE;
status = aml_toddr_get_status(p_pdm->tddr) & MEMIF_INT_MASK;
if (status & MEMIF_INT_COUNT_REPEAT) {
snd_pcm_period_elapsed(substream);
aml_toddr_ack_irq(p_pdm->tddr, MEMIF_INT_COUNT_REPEAT);
} else
dev_dbg(dev, "unexpected irq - STS 0x%02x\n",
status);
if (train_sts) {
pr_debug("%s train result:0x%x\n",
@@ -392,7 +478,7 @@ static irqreturn_t aml_pdm_isr_handler(int irq, void *data)
pdm_train_clr();
}
return IRQ_HANDLED;
return !status ? IRQ_NONE : IRQ_HANDLED;
}
static int aml_pdm_open(struct snd_pcm_substream *substream)
@@ -404,7 +490,7 @@ static int aml_pdm_open(struct snd_pcm_substream *substream)
dev_get_drvdata(dev);
int ret;
pr_info("%s, stream:%d\n",
pr_debug("%s, stream:%d\n",
__func__, substream->stream);
snd_soc_set_runtime_hwparams(substream, &aml_pdm_hardware);
@@ -453,7 +539,7 @@ static int aml_pdm_close(struct snd_pcm_substream *substream)
struct device *dev = rtd->platform->dev;
struct aml_pdm *p_pdm = (struct aml_pdm *)dev_get_drvdata(dev);
pr_info("enter %s type: %d\n",
pr_debug("enter %s type: %d\n",
__func__, substream->stream);
aml_audio_unregister_toddr(p_pdm->dev, substream);
@@ -469,7 +555,7 @@ static int aml_pdm_hw_params(
struct snd_pcm_runtime *runtime = substream->runtime;
int ret = 0;
pr_info("enter %s\n", __func__);
pr_debug("enter %s\n", __func__);
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = params_buffer_bytes(params);
@@ -480,7 +566,7 @@ static int aml_pdm_hw_params(
static int aml_pdm_hw_free(struct snd_pcm_substream *substream)
{
pr_info("%s\n", __func__);
pr_debug("%s\n", __func__);
snd_pcm_lib_free_pages(substream);
return 0;
@@ -547,7 +633,7 @@ static int aml_pdm_silence(
unsigned char *ppos = NULL;
ssize_t n;
pr_info("%s\n", __func__);
pr_debug("%s\n", __func__);
n = frames_to_bytes(runtime, count);
ppos = runtime->dma_area + frames_to_bytes(runtime, pos);
@@ -564,7 +650,7 @@ static int aml_pdm_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
int size = aml_pdm_hardware.buffer_bytes_max;
int ret = -EINVAL;
pr_info("%s dai->name: %s dai->id: %d\n",
pr_debug("%s dai->name: %s dai->id: %d\n",
__func__, dai->name, dai->id);
/* only capture for PDM */
@@ -586,7 +672,7 @@ static void aml_pdm_pcm_free(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
pr_info("%s\n", __func__);
pr_debug("%s\n", __func__);
substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
if (substream) {
@@ -611,7 +697,7 @@ static struct snd_pcm_ops aml_pdm_ops = {
static int aml_pdm_probe(struct snd_soc_platform *platform)
{
pr_info("%s\n", __func__);
pr_debug("%s\n", __func__);
return 0;
}
@@ -638,7 +724,6 @@ static int aml_pdm_dai_set_fmt(
return 0;
}
static int aml_pdm_dai_prepare(
struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
@@ -652,6 +737,8 @@ static int aml_pdm_dai_prepare(
&& pm_audio_is_suspend())
return 0;
p_pdm->rate = runtime->rate;
/* set bclk */
bitwidth = snd_pcm_format_width(runtime->format);
lsb = 32 - bitwidth;
@@ -670,17 +757,16 @@ static int aml_pdm_dai_prepare(
return -1;
}
pr_info("%s rate:%d, bits:%d, channels:%d\n",
pr_debug("%s rate:%d, bits:%d, channels:%d\n",
__func__,
runtime->rate,
bitwidth,
runtime->channels);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
struct toddr *to = p_pdm->tddr;
struct toddr_fmt fmt;
unsigned int osr = 192;
unsigned int osr = 192, filter_mode;
struct pdm_info info;
/* to ddr pdmin */
@@ -698,49 +784,27 @@ static int aml_pdm_dai_prepare(
info.bitdepth = bitwidth;
info.channels = runtime->channels;
info.lane_masks = p_pdm->lane_mask_in;
info.dclk_idx = pdm_dclk;
info.dclk_idx = p_pdm->dclk_idx;
info.bypass = p_pdm->bypass;
info.sample_count = pdm_get_sample_count(p_pdm->isLowPower,
p_pdm->dclk_idx);
aml_pdm_ctrl(&info);
filter_mode = p_pdm->filter_mode;
/* filter for pdm */
if (pdm_dclk == 1) {
if (runtime->rate == 16000)
osr = 64;
else if (runtime->rate == 8000)
osr = 128;
else {
pr_err("Not support rate:%d\n", runtime->rate);
return -EINVAL;
}
} else if (pdm_dclk == 2) {
if (runtime->rate == 16000)
osr = 48;
else if (runtime->rate == 8000)
osr = 96;
else {
pr_err("Not support rate:%d\n", runtime->rate);
return -EINVAL;
}
} else {
if (runtime->rate == 96000)
osr = 32;
else if (runtime->rate == 64000)
osr = 48;
else if (runtime->rate == 48000)
osr = 64;
else if (runtime->rate == 32000)
osr = 96;
else if (runtime->rate == 16000)
osr = 192;
else if (runtime->rate == 8000)
osr = 384;
else {
pr_err("Not support rate:%d\n", runtime->rate);
return -EINVAL;
}
}
p_pdm->filter_mode = s_pdm_filter_mode;
aml_pdm_filter_ctrl(osr, p_pdm->filter_mode);
osr = pdm_get_ors(p_pdm->dclk_idx, runtime->rate);
if (!osr)
return -EINVAL;
pr_info("%s, pdm_dclk:%d, osr:%d, rate:%d filter mode:%d\n",
__func__,
pdm_dclkidx2rate(p_pdm->dclk_idx),
osr,
runtime->rate,
p_pdm->filter_mode);
aml_pdm_filter_ctrl(osr, filter_mode);
if (p_pdm->chipinfo && p_pdm->chipinfo->truncate_data)
pdm_init_truncate_data(runtime->rate);
@@ -755,7 +819,7 @@ static int aml_pdm_dai_trigger(
{
struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
pr_info("%s, cmd:%d\n", __func__, cmd);
pr_debug("%s\n", __func__);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -773,7 +837,7 @@ static int aml_pdm_dai_trigger(
pdm_fifo_reset();
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
dev_info(substream->pcm->card->dev, "pdm capture start\n");
dev_info(substream->pcm->card->dev, "PDM Capture start\n");
aml_toddr_enable(p_pdm->tddr, 1);
pdm_enable(1);
}
@@ -820,37 +884,21 @@ static int aml_pdm_dai_set_sysclk(struct snd_soc_dai *cpu_dai,
if (dclk_srcpll_freq == 0)
clk_set_rate(p_pdm->dclk_srcpll, 24576000);
else
pr_info("pdm dclk_srcpll:%lu\n",
clk_get_rate(p_pdm->dclk_srcpll));
#endif
if (pdm_dclk == 1)
clk_set_rate(p_pdm->clk_pdm_dclk, 1024000);
else if (pdm_dclk == 2)
clk_set_rate(p_pdm->clk_pdm_dclk, 768000);
else
clk_set_rate(p_pdm->clk_pdm_dclk, 3072000);
clk_set_rate(p_pdm->clk_pdm_dclk,
pdm_dclkidx2rate(p_pdm->dclk_idx));
pr_info("pdm pdm_sysclk:%lu clk_pdm_dclk:%lu\n",
pr_info("\n%s, pdm_sysclk:%lu pdm_dclk:%lu, dclk_srcpll:%lu\n",
__func__,
clk_get_rate(p_pdm->clk_pdm_sysclk),
clk_get_rate(p_pdm->clk_pdm_dclk));
clk_get_rate(p_pdm->clk_pdm_dclk),
clk_get_rate(p_pdm->dclk_srcpll));
return 0;
}
static int aml_pdm_dai_probe(struct snd_soc_dai *cpu_dai)
{
int ret = 0;
ret = snd_soc_add_dai_controls(cpu_dai, snd_pdm_controls,
ARRAY_SIZE(snd_pdm_controls));
if (ret < 0) {
pr_err("%s, failed add snd pdm controls\n", __func__);
return ret;
}
pr_info("%s\n", __func__);
return 0;
}
@@ -919,6 +967,7 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream,
#endif
p_pdm->clk_on = false;
p_pdm->rate = 0;
/* disable clock and gate */
clk_disable_unprepare(p_pdm->clk_pdm_dclk);
@@ -955,6 +1004,8 @@ EXPORT_SYMBOL_GPL(aml_pdm_dai);
static const struct snd_soc_component_driver aml_pdm_component = {
.name = DRV_NAME,
.controls = snd_pdm_controls,
.num_controls = ARRAY_SIZE(snd_pdm_controls),
};
static int snd_soc_of_get_slot_mask(
@@ -1094,9 +1145,6 @@ static int aml_pdm_platform_probe(struct platform_device *pdev)
/* defulat set 1 */
p_pdm->filter_mode = 1;
}
s_pdm_filter_mode = p_pdm->filter_mode;
pr_info("%s pdm filter mode from dts:%d\n",
__func__, p_pdm->filter_mode);
p_pdm->dev = dev;
dev_set_drvdata(&pdev->dev, p_pdm);
@@ -1126,10 +1174,10 @@ err:
static int aml_pdm_platform_remove(struct platform_device *pdev)
{
struct aml_pdm *pdm_priv = dev_get_drvdata(&pdev->dev);
struct aml_pdm *p_pdm = dev_get_drvdata(&pdev->dev);
clk_disable_unprepare(pdm_priv->sysclk_srcpll);
clk_disable_unprepare(pdm_priv->clk_pdm_dclk);
clk_disable_unprepare(p_pdm->sysclk_srcpll);
clk_disable_unprepare(p_pdm->clk_pdm_dclk);
snd_soc_unregister_component(&pdev->dev);

View File

@@ -30,7 +30,6 @@
/* 8ch pdm in, 8 ch tdmin_lb */
#define PDM_CHANNELS_LB_MAX (PDM_CHANNELS_MAX + 8)
#define PDM_RATES (SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_64000 |\
SNDRV_PCM_RATE_48000 |\
@@ -70,6 +69,8 @@ struct aml_pdm {
struct clk *clk_pdm_sysclk;
struct clk *clk_pdm_dclk;
struct toddr *tddr;
/* sample rate */
int rate;
/*
* filter mode:0~4,
* from mode 0 to 4, the performance is from high to low,
@@ -90,6 +91,9 @@ struct aml_pdm {
/* train */
bool train_en;
/* low power mode, for dclk_sycpll to 24m */
bool isLowPower;
struct pdm_chipinfo *chipinfo;
struct snd_kcontrol *controls[PDM_RUN_MAX];
};

View File

@@ -70,22 +70,28 @@ void pdm_fifo_reset(void)
0x1 << 16);
}
void pdm_set_channel_ctrl(int sample_count)
{
aml_pdm_write(PDM_CHAN_CTRL, ((sample_count << 24) |
(sample_count << 16) |
(sample_count << 8) |
(sample_count << 0)
));
aml_pdm_write(PDM_CHAN_CTRL1, ((sample_count << 24) |
(sample_count << 16) |
(sample_count << 8) |
(sample_count << 0)
));
}
void aml_pdm_ctrl(struct pdm_info *info)
{
int mode, i, ch_mask = 0, sample_count;
int mode, i, ch_mask = 0;
int pdm_chs, lane_chs = 0;
if (!info)
return;
/* sameple count */
if (info->dclk_idx == 1)
sample_count = 38;
else if (info->dclk_idx == 2)
sample_count = 48;
else
sample_count = 18;
if (info->bitdepth == 32)
mode = 0;
else
@@ -124,7 +130,6 @@ void aml_pdm_ctrl(struct pdm_info *info)
/* must be sure that clk and pdm is enable */
aml_pdm_update_bits(PDM_CTRL,
(0x7 << 28 | 0xff << 8 | 0xff << 0),
/*(1 << 31) |*/
/* invert the PDM_DCLK or not */
(0 << 30) |
/* output mode: 1: 24bits. 0: 32 bits */
@@ -139,16 +144,7 @@ void aml_pdm_ctrl(struct pdm_info *info)
(ch_mask << 0)
);
aml_pdm_write(PDM_CHAN_CTRL, ((sample_count << 24) |
(sample_count << 16) |
(sample_count << 8) |
(sample_count << 0)
));
aml_pdm_write(PDM_CHAN_CTRL1, ((sample_count << 24) |
(sample_count << 16) |
(sample_count << 8) |
(sample_count << 0)
));
pdm_set_channel_ctrl(info->sample_count);
}
void aml_pdm_arb_config(struct aml_audio_controller *actrl)
@@ -351,9 +347,6 @@ void aml_pdm_filter_ctrl(int osr, int mode)
int lpf1_len, lpf2_len, lpf3_len;
const int *lpf1_coeff, *lpf2_coeff, *lpf3_coeff;
pr_info("%s, osr:%d, mode:%d\n",
__func__, osr, mode);
/* select LPF coefficent
* For filter 1 and filter 3,
* it's only relative with coefficent mode
@@ -489,6 +482,11 @@ void pdm_set_mute_channel(int mute_chmask)
(mute_chmask << 20 | mute_en << 17));
}
void pdm_set_bypass_data(bool bypass)
{
aml_pdm_update_bits(PDM_CTRL, 0x1 << 28, bypass << 28);
}
void pdm_init_truncate_data(int freq)
{
int mask_val;
@@ -519,3 +517,71 @@ int pdm_train_sts(void)
return ((val >> 4) & 0xff);
}
int pdm_dclkidx2rate(int idx)
{
int rate;
if (idx == 2)
rate = 768000;
else if (idx == 1)
rate = 1024000;
else
rate = 3072000;
return rate;
}
int pdm_get_sample_count(int isLowPower, int dclk_idx)
{
int count = 0;
if (isLowPower)
count = 0;
else if (dclk_idx == 1)
count = 38;
else if (dclk_idx == 2)
count = 48;
else
count = 18;
return count;
}
int pdm_get_ors(int dclk_idx, int sample_rate)
{
int osr = 0;
if (dclk_idx == 1) {
if (sample_rate == 16000)
osr = 64;
else if (sample_rate == 8000)
osr = 128;
else
pr_err("Not support rate:%d\n", sample_rate);
} else if (dclk_idx == 2) {
if (sample_rate == 16000)
osr = 48;
else if (sample_rate == 8000)
osr = 96;
else
pr_err("Not support rate:%d\n", sample_rate);
} else {
if (sample_rate == 96000)
osr = 32;
else if (sample_rate == 64000)
osr = 48;
else if (sample_rate == 48000)
osr = 64;
else if (sample_rate == 32000)
osr = 96;
else if (sample_rate == 16000)
osr = 192;
else if (sample_rate == 8000)
osr = 384;
else
pr_err("Not support rate:%d\n", sample_rate);
}
return osr;
}

View File

@@ -29,6 +29,7 @@ struct pdm_info {
int dclk_idx; /* mapping for dclk value */
int bypass; /* bypass all filter, capture raw data */
int sample_count;
};
extern void aml_pdm_ctrl(struct pdm_info *info);
@@ -47,14 +48,20 @@ extern int pdm_get_mute_value(void);
extern void pdm_set_mute_value(int val);
extern int pdm_get_mute_channel(void);
extern void pdm_set_mute_channel(int mute_chmask);
extern void pdm_set_bypass_data(bool bypass);
extern void pdm_init_truncate_data(int freq);
extern void pdm_train_en(bool en);
extern void pdm_train_clr(void);
extern int pdm_train_sts(void);
extern int pdm_dclkidx2rate(int idx);
extern int pdm_get_sample_count(int isLowPower, int dclk_idx);
extern int pdm_get_ors(int dclk_idx, int sample_rate);
extern void pdm_train_en(bool en);
extern void pdm_train_clr(void);
extern int pdm_train_sts(void);
extern int pdm_hcic_shift_gain;
extern int pdm_dclk;
#endif /*__AML_PDM_HW_H__*/

View File

@@ -197,16 +197,41 @@ enum clk_sel {
#define EE_AUDIO_ARB_CTRL 0x0a0
/*
* AUDIO TDM
* AUDIO LOOPBACK
*/
#define EE_AUDIO_LB_CTRL0 0x0b0
#define EE_AUDIO_LB_CTRL1 0x0b1
#define EE_AUDIO_DAT_ID0 0x0b2
#define EE_AUDIO_DAT_ID1 0x0b3
#define EE_AUDIO_LB_ID0 0x0b4
#define EE_AUDIO_LB_ID1 0x0b5
#define EE_AUDIO_LB_STS 0x0b6
#define EE_AUDIO_LB_A_CTRL0 0xb0
#define EE_AUDIO_LB_A_CTRL1 0xb1
#define EE_AUDIO_LB_A_CTRL2 0xb2
#define EE_AUDIO_LB_A_CTRL3 0xb3
#define EE_AUDIO_LB_A_DAT_CH_ID0 0xb4
#define EE_AUDIO_LB_A_DAT_CH_ID1 0xb5
#define EE_AUDIO_LB_A_DAT_CH_ID2 0xb6
#define EE_AUDIO_LB_A_DAT_CH_ID3 0xb7
#define EE_AUDIO_LB_A_LB_CH_ID0 0xb8
#define EE_AUDIO_LB_A_LB_CH_ID1 0xb9
#define EE_AUDIO_LB_A_LB_CH_ID2 0xba
#define EE_AUDIO_LB_A_LB_CH_ID3 0xbb
#define EE_AUDIO_LB_A_STS 0xbc
#define EE_AUDIO_LB_B_CTRL0 0x230
#define EE_AUDIO_LB_B_CTRL1 0x231
#define EE_AUDIO_LB_B_CTRL2 0x232
#define EE_AUDIO_LB_B_CTRL3 0x233
#define EE_AUDIO_LB_B_DAT_CH_ID0 0x234
#define EE_AUDIO_LB_B_DAT_CH_ID1 0x235
#define EE_AUDIO_LB_B_DAT_CH_ID2 0x236
#define EE_AUDIO_LB_B_DAT_CH_ID3 0x237
#define EE_AUDIO_LB_B_LB_CH_ID0 0x238
#define EE_AUDIO_LB_B_LB_CH_ID1 0x239
#define EE_AUDIO_LB_B_LB_CH_ID2 0x23a
#define EE_AUDIO_LB_B_LB_CH_ID3 0x23b
#define EE_AUDIO_LB_B_STS 0x23c
/*
* AUDIO TDM
*/
#define EE_AUDIO_TDMIN_A_CTRL 0x0c0
#define EE_AUDIO_TDMIN_A_SWAP0 0x0c1
#define EE_AUDIO_TDMIN_A_SWAP1 0x260
@@ -544,20 +569,6 @@ enum clk_sel {
#define EE_AUDIO_FRDDR_D_INIT_ADDR 0x229
#define EE_AUDIO_FRDDR_D_CTRL2 0x22a
#define EE_AUDIO_LB_B_CTRL0 0x230
#define EE_AUDIO_LB_B_CTRL1 0x231
#define EE_AUDIO_LB_B_CTRL2 0x232
#define EE_AUDIO_LB_B_CTRL3 0x233
#define EE_AUDIO_LB_B_DAT_CH_ID0 0x234
#define EE_AUDIO_LB_B_DAT_CH_ID1 0x235
#define EE_AUDIO_LB_B_DAT_CH_ID2 0x236
#define EE_AUDIO_LB_B_DAT_CH_ID3 0x237
#define EE_AUDIO_LB_B_LB_CH_ID0 0x238
#define EE_AUDIO_LB_B_LB_CH_ID1 0x239
#define EE_AUDIO_LB_B_LB_CH_ID2 0x23a
#define EE_AUDIO_LB_B_LB_CH_ID3 0x23b
#define EE_AUDIO_LB_B_STS 0x23c
/*
* AUDIO LOCKER
*/

View File

@@ -36,7 +36,6 @@
#include "ddr_mngr.h"
#include "spdif_hw.h"
#include "spdif_match_table.c"
#include "audio_utils.h"
#include "resample.h"
#include "resample_hw.h"
@@ -1163,50 +1162,30 @@ static int aml_dai_spdif_prepare(
struct toddr_fmt fmt;
unsigned int msb, lsb, toddr_type;
if (loopback_is_enable()) {
switch (bit_depth) {
case 8:
case 16:
case 32:
toddr_type = 0;
break;
case 24:
toddr_type = 4;
break;
default:
pr_err(
"runtime format invalid bit_depth: %d\n",
bit_depth);
return -EINVAL;
}
msb = 32 - 1;
lsb = 32 - bit_depth;
} else {
switch (bit_depth) {
case 8:
case 16:
toddr_type = 0;
break;
case 24:
toddr_type = 4;
break;
case 32:
toddr_type = 3;
break;
default:
dev_err(p_spdif->dev,
"runtime format invalid bit_depth: %d\n",
bit_depth);
return -EINVAL;
}
msb = 28 - 1;
if (bit_depth <= 24)
lsb = 28 - bit_depth;
else
lsb = 4;
switch (bit_depth) {
case 8:
case 16:
toddr_type = 0;
break;
case 24:
toddr_type = 4;
break;
case 32:
toddr_type = 3;
break;
default:
dev_err(p_spdif->dev,
"runtime format invalid bit_depth: %d\n",
bit_depth);
return -EINVAL;
}
msb = 28 - 1;
if (bit_depth <= 24)
lsb = 28 - bit_depth;
else
lsb = 4;
// to ddr spdifin
fmt.type = toddr_type;
fmt.msb = msb;

View File

@@ -107,6 +107,9 @@ struct aml_tdm {
bool en_share;
unsigned int lane_cnt;
/* tdmin_lb src sel */
int tdmin_lb_src;
};
static const struct snd_pcm_hardware aml_tdm_hardware = {
@@ -537,6 +540,9 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
case 2:
src = TDMIN_C;
break;
case 3:
src = TDMIN_LB;
break;
default:
dev_err(p_tdm->dev, "invalid id: %d\n",
p_tdm->id);
@@ -935,7 +941,7 @@ static int aml_dai_tdm_hw_free(struct snd_pcm_substream *substream,
struct frddr *fr = p_tdm->fddr;
int i;
for (i = 0; i < 4; i++)
for (i = 0; i < p_tdm->lane_cnt; i++)
aml_tdm_set_channel_mask(p_tdm->actrl,
substream->stream, p_tdm->id, i, 0);
@@ -1178,20 +1184,15 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
oe_val = p_tdm->setting.lane_oe_mask_out;
}
if (lanes_lb_cnt) {
in_src = p_tdm->id + 6;
if (in_src > 7) {
pr_err("unknown src(%d) for tdmin\n", in_src);
return -EINVAL;
}
}
if (lanes_lb_cnt)
in_src = p_tdm->tdmin_lb_src;
if (lanes_oe_in_cnt)
in_src = p_tdm->id + 3;
if (lanes_in_cnt)
in_src = p_tdm->id;
} else {
if (lanes_lb_cnt)
in_src = p_tdm->id + 3;
in_src = p_tdm->tdmin_lb_src;
if (lanes_in_cnt && lanes_in_cnt <= 4)
in_src = p_tdm->id;
if (in_src > 5) {
@@ -1310,69 +1311,85 @@ static struct snd_soc_dai_ops aml_dai_tdm_ops = {
static struct snd_soc_dai_driver aml_tdm_dai[] = {
{
.name = "TDM-A",
.id = 1,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
.name = "TDM-A",
.id = 1,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
},
{
.name = "TDM-B",
.id = 2,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
.name = "TDM-B",
.id = 2,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
},
{
.name = "TDM-C",
.id = 3,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
.name = "TDM-C",
.id = 3,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.playback = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
},
{
.name = "TDMIN-LB",
.id = 4,
.probe = aml_dai_tdm_probe,
.remove = aml_dai_tdm_remove,
.capture = {
.channels_min = 1,
.channels_max = 32,
.rates = AML_DAI_TDM_RATES,
.formats = AML_DAI_TDM_FORMATS,
},
.ops = &aml_dai_tdm_ops,
.symmetric_rates = 1,
}
};
static const struct snd_soc_component_driver aml_tdm_component = {
.name = DRV_NAME,
.name = DRV_NAME,
};
static int check_channel_mask(const char *str)
@@ -1520,9 +1537,23 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
&p_tdm->i2s2hdmitx);
if (ret < 0)
p_tdm->i2s2hdmitx = 0;
pr_info("TDM id %d i2s2hdmi:%d\n",
p_tdm->id,
p_tdm->i2s2hdmitx);
else
pr_info("TDM id %d i2s2hdmi:%d\n",
p_tdm->id,
p_tdm->i2s2hdmitx);
if (p_tdm->id == TDM_LB) {
ret = of_property_read_u32(node, "lb-src-sel",
&p_tdm->tdmin_lb_src);
if (ret < 0 || (p_tdm->tdmin_lb_src > 7)) {
dev_err(&pdev->dev, "invalid lb-src-sel:%d\n",
p_tdm->tdmin_lb_src);
return -EINVAL;
}
pr_info("TDM id %d lb-src-sel:%d\n",
p_tdm->id,
p_tdm->tdmin_lb_src);
}
/* get tdm lanes info. if not, set to default 0 */
ret = of_parse_tdm_lane_slot_in(node,
@@ -1594,6 +1625,12 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
/*set default clk for output*/
aml_set_default_tdm_clk(p_tdm);
/* mclk pad ctrl */
ret = of_property_read_u32(node, "mclk_pad",
&p_tdm->mclk_pad);
if (ret < 0)
p_tdm->mclk_pad = -1; /* not use mclk in defalut. */
p_tdm->dev = dev;
/* For debug to disable share buffer */
p_tdm->en_share = 1;

View File

@@ -24,6 +24,7 @@
#define TDM_A 0
#define TDM_B 1
#define TDM_C 2
#define TDM_LB 3
#define LANE_MAX0 2
#define LANE_MAX1 4

View File

@@ -60,6 +60,11 @@ struct tdm_chipinfo axg_tdmc_chipinfo = {
.no_mclkpad_ctrl = true,
};
struct tdm_chipinfo axg_tdminlb_chipinfo = {
.id = TDM_LB,
.no_mclkpad_ctrl = true,
};
struct tdm_chipinfo g12a_tdma_chipinfo = {
.id = TDM_A,
.sclk_ws_inv = true,
@@ -84,6 +89,14 @@ struct tdm_chipinfo g12a_tdmc_chipinfo = {
.mclkpad_no_offset = true,
};
struct tdm_chipinfo g12a_tdminlb_chipinfo = {
.id = TDM_LB,
.sclk_ws_inv = true,
.oe_fn = true,
.same_src_fn = true,
.mclkpad_no_offset = true,
};
struct tdm_chipinfo tl1_tdma_chipinfo = {
.id = TDM_A,
.sclk_ws_inv = true,
@@ -108,6 +121,14 @@ struct tdm_chipinfo tl1_tdmc_chipinfo = {
.adc_fn = true,
};
struct tdm_chipinfo tl1_tdminlb_chipinfo = {
.id = TDM_LB,
.sclk_ws_inv = true,
.oe_fn = true,
.same_src_fn = true,
.adc_fn = true,
};
struct tdm_chipinfo sm1_tdma_chipinfo = {
.id = TDM_A,
.sclk_ws_inv = true,
@@ -132,6 +153,14 @@ struct tdm_chipinfo sm1_tdmc_chipinfo = {
.lane_cnt = LANE_MAX1,
};
struct tdm_chipinfo sm1_tdminlb_chipinfo = {
.id = TDM_LB,
.sclk_ws_inv = true,
.oe_fn = true,
.same_src_fn = true,
.lane_cnt = LANE_MAX3,
};
struct tdm_chipinfo tm2_tdma_chipinfo = {
.id = TDM_A,
.sclk_ws_inv = true,
@@ -159,6 +188,14 @@ struct tdm_chipinfo tm2_tdmc_chipinfo = {
.lane_cnt = LANE_MAX1,
};
struct tdm_chipinfo tm2_tdminlb_chipinfo = {
.id = TDM_LB,
.sclk_ws_inv = true,
.oe_fn = true,
.same_src_fn = true,
.lane_cnt = LANE_MAX3,
};
static const struct of_device_id aml_tdm_device_id[] = {
{
.compatible = "amlogic, axg-snd-tdma",
@@ -172,6 +209,10 @@ static const struct of_device_id aml_tdm_device_id[] = {
.compatible = "amlogic, axg-snd-tdmc",
.data = &axg_tdmc_chipinfo,
},
{
.compatible = "amlogic, axg-snd-tdmlb",
.data = &axg_tdminlb_chipinfo,
},
{
.compatible = "amlogic, g12a-snd-tdma",
.data = &g12a_tdma_chipinfo,
@@ -184,6 +225,10 @@ static const struct of_device_id aml_tdm_device_id[] = {
.compatible = "amlogic, g12a-snd-tdmc",
.data = &g12a_tdmc_chipinfo,
},
{
.compatible = "amlogic, g12a-snd-tdmlb",
.data = &g12a_tdminlb_chipinfo,
},
{
.compatible = "amlogic, tl1-snd-tdma",
.data = &tl1_tdma_chipinfo,
@@ -196,29 +241,41 @@ static const struct of_device_id aml_tdm_device_id[] = {
.compatible = "amlogic, tl1-snd-tdmc",
.data = &tl1_tdmc_chipinfo,
},
{
.compatible = "amlogic, tl1-snd-tdmlb",
.data = &tl1_tdminlb_chipinfo,
},
{
.compatible = "amlogic, sm1-snd-tdma",
.data = &sm1_tdma_chipinfo,
.data = &sm1_tdma_chipinfo,
},
{
.compatible = "amlogic, sm1-snd-tdmb",
.data = &sm1_tdmb_chipinfo,
.data = &sm1_tdmb_chipinfo,
},
{
.compatible = "amlogic, sm1-snd-tdmc",
.data = &sm1_tdmc_chipinfo,
.data = &sm1_tdmc_chipinfo,
},
{
.compatible = "amlogic, sm1-snd-tdmlb",
.data = &sm1_tdminlb_chipinfo,
},
{
.compatible = "amlogic, tm2-snd-tdma",
.data = &tm2_tdma_chipinfo,
.data = &tm2_tdma_chipinfo,
},
{
.compatible = "amlogic, tm2-snd-tdmb",
.data = &tm2_tdmb_chipinfo,
.data = &tm2_tdmb_chipinfo,
},
{
.compatible = "amlogic, tm2-snd-tdmc",
.data = &tm2_tdmc_chipinfo,
.data = &tm2_tdmc_chipinfo,
},
{
.compatible = "amlogic, tm2-snd-tdmlb",
.data = &tm2_tdminlb_chipinfo,
},
{},
};

View File

@@ -34,18 +34,19 @@ static void ad82584f_early_suspend(struct early_suspend *h);
static void ad82584f_late_resume(struct early_suspend *h);
#endif
#define AD82584F_RATES (SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_64000 | \
SNDRV_PCM_RATE_88200 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_176400 | \
SNDRV_PCM_RATE_192000)
#define AD82584F_RATES (SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | \
SNDRV_PCM_RATE_64000 | \
SNDRV_PCM_RATE_88200 | \
SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_176400 | \
SNDRV_PCM_RATE_192000)
#define AD82584F_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -10300, 50, 1);
static const DECLARE_TLV_DB_SCALE(chvol_tlv, -10300, 50, 1);