audio: auge: improve compatibility for eARC RX/TX connection [1/1]

PD#SWPL-15189

Problem:
1. earc rx fails to connect to a sony tv
2. earc tx fails to connect to AVR-X4500H

Solution:
1. reset earc_rx pll
2. reduce comma_th

Verify:
ab311

Change-Id: I162b9697d151b682df01093cdc086330a97f8fab
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
This commit is contained in:
Xing Wang
2019-10-23 20:19:16 +08:00
committed by Luke Go
parent f31c0a9a3e
commit 27b3fa2f1b
5 changed files with 62 additions and 43 deletions

View File

@@ -75,8 +75,8 @@ struct earc {
struct extcon_dev *rx_edev;
struct extcon_dev *tx_edev;
bool tx_dmac_clk_on;
bool rx_dmac_clk_on;
bool tx_dmac_clk_on;
};
static struct earc *s_earc;
@@ -183,17 +183,19 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
pr_info("%s EARCRX_CMDC_EARC\n", __func__);
}
if (status0 & INT_EARCRX_CMDC_HB_STATUS)
pr_debug("%s EARCRX_CMDC_HB_STATUS\n", __func__);
/*
* if (status0 & INT_EARCRX_CMDC_HB_STATUS)
* pr_debug("%s EARCRX_CMDC_HB_STATUS\n", __func__);
*/
if (status0 & INT_EARCRX_CMDC_LOSTHB)
pr_debug("%s EARCRX_CMDC_LOSTHB\n", __func__);
if (status0)
earcrx_cdmc_clr_irqs(p_earc->rx_top_map, status0);
if (p_earc->rx_dmac_clk_on) {
unsigned int status1 = earcrx_dmac_get_irqs(p_earc->rx_top_map);
if (status1)
earcrx_dmac_clr_irqs(p_earc->rx_top_map, status1);
if (status1 & INT_ARCRX_BIPHASE_DECODE_C_FIND_PAPB)
pr_debug("%s ARCRX_C_FIND_PAPB\n", __func__);
if (status1 & INT_ARCRX_BIPHASE_DECODE_C_VALID_CHANGE)
@@ -208,9 +210,6 @@ static irqreturn_t earc_rx_isr(int irq, void *data)
pr_debug("%s ARCRX_I_SAMPLE_MODE_CHANGE\n", __func__);
if (status1 & INT_ARCRX_BIPHASE_DECODE_R_PARITY_ERR)
pr_debug("%s ARCRX_R_PARITY_ERR\n", __func__);
if (status1)
earcrx_dmac_clr_irqs(p_earc->rx_top_map, status1);
}
return IRQ_HANDLED;
@@ -221,25 +220,25 @@ static void earctx_update_attend_event(struct earc *p_earc,
{
if (state) {
if (is_earc) {
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_ARC,
false);
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_EARC,
state);
} else {
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_ARC,
state);
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_EARC,
false);
}
} else {
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_ARC,
state);
extcon_set_state_sync(p_earc->rx_edev,
extcon_set_state_sync(p_earc->tx_edev,
EXTCON_EARCTX_ATNDTYP_EARC,
state);
}
@@ -250,6 +249,9 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
struct earc *p_earc = (struct earc *)data;
unsigned int status0 = earctx_cdmc_get_irqs(p_earc->tx_top_map);
if (status0)
earctx_cdmc_clr_irqs(p_earc->tx_top_map, status0);
if (status0 & INT_EARCTX_CMDC_IDLE2) {
earctx_update_attend_event(p_earc,
false, true);
@@ -291,12 +293,12 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
if (status0 & INT_EARCTX_CMDC_RECV_UNEXP)
pr_debug("%s EARCTX_CMDC_RECV_UNEXP\n", __func__);
if (status0)
earctx_cdmc_clr_irqs(p_earc->tx_top_map, status0);
if (p_earc->tx_dmac_clk_on) {
unsigned int status1 = earctx_dmac_get_irqs(p_earc->tx_top_map);
if (status1)
earctx_dmac_clr_irqs(p_earc->tx_top_map, status1);
if (status1 & INT_EARCTX_FEM_C_HOLD_CLR)
pr_debug("%s EARCTX_FEM_C_HOLD_CLR\n", __func__);
if (status1 & INT_EARCTX_FEM_C_HOLD_START)
@@ -309,9 +311,6 @@ static irqreturn_t earc_tx_isr(int irq, void *data)
__func__);
if (status1 & INT_EARCTX_ERRCORR_C_FIFO_EMPTY)
pr_debug("%s EARCTX_ERRCORR_C_FIFO_EMPTY\n", __func__);
if (status1)
earctx_dmac_clr_irqs(p_earc->tx_top_map, status1);
}
return IRQ_HANDLED;
@@ -764,6 +763,8 @@ static int earc_dai_startup(
goto err;
}
}
earcrx_pll_refresh(p_earc->rx_top_map);
}
return 0;
@@ -890,6 +891,9 @@ static int earcrx_arc_set_enable(
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct earc *p_earc = dev_get_drvdata(component->dev);
if (!p_earc)
return 0;
earcrx_cmdc_arc_connect(
p_earc->rx_cmdc_map,
(bool)ucontrol->value.integer.value[0]);
@@ -1197,6 +1201,8 @@ void earc_hdmitx_hpdst(bool st)
/* ensure clock gate */
audiobus_update_bits(EE_AUDIO_CLK_GATE_EN1, 0x1 << 6, 0x1 << 6);
earcrx_cmdc_arc_connect(p_earc->rx_cmdc_map, st);
earcrx_cmdc_hpd_detect(p_earc->rx_cmdc_map, st);
}
@@ -1249,7 +1255,7 @@ static int earctx_extcon_register(struct earc *p_earc)
int ret = 0;
/* earc or arc connect */
p_earc->tx_edev = devm_extcon_dev_allocate(p_earc->dev, earcrx_extcon);
p_earc->tx_edev = devm_extcon_dev_allocate(p_earc->dev, earctx_extcon);
if (IS_ERR(p_earc->tx_edev)) {
pr_err("failed to allocate earc extcon!!!\n");
ret = -ENOMEM;

View File

@@ -20,6 +20,21 @@
#include <linux/amlogic/media/sound/spdif_info.h>
#include "earc_hw.h"
void earcrx_pll_refresh(struct regmap *top_map)
{
/* pll tdc mode */
mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
0x1 << 15, 0x1 << 15);
/* pll self reset */
mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
0x1 << 29, 0x1 << 29);
mmio_update_bits(top_map, EARCRX_PLL_CTRL0,
0x1 << 29, 0x0 << 29);
mmio_update_bits(top_map, EARCRX_PLL_CTRL3,
0x1 << 15, 0x0 << 15);
}
void earcrx_cmdc_init(struct regmap *top_map)
{
/* set irq mask */
@@ -98,8 +113,8 @@ void earcrx_cmdc_hpd_detect(struct regmap *cmdc_map, bool st)
mmio_update_bits(cmdc_map,
EARC_RX_CMDC_VSM_CTRL0,
0x1 << 19 | 0xff << 0,
0x1 << 19 | /* comma_cnt_rst */
0xff << 0
0x0 << 19 | /* comma_cnt_rst */
0xa << 0
);
} else {
/* soft reset */
@@ -216,7 +231,8 @@ void earcrx_arc_init(struct regmap *dmac_map)
0x1 << 30 | /* reg_chnum_sel */
0x1 << 25 | /* reg_findpapb_en */
0x1 << 24 | /* nonpcm2pcm_th enable */
0xFFF << 12 /* reg_nonpcm2pcm_th */
0xFFF << 12 | /* reg_nonpcm2pcm_th */
0x1 << 2 /* reg_check_parity */
);
mmio_write(dmac_map,
EARCRX_SPDIFIN_CTRL2,
@@ -419,17 +435,10 @@ void earctx_cmdc_hpd_detect(struct regmap *top_map,
0x3 << 20 | 0x3 << 22
);
/* no timeout */
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL5,
0x3 << 0,
0x1 << 1
);
mmio_update_bits(cmdc_map,
EARC_TX_CMDC_VSM_CTRL1,
0xff << 0,
0xa << 0 /* comma_cnt_th */
0x4 << 0 /* comma_cnt_th */
);
} else {
/* soft reset */
@@ -524,6 +533,14 @@ void earctx_set_channel_status_info(struct regmap *dmac_map,
((chsts->chstat1_r >> 8) & 0xf) << 24 | chsts->chstat0_r);
}
enum cmdc_st earctx_cmdc_get_state(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);
enum cmdc_st state = (enum cmdc_st)(val & 0x7);
return state;
}
enum attend_type earctx_cmdc_get_attended_type(struct regmap *cmdc_map)
{
int val = mmio_read(cmdc_map, EARC_TX_CMDC_STATUS0);

View File

@@ -151,6 +151,8 @@ void earctx_dmac_set_format(struct regmap *dmac_map,
int frddr_idx, int msb, int frddr_type);
void earctx_set_channel_status_info(struct regmap *dmac_map,
struct iec958_chsts *chsts);
enum cmdc_st earctx_cmdc_get_state(struct regmap *cmdc_map);
enum attend_type earctx_cmdc_get_attended_type(struct regmap *cmdc_map);
void earctx_cdmc_clr_irqs(struct regmap *top_map, int clr);
int earctx_cdmc_get_irqs(struct regmap *top_map);
void earctx_dmac_clr_irqs(struct regmap *top_map, int clr);

View File

@@ -182,10 +182,8 @@ static DEVICE_ATTR(locker_enable, 0644,
void audio_locker_set(int enable)
{
if (!s_locker) {
pr_debug("audio locker is not init\n");
if (!s_locker)
return;
}
s_locker->enable = enable;
audiolocker_init(s_locker);
@@ -193,10 +191,8 @@ void audio_locker_set(int enable)
int audio_locker_get(void)
{
if (!s_locker) {
pr_debug("audio locker is not init\n");
return -1;
}
if (!s_locker)
return 0;
return s_locker->enable;
}

View File

@@ -82,10 +82,8 @@ struct audioresample *get_audioresample(enum resample_idx id)
p_resample = ((id == RESAMPLE_A) ? s_resample_a : s_resample_b);
if (!p_resample) {
pr_debug("Not init audio resample\n");
if (!p_resample)
return NULL;
}
return p_resample;
}