mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
audio: auge: fix spdif in & out work at the same time for ASRC
PD#163795: audio: auge: fix spdif in & out work at the same time for ASRC 1. fix spdifin toddr as right_j for asrc, not support asrc 32bit now 2. fix clk dir for set_sysclk 3. auto enable/disable asrc when switch raw data and pcm data source 4. fix lr channel swap when replug in 5. detect spdifin sample mode by max_width 6. force to clear spdif in sample rate irq bit for axg 7. enable spdif in for s420 boards Change-Id: I83dc211815068b9d073fb20433c76ce9f129b40e Signed-off-by: Xing Wang <xing.wang@amlogic.com>
This commit is contained in:
@@ -1158,6 +1158,20 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pdm: pdm {
|
||||
@@ -1242,7 +1256,7 @@
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <4>;
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pwrdet: pwrdet {
|
||||
@@ -1266,7 +1280,7 @@
|
||||
hi_th = <0x70000>;
|
||||
lo_th = <0x16000>;
|
||||
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
|
||||
@@ -1139,6 +1139,20 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pdm: pdm {
|
||||
@@ -1206,6 +1220,49 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pwrdet: pwrdet {
|
||||
compatible = "amlogic, axg-power-detect";
|
||||
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "pwrdet_irq";
|
||||
|
||||
/* pwrdet source sel
|
||||
* 7: loopback;
|
||||
* 6: tdmin_lb;
|
||||
* 5: reserved;
|
||||
* 4: pdmin;
|
||||
* 3: spdifin;
|
||||
* 2: tdmin_c;
|
||||
* 1: tdmin_b;
|
||||
* 0: tdmin_a;
|
||||
*/
|
||||
pwrdet_src = <4>;
|
||||
|
||||
hi_th = <0x70000>;
|
||||
lo_th = <0x16000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -1016,6 +1016,20 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pdm: pdm {
|
||||
@@ -1080,6 +1094,49 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pwrdet: pwrdet {
|
||||
compatible = "amlogic, axg-power-detect";
|
||||
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "pwrdet_irq";
|
||||
|
||||
/* pwrdet source sel
|
||||
* 7: loopback;
|
||||
* 6: tdmin_lb;
|
||||
* 5: reserved;
|
||||
* 4: pdmin;
|
||||
* 3: spdifin;
|
||||
* 2: tdmin_c;
|
||||
* 1: tdmin_b;
|
||||
* 0: tdmin_a;
|
||||
*/
|
||||
pwrdet_src = <4>;
|
||||
|
||||
hi_th = <0x70000>;
|
||||
lo_th = <0x16000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -1060,6 +1060,20 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pdm: pdm {
|
||||
@@ -1124,6 +1138,49 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pwrdet: pwrdet {
|
||||
compatible = "amlogic, axg-power-detect";
|
||||
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "pwrdet_irq";
|
||||
|
||||
/* pwrdet source sel
|
||||
* 7: loopback;
|
||||
* 6: tdmin_lb;
|
||||
* 5: reserved;
|
||||
* 4: pdmin;
|
||||
* 3: spdifin;
|
||||
* 2: tdmin_c;
|
||||
* 1: tdmin_b;
|
||||
* 0: tdmin_a;
|
||||
*/
|
||||
pwrdet_src = <4>;
|
||||
|
||||
hi_th = <0x70000>;
|
||||
lo_th = <0x16000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -1026,6 +1026,20 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pdm: pdm {
|
||||
@@ -1090,6 +1104,49 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
aml_pwrdet: pwrdet {
|
||||
compatible = "amlogic, axg-power-detect";
|
||||
|
||||
interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "pwrdet_irq";
|
||||
|
||||
/* pwrdet source sel
|
||||
* 7: loopback;
|
||||
* 6: tdmin_lb;
|
||||
* 5: reserved;
|
||||
* 4: pdmin;
|
||||
* 3: spdifin;
|
||||
* 2: tdmin_c;
|
||||
* 1: tdmin_b;
|
||||
* 0: tdmin_a;
|
||||
*/
|
||||
pwrdet_src = <4>;
|
||||
|
||||
hi_th = <0x70000>;
|
||||
lo_th = <0x16000>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -434,16 +434,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
/*aml-audio-card,dai-link@4 {
|
||||
* mclk-fs = <128>;
|
||||
* cpu {
|
||||
* sound-dai = <&aml_spdif>;
|
||||
* };
|
||||
* codec {
|
||||
* sound-dai = <&dummy_codec>;
|
||||
* };
|
||||
*};
|
||||
*/
|
||||
aml-audio-card,dai-link@4 {
|
||||
mclk-fs = <128>;
|
||||
cpu {
|
||||
sound-dai = <&aml_spdif>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&dummy_codec>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
bt-dev{
|
||||
@@ -955,7 +954,21 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
status = "disabled";
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aml_pdm: pdm {
|
||||
@@ -1020,6 +1033,26 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -425,16 +425,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
/*aml-audio-card,dai-link@4 {
|
||||
* mclk-fs = <128>;
|
||||
* cpu {
|
||||
* sound-dai = <&aml_spdif>;
|
||||
* };
|
||||
* codec {
|
||||
* sound-dai = <&dummy_codec>;
|
||||
* };
|
||||
*};
|
||||
*/
|
||||
aml-audio-card,dai-link@4 {
|
||||
mclk-fs = <128>;
|
||||
cpu {
|
||||
sound-dai = <&aml_spdif>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&dummy_codec>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
bt-dev{
|
||||
@@ -822,7 +821,21 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
status = "disabled";
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aml_pdm: pdm {
|
||||
@@ -886,6 +899,26 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -437,16 +437,15 @@
|
||||
};
|
||||
};
|
||||
|
||||
/*aml-audio-card,dai-link@4 {
|
||||
* mclk-fs = <128>;
|
||||
* cpu {
|
||||
* sound-dai = <&aml_spdif>;
|
||||
* };
|
||||
* codec {
|
||||
* sound-dai = <&dummy_codec>;
|
||||
* };
|
||||
*};
|
||||
*/
|
||||
aml-audio-card,dai-link@4 {
|
||||
mclk-fs = <128>;
|
||||
cpu {
|
||||
sound-dai = <&aml_spdif>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&dummy_codec>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
bt-dev{
|
||||
@@ -960,7 +959,21 @@
|
||||
interrupt-names = "irq_spdifin";
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout &spdifin>;
|
||||
status = "disabled";
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm.
|
||||
* if raw data, asrc is disabled automatically
|
||||
* 0: "Disable",
|
||||
* 1: "Enable:32K",
|
||||
* 2: "Enable:44K",
|
||||
* 3: "Enable:48K",
|
||||
* 4: "Enable:88K",
|
||||
* 5: "Enable:96K",
|
||||
* 6: "Enable:176K",
|
||||
* 7: "Enable:192K",
|
||||
*/
|
||||
auto_asrc = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aml_pdm: pdm {
|
||||
@@ -1026,6 +1039,26 @@
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
audioresample: resample {
|
||||
compatible = "amlogic, axg-resample";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_CTRL>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A,
|
||||
* TDMIN_B,
|
||||
* TDMIN_C,
|
||||
* SPDIFIN,
|
||||
* PDMIN,
|
||||
* NONE,
|
||||
* TDMIN_LB,
|
||||
* LOOPBACK,
|
||||
*/
|
||||
resample_module = <3>;
|
||||
status = "okay";
|
||||
};
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
@@ -433,6 +433,12 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream,
|
||||
aml_priv_to_props(priv, rtd->num);
|
||||
unsigned int mclk = 0, mclk_fs = 0;
|
||||
int i = 0, ret = 0;
|
||||
int clk_dir = 0;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
clk_dir = SND_SOC_CLOCK_OUT;
|
||||
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
clk_dir = SND_SOC_CLOCK_IN;
|
||||
|
||||
if (priv->mclk_fs)
|
||||
mclk_fs = priv->mclk_fs;
|
||||
@@ -444,16 +450,15 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
for (i = 0; i < rtd->num_codecs; i++) {
|
||||
codec_dai = rtd->codec_dais[i];
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
|
||||
SND_SOC_CLOCK_IN);
|
||||
clk_dir);
|
||||
|
||||
if (ret && ret != -ENOTSUPP)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
|
||||
SND_SOC_CLOCK_OUT);
|
||||
clk_dir);
|
||||
if (ret && ret != -ENOTSUPP)
|
||||
goto err;
|
||||
|
||||
|
||||
@@ -74,8 +74,9 @@ struct toddr {
|
||||
unsigned int msb_bit;
|
||||
unsigned int lsb_bit;
|
||||
unsigned int reg_base;
|
||||
unsigned int channels;
|
||||
unsigned int bitdepth;
|
||||
unsigned int channels;
|
||||
unsigned int rate;
|
||||
enum toddr_src src;
|
||||
unsigned int fifo_id;
|
||||
|
||||
@@ -129,14 +130,17 @@ static struct toddr toddrs[DDRMAX];
|
||||
/* resample */
|
||||
static struct toddr_attach attach_resample;
|
||||
static void aml_check_resample(bool enable);
|
||||
static bool aml_check_resample_module(int src);
|
||||
|
||||
/* power detect */
|
||||
static struct toddr_attach attach_pwrdet;
|
||||
static void aml_check_pwrdet(bool enable);
|
||||
static bool aml_check_pwrdet_module(int src);
|
||||
|
||||
/* Audio EQ DRC */
|
||||
static struct frddr_attach attach_aed;
|
||||
static void aml_check_aed(bool enable, int dst);
|
||||
static bool aml_check_aed_module(int dst);
|
||||
|
||||
/* to DDRS */
|
||||
static struct toddr *register_toddr_l(struct device *dev,
|
||||
@@ -341,10 +345,15 @@ void aml_toddr_enable(struct toddr *to, bool enable)
|
||||
aml_audiobus_update_bits(actrl, reg, 1<<31, enable<<31);
|
||||
|
||||
/* check resample */
|
||||
aml_check_resample(enable);
|
||||
if (aml_check_resample_module(to->src))
|
||||
aml_check_resample(enable);
|
||||
|
||||
/* check power detect */
|
||||
aml_check_pwrdet(enable);
|
||||
if (aml_check_pwrdet_module(to->src))
|
||||
aml_check_pwrdet(enable);
|
||||
|
||||
if (!enable)
|
||||
aml_audiobus_write(actrl, reg, 0x0);
|
||||
}
|
||||
|
||||
void aml_toddr_select_src(struct toddr *to, enum toddr_src src)
|
||||
@@ -377,84 +386,170 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh)
|
||||
aml_audiobus_write(actrl, reg, (thresh-1)<<16|2<<8);
|
||||
}
|
||||
|
||||
void aml_toddr_set_format(struct toddr *to,
|
||||
unsigned int type, unsigned int msb, unsigned int lsb,
|
||||
int ch_num, int bit_depth)
|
||||
void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
|
||||
{
|
||||
struct aml_audio_controller *actrl = to->actrl;
|
||||
unsigned int reg_base = to->reg_base;
|
||||
unsigned int reg;
|
||||
|
||||
to->channels = ch_num;
|
||||
to->bitdepth = bit_depth;
|
||||
to->bitdepth = fmt->bit_depth;
|
||||
to->channels = fmt->ch_num;
|
||||
to->rate = fmt->rate;
|
||||
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 0x1fff<<3,
|
||||
type<<13|msb<<8|lsb<<3);
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
0x7 << 24 | 0x1fff << 3,
|
||||
fmt->endian << 24 | fmt->type << 13 |
|
||||
fmt->msb << 8 | fmt->lsb << 3);
|
||||
}
|
||||
|
||||
void aml_toddr_insert_chanum(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_CTRL1, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 1 << 24, 1 << 24);
|
||||
}
|
||||
|
||||
unsigned int aml_toddr_read(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_CTRL0, reg_base);
|
||||
|
||||
return aml_audiobus_read(actrl, reg);
|
||||
}
|
||||
|
||||
void aml_toddr_write(struct toddr *to, unsigned int val)
|
||||
{
|
||||
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_CTRL0, reg_base);
|
||||
|
||||
aml_audiobus_write(actrl, reg, val);
|
||||
}
|
||||
|
||||
void aml_toddr_set_resample(struct toddr *to, bool enable)
|
||||
{
|
||||
struct aml_audio_controller *actrl = to->actrl;
|
||||
unsigned int reg_base = to->reg_base;
|
||||
unsigned int reg;
|
||||
|
||||
pr_info("toddr selects data to %s resample\n",
|
||||
enable ? "enable" : "disable");
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30);
|
||||
}
|
||||
|
||||
static void aml_set_resample(struct toddr *to,
|
||||
bool enable)
|
||||
{
|
||||
struct aml_audio_controller *actrl = to->actrl;
|
||||
unsigned int reg_base = to->reg_base;
|
||||
unsigned int reg;
|
||||
|
||||
if (enable) {
|
||||
int bitwidth = to->bitdepth;
|
||||
/* channels and bit depth for resample */
|
||||
resample_format_set(to->channels, to->bitdepth);
|
||||
if ((to->src == SPDIFIN) && (bitwidth == 32)) {
|
||||
struct aml_audio_controller *actrl = to->actrl;
|
||||
unsigned int reg_base = to->reg_base;
|
||||
unsigned int reg;
|
||||
unsigned int endian, toddr_type;
|
||||
|
||||
/* TODO: fixed me */
|
||||
pr_info("Warning: Not support 32bit sample rate for axg chipset\n");
|
||||
bitwidth = 24;
|
||||
endian = 5;
|
||||
toddr_type = 4;
|
||||
|
||||
/* FIX ME */
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0,
|
||||
reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
0x7 << 24 | 0x7 << 13,
|
||||
endian << 24 | toddr_type << 13);
|
||||
}
|
||||
resample_format_set(to->channels, bitwidth);
|
||||
|
||||
/* toddr index for resample */
|
||||
resample_src_select(to->fifo_id);
|
||||
}
|
||||
|
||||
/* resample enable or not */
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 0x1 << 30, enable << 30);
|
||||
resample_enable(enable);
|
||||
/* select reample data */
|
||||
aml_toddr_set_resample(to, enable);
|
||||
}
|
||||
|
||||
void aml_resample_enable(bool enable, int resample_module)
|
||||
{
|
||||
/* when try to enable resample, if toddr is not in used,
|
||||
* set resample status as ready
|
||||
*/
|
||||
attach_resample.enable = enable;
|
||||
attach_resample.attach_module = resample_module;
|
||||
if (enable) {
|
||||
if ((attach_resample.status == DISABLED)
|
||||
|| (attach_resample.status == READY)) {
|
||||
struct toddr *to = fetch_toddr_by_src(resample_module);
|
||||
|
||||
if (!to) {
|
||||
attach_resample.status = READY;
|
||||
pr_info("not in capture, resample is ready");
|
||||
} else {
|
||||
attach_resample.status = RUNNING;
|
||||
aml_set_resample(to, enable);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (attach_resample.status == RUNNING) {
|
||||
struct toddr *to = fetch_toddr_by_src(resample_module);
|
||||
|
||||
aml_set_resample(to, enable);
|
||||
}
|
||||
attach_resample.status = DISABLED;
|
||||
}
|
||||
aml_check_resample(enable);
|
||||
}
|
||||
|
||||
static bool aml_check_resample_module(int src)
|
||||
{
|
||||
bool is_module_resample = false;
|
||||
|
||||
if (attach_resample.enable
|
||||
&& (src == attach_resample.attach_module))
|
||||
is_module_resample = true;
|
||||
|
||||
return is_module_resample;
|
||||
}
|
||||
|
||||
/*
|
||||
* when try to enable resample, if toddr is not in used,
|
||||
* set resample status as ready
|
||||
*/
|
||||
static void aml_check_resample(bool enable)
|
||||
{
|
||||
/* resample in enable */
|
||||
if (attach_resample.enable) {
|
||||
if (enable) {
|
||||
/* check whether ready ? */
|
||||
if (attach_resample.status == READY)
|
||||
aml_resample_enable(true,
|
||||
if ((attach_resample.status == DISABLED)
|
||||
|| (attach_resample.status == READY)) {
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
attach_resample.attach_module);
|
||||
|
||||
if (!to) {
|
||||
attach_resample.status = READY;
|
||||
pr_info("not in capture, Resample is ready\n");
|
||||
} else {
|
||||
attach_resample.status = RUNNING;
|
||||
aml_set_resample(to, enable);
|
||||
pr_info("Resample in running, module:%d, toddr:%d\n",
|
||||
attach_resample.attach_module,
|
||||
to->fifo_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (attach_resample.status == RUNNING)
|
||||
attach_resample.status = READY;
|
||||
if (attach_resample.status == RUNNING) {
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
attach_resample.attach_module);
|
||||
|
||||
aml_set_resample(to, enable);
|
||||
attach_resample.status = DISABLED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* ensure resample is disabled */
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
attach_resample.attach_module);
|
||||
|
||||
if (to) {
|
||||
pr_info("Resample in running, disable it\n");
|
||||
|
||||
/* select reample data */
|
||||
aml_toddr_set_resample(to, false);
|
||||
/* update resample status */
|
||||
attach_resample.status = DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -490,7 +585,7 @@ void aml_pwrdet_enable(bool enable, int pwrdet_module)
|
||||
|
||||
if (!to) {
|
||||
attach_pwrdet.status = READY;
|
||||
pr_info("not in capture, power detect is ready");
|
||||
pr_info("not in capture, power detect is ready\n");
|
||||
} else {
|
||||
attach_pwrdet.status = RUNNING;
|
||||
aml_set_pwrdet(to, enable);
|
||||
@@ -506,6 +601,17 @@ void aml_pwrdet_enable(bool enable, int pwrdet_module)
|
||||
}
|
||||
}
|
||||
|
||||
static bool aml_check_pwrdet_module(int src)
|
||||
{
|
||||
bool is_module_pwrdet = false;
|
||||
|
||||
if (attach_pwrdet.enable
|
||||
&& (src == attach_pwrdet.attach_module))
|
||||
is_module_pwrdet = true;
|
||||
|
||||
return is_module_pwrdet;
|
||||
}
|
||||
|
||||
static void aml_check_pwrdet(bool enable)
|
||||
{
|
||||
/* power detect in enable */
|
||||
@@ -746,7 +852,8 @@ void aml_frddr_enable(struct frddr *fr, bool enable)
|
||||
aml_audiobus_write(actrl, reg, 0x0);
|
||||
|
||||
/* check for Audio EQ/DRC */
|
||||
aml_check_aed(enable, fr->dest);
|
||||
if (aml_check_aed_module(fr->dest))
|
||||
aml_check_aed(enable, fr->dest);
|
||||
}
|
||||
|
||||
void aml_frddr_select_dst(struct frddr *fr, enum frddr_dest dst)
|
||||
@@ -868,6 +975,17 @@ void aml_aed_enable(bool enable, int aed_module)
|
||||
}
|
||||
}
|
||||
|
||||
static bool aml_check_aed_module(int dst)
|
||||
{
|
||||
bool is_module_aed = false;
|
||||
|
||||
if (attach_aed.enable
|
||||
&& (dst == attach_aed.attach_module))
|
||||
is_module_aed = true;
|
||||
|
||||
return is_module_aed;
|
||||
}
|
||||
|
||||
static void aml_check_aed(bool enable, int dst)
|
||||
{
|
||||
/* check effect module is sync with crruent frddr dst */
|
||||
|
||||
@@ -55,6 +55,16 @@ enum frddr_dest {
|
||||
SPDIFOUT_B,
|
||||
};
|
||||
|
||||
struct toddr_fmt {
|
||||
unsigned int type;
|
||||
unsigned int msb;
|
||||
unsigned int lsb;
|
||||
unsigned int endian;
|
||||
unsigned int bit_depth;
|
||||
unsigned int ch_num;
|
||||
unsigned int rate;
|
||||
};
|
||||
|
||||
/* to ddrs */
|
||||
int fetch_toddr_index_by_src(int toddr_src);
|
||||
struct toddr *fetch_toddr_by_src(int toddr_src);
|
||||
@@ -69,9 +79,10 @@ unsigned int aml_toddr_get_position(struct toddr *to);
|
||||
void aml_toddr_select_src(struct toddr *to, enum toddr_src);
|
||||
void aml_toddr_enable(struct toddr *to, bool enable);
|
||||
void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh);
|
||||
void aml_toddr_set_format(struct toddr *to,
|
||||
unsigned int type, unsigned int msb, unsigned int lsb,
|
||||
int ch_num, int bit_depth);
|
||||
void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt);
|
||||
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);
|
||||
|
||||
/* resample */
|
||||
void aml_resample_enable(bool enable, int resample_module);
|
||||
|
||||
@@ -619,13 +619,19 @@ static int aml_pdm_dai_prepare(
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
struct toddr *to = p_pdm->tddr;
|
||||
struct toddr_fmt fmt;
|
||||
unsigned int osr = 192;
|
||||
|
||||
/* to ddr pdmin */
|
||||
fmt.type = toddr_type;
|
||||
fmt.msb = 31;
|
||||
fmt.lsb = lsb;
|
||||
fmt.endian = 0;
|
||||
fmt.bit_depth = bitwidth;
|
||||
fmt.ch_num = runtime->channels;
|
||||
fmt.rate = runtime->rate;
|
||||
aml_toddr_select_src(to, PDMIN);
|
||||
aml_toddr_set_format(to, toddr_type, 31, lsb,
|
||||
runtime->channels,
|
||||
bitwidth);
|
||||
aml_toddr_set_format(to, &fmt);
|
||||
aml_toddr_set_fifos(to, 0x40);
|
||||
|
||||
aml_pdm_ctrl(p_pdm->actrl,
|
||||
|
||||
@@ -20,15 +20,20 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "resample.h"
|
||||
#include "resample_hw.h"
|
||||
#include "ddr_mngr.h"
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
#define DRV_NAME "audioresample"
|
||||
|
||||
#define CLK_RATIO 256
|
||||
|
||||
struct resample_chipinfo {
|
||||
bool dividor_fn;
|
||||
};
|
||||
@@ -50,6 +55,9 @@ struct audioresample {
|
||||
/* resample to the rate */
|
||||
int out_rate;
|
||||
|
||||
/* sync with auge_resample_texts */
|
||||
int asr_idx;
|
||||
|
||||
bool enable;
|
||||
};
|
||||
|
||||
@@ -63,23 +71,30 @@ static int resample_clk_set(struct audioresample *p_resample)
|
||||
if (p_resample->enable) {
|
||||
ret = clk_prepare_enable(p_resample->clk);
|
||||
if (ret) {
|
||||
pr_err("Can't enable resample_clk clock: %d\n", ret);
|
||||
pr_err("Can't enable resample_clk clock: %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(p_resample->sclk);
|
||||
if (ret) {
|
||||
pr_err("Can't enable resample_src clock: %d\n", ret);
|
||||
pr_err("Can't enable resample_src clock: %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (p_resample->out_rate) {
|
||||
clk_set_rate(p_resample->pll,
|
||||
p_resample->out_rate * CLK_RATIO * 2);
|
||||
clk_set_rate(p_resample->sclk,
|
||||
p_resample->out_rate * 256);
|
||||
p_resample->out_rate * CLK_RATIO);
|
||||
clk_set_rate(p_resample->clk,
|
||||
p_resample->out_rate * 256);
|
||||
p_resample->out_rate * CLK_RATIO);
|
||||
} else {
|
||||
/* defaule resample clk */
|
||||
clk_set_rate(p_resample->sclk, 48000 * 256);
|
||||
clk_set_rate(p_resample->clk, 48000 * 256);
|
||||
clk_set_rate(p_resample->pll, 48000 * CLK_RATIO * 2);
|
||||
clk_set_rate(p_resample->sclk, 48000 * CLK_RATIO);
|
||||
clk_set_rate(p_resample->clk, 48000 * CLK_RATIO);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(p_resample->pll);
|
||||
@@ -104,10 +119,10 @@ static int resample_clk_set(struct audioresample *p_resample)
|
||||
|
||||
static void audio_resample_init(struct audioresample *p_resample)
|
||||
{
|
||||
resample_clk_set(p_resample);
|
||||
|
||||
aml_resample_enable(p_resample->enable,
|
||||
p_resample->resample_module);
|
||||
|
||||
resample_clk_set(p_resample);
|
||||
}
|
||||
|
||||
static int audio_resample_set(int enable, int rate)
|
||||
@@ -124,8 +139,6 @@ static int audio_resample_set(int enable, int rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int auge_resample;
|
||||
|
||||
static const char *const auge_resample_texts[] = {
|
||||
"Disable",
|
||||
"Enable:32K",
|
||||
@@ -137,6 +150,30 @@ static const char *const auge_resample_texts[] = {
|
||||
"Enable:192K",
|
||||
};
|
||||
|
||||
static int resample_idx2rate(int index)
|
||||
{
|
||||
int rate = 0;
|
||||
|
||||
if (index == 0)
|
||||
rate = 0;
|
||||
else if (index == 1)
|
||||
rate = 32000;
|
||||
else if (index == 2)
|
||||
rate = 44100;
|
||||
else if (index == 3)
|
||||
rate = 48000;
|
||||
else if (index == 4)
|
||||
rate = 88200;
|
||||
else if (index == 5)
|
||||
rate = 96000;
|
||||
else if (index == 6)
|
||||
rate = 176400;
|
||||
else if (index == 7)
|
||||
rate = 192000;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static const struct soc_enum auge_resample_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(auge_resample_texts),
|
||||
auge_resample_texts);
|
||||
@@ -145,7 +182,36 @@ static int resample_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.enumerated.item[0] = auge_resample;
|
||||
struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_resample->asr_idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resample_set(int index)
|
||||
{
|
||||
int resample_rate = resample_idx2rate(index);
|
||||
|
||||
if (index == s_resample->asr_idx)
|
||||
return 0;
|
||||
|
||||
s_resample->asr_idx = index;
|
||||
|
||||
pr_info("%s %s\n",
|
||||
__func__,
|
||||
auge_resample_texts[index]);
|
||||
|
||||
if (audio_resample_set(index, resample_rate))
|
||||
return 0;
|
||||
|
||||
if ((index == 0) || (resample_rate == 0))
|
||||
resample_disable();
|
||||
else {
|
||||
resample_init(resample_rate);
|
||||
|
||||
resample_set_hw_param(index - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -154,51 +220,9 @@ static int resample_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
/* struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
|
||||
* struct aml_audio_private_data *p_aml_audio =
|
||||
* snd_soc_card_get_drvdata(card);
|
||||
* struct aml_card_info *p_cardinfo = p_aml_audio->cardinfo;
|
||||
*/
|
||||
int index = ucontrol->value.enumerated.item[0];
|
||||
int resample_rate = 0;
|
||||
|
||||
if (index == 0)
|
||||
resample_rate = 0;
|
||||
else if (index == 1)
|
||||
resample_rate = 32000;
|
||||
else if (index == 2)
|
||||
resample_rate = 44100;
|
||||
else if (index == 3)
|
||||
resample_rate = 48000;
|
||||
else if (index == 4)
|
||||
resample_rate = 88200;
|
||||
else if (index == 5)
|
||||
resample_rate = 96000;
|
||||
else if (index == 6)
|
||||
resample_rate = 176400;
|
||||
else if (index == 7)
|
||||
resample_rate = 192000;
|
||||
else
|
||||
return 0;
|
||||
|
||||
auge_resample = index;
|
||||
|
||||
if (audio_resample_set(index, resample_rate))
|
||||
return 0;
|
||||
|
||||
if (index == 0)
|
||||
resample_disable();
|
||||
else {
|
||||
resample_enable(resample_rate);
|
||||
// TODO: fixe me
|
||||
resample_set_hw_param(index - 1);
|
||||
}
|
||||
/*
|
||||
* if (index > 0
|
||||
* && p_aml_audio
|
||||
* && p_cardinfo)
|
||||
* p_cardinfo->set_resample_param(index - 1);
|
||||
*/
|
||||
resample_set(index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -246,9 +270,61 @@ static int mixer_audiobus_write(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new snd_resample_controls[] = {
|
||||
/* resample module
|
||||
* keep sync with enum toddr_src in ddr_mngr.h
|
||||
*/
|
||||
static const char *const auge_resample_module_texts[] = {
|
||||
"TDMIN_A",
|
||||
"TDMIN_B",
|
||||
"TDMIN_C",
|
||||
"SPDIFIN",
|
||||
"PDMIN",
|
||||
"NONE",
|
||||
"TDMIN_LB",
|
||||
"LOOPBACK",
|
||||
};
|
||||
|
||||
/* resample */
|
||||
static const struct soc_enum auge_resample_module_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(auge_resample_module_texts),
|
||||
auge_resample_module_texts);
|
||||
|
||||
static int resample_module_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (!p_resample) {
|
||||
pr_err("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_resample->resample_module;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resample_module_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (!p_resample) {
|
||||
pr_err("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p_resample->resample_module = ucontrol->value.enumerated.item[0];
|
||||
|
||||
/* update info to ddr */
|
||||
aml_resample_enable(p_resample->enable,
|
||||
p_resample->resample_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new snd_resample_controls[] = {
|
||||
SOC_ENUM_EXT("Hardware resample enable",
|
||||
auge_resample_enum,
|
||||
resample_get_enum,
|
||||
@@ -261,12 +337,26 @@ static const struct snd_kcontrol_new snd_resample_controls[] = {
|
||||
EE_AUDIO_RESAMPLE_CTRL2, 0, 0xffffff, 0,
|
||||
mixer_audiobus_read, mixer_audiobus_write,
|
||||
NULL),
|
||||
SOC_ENUM_EXT("Hardware resample module",
|
||||
auge_resample_module_enum,
|
||||
resample_module_get_enum,
|
||||
resample_module_set_enum),
|
||||
};
|
||||
|
||||
int card_add_resample_kcontrols(struct snd_soc_card *card)
|
||||
{
|
||||
return snd_soc_add_card_controls(card,
|
||||
snd_resample_controls, ARRAY_SIZE(snd_resample_controls));
|
||||
unsigned int idx;
|
||||
int err;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_resample_controls); idx++) {
|
||||
err = snd_ctl_add(card->snd_card,
|
||||
snd_ctl_new1(&snd_resample_controls[idx],
|
||||
s_resample));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resample_chipinfo g12a_resample_chipinfo = {
|
||||
|
||||
@@ -19,4 +19,5 @@
|
||||
|
||||
extern int card_add_resample_kcontrols(struct snd_soc_card *card);
|
||||
|
||||
extern int resample_set(int index);
|
||||
#endif
|
||||
|
||||
@@ -14,8 +14,11 @@
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "resample_hw.h"
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
/*Cnt_ctrl = mclk/fs_out-1 ; fest 256fs */
|
||||
#define RESAMPLE_CNT_CONTROL 255
|
||||
@@ -37,22 +40,39 @@ static u32 resample_coef_parameters_table[7][5] = {
|
||||
{0x00800000, 0x0, 0x0, 0x0, 0x0},
|
||||
};
|
||||
|
||||
int resample_enable(int input_sr)
|
||||
void resample_enable(bool enable)
|
||||
{
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
0x1 << 31,
|
||||
1 << 31);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
0x1 << 31,
|
||||
0 << 31);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
0x1 << 28,
|
||||
enable << 28);
|
||||
}
|
||||
|
||||
int resample_init(int input_sr)
|
||||
{
|
||||
u16 Avg_cnt_init = 0;
|
||||
unsigned int clk_rate = 167000000;//clk81;
|
||||
|
||||
Avg_cnt_init = (u16)(clk_rate * 4 / input_sr);
|
||||
if (input_sr)
|
||||
Avg_cnt_init = (u16)(clk_rate * 4 / input_sr);
|
||||
else
|
||||
pr_err("unsupport input sample rate:%d\n", input_sr);
|
||||
|
||||
pr_info("clk_rate = %u, input_sr = %d, Avg_cnt_init = %u\n",
|
||||
clk_rate, input_sr, Avg_cnt_init);
|
||||
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, (1 << 31));
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, 0);
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
(1 << 28) /* enable */
|
||||
| (0 << 26) /* method0 */
|
||||
| (RESAMPLE_CNT_CONTROL << 16)
|
||||
| Avg_cnt_init);
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
0x3 << 26 | 0x3ff << 16 | 0xffff << 0,
|
||||
0x0 << 26 | /* method0 */
|
||||
RESAMPLE_CNT_CONTROL << 16 |
|
||||
Avg_cnt_init << 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -91,3 +111,13 @@ void resample_format_set(int ch_num, int bits)
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL3,
|
||||
ch_num << 8 | (bits - 1) << 0);
|
||||
}
|
||||
|
||||
int resample_ctrl_read(int idx)
|
||||
{
|
||||
return audiobus_read(EE_AUDIO_RESAMPLE_CTRL0);
|
||||
}
|
||||
|
||||
void resample_ctrl_write(int idx, int value)
|
||||
{
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, value);
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
*/
|
||||
#ifndef __AML_AUDIO_RESAMPLE_HW_H__
|
||||
#define __AML_AUDIO_RESAMPLE_HW_H__
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
extern int resample_enable(int input_sr);
|
||||
extern void resample_enable(bool enable);
|
||||
extern int resample_init(int input_sr);
|
||||
extern int resample_disable(void);
|
||||
extern int resample_set_hw_param(int index);
|
||||
extern void resample_src_select(int src);
|
||||
extern void resample_format_set(int ch_num, int bits);
|
||||
|
||||
extern int resample_ctrl_read(int idx);
|
||||
extern void resample_ctrl_write(int idx, int value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "ddr_mngr.h"
|
||||
#include "spdif_hw.h"
|
||||
#include "audio_utils.h"
|
||||
#include "resample.h"
|
||||
#include "resample_hw.h"
|
||||
|
||||
#define DRV_NAME "aml_spdif"
|
||||
|
||||
@@ -46,15 +48,22 @@
|
||||
/* Debug by PTM when bringup */
|
||||
/* #define G12A_PTM */
|
||||
|
||||
/* for debug */
|
||||
/*#define __SPDIFIN_INSERT_CHNUM__*/
|
||||
|
||||
struct spdif_chipinfo {
|
||||
unsigned int id;
|
||||
|
||||
/* add ch_cnt to ch_num */
|
||||
bool chnum_en;
|
||||
/* Reg_clr_interrupt[7:0] for each bit of irq_status[7:0]; */
|
||||
bool clr_irq_bits;
|
||||
/* find PaPb */
|
||||
bool irq_papb;
|
||||
/*
|
||||
* axg, clear all irq bits
|
||||
* after axg, such as g12a, clear each bits
|
||||
* Reg_clr_interrupt[7:0] for each bit of irq_status[7:0];
|
||||
*/
|
||||
bool clr_irq_all_bits;
|
||||
/* no PaPb irq */
|
||||
bool irq_no_papb;
|
||||
/* reg_hold_start_en; 1: add delay to match TDM out when share buff; */
|
||||
bool hold_start;
|
||||
/* eq/drc */
|
||||
@@ -83,6 +92,27 @@ struct aml_spdif {
|
||||
unsigned int id;
|
||||
struct spdif_chipinfo *chipinfo;
|
||||
unsigned int clk_cont; /* CONTINUOUS CLOCK */
|
||||
|
||||
/* spdif in do asrc for pcm,
|
||||
* if raw data, disable it automatically.
|
||||
*/
|
||||
unsigned int auto_asrc;
|
||||
/* check spdifin channel status for pcm or nonpcm */
|
||||
struct timer_list timer;
|
||||
struct work_struct work;
|
||||
|
||||
/* spdif in reset for l/r channel swap when plug/unplug */
|
||||
struct timer_list reset_timer;
|
||||
/* timer is used */
|
||||
int is_reset_timer_used;
|
||||
/* reset timer counter */
|
||||
int timer_counter;
|
||||
/* 0: default, 1: spdif in firstly enable, 2: spdif in could be reset */
|
||||
int sample_rate_detect_start;
|
||||
/* is spdif in reset */
|
||||
int is_reset;
|
||||
int last_sample_rate_mode;
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware aml_spdif_hardware = {
|
||||
@@ -102,7 +132,7 @@ static const struct snd_pcm_hardware aml_spdif_hardware = {
|
||||
.buffer_bytes_max = 256 * 1024,
|
||||
|
||||
.rate_min = 8000,
|
||||
.rate_max = 48000,
|
||||
.rate_max = 192000,
|
||||
.channels_min = 2,
|
||||
.channels_max = 32,
|
||||
};
|
||||
@@ -114,24 +144,14 @@ static const unsigned int spdifin_extcon[] = {
|
||||
};
|
||||
|
||||
/* current sample mode and its sample rate */
|
||||
int sample_mode[] = {
|
||||
24000,
|
||||
32000,
|
||||
44100,
|
||||
46000,
|
||||
48000,
|
||||
96000,
|
||||
192000,
|
||||
};
|
||||
|
||||
static const char *const spdifin_samplerate[] = {
|
||||
"N/A",
|
||||
"24000",
|
||||
"32000",
|
||||
"44100",
|
||||
"46000",
|
||||
"48000",
|
||||
"88200",
|
||||
"96000",
|
||||
"176400",
|
||||
"192000"
|
||||
};
|
||||
|
||||
@@ -187,18 +207,17 @@ static const struct sppdif_audio_info type_texts[] = {
|
||||
{6, 0x003, "PAUSE"},
|
||||
{6, 0x100, "PAUSE"},
|
||||
};
|
||||
|
||||
static const struct soc_enum spdif_audio_type_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts),
|
||||
spdif_audio_type_texts);
|
||||
|
||||
static int spdifin_audio_type_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
static int spdifin_check_audio_type(void)
|
||||
{
|
||||
int audio_type = 0;
|
||||
int i;
|
||||
int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info);
|
||||
int pc = spdifin_get_audio_type();
|
||||
int audio_type = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < total_num; i++) {
|
||||
if (pc == type_texts[i].pc) {
|
||||
@@ -206,7 +225,18 @@ static int spdifin_audio_type_get_enum(
|
||||
break;
|
||||
}
|
||||
}
|
||||
ucontrol->value.enumerated.item[0] = audio_type;
|
||||
|
||||
pr_info("%s audio type:%d\n", __func__, audio_type);
|
||||
|
||||
return audio_type;
|
||||
}
|
||||
|
||||
static int spdifin_audio_type_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.enumerated.item[0] =
|
||||
spdifin_check_audio_type();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -223,54 +253,271 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = {
|
||||
NULL),
|
||||
};
|
||||
|
||||
static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif)
|
||||
{
|
||||
if (p_spdif
|
||||
&& p_spdif->chipinfo
|
||||
&& p_spdif->chipinfo->irq_no_papb)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_start_timer(
|
||||
struct aml_spdif *p_spdif)
|
||||
{
|
||||
p_spdif->timer.expires = jiffies + 1;
|
||||
add_timer(&p_spdif->timer);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_stop_timer(
|
||||
struct aml_spdif *p_spdif)
|
||||
{
|
||||
del_timer(&p_spdif->timer);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_timer_func(unsigned long data)
|
||||
{
|
||||
struct aml_spdif *p_spdif = (struct aml_spdif *)data;
|
||||
unsigned long delay = msecs_to_jiffies(1);
|
||||
|
||||
schedule_work(&p_spdif->work);
|
||||
mod_timer(&p_spdif->timer, jiffies + delay);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_work_func(struct work_struct *work)
|
||||
{
|
||||
struct aml_spdif *p_spdif = container_of(
|
||||
work, struct aml_spdif, work);
|
||||
|
||||
int val = spdifin_get_ch_status0to31();
|
||||
|
||||
/* auto resample ? */
|
||||
if (!p_spdif->auto_asrc)
|
||||
return;
|
||||
|
||||
if (val & 0x2)
|
||||
/* nonpcm, resample disable */
|
||||
resample_set(0);
|
||||
else
|
||||
/* pcm, resample which rate ? */
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_detect_init(struct aml_spdif *p_spdif)
|
||||
{
|
||||
init_timer(&p_spdif->timer);
|
||||
p_spdif->timer.function = spdifin_audio_type_timer_func;
|
||||
p_spdif->timer.data = (unsigned long)p_spdif;
|
||||
|
||||
INIT_WORK(&p_spdif->work, spdifin_audio_type_work_func);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_detect_deinit(struct aml_spdif *p_spdif)
|
||||
{
|
||||
cancel_work_sync(&p_spdif->work);
|
||||
}
|
||||
|
||||
static void spdifin_fast_reset(struct aml_spdif *p_spdif)
|
||||
{
|
||||
struct aml_audio_controller *actrl = p_spdif->actrl;
|
||||
unsigned int tddr_val = aml_toddr_read(p_spdif->tddr);
|
||||
unsigned int spdifin_ctrl_val = aml_spdif_ctrl_read(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id);
|
||||
unsigned int asr_ctrl_val = 0;
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
/* toddr disable */
|
||||
tddr_val &= ~(1 << 31);
|
||||
aml_toddr_write(p_spdif->tddr, tddr_val);
|
||||
|
||||
/* resample disable and reset */
|
||||
if (p_spdif->auto_asrc) {
|
||||
asr_ctrl_val = resample_ctrl_read(0);
|
||||
asr_ctrl_val &= ~(1 << 28);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
asr_ctrl_val |= (1 << 31);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
asr_ctrl_val &= ~(1 << 31);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
}
|
||||
|
||||
/* spdif in disable and reset */
|
||||
spdifin_ctrl_val &= ~(0x1 << 31);
|
||||
aml_spdif_ctrl_write(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
|
||||
spdifin_ctrl_val &= ~(0x3 << 28);
|
||||
aml_spdif_ctrl_write(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
|
||||
spdifin_ctrl_val |= (0x1 << 29);
|
||||
aml_spdif_ctrl_write(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
|
||||
spdifin_ctrl_val |= (0x1 << 28);
|
||||
aml_spdif_ctrl_write(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
|
||||
|
||||
/* toddr enable */
|
||||
tddr_val |= (1 << 31);
|
||||
aml_toddr_write(p_spdif->tddr, tddr_val);
|
||||
|
||||
/* resample enable */
|
||||
if (p_spdif->auto_asrc) {
|
||||
asr_ctrl_val |= (1 << 28);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
}
|
||||
|
||||
/* spdif in enable */
|
||||
spdifin_ctrl_val |= (0x1 << 31);
|
||||
aml_spdif_ctrl_write(actrl,
|
||||
SNDRV_PCM_STREAM_CAPTURE, p_spdif->id, spdifin_ctrl_val);
|
||||
}
|
||||
|
||||
#define MAX_TIMER_COUNTER 30
|
||||
#define FIRST_DELAY 20
|
||||
|
||||
static void spdifin_reset_timer(unsigned long data)
|
||||
{
|
||||
struct aml_spdif *p_spdif = (struct aml_spdif *)data;
|
||||
unsigned long delay = msecs_to_jiffies(1);
|
||||
int intrpt_status = aml_spdifin_status_check(p_spdif->actrl);
|
||||
int mode = (intrpt_status >> 28) & 0x7;
|
||||
|
||||
if ((p_spdif->last_sample_rate_mode != mode) ||
|
||||
(p_spdif->last_sample_rate_mode == 0x7)) {
|
||||
|
||||
p_spdif->last_sample_rate_mode = mode;
|
||||
p_spdif->timer_counter = 0;
|
||||
mod_timer(&p_spdif->reset_timer, jiffies + delay);
|
||||
} else if ((p_spdif->last_sample_rate_mode == mode) &&
|
||||
(mode != 0x7)) {
|
||||
|
||||
if (p_spdif->timer_counter > MAX_TIMER_COUNTER) {
|
||||
p_spdif->timer_counter = 0;
|
||||
|
||||
if (p_spdif->is_reset ||
|
||||
(p_spdif->sample_rate_detect_start == 1)) {
|
||||
p_spdif->is_reset = 0;
|
||||
p_spdif->sample_rate_detect_start = 2;
|
||||
if (p_spdif->is_reset_timer_used) {
|
||||
p_spdif->is_reset_timer_used = 0;
|
||||
del_timer(&p_spdif->reset_timer);
|
||||
}
|
||||
pr_debug("%s,last sample mode:0x%x, stop timer\n",
|
||||
__func__,
|
||||
p_spdif->last_sample_rate_mode);
|
||||
} else {
|
||||
p_spdif->last_sample_rate_mode = 0;
|
||||
|
||||
p_spdif->is_reset = 1;
|
||||
spdifin_fast_reset(p_spdif);
|
||||
|
||||
delay = msecs_to_jiffies(FIRST_DELAY);
|
||||
mod_timer(&p_spdif->reset_timer,
|
||||
jiffies + delay);
|
||||
}
|
||||
} else {
|
||||
p_spdif->timer_counter++;
|
||||
mod_timer(&p_spdif->reset_timer, jiffies + delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spdifin_status_event(struct aml_spdif *p_spdif)
|
||||
{
|
||||
int intrpt_status;
|
||||
|
||||
if (p_spdif == NULL)
|
||||
if (!p_spdif)
|
||||
return;
|
||||
|
||||
/*
|
||||
* interrupt status, check and clear by reg_clk_interrupt;
|
||||
*/
|
||||
/* interrupt status, check and clear by reg_clk_interrupt */
|
||||
intrpt_status = aml_spdifin_status_check(p_spdif->actrl);
|
||||
|
||||
/* clear irq bits immediametely */
|
||||
if (p_spdif->chipinfo)
|
||||
aml_spdifin_clr_irq(p_spdif->actrl,
|
||||
p_spdif->chipinfo->clr_irq_all_bits,
|
||||
intrpt_status & 0xff);
|
||||
|
||||
if (intrpt_status & 0x1)
|
||||
pr_warn_once("over flow!!\n");
|
||||
pr_info("over flow!!\n");
|
||||
if (intrpt_status & 0x2)
|
||||
pr_warn_once("parity error\n");
|
||||
pr_info("parity error\n");
|
||||
|
||||
if (intrpt_status & 0x4) {
|
||||
int mode = (intrpt_status >> 28) & 0x7;
|
||||
|
||||
pr_warn_once("sample mode changed\n");
|
||||
if (mode == 0x7) {
|
||||
pr_debug("Default value, not detect sample rate\n");
|
||||
pr_debug("sample rate, mode:%x\n", mode);
|
||||
if (/*(mode == 0x7) && */(!p_spdif->sample_rate_detect_start)) {
|
||||
p_spdif->sample_rate_detect_start = 1;
|
||||
pr_debug("spdif in sample rate started\n");
|
||||
}
|
||||
|
||||
if (p_spdif->sample_rate_detect_start) {
|
||||
|
||||
p_spdif->last_sample_rate_mode = mode;
|
||||
|
||||
if (!p_spdif->is_reset_timer_used) {
|
||||
unsigned long delay = msecs_to_jiffies(1);
|
||||
|
||||
if (p_spdif->sample_rate_detect_start == 1)
|
||||
delay = msecs_to_jiffies(FIRST_DELAY);
|
||||
|
||||
setup_timer(&p_spdif->reset_timer,
|
||||
spdifin_reset_timer,
|
||||
(unsigned long)p_spdif);
|
||||
mod_timer(&p_spdif->reset_timer,
|
||||
jiffies + delay);
|
||||
}
|
||||
p_spdif->is_reset_timer_used++;
|
||||
p_spdif->timer_counter = 0;
|
||||
}
|
||||
|
||||
if ((mode == 0x7) ||
|
||||
(((intrpt_status >> 18) & 0x3ff) == 0x3ff)) {
|
||||
pr_info("Default value, not detect sample rate\n");
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_SAMPLERATE, 0);
|
||||
} else if (mode >= 0) {
|
||||
pr_debug("Event: EXTCON_SPDIFIN_SAMPLERATE, new sample rate:%d\n",
|
||||
sample_mode[mode]);
|
||||
if (p_spdif->last_sample_rate_mode != mode) {
|
||||
pr_info("Event: EXTCON_SPDIFIN_SAMPLERATE, new sample rate:%s\n",
|
||||
spdifin_samplerate[mode + 1]);
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_SAMPLERATE, 1);
|
||||
/* resample enable, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_SAMPLERATE, 1);
|
||||
}
|
||||
}
|
||||
p_spdif->last_sample_rate_mode = mode;
|
||||
|
||||
}
|
||||
|
||||
if (intrpt_status & 0x8) {
|
||||
pr_warn_once("Pc changed, try to read spdifin audio type\n");
|
||||
pr_info("Pc changed, try to read spdifin audio type\n");
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_AUDIOTYPE, 1);
|
||||
} else
|
||||
|
||||
/* resample disable, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(0);
|
||||
}
|
||||
if (intrpt_status & 0x10)
|
||||
pr_info("Pd changed\n");
|
||||
if (intrpt_status & 0x20) {
|
||||
pr_info("nonpcm to pcm\n");
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_AUDIOTYPE, 0);
|
||||
|
||||
if (intrpt_status & 0x10)
|
||||
pr_warn_once("Pd changed\n");
|
||||
if (intrpt_status & 0x20)
|
||||
pr_warn_once("nonpcm to pcm\n");
|
||||
/* resample to 48k, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
}
|
||||
if (intrpt_status & 0x40)
|
||||
pr_warn_once("valid changed\n");
|
||||
pr_info("valid changed\n");
|
||||
}
|
||||
|
||||
static irqreturn_t aml_spdif_ddr_isr(int irq, void *devid)
|
||||
@@ -291,8 +538,6 @@ static irqreturn_t aml_spdifin_status_isr(int irq, void *devid)
|
||||
{
|
||||
struct aml_spdif *p_spdif = (struct aml_spdif *)devid;
|
||||
|
||||
aml_spdifin_status_check(p_spdif->actrl);
|
||||
|
||||
spdifin_status_event(p_spdif);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -306,7 +551,7 @@ static int aml_spdif_open(struct snd_pcm_substream *substream)
|
||||
struct aml_spdif *p_spdif;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
p_spdif = (struct aml_spdif *)dev_get_drvdata(dev);
|
||||
|
||||
@@ -337,6 +582,10 @@ static int aml_spdif_open(struct snd_pcm_substream *substream)
|
||||
p_spdif->irq_spdifin);
|
||||
return ret;
|
||||
}
|
||||
if (spdifin_check_audiotype_by_sw(p_spdif))
|
||||
spdifin_audio_type_detect_init(p_spdif);
|
||||
|
||||
p_spdif->sample_rate_detect_start = 0;
|
||||
}
|
||||
|
||||
runtime->private_data = p_spdif;
|
||||
@@ -350,13 +599,30 @@ static int aml_spdif_close(struct snd_pcm_substream *substream)
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct aml_spdif *p_spdif = runtime->private_data;
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
aml_audio_unregister_frddr(p_spdif->dev, substream);
|
||||
} else {
|
||||
aml_audio_unregister_toddr(p_spdif->dev, substream);
|
||||
free_irq(p_spdif->irq_spdifin, p_spdif);
|
||||
|
||||
if (spdifin_check_audiotype_by_sw(p_spdif))
|
||||
spdifin_audio_type_detect_deinit(p_spdif);
|
||||
|
||||
if (p_spdif->is_reset_timer_used) {
|
||||
p_spdif->is_reset_timer_used = 0;
|
||||
del_timer(&p_spdif->reset_timer);
|
||||
}
|
||||
|
||||
/* clear extcon status */
|
||||
if (p_spdif->id == 0) {
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_SAMPLERATE, 0);
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_AUDIOTYPE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
runtime->private_data = NULL;
|
||||
@@ -381,7 +647,30 @@ static int aml_spdif_hw_free(struct snd_pcm_substream *substream)
|
||||
|
||||
static int aml_spdif_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
return 0;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct aml_spdif *p_spdif = runtime->private_data;
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
if ((spdifin_check_audiotype_by_sw(p_spdif))
|
||||
&& (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
|
||||
spdifin_audio_type_start_timer(p_spdif);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
if ((spdifin_check_audiotype_by_sw(p_spdif))
|
||||
&& (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
|
||||
spdifin_audio_type_stop_timer(p_spdif);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aml_spdif_prepare(struct snd_pcm_substream *substream)
|
||||
@@ -475,6 +764,7 @@ static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd)
|
||||
__func__,
|
||||
(p_spdif->id == 0) ? "a":"b",
|
||||
p_spdif->clk_cont);
|
||||
|
||||
/* keep frddr when probe, after spdif_frddr_init done
|
||||
* frddr can be released, and spdif outputs zero data
|
||||
* without frddr used.
|
||||
@@ -498,6 +788,8 @@ static int aml_dai_spdif_probe(struct snd_soc_dai *cpu_dai)
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret = 0;
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
if (p_spdif->id == SPDIF_A) {
|
||||
ret = snd_soc_add_dai_controls(cpu_dai, snd_spdif_controls,
|
||||
ARRAY_SIZE(snd_spdif_controls));
|
||||
@@ -505,14 +797,12 @@ static int aml_dai_spdif_probe(struct snd_soc_dai *cpu_dai)
|
||||
pr_err("%s, failed add snd spdif controls\n", __func__);
|
||||
}
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_dai_spdif_remove(struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
pr_info("%s\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -524,7 +814,9 @@ static int aml_dai_spdif_startup(
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret;
|
||||
|
||||
pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
|
||||
pr_info("%s stream:%d\n",
|
||||
__func__,
|
||||
substream->stream);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
|
||||
@@ -579,6 +871,9 @@ static int aml_dai_spdif_startup(
|
||||
pr_err("Can't enable pcm clk_spdifin clock: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
/* resample to 48k in default, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -593,6 +888,10 @@ static void aml_dai_spdif_shutdown(
|
||||
{
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
pr_info("%s, stream:%d\n",
|
||||
__func__,
|
||||
substream->stream);
|
||||
|
||||
/* disable clock and gate */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (p_spdif->clk_cont) {
|
||||
@@ -605,6 +904,10 @@ static void aml_dai_spdif_shutdown(
|
||||
clk_disable_unprepare(p_spdif->sysclk);
|
||||
clk_disable_unprepare(p_spdif->gate_spdifout);
|
||||
} else {
|
||||
/* resample disabled, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(0);
|
||||
|
||||
clk_disable_unprepare(p_spdif->clk_spdifin);
|
||||
clk_disable_unprepare(p_spdif->fixed_clk);
|
||||
clk_disable_unprepare(p_spdif->gate_spdifin);
|
||||
@@ -657,6 +960,7 @@ static int aml_dai_spdif_prepare(
|
||||
|
||||
} else {
|
||||
struct toddr *to = p_spdif->tddr;
|
||||
struct toddr_fmt fmt;
|
||||
unsigned int msb, lsb, toddr_type;
|
||||
|
||||
if (loopback_is_enable()) {
|
||||
@@ -704,16 +1008,30 @@ static int aml_dai_spdif_prepare(
|
||||
}
|
||||
|
||||
// to ddr spdifin
|
||||
fmt.type = toddr_type;
|
||||
fmt.msb = msb;
|
||||
fmt.lsb = lsb;
|
||||
fmt.endian = 0;
|
||||
fmt.bit_depth = bit_depth;
|
||||
fmt.ch_num = runtime->channels;
|
||||
fmt.rate = runtime->rate;
|
||||
aml_toddr_select_src(to, SPDIFIN);
|
||||
aml_toddr_set_format(to, toddr_type, msb, lsb,
|
||||
runtime->channels,
|
||||
bit_depth);
|
||||
aml_toddr_set_format(to, &fmt);
|
||||
aml_toddr_set_fifos(to, 0x40);
|
||||
#ifdef __SPDIFIN_INSERT_CHNUM__
|
||||
aml_toddr_insert_chanum(to);
|
||||
#endif
|
||||
}
|
||||
|
||||
aml_spdif_fifo_ctrl(p_spdif->actrl, bit_depth,
|
||||
substream->stream, p_spdif->id, fifo_id);
|
||||
|
||||
#ifdef __SPDIFIN_INSERT_CHNUM__
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
aml_spdifin_chnum_en(p_spdif->actrl,
|
||||
p_spdif->id, true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -741,6 +1059,7 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
|
||||
aml_spdif_enable(p_spdif->actrl,
|
||||
substream->stream, p_spdif->id, true);
|
||||
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
@@ -769,7 +1088,6 @@ static int aml_dai_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
@@ -778,14 +1096,13 @@ static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned int rate = params_rate(params);
|
||||
int ret = 0;
|
||||
|
||||
pr_info("%s\n", __func__);
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
rate *= 128;
|
||||
|
||||
snd_soc_dai_set_sysclk(cpu_dai,
|
||||
0, rate, SND_SOC_CLOCK_OUT);
|
||||
} else {
|
||||
clk_set_rate(p_spdif->clk_spdifin, 250000000);
|
||||
clk_set_rate(p_spdif->clk_spdifin, 500000000);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -793,9 +1110,7 @@ static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
static int aml_dai_set_spdif_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
|
||||
{
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
pr_info("asoc aml_dai_set_spdif_fmt, %#x, %p\n", fmt, p_spdif);
|
||||
pr_info("%s , fmt %#x\n", __func__, fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -804,8 +1119,10 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
{
|
||||
unsigned int mpll_freq = 0;
|
||||
|
||||
pr_info("asoc debug: %s-%d, sys freq:%d\n", __func__, __LINE__,
|
||||
pr_info("%s, sys freq:%d\n",
|
||||
__func__,
|
||||
p_spdif->sysclk_freq);
|
||||
|
||||
if (p_spdif->sysclk_freq) {
|
||||
unsigned int mul = 4;
|
||||
int ret;
|
||||
@@ -821,6 +1138,10 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
#ifdef G12A_PTM
|
||||
mpll_freq = p_spdif->sysclk_freq * 57;
|
||||
#endif
|
||||
pr_info("\t finally sys freq:%d, mpll freq:%d\n",
|
||||
p_spdif->sysclk_freq,
|
||||
mpll_freq);
|
||||
|
||||
clk_set_rate(p_spdif->sysclk, mpll_freq);
|
||||
clk_set_rate(p_spdif->clk_spdifout,
|
||||
p_spdif->sysclk_freq);
|
||||
@@ -841,13 +1162,18 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
pr_info("%s, clk_id:%d, freq:%d, dir:%d\n",
|
||||
__func__,
|
||||
clk_id,
|
||||
freq,
|
||||
dir);
|
||||
|
||||
p_spdif->sysclk_freq = freq;
|
||||
pr_info("aml_dai_set_spdif_sysclk, %d, %d, %d\n",
|
||||
clk_id, freq, dir);
|
||||
if (dir == SND_SOC_CLOCK_OUT) {
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
aml_set_spdifclk(p_spdif);
|
||||
p_spdif->sysclk_freq = freq;
|
||||
aml_set_spdifclk(p_spdif);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -970,6 +1296,14 @@ static int aml_spdif_parse_of(struct platform_device *pdev)
|
||||
ret = extcon_dev_register(p_spdif->edev);
|
||||
if (ret < 0)
|
||||
pr_err("SPDIF IN extcon failed to register!!, ignore it\n");
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"auto_asrc", &p_spdif->auto_asrc);
|
||||
if (ret < 0)
|
||||
p_spdif->auto_asrc = 0;
|
||||
pr_info("SPDIF id %d auto_asrc:%d\n",
|
||||
p_spdif->id,
|
||||
p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
/* clock for spdif out */
|
||||
@@ -996,14 +1330,14 @@ static int aml_spdif_parse_of(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
struct spdif_chipinfo axg_spdif_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.id = SPDIF_A,
|
||||
.irq_no_papb = true,
|
||||
.clr_irq_all_bits = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.clr_irq_bits = true,
|
||||
.irq_papb = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
@@ -1011,8 +1345,6 @@ struct spdif_chipinfo g12a_spdif_a_chipinfo = {
|
||||
struct spdif_chipinfo g12a_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.clr_irq_bits = true,
|
||||
.irq_papb = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
};
|
||||
@@ -1058,11 +1390,10 @@ static int aml_spdif_platform_probe(struct platform_device *pdev)
|
||||
of_device_get_match_data(dev);
|
||||
if (p_spdif_chipinfo) {
|
||||
aml_spdif->id = p_spdif_chipinfo->id;
|
||||
/* for spdif_b, clk be continuous,
|
||||
/* for spdif output zero data, clk be continuous,
|
||||
* and keep silence when no valid data
|
||||
*/
|
||||
/*if (aml_spdif->id == 1)*/
|
||||
aml_spdif->clk_cont = 1;
|
||||
aml_spdif->clk_cont = 1;
|
||||
|
||||
aml_spdif->chipinfo = p_spdif_chipinfo;
|
||||
} else
|
||||
|
||||
@@ -26,6 +26,49 @@
|
||||
/*#define G12A_PTM*/
|
||||
/*#define G12A_PTM_LB_INTERNAL*/
|
||||
|
||||
unsigned int aml_spdif_ctrl_read(struct aml_audio_controller *actrl,
|
||||
int stream, int index)
|
||||
{
|
||||
unsigned int offset, reg;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0;
|
||||
reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index;
|
||||
} else {
|
||||
reg = EE_AUDIO_SPDIFIN_CTRL0;
|
||||
}
|
||||
|
||||
return aml_audiobus_read(actrl, reg);
|
||||
}
|
||||
|
||||
void aml_spdif_ctrl_write(struct aml_audio_controller *actrl,
|
||||
int stream, int index, int val)
|
||||
{
|
||||
unsigned int offset, reg;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
offset = EE_AUDIO_SPDIFOUT_B_CTRL0 - EE_AUDIO_SPDIFOUT_CTRL0;
|
||||
reg = EE_AUDIO_SPDIFOUT_CTRL0 + offset * index;
|
||||
} else {
|
||||
reg = EE_AUDIO_SPDIFIN_CTRL0;
|
||||
}
|
||||
|
||||
aml_audiobus_write(actrl, reg, val);
|
||||
}
|
||||
|
||||
void aml_spdifin_chnum_en(struct aml_audio_controller *actrl,
|
||||
int index, bool is_enable)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
reg = EE_AUDIO_SPDIFIN_CTRL0;
|
||||
aml_audiobus_update_bits(actrl, reg, 1 << 26, is_enable << 26);
|
||||
|
||||
pr_info("%s spdifin ctrl0:0x%x\n",
|
||||
__func__,
|
||||
aml_audiobus_read(actrl, reg));
|
||||
}
|
||||
|
||||
void aml_spdif_enable(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream,
|
||||
@@ -84,23 +127,31 @@ int aml_spdifin_status_check(struct aml_audio_controller *actrl)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = aml_audiobus_read(actrl,
|
||||
EE_AUDIO_SPDIFIN_STAT0);
|
||||
val = aml_audiobus_read(actrl, EE_AUDIO_SPDIFIN_STAT0);
|
||||
|
||||
/* pr_info("\t--- spdif handles status0 %#x\n", val); */
|
||||
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL0,
|
||||
1<<26,
|
||||
1<<26);
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL0,
|
||||
1<<26,
|
||||
0);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void aml_spdifin_clr_irq(struct aml_audio_controller *actrl,
|
||||
bool is_all_bits, int clr_bits_val)
|
||||
{
|
||||
if (is_all_bits) {
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL0,
|
||||
1 << 26,
|
||||
1 << 26);
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL0,
|
||||
1 << 26,
|
||||
0);
|
||||
} else
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL6,
|
||||
0xff << 16,
|
||||
clr_bits_val << 16);
|
||||
}
|
||||
|
||||
void aml_spdif_fifo_reset(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream, int index)
|
||||
@@ -161,7 +212,10 @@ void aml_spdif_fifo_ctrl(
|
||||
}
|
||||
|
||||
pr_info("%s, bit depth:%d, frddr type:%d, toddr:type:%d\n",
|
||||
__func__, bitwidth, frddr_type, toddr_type);
|
||||
__func__,
|
||||
bitwidth,
|
||||
frddr_type,
|
||||
toddr_type);
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
unsigned int offset, reg;
|
||||
@@ -187,61 +241,65 @@ void aml_spdif_fifo_ctrl(
|
||||
reg,
|
||||
1<<4);
|
||||
} else {
|
||||
unsigned int lsb;
|
||||
unsigned int spdifin_clk = 500000000;
|
||||
|
||||
if (bitwidth <= 24)
|
||||
lsb = 28 - bitwidth;
|
||||
else
|
||||
lsb = 4;
|
||||
/* sysclk/rate/32(bit)/2(ch)/2(bmc) */
|
||||
unsigned int counter_32k = (spdifin_clk / (32000 * 64));
|
||||
unsigned int counter_44k = (spdifin_clk / (44100 * 64));
|
||||
unsigned int counter_48k = (spdifin_clk / (48000 * 64));
|
||||
unsigned int counter_88k = (spdifin_clk / (88200 * 64));
|
||||
unsigned int counter_96k = (spdifin_clk / (96000 * 64));
|
||||
unsigned int counter_176k = (spdifin_clk / (176400 * 64));
|
||||
unsigned int counter_192k = (spdifin_clk / (192000 * 64));
|
||||
unsigned int mode0_th = 3 * (counter_32k + counter_44k) >> 1;
|
||||
unsigned int mode1_th = 3 * (counter_44k + counter_48k) >> 1;
|
||||
unsigned int mode2_th = 3 * (counter_48k + counter_88k) >> 1;
|
||||
unsigned int mode3_th = 3 * (counter_88k + counter_96k) >> 1;
|
||||
unsigned int mode4_th = 3 * (counter_96k + counter_176k) >> 1;
|
||||
unsigned int mode5_th = 3 * (counter_176k + counter_192k) >> 1;
|
||||
unsigned int mode0_timer = counter_32k >> 1;
|
||||
unsigned int mode1_timer = counter_44k >> 1;
|
||||
unsigned int mode2_timer = counter_48k >> 1;
|
||||
unsigned int mode3_timer = counter_88k >> 1;
|
||||
unsigned int mode4_timer = counter_96k >> 1;
|
||||
unsigned int mode5_timer = (counter_176k >> 1);
|
||||
unsigned int mode6_timer = (counter_192k >> 1);
|
||||
|
||||
// 250M
|
||||
#ifdef G12A_PTM
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL1,
|
||||
25000 << 0);
|
||||
#else
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL1,
|
||||
0xff << 20 | 25000 << 0);
|
||||
#endif
|
||||
0xff << 20 | (spdifin_clk / 10000) << 0);
|
||||
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL2,
|
||||
140 << 20 | 100 << 10 | 86 << 0);
|
||||
mode0_th << 20 |
|
||||
mode1_th << 10 |
|
||||
mode2_th << 0);
|
||||
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL3,
|
||||
83 << 20 | 60 << 10 | 30 << 0);
|
||||
mode3_th << 20 |
|
||||
mode4_th << 10 |
|
||||
mode5_th << 0);
|
||||
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL4,
|
||||
(81<<24) | /* reg_sample_mode0_timer */
|
||||
(61<<16) | /* reg_sample_mode1_timer */
|
||||
(44<<8) | /* reg_sample_mode2_timer*/
|
||||
(42<<0)
|
||||
(mode0_timer << 24) |
|
||||
(mode1_timer << 16) |
|
||||
(mode2_timer << 8) |
|
||||
(mode3_timer << 0)
|
||||
);
|
||||
|
||||
#ifdef G12A_PTM
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL5,
|
||||
(40<<24) |
|
||||
(20<<16) |
|
||||
(10<<8) |
|
||||
(0<<0)
|
||||
(mode4_timer << 24) |
|
||||
(mode5_timer << 16) |
|
||||
(mode6_timer << 8)
|
||||
);
|
||||
#else
|
||||
aml_audiobus_write(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL5,
|
||||
(40<<24) | /* reg_sample_mode4_timer = 5[31:24]; */
|
||||
(20<<16) | /* reg_sample_mode5_timer = 5[23:16]; */
|
||||
(9<<8) | /* reg_sample_mode6_timer = 5[15:8]; */
|
||||
(0<<0) /* reg_sample_mode7_timer = 5[7:0]; */
|
||||
);
|
||||
#endif
|
||||
|
||||
aml_audiobus_update_bits(actrl,
|
||||
EE_AUDIO_SPDIFIN_CTRL0,
|
||||
0x3<<24|1<<12,
|
||||
3<<24|1<<12);
|
||||
0x1 << 25 | 0x1 << 24 | 0xfff << 12,
|
||||
0x1 << 25 | 0x0 << 24 | 0xff << 12);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -432,17 +490,36 @@ int spdifin_get_sample_rate(void)
|
||||
|
||||
val = audiobus_read(EE_AUDIO_SPDIFIN_STAT0);
|
||||
|
||||
/* NA when check min width of two edges */
|
||||
if (((val >> 18) & 0x3ff) == 0x3ff)
|
||||
return 0x7;
|
||||
|
||||
return (val >> 28) & 0x7;
|
||||
}
|
||||
|
||||
static int spdifin_get_channel_status(int sel)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* set ch_status_sel to channel status */
|
||||
audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0xf << 8, sel << 8);
|
||||
|
||||
val = audiobus_read(EE_AUDIO_SPDIFIN_STAT1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int spdifin_get_ch_status0to31(void)
|
||||
{
|
||||
return spdifin_get_channel_status(0x0);
|
||||
}
|
||||
|
||||
int spdifin_get_audio_type(void)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* set ch_status_sel to read Pc*/
|
||||
audiobus_update_bits(EE_AUDIO_SPDIFIN_CTRL0, 0xf << 8, 0x6 << 8);
|
||||
|
||||
val = audiobus_read(EE_AUDIO_SPDIFIN_STAT1);
|
||||
/* set ch_status_sel to read Pc */
|
||||
val = spdifin_get_channel_status(0x6);
|
||||
|
||||
return (val >> 16) & 0xff;
|
||||
}
|
||||
@@ -557,7 +634,9 @@ void spdifout_play_with_zerodata(unsigned int spdif_id)
|
||||
|
||||
void spdifout_play_with_zerodata_free(unsigned int spdif_id)
|
||||
{
|
||||
pr_info("%s, spdif id:%d\n", __func__, spdif_id);
|
||||
pr_info("%s, spdif id:%d\n",
|
||||
__func__,
|
||||
spdif_id);
|
||||
|
||||
/* free frddr, then frddr in mngr */
|
||||
frddr_deinit_without_mngr(spdif_id);
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
#include <linux/amlogic/media/sound/spdif_info.h>
|
||||
|
||||
extern unsigned int aml_spdif_ctrl_read(struct aml_audio_controller *actrl,
|
||||
int stream, int index);
|
||||
extern void aml_spdif_ctrl_write(struct aml_audio_controller *actrl,
|
||||
int stream, int index, int val);
|
||||
extern void aml_spdifin_chnum_en(struct aml_audio_controller *actrl,
|
||||
int index, bool is_enable);
|
||||
extern void aml_spdif_enable(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream,
|
||||
@@ -38,6 +44,8 @@ extern void aml_spdif_arb_config(struct aml_audio_controller *actrl);
|
||||
|
||||
extern int aml_spdifin_status_check(
|
||||
struct aml_audio_controller *actrl);
|
||||
extern void aml_spdifin_clr_irq(struct aml_audio_controller *actrl,
|
||||
bool is_all_bits, int clr_bits_val);
|
||||
|
||||
extern void aml_spdif_fifo_reset(
|
||||
struct aml_audio_controller *actrl,
|
||||
@@ -69,6 +77,8 @@ extern void spdifout_enable(int spdif_id, bool is_enable);
|
||||
|
||||
extern int spdifin_get_sample_rate(void);
|
||||
|
||||
extern int spdifin_get_ch_status0to31(void);
|
||||
|
||||
extern int spdifin_get_audio_type(void);
|
||||
|
||||
extern void spdif_set_channel_status_info(
|
||||
|
||||
@@ -451,6 +451,7 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
|
||||
enum toddr_src src;
|
||||
unsigned int lsb = 32 - bit_depth;
|
||||
unsigned int toddr_type;
|
||||
struct toddr_fmt fmt;
|
||||
|
||||
switch (bit_depth) {
|
||||
case 8:
|
||||
@@ -484,10 +485,15 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fmt.type = toddr_type;
|
||||
fmt.msb = 31;
|
||||
fmt.lsb = lsb;
|
||||
fmt.endian = 0;
|
||||
fmt.bit_depth = bit_depth;
|
||||
fmt.ch_num = runtime->channels;
|
||||
fmt.rate = runtime->rate;
|
||||
aml_toddr_select_src(to, src);
|
||||
aml_toddr_set_format(to, toddr_type, 31, lsb,
|
||||
runtime->channels,
|
||||
bit_depth);
|
||||
aml_toddr_set_format(to, &fmt);
|
||||
aml_toddr_set_fifos(to, 0x40);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user