audio: set audio path from frhdmirx through spdifin mode [1/2]

PD#SWPL-11054

Problem:
hdmiin source, audio input is randomly LR invert

Solution:
set audio path from frhdmirx through spdifin mode

Verify:
Verified on X301

Change-Id: Ib40d30b8b6d8bc28da69bf9b4f37ae2ef9228761
Signed-off-by: Zhe Wang <Zhe.Wang@amlogic.com>
This commit is contained in:
Zhe Wang
2019-07-09 17:07:20 +08:00
committed by Luke Go
parent d204178ebf
commit f52a9e725f
7 changed files with 109 additions and 118 deletions

View File

@@ -90,7 +90,7 @@ MODULE_PARM_DESC(hdcp22_on, "\n hdcp22_on\n");
module_param(hdcp22_on, int, 0664);
/* test for HBR CTS, audio module can set it to force 8ch */
int hbr_force_8ch = 1;
int hbr_force_8ch;
/*
* hdcp14_key_mode:hdcp1.4 key handle method select
* NORMAL_MODE:systemcontrol path
@@ -1913,7 +1913,7 @@ int hdmirx_audio_init(void)
hdmirx_wr_dwc(DWC_PDEC_ACRM_CTRL, data32);
/* unsupport HBR serial mode. invalid bit */
/* hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1); */
hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1);
/* SAO cfg, disable I2S output, no use */
data32 = 0;

View File

