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:
Laxminath Kasam
2019-08-08 18:00:35 +05:30
parent 47673f2f83
commit 52ae6581d7
2 changed files with 227 additions and 27 deletions

View File

@@ -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),