audio: codec: add tl1_acodec support for tl1 [1/1]

PD#SWPL-1759

Problem:
add tl1_acodec support

Solution:
add code, update xxx.dts and aml_codec_tl1_acodec.c

Verify:
verify by T962x2_X309 board

Change-Id: Ia91e4e0f113af3d537d1828c5c4cfabc127eac8f
Signed-off-by: shuyu.li <shuyu.li@amlogic.com>
This commit is contained in:
shuyu.li
2018-11-28 19:24:14 +08:00
committed by Dongjin Kim
parent 55bc24640a
commit 83aa4314fb
7 changed files with 203 additions and 45 deletions

View File

@@ -144,6 +144,7 @@
status = "disabled";
reg = <0xff632000 0x1c>;
tdmout_index = <1>;
tdmin_index = <1>;
};
aml_dtv_demod {

View File

@@ -163,9 +163,10 @@
tl1_codec:codec {
#sound-dai-cells = <0>;
compatible = "amlogic, tl1_acodec";
status = "disabled";
status = "okay";
reg = <0xff632000 0x1c>;
tdmout_index = <1>;
tdmout_index = <0>;
tdmin_index = <0>;
};
auge_sound {
@@ -176,7 +177,7 @@
format = "i2s";
mclk-fs = <256>;
//continuous-clock;
//bitclock-inversion;
bitclock-inversion;
//frame-inversion;
/* master mode */
bitclock-master = <&tdma>;
@@ -199,7 +200,8 @@
system-clock-frequency = <12288000>;
};
tdmacodec: codec {
sound-dai = <&dummy_codec>;
//sound-dai = <&dummy_codec>;
sound-dai = <&tl1_codec>;
};
};

View File

@@ -163,15 +163,18 @@
tl1_codec:codec {
#sound-dai-cells = <0>;
compatible = "amlogic, tl1_acodec";
status = "disabled";
status = "okay";
reg = <0xff632000 0x1c>;
tdmout_index = <1>;
tdmout_index = <0>;
tdmin_index = <0>;
};
auge_sound {
compatible = "amlogic, tl1-sound-card";
aml-audio-card,name = "AML-AUGESOUND";
avout_mute-gpios = <&gpio GPIODV_3 GPIO_ACTIVE_HIGH>;
aml-audio-card,dai-link@0 {
format = "i2s";
mclk-fs = <256>;
@@ -199,7 +202,8 @@
system-clock-frequency = <12288000>;
};
tdmacodec: codec {
sound-dai = <&ad82584f>;
//sound-dai = <&dummy_codec>;
sound-dai = <&ad82584f &tl1_codec>;
};
};
@@ -927,7 +931,7 @@
compatible = "amlogic, tl1-snd-tdma";
#sound-dai-cells = <0>;
#dai-tdm-lane-slot-mask-in = <1 0>;
dai-tdm-lane-slot-mask-in = <1 0>;
dai-tdm-lane-slot-mask-out = <1 1 1 1>;
dai-tdm-clk-sel = <0>;
@@ -948,6 +952,9 @@
*/
samesource_sel = <3>;
/* In for ACODEC_ADC */
acodec_adc = <1>;
status = "okay";
};

View File

