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:
Xing Wang
2018-10-30 15:38:34 +08:00
committed by Dongjin Kim
parent 7ca30cf598
commit 55bc24640a
49 changed files with 5735 additions and 736 deletions

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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__ */

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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 \

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}

View 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);
}

View 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

View 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 */
};

View 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);

View 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

View File

@@ -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,

View File

@@ -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 */
);

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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[] = {

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -1 +1,3 @@
obj-y += notify.o spdif_info.o
obj-y += notify.o \
spdif_info.o \
misc.o

View 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

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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",

View File

@@ -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