@@ -441,8 +441,8 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt)
reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base);
aml_audiobus_update_bits(actrl, reg,
0x7 << 24 | 0x1fff << 3,
fmt->endian << 24 | fmt->type << 13 |
0x1 << 27 | 0x7 << 24 | 0x1fff << 3,
0x1 << 27 | fmt->endian << 24 | fmt->type << 13 |
fmt->msb << 8 | fmt->lsb << 3);
}
@@ -651,9 +651,6 @@ static void aml_resample_enable(
}
}
/* resample enable or not */
resample_enable(p_attach_resample->id, enable);
/* select reample data */
if (to->chipinfo
&& to->chipinfo->asrc_src_sel_ctrl)
@@ -673,7 +670,6 @@ void aml_set_resample(enum resample_idx id,
{
struct toddr_attach *p_attach_resample;
struct toddr *to;
bool update_running = false;
if (id == RESAMPLE_A)
p_attach_resample = &attach_resample_a;
@@ -688,26 +684,7 @@ void aml_set_resample(enum resample_idx id,
to = fetch_toddr_by_src(
p_attach_resample->attach_module);
if (enable) {
if ((p_attach_resample->status == DISABLED)
|| (p_attach_resample->status == READY)) {
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 && to)
if (p_attach_resample->status == RUNNING)
aml_resample_enable(to, p_attach_resample, enable);
}

View File

@@ -48,6 +48,11 @@
#define DYNC_KCNTL_CNT 2
enum {
HDMIRX_MODE_SPDIFIN = 0,
HDMIRX_MODE_PAO = 1,
};
struct extn_chipinfo {
/* try to check papb before fetch pcpd
* no nonpcm2pcm irq for tl1
@@ -145,27 +150,24 @@ static irqreturn_t extn_ddr_isr(int irq, void *devid)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->platform->dev;
struct extn *p_extn = (struct extn *)dev_get_drvdata(dev);
int timeout_thres = 5;
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
int sample_rate_index = get_hdmi_sample_rate_index();
/*192K audio*/
if (sample_rate_index == 7)
timeout_thres = 10;
else
timeout_thres = 5;
#endif
if (!snd_pcm_running(substream))
return IRQ_HANDLED;
snd_pcm_period_elapsed(substream);
/* check pcm or nonpcm */
if (p_extn &&
p_extn->chipinfo &&
p_extn->chipinfo->no_nonpcm2pcm_clr) {
/* check pcm or nonpcm for PAO*/
if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) {
int timeout_thres = 5;
#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI
int sample_rate_index = get_hdmi_sample_rate_index();
/*192K audio*/
if (sample_rate_index == 7)
timeout_thres = 10;
else
timeout_thres = 5;
#endif
if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) {
p_extn->frhdmirx_same_cnt++;
@@ -181,6 +183,8 @@ static irqreturn_t extn_ddr_isr(int irq, void *devid)
p_extn->nonpcm_flag = true;
frhdmirx_clr_PAO_irq_bits();
}
} else {
frhdmirx_clr_SPDIF_irq_bits();
}
return IRQ_HANDLED;
@@ -258,8 +262,7 @@ static int extn_close(struct snd_pcm_substream *substream)
if (toddr_src_get() == FRHDMIRX) {
frhdmirx_nonpcm2pcm_clr_reset(p_extn);
if (p_extn->hdmirx_mode == 1)
frhdmirx_clr_PAO_irq_bits();
frhdmirx_clr_all_irq_bits();
free_irq(p_extn->irq_frhdmirx, p_extn);
}
}
@@ -497,20 +500,26 @@ static int extn_dai_prepare(
*/
/* 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;
if (bit_depth == 32)
toddr_type = 3;
else if (bit_depth == 24)
toddr_type = 4;
else
toddr_type = 0;
if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) { /* PAO */
msb = 28 - 1 - 4;
if (bit_depth == 16)
lsb = 24 - bit_depth;
else
lsb = 4;
} else { /* SPDIFIN */
msb = 28 - 1;
if (bit_depth <= 24)
lsb = 28 - bit_depth;
else
lsb = 4;
}
frhdmirx_ctrl(runtime->channels, p_extn->hdmirx_mode);
@@ -808,7 +817,7 @@ static int hdmiin_check_audio_type(struct extn *p_extn)
int audio_type = 0;
int i;
if (!p_extn->nonpcm_flag)
if (!p_extn->nonpcm_flag && p_extn->hdmirx_mode)
return audio_type;
for (i = 0; i < total_num; i++) {
@@ -931,9 +940,9 @@ static const struct snd_kcontrol_new extn_controls[] = {
aml_set_atmos_audio_edid),
SOC_ENUM_EXT("HDMIIN Audio Type",
hdmirx_audio_type_enum,
hdmirx_audio_type_get_enum,
NULL),
hdmirx_audio_type_enum,
hdmirx_audio_type_get_enum,
NULL),
#endif
};
@@ -1010,8 +1019,8 @@ static int extn_platform_probe(struct platform_device *pdev)
/* Default ARC SRC */
p_extn->arc_src = 1;
/* Default: PAO mode */
p_extn->hdmirx_mode = 1;
/* Default: SPDIFIN mode */
p_extn->hdmirx_mode = HDMIRX_MODE_SPDIFIN;
ret = devm_snd_soc_register_component(&pdev->dev,
&extn_component,

View File

@@ -51,12 +51,7 @@ void frhdmirx_src_select(int src)
static void frhdmirx_enable_irq_bits(int channels, int src)
{
int lane, int_bits = 0, i;
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
unsigned int int_bits = 0;
/* interrupt bits */
if (src) { /* PAO mode */
@@ -66,78 +61,59 @@ static void frhdmirx_enable_irq_bits(int channels, int src)
);
} else { /* SPDIF Lane */
int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
0x1 << 6 | /* lane: find papb */
0x1 << 6 | /* lane: find valid changed */
0x1 << 5 | /* lane: find nonpcm to pcm */
0x1 << 4 | /* lane: find pcpd changed */
0x1 << 3 | /* lane: find ch status changed */
0x1 << 1 /* lane: find parity error */
);
int lane, i;
lane = (channels % 2) ? (channels / 2 + 1) : (channels / 2);
for (i = 0; i < lane; i++)
int_bits |= (lane_irq_bits << i);
int_bits |= (lane_irq_bits << 8 * i);
}
int_bits |= audiobus_read(EE_AUDIO_FRHDMIRX_CTRL2);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits);
}
void frhdmirx_clr_irq_bits(int channels, int src)
void frhdmirx_clr_all_irq_bits(void)
{
int lane, int_clr_mask = 0, i;
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
/* interrupt bits */
if (src) { /* PAO mode */
int_clr_mask = (
0x1 << INT_PAO_PAPB_MASK | /* find papb */
0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */
);
} else { /* SPDIF Lane */
int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
0x1 << 6 | /* lane: find valid changed; */
0x1 << 5 | /* lane: find nonpcm to pcm */
0x1 << 4 | /* lane: find pcpd changed */
0x1 << 3 | /* lane: find ch status changed */
0x1 << 1 /* lane: find parity error */
);
for (i = 0; i < lane; i++)
int_clr_mask |= (lane_irq_bits << i);
}
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, ~int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, ~int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0xffffffff);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0x0);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0xffffffff);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0x0);
}
void frhdmirx_ctrl(int channels, int src)
{
int lane, lane_mask = 0, i;
/* PAO mode */
if (src) {
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0,
0x1 << 22 | /* capture input by fall edge*/
0x1 << 8 | /* start detect PAPB */
0x1 << 7 | /* add channel num */
0x4 << 4 /* chan status sel: pao pc/pd value */
);
} else {
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
int lane, lane_mask = 0, i;
lane = (channels % 2) ? (channels / 2 + 1) : (channels / 2);
for (i = 0; i < lane; i++)
lane_mask |= (1 << i);
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0,
0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11,
0x1 << 30 | 0xf << 24 | 0x1 << 22 |
0x3 << 11 | 0x1 << 8 | 0x1 << 7 | 0x7 << 0,
0x1 << 30 | /* chnum_sel */
lane_mask << 24 | /* chnum_sel */
0x1 << 22 | /* clk_inv */
0x0 << 11 /* req_sel, Sync 4 spdifin by which */
0x0 << 11 | /* req_sel, Sync 4 spdifin by which */
0x1 << 8 | /* start detect PAPB */
0x1 << 7 | /* add channel num*/
0x6 << 0 /* channel status*/
);
}
/* nonpcm2pcm_th */
@@ -158,6 +134,35 @@ void frhdmirx_clr_PAO_irq_bits(void)
0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK);
}
void frhdmirx_clr_SPDIF_irq_bits(void)
{
unsigned int value = audiobus_read(EE_AUDIO_FRHDMIRX_STAT0);
unsigned int clr_mask = audiobus_read(EE_AUDIO_FRHDMIRX_CTRL4);
unsigned int reg = 0;
int i;
reg = clr_mask | value;
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg);
reg = clr_mask & (~value);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg);
/*compressed audio only transfer through lane0*/
for (i = 0; i < 1; i++) {
/*nonpcm2pcm irq, clear papb/pcpd/nonpcm*/
if (value & (0x20 << 8 * i)) {
audiobus_update_bits(
EE_AUDIO_FRHDMIRX_CTRL3,
0xf << 8 * i, 0xf << 8 * i);
audiobus_update_bits(
EE_AUDIO_FRHDMIRX_CTRL3,
0xf << 8 * i, 0x0 << 8 * i);
pr_info("raw to pcm change: irq status:%x, lane: %d\n",
value, i);
}
}
}
unsigned int frhdmirx_get_ch_status0to31(void)
{
return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0);
@@ -170,3 +175,4 @@ unsigned int frhdmirx_get_chan_status_pc(void)
val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1);
return (val >> 16) & 0xff;
}

