mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
audio: auge: fix drivers for tl1 [1/1]
PD#172587 Problem: resample, eqdrc, dolby efuse, audio input (from atv, hdmirx) Solution: add drivers for them Verify: x301 Change-Id: I5187f9824d904283794f6e4be3dd9ce8463908e1 Signed-off-by: Xing Wang <xing.wang@amlogic.com> Conflicts: arch/arm/boot/dts/amlogic/mesontl1.dtsi arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
This commit is contained in:
12
MAINTAINERS
12
MAINTAINERS
@@ -14668,15 +14668,13 @@ M: Luan Yuan <luan.yuan@amlogic.com>
|
||||
F: arch/arm/boot/dts/amlogic/partition_mbox_p241_P.dtsi
|
||||
|
||||
AMLOGIC TL1 SOUND CARD
|
||||
M: Xing Wang <xing.wang@amlogic.com
|
||||
F: include/dt-bindings/clock/amlogic,tl1-audio-clk.h
|
||||
F: sound/soc/amlogic/auge/*
|
||||
|
||||
AMLOGIC TL1 AUDIO EXTERANL INPUT/OUTPUT DRIVERS
|
||||
AMLOGIC TL1 NEW EQDRC
|
||||
AMLOGIC TL1 MIXER CONTROLS
|
||||
M: Xing Wang <xing.wang@amlogic.com
|
||||
F: sound/soc/amlogic/auge/extn.c
|
||||
F: sound/soc/amlogic/auge/frhdmirx_hw.c
|
||||
F: sound/soc/amlogic/auge/frhdmirx_hw.h
|
||||
F: arch/arm/boot/dts/amlogic/tl1_pxp.dts
|
||||
F: include/dt-bindings/clock/amlogic,tl1-audio-clk.h
|
||||
F: include/linux/amlogic/media/sound/misc.h
|
||||
F: sound/soc/amlogic/auge/*
|
||||
|
||||
AMLOGIC LCD DRIVERS
|
||||
|
||||
@@ -1082,6 +1082,58 @@
|
||||
compatible = "amlogic, vdac-tl1";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dmc_monitor {
|
||||
compatible = "amlogic, dmc_monitor";
|
||||
status = "okay";
|
||||
reg_base = <0xff638800>;
|
||||
interrupts = <GIC_SPI 51 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
|
||||
efuse: efuse{
|
||||
compatible = "amlogic, efuse";
|
||||
read_cmd = <0x82000030>;
|
||||
write_cmd = <0x82000031>;
|
||||
get_max_cmd = <0x82000033>;
|
||||
key = <&efusekey>;
|
||||
clocks = <&clkc CLKID_EFUSE>;
|
||||
clock-names = "efuse_clk";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
efusekey:efusekey{
|
||||
keynum = <4>;
|
||||
key0 = <&key_0>;
|
||||
key1 = <&key_1>;
|
||||
key2 = <&key_2>;
|
||||
key3 = <&key_3>;
|
||||
key_0:key_0{
|
||||
keyname = "mac";
|
||||
offset = <0>;
|
||||
size = <6>;
|
||||
};
|
||||
key_1:key_1{
|
||||
keyname = "mac_bt";
|
||||
offset = <6>;
|
||||
size = <6>;
|
||||
};
|
||||
key_2:key_2{
|
||||
keyname = "mac_wifi";
|
||||
offset = <12>;
|
||||
size = <6>;
|
||||
};
|
||||
key_3:key_3{
|
||||
keyname = "usid";
|
||||
offset = <18>;
|
||||
size = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
audio_data: audio_data {
|
||||
compatible = "amlogic, audio_data";
|
||||
query_licence_cmd = <0x82000050>;
|
||||
status = "disabled";
|
||||
};
|
||||
}; /* end of / */
|
||||
|
||||
&pinctrl_aobus {
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
/* suffix-name, sync with android audio hal used for */
|
||||
suffix-name = "alsaPORT-spdif";
|
||||
cpu {
|
||||
sound-dai = <&spdif_a>;
|
||||
sound-dai = <&spdifa>;
|
||||
system-clock-frequency = <6144000>;
|
||||
};
|
||||
codec {
|
||||
@@ -295,7 +295,7 @@
|
||||
aml-audio-card,dai-link@5 {
|
||||
mclk-fs = <128>;
|
||||
cpu {
|
||||
sound-dai = <&spdif_b>;
|
||||
sound-dai = <&spdifb>;
|
||||
system-clock-frequency = <6144000>;
|
||||
};
|
||||
codec {
|
||||
@@ -473,7 +473,7 @@
|
||||
}; /* end of / */
|
||||
|
||||
&audiobus {
|
||||
tdma:tdm {
|
||||
tdma:tdm@0 {
|
||||
compatible = "amlogic, tl1-snd-tdma";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
@@ -491,7 +491,7 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
tdmb:tdm {
|
||||
tdmb:tdm@1 {
|
||||
compatible = "amlogic, tl1-snd-tdmb";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
@@ -506,7 +506,7 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
tdmc:tdm {
|
||||
tdmc:tdm@2 {
|
||||
compatible = "amlogic, tl1-snd-tdmc";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
@@ -524,16 +524,16 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spdif_a:spdif {
|
||||
spdifa:spdif@0 {
|
||||
compatible = "amlogic, tl1-snd-spdif-a";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&clkc CLKID_MPLL0
|
||||
&clkc CLKID_FCLK_DIV4
|
||||
&clkaudio CLKID_AUDIO_GATE_SPDIFIN
|
||||
&clkaudio CLKID_AUDIO_GATE_SPDIFOUT_A
|
||||
&clkaudio CLKID_AUDIO_SPDIFIN
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUT
|
||||
&clkaudio CLKID_AUDIO_SPDIFIN_CTRL
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUT_CTRL>;
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUT_A>;
|
||||
clock-names = "sysclk", "fixed_clk", "gate_spdifin",
|
||||
"gate_spdifout", "clk_spdifin", "clk_spdifout";
|
||||
|
||||
@@ -544,16 +544,31 @@
|
||||
pinctrl-names = "spdif_pins";
|
||||
pinctrl-0 = <&spdifout_a &spdifin_a>;
|
||||
|
||||
/*
|
||||
* whether do asrc for pcm and resample a or b
|
||||
* 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",
|
||||
*/
|
||||
asrc_id = <0>;
|
||||
auto_asrc = <0>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spdif_b:spdif {
|
||||
spdifb:spdif@1 {
|
||||
compatible = "amlogic, tl1-snd-spdif-b";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&clkc CLKID_MPLL0 /*CLKID_HIFI_PLL*/
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUTB
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUTB_CTRL>;
|
||||
&clkaudio CLKID_AUDIO_GATE_SPDIFOUT_B
|
||||
&clkaudio CLKID_AUDIO_SPDIFOUT_B>;
|
||||
clock-names = "sysclk",
|
||||
"gate_spdifout", "clk_spdifout";
|
||||
|
||||
@@ -564,7 +579,7 @@
|
||||
compatible = "amlogic, tl1-snd-pdm";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&clkaudio CLKID_AUDIO_PDM
|
||||
clocks = <&clkaudio CLKID_AUDIO_GATE_PDM
|
||||
&clkc CLKID_FCLK_DIV3
|
||||
&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_PDMIN0
|
||||
@@ -595,6 +610,78 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aed:effect {
|
||||
compatible = "amlogic, snd-effect-v2";
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
clocks = <&clkaudio CLKID_AUDIO_GATE_EQDRC
|
||||
&clkc CLKID_FCLK_DIV5
|
||||
&clkaudio CLKID_AUDIO_EQDRC>;
|
||||
clock-names = "gate", "clk_srcpll", "eqdrc";
|
||||
|
||||
eq_enable = <1>;
|
||||
multiband_drc_enable = <0>;
|
||||
fullband_drc_enable = <0>;
|
||||
/*
|
||||
* 0:tdmout_a
|
||||
* 1:tdmout_b
|
||||
* 2:tdmout_c
|
||||
* 3:spdifout
|
||||
* 4:spdifout_b
|
||||
*/
|
||||
eqdrc_module = <1>;
|
||||
/* max 0xf, each bit for one lane, usually one lane */
|
||||
lane_mask = <0x1>;
|
||||
/* max 0xff, each bit for one channel */
|
||||
channel_mask = <0x3>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
asrca: resample@0 {
|
||||
compatible = "amlogic, tl1-resample-a";
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_A>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
/*same with toddr_src
|
||||
* TDMIN_A, 0
|
||||
* TDMIN_B, 1
|
||||
* TDMIN_C, 2
|
||||
* SPDIFIN, 3
|
||||
* PDMIN, 4
|
||||
* NONE,
|
||||
* TDMIN_LB, 6
|
||||
* LOOPBACK, 7
|
||||
*/
|
||||
resample_module = <3>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
asrcb: resample@1 {
|
||||
compatible = "amlogic, tl1-resample-b";
|
||||
|
||||
clocks = <&clkc CLKID_MPLL3
|
||||
&clkaudio CLKID_AUDIO_MCLK_F
|
||||
&clkaudio CLKID_AUDIO_RESAMPLE_B>;
|
||||
clock-names = "resample_pll", "resample_src", "resample_clk";
|
||||
|
||||
/*same with toddr_src
|
||||
* TDMIN_A, 0
|
||||
* TDMIN_B, 1
|
||||
* TDMIN_C, 2
|
||||
* SPDIFIN, 3
|
||||
* PDMIN, 4
|
||||
* NONE,
|
||||
* TDMIN_LB, 6
|
||||
* LOOPBACK, 7
|
||||
*/
|
||||
resample_module = <3>;
|
||||
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
}; /* end of audiobus */
|
||||
|
||||
&pinctrl_periphs {
|
||||
|
||||
1390
arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts
Normal file
1390
arch/arm/boot/dts/amlogic/tl1_t962x2_skt.dts
Normal file
File diff suppressed because it is too large
Load Diff
1403
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
Normal file
1403
arch/arm/boot/dts/amlogic/tl1_t962x2_x301.dts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,45 +15,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TL1_AUDIO_CLK_H
|
||||
#define __TL1_AUDIO_CLK_H
|
||||
#ifndef __TL1_AUDIO_CLK_H__
|
||||
#define __TL1_AUDIO_CLK_H__
|
||||
|
||||
/*
|
||||
* CLKID audio index values
|
||||
*/
|
||||
|
||||
#define CLKID_AUDIO_DDR_ARB 0
|
||||
#define CLKID_AUDIO_PDM 1
|
||||
#define CLKID_AUDIO_TDMINA 2
|
||||
#define CLKID_AUDIO_TDMINB 3
|
||||
#define CLKID_AUDIO_TDMINC 4
|
||||
#define CLKID_AUDIO_TDMINLB 5
|
||||
#define CLKID_AUDIO_TDMOUTA 6
|
||||
#define CLKID_AUDIO_TDMOUTB 7
|
||||
#define CLKID_AUDIO_TDMOUTC 8
|
||||
#define CLKID_AUDIO_FRDDRA 9
|
||||
#define CLKID_AUDIO_FRDDRB 10
|
||||
#define CLKID_AUDIO_FRDDRC 11
|
||||
#define CLKID_AUDIO_TODDRA 12
|
||||
#define CLKID_AUDIO_TODDRB 13
|
||||
#define CLKID_AUDIO_TODDRC 14
|
||||
#define CLKID_AUDIO_LOOPBACKA 15
|
||||
#define CLKID_AUDIO_SPDIFIN 16
|
||||
#define CLKID_AUDIO_SPDIFOUT 17
|
||||
#define CLKID_AUDIO_RESAMPLEA 18
|
||||
#define CLKID_AUDIO_RESERVED0 19
|
||||
#define CLKID_AUDIO_RESERVED1 20
|
||||
#define CLKID_AUDIO_SPDIFOUTB 21
|
||||
#define CLKID_AUDIO_EQDRC 22
|
||||
#define CLKID_AUDIO_RESAMPLEB 23
|
||||
#define CLKID_AUDIO_TOVAD 24
|
||||
#define CLKID_AUDIO_AUDIOLOCKER 25
|
||||
#define CLKID_AUDIO_SPDIFIN_LB 26
|
||||
#define CLKID_AUDIO_FRATV 27
|
||||
#define CLKID_AUDIO_FRHDMIRX 28
|
||||
#define CLKID_AUDIO_FRDDRD 29
|
||||
#define CLKID_AUDIO_TODDRD 30
|
||||
#define CLKID_AUDIO_LOOPBACKB 31
|
||||
#define CLKID_AUDIO_GATE_DDR_ARB 0
|
||||
#define CLKID_AUDIO_GATE_PDM 1
|
||||
#define CLKID_AUDIO_GATE_TDMINA 2
|
||||
#define CLKID_AUDIO_GATE_TDMINB 3
|
||||
#define CLKID_AUDIO_GATE_TDMINC 4
|
||||
#define CLKID_AUDIO_GATE_TDMINLB 5
|
||||
#define CLKID_AUDIO_GATE_TDMOUTA 6
|
||||
#define CLKID_AUDIO_GATE_TDMOUTB 7
|
||||
#define CLKID_AUDIO_GATE_TDMOUTC 8
|
||||
#define CLKID_AUDIO_GATE_FRDDRA 9
|
||||
#define CLKID_AUDIO_GATE_FRDDRB 10
|
||||
#define CLKID_AUDIO_GATE_FRDDRC 11
|
||||
#define CLKID_AUDIO_GATE_TODDRA 12
|
||||
#define CLKID_AUDIO_GATE_TODDRB 13
|
||||
#define CLKID_AUDIO_GATE_TODDRC 14
|
||||
#define CLKID_AUDIO_GATE_LOOPBACKA 15
|
||||
#define CLKID_AUDIO_GATE_SPDIFIN 16
|
||||
#define CLKID_AUDIO_GATE_SPDIFOUT_A 17
|
||||
#define CLKID_AUDIO_GATE_RESAMPLEA 18
|
||||
#define CLKID_AUDIO_GATE_RESERVED0 19
|
||||
#define CLKID_AUDIO_GATE_RESERVED1 20
|
||||
#define CLKID_AUDIO_GATE_SPDIFOUT_B 21
|
||||
#define CLKID_AUDIO_GATE_EQDRC 22
|
||||
#define CLKID_AUDIO_GATE_RESAMPLEB 23
|
||||
#define CLKID_AUDIO_GATE_TOVAD 24
|
||||
#define CLKID_AUDIO_GATE_AUDIOLOCKER 25
|
||||
#define CLKID_AUDIO_GATE_SPDIFIN_LB 26
|
||||
#define CLKID_AUDIO_GATE_FRATV 27
|
||||
#define CLKID_AUDIO_GATE_FRHDMIRX 28
|
||||
#define CLKID_AUDIO_GATE_FRDDRD 29
|
||||
#define CLKID_AUDIO_GATE_TODDRD 30
|
||||
#define CLKID_AUDIO_GATE_LOOPBACKB 31
|
||||
|
||||
#define MCLK_BASE 32
|
||||
#define CLKID_AUDIO_MCLK_A (MCLK_BASE + 0)
|
||||
@@ -63,14 +63,18 @@
|
||||
#define CLKID_AUDIO_MCLK_E (MCLK_BASE + 4)
|
||||
#define CLKID_AUDIO_MCLK_F (MCLK_BASE + 5)
|
||||
|
||||
#define CLKID_AUDIO_SPDIFIN_CTRL (MCLK_BASE + 6)
|
||||
#define CLKID_AUDIO_SPDIFOUT_CTRL (MCLK_BASE + 7)
|
||||
#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 8)
|
||||
#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 9)
|
||||
#define CLKID_AUDIO_SPDIFOUTB_CTRL (MCLK_BASE + 10)
|
||||
#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 11)
|
||||
#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 12)
|
||||
#define CLKID_AUDIO_RESAMPLE_CTRL (MCLK_BASE + 13)
|
||||
#define CLKID_AUDIO_SPDIFIN (MCLK_BASE + 6)
|
||||
#define CLKID_AUDIO_SPDIFOUT_A (MCLK_BASE + 7)
|
||||
#define CLKID_AUDIO_RESAMPLE_A (MCLK_BASE + 8)
|
||||
#define CLKID_AUDIO_LOCKER_OUT (MCLK_BASE + 9)
|
||||
#define CLKID_AUDIO_LOCKER_IN (MCLK_BASE + 10)
|
||||
#define CLKID_AUDIO_PDMIN0 (MCLK_BASE + 11)
|
||||
#define CLKID_AUDIO_PDMIN1 (MCLK_BASE + 12)
|
||||
#define CLKID_AUDIO_SPDIFOUT_B (MCLK_BASE + 13)
|
||||
#define CLKID_AUDIO_RESAMPLE_B (MCLK_BASE + 14)
|
||||
#define CLKID_AUDIO_SPDIFIN_LB (MCLK_BASE + 15)
|
||||
#define CLKID_AUDIO_EQDRC (MCLK_BASE + 16)
|
||||
#define CLKID_AUDIO_VAD (MCLK_BASE + 17)
|
||||
|
||||
#define NUM_AUDIO_CLKS (MCLK_BASE + 14)
|
||||
#endif /* __G12A_AUDIO_CLK_H */
|
||||
#define NUM_AUDIO_CLKS (MCLK_BASE + 18)
|
||||
#endif /* __TL1_AUDIO_CLK_H__ */
|
||||
|
||||
@@ -490,4 +490,6 @@ extern int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara);
|
||||
extern void tvafe_set_ddemod_default(void);/* add for dtv demod*/
|
||||
extern void rx_get_audio_status(struct rx_audio_stat_s *aud_sts);
|
||||
|
||||
extern void rx_set_atmos_flag(bool en);
|
||||
extern bool rx_get_atmos_flag(void);
|
||||
#endif
|
||||
|
||||
67
include/linux/amlogic/media/sound/misc.h
Normal file
67
include/linux/amlogic/media/sound/misc.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* include/linux/amlogic/media/sound/misc.h
|
||||
*
|
||||
* Copyright (C) 2017 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 __MISC_H__
|
||||
#define __MISC_H__
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/control.h>
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
extern const struct soc_enum atv_audio_status_enum;
|
||||
|
||||
int aml_get_atv_audio_stable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
extern int update_spdifin_audio_type(int audio_type);
|
||||
|
||||
extern const struct soc_enum hdmi_in_status_enum[];
|
||||
|
||||
extern int get_hdmi_sample_rate_index(void);
|
||||
|
||||
extern int aml_get_hdmiin_audio_stable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int aml_get_hdmiin_audio_samplerate(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int aml_get_hdmiin_audio_channels(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int aml_get_hdmiin_audio_format(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int aml_set_atmos_audio_edid(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int aml_get_atmos_audio_edid(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -18,7 +18,9 @@
|
||||
#ifndef __SPDIF_INFO_H__
|
||||
#define __SPDIF_INFO_H__
|
||||
|
||||
#include <sound/soc.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/control.h>
|
||||
|
||||
struct iec958_chsts {
|
||||
unsigned short chstat0_l;
|
||||
@@ -34,4 +36,13 @@ extern void spdif_get_channel_status_info(struct iec958_chsts *chsts,
|
||||
|
||||
extern void spdif_notify_to_hdmitx(struct snd_pcm_substream *substream);
|
||||
|
||||
extern const struct soc_enum spdif_format_enum;
|
||||
|
||||
extern int spdif_format_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
|
||||
extern int spdif_format_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol);
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,8 @@ obj-$(CONFIG_AMLOGIC_SND_SOC_AUGE) += audio_controller.o \
|
||||
resample_hw.o \
|
||||
effects.o \
|
||||
effects_hw.o \
|
||||
effects_v2.o \
|
||||
effects_hw_v2.o \
|
||||
pwrdet.o \
|
||||
pwrdet_hw.o \
|
||||
sharebuffer.o \
|
||||
|
||||
@@ -103,7 +103,7 @@ static int register_audio_controller(struct platform_device *pdev,
|
||||
platform_set_drvdata(pdev, actrl);
|
||||
|
||||
/* gate on all clks on bringup stage, need gate separately */
|
||||
aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN0, 0xffffff);
|
||||
aml_audiobus_write(actrl, EE_AUDIO_CLK_GATE_EN0, 0xffffffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "tdm_hw.h"
|
||||
#include "ddr_mngr.h"
|
||||
#include "resample.h"
|
||||
#include "effects_v2.h"
|
||||
|
||||
#include <linux/amlogic/iomap.h>
|
||||
#include <linux/amlogic/media/sound/auge_utils.h>
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
@@ -943,6 +945,12 @@ int snd_card_add_kcontrols(struct snd_soc_card *card)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = card_add_effect_v2_kcontrols(card);
|
||||
if (ret < 0) {
|
||||
pr_err("Failed to add AED v2 controls\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snd_soc_add_card_controls(card,
|
||||
snd_auge_controls, ARRAY_SIZE(snd_auge_controls));
|
||||
|
||||
@@ -1505,3 +1513,10 @@ void fratv_src_select(int src)
|
||||
{
|
||||
audiobus_update_bits(EE_AUDIO_FRATV_CTRL0, 0x1 << 20, (bool)src << 20);
|
||||
}
|
||||
|
||||
void cec_arc_enable(int src, bool enable)
|
||||
{
|
||||
aml_hiubus_update_bits(HHI_HDMIRX_ARC_CNTL,
|
||||
0x1f << 0,
|
||||
src << 2 | enable << 1 | 0x0 << 0);
|
||||
}
|
||||
|
||||
@@ -162,4 +162,6 @@ extern int audio_locker_get(void);
|
||||
|
||||
extern void fratv_enable(bool enable);
|
||||
extern void fratv_src_select(int src);
|
||||
|
||||
extern void cec_arc_enable(int src, bool enable);
|
||||
#endif
|
||||
|
||||
@@ -982,12 +982,11 @@ static int aml_card_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (priv->chipinfo && priv->chipinfo->eqdrc_fn) {
|
||||
pr_info("eq/drc function enable\n");
|
||||
pr_info("eq/drc v1 function enable\n");
|
||||
ret = card_add_effects_init(&priv->snd_card);
|
||||
if (ret < 0)
|
||||
pr_warn_once("Failed to add audio effects controls\n");
|
||||
} else
|
||||
pr_info("not support eq/drc function\n");
|
||||
pr_warn_once("Failed to add audio effects v1 controls\n");
|
||||
}
|
||||
|
||||
if (priv->hp_det_enable == 1 || priv->mic_det_enable == 1) {
|
||||
audio_jack_detect(priv);
|
||||
|
||||
@@ -27,8 +27,11 @@
|
||||
#include "ddr_mngr.h"
|
||||
#include "audio_utils.h"
|
||||
|
||||
#include "resample.h"
|
||||
#include "resample_hw.h"
|
||||
#include "effects_hw.h"
|
||||
#include "effects_hw_v2.h"
|
||||
#include "effects_v2.h"
|
||||
#include "pwrdet_hw.h"
|
||||
|
||||
#define DRV_NAME "audio-ddr-manager"
|
||||
@@ -64,6 +67,10 @@ struct ddr_chipinfo {
|
||||
bool same_src_fn;
|
||||
/* insert channel number */
|
||||
bool insert_chnum;
|
||||
|
||||
/* ddr bus in urgent */
|
||||
bool ugt;
|
||||
|
||||
/* source sel switch to ctrl1
|
||||
* for toddr, 0: source sel is controlled by ctrl0
|
||||
* 1: source sel is controlled by ctrl1
|
||||
@@ -71,6 +78,16 @@ struct ddr_chipinfo {
|
||||
* 1: source sel is controlled by ctrl2
|
||||
*/
|
||||
bool src_sel_ctrl;
|
||||
|
||||
/*
|
||||
* resample source sel switch
|
||||
* resample : from ctrl0 to ctrl3
|
||||
* toddr : from ctrl0 to ctrl1
|
||||
*/
|
||||
bool asrc_src_sel_ctrl;
|
||||
/* spdif in 32bit, only support left justified */
|
||||
bool asrc_only_left_j;
|
||||
|
||||
/* toddr number max
|
||||
* 0: default, 3 toddr, axg, g12a, g12b
|
||||
* 4: 4 toddr, tl1
|
||||
@@ -92,6 +109,8 @@ struct toddr {
|
||||
enum toddr_src src;
|
||||
unsigned int fifo_id;
|
||||
|
||||
unsigned int asrc_src_sel;
|
||||
|
||||
int is_lb; /* check whether for loopback */
|
||||
int irq;
|
||||
bool in_use: 1;
|
||||
@@ -107,6 +126,7 @@ enum status {
|
||||
|
||||
struct toddr_attach {
|
||||
bool enable;
|
||||
int id;
|
||||
int status;
|
||||
/* which module should be attached,
|
||||
* check which toddr in use should be attached
|
||||
@@ -130,6 +150,10 @@ struct frddr {
|
||||
struct aml_audio_controller *actrl;
|
||||
unsigned int reg_base;
|
||||
unsigned int fifo_id;
|
||||
|
||||
unsigned int msb;
|
||||
unsigned int type;
|
||||
|
||||
int irq;
|
||||
bool in_use;
|
||||
struct ddr_chipinfo *chipinfo;
|
||||
@@ -140,9 +164,9 @@ static struct frddr frddrs[DDRMAX];
|
||||
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);
|
||||
static struct toddr_attach attach_resample_a;
|
||||
static struct toddr_attach attach_resample_b;
|
||||
static void aml_check_resample(struct toddr *to, bool enable);
|
||||
|
||||
/* power detect */
|
||||
static struct toddr_attach attach_pwrdet;
|
||||
@@ -357,8 +381,7 @@ void aml_toddr_enable(struct toddr *to, bool enable)
|
||||
aml_audiobus_update_bits(actrl, reg, 1<<31, enable<<31);
|
||||
|
||||
/* check resample */
|
||||
if (aml_check_resample_module(to->src))
|
||||
aml_check_resample(enable);
|
||||
aml_check_resample(to, enable);
|
||||
|
||||
/* check power detect */
|
||||
if (aml_check_pwrdet_module(to->src))
|
||||
@@ -381,7 +404,7 @@ void aml_toddr_select_src(struct toddr *to, enum toddr_src src)
|
||||
if (loopback_check_enable(src)) {
|
||||
loopback_set_status(1);
|
||||
to->is_lb = 1; /* in loopback */
|
||||
src = LOOPBACK;
|
||||
src = LOOPBACK_A;
|
||||
}
|
||||
|
||||
if (to->chipinfo
|
||||
@@ -414,6 +437,11 @@ void aml_toddr_set_fifos(struct toddr *to, unsigned int thresh)
|
||||
}
|
||||
|
||||
aml_audiobus_update_bits(actrl, reg, mask, val);
|
||||
|
||||
if (to->chipinfo && to->chipinfo->ugt) {
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0);
|
||||
}
|
||||
}
|
||||
|
||||
void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
|
||||
@@ -477,13 +505,60 @@ void aml_toddr_set_resample(struct toddr *to, bool enable)
|
||||
aml_audiobus_update_bits(actrl, reg, 1<<30, enable<<30);
|
||||
}
|
||||
|
||||
static void aml_set_resample(struct toddr *to,
|
||||
void aml_toddr_set_resample_ab(struct toddr *to, int asrc_src_sel, 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 %c\n",
|
||||
enable ? "enable" : "disable",
|
||||
(asrc_src_sel == 0) ? 'a' : 'b');
|
||||
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL1, reg_base);
|
||||
if (asrc_src_sel == 0)
|
||||
aml_audiobus_update_bits(actrl, reg, 1 << 27, enable << 27);
|
||||
else
|
||||
aml_audiobus_update_bits(actrl, reg, 1 << 26, enable << 26);
|
||||
}
|
||||
|
||||
static void aml_resample_enable(
|
||||
struct toddr_attach *p_attach_resample,
|
||||
bool enable)
|
||||
{
|
||||
struct toddr *to = fetch_toddr_by_src(p_attach_resample->attach_module);
|
||||
|
||||
if (!to)
|
||||
return;
|
||||
|
||||
if (to->chipinfo
|
||||
&& to->chipinfo->asrc_src_sel_ctrl) {
|
||||
/* fix asrc_src_sel */
|
||||
switch (p_attach_resample->attach_module) {
|
||||
case LOOPBACK_A:
|
||||
to->asrc_src_sel = ASRC_LOOPBACK_A;
|
||||
break;
|
||||
case LOOPBACK_B:
|
||||
to->asrc_src_sel = ASRC_LOOPBACK_B;
|
||||
break;
|
||||
default:
|
||||
to->asrc_src_sel = to->fifo_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("Resample %d in running, module:%d, toddr:%d, asrc_src_sel:%d\n",
|
||||
p_attach_resample->id,
|
||||
p_attach_resample->attach_module,
|
||||
to->fifo_id,
|
||||
to->asrc_src_sel);
|
||||
|
||||
if (enable) {
|
||||
int bitwidth = to->bitdepth;
|
||||
/* channels and bit depth for resample */
|
||||
if ((to->src == SPDIFIN) && (bitwidth == 32)) {
|
||||
if (to->chipinfo
|
||||
&& to->chipinfo->asrc_only_left_j
|
||||
&& (to->src == SPDIFIN)
|
||||
&& (bitwidth == 32)) {
|
||||
struct aml_audio_controller *actrl = to->actrl;
|
||||
unsigned int reg_base = to->reg_base;
|
||||
unsigned int reg;
|
||||
@@ -502,85 +577,103 @@ static void aml_set_resample(struct toddr *to,
|
||||
0x7 << 24 | 0x7 << 13,
|
||||
endian << 24 | toddr_type << 13);
|
||||
}
|
||||
resample_format_set(to->channels, bitwidth);
|
||||
|
||||
resample_format_set(p_attach_resample->id,
|
||||
to->channels, bitwidth);
|
||||
|
||||
/* toddr index for resample */
|
||||
resample_src_select(to->fifo_id);
|
||||
if (to->chipinfo
|
||||
&& to->chipinfo->asrc_src_sel_ctrl)
|
||||
resample_src_select_ab(p_attach_resample->id,
|
||||
to->asrc_src_sel);
|
||||
else
|
||||
resample_src_select(to->fifo_id);
|
||||
}
|
||||
|
||||
/* resample enable or not */
|
||||
resample_enable(enable);
|
||||
resample_enable(p_attach_resample->id, enable);
|
||||
|
||||
/* select reample data */
|
||||
aml_toddr_set_resample(to, enable);
|
||||
if (to->chipinfo
|
||||
&& to->chipinfo->asrc_src_sel_ctrl)
|
||||
aml_toddr_set_resample_ab(to, p_attach_resample->id, enable);
|
||||
else
|
||||
aml_toddr_set_resample(to, enable);
|
||||
}
|
||||
|
||||
void aml_resample_enable(bool enable, int resample_module)
|
||||
void aml_set_resample(int id, bool enable, int resample_module)
|
||||
{
|
||||
attach_resample.enable = enable;
|
||||
attach_resample.attach_module = resample_module;
|
||||
struct toddr_attach *p_attach_resample;
|
||||
|
||||
aml_check_resample(enable);
|
||||
}
|
||||
bool update_running = false;
|
||||
|
||||
static bool aml_check_resample_module(int src)
|
||||
{
|
||||
bool is_module_resample = false;
|
||||
if (id == 0)
|
||||
p_attach_resample = &attach_resample_a;
|
||||
else
|
||||
p_attach_resample = &attach_resample_b;
|
||||
|
||||
if (attach_resample.enable
|
||||
&& (src == attach_resample.attach_module))
|
||||
is_module_resample = true;
|
||||
p_attach_resample->enable = enable;
|
||||
p_attach_resample->id = id;
|
||||
p_attach_resample->attach_module = resample_module;
|
||||
|
||||
return is_module_resample;
|
||||
if (enable) {
|
||||
if ((p_attach_resample->status == DISABLED)
|
||||
|| (p_attach_resample->status == READY)) {
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
p_attach_resample->attach_module);
|
||||
|
||||
if (!to) {
|
||||
p_attach_resample->status = READY;
|
||||
} else {
|
||||
p_attach_resample->status = RUNNING;
|
||||
update_running = true;
|
||||
pr_info("Capture with resample\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (p_attach_resample->status == RUNNING)
|
||||
update_running = true;
|
||||
|
||||
p_attach_resample->status = DISABLED;
|
||||
}
|
||||
|
||||
if (update_running)
|
||||
aml_resample_enable(p_attach_resample, enable);
|
||||
}
|
||||
|
||||
/*
|
||||
* when try to enable resample, if toddr is not in used,
|
||||
* set resample status as ready
|
||||
*/
|
||||
static void aml_check_resample(bool enable)
|
||||
static void aml_check_resample(struct toddr *to, bool enable)
|
||||
{
|
||||
struct toddr_attach *p_attach_resample;
|
||||
bool is_module_resample;
|
||||
bool resample_b_check = false;
|
||||
|
||||
p_attach_resample = &attach_resample_a;
|
||||
|
||||
start_check:
|
||||
is_module_resample = false;
|
||||
if (p_attach_resample->enable
|
||||
&& (to->src == p_attach_resample->attach_module))
|
||||
is_module_resample = true;
|
||||
|
||||
/* resample in enable */
|
||||
if (attach_resample.enable) {
|
||||
if (enable) {
|
||||
/* check whether ready ? */
|
||||
if ((attach_resample.status == DISABLED)
|
||||
|| (attach_resample.status == READY)) {
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
attach_resample.attach_module);
|
||||
if (is_module_resample) {
|
||||
if (enable)
|
||||
p_attach_resample->status = RUNNING;
|
||||
else
|
||||
p_attach_resample->status = DISABLED;
|
||||
|
||||
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) {
|
||||
struct toddr *to = fetch_toddr_by_src(
|
||||
attach_resample.attach_module);
|
||||
aml_resample_enable(p_attach_resample, enable);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if ((!resample_b_check)
|
||||
&& (get_resample_module_num() == 2)) {
|
||||
p_attach_resample = &attach_resample_b;
|
||||
resample_b_check = true;
|
||||
goto start_check;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,6 +1060,11 @@ void aml_frddr_set_fifos(struct frddr *fr,
|
||||
aml_audiobus_update_bits(actrl, reg,
|
||||
0xffff<<16 | 0xf<<8,
|
||||
(depth - 1)<<24 | (thresh - 1)<<16 | 2<<8);
|
||||
|
||||
if (fr->chipinfo && fr->chipinfo->ugt) {
|
||||
reg = calc_toddr_address(EE_AUDIO_FRDDR_A_CTRL0, reg_base);
|
||||
aml_audiobus_update_bits(actrl, reg, 0x0 << 0, 0x1 << 0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int aml_frddr_get_fifo_id(struct frddr *fr)
|
||||
@@ -974,23 +1072,54 @@ unsigned int aml_frddr_get_fifo_id(struct frddr *fr)
|
||||
return fr->fifo_id;
|
||||
}
|
||||
|
||||
static void aml_set_aed(struct frddr *fr, bool enable)
|
||||
void aml_frddr_set_format(struct frddr *fr,
|
||||
unsigned int msb, unsigned int frddr_type)
|
||||
{
|
||||
if (enable) {
|
||||
/* frddr type and bit depth for AED */
|
||||
aml_aed_format_set(fr->dest);
|
||||
}
|
||||
aed_src_select(enable, fr->dest, fr->fifo_id);
|
||||
fr->msb = msb;
|
||||
fr->type = frddr_type;
|
||||
}
|
||||
|
||||
|
||||
void aml_aed_enable(bool enable, int aed_module)
|
||||
static void aml_aed_enable(struct frddr_attach *p_attach_aed, bool enable)
|
||||
{
|
||||
struct frddr *fr = fetch_frddr_by_src(p_attach_aed->attach_module);
|
||||
|
||||
|
||||
if (check_aed_v2()) {
|
||||
if (fr->chipinfo
|
||||
&& fr->chipinfo->src_sel_ctrl) {
|
||||
struct aml_audio_controller *actrl = fr->actrl;
|
||||
unsigned int reg_base = fr->reg_base;
|
||||
unsigned int reg;
|
||||
|
||||
reg = calc_frddr_address(EE_AUDIO_FRDDR_A_CTRL2,
|
||||
reg_base);
|
||||
aml_audiobus_update_bits(actrl,
|
||||
reg, 0x1 << 3, enable << 3);
|
||||
}
|
||||
|
||||
aed_set_ctrl(enable, 0, p_attach_aed->attach_module);
|
||||
aed_set_format(fr->msb, fr->type);
|
||||
aed_enable(enable, fr->dest, fr->fifo_id);
|
||||
} else {
|
||||
if (enable) {
|
||||
/* frddr type and bit depth for AED */
|
||||
aml_aed_format_set(fr->dest);
|
||||
}
|
||||
aed_src_select(enable, fr->dest, fr->fifo_id);
|
||||
}
|
||||
}
|
||||
|
||||
void aml_set_aed(bool enable, int aed_module)
|
||||
{
|
||||
bool update_running = false;
|
||||
|
||||
/* when try to enable AED, if frddr is not in used,
|
||||
* set AED status as ready
|
||||
*/
|
||||
attach_aed.enable = enable;
|
||||
attach_aed.attach_module = aed_module;
|
||||
|
||||
if (enable) {
|
||||
if ((attach_aed.status == DISABLED)
|
||||
|| (attach_aed.status == READY)) {
|
||||
@@ -998,20 +1127,21 @@ void aml_aed_enable(bool enable, int aed_module)
|
||||
|
||||
if (!fr) {
|
||||
attach_aed.status = READY;
|
||||
pr_info("not in playback, AED is ready");
|
||||
} else {
|
||||
attach_aed.status = RUNNING;
|
||||
aml_set_aed(fr, enable);
|
||||
update_running = true;
|
||||
pr_info("Playback with AED\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (attach_aed.status == RUNNING) {
|
||||
struct frddr *fr = fetch_frddr_by_src(aed_module);
|
||||
if (attach_aed.status == RUNNING)
|
||||
update_running = true;
|
||||
|
||||
aml_set_aed(fr, enable);
|
||||
}
|
||||
attach_aed.status = DISABLED;
|
||||
}
|
||||
|
||||
if (update_running)
|
||||
aml_aed_enable(&attach_aed, enable);
|
||||
}
|
||||
|
||||
static bool aml_check_aed_module(int dst)
|
||||
@@ -1033,14 +1163,12 @@ static void aml_check_aed(bool enable, int dst)
|
||||
|
||||
/* AED in enable */
|
||||
if (attach_aed.enable) {
|
||||
if (enable) {
|
||||
/* check whether ready ? */
|
||||
if (attach_aed.status == READY)
|
||||
aml_aed_enable(true, attach_aed.attach_module);
|
||||
} else {
|
||||
if (attach_aed.status == RUNNING)
|
||||
attach_aed.status = READY;
|
||||
}
|
||||
if (enable)
|
||||
attach_aed.status = RUNNING;
|
||||
else
|
||||
attach_aed.status = DISABLED;
|
||||
|
||||
aml_aed_enable(&attach_aed, enable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1142,7 +1270,7 @@ static int toddr_src_enum_set(struct snd_kcontrol *kcontrol,
|
||||
static int frddr_src_idx = -1;
|
||||
|
||||
static const char *const frddr_src_sel_texts[] = {
|
||||
"TDMOUT_A", "TDMOUT_B", "TDMOUT_C", "SPDIFOUT", "SPDIFOUT_B"
|
||||
"TDMOUT_A", "TDMOUT_B", "TDMOUT_C", "SPDIFOUT_A", "SPDIFOUT_B"
|
||||
};
|
||||
|
||||
static const struct soc_enum frddr_output_source_enum =
|
||||
@@ -1207,15 +1335,19 @@ int card_add_ddr_kcontrols(struct snd_soc_card *card)
|
||||
|
||||
static struct ddr_chipinfo axg_ddr_chipinfo = {
|
||||
.int_start_same_addr = true,
|
||||
.asrc_only_left_j = true,
|
||||
};
|
||||
|
||||
static struct ddr_chipinfo g12a_ddr_chipinfo = {
|
||||
.same_src_fn = true,
|
||||
.asrc_only_left_j = true,
|
||||
};
|
||||
|
||||
static struct ddr_chipinfo tl1_ddr_chipinfo = {
|
||||
.same_src_fn = true,
|
||||
.ugt = true,
|
||||
.src_sel_ctrl = true,
|
||||
.asrc_src_sel_ctrl = true,
|
||||
.fifo_num = 4,
|
||||
};
|
||||
|
||||
|
||||
@@ -49,18 +49,27 @@ enum toddr_src {
|
||||
PDMIN,
|
||||
FRATV, /* NONE for axg, g12a, g12b */
|
||||
TDMIN_LB,
|
||||
LOOPBACK,
|
||||
LOOPBACK_A,
|
||||
FRHDMIRX, /* from tl1 chipset*/
|
||||
LOOPBACK_B,
|
||||
SPDIFIN_LB,
|
||||
VAD,
|
||||
};
|
||||
|
||||
enum resample_src {
|
||||
ASRC_TODDR_A,
|
||||
ASRC_TODDR_B,
|
||||
ASRC_TODDR_C,
|
||||
ASRC_TODDR_D, /* from tl1 chipset */
|
||||
ASRC_LOOPBACK_A,
|
||||
ASRC_LOOPBACK_B,
|
||||
};
|
||||
|
||||
enum frddr_dest {
|
||||
TDMOUT_A,
|
||||
TDMOUT_B,
|
||||
TDMOUT_C,
|
||||
SPDIFOUT,
|
||||
SPDIFOUT_A,
|
||||
SPDIFOUT_B,
|
||||
};
|
||||
|
||||
@@ -94,7 +103,7 @@ 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);
|
||||
void aml_set_resample(int id, bool enable, int resample_module);
|
||||
/* power detect */
|
||||
void aml_pwrdet_enable(bool enable, int pwrdet_module);
|
||||
|
||||
@@ -120,8 +129,10 @@ int aml_check_sharebuffer_valid(struct frddr *fr, int ss_sel);
|
||||
void aml_frddr_set_fifos(struct frddr *fr,
|
||||
unsigned int depth, unsigned int thresh);
|
||||
unsigned int aml_frddr_get_fifo_id(struct frddr *fr);
|
||||
void aml_frddr_set_format(struct frddr *fr,
|
||||
unsigned int msb, unsigned int frddr_type);
|
||||
/* audio eq drc */
|
||||
void aml_aed_enable(bool enable, int aed_module);
|
||||
void aml_set_aed(bool enable, int aed_module);
|
||||
|
||||
void frddr_init_without_mngr(unsigned int frddr_index, unsigned int src0_sel);
|
||||
void frddr_deinit_without_mngr(unsigned int frddr_index);
|
||||
|
||||
@@ -65,7 +65,7 @@ static const char *const aed_req_module_texts[] = {
|
||||
"TDMOUT_A",
|
||||
"TDMOUT_B",
|
||||
"TDMOUT_C",
|
||||
"SPDIFOUT",
|
||||
"SPDIFOUT_A",
|
||||
"SPDIFOUT_B",
|
||||
};
|
||||
|
||||
@@ -145,7 +145,7 @@ static int mixer_set_EQ(struct snd_kcontrol *kcontrol,
|
||||
aed_set_eq(value, aml_EQ_param_length, &aml_EQ_param[0]);
|
||||
|
||||
eqdrc_module = aed_get_req_sel(0);
|
||||
aml_aed_enable(value, eqdrc_module);
|
||||
aml_set_aed(value, eqdrc_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -160,7 +160,7 @@ static int mixer_set_DRC_params(struct snd_kcontrol *kcontrol,
|
||||
aml_DRC_param_length, &aml_drc_tko_table[0]);
|
||||
|
||||
eqdrc_module = aed_get_req_sel(0);
|
||||
aml_aed_enable(value, eqdrc_module);
|
||||
aml_set_aed(value, eqdrc_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -198,15 +198,15 @@ static const struct snd_kcontrol_new snd_eqdrc_controls[] = {
|
||||
mixer_eqdrc_read, mixer_eqdrc_write),
|
||||
|
||||
SOC_SINGLE_EXT("EQ/DRC Channel Mask",
|
||||
AED_TOP_CTL, 18, 0xff, 0,
|
||||
AED_TOP_CTL_G12X, 18, 0xff, 0,
|
||||
mixer_eqdrc_read, mixer_eqdrc_write),
|
||||
|
||||
SOC_SINGLE_EXT("EQ/DRC Lane Mask",
|
||||
AED_TOP_CTL, 14, 0xf, 0,
|
||||
AED_TOP_CTL_G12X, 14, 0xf, 0,
|
||||
mixer_eqdrc_read, mixer_eqdrc_write),
|
||||
|
||||
SOC_SINGLE_EXT("EQ/DRC Req Module",
|
||||
AED_TOP_REQ_CTL, 0, 0x7, 0,
|
||||
AED_TOP_REQ_CTL_G12X, 0, 0x7, 0,
|
||||
mixer_eqdrc_read, mixer_set_AED_req_ctrl),
|
||||
|
||||
SOC_SINGLE_EXT("EQ enable",
|
||||
@@ -243,8 +243,7 @@ int card_add_effects_init(struct snd_soc_card *card)
|
||||
audio_effect_np = of_parse_phandle(card->dev->of_node,
|
||||
"aml-audio-card,effect", 0);
|
||||
if (audio_effect_np == NULL) {
|
||||
pr_err("error: failed to find node %s for eq/drc info!\n",
|
||||
"audio_effect");
|
||||
pr_warn("no node %s for eq/drc info!\n", "audio_effect");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,13 +82,13 @@ void aed_req_sel(bool enable, int sel, int req_module)
|
||||
return;
|
||||
}
|
||||
|
||||
eqdrc_update_bits(AED_TOP_REQ_CTL, mask_offset, val_offset);
|
||||
eqdrc_update_bits(AED_TOP_REQ_CTL_G12X, mask_offset, val_offset);
|
||||
}
|
||||
|
||||
/* get eq/drc module */
|
||||
int aed_get_req_sel(int sel)
|
||||
{
|
||||
int val = eqdrc_read(AED_TOP_REQ_CTL);
|
||||
int val = eqdrc_read(AED_TOP_REQ_CTL_G12X);
|
||||
int mask_off;
|
||||
|
||||
switch (sel) {
|
||||
@@ -170,7 +170,7 @@ int aml_aed_format_set(int frddr_dst)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x7 << 11 | 0x1f << 6,
|
||||
eqdrc_update_bits(AED_TOP_CTL_G12X, 0x7 << 11 | 0x1f << 6,
|
||||
frddr_type << 11 | width << 6);
|
||||
|
||||
return 0;
|
||||
@@ -192,17 +192,17 @@ void aed_src_select(bool enable, int frddr_dst, int fifo_id)
|
||||
aed_req_sel(enable, 0, frddr_dst);
|
||||
|
||||
/* AED module, sel & enable */
|
||||
eqdrc_update_bits(AED_TOP_CTL,
|
||||
eqdrc_update_bits(AED_TOP_CTL_G12X,
|
||||
0x3 << 4 | 0x1 << 0,
|
||||
fifo_id << 4 | enable << 0);
|
||||
}
|
||||
|
||||
void aed_set_lane(int lane_mask)
|
||||
{
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0xf << 14, lane_mask << 14);
|
||||
eqdrc_update_bits(AED_TOP_CTL_G12X, 0xf << 14, lane_mask << 14);
|
||||
}
|
||||
|
||||
void aed_set_channel(int channel_mask)
|
||||
{
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0xff << 18, channel_mask << 18);
|
||||
eqdrc_update_bits(AED_TOP_CTL_G12X, 0xff << 18, channel_mask << 18);
|
||||
}
|
||||
|
||||
236
sound/soc/amlogic/auge/effects_hw_v2.c
Normal file
236
sound/soc/amlogic/auge/effects_hw_v2.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/effect_hw_v2.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "effects_hw_v2.h"
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
#include "tdm_hw.h"
|
||||
#include "spdif_hw.h"
|
||||
|
||||
void aed_set_ram_coeff(int len, int *params)
|
||||
{
|
||||
int i, ctrl_v;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
ctrl_v = (i << 2) | (0x1 << 1) | (0x1 << 0);
|
||||
eqdrc_write(AED_COEF_RAM_DATA, params[i]);
|
||||
eqdrc_write(AED_COEF_RAM_CNTL, ctrl_v);
|
||||
}
|
||||
}
|
||||
|
||||
void aed_set_multiband_drc_coeff(int len, int *params)
|
||||
{
|
||||
int band_len = len / 3, i, j;
|
||||
int offset = AED_MDRC_RMS_COEF10 - AED_MDRC_RMS_COEF00;
|
||||
int reg = AED_MDRC_RMS_COEF00;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < band_len; j++)
|
||||
eqdrc_write(reg + i * offset + j,
|
||||
params[i * band_len + j]);
|
||||
|
||||
eqdrc_write(AED_MDRC_THD0, 0xf6000000);
|
||||
eqdrc_write(AED_MDRC_K0, 0x20000);
|
||||
eqdrc_write(AED_MDRC_OFFSET0, 0x200);
|
||||
eqdrc_write(AED_MDRC_LOW_GAIN, 0x40000);
|
||||
|
||||
eqdrc_write(AED_MDRC_THD1, 0xfb000000);
|
||||
eqdrc_write(AED_MDRC_K1, 0x26666);
|
||||
eqdrc_write(AED_MDRC_OFFSET1, 0x200);
|
||||
eqdrc_write(AED_MDRC_MID_GAIN, 0x40000);
|
||||
|
||||
eqdrc_write(AED_MDRC_THD2, 0xf1000000);
|
||||
eqdrc_write(AED_MDRC_K2, 0x2cccc);
|
||||
eqdrc_write(AED_MDRC_OFFSET2, 0x200);
|
||||
eqdrc_write(AED_MDRC_HIGH_GAIN, 0x40000);
|
||||
}
|
||||
|
||||
void aed_set_fullband_drc_coeff(int len, int *params)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
eqdrc_write(AED_DRC_RELEASE_COEF00 + i,
|
||||
params[i]);
|
||||
|
||||
eqdrc_write(AED_DRC_RMS_COEF0, 0x34ebb);
|
||||
eqdrc_write(AED_DRC_RMS_COEF1, 0x7cb145);
|
||||
eqdrc_write(AED_DRC_THD0, 0xf7000000);
|
||||
eqdrc_write(AED_DRC_THD1, 0xf6000000);
|
||||
eqdrc_write(AED_DRC_THD2, 0xec000000);
|
||||
eqdrc_write(AED_DRC_THD3, 0xe2000000);
|
||||
eqdrc_write(AED_DRC_THD4, 0xce000000);
|
||||
eqdrc_write(AED_DRC_K0, 0x20000);
|
||||
eqdrc_write(AED_DRC_K1, 0x46666);
|
||||
eqdrc_write(AED_DRC_K2, 0x40000);
|
||||
eqdrc_write(AED_DRC_K3, 0x39999);
|
||||
eqdrc_write(AED_DRC_K4, 0x33333);
|
||||
eqdrc_write(AED_DRC_K5, 0x4cccc);
|
||||
eqdrc_write(AED_DRC_THD_OUT0, 0xf5e66667);
|
||||
eqdrc_write(AED_DRC_THD_OUT1, 0xebe66667);
|
||||
eqdrc_write(AED_DRC_THD_OUT2, 0xe2e66667);
|
||||
eqdrc_write(AED_DRC_THD_OUT3, 0xd2e66667);
|
||||
eqdrc_write(AED_DRC_OFFSET, 0x100);
|
||||
eqdrc_write(AED_DRC_LOOPBACK_CNTL, (144 << 0));
|
||||
}
|
||||
|
||||
static void aed_set_mixer_params(void)
|
||||
{
|
||||
eqdrc_write(AED_MIX0_LL, 0x40000);
|
||||
eqdrc_write(AED_MIX0_RL, 0x0);
|
||||
eqdrc_write(AED_MIX0_LR, 0x0);
|
||||
eqdrc_write(AED_MIX0_RR, 0x40000);
|
||||
eqdrc_write(AED_CLIP_THD, 0x7fffff);
|
||||
}
|
||||
|
||||
void aed_dc_enable(bool enable)
|
||||
{
|
||||
eqdrc_write(AED_DC_EN, enable << 0);
|
||||
}
|
||||
|
||||
void aed_nd_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
eqdrc_write(AED_ND_LOW_THD, 0x100);
|
||||
eqdrc_write(AED_ND_HIGH_THD, 0x200);
|
||||
eqdrc_write(AED_ND_CNT_THD, 0x100);
|
||||
eqdrc_write(AED_ND_SUM_NUM, 0x200);
|
||||
eqdrc_write(AED_ND_CZ_NUM, 0x800);
|
||||
eqdrc_write(AED_ND_SUM_THD0, 0x20000);
|
||||
eqdrc_write(AED_ND_SUM_THD1, 0x30000);
|
||||
eqdrc_write(AED_ND_CZ_THD0, 0x200);
|
||||
eqdrc_write(AED_ND_CZ_THD1, 0x100);
|
||||
eqdrc_write(AED_ND_COND_CNTL, 0x3f);
|
||||
eqdrc_write(AED_ND_RELEASE_COEF0, 0x3263a);
|
||||
eqdrc_write(AED_ND_RELEASE_COEF1, 0x7cd9c6);
|
||||
eqdrc_write(AED_ND_ATTACK_COEF0, 0x5188);
|
||||
eqdrc_write(AED_ND_ATTACK_COEF1, 0x7fae78);
|
||||
}
|
||||
|
||||
eqdrc_write(AED_ND_CNTL, (enable << 0)|(3 << 1));
|
||||
}
|
||||
|
||||
void aed_eq_enable(int idx, bool enable)
|
||||
{
|
||||
eqdrc_update_bits(AED_EQ_EN, 0x1 << idx, enable << idx);
|
||||
eqdrc_update_bits(AED_EQ_TAP_CNTL, 0x1f << (5 * idx), 10 << (5 * idx));
|
||||
}
|
||||
|
||||
void aed_multiband_drc_enable(bool enable)
|
||||
{
|
||||
eqdrc_write(AED_MDRC_CNTL,
|
||||
(1 << 16) | /* mdrc_pow_sel */
|
||||
(enable << 8) | /* mdrc_all_en */
|
||||
(7 << 3) | /* mdrc_rms_mode[2:0] */
|
||||
(7 << 0) /* mdrc_en[2:0] */
|
||||
);
|
||||
}
|
||||
|
||||
void aed_fullband_drc_enable(bool enable)
|
||||
{
|
||||
eqdrc_write(AED_DRC_CNTL,
|
||||
(5 << 3) | /* drc_tap */
|
||||
(enable << 0) /* drc_en */
|
||||
);
|
||||
}
|
||||
|
||||
void aed_set_EQ_volume(
|
||||
unsigned int master_vol,
|
||||
unsigned int Lch_vol,
|
||||
unsigned int Rch_vol)
|
||||
{
|
||||
eqdrc_write(AED_EQ_VOLUME,
|
||||
(0 << 30) | /* volume step: 0.125dB */
|
||||
(master_vol << 16) | /* master volume: 0dB */
|
||||
(Rch_vol << 8) | /* channel 2 volume: 0dB */
|
||||
(Lch_vol << 0) /* channel 1 volume: 0dB */
|
||||
);
|
||||
eqdrc_write(AED_EQ_VOLUME_SLEW_CNT, 0x40);
|
||||
eqdrc_write(AED_MUTE, 0);
|
||||
}
|
||||
|
||||
void aed_set_lane_and_channels(int lane_mask, int ch_mask)
|
||||
{
|
||||
eqdrc_update_bits(AED_TOP_CTL,
|
||||
0xff << 18 | 0xf << 14,
|
||||
ch_mask << 18 | lane_mask << 14);
|
||||
}
|
||||
|
||||
void aed_set_ctrl(bool enable, int sel, int module)
|
||||
{
|
||||
int mask = 0, val = 0;
|
||||
|
||||
switch (sel) {
|
||||
case 0: /* REQ_SEL0 */
|
||||
mask = 0xf << 0;
|
||||
val = 0x1 << 3 | module << 0;
|
||||
break;
|
||||
case 1: /* REQ_SEL1 */
|
||||
mask = 0xf << 4;
|
||||
val = 0x1 << 7 | module << 4;
|
||||
break;
|
||||
case 2: /* REQ_SEL2 */
|
||||
mask = 0xf << 8;
|
||||
val = 0x1 << 11 | module << 8;
|
||||
break;
|
||||
default:
|
||||
pr_err("unknown AED req_sel:%d, module:%d\n",
|
||||
sel, module);
|
||||
return;
|
||||
}
|
||||
eqdrc_update_bits(AED_TOP_REQ_CTL, mask, val);
|
||||
|
||||
/* Effect Module */
|
||||
if (module >= 3) {
|
||||
/* SPDIFOUT A/B */
|
||||
aml_spdifout_select_aed(enable, module - 3);
|
||||
} else if (module < 3 && module >= 0) {
|
||||
/* TDMOUT A/B/C */
|
||||
aml_tdmout_select_aed(enable, module);
|
||||
} else
|
||||
pr_err("unknown module:%d for AED\n", module);
|
||||
|
||||
}
|
||||
|
||||
void aed_set_format(int msb, int frddr_type)
|
||||
{
|
||||
eqdrc_update_bits(AED_TOP_CTL,
|
||||
0x7 << 11 | 0x1f << 6,
|
||||
frddr_type << 11 | msb << 6);
|
||||
}
|
||||
|
||||
void aed_enable(bool enable, int frddr_dst, int fifo_id)
|
||||
{
|
||||
if (enable) {
|
||||
eqdrc_write(AED_ED_CNTL, 0x1);
|
||||
eqdrc_write(AED_ED_CNTL, 0x0);
|
||||
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 1, 0x1 << 1);
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 2, 0x1 << 2);
|
||||
|
||||
aed_set_mixer_params();
|
||||
} else
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x3 << 1, 0x0 << 1);
|
||||
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 0, enable << 0);
|
||||
|
||||
/* start en */
|
||||
if (enable)
|
||||
eqdrc_update_bits(AED_TOP_CTL, 0x1 << 31, 0x1 << 31);
|
||||
}
|
||||
37
sound/soc/amlogic/auge/effects_hw_v2.h
Normal file
37
sound/soc/amlogic/auge/effects_hw_v2.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/effects_hw_v2.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 __EFFECTS_HW_V2_H__
|
||||
#define __EFFECTS_HW_V2_H__
|
||||
#include <linux/types.h>
|
||||
|
||||
void aed_set_ram_coeff(int len, int *params);
|
||||
void aed_set_multiband_drc_coeff(int len, int *params);
|
||||
void aed_set_fullband_drc_coeff(int len, int *params);
|
||||
void aed_dc_enable(bool enable);
|
||||
void aed_nd_enable(bool enable);
|
||||
void aed_eq_enable(int idx, bool enable);
|
||||
void aed_multiband_drc_enable(bool enable);
|
||||
void aed_fullband_drc_enable(bool enable);
|
||||
void aed_set_EQ_volume(
|
||||
unsigned int master_volume,
|
||||
unsigned int Lch_vol,
|
||||
unsigned int Rch_vol);
|
||||
void aed_set_lane_and_channels(int lane_mask, int ch_mask);
|
||||
void aed_set_ctrl(bool enable, int sel, int module);
|
||||
void aed_set_format(int msb, int frddr_type);
|
||||
void aed_enable(bool enable, int frddr_dst, int fifo_id);
|
||||
#endif
|
||||
298
sound/soc/amlogic/auge/effects_hw_v2_coeff.c
Normal file
298
sound/soc/amlogic/auge/effects_hw_v2_coeff.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/effects_hw_v2_coeff.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define AED_EQ_LENGTH 225
|
||||
#define AED_MULTIBAND_DRC_LENGTH 18
|
||||
#define AED_FULLBAND_DRC_LENGTH 24
|
||||
|
||||
static int eq_coeff[] = {
|
||||
/* 0 */ 0x7fd51b,
|
||||
/* 1 */ 0x30055c9,
|
||||
/* 2 */ 0x7fd51b,
|
||||
/* 3 */ 0x30055e6,
|
||||
/* 4 */ 0x7faa53,
|
||||
/* 5 */ 0x7ed219,
|
||||
/* 6 */ 0x3025bce,
|
||||
/* 7 */ 0x7ed219,
|
||||
/* 8 */ 0x3025e96,
|
||||
/* 9 */ 0x7da6fb,
|
||||
/* 10 */ 0x7ed219,
|
||||
/* 11 */ 0x3025bce,
|
||||
/* 12 */ 0x7ed219,
|
||||
/* 13 */ 0x3025e96,
|
||||
/* 14 */ 0x7da6fb,
|
||||
/* 15 */ 0xdf71e0,
|
||||
/* 16 */ 0x2411c40,
|
||||
/* 17 */ 0xdf71e0,
|
||||
/* 18 */ 0x304bd12,
|
||||
/* 19 */ 0x7b58fb,
|
||||
/* 20 */ 0x7d8252,
|
||||
/* 21 */ 0x30bb7df,
|
||||
/* 22 */ 0x771ba1,
|
||||
/* 23 */ 0x30bb7df,
|
||||
/* 24 */ 0x749df4,
|
||||
/* 25 */ 0x79f87b,
|
||||
/* 26 */ 0x31971e4,
|
||||
/* 27 */ 0x6ddabe,
|
||||
/* 28 */ 0x31971e4,
|
||||
/* 29 */ 0x67d339,
|
||||
/* 30 */ 0x84f8f3,
|
||||
/* 31 */ 0x31d2c91,
|
||||
/* 32 */ 0x62ebbf,
|
||||
/* 33 */ 0x31d2c91,
|
||||
/* 34 */ 0x67e4b1,
|
||||
/* 35 */ 0x711f0e,
|
||||
/* 36 */ 0x3543f10,
|
||||
/* 37 */ 0x4ae2f0,
|
||||
/* 38 */ 0x3543f10,
|
||||
/* 39 */ 0x3c01ff,
|
||||
/* 40 */ 0xaaf457,
|
||||
/* 41 */ 0x3831bd5,
|
||||
/* 42 */ 0xfb150,
|
||||
/* 43 */ 0x3831bd5,
|
||||
/* 44 */ 0x3aa5a8,
|
||||
/* 45 */ 0x65b5d1,
|
||||
/* 46 */ 0xe3390,
|
||||
/* 47 */ 0x2226c8,
|
||||
/* 48 */ 0xe3390,
|
||||
/* 49 */ 0x7dc99,
|
||||
/* 50 */ 0x358660,
|
||||
/* 51 */ 0x6b0cc1,
|
||||
/* 52 */ 0x358660,
|
||||
/* 53 */ 0x3b418e,
|
||||
/* 54 */ 0x1ad7f4,
|
||||
/* 55 */ 0x800000,
|
||||
/* 56 */ 0x0,
|
||||
/* 57 */ 0x0,
|
||||
/* 58 */ 0x0,
|
||||
/* 59 */ 0x0,
|
||||
/* 60 */ 0x800000,
|
||||
/* 61 */ 0x0,
|
||||
/* 62 */ 0x0,
|
||||
/* 63 */ 0x0,
|
||||
/* 64 */ 0x0,
|
||||
/* 65 */ 0x800000,
|
||||
/* 66 */ 0x0,
|
||||
/* 67 */ 0x0,
|
||||
/* 68 */ 0x0,
|
||||
/* 69 */ 0x0,
|
||||
/* 70 */ 0x800000,
|
||||
/* 71 */ 0x0,
|
||||
/* 72 */ 0x0,
|
||||
/* 73 */ 0x0,
|
||||
/* 74 */ 0x0,
|
||||
/* 75 */ 0x800000,
|
||||
/* 76 */ 0x0,
|
||||
/* 77 */ 0x0,
|
||||
/* 78 */ 0x0,
|
||||
/* 79 */ 0x0,
|
||||
/* 80 */ 0x800000,
|
||||
/* 81 */ 0x0,
|
||||
/* 82 */ 0x0,
|
||||
/* 83 */ 0x0,
|
||||
/* 84 */ 0x0,
|
||||
/* 85 */ 0x800000,
|
||||
/* 86 */ 0x0,
|
||||
/* 87 */ 0x0,
|
||||
/* 88 */ 0x0,
|
||||
/* 89 */ 0x0,
|
||||
/* 90 */ 0x800000,
|
||||
/* 91 */ 0x0,
|
||||
/* 92 */ 0x0,
|
||||
/* 93 */ 0x0,
|
||||
/* 94 */ 0x0,
|
||||
/* 95 */ 0x800000,
|
||||
/* 96 */ 0x0,
|
||||
/* 97 */ 0x0,
|
||||
/* 98 */ 0x0,
|
||||
/* 99 */ 0x0,
|
||||
/* 100 */ 0x800000,
|
||||
/* 101 */ 0x0,
|
||||
/* 102 */ 0x0,
|
||||
/* 103 */ 0x0,
|
||||
/* 104 */ 0x0,
|
||||
/* 105 */ 0x7ed219,
|
||||
/* 106 */ 0x3025bce,
|
||||
/* 107 */ 0x7ed219,
|
||||
/* 108 */ 0x3025e96,
|
||||
/* 109 */ 0x7da6fb,
|
||||
/* 110 */ 0x7ed219,
|
||||
/* 111 */ 0x3025bce,
|
||||
/* 112 */ 0x7ed219,
|
||||
/* 113 */ 0x3025e96,
|
||||
/* 114 */ 0x7da6fb,
|
||||
/* 115 */ 0xdf71e0,
|
||||
/* 116 */ 0x2411c40,
|
||||
/* 117 */ 0xdf71e0,
|
||||
/* 118 */ 0x304bd12,
|
||||
/* 119 */ 0x7b58fb,
|
||||
/* 120 */ 0x7d8252,
|
||||
/* 121 */ 0x30bb7df,
|
||||
/* 122 */ 0x771ba1,
|
||||
/* 123 */ 0x30bb7df,
|
||||
/* 124 */ 0x749df4,
|
||||
/* 125 */ 0x79f87b,
|
||||
/* 126 */ 0x31971e4,
|
||||
/* 127 */ 0x6ddabe,
|
||||
/* 128 */ 0x31971e4,
|
||||
/* 129 */ 0x67d339,
|
||||
/* 130 */ 0x84f8f3,
|
||||
/* 131 */ 0x31d2c91,
|
||||
/* 132 */ 0x62ebbf,
|
||||
/* 133 */ 0x31d2c91,
|
||||
/* 134 */ 0x67e4b1,
|
||||
/* 135 */ 0x711f0e,
|
||||
/* 136 */ 0x3543f10,
|
||||
/* 137 */ 0x4ae2f0,
|
||||
/* 138 */ 0x3543f10,
|
||||
/* 139 */ 0x3c01ff,
|
||||
/* 140 */ 0xaaf457,
|
||||
/* 141 */ 0x3831bd5,
|
||||
/* 142 */ 0xfb150,
|
||||
/* 143 */ 0x3831bd5,
|
||||
/* 144 */ 0x3aa5a8,
|
||||
/* 145 */ 0x65b5d1,
|
||||
/* 146 */ 0xe3390,
|
||||
/* 147 */ 0x2226c8,
|
||||
/* 148 */ 0xe3390,
|
||||
/* 149 */ 0x7dc99,
|
||||
/* 150 */ 0x358660,
|
||||
/* 151 */ 0x6b0cc1,
|
||||
/* 152 */ 0x358660,
|
||||
/* 153 */ 0x3b418e,
|
||||
/* 154 */ 0x1ad7f4,
|
||||
/* 155 */ 0x800000,
|
||||
/* 156 */ 0x0,
|
||||
/* 157 */ 0x0,
|
||||
/* 158 */ 0x0,
|
||||
/* 159 */ 0x0,
|
||||
/* 160 */ 0x800000,
|
||||
/* 161 */ 0x0,
|
||||
/* 162 */ 0x0,
|
||||
/* 163 */ 0x0,
|
||||
/* 164 */ 0x0,
|
||||
/* 165 */ 0x800000,
|
||||
/* 166 */ 0x0,
|
||||
/* 167 */ 0x0,
|
||||
/* 168 */ 0x0,
|
||||
/* 169 */ 0x0,
|
||||
/* 170 */ 0x800000,
|
||||
/* 171 */ 0x0,
|
||||
/* 172 */ 0x0,
|
||||
/* 173 */ 0x0,
|
||||
/* 174 */ 0x0,
|
||||
/* 175 */ 0x800000,
|
||||
/* 176 */ 0x0,
|
||||
/* 177 */ 0x0,
|
||||
/* 178 */ 0x0,
|
||||
/* 179 */ 0x0,
|
||||
/* 180 */ 0x800000,
|
||||
/* 181 */ 0x0,
|
||||
/* 182 */ 0x0,
|
||||
/* 183 */ 0x0,
|
||||
/* 184 */ 0x0,
|
||||
/* 185 */ 0x800000,
|
||||
/* 186 */ 0x0,
|
||||
/* 187 */ 0x0,
|
||||
/* 188 */ 0x0,
|
||||
/* 189 */ 0x0,
|
||||
/* 190 */ 0x800000,
|
||||
/* 191 */ 0x0,
|
||||
/* 192 */ 0x0,
|
||||
/* 193 */ 0x0,
|
||||
/* 194 */ 0x0,
|
||||
/* 195 */ 0x800000,
|
||||
/* 196 */ 0x0,
|
||||
/* 197 */ 0x0,
|
||||
/* 198 */ 0x0,
|
||||
/* 199 */ 0x0,
|
||||
/* 200 */ 0x800000,
|
||||
/* 201 */ 0x0,
|
||||
/* 202 */ 0x0,
|
||||
/* 203 */ 0x0,
|
||||
/* 204 */ 0x0,
|
||||
/* 205 */ 0x25b,
|
||||
/* 206 */ 0x4b5,
|
||||
/* 207 */ 0x25b,
|
||||
/* 208 */ 0x3045701,
|
||||
/* 209 */ 0x7bb269,
|
||||
/* 210 */ 0x7dd6da,
|
||||
/* 211 */ 0x304524c,
|
||||
/* 212 */ 0x7dd6da,
|
||||
/* 213 */ 0x3045701,
|
||||
/* 214 */ 0x7bb269,
|
||||
/* 215 */ 0x7f3ee,
|
||||
/* 216 */ 0xfe7dc,
|
||||
/* 217 */ 0x7f3ee,
|
||||
/* 218 */ 0x37f9f4a,
|
||||
/* 219 */ 0x20306d,
|
||||
/* 220 */ 0x482449,
|
||||
/* 221 */ 0x36fb76e,
|
||||
/* 222 */ 0x482449,
|
||||
/* 223 */ 0x37f9f4a,
|
||||
/* 224 */ 0x20306d,
|
||||
};
|
||||
|
||||
static int multiband_drc_coeff[] = {
|
||||
0x34ebb, /* Low SMS coeff0 */
|
||||
0x7f54e0, /* Low SMS coeff1 */
|
||||
0x5188, /* Low RELEASE coeff0 */
|
||||
0x7fae78, /* Low RELEASE coeff1 */
|
||||
0x3263a, /* Low ATTACK coeff0 */
|
||||
0x7cd9c6, /* Low ATTACK coeff1 */
|
||||
|
||||
0x34ebb, /* Mid */
|
||||
0x7f54e0,
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
|
||||
0x34ebb, /* High */
|
||||
0x7f54e0,
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
};
|
||||
|
||||
static int fullband_drc_coeff[] = {
|
||||
0x5188, /* RELEASE_COEF00 */
|
||||
0x7fae78, /* RELEASE_COEF01 */
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x5188,
|
||||
0x7fae78,
|
||||
0x5188, /* RELEASE_COEF50 */
|
||||
0x7fae78, /* RELEASE_COEF51 */
|
||||
0x3263a, /* ATTACK_COEF00 */
|
||||
0x7cd9c6, /* ATTACK_COEF01 */
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
0x3263a,
|
||||
0x7cd9c6,
|
||||
0x3263a, /* ATTACK_COEF50 */
|
||||
0x7cd9c6, /* ATTACK_COEF51 */
|
||||
};
|
||||
698
sound/soc/amlogic/auge/effects_v2.c
Normal file
698
sound/soc/amlogic/auge/effects_v2.c
Normal file
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/effects_v2.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "effects_v2.h"
|
||||
#include "effects_hw_v2.h"
|
||||
#include "effects_hw_v2_coeff.c"
|
||||
#include "ddr_mngr.h"
|
||||
#include "regs.h"
|
||||
#include "iomap.h"
|
||||
|
||||
#define DRV_NAME "Effects"
|
||||
|
||||
/*
|
||||
* AED Diagram
|
||||
* DC -- ND -- MIX -- EQ -- Mutiband DRC -- LR Vol
|
||||
* -- Fullband DRC -- Master Volume
|
||||
*/
|
||||
|
||||
enum {
|
||||
AED_DC,
|
||||
AED_ND,
|
||||
AED_EQ,
|
||||
AED_MDRC,
|
||||
AED_FDRC
|
||||
};
|
||||
|
||||
struct effect_chipinfo {
|
||||
/* v1 is for G12X(g12a, g12b)
|
||||
* v2 is for tl1
|
||||
*/
|
||||
bool v2;
|
||||
};
|
||||
|
||||
struct audioeffect {
|
||||
struct device *dev;
|
||||
|
||||
/* gate */
|
||||
struct clk *gate;
|
||||
/* source mpll */
|
||||
struct clk *srcpll;
|
||||
/* eqdrc clk */
|
||||
struct clk *clk;
|
||||
|
||||
struct effect_chipinfo *chipinfo;
|
||||
|
||||
bool dc_en;
|
||||
bool nd_en;
|
||||
bool eq_en;
|
||||
bool multiband_drc_en;
|
||||
bool fullband_drc_en;
|
||||
int mask_en;
|
||||
|
||||
int lane_mask;
|
||||
int ch_mask;
|
||||
|
||||
/*which module should be effected */
|
||||
int effect_module;
|
||||
};
|
||||
|
||||
struct audioeffect *s_effect;
|
||||
|
||||
static struct audioeffect *get_audioeffects(void)
|
||||
{
|
||||
if (!s_effect) {
|
||||
pr_info("Not init audio effects\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s_effect;
|
||||
}
|
||||
|
||||
bool check_aed_v2(void)
|
||||
{
|
||||
struct audioeffect *p_effect = get_audioeffects();
|
||||
|
||||
if (!p_effect)
|
||||
return false;
|
||||
|
||||
if (p_effect->chipinfo && p_effect->chipinfo->v2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int eqdrc_clk_set(struct audioeffect *p_effect)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_prepare_enable(p_effect->clk);
|
||||
if (ret) {
|
||||
pr_err("Can't enable eqdrc clock: %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(p_effect->srcpll);
|
||||
if (ret) {
|
||||
pr_err("Can't enable eqdrc src pll clock: %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* defaule clk */
|
||||
clk_set_rate(p_effect->clk, 200000000);
|
||||
|
||||
pr_info("%s, src pll:%lu, clk:%lu\n",
|
||||
__func__,
|
||||
clk_get_rate(p_effect->srcpll),
|
||||
clk_get_rate(p_effect->clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_read(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int max = mc->max;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned int value =
|
||||
(((unsigned int)eqdrc_read(reg)) >> shift) & max;
|
||||
|
||||
if (invert)
|
||||
value = (~value) & max;
|
||||
ucontrol->value.integer.value[0] = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_write(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int max = mc->max;
|
||||
unsigned int invert = mc->invert;
|
||||
unsigned int value = ucontrol->value.integer.value[0];
|
||||
unsigned int new_val = (unsigned int)eqdrc_read(reg);
|
||||
|
||||
if (invert)
|
||||
value = (~value) & max;
|
||||
max = ~(max << shift);
|
||||
new_val &= max;
|
||||
new_val |= (value << shift);
|
||||
|
||||
eqdrc_write(reg, new_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_set_aed_top(
|
||||
struct audioeffect *p_effect,
|
||||
int mask_new, bool enable)
|
||||
{
|
||||
int mask_last = p_effect->mask_en;
|
||||
bool update_aed_top = false;
|
||||
|
||||
pr_info("%s, mask:0x%x\n", __func__, mask_new);
|
||||
|
||||
if (enable)
|
||||
p_effect->mask_en |= mask_new;
|
||||
else
|
||||
p_effect->mask_en &= ~mask_new;
|
||||
|
||||
if (enable && (!mask_last) && p_effect->mask_en)
|
||||
update_aed_top = true; /* to enable */
|
||||
else if ((!enable) && mask_last && (!p_effect->mask_en))
|
||||
update_aed_top = true; /* to disable */
|
||||
|
||||
if (update_aed_top)
|
||||
aml_set_aed(enable, p_effect->effect_module);
|
||||
}
|
||||
|
||||
static int mixer_aed_enable_DC(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
p_effect->dc_en = ucontrol->value.integer.value[0];
|
||||
|
||||
aed_dc_enable(p_effect->dc_en);
|
||||
|
||||
check_set_aed_top(p_effect,
|
||||
0x1 << AED_DC,
|
||||
p_effect->dc_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_enable_ND(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
p_effect->nd_en = ucontrol->value.integer.value[0];
|
||||
|
||||
aed_nd_enable(p_effect->nd_en);
|
||||
|
||||
check_set_aed_top(p_effect,
|
||||
0x1 << AED_ND,
|
||||
p_effect->nd_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_enable_EQ(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
int *p_eq_coeff = eq_coeff;
|
||||
int len = ARRAY_SIZE(eq_coeff);
|
||||
|
||||
p_effect->eq_en = ucontrol->value.integer.value[0];
|
||||
|
||||
aed_set_ram_coeff(len, p_eq_coeff);
|
||||
aed_eq_enable(0, p_effect->eq_en);
|
||||
|
||||
check_set_aed_top(p_effect,
|
||||
0x1 << AED_EQ,
|
||||
p_effect->eq_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_enable_multiband_DRC(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
int *p_multiband_coeff = multiband_drc_coeff;
|
||||
int len = ARRAY_SIZE(multiband_drc_coeff);
|
||||
|
||||
if (!p_effect)
|
||||
return -EINVAL;
|
||||
|
||||
p_effect->multiband_drc_en = ucontrol->value.integer.value[0];
|
||||
|
||||
aed_set_multiband_drc_coeff(len, p_multiband_coeff);
|
||||
aed_multiband_drc_enable(p_effect->multiband_drc_en);
|
||||
|
||||
check_set_aed_top(p_effect,
|
||||
0x1 << AED_MDRC,
|
||||
p_effect->multiband_drc_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_aed_enable_fullband_DRC(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
int *p_fullband_coeff = fullband_drc_coeff;
|
||||
int len = ARRAY_SIZE(fullband_drc_coeff);
|
||||
|
||||
if (!p_effect)
|
||||
return -EINVAL;
|
||||
|
||||
p_effect->fullband_drc_en = ucontrol->value.integer.value[0];
|
||||
|
||||
aed_set_fullband_drc_coeff(len, p_fullband_coeff);
|
||||
aed_fullband_drc_enable(p_effect->fullband_drc_en);
|
||||
|
||||
check_set_aed_top(p_effect,
|
||||
0x1 << AED_FDRC,
|
||||
p_effect->fullband_drc_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_get_EQ_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int *val = (int *)ucontrol->value.bytes.data;
|
||||
int *p = &eq_coeff[0];
|
||||
|
||||
memcpy(val, p, AED_EQ_LENGTH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int mixer_set_EQ_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
|
||||
void *data;
|
||||
int *val, *p = &eq_coeff[0];
|
||||
|
||||
data = kmemdup(ucontrol->value.bytes.data,
|
||||
params->max, GFP_KERNEL | GFP_DMA);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
val = (int *)data;
|
||||
memcpy(p, val, params->max / sizeof(int));
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_get_multiband_DRC_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int *val = (int *)ucontrol->value.bytes.data;
|
||||
int *p = &multiband_drc_coeff[0];
|
||||
|
||||
memcpy(val, p, AED_MULTIBAND_DRC_LENGTH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_set_multiband_DRC_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
|
||||
void *data;
|
||||
int *val, *p = &multiband_drc_coeff[0];
|
||||
|
||||
data = kmemdup(ucontrol->value.bytes.data,
|
||||
params->max, GFP_KERNEL | GFP_DMA);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
val = (int *)data;
|
||||
memcpy(p, val, params->max / sizeof(int));
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_get_fullband_DRC_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int *val = (int *)ucontrol->value.bytes.data;
|
||||
int *p = &fullband_drc_coeff[0];
|
||||
|
||||
memcpy(val, p, AED_FULLBAND_DRC_LENGTH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mixer_set_fullband_DRC_params(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_bytes_ext *params = (void *)kcontrol->private_value;
|
||||
void *data;
|
||||
int *val, *p = &fullband_drc_coeff[0];
|
||||
|
||||
data = kmemdup(ucontrol->value.bytes.data,
|
||||
params->max, GFP_KERNEL | GFP_DMA);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
val = (int *)data;
|
||||
memcpy(p, val, params->max / sizeof(int));
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* aed module
|
||||
* check to sync with enum frddr_dest in ddr_mngr.h
|
||||
*/
|
||||
static const char *const aed_module_texts[] = {
|
||||
"TDMOUT_A",
|
||||
"TDMOUT_B",
|
||||
"TDMOUT_C",
|
||||
"SPDIFIN",
|
||||
"SPDIFOUT_A",
|
||||
"SPDIFOUT_B",
|
||||
};
|
||||
|
||||
static const struct soc_enum aed_module_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(aed_module_texts),
|
||||
aed_module_texts);
|
||||
|
||||
static int aed_module_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (!p_effect)
|
||||
return -EINVAL;
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_effect->effect_module;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aed_module_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioeffect *p_effect = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (!p_effect)
|
||||
return -EINVAL;
|
||||
|
||||
p_effect->effect_module = ucontrol->value.enumerated.item[0];
|
||||
|
||||
/* update info to ddr and modules */
|
||||
aed_set_ctrl(
|
||||
p_effect->eq_en |
|
||||
p_effect->multiband_drc_en |
|
||||
p_effect->fullband_drc_en,
|
||||
0,
|
||||
p_effect->effect_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12276, 12, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(lr_vol_tlv, -12750, 50, 1);
|
||||
|
||||
static const struct snd_kcontrol_new snd_effect_controls[] = {
|
||||
|
||||
SOC_SINGLE_EXT("AED DC cut enable",
|
||||
AED_DC_EN, 0, 0x1, 0,
|
||||
mixer_aed_read, mixer_aed_enable_DC),
|
||||
|
||||
SOC_SINGLE_EXT("AED Noise Detect enable",
|
||||
AED_ND_CNTL, 0, 0x1, 0,
|
||||
mixer_aed_read, mixer_aed_enable_ND),
|
||||
|
||||
SOC_SINGLE_EXT("AED EQ enable",
|
||||
AED_EQ_EN, 0, 0x1, 0,
|
||||
mixer_aed_read, mixer_aed_enable_EQ),
|
||||
|
||||
SOC_SINGLE_EXT("AED Multi-band DRC enable",
|
||||
AED_MDRC_CNTL, 8, 0x1, 0,
|
||||
mixer_aed_read, mixer_aed_enable_multiband_DRC),
|
||||
|
||||
SOC_SINGLE_EXT("AED Full-band DRC enable",
|
||||
AED_DRC_CNTL, 0, 0x1, 0,
|
||||
mixer_aed_read, mixer_aed_enable_fullband_DRC),
|
||||
|
||||
SND_SOC_BYTES_EXT("AED EQ Parameters",
|
||||
AED_EQ_LENGTH,
|
||||
mixer_get_EQ_params,
|
||||
mixer_set_EQ_params),
|
||||
|
||||
SND_SOC_BYTES_EXT("AED Multi-band DRC Parameters",
|
||||
AED_MULTIBAND_DRC_LENGTH,
|
||||
mixer_get_multiband_DRC_params,
|
||||
mixer_set_multiband_DRC_params),
|
||||
|
||||
SND_SOC_BYTES_EXT("AED Full-band DRC Parameters",
|
||||
AED_FULLBAND_DRC_LENGTH,
|
||||
mixer_get_fullband_DRC_params,
|
||||
mixer_set_fullband_DRC_params),
|
||||
|
||||
SOC_ENUM_EXT("AED module",
|
||||
aed_module_enum,
|
||||
aed_module_get_enum,
|
||||
aed_module_set_enum),
|
||||
|
||||
SOC_SINGLE_EXT("AED Lane mask",
|
||||
AED_TOP_CTL, 14, 0xF, 0,
|
||||
mixer_aed_read, mixer_aed_write),
|
||||
|
||||
SOC_SINGLE_EXT("AED Channel mask",
|
||||
AED_TOP_CTL, 18, 0xFF, 0,
|
||||
mixer_aed_read, mixer_aed_write),
|
||||
|
||||
SOC_SINGLE_EXT_TLV("AED Lch volume",
|
||||
AED_EQ_VOLUME, 0, 0xFF, 1,
|
||||
mixer_aed_read, mixer_aed_write,
|
||||
lr_vol_tlv),
|
||||
|
||||
SOC_SINGLE_EXT_TLV("AED Rch volume",
|
||||
AED_EQ_VOLUME, 8, 0xFF, 1,
|
||||
mixer_aed_read, mixer_aed_write,
|
||||
lr_vol_tlv),
|
||||
|
||||
SOC_SINGLE_EXT_TLV("AED master volume",
|
||||
AED_EQ_VOLUME, 16, 0x3FF, 1,
|
||||
mixer_aed_read, mixer_aed_write,
|
||||
master_vol_tlv),
|
||||
};
|
||||
|
||||
int card_add_effect_v2_kcontrols(struct snd_soc_card *card)
|
||||
{
|
||||
unsigned int idx;
|
||||
int err;
|
||||
|
||||
if (!s_effect) {
|
||||
pr_info("effect_v2 is not init\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(snd_effect_controls); idx++) {
|
||||
err = snd_ctl_add(card->snd_card,
|
||||
snd_ctl_new1(&snd_effect_controls[idx],
|
||||
s_effect));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const struct snd_soc_component_driver effect_component_drv = {
|
||||
.name = DRV_NAME,
|
||||
|
||||
.controls = snd_effect_controls,
|
||||
.num_controls = ARRAY_SIZE(snd_effect_controls),
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct effect_chipinfo tl1_effect_chipinfo = {
|
||||
.v2 = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id effect_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, snd-effect-v1"
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, snd-effect-v2",
|
||||
.data = &tl1_effect_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-effect",
|
||||
.data = &tl1_effect_chipinfo,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, effect_device_id);
|
||||
|
||||
static int effect_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct audioeffect *p_effect;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct effect_chipinfo *p_chipinfo;
|
||||
bool eq_enable = false;
|
||||
bool multiband_drc_enable = false;
|
||||
bool fullband_drc_enable = false;
|
||||
int lane_mask = -1, channel_mask = -1, eqdrc_module = -1;
|
||||
|
||||
int ret;
|
||||
|
||||
pr_info("%s, line:%d\n", __func__, __LINE__);
|
||||
|
||||
p_effect = devm_kzalloc(&pdev->dev,
|
||||
sizeof(struct audioeffect),
|
||||
GFP_KERNEL);
|
||||
if (!p_effect) {
|
||||
dev_err(&pdev->dev, "Can't allocate pcm_p\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* match data */
|
||||
p_chipinfo = (struct effect_chipinfo *)
|
||||
of_device_get_match_data(dev);
|
||||
if (!p_chipinfo)
|
||||
dev_warn_once(dev, "check whether to update effect chipinfo\n");
|
||||
p_effect->chipinfo = p_chipinfo;
|
||||
|
||||
p_effect->gate = devm_clk_get(&pdev->dev, "gate");
|
||||
if (IS_ERR(p_effect->gate)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't retrieve eqdrc gate clock\n");
|
||||
ret = PTR_ERR(p_effect->gate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
p_effect->srcpll = devm_clk_get(&pdev->dev, "srcpll");
|
||||
if (IS_ERR(p_effect->srcpll)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't retrieve source mpll clock\n");
|
||||
ret = PTR_ERR(p_effect->srcpll);
|
||||
return ret;
|
||||
}
|
||||
|
||||
p_effect->clk = devm_clk_get(&pdev->dev, "eqdrc");
|
||||
if (IS_ERR(p_effect->clk)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't retrieve eqdrc clock\n");
|
||||
ret = PTR_ERR(p_effect->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_parent(p_effect->clk, p_effect->srcpll);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't set eqdrc clock parent clock\n");
|
||||
ret = PTR_ERR(p_effect->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
eqdrc_clk_set(p_effect);
|
||||
|
||||
eq_enable = of_property_read_bool(pdev->dev.of_node,
|
||||
"eq_enable");
|
||||
|
||||
multiband_drc_enable = of_property_read_bool(pdev->dev.of_node,
|
||||
"multiband_drc_enable");
|
||||
|
||||
fullband_drc_enable = of_property_read_bool(pdev->dev.of_node,
|
||||
"fullband_drc_enable");
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"eqdrc_module",
|
||||
&eqdrc_module);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Can't retrieve eqdrc_module\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"lane_mask",
|
||||
&lane_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Can't retrieve lane_mask\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"channel_mask",
|
||||
&channel_mask);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Can't retrieve channel_mask\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("%s \t eq_en:%d, multi-band drc en:%d, full-band drc en:%d, module:%d, lane_mask:%d, ch_mask:%d\n",
|
||||
__func__,
|
||||
eq_enable,
|
||||
multiband_drc_enable,
|
||||
fullband_drc_enable,
|
||||
eqdrc_module,
|
||||
lane_mask,
|
||||
channel_mask
|
||||
);
|
||||
|
||||
/* config from dts */
|
||||
p_effect->eq_en = eq_enable;
|
||||
p_effect->multiband_drc_en = multiband_drc_enable;
|
||||
p_effect->fullband_drc_en = fullband_drc_enable;
|
||||
p_effect->lane_mask = lane_mask;
|
||||
p_effect->ch_mask = channel_mask;
|
||||
p_effect->effect_module = eqdrc_module;
|
||||
|
||||
aed_set_lane_and_channels(lane_mask, channel_mask);
|
||||
aed_set_EQ_volume(0xc0, 0x30, 0x30);
|
||||
|
||||
p_effect->dev = dev;
|
||||
s_effect = p_effect;
|
||||
dev_set_drvdata(&pdev->dev, p_effect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver effect_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(effect_device_id),
|
||||
},
|
||||
.probe = effect_platform_probe,
|
||||
};
|
||||
module_platform_driver(effect_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("AMLogic, Inc.");
|
||||
MODULE_DESCRIPTION("Amlogic Audio Effects driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
23
sound/soc/amlogic/auge/effects_v2.h
Normal file
23
sound/soc/amlogic/auge/effects_v2.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* sound/soc/amlogic/auge/effects_v2.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 __EFFECTS_V2_H__
|
||||
#define __EFFECTS_V2_H__
|
||||
|
||||
extern bool check_aed_v2(void);
|
||||
extern int card_add_effect_v2_kcontrols(struct snd_soc_card *card);
|
||||
|
||||
#endif
|
||||
@@ -38,20 +38,40 @@
|
||||
#include "audio_utils.h"
|
||||
#include "frhdmirx_hw.h"
|
||||
|
||||
#include <linux/amlogic/media/sound/misc.h>
|
||||
|
||||
#define DRV_NAME "EXTN"
|
||||
|
||||
struct extn {
|
||||
struct aml_audio_controller *actrl;
|
||||
struct device *dev;
|
||||
unsigned int sysclk_freq;
|
||||
|
||||
int irq_frhdmirx;
|
||||
|
||||
struct toddr *tddr;
|
||||
struct frddr *fddr;
|
||||
|
||||
int sysclk_freq;
|
||||
|
||||
int irq_frhdmirx;
|
||||
|
||||
/*
|
||||
* 0: select spdif lane;
|
||||
* 1: select PAO mode;
|
||||
*/
|
||||
int hdmirx_mode;
|
||||
|
||||
/*
|
||||
* arc source sel:
|
||||
* 0: hi_hdmirx_arc_cntl[5]
|
||||
* 1: audio_spdif_a
|
||||
* 2: audio_spdif_b
|
||||
* 4: hdmir_aud_spdif
|
||||
*/
|
||||
int arc_src;
|
||||
int arc_en;
|
||||
|
||||
};
|
||||
|
||||
#define PREALLOC_BUFFER (32 * 1024)
|
||||
#define PREALLOC_BUFFER (128 * 1024)
|
||||
#define PREALLOC_BUFFER_MAX (256 * 1024)
|
||||
|
||||
#define EXTN_RATES (SNDRV_PCM_RATE_8000_192000)
|
||||
@@ -320,37 +340,58 @@ static int extn_dai_prepare(
|
||||
aml_frddr_set_fifos(fr, 0x40, 0x20);
|
||||
} else {
|
||||
struct toddr *to = p_extn->tddr;
|
||||
unsigned int msb = 32 - 1;
|
||||
unsigned int lsb = 32 - bit_depth;
|
||||
unsigned int toddr_type;
|
||||
unsigned int msb = 0, lsb = 0, toddr_type = 0;
|
||||
unsigned int src = toddr_src_get();
|
||||
struct toddr_fmt fmt;
|
||||
|
||||
switch (bit_depth) {
|
||||
case 8:
|
||||
case 16:
|
||||
case 32:
|
||||
toddr_type = 0;
|
||||
break;
|
||||
case 24:
|
||||
if (bit_depth == 24)
|
||||
toddr_type = 4;
|
||||
break;
|
||||
default:
|
||||
pr_err("invalid bit_depth: %d\n", bit_depth);
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
toddr_type = 0;
|
||||
|
||||
pr_info("%s Expected toddr src:%s\n",
|
||||
__func__,
|
||||
toddr_src_get_str(src));
|
||||
|
||||
if (src == FRATV)
|
||||
fratv_src_select(0);
|
||||
else if (src == FRHDMIRX) {
|
||||
frhdmirx_ctrl(runtime->channels, 0);
|
||||
frhdmirx_src_select(0);
|
||||
if (src == FRATV) {
|
||||
/* Now tv supports 48k, 16bits */
|
||||
if ((bit_depth != 16) || (runtime->rate != 48000)) {
|
||||
pr_err("not support sample rate:%d, bits:%d\n",
|
||||
runtime->rate, bit_depth);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msb = 15;
|
||||
lsb = 0;
|
||||
|
||||
fratv_src_select(1);
|
||||
} else if (src == FRHDMIRX) {
|
||||
if (p_extn->hdmirx_mode) { /* PAO */
|
||||
|
||||
if (bit_depth == 32)
|
||||
toddr_type = 3;
|
||||
else if (bit_depth == 24)
|
||||
toddr_type = 4;
|
||||
else
|
||||
toddr_type = 0;
|
||||
|
||||
msb = 28 - 1 - 4;
|
||||
if (bit_depth == 16)
|
||||
lsb = 24 - bit_depth;
|
||||
else
|
||||
lsb = 4;
|
||||
}
|
||||
|
||||
frhdmirx_ctrl(runtime->channels, p_extn->hdmirx_mode);
|
||||
frhdmirx_src_select(p_extn->hdmirx_mode);
|
||||
} else {
|
||||
pr_info("Not support toddr src:%s\n",
|
||||
toddr_src_get_str(src));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pr_info("%s m:%d, n:%d\n", __func__, msb, lsb);
|
||||
|
||||
fmt.type = toddr_type;
|
||||
fmt.msb = msb;
|
||||
fmt.lsb = lsb;
|
||||
@@ -486,7 +527,150 @@ static struct snd_soc_dai_driver extn_dai[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const char *const arc_src_txt[] = {
|
||||
"HI_HDMIRX_ARC_CNTL[5]",
|
||||
"AUDIO_SPDIF_A",
|
||||
"AUDIO_SPDIF_B",
|
||||
"HDMIR_AUD_SPDIF",
|
||||
};
|
||||
|
||||
const struct soc_enum arc_src_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(arc_src_txt),
|
||||
arc_src_txt);
|
||||
|
||||
static int arc_get_src(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
ucontrol->value.integer.value[0] = p_extn->arc_src;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_set_src(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
p_extn->arc_src = ucontrol->value.integer.value[0];
|
||||
|
||||
cec_arc_enable(p_extn->arc_src, p_extn->arc_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_get_enable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
ucontrol->value.integer.value[0] = p_extn->arc_en;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_set_enable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
p_extn->arc_en = ucontrol->value.integer.value[0];
|
||||
|
||||
cec_arc_enable(p_extn->arc_src, p_extn->arc_en);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int frhdmirx_get_mode(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
ucontrol->value.integer.value[0] = p_extn->hdmirx_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int frhdmirx_set_mode(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
|
||||
struct extn *p_extn = dev_get_drvdata(component->dev);
|
||||
|
||||
p_extn->hdmirx_mode = ucontrol->value.integer.value[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new extn_controls[] = {
|
||||
/* Out */
|
||||
SOC_ENUM_EXT("HDMI ARC Source",
|
||||
arc_src_enum,
|
||||
arc_get_src,
|
||||
arc_set_src),
|
||||
|
||||
SOC_SINGLE_BOOL_EXT("HDMI ARC Switch",
|
||||
0,
|
||||
arc_get_enable,
|
||||
arc_set_enable),
|
||||
|
||||
/* In */
|
||||
SOC_SINGLE_BOOL_EXT("SPDIFIN PAO",
|
||||
0,
|
||||
frhdmirx_get_mode,
|
||||
frhdmirx_set_mode),
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
SOC_ENUM_EXT("ATV audio stable",
|
||||
atv_audio_status_enum,
|
||||
aml_get_atv_audio_stable,
|
||||
NULL),
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
SOC_ENUM_EXT("HDMIIN audio stable",
|
||||
hdmi_in_status_enum[0],
|
||||
aml_get_hdmiin_audio_stable,
|
||||
NULL),
|
||||
|
||||
SOC_ENUM_EXT("HDMIIN audio samplerate",
|
||||
hdmi_in_status_enum[1],
|
||||
aml_get_hdmiin_audio_samplerate,
|
||||
NULL),
|
||||
|
||||
SOC_ENUM_EXT("HDMIIN audio channels",
|
||||
hdmi_in_status_enum[2],
|
||||
aml_get_hdmiin_audio_channels,
|
||||
NULL),
|
||||
|
||||
SOC_ENUM_EXT("HDMIIN audio format",
|
||||
hdmi_in_status_enum[3],
|
||||
aml_get_hdmiin_audio_format,
|
||||
NULL),
|
||||
|
||||
SOC_SINGLE_BOOL_EXT("HDMI ATMOS EDID Switch",
|
||||
0,
|
||||
aml_get_atmos_audio_edid,
|
||||
aml_set_atmos_audio_edid),
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver extn_component = {
|
||||
.controls = extn_controls,
|
||||
.num_controls = ARRAY_SIZE(extn_controls),
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
@@ -506,16 +690,16 @@ static int extn_platform_probe(struct platform_device *pdev)
|
||||
struct platform_device *pdev_parent;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct aml_audio_controller *actrl = NULL;
|
||||
struct extn *extn = NULL;
|
||||
struct extn *p_extn = NULL;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
extn = devm_kzalloc(dev, sizeof(struct extn), GFP_KERNEL);
|
||||
if (!extn)
|
||||
p_extn = devm_kzalloc(dev, sizeof(struct extn), GFP_KERNEL);
|
||||
if (!p_extn)
|
||||
return -ENOMEM;
|
||||
|
||||
extn->dev = dev;
|
||||
dev_set_drvdata(dev, extn);
|
||||
p_extn->dev = dev;
|
||||
dev_set_drvdata(dev, p_extn);
|
||||
|
||||
/* get audio controller */
|
||||
node_prt = of_get_parent(node);
|
||||
@@ -526,16 +710,22 @@ static int extn_platform_probe(struct platform_device *pdev)
|
||||
of_node_put(node_prt);
|
||||
actrl = (struct aml_audio_controller *)
|
||||
platform_get_drvdata(pdev_parent);
|
||||
extn->actrl = actrl;
|
||||
p_extn->actrl = actrl;
|
||||
|
||||
/* irqs */
|
||||
extn->irq_frhdmirx = platform_get_irq_byname(pdev, "irq_frhdmirx");
|
||||
if (extn->irq_frhdmirx < 0) {
|
||||
p_extn->irq_frhdmirx = platform_get_irq_byname(pdev, "irq_frhdmirx");
|
||||
if (p_extn->irq_frhdmirx < 0) {
|
||||
dev_err(dev, "Failed to get irq_frhdmirx:%d\n",
|
||||
extn->irq_frhdmirx);
|
||||
p_extn->irq_frhdmirx);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Default ARC SRC */
|
||||
p_extn->arc_src = 1;
|
||||
|
||||
/* Default: PAO mode */
|
||||
p_extn->hdmirx_mode = 1;
|
||||
|
||||
ret = snd_soc_register_component(&pdev->dev,
|
||||
&extn_component,
|
||||
extn_dai,
|
||||
|
||||
@@ -81,6 +81,13 @@ void frhdmirx_ctrl(int channels, int src)
|
||||
{
|
||||
int lane, lane_mask = 0, i;
|
||||
|
||||
/* PAO mode */
|
||||
if (src) {
|
||||
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0,
|
||||
0x1 << 23 | 0x1 << 22 | 0x1 << 7);
|
||||
return;
|
||||
}
|
||||
|
||||
if (channels % 2)
|
||||
lane = channels / 2 + 1;
|
||||
else
|
||||
@@ -90,9 +97,10 @@ void frhdmirx_ctrl(int channels, int src)
|
||||
lane_mask |= (1 << i);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0,
|
||||
0x1 << 30 | 0xf << 24 | 0x3 << 11,
|
||||
0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11,
|
||||
0x1 << 30 | /* chnum_sel */
|
||||
lane_mask << 24 | /* chnum_sel */
|
||||
0x1 << 22 | /* clk_inv */
|
||||
0x0 << 11 /* req_sel, Sync 4 spdifin by which */
|
||||
);
|
||||
|
||||
|
||||
@@ -204,6 +204,33 @@ void audioreset_update_bits(unsigned int reg,
|
||||
}
|
||||
EXPORT_SYMBOL(audioreset_update_bits);
|
||||
|
||||
int vad_read(unsigned int reg)
|
||||
{
|
||||
int ret, val = 0;
|
||||
|
||||
ret = aml_snd_read(IO_VAD, reg, &val);
|
||||
|
||||
if (ret) {
|
||||
pr_err("read audio reg %x error %d\n", reg, ret);
|
||||
return -1;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL(vad_read);
|
||||
|
||||
void vad_write(unsigned int reg, unsigned int val)
|
||||
{
|
||||
aml_snd_write(IO_VAD, reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL(vad_write);
|
||||
|
||||
void vad_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
aml_snd_update_bits(IO_VAD, reg, mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL(vad_update_bits);
|
||||
|
||||
static int snd_iomap_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource res;
|
||||
|
||||
@@ -24,6 +24,7 @@ enum{
|
||||
IO_AUDIO_LOCKER,
|
||||
IO_EQDRC_BUS,
|
||||
IO_RESET,
|
||||
IO_VAD,
|
||||
|
||||
IO_MAX,
|
||||
};
|
||||
@@ -52,4 +53,9 @@ extern int audioreset_read(unsigned int reg);
|
||||
extern void audioreset_write(unsigned int reg, unsigned int val);
|
||||
extern void audioreset_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
|
||||
extern int vad_read(unsigned int reg);
|
||||
extern void vad_write(unsigned int reg, unsigned int val);
|
||||
extern void vad_update_bits(unsigned int reg,
|
||||
unsigned int mask, unsigned int val);
|
||||
#endif
|
||||
|
||||
@@ -181,7 +181,7 @@ static DEVICE_ATTR(locker_enable, 0644,
|
||||
void audio_locker_set(int enable)
|
||||
{
|
||||
if (!s_locker) {
|
||||
pr_err("audio locker is not init\n");
|
||||
pr_debug("audio locker is not init\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -676,6 +676,9 @@ static int aml_pdm_dai_prepare(
|
||||
}
|
||||
p_pdm->filter_mode = s_pdm_filter_mode;
|
||||
aml_pdm_filter_ctrl(osr, p_pdm->filter_mode);
|
||||
|
||||
if (p_pdm->chipinfo && p_pdm->chipinfo->truncate_data)
|
||||
pdm_init_truncate_data(runtime->rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -874,7 +877,7 @@ static struct pdm_chipinfo g12a_pdm_chipinfo = {
|
||||
|
||||
static struct pdm_chipinfo tl1_pdm_chipinfo = {
|
||||
.mute_fn = true,
|
||||
.truncate_data = true,
|
||||
.truncate_data = false,
|
||||
};
|
||||
|
||||
static const struct of_device_id aml_pdm_device_id[] = {
|
||||
|
||||
@@ -452,3 +452,13 @@ void pdm_set_mute_channel(int mute_chmask)
|
||||
(0xff << 20 | 0x1 << 17),
|
||||
(mute_chmask << 20 | mute_en << 17));
|
||||
}
|
||||
|
||||
void pdm_init_truncate_data(int freq)
|
||||
{
|
||||
int mask_val;
|
||||
|
||||
/* assume mask 1.05ms */
|
||||
mask_val = ((freq / 1000) * 1050) / 1000 - 1;
|
||||
|
||||
aml_pdm_write(PDM_MASK_NUM, mask_val);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ 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_init_truncate_data(int freq);
|
||||
|
||||
extern int pdm_hcic_shift_gain;
|
||||
extern int pdm_dclk;
|
||||
|
||||
|
||||
@@ -270,16 +270,27 @@ enum clk_sel {
|
||||
#define EE_AUDIO_SPDIFIN_STAT2 0x109
|
||||
#define EE_AUDIO_SPDIFIN_MUTE_VAL 0x10a
|
||||
|
||||
#define EE_AUDIO_RESAMPLE_CTRL0 0x110
|
||||
#define EE_AUDIO_RESAMPLE_CTRL1 0x111
|
||||
#define EE_AUDIO_RESAMPLE_CTRL2 0x112
|
||||
#define EE_AUDIO_RESAMPLE_CTRL3 0x113
|
||||
#define EE_AUDIO_RESAMPLE_COEF0 0x114
|
||||
#define EE_AUDIO_RESAMPLE_COEF1 0x115
|
||||
#define EE_AUDIO_RESAMPLE_COEF2 0x116
|
||||
#define EE_AUDIO_RESAMPLE_COEF3 0x117
|
||||
#define EE_AUDIO_RESAMPLE_COEF4 0x118
|
||||
#define EE_AUDIO_RESAMPLE_STATUS1 0x119
|
||||
#define EE_AUDIO_RESAMPLEA_CTRL0 0x110
|
||||
#define EE_AUDIO_RESAMPLEA_CTRL1 0x111
|
||||
#define EE_AUDIO_RESAMPLEA_CTRL2 0x112
|
||||
#define EE_AUDIO_RESAMPLEA_CTRL3 0x113
|
||||
#define EE_AUDIO_RESAMPLEA_COEF0 0x114
|
||||
#define EE_AUDIO_RESAMPLEA_COEF1 0x115
|
||||
#define EE_AUDIO_RESAMPLEA_COEF2 0x116
|
||||
#define EE_AUDIO_RESAMPLEA_COEF3 0x117
|
||||
#define EE_AUDIO_RESAMPLEA_COEF4 0x118
|
||||
#define EE_AUDIO_RESAMPLEA_STATUS1 0x119
|
||||
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL0 0x1e0
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL1 0x1e1
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL2 0x1e2
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL3 0x1e3
|
||||
#define EE_AUDIO_RESAMPLEB_COEF0 0x1e4
|
||||
#define EE_AUDIO_RESAMPLEB_COEF1 0x1e5
|
||||
#define EE_AUDIO_RESAMPLEB_COEF2 0x1e6
|
||||
#define EE_AUDIO_RESAMPLEB_COEF3 0x1e7
|
||||
#define EE_AUDIO_RESAMPLEB_COEF4 0x1e8
|
||||
#define EE_AUDIO_RESAMPLEB_STATUS1 0x1e9
|
||||
|
||||
#define EE_AUDIO_SPDIFOUT_STAT 0x120
|
||||
#define EE_AUDIO_SPDIFOUT_GAIN0 0x121
|
||||
@@ -403,6 +414,11 @@ enum clk_sel {
|
||||
*/
|
||||
#define EE_RESET1 0x002
|
||||
|
||||
/*
|
||||
* HIU, ARC
|
||||
*/
|
||||
#define HHI_HDMIRX_ARC_CNTL 0xe8
|
||||
|
||||
/*
|
||||
* AUDIO MUX CONTROLS
|
||||
*/
|
||||
@@ -411,17 +427,6 @@ enum clk_sel {
|
||||
#define EE_AUDIO_TOVAD_CTRL0 0x1d2
|
||||
#define EE_AUDIO_FRATV_CTRL0 0x1d3
|
||||
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL0 0x1e0
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL1 0x1e1
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL2 0x1e2
|
||||
#define EE_AUDIO_RESAMPLEB_CTRL3 0x1e3
|
||||
#define EE_AUDIO_RESAMPLEB_COEF0 0x1e4
|
||||
#define EE_AUDIO_RESAMPLEB_COEF1 0x1e5
|
||||
#define EE_AUDIO_RESAMPLEB_COEF2 0x1e6
|
||||
#define EE_AUDIO_RESAMPLEB_COEF3 0x1e7
|
||||
#define EE_AUDIO_RESAMPLEB_COEF4 0x1e8
|
||||
#define EE_AUDIO_RESAMPLEB_STATUS1 0x1e9
|
||||
|
||||
#define EE_AUDIO_SPDIFIN_LB_CTRL0 0x1f0
|
||||
#define EE_AUDIO_SPDIFIN_LB_CTRL1 0x1f1
|
||||
#define EE_AUDIO_SPDIFIN_LB_CTRL6 0x1f6
|
||||
@@ -507,7 +512,7 @@ enum clk_sel {
|
||||
#define RO_AUD_LOCK_INT_STATUS 0x01b
|
||||
|
||||
/*
|
||||
* EQ DRC, g12a, g12b
|
||||
* EQ DRC, G12X means g12a, g12b
|
||||
*/
|
||||
#define AED_EQ_CH1_COEF00 0x00
|
||||
#define AED_EQ_CH1_COEF01 0x01
|
||||
@@ -645,6 +650,10 @@ enum clk_sel {
|
||||
#define AED_DRC_AD_1M_H 0x85
|
||||
#define AED_NG_CNT 0x86
|
||||
#define AED_NG_STEP 0x87
|
||||
|
||||
#define AED_TOP_CTL_G12X 0x88
|
||||
#define AED_TOP_REQ_CTL_G12X 0x89
|
||||
|
||||
/*
|
||||
* EQ DRC, New ARCH, from tl1
|
||||
*/
|
||||
@@ -780,8 +789,9 @@ enum clk_sel {
|
||||
#define AED_MASTER_VOLUME_STATE 0x81
|
||||
#define AED_MASTER_VOLUME_GAIN 0x82
|
||||
|
||||
#define AED_TOP_CTL 0x88
|
||||
#define AED_TOP_REQ_CTL 0x89
|
||||
#define AED_TOP_CTL 0x83
|
||||
#define AED_TOP_REQ_CTL 0x84
|
||||
|
||||
|
||||
/*
|
||||
* VAD, Voice activity detection
|
||||
|
||||
@@ -34,7 +34,15 @@
|
||||
|
||||
#define CLK_RATIO 256
|
||||
|
||||
/*#define __PTM_RESAMPLE_CLK__*/
|
||||
|
||||
#define RESAMPLE_A 0
|
||||
#define RESAMPLE_B 1
|
||||
|
||||
struct resample_chipinfo {
|
||||
int num; /* support resample a/b */
|
||||
int id;
|
||||
|
||||
bool dividor_fn;
|
||||
};
|
||||
|
||||
@@ -50,18 +58,46 @@ struct audioresample {
|
||||
|
||||
struct resample_chipinfo *chipinfo;
|
||||
|
||||
int id;
|
||||
|
||||
/*which module should be resampled */
|
||||
int resample_module;
|
||||
/* resample to the rate */
|
||||
int out_rate;
|
||||
|
||||
/* sync with auge_resample_texts */
|
||||
int asr_idx;
|
||||
int asrc_rate_idx;
|
||||
|
||||
bool enable;
|
||||
};
|
||||
|
||||
struct audioresample *s_resample;
|
||||
struct audioresample *s_resample_a;
|
||||
|
||||
struct audioresample *s_resample_b;
|
||||
|
||||
static struct audioresample *get_audioresample(int id)
|
||||
{
|
||||
struct audioresample *p_resample;
|
||||
|
||||
p_resample = ((id == 0) ? s_resample_a : s_resample_b);
|
||||
|
||||
if (!p_resample) {
|
||||
pr_info("Not init audio resample\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p_resample;
|
||||
}
|
||||
|
||||
int get_resample_module_num(void)
|
||||
{
|
||||
struct audioresample *p_resample = get_audioresample(0);
|
||||
|
||||
if (p_resample && p_resample->chipinfo)
|
||||
return p_resample->chipinfo->num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int resample_clk_set(struct audioresample *p_resample)
|
||||
{
|
||||
@@ -84,8 +120,13 @@ static int resample_clk_set(struct audioresample *p_resample)
|
||||
}
|
||||
|
||||
if (p_resample->out_rate) {
|
||||
#ifdef __PTM_RESAMPLE_CLK__
|
||||
clk_set_rate(p_resample->pll,
|
||||
p_resample->out_rate * CLK_RATIO * 2 * 14);
|
||||
#else
|
||||
clk_set_rate(p_resample->pll,
|
||||
p_resample->out_rate * CLK_RATIO * 2);
|
||||
#endif
|
||||
clk_set_rate(p_resample->sclk,
|
||||
p_resample->out_rate * CLK_RATIO);
|
||||
clk_set_rate(p_resample->clk,
|
||||
@@ -121,20 +162,20 @@ static void audio_resample_init(struct audioresample *p_resample)
|
||||
{
|
||||
resample_clk_set(p_resample);
|
||||
|
||||
aml_resample_enable(p_resample->enable,
|
||||
aml_set_resample(p_resample->id, p_resample->enable,
|
||||
p_resample->resample_module);
|
||||
}
|
||||
|
||||
static int audio_resample_set(int enable, int rate)
|
||||
static int audio_resample_set(
|
||||
struct audioresample *p_resample,
|
||||
bool enable, int rate)
|
||||
{
|
||||
if (!s_resample) {
|
||||
pr_err("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!p_resample)
|
||||
return 0;
|
||||
|
||||
s_resample->enable = (bool)enable;
|
||||
s_resample->out_rate = rate;
|
||||
audio_resample_init(s_resample);
|
||||
p_resample->enable = enable;
|
||||
p_resample->out_rate = rate;
|
||||
audio_resample_init(p_resample);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -186,41 +227,40 @@ static int resample_get_enum(
|
||||
|
||||
if (!p_resample) {
|
||||
pr_info("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_resample->asr_idx;
|
||||
ucontrol->value.enumerated.item[0] = p_resample->asrc_rate_idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resample_set(int index)
|
||||
int resample_set(int id, int index)
|
||||
{
|
||||
int resample_rate = resample_idx2rate(index);
|
||||
struct audioresample *p_resample = get_audioresample(id);
|
||||
|
||||
if (!s_resample) {
|
||||
pr_info("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (index == s_resample->asr_idx)
|
||||
if (!p_resample)
|
||||
return 0;
|
||||
|
||||
s_resample->asr_idx = index;
|
||||
if (index == p_resample->asrc_rate_idx)
|
||||
return 0;
|
||||
|
||||
p_resample->asrc_rate_idx = index;
|
||||
|
||||
pr_info("%s %s\n",
|
||||
__func__,
|
||||
auge_resample_texts[index]);
|
||||
|
||||
if (audio_resample_set(index, resample_rate))
|
||||
if (audio_resample_set(p_resample, (bool)index, resample_rate))
|
||||
return 0;
|
||||
|
||||
if ((index == 0) || (resample_rate == 0))
|
||||
resample_disable();
|
||||
resample_disable(p_resample->id);
|
||||
else {
|
||||
resample_init(resample_rate);
|
||||
resample_init(p_resample->id, resample_rate);
|
||||
|
||||
resample_set_hw_param(index - 1);
|
||||
resample_set_hw_param(p_resample->id, index - 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -230,9 +270,15 @@ static int resample_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct audioresample *p_resample = snd_kcontrol_chip(kcontrol);
|
||||
int index = ucontrol->value.enumerated.item[0];
|
||||
|
||||
resample_set(index);
|
||||
if (!p_resample) {
|
||||
pr_info("audio resample is not init\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
resample_set(p_resample->id, index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -289,9 +335,13 @@ static const char *const auge_resample_module_texts[] = {
|
||||
"TDMIN_C",
|
||||
"SPDIFIN",
|
||||
"PDMIN",
|
||||
"NONE",
|
||||
"FRATV", /* NONE for axg, g12a, g12b */
|
||||
"TDMIN_LB",
|
||||
"LOOPBACK",
|
||||
"LOOPBACK_A",
|
||||
"FRHDMIRX", /* from tl1 chipset*/
|
||||
"LOOPBACK_B",
|
||||
"SPDIFIN_LB",
|
||||
"VAD",
|
||||
};
|
||||
|
||||
static const struct soc_enum auge_resample_module_enum =
|
||||
@@ -306,7 +356,7 @@ static int resample_module_get_enum(
|
||||
|
||||
if (!p_resample) {
|
||||
pr_info("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ucontrol->value.enumerated.item[0] = p_resample->resample_module;
|
||||
@@ -322,32 +372,52 @@ static int resample_module_set_enum(
|
||||
|
||||
if (!p_resample) {
|
||||
pr_info("audio resample is not init\n");
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_resample->resample_module = ucontrol->value.enumerated.item[0];
|
||||
|
||||
/* update info to ddr */
|
||||
aml_resample_enable(p_resample->enable,
|
||||
aml_set_resample(p_resample->id,
|
||||
p_resample->enable,
|
||||
p_resample->resample_module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new snd_resample_controls[] = {
|
||||
static const struct snd_kcontrol_new asrc_a_controls[] = {
|
||||
SOC_ENUM_EXT("Hardware resample enable",
|
||||
auge_resample_enum,
|
||||
resample_get_enum,
|
||||
resample_set_enum),
|
||||
SOC_SINGLE_EXT_TLV("Hw resample pause enable",
|
||||
EE_AUDIO_RESAMPLE_CTRL2, 24, 0x1, 0,
|
||||
EE_AUDIO_RESAMPLEA_CTRL2, 24, 0x1, 0,
|
||||
mixer_audiobus_read, mixer_audiobus_write,
|
||||
NULL),
|
||||
SOC_SINGLE_EXT_TLV("Hw resample pause thd",
|
||||
EE_AUDIO_RESAMPLE_CTRL2, 0, 0xffffff, 0,
|
||||
EE_AUDIO_RESAMPLEA_CTRL2, 0, 0xffffff, 0,
|
||||
mixer_audiobus_read, mixer_audiobus_write,
|
||||
NULL),
|
||||
SOC_ENUM_EXT("Hardware resample module",
|
||||
SOC_ENUM_EXT("Hw resample module",
|
||||
auge_resample_module_enum,
|
||||
resample_module_get_enum,
|
||||
resample_module_set_enum),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new asrc_b_controls[] = {
|
||||
SOC_ENUM_EXT("Hardware resample b enable",
|
||||
auge_resample_enum,
|
||||
resample_get_enum,
|
||||
resample_set_enum),
|
||||
SOC_SINGLE_EXT_TLV("Hw resample b pause enable",
|
||||
EE_AUDIO_RESAMPLEB_CTRL2, 24, 0x1, 0,
|
||||
mixer_audiobus_read, mixer_audiobus_write,
|
||||
NULL),
|
||||
SOC_SINGLE_EXT_TLV("Hw resample b pause thd",
|
||||
EE_AUDIO_RESAMPLEB_CTRL2, 0, 0xffffff, 0,
|
||||
mixer_audiobus_read, mixer_audiobus_write,
|
||||
NULL),
|
||||
SOC_ENUM_EXT("Hw resample b module",
|
||||
auge_resample_module_enum,
|
||||
resample_module_get_enum,
|
||||
resample_module_set_enum),
|
||||
@@ -358,12 +428,24 @@ int card_add_resample_kcontrols(struct snd_soc_card *card)
|
||||
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;
|
||||
if (s_resample_a) {
|
||||
for (idx = 0; idx < ARRAY_SIZE(asrc_a_controls); idx++) {
|
||||
err = snd_ctl_add(card->snd_card,
|
||||
snd_ctl_new1(&asrc_a_controls[idx],
|
||||
s_resample_a));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_resample_b) {
|
||||
for (idx = 0; idx < ARRAY_SIZE(asrc_b_controls); idx++) {
|
||||
err = snd_ctl_add(card->snd_card,
|
||||
snd_ctl_new1(&asrc_b_controls[idx],
|
||||
s_resample_b));
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -373,6 +455,18 @@ static struct resample_chipinfo g12a_resample_chipinfo = {
|
||||
.dividor_fn = true,
|
||||
};
|
||||
|
||||
static struct resample_chipinfo tl1_resample_a_chipinfo = {
|
||||
.num = 2,
|
||||
.id = RESAMPLE_A,
|
||||
.dividor_fn = true,
|
||||
};
|
||||
|
||||
static struct resample_chipinfo tl1_resample_b_chipinfo = {
|
||||
.num = 2,
|
||||
.id = RESAMPLE_B,
|
||||
.dividor_fn = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id resample_device_id[] = {
|
||||
{
|
||||
.compatible = "amlogic, axg-resample",
|
||||
@@ -381,6 +475,14 @@ static const struct of_device_id resample_device_id[] = {
|
||||
.compatible = "amlogic, g12a-resample",
|
||||
.data = &g12a_resample_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-resample-a",
|
||||
.data = &tl1_resample_a_chipinfo,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic, tl1-resample-b",
|
||||
.data = &tl1_resample_b_chipinfo,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, resample_device_id);
|
||||
@@ -408,6 +510,9 @@ static int resample_platform_probe(struct platform_device *pdev)
|
||||
of_device_get_match_data(dev);
|
||||
if (!p_chipinfo)
|
||||
dev_warn_once(dev, "check whether to update resample chipinfo\n");
|
||||
else
|
||||
p_resample->id = p_chipinfo->id;
|
||||
|
||||
p_resample->chipinfo = p_chipinfo;
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "resample_module",
|
||||
@@ -458,8 +563,11 @@ static int resample_platform_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
p_resample->dev = dev;
|
||||
s_resample = p_resample;
|
||||
dev_set_drvdata(&pdev->dev, p_resample);
|
||||
|
||||
if (p_chipinfo && p_chipinfo->id == 1)
|
||||
s_resample_b = p_resample;
|
||||
else
|
||||
s_resample_a = p_resample;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -19,5 +19,8 @@
|
||||
|
||||
extern int card_add_resample_kcontrols(struct snd_soc_card *card);
|
||||
|
||||
extern int resample_set(int index);
|
||||
extern int resample_set(int id, int index);
|
||||
|
||||
extern int get_resample_module_num(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,35 +40,43 @@ static u32 resample_coef_parameters_table[7][5] = {
|
||||
{0x00800000, 0x0, 0x0, 0x0, 0x0},
|
||||
};
|
||||
|
||||
void resample_enable(bool enable)
|
||||
void resample_enable(int id, bool enable)
|
||||
{
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
|
||||
|
||||
audiobus_update_bits(reg,
|
||||
0x1 << 31,
|
||||
1 << 31);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
audiobus_update_bits(reg,
|
||||
0x1 << 31,
|
||||
0 << 31);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
audiobus_update_bits(reg,
|
||||
0x1 << 28,
|
||||
enable << 28);
|
||||
}
|
||||
|
||||
int resample_init(int input_sr)
|
||||
int resample_init(int id, int input_sr)
|
||||
{
|
||||
u16 Avg_cnt_init = 0;
|
||||
unsigned int clk_rate = 167000000;//clk81;
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
|
||||
|
||||
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);
|
||||
pr_info("resample id:%d, clk_rate = %u, input_sr = %d, Avg_cnt_init = %u\n",
|
||||
id,
|
||||
clk_rate,
|
||||
input_sr,
|
||||
Avg_cnt_init);
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
audiobus_update_bits(reg,
|
||||
0x3 << 26 | 0x3ff << 16 | 0xffff << 0,
|
||||
0x0 << 26 | /* method0 */
|
||||
RESAMPLE_CNT_CONTROL << 16 |
|
||||
@@ -77,23 +85,30 @@ int resample_init(int input_sr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resample_disable(void)
|
||||
int resample_disable(int id)
|
||||
{
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, 0);
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
|
||||
|
||||
audiobus_write(reg, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resample_set_hw_param(int index)
|
||||
int resample_set_hw_param(int id, int index)
|
||||
{
|
||||
int i;
|
||||
int i, reg, offset;
|
||||
|
||||
offset = EE_AUDIO_RESAMPLEB_COEF0 - EE_AUDIO_RESAMPLEA_COEF0;
|
||||
reg = EE_AUDIO_RESAMPLEA_COEF0 + offset * id;
|
||||
for (i = 0; i < 5; i++) {
|
||||
audiobus_write((EE_AUDIO_RESAMPLE_COEF0 + i),
|
||||
audiobus_write((reg + i),
|
||||
resample_coef_parameters_table[index][i]);
|
||||
}
|
||||
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL2,
|
||||
offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2;
|
||||
reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id;
|
||||
audiobus_update_bits(reg,
|
||||
1 << 25, 1 << 25);
|
||||
|
||||
return 0;
|
||||
@@ -101,23 +116,42 @@ int resample_set_hw_param(int index)
|
||||
|
||||
void resample_src_select(int src)
|
||||
{
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLE_CTRL0,
|
||||
audiobus_update_bits(EE_AUDIO_RESAMPLEA_CTRL0,
|
||||
0x3 << 29,
|
||||
src << 29);
|
||||
}
|
||||
|
||||
void resample_format_set(int ch_num, int bits)
|
||||
void resample_src_select_ab(int id, int src)
|
||||
{
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL3,
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id;
|
||||
|
||||
audiobus_update_bits(reg,
|
||||
0x7 << 16,
|
||||
src << 16);
|
||||
}
|
||||
|
||||
void resample_format_set(int id, int ch_num, int bits)
|
||||
{
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL3 - EE_AUDIO_RESAMPLEA_CTRL3;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL3 + offset * id;
|
||||
|
||||
audiobus_write(reg,
|
||||
ch_num << 8 | (bits - 1) << 0);
|
||||
}
|
||||
|
||||
int resample_ctrl_read(int idx)
|
||||
int resample_ctrl_read(int id)
|
||||
{
|
||||
return audiobus_read(EE_AUDIO_RESAMPLE_CTRL0);
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
|
||||
|
||||
return audiobus_read(reg);
|
||||
}
|
||||
|
||||
void resample_ctrl_write(int idx, int value)
|
||||
void resample_ctrl_write(int id, int value)
|
||||
{
|
||||
audiobus_write(EE_AUDIO_RESAMPLE_CTRL0, value);
|
||||
int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0;
|
||||
int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id;
|
||||
|
||||
audiobus_write(reg, value);
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
#ifndef __AML_AUDIO_RESAMPLE_HW_H__
|
||||
#define __AML_AUDIO_RESAMPLE_HW_H__
|
||||
|
||||
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_enable(int id, bool enable);
|
||||
extern int resample_init(int id, int input_sr);
|
||||
extern int resample_disable(int id);
|
||||
extern int resample_set_hw_param(int id, int index);
|
||||
extern void resample_src_select(int src);
|
||||
extern void resample_format_set(int ch_num, int bits);
|
||||
extern void resample_src_select_ab(int id, int src);
|
||||
extern void resample_format_set(int id, int ch_num, int bits);
|
||||
|
||||
extern int resample_ctrl_read(int idx);
|
||||
extern void resample_ctrl_write(int idx, int value);
|
||||
extern int resample_ctrl_read(int id);
|
||||
extern void resample_ctrl_write(int id, int value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,8 @@ struct spdif_chipinfo {
|
||||
bool hold_start;
|
||||
/* eq/drc */
|
||||
bool eq_drc_en;
|
||||
/* pc, pd interrupt is separated. */
|
||||
bool pcpd_separated;
|
||||
};
|
||||
|
||||
struct aml_spdif {
|
||||
@@ -93,10 +95,15 @@ struct aml_spdif {
|
||||
struct spdif_chipinfo *chipinfo;
|
||||
unsigned int clk_cont; /* CONTINUOUS CLOCK */
|
||||
|
||||
/*
|
||||
* resample a/b do asrc for spdif in
|
||||
*/
|
||||
unsigned int asrc_id;
|
||||
/* spdif in do asrc for pcm,
|
||||
* if raw data, disable it automatically.
|
||||
*/
|
||||
unsigned int auto_asrc;
|
||||
unsigned int auto_asrc;
|
||||
|
||||
/* check spdifin channel status for pcm or nonpcm */
|
||||
struct timer_list timer;
|
||||
struct work_struct work;
|
||||
@@ -113,6 +120,9 @@ struct aml_spdif {
|
||||
int is_reset;
|
||||
int last_sample_rate_mode;
|
||||
|
||||
/* last value for pc, pd */
|
||||
int pc_last;
|
||||
int pd_last;
|
||||
};
|
||||
|
||||
static const struct snd_pcm_hardware aml_spdif_hardware = {
|
||||
@@ -226,7 +236,7 @@ static int spdifin_check_audio_type(void)
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("%s audio type:%d\n", __func__, audio_type);
|
||||
pr_debug("%s audio type:%d\n", __func__, audio_type);
|
||||
|
||||
return audio_type;
|
||||
}
|
||||
@@ -241,9 +251,27 @@ static int spdifin_audio_type_get_enum(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For fake */
|
||||
static bool is_mute;
|
||||
static int aml_audio_set_spdif_mute(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
is_mute =
|
||||
ucontrol->value.integer.value[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.integer.value[0] = is_mute;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new snd_spdif_controls[] = {
|
||||
|
||||
SOC_ENUM_EXT("SPDIFIN Sample Rate", spdifin_sample_rate_enum,
|
||||
SOC_ENUM_EXT("SPDIFIN audio samplerate", spdifin_sample_rate_enum,
|
||||
spdifin_samplerate_get_enum,
|
||||
NULL),
|
||||
|
||||
@@ -251,6 +279,16 @@ static const struct snd_kcontrol_new snd_spdif_controls[] = {
|
||||
spdif_audio_type_enum,
|
||||
spdifin_audio_type_get_enum,
|
||||
NULL),
|
||||
|
||||
SOC_ENUM_EXT("Audio spdif format",
|
||||
spdif_format_enum,
|
||||
spdif_format_get_enum,
|
||||
spdif_format_set_enum),
|
||||
|
||||
SOC_SINGLE_BOOL_EXT("Audio spdif mute",
|
||||
0, aml_audio_get_spdif_mute,
|
||||
aml_audio_set_spdif_mute),
|
||||
|
||||
};
|
||||
|
||||
static bool spdifin_check_audiotype_by_sw(struct aml_spdif *p_spdif)
|
||||
@@ -296,12 +334,16 @@ static void spdifin_audio_type_work_func(struct work_struct *work)
|
||||
if (!p_spdif->auto_asrc)
|
||||
return;
|
||||
|
||||
#ifdef __PTM_SPDIF_CLK__
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (val & 0x2)
|
||||
/* nonpcm, resample disable */
|
||||
resample_set(0);
|
||||
resample_set(p_spdif->asrc_id, 0);
|
||||
else
|
||||
/* pcm, resample which rate ? */
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
resample_set(p_spdif->asrc_id, p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
static void spdifin_audio_type_detect_init(struct aml_spdif *p_spdif)
|
||||
@@ -334,13 +376,13 @@ static void spdifin_fast_reset(struct aml_spdif *p_spdif)
|
||||
|
||||
/* resample disable and reset */
|
||||
if (p_spdif->auto_asrc) {
|
||||
asr_ctrl_val = resample_ctrl_read(0);
|
||||
asr_ctrl_val = resample_ctrl_read(p_spdif->asrc_id);
|
||||
asr_ctrl_val &= ~(1 << 28);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
resample_ctrl_write(p_spdif->asrc_id, asr_ctrl_val);
|
||||
asr_ctrl_val |= (1 << 31);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
resample_ctrl_write(p_spdif->asrc_id, asr_ctrl_val);
|
||||
asr_ctrl_val &= ~(1 << 31);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
resample_ctrl_write(p_spdif->asrc_id, asr_ctrl_val);
|
||||
}
|
||||
|
||||
/* spdif in disable and reset */
|
||||
@@ -364,7 +406,7 @@ static void spdifin_fast_reset(struct aml_spdif *p_spdif)
|
||||
/* resample enable */
|
||||
if (p_spdif->auto_asrc) {
|
||||
asr_ctrl_val |= (1 << 28);
|
||||
resample_ctrl_write(0, asr_ctrl_val);
|
||||
resample_ctrl_write(p_spdif->asrc_id, asr_ctrl_val);
|
||||
}
|
||||
|
||||
/* spdif in enable */
|
||||
@@ -485,7 +527,8 @@ static void spdifin_status_event(struct aml_spdif *p_spdif)
|
||||
|
||||
/* resample enable, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
resample_set(p_spdif->asrc_id,
|
||||
p_spdif->auto_asrc);
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_SAMPLERATE, 1);
|
||||
@@ -495,18 +538,42 @@ static void spdifin_status_event(struct aml_spdif *p_spdif)
|
||||
|
||||
}
|
||||
|
||||
if (intrpt_status & 0x8) {
|
||||
pr_info("Pc changed, try to read spdifin audio type\n");
|
||||
if (p_spdif->chipinfo
|
||||
&& p_spdif->chipinfo->pcpd_separated) {
|
||||
if (intrpt_status & 0x8) {
|
||||
pr_info("Pc changed, try to read spdifin audio type\n");
|
||||
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_AUDIOTYPE, 1);
|
||||
extcon_set_state(p_spdif->edev,
|
||||
EXTCON_SPDIFIN_AUDIOTYPE, 1);
|
||||
|
||||
/* resample disable, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(0);
|
||||
#ifdef __PTM_SPDIF_CLK__
|
||||
/* resample disable, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->asrc_id, 0);
|
||||
#endif
|
||||
}
|
||||
if (intrpt_status & 0x10)
|
||||
pr_info("Pd changed\n");
|
||||
} else {
|
||||
if (intrpt_status & 0x8)
|
||||
pr_info("CH status changed\n");
|
||||
|
||||
if (intrpt_status & 0x10) {
|
||||
int val = spdifin_get_ch_status0to31();
|
||||
int pc_v = (val >> 16) & 0xffff;
|
||||
int pd_v = val & 0xffff;
|
||||
|
||||
if (pc_v != p_spdif->pc_last) {
|
||||
p_spdif->pc_last = pc_v;
|
||||
pr_info("Pc changed\n");
|
||||
}
|
||||
if (pd_v != p_spdif->pd_last) {
|
||||
p_spdif->pd_last = pd_v;
|
||||
pr_info("Pd changed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
@@ -514,7 +581,7 @@ static void spdifin_status_event(struct aml_spdif *p_spdif)
|
||||
|
||||
/* resample to 48k, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
resample_set(p_spdif->asrc_id, p_spdif->auto_asrc);
|
||||
}
|
||||
if (intrpt_status & 0x40)
|
||||
pr_info("valid changed\n");
|
||||
@@ -814,10 +881,6 @@ static int aml_dai_spdif_startup(
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
int ret;
|
||||
|
||||
pr_info("%s stream:%d\n",
|
||||
__func__,
|
||||
substream->stream);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
|
||||
if (p_spdif->clk_cont) {
|
||||
@@ -873,7 +936,7 @@ static int aml_dai_spdif_startup(
|
||||
}
|
||||
/* resample to 48k in default, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(p_spdif->auto_asrc);
|
||||
resample_set(p_spdif->asrc_id, p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -888,10 +951,6 @@ 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) {
|
||||
@@ -906,7 +965,7 @@ static void aml_dai_spdif_shutdown(
|
||||
} else {
|
||||
/* resample disabled, by hw */
|
||||
if (!spdifin_check_audiotype_by_sw(p_spdif))
|
||||
resample_set(0);
|
||||
resample_set(p_spdif->asrc_id, 0);
|
||||
|
||||
clk_disable_unprepare(p_spdif->clk_spdifin);
|
||||
clk_disable_unprepare(p_spdif->fixed_clk);
|
||||
@@ -933,7 +992,7 @@ static int aml_dai_spdif_prepare(
|
||||
|
||||
switch (p_spdif->id) {
|
||||
case 0:
|
||||
dst = SPDIFOUT;
|
||||
dst = SPDIFOUT_A;
|
||||
break;
|
||||
case 1:
|
||||
dst = SPDIFOUT_B;
|
||||
@@ -944,6 +1003,8 @@ static int aml_dai_spdif_prepare(
|
||||
}
|
||||
|
||||
fifo_id = aml_frddr_get_fifo_id(fr);
|
||||
aml_frddr_set_format(fr, bit_depth - 1,
|
||||
spdifout_get_frddr_type(bit_depth));
|
||||
aml_frddr_select_dst(fr, dst);
|
||||
aml_frddr_set_fifos(fr, 0x40, 0x20);
|
||||
|
||||
@@ -1119,10 +1180,6 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
{
|
||||
unsigned int mpll_freq = 0;
|
||||
|
||||
pr_info("%s, sys freq:%d\n",
|
||||
__func__,
|
||||
p_spdif->sysclk_freq);
|
||||
|
||||
if (p_spdif->sysclk_freq) {
|
||||
unsigned int mul = 4;
|
||||
int ret;
|
||||
@@ -1136,12 +1193,9 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
mpll_freq = p_spdif->sysclk_freq * mul;
|
||||
|
||||
#ifdef __PTM_SPDIF_CLK__
|
||||
mpll_freq = p_spdif->sysclk_freq * 58;
|
||||
/* mpll_freq = p_spdif->sysclk_freq * 58; */ /* 48k */
|
||||
mpll_freq = p_spdif->sysclk_freq * 58 / 2; /* 96k */
|
||||
#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);
|
||||
@@ -1156,18 +1210,18 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
|
||||
pr_err("Can't enable clk_spdifout clock: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
pr_info("\t set spdifout clk:%d, mpll:%d\n",
|
||||
p_spdif->sysclk_freq,
|
||||
mpll_freq);
|
||||
pr_info("\t get spdifout clk:%lu, mpll:%lu\n",
|
||||
clk_get_rate(p_spdif->clk_spdifout),
|
||||
clk_get_rate(p_spdif->sysclk));
|
||||
}
|
||||
}
|
||||
|
||||
static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
int clk_id, unsigned int freq, int dir)
|
||||
{
|
||||
pr_info("%s, clk_id:%d, freq:%d, dir:%d\n",
|
||||
__func__,
|
||||
clk_id,
|
||||
freq,
|
||||
dir);
|
||||
|
||||
if (clk_id == 0) {
|
||||
struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
@@ -1297,12 +1351,19 @@ static int aml_spdif_parse_of(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
pr_err("SPDIF IN extcon failed to register!!, ignore it\n");
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node,
|
||||
"asrc_id", &p_spdif->asrc_id);
|
||||
if (ret < 0)
|
||||
p_spdif->asrc_id = 0;
|
||||
|
||||
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",
|
||||
|
||||
pr_info("SPDIF id %d asrc_id:%d auto_asrc:%d\n",
|
||||
p_spdif->id,
|
||||
p_spdif->asrc_id,
|
||||
p_spdif->auto_asrc);
|
||||
}
|
||||
|
||||
@@ -1333,20 +1394,23 @@ struct spdif_chipinfo axg_spdif_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.irq_no_papb = true,
|
||||
.clr_irq_all_bits = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_a_chipinfo = {
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.id = SPDIF_A,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo g12a_spdif_b_chipinfo = {
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.id = SPDIF_B,
|
||||
.chnum_en = true,
|
||||
.hold_start = true,
|
||||
.eq_drc_en = true,
|
||||
.pcpd_separated = true,
|
||||
};
|
||||
|
||||
struct spdif_chipinfo tl1_spdif_a_chipinfo = {
|
||||
|
||||
@@ -179,6 +179,32 @@ void aml_spdif_fifo_reset(
|
||||
}
|
||||
}
|
||||
|
||||
int spdifout_get_frddr_type(int bitwidth)
|
||||
{
|
||||
unsigned int frddr_type = 0;
|
||||
|
||||
switch (bitwidth) {
|
||||
case 8:
|
||||
frddr_type = 0;
|
||||
break;
|
||||
case 16:
|
||||
frddr_type = 1;
|
||||
break;
|
||||
case 24:
|
||||
frddr_type = 4;
|
||||
break;
|
||||
case 32:
|
||||
frddr_type = 3;
|
||||
break;
|
||||
default:
|
||||
pr_err("runtime format invalid bitwidth: %d\n",
|
||||
bitwidth);
|
||||
break;
|
||||
}
|
||||
|
||||
return frddr_type;
|
||||
}
|
||||
|
||||
void aml_spdif_fifo_ctrl(
|
||||
struct aml_audio_controller *actrl,
|
||||
int bitwidth,
|
||||
@@ -186,23 +212,20 @@ void aml_spdif_fifo_ctrl(
|
||||
int index,
|
||||
unsigned int fifo_id)
|
||||
{
|
||||
unsigned int frddr_type, toddr_type;
|
||||
unsigned int toddr_type;
|
||||
unsigned int frddr_type = spdifout_get_frddr_type(bitwidth);
|
||||
|
||||
switch (bitwidth) {
|
||||
case 8:
|
||||
frddr_type = 0;
|
||||
toddr_type = 0;
|
||||
break;
|
||||
case 16:
|
||||
frddr_type = 1;
|
||||
toddr_type = 1;
|
||||
break;
|
||||
case 24:
|
||||
frddr_type = 4;
|
||||
toddr_type = 4;
|
||||
break;
|
||||
case 32:
|
||||
frddr_type = 3;
|
||||
toddr_type = 3;
|
||||
break;
|
||||
default:
|
||||
@@ -336,7 +359,7 @@ void aml_spdifout_select_aed(bool enable, int spdifout_id)
|
||||
/* select eq_drc output */
|
||||
offset = EE_AUDIO_SPDIFOUT_B_CTRL1 - EE_AUDIO_SPDIFOUT_CTRL1;
|
||||
reg = EE_AUDIO_SPDIFOUT_CTRL1 + offset * spdifout_id;
|
||||
audiobus_update_bits(reg, 0x1 << 31, enable << 31);
|
||||
audiobus_update_bits(reg, 0x1 << 21, enable << 21);
|
||||
}
|
||||
|
||||
void aml_spdifout_get_aed_info(int spdifout_id,
|
||||
@@ -382,28 +405,9 @@ void spdifout_clk_ctrl(int spdif_id, bool is_enable)
|
||||
|
||||
void spdifout_fifo_ctrl(int spdif_id, int fifo_id, int bitwidth)
|
||||
{
|
||||
unsigned int frddr_type;
|
||||
unsigned int frddr_type = spdifout_get_frddr_type(bitwidth);
|
||||
unsigned int offset, reg;
|
||||
|
||||
switch (bitwidth) {
|
||||
case 8:
|
||||
frddr_type = 0;
|
||||
break;
|
||||
case 16:
|
||||
frddr_type = 1;
|
||||
break;
|
||||
case 24:
|
||||
frddr_type = 4;
|
||||
break;
|
||||
case 32:
|
||||
frddr_type = 3;
|
||||
break;
|
||||
default:
|
||||
pr_err("runtime format invalid bitwidth: %d\n",
|
||||
bitwidth);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("spdif_%s fifo ctrl, frddr:%d type:%d, %d bits\n",
|
||||
(spdif_id == 0) ? "a":"b",
|
||||
fifo_id,
|
||||
|
||||
@@ -51,6 +51,8 @@ extern void aml_spdif_fifo_reset(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream, int index);
|
||||
|
||||
extern int spdifout_get_frddr_type(int bitwidth);
|
||||
|
||||
extern void aml_spdif_fifo_ctrl(
|
||||
struct aml_audio_controller *actrl,
|
||||
int bitwidth,
|
||||
|
||||
@@ -349,7 +349,7 @@ static struct snd_pcm_ops aml_tdm_ops = {
|
||||
.mmap = aml_tdm_mmap,
|
||||
};
|
||||
|
||||
#define PREALLOC_BUFFER (32 * 1024)
|
||||
#define PREALLOC_BUFFER (128 * 1024)
|
||||
#define PREALLOC_BUFFER_MAX (256 * 1024)
|
||||
static int aml_tdm_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
@@ -444,6 +444,8 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
|
||||
p_tdm->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
aml_frddr_set_format(fr, bit_depth - 1,
|
||||
tdmout_get_frddr_type(bit_depth));
|
||||
aml_frddr_select_dst(fr, dst);
|
||||
aml_frddr_set_fifos(fr, 0x40, 0x20);
|
||||
} else {
|
||||
@@ -811,9 +813,6 @@ static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
unsigned int ratio = aml_mpll_mclk_ratio(freq);
|
||||
|
||||
pr_info("aml_dai_set_tdm_sysclk freq(%d), mpll/mclk(%d)\n",
|
||||
freq, ratio);
|
||||
|
||||
p_tdm->setting.sysclk = freq;
|
||||
|
||||
#ifdef __PTM_TDM_CLK__
|
||||
@@ -828,6 +827,12 @@ static int aml_dai_set_tdm_sysclk(struct snd_soc_dai *cpu_dai,
|
||||
clk_set_rate(p_tdm->clk, freq * ratio);
|
||||
clk_set_rate(p_tdm->mclk, freq);
|
||||
|
||||
pr_info("set mclk:%d, mpll:%d, get mclk:%lu, mpll:%lu\n",
|
||||
freq,
|
||||
freq * ratio,
|
||||
clk_get_rate(p_tdm->mclk),
|
||||
clk_get_rate(p_tdm->clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1069,7 +1074,7 @@ static struct snd_soc_dai_driver aml_tdm_dai[] = {
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver aml_tdm_component = {
|
||||
.name = DRV_NAME,
|
||||
.name = DRV_NAME,
|
||||
};
|
||||
|
||||
struct tdm_chipinfo axg_tdma_chipinfo = {
|
||||
|
||||
@@ -141,13 +141,9 @@ void tdm_fifo_enable(int tdm_index, int is_enable)
|
||||
}
|
||||
}
|
||||
|
||||
void aml_tdm_fifo_ctrl(
|
||||
struct aml_audio_controller *actrl,
|
||||
int bitwidth, int stream,
|
||||
int index, unsigned int fifo_id)
|
||||
int tdmout_get_frddr_type(int bitwidth)
|
||||
{
|
||||
unsigned int frddr_type;
|
||||
unsigned int reg, offset;
|
||||
unsigned int frddr_type = 0;
|
||||
|
||||
switch (bitwidth) {
|
||||
case 8:
|
||||
@@ -163,9 +159,20 @@ void aml_tdm_fifo_ctrl(
|
||||
default:
|
||||
pr_err("invalid bit_depth: %d\n",
|
||||
bitwidth);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
return frddr_type;
|
||||
}
|
||||
|
||||
void aml_tdm_fifo_ctrl(
|
||||
struct aml_audio_controller *actrl,
|
||||
int bitwidth, int stream,
|
||||
int index, unsigned int fifo_id)
|
||||
{
|
||||
unsigned int frddr_type = tdmout_get_frddr_type(bitwidth);
|
||||
unsigned int reg, offset;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
pr_debug("tdm prepare----playback\n");
|
||||
// from ddr, 63bit split into 2 samples
|
||||
|
||||
@@ -72,6 +72,8 @@ extern void aml_tdm_fifo_reset(
|
||||
struct aml_audio_controller *actrl,
|
||||
int stream, int index);
|
||||
|
||||
extern int tdmout_get_frddr_type(int bitwidth);
|
||||
|
||||
extern void aml_tdm_fifo_ctrl(
|
||||
struct aml_audio_controller *actrl,
|
||||
int bitwidth, int stream,
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
|
||||
static spinlock_t aclk_lock;
|
||||
|
||||
static const char *const mclk_parent_names[] = {"mpll0", "mpll1",
|
||||
"mpll2", "mpll3", "hifi_pll", "fclk_div3", "fclk_div4", "gp0_pll"};
|
||||
static const char *const mclk_parent_names[] = {
|
||||
"mpll0", "mpll1", "mpll2", "mpll3", "hifi_pll",
|
||||
"fclk_div3", "fclk_div4", "fclk_div5"};
|
||||
|
||||
static const char *const audioclk_parent_names[] = {
|
||||
"mclk_a", "mclk_b", "mclk_c", "mclk_d", "mclk_e",
|
||||
@@ -105,38 +106,38 @@ static struct clk_gate *tl1_audio_clk_gates[] = {
|
||||
|
||||
/* Array of all clocks provided by this provider */
|
||||
static struct clk_hw *tl1_audio_clk_hws[] = {
|
||||
[CLKID_AUDIO_DDR_ARB] = &audio_ddr_arb.hw,
|
||||
[CLKID_AUDIO_PDM] = &audio_pdm.hw,
|
||||
[CLKID_AUDIO_TDMINA] = &audio_tdmina.hw,
|
||||
[CLKID_AUDIO_TDMINB] = &audio_tdminb.hw,
|
||||
[CLKID_AUDIO_TDMINC] = &audio_tdminc.hw,
|
||||
[CLKID_AUDIO_TDMINLB] = &audio_tdminlb.hw,
|
||||
[CLKID_AUDIO_TDMOUTA] = &audio_tdmouta.hw,
|
||||
[CLKID_AUDIO_TDMOUTB] = &audio_tdmoutb.hw,
|
||||
[CLKID_AUDIO_TDMOUTC] = &audio_tdmoutc.hw,
|
||||
[CLKID_AUDIO_FRDDRA] = &audio_frddra.hw,
|
||||
[CLKID_AUDIO_FRDDRB] = &audio_frddrb.hw,
|
||||
[CLKID_AUDIO_FRDDRC] = &audio_frddrc.hw,
|
||||
[CLKID_AUDIO_TODDRA] = &audio_toddra.hw,
|
||||
[CLKID_AUDIO_TODDRB] = &audio_toddrb.hw,
|
||||
[CLKID_AUDIO_TODDRC] = &audio_toddrc.hw,
|
||||
[CLKID_AUDIO_LOOPBACKA] = &audio_loopbacka.hw,
|
||||
[CLKID_AUDIO_SPDIFIN] = &audio_spdifin.hw,
|
||||
[CLKID_AUDIO_SPDIFOUT] = &audio_spdifout.hw,
|
||||
[CLKID_AUDIO_RESAMPLEA] = &audio_resamplea.hw,
|
||||
[CLKID_AUDIO_RESERVED0] = &audio_reserved0.hw,
|
||||
[CLKID_AUDIO_RESERVED1] = &audio_reserved1.hw,
|
||||
[CLKID_AUDIO_SPDIFOUTB] = &audio_spdifoutb.hw,
|
||||
[CLKID_AUDIO_EQDRC] = &audio_eqdrc.hw,
|
||||
[CLKID_AUDIO_RESAMPLEB] = &audio_resampleb.hw,
|
||||
[CLKID_AUDIO_TOVAD] = &audio_tovad.hw,
|
||||
[CLKID_AUDIO_AUDIOLOCKER] = &audio_audiolocker.hw,
|
||||
[CLKID_AUDIO_SPDIFIN_LB] = &audio_spdifin_lb.hw,
|
||||
[CLKID_AUDIO_FRATV] = &audio_fratv.hw,
|
||||
[CLKID_AUDIO_FRHDMIRX] = &audio_frhdmirx.hw,
|
||||
[CLKID_AUDIO_FRDDRD] = &audio_frddrd.hw,
|
||||
[CLKID_AUDIO_TODDRD] = &audio_toddrd.hw,
|
||||
[CLKID_AUDIO_LOOPBACKB] = &audio_loopbackb.hw,
|
||||
[CLKID_AUDIO_GATE_DDR_ARB] = &audio_ddr_arb.hw,
|
||||
[CLKID_AUDIO_GATE_PDM] = &audio_pdm.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINA] = &audio_tdmina.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINB] = &audio_tdminb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINC] = &audio_tdminc.hw,
|
||||
[CLKID_AUDIO_GATE_TDMINLB] = &audio_tdminlb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTA] = &audio_tdmouta.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTB] = &audio_tdmoutb.hw,
|
||||
[CLKID_AUDIO_GATE_TDMOUTC] = &audio_tdmoutc.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRA] = &audio_frddra.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRB] = &audio_frddrb.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRC] = &audio_frddrc.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRA] = &audio_toddra.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRB] = &audio_toddrb.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRC] = &audio_toddrc.hw,
|
||||
[CLKID_AUDIO_GATE_LOOPBACKA] = &audio_loopbacka.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFIN] = &audio_spdifin.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFOUT_A] = &audio_spdifout.hw,
|
||||
[CLKID_AUDIO_GATE_RESAMPLEA] = &audio_resamplea.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED0] = &audio_reserved0.hw,
|
||||
[CLKID_AUDIO_GATE_RESERVED1] = &audio_reserved1.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFOUT_B] = &audio_spdifoutb.hw,
|
||||
[CLKID_AUDIO_GATE_EQDRC] = &audio_eqdrc.hw,
|
||||
[CLKID_AUDIO_GATE_RESAMPLEB] = &audio_resampleb.hw,
|
||||
[CLKID_AUDIO_GATE_TOVAD] = &audio_tovad.hw,
|
||||
[CLKID_AUDIO_GATE_AUDIOLOCKER] = &audio_audiolocker.hw,
|
||||
[CLKID_AUDIO_GATE_SPDIFIN_LB] = &audio_spdifin_lb.hw,
|
||||
[CLKID_AUDIO_GATE_FRATV] = &audio_fratv.hw,
|
||||
[CLKID_AUDIO_GATE_FRHDMIRX] = &audio_frhdmirx.hw,
|
||||
[CLKID_AUDIO_GATE_FRDDRD] = &audio_frddrd.hw,
|
||||
[CLKID_AUDIO_GATE_TODDRD] = &audio_toddrd.hw,
|
||||
[CLKID_AUDIO_GATE_LOOPBACKB] = &audio_loopbackb.hw,
|
||||
};
|
||||
|
||||
static int tl1_clk_gates_init(struct clk **clks, void __iomem *iobase)
|
||||
@@ -189,6 +190,19 @@ CLOCK_COM_GATE(spdifin, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFIN_CTRL), 31);
|
||||
CLOCK_COM_MUX(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 0, 10);
|
||||
CLOCK_COM_GATE(spdifout, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_CTRL), 31);
|
||||
/* audio resample_a */
|
||||
CLOCK_COM_MUX(resample_a,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(resample_a, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31);
|
||||
/* audio locker_out */
|
||||
CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8);
|
||||
CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31);
|
||||
/* audio locker_in */
|
||||
CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8);
|
||||
CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15);
|
||||
/* pdmin0 */
|
||||
CLOCK_COM_MUX(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0x7, 24);
|
||||
CLOCK_COM_DIV(pdmin0, AUD_ADDR_OFFSET(EE_AUDIO_CLK_PDMIN_CTRL0), 0, 16);
|
||||
@@ -202,18 +216,24 @@ CLOCK_COM_MUX(spdifout_b,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 10);
|
||||
CLOCK_COM_GATE(spdifout_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31);
|
||||
/* audio locker_out */
|
||||
CLOCK_COM_MUX(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 16, 8);
|
||||
CLOCK_COM_GATE(locker_out, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 31);
|
||||
/* audio locker_in */
|
||||
CLOCK_COM_MUX(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0xf, 8);
|
||||
CLOCK_COM_DIV(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(locker_in, AUD_ADDR_OFFSET(EE_AUDIO_CLK_LOCKER_CTRL), 15);
|
||||
/* audio resample */
|
||||
CLOCK_COM_MUX(resample, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(resample, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(resample, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEA_CTRL), 31);
|
||||
/* audio resample_b */
|
||||
CLOCK_COM_MUX(resample_b,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0xf, 24);
|
||||
CLOCK_COM_DIV(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 0, 8);
|
||||
CLOCK_COM_GATE(resample_b, AUD_ADDR_OFFSET(EE_AUDIO_CLK_RESAMPLEB_CTRL), 31);
|
||||
/* spdifin_lb, div is a fake */
|
||||
CLOCK_COM_MUX(spdifin_lb,
|
||||
AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0x1, 30);
|
||||
CLOCK_COM_DIV(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 0, 29);
|
||||
CLOCK_COM_GATE(spdifin_lb, AUD_ADDR_OFFSET(EE_AUDIO_CLK_SPDIFOUT_B_CTRL), 31);
|
||||
/* audio eqdrc */
|
||||
CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24);
|
||||
CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16);
|
||||
CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31);
|
||||
/* audio vad */
|
||||
CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24);
|
||||
CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16);
|
||||
CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31);
|
||||
|
||||
static int tl1_clks_init(struct clk **clks, void __iomem *iobase)
|
||||
{
|
||||
@@ -242,12 +262,24 @@ static int tl1_clks_init(struct clk **clks, void __iomem *iobase)
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_MCLK_F]));
|
||||
|
||||
IOMAP_COM_CLK(spdifin, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFIN_CTRL] = REGISTER_CLK_COM(spdifin);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_CTRL]));
|
||||
clks[CLKID_AUDIO_SPDIFIN] = REGISTER_CLK_COM(spdifin);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN]));
|
||||
|
||||
IOMAP_COM_CLK(spdifout, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFOUT_CTRL] = REGISTER_CLK_COM(spdifout);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_CTRL]));
|
||||
clks[CLKID_AUDIO_SPDIFOUT_A] = REGISTER_CLK_COM(spdifout);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_A]));
|
||||
|
||||
IOMAP_COM_CLK(resample_a, iobase);
|
||||
clks[CLKID_AUDIO_RESAMPLE_A] = REGISTER_AUDIOCLK_COM(resample_a);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_A]));
|
||||
|
||||
IOMAP_COM_CLK(locker_out, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT]));
|
||||
|
||||
IOMAP_COM_CLK(locker_in, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN]));
|
||||
|
||||
IOMAP_COM_CLK(pdmin0, iobase);
|
||||
clks[CLKID_AUDIO_PDMIN0] = REGISTER_CLK_COM(pdmin0);
|
||||
@@ -258,20 +290,24 @@ static int tl1_clks_init(struct clk **clks, void __iomem *iobase)
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_PDMIN1]));
|
||||
|
||||
IOMAP_COM_CLK(spdifout_b, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFOUTB_CTRL] = REGISTER_CLK_COM(spdifout_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUTB_CTRL]));
|
||||
clks[CLKID_AUDIO_SPDIFOUT_B] = REGISTER_CLK_COM(spdifout_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFOUT_B]));
|
||||
|
||||
IOMAP_COM_CLK(locker_out, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_OUT] = REGISTER_AUDIOCLK_COM(locker_out);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_OUT]));
|
||||
IOMAP_COM_CLK(resample_b, iobase);
|
||||
clks[CLKID_AUDIO_RESAMPLE_B] = REGISTER_AUDIOCLK_COM(resample_b);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_B]));
|
||||
|
||||
IOMAP_COM_CLK(locker_in, iobase);
|
||||
clks[CLKID_AUDIO_LOCKER_IN] = REGISTER_AUDIOCLK_COM(locker_in);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_LOCKER_IN]));
|
||||
IOMAP_COM_CLK(spdifin_lb, iobase);
|
||||
clks[CLKID_AUDIO_SPDIFIN_LB] = REGISTER_CLK_COM(spdifin_lb);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_SPDIFIN_LB]));
|
||||
|
||||
IOMAP_COM_CLK(resample, iobase);
|
||||
clks[CLKID_AUDIO_RESAMPLE_CTRL] = REGISTER_AUDIOCLK_COM(resample);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_RESAMPLE_CTRL]));
|
||||
IOMAP_COM_CLK(eqdrc, iobase);
|
||||
clks[CLKID_AUDIO_EQDRC] = REGISTER_CLK_COM(eqdrc);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_EQDRC]));
|
||||
|
||||
IOMAP_COM_CLK(vad, iobase);
|
||||
clks[CLKID_AUDIO_VAD] = REGISTER_CLK_COM(vad);
|
||||
WARN_ON(IS_ERR_OR_NULL(clks[CLKID_AUDIO_VAD]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
obj-y += notify.o spdif_info.o
|
||||
obj-y += notify.o \
|
||||
spdif_info.o \
|
||||
misc.o
|
||||
|
||||
248
sound/soc/amlogic/common/misc.c
Normal file
248
sound/soc/amlogic/common/misc.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* sound/soc/amlogic/common/misc.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <linux/amlogic/media/sound/misc.h>
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
#include <linux/amlogic/aml_atvdemod.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
|
||||
#endif
|
||||
|
||||
static const char *const audio_is_stable[] = {
|
||||
"false",
|
||||
"true"
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
|
||||
const struct soc_enum atv_audio_status_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable),
|
||||
audio_is_stable);
|
||||
|
||||
int aml_get_atv_audio_stable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int state = 0;
|
||||
|
||||
aml_fe_get_atvaudio_state(&state);
|
||||
ucontrol->value.integer.value[0] = state;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_AMLOGIC_ATV_DEMOD */
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
int hdmiin_fifo_disable_count;
|
||||
|
||||
int get_hdmi_sample_rate_index(void)
|
||||
{
|
||||
struct rx_audio_stat_s aud_sts;
|
||||
int val = 0;
|
||||
|
||||
rx_get_audio_status(&aud_sts);
|
||||
switch (aud_sts.aud_sr) {
|
||||
case 0:
|
||||
val = 0;
|
||||
break;
|
||||
case 32000:
|
||||
val = 1;
|
||||
break;
|
||||
case 44100:
|
||||
val = 2;
|
||||
break;
|
||||
case 48000:
|
||||
val = 3;
|
||||
break;
|
||||
case 88200:
|
||||
val = 4;
|
||||
break;
|
||||
case 96000:
|
||||
val = 5;
|
||||
break;
|
||||
case 176400:
|
||||
val = 6;
|
||||
break;
|
||||
case 192000:
|
||||
val = 7;
|
||||
break;
|
||||
default:
|
||||
pr_err("HDMIRX samplerate not support: %d\n",
|
||||
aud_sts.aud_sr);
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int update_spdifin_audio_type(int audio_type)
|
||||
{
|
||||
struct rx_audio_stat_s aud_sts;
|
||||
|
||||
rx_get_audio_status(&aud_sts);
|
||||
if (aud_sts.afifo_thres_pass == true)
|
||||
hdmiin_fifo_disable_count = 0;
|
||||
else
|
||||
hdmiin_fifo_disable_count++;
|
||||
if (hdmiin_fifo_disable_count > 200)
|
||||
audio_type = 6/*PAUSE*/;
|
||||
|
||||
return audio_type;
|
||||
}
|
||||
|
||||
static const char *const hdmi_in_samplerate[] = {
|
||||
"N/A",
|
||||
"32000",
|
||||
"44100",
|
||||
"48000",
|
||||
"88200",
|
||||
"96000",
|
||||
"176400",
|
||||
"192000"
|
||||
};
|
||||
|
||||
static const char *const hdmi_in_channels[] = {
|
||||
"NONE",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8"
|
||||
};
|
||||
|
||||
enum HDMIIN_format {
|
||||
REFER_TO_HEADER = 0,
|
||||
LPCM = 1,
|
||||
AC3,
|
||||
MPEG1,
|
||||
MP3,
|
||||
MPEG2,
|
||||
AAC,
|
||||
DTS,
|
||||
ATRAC,
|
||||
ONE_BIT_AUDIO,
|
||||
DDP,
|
||||
DTS_HD,
|
||||
MAT,
|
||||
DST,
|
||||
WMA_PRO
|
||||
};
|
||||
|
||||
static const char * const hdmi_in_format[] = {
|
||||
"REFER_TO_HEADER",
|
||||
"LPCM",
|
||||
"AC3",
|
||||
"MPEG1",
|
||||
"MP3",
|
||||
"MPEG2",
|
||||
"AAC",
|
||||
"DTS",
|
||||
"ATRAC",
|
||||
"ONE_BIT_AUDIO",
|
||||
"DDP",
|
||||
"DTS_HD",
|
||||
"MAT",
|
||||
"DST",
|
||||
"WMA_PRO"
|
||||
};
|
||||
|
||||
const struct soc_enum hdmi_in_status_enum[] = {
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(audio_is_stable),
|
||||
audio_is_stable),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_samplerate),
|
||||
hdmi_in_samplerate),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_channels),
|
||||
hdmi_in_channels),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_format),
|
||||
hdmi_in_format)
|
||||
};
|
||||
|
||||
int aml_get_hdmiin_audio_stable(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct rx_audio_stat_s aud_sts;
|
||||
|
||||
rx_get_audio_status(&aud_sts);
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_rcv_flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aml_get_hdmiin_audio_samplerate(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int val = get_hdmi_sample_rate_index();
|
||||
|
||||
ucontrol->value.integer.value[0] = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aml_get_hdmiin_audio_channels(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct rx_audio_stat_s aud_sts;
|
||||
|
||||
rx_get_audio_status(&aud_sts);
|
||||
if (aud_sts.aud_channel_cnt <= 7)
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_channel_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aml_get_hdmiin_audio_format(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct rx_audio_stat_s aud_sts;
|
||||
|
||||
rx_get_audio_status(&aud_sts);
|
||||
if (aud_sts.aud_type <= 14)
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call HDMI CEC API to enable arc audio */
|
||||
int aml_set_atmos_audio_edid(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
bool enable = ucontrol->value.integer.value[0];
|
||||
|
||||
rx_set_atmos_flag(enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aml_get_atmos_audio_edid(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
bool flag = rx_get_atmos_flag();
|
||||
|
||||
ucontrol->value.integer.value[0] = flag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -158,3 +158,35 @@ void spdif_notify_to_hdmitx(struct snd_pcm_substream *substream)
|
||||
substream);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *const spdif_format_texts[10] = {
|
||||
"2 CH PCM", "DTS RAW Mode", "Dolby Digital", "DTS",
|
||||
"DD+", "DTS-HD", "Multi-channel LPCM", "TrueHD", "DTS-HD MA",
|
||||
"HIGH SR Stereo LPCM"
|
||||
};
|
||||
|
||||
const struct soc_enum spdif_format_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_format_texts),
|
||||
spdif_format_texts);
|
||||
|
||||
int spdif_format_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.enumerated.item[0] = IEC958_mode_codec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spdif_format_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int index = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (index >= 10) {
|
||||
pr_err("bad parameter for spdif format set\n");
|
||||
return -1;
|
||||
}
|
||||
IEC958_mode_codec = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/amlogic/media/vout/hdmi_tx/hdmi_tx_ext.h>
|
||||
#endif
|
||||
#include "spdif_dai.h"
|
||||
#include <linux/amlogic/media/sound/spdif_info.h>
|
||||
|
||||
#define DRV_NAME "spdif-dit"
|
||||
|
||||
@@ -164,38 +165,6 @@ static int aml_audio_get_spdif_mute(struct snd_kcontrol *kcontrol,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const spdif_format_texts[10] = {
|
||||
"2 CH PCM", "DTS RAW Mode", "Dolby Digital", "DTS",
|
||||
"DD+", "DTS-HD", "Multi-channel LPCM", "TrueHD", "DTS-HD MA",
|
||||
"HIGH SR Stereo LPCM"
|
||||
};
|
||||
|
||||
static const struct soc_enum spdif_format_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_format_texts),
|
||||
spdif_format_texts);
|
||||
|
||||
static int spdif_format_get_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
ucontrol->value.enumerated.item[0] = IEC958_mode_codec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spdif_format_set_enum(
|
||||
struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int index = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (index >= 10) {
|
||||
pr_err("bad parameter for spdif format set\n");
|
||||
return -1;
|
||||
}
|
||||
IEC958_mode_codec = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_HDMITX
|
||||
/* call HDMITX API to enable/disable internal audio out */
|
||||
static int aml_get_hdmi_out_audio(struct snd_kcontrol *kcontrol,
|
||||
|
||||
@@ -50,9 +50,8 @@
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
#include <linux/amlogic/aml_atvdemod.h>
|
||||
#endif
|
||||
|
||||
#include <linux/amlogic/media/sound/misc.h>
|
||||
|
||||
#include "i2s.h"
|
||||
#include "audio_hw.h"
|
||||
@@ -63,34 +62,6 @@
|
||||
#define AML_EQ_PARAM_LENGTH 100
|
||||
#define AML_DRC_PARAM_LENGTH 12
|
||||
#define AML_REG_BYTES 4
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
static int hdmiin_fifo_disable_count;
|
||||
|
||||
/* copy from drivers/amlogic/tvin/hdmirx/hdmirx_drv.h */
|
||||
struct hdmi_in_audio_status {
|
||||
/*audio packets received*/
|
||||
bool aud_rcv_flag;
|
||||
/*audio stable status*/
|
||||
bool aud_stb_flag;
|
||||
/*audio sample rate*/
|
||||
int aud_sr;
|
||||
/*audio channel count*/
|
||||
/*0: refer to stream header,*/
|
||||
/*1: 2ch, 2: 3ch, 3: 4ch, 4: 5ch,*/
|
||||
/*5: 6ch, 6: 7ch, 7: 8ch*/
|
||||
int aud_channel_cnt;
|
||||
/*audio coding type*/
|
||||
/*0: refer to stream header, 1: IEC60958 PCM,*/
|
||||
/*2: AC-3, 3: MPEG1 (Layers 1 and 2),*/
|
||||
/*4: MP3 (MPEG1 Layer 3), 5: MPEG2 (multichannel),*/
|
||||
/*6: AAC, 7: DTS, 8: ATRAC, 9: One Bit Audio,*/
|
||||
/*10: Dolby Digital Plus, 11: DTS-HD,*/
|
||||
/*12: MAT (MLP), 13: DST, 14: WMA Pro*/
|
||||
int aud_type;
|
||||
/* indicate if audio FIFO start threshold is crossed */
|
||||
bool afifo_thres_pass;
|
||||
};
|
||||
#endif
|
||||
|
||||
static u32 aml_EQ_table[AML_EQ_PARAM_LENGTH] = {
|
||||
/*channel 1 param*/
|
||||
@@ -189,48 +160,6 @@ static int get_spdif_sample_rate_index(void)
|
||||
return index;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
static int get_hdmi_sample_rate_index(void)
|
||||
{
|
||||
struct hdmi_in_audio_status aud_sts;
|
||||
struct rx_audio_stat_s *rx_aud_sts;
|
||||
int val = 0;
|
||||
|
||||
rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts;
|
||||
rx_get_audio_status(rx_aud_sts);
|
||||
switch (aud_sts.aud_sr) {
|
||||
case 0:
|
||||
val = 0;
|
||||
break;
|
||||
case 32000:
|
||||
val = 1;
|
||||
break;
|
||||
case 44100:
|
||||
val = 2;
|
||||
break;
|
||||
case 48000:
|
||||
val = 3;
|
||||
break;
|
||||
case 88200:
|
||||
val = 4;
|
||||
break;
|
||||
case 96000:
|
||||
val = 5;
|
||||
break;
|
||||
case 176400:
|
||||
val = 6;
|
||||
break;
|
||||
case 192000:
|
||||
val = 7;
|
||||
break;
|
||||
default:
|
||||
pr_err("HDMIRX samplerate not support: %d\n", aud_sts.aud_sr);
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *const audio_in_source_texts[] = {
|
||||
"LINEIN", "ATV", "HDMI", "SPDIFIN" };
|
||||
|
||||
@@ -372,18 +301,9 @@ static int aml_get_spdif_audio_type(
|
||||
/* HDMI in,also check the hdmirx fifo status*/
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
if (audio_in_source == 2) {
|
||||
struct hdmi_in_audio_status aud_sts;
|
||||
struct rx_audio_stat_s *rx_aud_sts;
|
||||
int index = 0;
|
||||
|
||||
rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts;
|
||||
rx_get_audio_status(rx_aud_sts);
|
||||
if (aud_sts.afifo_thres_pass == true)
|
||||
hdmiin_fifo_disable_count = 0;
|
||||
else
|
||||
hdmiin_fifo_disable_count++;
|
||||
if (hdmiin_fifo_disable_count > 200)
|
||||
audio_type = 6/*PAUSE*/;
|
||||
update_spdifin_audio_type(audio_type);
|
||||
|
||||
index = get_hdmi_sample_rate_index();
|
||||
if (p_aml_audio &&
|
||||
@@ -642,161 +562,6 @@ static int aml_set_arc_audio(struct snd_kcontrol *kcontrol,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
/* call HDMI CEC API to enable arc audio */
|
||||
static int aml_set_atmos_audio_edid(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;
|
||||
bool enable = ucontrol->value.integer.value[0];
|
||||
|
||||
p_aml_audio = snd_soc_card_get_drvdata(card);
|
||||
rx_set_atmos_flag(enable);
|
||||
p_aml_audio->atmos_edid_enable = enable;
|
||||
return 0;
|
||||
}
|
||||
static int aml_get_atmos_audio_edid(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;
|
||||
|
||||
p_aml_audio = snd_soc_card_get_drvdata(card);
|
||||
ucontrol->value.integer.value[0] = p_aml_audio->atmos_edid_enable;
|
||||
return 0;
|
||||
}
|
||||
;
|
||||
static const char *const hdmi_in_is_stable[] = {
|
||||
"false",
|
||||
"true"
|
||||
};
|
||||
static const char *const hdmi_in_samplerate[] = {
|
||||
"N/A",
|
||||
"32000",
|
||||
"44100",
|
||||
"48000",
|
||||
"88200",
|
||||
"96000",
|
||||
"176400",
|
||||
"192000"
|
||||
};
|
||||
static const char *const hdmi_in_channels[] = {
|
||||
"NONE",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8"
|
||||
};
|
||||
enum HDMIIN_format {
|
||||
REFER_TO_HEADER = 0,
|
||||
LPCM = 1,
|
||||
AC3,
|
||||
MPEG1,
|
||||
MP3,
|
||||
MPEG2,
|
||||
AAC,
|
||||
DTS,
|
||||
ATRAC,
|
||||
ONE_BIT_AUDIO,
|
||||
DDP,
|
||||
DTS_HD,
|
||||
MAT,
|
||||
DST,
|
||||
WMA_PRO
|
||||
};
|
||||
static const char * const hdmi_in_format[] = {
|
||||
"REFER_TO_HEADER",
|
||||
"LPCM",
|
||||
"AC3",
|
||||
"MPEG1",
|
||||
"MP3",
|
||||
"MPEG2",
|
||||
"AAC",
|
||||
"DTS",
|
||||
"ATRAC",
|
||||
"ONE_BIT_AUDIO",
|
||||
"DDP",
|
||||
"DTS_HD",
|
||||
"MAT",
|
||||
"DST",
|
||||
"WMA_PRO"
|
||||
};
|
||||
static const struct soc_enum hdmi_in_status_enum[] = {
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_is_stable),
|
||||
hdmi_in_is_stable),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_samplerate),
|
||||
hdmi_in_samplerate),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_channels),
|
||||
hdmi_in_channels),
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hdmi_in_format),
|
||||
hdmi_in_format)
|
||||
};
|
||||
static int aml_get_hdmiin_audio_stable(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct hdmi_in_audio_status aud_sts;
|
||||
struct rx_audio_stat_s *rx_aud_sts;
|
||||
|
||||
rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts;
|
||||
rx_get_audio_status(rx_aud_sts);
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_rcv_flag;
|
||||
return 0;
|
||||
}
|
||||
static int aml_get_hdmiin_audio_samplerate(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int val = get_hdmi_sample_rate_index();
|
||||
ucontrol->value.integer.value[0] = val;
|
||||
return 0;
|
||||
}
|
||||
static int aml_get_hdmiin_audio_channels(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct rx_audio_stat_s *rx_aud_sts;
|
||||
struct hdmi_in_audio_status aud_sts;
|
||||
|
||||
rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts;
|
||||
rx_get_audio_status(rx_aud_sts);
|
||||
if (aud_sts.aud_channel_cnt <= 7)
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_channel_cnt;
|
||||
return 0;
|
||||
}
|
||||
static int aml_get_hdmiin_audio_format(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct rx_audio_stat_s *rx_aud_sts;
|
||||
struct hdmi_in_audio_status aud_sts;
|
||||
|
||||
rx_aud_sts = (struct rx_audio_stat_s *)&aud_sts;
|
||||
rx_get_audio_status(rx_aud_sts);
|
||||
if (aud_sts.aud_type <= 14)
|
||||
ucontrol->value.integer.value[0] = aud_sts.aud_type;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMLOGIC_ATV_DEMOD
|
||||
static const char *const atv_audio_is_stable[] = {
|
||||
"false",
|
||||
"true"
|
||||
};
|
||||
static const struct soc_enum atv_audio_status_enum =
|
||||
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(atv_audio_is_stable),
|
||||
atv_audio_is_stable);
|
||||
static int aml_get_atv_audio_stable(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
int state = 0;
|
||||
|
||||
aml_fe_get_atvaudio_state(&state);
|
||||
ucontrol->value.integer.value[0] = state;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_AMLOGIC_ATV_DEMOD */
|
||||
#ifdef CONFIG_TVIN_VDIN
|
||||
static const char *const av_audio_is_stable[] = {
|
||||
"false",
|
||||
|
||||
@@ -70,9 +70,6 @@ struct aml_audio_private_data {
|
||||
struct aml_card_info *cardinfo;
|
||||
#ifdef CONFIG_AMLOGIC_AO_CEC
|
||||
int arc_enable;
|
||||
#endif
|
||||
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
|
||||
int atmos_edid_enable;
|
||||
#endif
|
||||
int Hardware_resample_enable;
|
||||
int spdif_sample_rate_index;
|
||||
@@ -100,6 +97,4 @@ extern int External_Mute(int mute_flag);
|
||||
#else
|
||||
int External_Mute(int mute_flag) { return 0; }
|
||||
#endif
|
||||
extern void rx_set_atmos_flag(bool en);
|
||||
extern void rx_get_atmos_flag(void);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user