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;
struct earc *p_earc = (struct earc *)data;
unsigned int status0 = earcrx_cdmc_get_irqs(p_earc->rx_top_map);
+ if (status0)
+ earcrx_cdmc_clr_irqs(p_earc->rx_top_map, status0);
+
if (status0 & INT_EARCRX_CMDC_IDLE2) {
earcrx_update_attend_event(p_earc,
false, true);
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 & INT_EARCRX_CMDC_TIMEOUT) {
pr_debug("%s EARCRX_CMDC_TIMEOUT\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)
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;
{
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);
}
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);
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)
__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;
goto err;
}
}
+
+ earcrx_pll_refresh(p_earc->rx_top_map);
}
return 0;
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]);
return 0;
}
+int earctx_get_attend_type(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct earc *p_earc = dev_get_drvdata(component->dev);
+ enum attend_type type;
+
+ if (!p_earc || IS_ERR(p_earc->tx_top_map))
+ return 0;
+
+ type = earctx_cmdc_get_attended_type(p_earc->tx_cmdc_map);
+
+ ucontrol->value.integer.value[0] = type;
+
+ return 0;
+}
+
+int earctx_set_attend_type(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct earc *p_earc = dev_get_drvdata(component->dev);
+ enum cmdc_st state;
+
+ if (!p_earc || IS_ERR(p_earc->tx_top_map))
+ return 0;
+
+ state = earctx_cmdc_get_state(p_earc->tx_cmdc_map);
+
+ if (state != CMDC_ST_IDLE2)
+ return 0;
+
+ /* only support set cmdc from idle to ARC */
+
+ return 0;
+}
+
static const struct snd_kcontrol_new earc_controls[] = {
SOC_ENUM_EXT("eARC_RX attended type",
attended_type_enum,
0,
earcrx_arc_get_enable,
earcrx_arc_set_enable),
+
+ SOC_ENUM_EXT("eARC_TX attended type",
+ attended_type_enum,
+ earctx_get_attend_type,
+ earctx_set_attend_type),
};
static const struct snd_soc_component_driver earc_component = {
/* 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);
}
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;
#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 */
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 */
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,
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 */
((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);