View File

@@ -20,10 +20,13 @@
#define INT_PAO_PAPB_MASK 24
#define INT_PAO_PCPD_MASK 16
extern void frhdmirx_enable(bool enable);
extern void frhdmirx_src_select(int src);
extern void frhdmirx_ctrl(int channels, int src);
extern void frhdmirx_clr_PAO_irq_bits(void);
extern unsigned int frhdmirx_get_ch_status0to31(void);
extern unsigned int frhdmirx_get_chan_status_pc(void);
void frhdmirx_enable(bool enable);
void frhdmirx_src_select(int src);
void frhdmirx_ctrl(int channels, int src);
void frhdmirx_clr_PAO_irq_bits(void);
void frhdmirx_clr_SPDIF_irq_bits(void);
unsigned int frhdmirx_get_ch_status0to31(void);
unsigned int frhdmirx_get_chan_status_pc(void);
void frhdmirx_clr_all_irq_bits(void);
#endif

View File

@@ -156,12 +156,6 @@ static int resample_clk_set(struct audioresample *p_resample, int output_sr)
return ret;
}
static void audio_resample_init(struct audioresample *p_resample)
{
aml_set_resample(p_resample->id, p_resample->enable,
p_resample->resample_module);
}
static int audio_resample_set(
struct audioresample *p_resample,
bool enable, int rate)
@@ -171,7 +165,9 @@ static int audio_resample_set(
p_resample->enable = enable;
p_resample->out_rate = rate;
audio_resample_init(p_resample);
aml_set_resample(
p_resample->id, p_resample->enable,
p_resample->resample_module);
return 0;
}

View File

@@ -317,7 +317,7 @@ int resample_set_hw_param(enum resample_idx id,
offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2;
reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id;
audiobus_update_bits(reg, 1 << 25, 1 << 25);
audiobus_update_bits(reg, 3 << 26 | 1 << 25, 3 << 26 | 1 << 25);
resample_set_hw_pause_thd(id, 128);
return 0;