asoc: codecs: bolero: Fix L/R swap issue on bolero RX
Left and right channel content can get swapped in new cdc_dma interface. DMA interfaces underrun results in Channels being swapped. This issue is a side effect current SW setup for RX path: 1. HLOS Setup WCD Analog Path, Bolero CODEC. CODEC would drive Fs to LPASS DMAs requesting for PCM samples. 2. DSP setup RX Buffers in Memory : 3. DSP Configures RD DMAs and DMA RXTX CODEC interface (Enable CODEC DMA interface buffer and Enable DMA LPASS_RXTX_LPAIF_RDDMA_CTL0.ENABLE and LPASS_RXTX_LPAIF_RDDMA_CODEC_INTF0.ENABLE If CODEC Fs, aligns with DMA interface being enabled there is an underrun as DMA interface pingpong buffer is empty. This results in channels being swapped. Proposed work around while keeping current SW setup order. Provide a workaround to Keep Fs disabled until DMAs and CODEC DMA interface are enabled and HW could prefetch all buffers. SW would keep existing setup order: 1. HLOS Setup WCD Analog Path, Bolero CODEC. CODEC would drive Fs to LPASS DMAs requesting for PCM samples. 2. DSP setup RX Buffers in Memory : 3. DSP Configures DMAs and DMA CODEC interface (Enable CODEC DMA interface buffer and Enable DMA LPASS_RXTX_LPAIF_RDDMA_CTL0.ENABLE and LPASS_RXTX_LPAIF_RDDMA_CODEC_INTF0.ENABLE) 4. Enable Fs Set #LPASS_RX_CDC_RX0_RX_PATH_CTL. CLK_EN to ONE Change-Id: I7916667f5d857464cc7d77b51da307ab234cc7bb Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
@@ -88,6 +88,16 @@ enum {
|
||||
WSA_MACRO_SOFTCLIP_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
INTn_1_INP_SEL_ZERO = 0,
|
||||
INTn_1_INP_SEL_RX0,
|
||||
INTn_1_INP_SEL_RX1,
|
||||
INTn_1_INP_SEL_RX2,
|
||||
INTn_1_INP_SEL_RX3,
|
||||
INTn_1_INP_SEL_DEC0,
|
||||
INTn_1_INP_SEL_DEC1,
|
||||
};
|
||||
|
||||
struct interp_sample_rate {
|
||||
int sample_rate;
|
||||
int rate_val;
|
||||
@@ -129,6 +139,7 @@ static int wsa_macro_hw_params(struct snd_pcm_substream *substream,
|
||||
static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
|
||||
unsigned int *tx_num, unsigned int *tx_slot,
|
||||
unsigned int *rx_num, unsigned int *rx_slot);
|
||||
static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute);
|
||||
/* Hold instance to soundwire platform device */
|
||||
struct wsa_macro_swr_ctrl_data {
|
||||
struct platform_device *wsa_swr_pdev;
|
||||
@@ -358,6 +369,7 @@ static const struct snd_kcontrol_new rx_mix_ec1_mux =
|
||||
static struct snd_soc_dai_ops wsa_macro_dai_ops = {
|
||||
.hw_params = wsa_macro_hw_params,
|
||||
.get_channel_map = wsa_macro_get_channel_map,
|
||||
.digital_mute = wsa_macro_digital_mute,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver wsa_macro_dai[] = {
|
||||
@@ -794,6 +806,53 @@ static int wsa_macro_get_channel_map(struct snd_soc_dai *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct device *wsa_dev = NULL;
|
||||
struct wsa_macro_priv *wsa_priv = NULL;
|
||||
uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0;
|
||||
u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
|
||||
u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
|
||||
|
||||
if (mute)
|
||||
return 0;
|
||||
|
||||
if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
switch (dai->id) {
|
||||
case WSA_MACRO_AIF1_PB:
|
||||
case WSA_MACRO_AIF_MIX1_PB:
|
||||
for (j = 0; j < NUM_INTERPOLATORS; j++) {
|
||||
reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
|
||||
(j * WSA_MACRO_RX_PATH_OFFSET);
|
||||
mix_reg = BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL +
|
||||
(j * WSA_MACRO_RX_PATH_OFFSET);
|
||||
dsm_reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
|
||||
(j * WSA_MACRO_RX_PATH_OFFSET) +
|
||||
WSA_MACRO_RX_PATH_DSMDEM_OFFSET;
|
||||
int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
|
||||
int_mux_cfg1 = int_mux_cfg0 + 4;
|
||||
int_mux_cfg0_val = snd_soc_component_read32(component,
|
||||
int_mux_cfg0);
|
||||
int_mux_cfg1_val = snd_soc_component_read32(component,
|
||||
int_mux_cfg1);
|
||||
if (snd_soc_component_read32(component, dsm_reg) & 0x01) {
|
||||
if (int_mux_cfg0_val || (int_mux_cfg1_val & 0x38))
|
||||
snd_soc_component_update_bits(component, reg,
|
||||
0x20, 0x20);
|
||||
if (int_mux_cfg1_val & 0x07)
|
||||
snd_soc_component_update_bits(component,
|
||||
mix_reg, 0x20, 0x20);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv,
|
||||
bool mclk_enable, bool dapm)
|
||||
{
|
||||
@@ -1102,6 +1161,8 @@ static int wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
|
||||
snd_soc_component_write(component, gain_reg, val);
|
||||
break;
|
||||
case SND_SOC_DAPM_POST_PMD:
|
||||
snd_soc_component_update_bits(component,
|
||||
w->reg, 0x20, 0x00);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1323,6 +1384,58 @@ static int wsa_macro_config_softclip(struct snd_soc_component *component,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool wsa_macro_adie_lb(struct snd_soc_component *component,
|
||||
int interp_idx)
|
||||
{
|
||||
u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
|
||||
u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
|
||||
u8 int_n_inp0 = 0, int_n_inp1 = 0, int_n_inp2 = 0;
|
||||
|
||||
int_mux_cfg0 = BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 + interp_idx * 8;
|
||||
int_mux_cfg1 = int_mux_cfg0 + 4;
|
||||
int_mux_cfg0_val = snd_soc_component_read32(component, int_mux_cfg0);
|
||||
int_mux_cfg1_val = snd_soc_component_read32(component, int_mux_cfg1);
|
||||
|
||||
int_n_inp0 = int_mux_cfg0_val & 0x0F;
|
||||
if (int_n_inp0 == INTn_1_INP_SEL_DEC0 ||
|
||||
int_n_inp0 == INTn_1_INP_SEL_DEC1)
|
||||
return true;
|
||||
|
||||
int_n_inp1 = int_mux_cfg0_val >> 4;
|
||||
if (int_n_inp1 == INTn_1_INP_SEL_DEC0 ||
|
||||
int_n_inp1 == INTn_1_INP_SEL_DEC1)
|
||||
return true;
|
||||
|
||||
int_n_inp2 = int_mux_cfg1_val >> 4;
|
||||
if (int_n_inp2 == INTn_1_INP_SEL_DEC0 ||
|
||||
int_n_inp2 == INTn_1_INP_SEL_DEC1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol,
|
||||
int event)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_dapm_to_component(w->dapm);
|
||||
u16 reg = 0;
|
||||
|
||||
reg = BOLERO_CDC_WSA_RX0_RX_PATH_CTL +
|
||||
WSA_MACRO_RX_PATH_OFFSET * w->shift;
|
||||
switch (event) {
|
||||
case SND_SOC_DAPM_PRE_PMU:
|
||||
if (wsa_macro_adie_lb(component, w->shift))
|
||||
snd_soc_component_update_bits(component,
|
||||
reg, 0x20, 0x20);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wsa_macro_interp_get_primary_reg(u16 reg, u16 *ind)
|
||||
{
|
||||
u16 prim_int_reg = 0;
|
||||
@@ -1370,8 +1483,6 @@ static int wsa_macro_enable_prim_interpolator(
|
||||
snd_soc_component_update_bits(component,
|
||||
prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
|
||||
0x1, 0x1);
|
||||
snd_soc_component_update_bits(component, prim_int_reg,
|
||||
1 << 0x5, 1 << 0x5);
|
||||
}
|
||||
if ((reg != prim_int_reg) &&
|
||||
((snd_soc_component_read32(
|
||||
@@ -1384,6 +1495,9 @@ static int wsa_macro_enable_prim_interpolator(
|
||||
if (wsa_priv->prim_int_users[ind] == 0) {
|
||||
snd_soc_component_update_bits(component, prim_int_reg,
|
||||
1 << 0x5, 0 << 0x5);
|
||||
snd_soc_component_update_bits(component,
|
||||
prim_int_reg + WSA_MACRO_RX_PATH_DSMDEM_OFFSET,
|
||||
0x1, 0x0);
|
||||
snd_soc_component_update_bits(component, prim_int_reg,
|
||||
0x40, 0x40);
|
||||
snd_soc_component_update_bits(component, prim_int_reg,
|
||||
@@ -2382,8 +2496,8 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0,
|
||||
&rx0_prim_inp2_mux, wsa_macro_enable_swr,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, 0, 0,
|
||||
&rx0_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", BOLERO_CDC_WSA_RX0_RX_PATH_MIX_CTL,
|
||||
0, 0, &rx0_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0,
|
||||
&rx1_prim_inp0_mux, wsa_macro_enable_swr,
|
||||
@@ -2394,11 +2508,15 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0,
|
||||
&rx1_prim_inp2_mux, wsa_macro_enable_swr,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, 0, 0,
|
||||
&rx1_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", BOLERO_CDC_WSA_RX1_RX_PATH_MIX_CTL,
|
||||
0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MIXER("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("WSA_RX INT1 MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
|
||||
0, 0, NULL, 0, wsa_macro_enable_main_path,
|
||||
SND_SOC_DAPM_PRE_PMU),
|
||||
SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
|
||||
1, 0, NULL, 0, wsa_macro_enable_main_path,
|
||||
SND_SOC_DAPM_PRE_PMU),
|
||||
SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
|
Reference in New Issue
Block a user