@@ -88,6 +88,9 @@ struct tdm_chipinfo {
/* same source */
bool same_src_fn;
/* ACODEC_ADC function */
bool adc_fn;
};
struct aml_tdm {
@@ -111,6 +114,7 @@ struct aml_tdm {
int samesource_sel;
/* virtual link for i2s to hdmitx */
int i2s2hdmitx;
int acodec_adc;
};
static const struct snd_pcm_hardware aml_tdm_hardware = {
@@ -490,8 +494,15 @@ static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
if (toddr_src_get() == FRHDMIRX) {
src = FRHDMIRX;
tdm_update_slot_in(p_tdm->actrl, p_tdm->id, HDMIRX_I2S);
}
aml_update_tdmin_src(p_tdm->actrl,
p_tdm->id,
HDMIRX_I2S);
} else if (p_tdm->chipinfo
&& p_tdm->chipinfo->adc_fn
&& p_tdm->acodec_adc)
aml_update_tdmin_src(p_tdm->actrl,
p_tdm->id,
ACODEC_ADC);
pr_info("%s Expected toddr src:%s\n",
__func__,
@@ -786,6 +797,13 @@ static int aml_dai_set_tdm_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
cpu_dai->capture_active,
cpu_dai->playback_active);
/* update skew for ACODEC_ADC */
if (cpu_dai->capture_active
&& p_tdm->chipinfo
&& p_tdm->chipinfo->adc_fn
&& p_tdm->acodec_adc)
aml_update_tdmin_skew(p_tdm->actrl, p_tdm->id, 4);
return 0;
}
@@ -961,9 +979,17 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
out_lanes = lanes_out_cnt + lanes_oe_out_cnt;
in_lanes = lanes_in_cnt + lanes_oe_in_cnt + lanes_lb_cnt;
if (p_tdm->chipinfo
&& p_tdm->chipinfo->adc_fn
&& p_tdm->acodec_adc) {
in_src = ACODEC_ADC;
}
if (in_lanes >= 0 && in_lanes <= 4)
aml_tdm_set_slot_in(p_tdm->actrl,
p_tdm->id, in_src, slot_width);
if (out_lanes >= 0 && out_lanes <= 4)
aml_tdm_set_slot_out(p_tdm->actrl,
p_tdm->id, slots, slot_width,
@@ -1119,6 +1145,7 @@ struct tdm_chipinfo tl1_tdma_chipinfo = {
.oe_fn = true,
.clk_pad_ctl = true,
.same_src_fn = true,
.adc_fn = true,
};
struct tdm_chipinfo tl1_tdmb_chipinfo = {
@@ -1127,6 +1154,7 @@ struct tdm_chipinfo tl1_tdmb_chipinfo = {
.oe_fn = true,
.clk_pad_ctl = true,
.same_src_fn = true,
.adc_fn = true,
};
struct tdm_chipinfo tl1_tdmc_chipinfo = {
@@ -1135,6 +1163,7 @@ struct tdm_chipinfo tl1_tdmc_chipinfo = {
.oe_fn = true,
.clk_pad_ctl = true,
.same_src_fn = true,
.adc_fn = true,
};
static const struct of_device_id aml_tdm_device_id[] = {
@@ -1239,10 +1268,21 @@ static int aml_tdm_platform_probe(struct platform_device *pdev)
"Can't retrieve samesrc_sysclk clock\n");
return PTR_ERR(p_tdm->samesrc_sysclk);
}
pr_info("TDM id %d samesource_sel:%d\n",
p_tdm->id,
p_tdm->samesource_sel);
}
pr_info("TDM id %d samesource_sel:%d\n",
p_tdm->id,
p_tdm->samesource_sel);
}
/* default no acodec_adc */
if (p_tdm->chipinfo &&
p_tdm->chipinfo->adc_fn) {
ret = of_property_read_u32(node, "acodec_adc",
&p_tdm->acodec_adc);
if (ret < 0)
p_tdm->acodec_adc = 0;
else
pr_info("TDM id %d supports ACODEC_ADC\n", p_tdm->id);
}
ret = of_property_read_u32(node, "i2s2hdmi",

View File

@@ -403,6 +403,17 @@ void aml_tdm_set_format(
}
}
void aml_update_tdmin_skew(struct aml_audio_controller *actrl,
int idx, int skew)
{
unsigned int reg_in, off_set;
off_set = EE_AUDIO_TDMIN_B_CTRL - EE_AUDIO_TDMIN_A_CTRL;
reg_in = EE_AUDIO_TDMIN_A_CTRL + off_set * idx;
aml_audiobus_update_bits(actrl, reg_in,
0x7 << 16, skew << 16);
}
void aml_tdm_set_slot_out(
struct aml_audio_controller *actrl,
int index, int slots, int slot_width,
@@ -457,7 +468,7 @@ else
0xf << 20 | 0x1f, in_src << 20 | (slot_width-1));
}
void tdm_update_slot_in(
void aml_update_tdmin_src(
struct aml_audio_controller *actrl,
int index, int in_src)
{

View File

@@ -26,11 +26,11 @@ enum tdmin_src {
PAD_TDMINA_DIN = 0,
PAD_TDMINB_DIN = 1,
PAD_TDMINC_DIN = 2,
PAD_TDMINA_D = 4,
PAD_TDMINB_D = 5,
PAD_TDMINC_D = 6,
HDMIRX_I2S = 7,
ACODEC_ADC = 8,
PAD_TDMINA_D = 3,
PAD_TDMINB_D = 4,
PAD_TDMINC_D = 5,
HDMIRX_I2S = 6,
ACODEC_ADC = 7,
TDMOUTA = 13,
TDMOUTB = 14,
TDMOUTC = 15,
@@ -88,6 +88,9 @@ extern void aml_tdm_set_format(
unsigned int capture_active,
unsigned int playback_active);
extern void aml_update_tdmin_skew(struct aml_audio_controller *actrl,
int idx, int skew);
extern void aml_tdm_set_slot_out(
struct aml_audio_controller *actrl,
int index, int slots, int slot_width,
@@ -97,7 +100,7 @@ extern void aml_tdm_set_slot_in(
struct aml_audio_controller *actrl,
int index, int in_src, int slot_width);
extern void tdm_update_slot_in(
extern void aml_update_tdmin_src(
struct aml_audio_controller *actrl,
int index, int in_src);

View File

@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -37,21 +38,43 @@
#include <linux/amlogic/iomap.h>
#include <linux/amlogic/media/sound/auge_utils.h>
#include <linux/amlogic/media/sound/aiu_regs.h>
#include "../../../soc/amlogic/auge/iomap.h"
#include "../../../soc/amlogic/auge/regs.h"
#include "aml_codec_tl1_acodec.h"
struct tl1_acodec_chipinfo {
int id;
bool is_bclk_cap_inv; //default true
bool is_bclk_o_inv; //default false
bool is_lrclk_inv; //default false
bool is_dac_phase_differ_exist;
bool is_adc_phase_differ_exist;
int mclk_sel;
};
struct tl1_acodec_priv {
struct snd_soc_codec *codec;
struct snd_pcm_hw_params *params;
struct regmap *regmap;
struct tl1_acodec_chipinfo *chipinfo;
int tdmout_index;
int dat0_ch_sel;
int dat1_ch_sel;
int tdmin_index;
int adc_output_sel;
//int input_data_sel; //tdmouta,tdmoutb,
//tdmouta,tdmoutb,tdmoutc,tdmina,tdminb,tdminc
//int clk_sel;
//tdmouta,tdmoutb,tdmoutc,none,tdmina,tdminb,tdminc
int dac1_input_sel;
int dac2_input_sel;
};
static const struct reg_default tl1_acodec_init_list[] = {
{ACODEC_0, 0x3403BFCF},
{ACODEC_1, 0x50502929},
{ACODEC_1, 0x50503030},
{ACODEC_2, 0xFBFB0000},
{ACODEC_3, 0x00002222},
{ACODEC_4, 0x00010000},
@@ -59,6 +82,18 @@ static const struct reg_default tl1_acodec_init_list[] = {
{ACODEC_6, 0x0},
{ACODEC_7, 0x0}
};
static struct tl1_acodec_chipinfo tl1_acodec_cinfo = {
.id = 0,
.is_bclk_cap_inv = true, //default true
.is_bclk_o_inv = false, //default false
.is_lrclk_inv = false,
.is_dac_phase_differ_exist = false,
.is_adc_phase_differ_exist = true,
//if is_adc_phase_differ=true,modified tdmin_in_rev_ws,revert ws(lrclk);
//0 :disable; 1: enable;
//.mclk_sel = 1,
};
static int tl1_acodec_reg_init(struct snd_soc_codec *codec)
{
@@ -115,7 +150,7 @@ static int aml_DAC_Gain_set_enum(
pr_info("It has risk of distortion!\n");
}
snd_soc_write(codec, val, reg_addr);
snd_soc_write(codec, reg_addr, val);
return 0;
}
@@ -163,7 +198,7 @@ static int aml_DAC2_Gain_set_enum(
pr_info("It has risk of distortion!\n");
}
snd_soc_write(codec, val, reg_addr);
snd_soc_write(codec, reg_addr, val);
return 0;
}
@@ -519,34 +554,34 @@ static int tl1_acodec_dai_mute_stream(struct snd_soc_dai *dai, int mute,
struct tl1_acodec_priv *aml_acodec =
snd_soc_codec_get_drvdata(dai->codec);
u32 reg_val;
int ret;
pr_debug("%s, mute:%d\n", __func__, mute);
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* DAC 1 */
regmap_read(aml_acodec->regmap,
ret = regmap_read(aml_acodec->regmap,
ACODEC_2,
&reg_val);
if (mute)
reg_val |= DAC_SOFT_MUTE;
reg_val |= (0x1<<DAC_SOFT_MUTE);
else
reg_val &= ~DAC_SOFT_MUTE;
reg_val &= ~(0x1<<DAC_SOFT_MUTE);
regmap_write(aml_acodec->regmap,
ret = regmap_write(aml_acodec->regmap,
ACODEC_2,
reg_val);
/* DAC 2 */
regmap_read(aml_acodec->regmap,
ret = regmap_read(aml_acodec->regmap,
ACODEC_6,
&reg_val);
if (mute)
reg_val |= DAC2_SOFT_MUTE;
reg_val |= (0x1<<DAC2_SOFT_MUTE);
else
reg_val &= ~DAC2_SOFT_MUTE;
reg_val &= ~(0x1<<DAC2_SOFT_MUTE);
regmap_write(aml_acodec->regmap,
ret = regmap_write(aml_acodec->regmap,
ACODEC_6,
reg_val);
}
@@ -577,12 +612,9 @@ static int tl1_acodec_probe(struct snd_soc_codec *codec)
tl1_acodec_start_up(codec);
tl1_acodec_reg_init(codec);
if (aml_acodec)
auge_toacodec_ctrl(aml_acodec->tdmout_index);
aml_acodec->codec = codec;
tl1_acodec_dai_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
pr_info("%s\n", __func__);
return 0;
}
@@ -667,10 +699,50 @@ struct snd_soc_dai_driver aml_tl1_acodec_dai = {
},
.ops = &tl1_acodec_dai_ops,
};
static int tl1_acodec_set_toacodec(struct tl1_acodec_priv *aml_acodec)
{
int dat0_sel, dat1_sel, lrclk_sel, bclk_sel, mclk_sel;
unsigned int update_bits_msk = 0x0, update_bits = 0x0;
update_bits_msk = 0x80FF7777;
if (aml_acodec->chipinfo->is_bclk_cap_inv == true)
update_bits |= (0x1<<9);
if (aml_acodec->chipinfo->is_bclk_o_inv == true)
update_bits |= (0x1<<8);
if (aml_acodec->chipinfo->is_lrclk_inv == true)
update_bits |= (0x1<<10);
dat0_sel = (aml_acodec->tdmout_index<<2)+aml_acodec->dat0_ch_sel;
dat0_sel = dat0_sel<<16;
dat1_sel = (aml_acodec->tdmout_index<<2)+aml_acodec->dat1_ch_sel;
dat1_sel = dat1_sel<<20;
lrclk_sel = (aml_acodec->tdmout_index)<<12;
bclk_sel = (aml_acodec->tdmout_index)<<4;
//mclk_sel = aml_acodec->chipinfo->mclk_sel;
mclk_sel = aml_acodec->tdmin_index;
update_bits |= dat0_sel|dat1_sel|lrclk_sel|bclk_sel|mclk_sel;
update_bits |= 0x1<<31;
audiobus_update_bits(EE_AUDIO_TOACODEC_CTRL0, update_bits_msk,
update_bits);
pr_info("%s, is_bclk_cap_inv %s\n", __func__,
aml_acodec->chipinfo->is_bclk_cap_inv?"true":"false");
pr_info("%s, is_bclk_o_inv %s\n", __func__,
aml_acodec->chipinfo->is_bclk_o_inv?"true":"false");
pr_info("%s, is_lrclk_inv %s\n", __func__,
aml_acodec->chipinfo->is_lrclk_inv?"true":"false");
pr_info("%s read EE_AUDIO_TOACODEC_CTRL0=0x%08x\n", __func__,
audiobus_read(EE_AUDIO_TOACODEC_CTRL0));
return 0;
}
static int aml_tl1_acodec_probe(struct platform_device *pdev)
{
struct tl1_acodec_priv *aml_acodec;
struct tl1_acodec_chipinfo *p_chipinfo;
struct resource *res_mem;
struct device_node *np;
void __iomem *regs;
@@ -684,6 +756,13 @@ static int aml_tl1_acodec_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!aml_acodec)
return -ENOMEM;
/* match data */
p_chipinfo = (struct tl1_acodec_chipinfo *)
of_device_get_match_data(&pdev->dev);
if (!p_chipinfo)
dev_warn_once(&pdev->dev, "check whether to update tl1_acodec_chipinfo\n");
aml_acodec->chipinfo = p_chipinfo;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem)
@@ -695,24 +774,36 @@ static int aml_tl1_acodec_probe(struct platform_device *pdev)
aml_acodec->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
&tl1_acodec_regmap_config);
if (IS_ERR(aml_acodec->regmap))
return PTR_ERR(aml_acodec->regmap);
of_property_read_u32(
pdev->dev.of_node,
"tdmout_index",
&aml_acodec->tdmout_index);
pr_info("aml_tl1_acodec is used by tdmout:%d\n",
pr_info("aml_tl1_acodec tdmout_index=%d\n",
aml_acodec->tdmout_index);
if (IS_ERR(aml_acodec->regmap))
return PTR_ERR(aml_acodec->regmap);
of_property_read_u32(
pdev->dev.of_node,
"tdmin_index",
&aml_acodec->tdmin_index);
pr_info("aml_tl1_acodec tdmin_index=%d\n",
aml_acodec->tdmin_index);
tl1_acodec_set_toacodec(aml_acodec);
platform_set_drvdata(pdev, aml_acodec);
ret = snd_soc_register_codec(&pdev->dev,
&soc_codec_dev_tl1_acodec,
&aml_tl1_acodec_dai, 1);
if (ret)
pr_info("%s call snd_soc_register_codec error\n", __func__);
else
pr_info("%s over\n", __func__);
pr_info("%s read EE_AUDIO_TOACODEC_CTRL0=0x%08x\n", __func__,
audiobus_read(EE_AUDIO_TOACODEC_CTRL0));
return ret;
}
@@ -735,13 +826,16 @@ static void aml_tl1_acodec_shutdown(struct platform_device *pdev)
}
static const struct of_device_id aml_tl1_acodec_dt_match[] = {
{.compatible = "amlogic, tl1_codec",},
{
.compatible = "amlogic, tl1_acodec",
.data = &tl1_acodec_cinfo,
},
{},
};
static struct platform_driver aml_tl1_acodec_platform_driver = {
.driver = {
.name = "tl1_codec",
.name = "tl1_acodec",
.owner = THIS_MODULE,
.of_match_table = aml_tl1_acodec_dt_match,
},