Message ID | 20240612-lpass-codec-v25-v1-3-9f40611a1370@linaro.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | ASoC: codecs: lpass: add support for v2.5 rx macro | expand |
On Wed, Jun 12, 2024 at 05:57:23PM +0100, Srinivas Kandagatla wrote: > LPASS Codec v2.5 has significant changes in the rx register strides. > Due to this headset playback on SM8550, SM8650, x1e80100 and all SoCs > after SM8450 have only Left working. > > This patch adjusts the registers to accomdate 2.5 changes. With this > fixed now L and R are functional on Headset playback. > > Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> > --- > sound/soc/codecs/lpass-rx-macro.c | 220 +++++++++++++++++++++++++++++++++++--- > 1 file changed, 207 insertions(+), 13 deletions(-) > > diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c > index 8beeacbd6ae6..7e8bb005b0b9 100644 > --- a/sound/soc/codecs/lpass-rx-macro.c > +++ b/sound/soc/codecs/lpass-rx-macro.c > @@ -262,6 +262,53 @@ > #define CDC_RX_RX2_RX_PATH_MIX_SEC0 (0x0544) > #define CDC_RX_RX2_RX_PATH_MIX_SEC1 (0x0548) > #define CDC_RX_RX2_RX_PATH_DSM_CTL (0x054C) > + > +/* LPASS CODEC version 2.5 rx reg offsets */ > +#define CDC_2_5_RX_RX1_RX_PATH_CTL (0x04c0) > +#define CDC_2_5_RX_RX1_RX_PATH_CFG0 (0x04c4) > +#define CDC_2_5_RX_RX1_RX_PATH_CFG1 (0x04c8) > +#define CDC_2_5_RX_RX1_RX_PATH_CFG2 (0x04cC) > +#define CDC_2_5_RX_RX1_RX_PATH_CFG3 (0x04d0) > +#define CDC_2_5_RX_RX1_RX_VOL_CTL (0x04d4) > +#define CDC_2_5_RX_RX1_RX_PATH_MIX_CTL (0x04d8) > +#define CDC_2_5_RX_RX1_RX_PATH_MIX_CFG (0x04dC) > +#define CDC_2_5_RX_RX1_RX_VOL_MIX_CTL (0x04e0) > +#define CDC_2_5_RX_RX1_RX_PATH_SEC1 (0x04e4) > +#define CDC_2_5_RX_RX1_RX_PATH_SEC2 (0x04e8) > +#define CDC_2_5_RX_RX1_RX_PATH_SEC3 (0x04eC) > +#define CDC_2_5_RX_RX1_RX_PATH_SEC4 (0x04f0) > +#define CDC_2_5_RX_RX1_RX_PATH_SEC7 (0x04f4) > +#define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0 (0x04f8) > +#define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1 (0x04fC) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_CTL (0x0500) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1 (0x0504) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2 (0x0508) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3 (0x050C) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4 (0x0510) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5 (0x0514) > +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6 (0x0518) > + > +#define CDC_2_5_RX_RX2_RX_PATH_CTL (0x0580) > +#define CDC_2_5_RX_RX2_RX_PATH_CFG0 (0x0584) > +#define CDC_2_5_RX_RX2_RX_PATH_CFG1 (0x0588) > +#define CDC_2_5_RX_RX2_RX_PATH_CFG2 (0x058C) > +#define CDC_2_5_RX_RX2_RX_PATH_CFG3 (0x0590) > +#define CDC_2_5_RX_RX2_RX_VOL_CTL (0x0594) > +#define CDC_2_5_RX_RX2_RX_PATH_MIX_CTL (0x0598) > +#define CDC_2_5_RX_RX2_RX_PATH_MIX_CFG (0x059C) > +#define CDC_2_5_RX_RX2_RX_VOL_MIX_CTL (0x05a0) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC0 (0x05a4) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC1 (0x05a8) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC2 (0x05aC) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC3 (0x05b0) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC4 (0x05b4) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC5 (0x05b8) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC6 (0x05bC) > +#define CDC_2_5_RX_RX2_RX_PATH_SEC7 (0x05c0) > +#define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0 (0x05c4) > +#define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1 (0x05c8) > +#define CDC_2_5_RX_RX2_RX_PATH_DSM_CTL (0x05cC) > + > #define CDC_RX_IDLE_DETECT_PATH_CTL (0x0780) > #define CDC_RX_IDLE_DETECT_CFG0 (0x0784) > #define CDC_RX_IDLE_DETECT_CFG1 (0x0788) > @@ -764,6 +811,8 @@ static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0, > rx_int_dem_inp_mux_text); > static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0, > rx_int_dem_inp_mux_text); > +static SOC_ENUM_SINGLE_DECL(rx_2_5_int1_dem_inp_enum, CDC_2_5_RX_RX1_RX_PATH_CFG1, 0, > + rx_int_dem_inp_mux_text); > > static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); > static SOC_ENUM_SINGLE_DECL(rx_macro_rx1_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); > @@ -1083,6 +1132,52 @@ static const struct reg_default rx_defaults[] = { > { CDC_RX_DSD1_CFG2, 0x96 }, > }; > > +static const struct reg_default rx_2_5_defaults[] = { > + { CDC_2_5_RX_RX1_RX_PATH_CTL, 0x04 }, > + { CDC_2_5_RX_RX1_RX_PATH_CFG0, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_CFG1, 0x64 }, > + { CDC_2_5_RX_RX1_RX_PATH_CFG2, 0x8F }, > + { CDC_2_5_RX_RX1_RX_PATH_CFG3, 0x00 }, > + { CDC_2_5_RX_RX1_RX_VOL_CTL, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, > + { CDC_2_5_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, > + { CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_SEC1, 0x08 }, > + { CDC_2_5_RX_RX1_RX_PATH_SEC2, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_SEC3, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_SEC4, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_SEC7, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, > + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, > + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, > + { CDC_2_5_RX_RX2_RX_PATH_CTL, 0x04 }, > + { CDC_2_5_RX_RX2_RX_PATH_CFG0, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_CFG1, 0x64 }, > + { CDC_2_5_RX_RX2_RX_PATH_CFG2, 0x8F }, > + { CDC_2_5_RX_RX2_RX_PATH_CFG3, 0x00 }, > + { CDC_2_5_RX_RX2_RX_VOL_CTL, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, > + { CDC_2_5_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, > + { CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC0, 0x04 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC1, 0x08 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC2, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC3, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC4, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC5, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC6, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_SEC7, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, > + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, > + { CDC_2_5_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, > +}; > + > static const struct reg_default rx_pre_2_5_defaults[] = { > { CDC_RX_RX1_RX_PATH_CTL, 0x04 }, > { CDC_RX_RX1_RX_PATH_CFG0, 0x00 }, > @@ -1236,8 +1331,62 @@ static bool rx_pre_2_5_is_rw_register(struct device *dev, unsigned int reg) > return false; > } > > +static bool rx_2_5_is_rw_register(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case CDC_2_5_RX_RX1_RX_PATH_CTL: > + case CDC_2_5_RX_RX1_RX_PATH_CFG0: > + case CDC_2_5_RX_RX1_RX_PATH_CFG1: > + case CDC_2_5_RX_RX1_RX_PATH_CFG2: > + case CDC_2_5_RX_RX1_RX_PATH_CFG3: > + case CDC_2_5_RX_RX1_RX_VOL_CTL: > + case CDC_2_5_RX_RX1_RX_PATH_MIX_CTL: > + case CDC_2_5_RX_RX1_RX_PATH_MIX_CFG: > + case CDC_2_5_RX_RX1_RX_VOL_MIX_CTL: > + case CDC_2_5_RX_RX1_RX_PATH_SEC1: > + case CDC_2_5_RX_RX1_RX_PATH_SEC2: > + case CDC_2_5_RX_RX1_RX_PATH_SEC3: > + case CDC_2_5_RX_RX1_RX_PATH_SEC4: > + case CDC_2_5_RX_RX1_RX_PATH_SEC7: > + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0: > + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_CTL: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5: > + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6: > + case CDC_2_5_RX_RX2_RX_PATH_CTL: > + case CDC_2_5_RX_RX2_RX_PATH_CFG0: > + case CDC_2_5_RX_RX2_RX_PATH_CFG1: > + case CDC_2_5_RX_RX2_RX_PATH_CFG2: > + case CDC_2_5_RX_RX2_RX_PATH_CFG3: > + case CDC_2_5_RX_RX2_RX_VOL_CTL: > + case CDC_2_5_RX_RX2_RX_PATH_MIX_CTL: > + case CDC_2_5_RX_RX2_RX_PATH_MIX_CFG: > + case CDC_2_5_RX_RX2_RX_VOL_MIX_CTL: > + case CDC_2_5_RX_RX2_RX_PATH_SEC0: > + case CDC_2_5_RX_RX2_RX_PATH_SEC1: > + case CDC_2_5_RX_RX2_RX_PATH_SEC2: > + case CDC_2_5_RX_RX2_RX_PATH_SEC3: > + case CDC_2_5_RX_RX2_RX_PATH_SEC4: > + case CDC_2_5_RX_RX2_RX_PATH_SEC5: > + case CDC_2_5_RX_RX2_RX_PATH_SEC6: > + case CDC_2_5_RX_RX2_RX_PATH_SEC7: > + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0: > + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1: > + case CDC_2_5_RX_RX2_RX_PATH_DSM_CTL: > + return true; > + } > + > + return false; > +} > + > static bool rx_is_rw_register(struct device *dev, unsigned int reg) > { > + struct rx_macro *rx = dev_get_drvdata(dev); > + > switch (reg) { > case CDC_RX_TOP_TOP_CFG0: > case CDC_RX_TOP_SWR_CTRL: > @@ -1453,6 +1602,9 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) > return true; > } > > + if (rx->codec_version >= LPASS_CODEC_VERSION_2_5) > + return rx_2_5_is_rw_register(dev, reg); > + > return rx_pre_2_5_is_rw_register(dev, reg); > } > > @@ -1551,6 +1703,10 @@ static const struct snd_kcontrol_new rx_int1_dem_inp_mux = > SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum, > snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); > > +static const struct snd_kcontrol_new rx_2_5_int1_dem_inp_mux = > + SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_2_5_int1_dem_inp_enum, > + snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); > + > static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, > int rate_reg_val, u32 sample_rate) > { > @@ -2835,6 +2991,18 @@ static const struct snd_kcontrol_new rx_macro_def_snd_controls[] = { > -84, 40, digital_gain), > }; > > +static const struct snd_kcontrol_new rx_macro_2_5_snd_controls[] = { > + > + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_2_5_RX_RX1_RX_VOL_CTL, > + -84, 40, digital_gain), > + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_2_5_RX_RX2_RX_VOL_CTL, > + -84, 40, digital_gain), > + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, > + -84, 40, digital_gain), > + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, > + -84, 40, digital_gain), > +}; > + > static const struct snd_kcontrol_new rx_macro_snd_controls[] = { > SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, > -84, 40, digital_gain), > @@ -2956,6 +3124,12 @@ static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w, > > return 0; > } > + > +static const struct snd_soc_dapm_widget rx_macro_2_5_dapm_widgets[] = { > + SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, > + &rx_2_5_int1_dem_inp_mux), > +}; > + > static const struct snd_soc_dapm_widget rx_macro_def_dapm_widgets[] = { > SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, > &rx_int1_dem_inp_mux), > @@ -3454,10 +3628,17 @@ static int rx_macro_component_probe(struct snd_soc_component *component) > CDC_RX_DC_COEFF_SEL_MASK, > CDC_RX_DC_COEFF_SEL_TWO); > > - controls = rx_macro_def_snd_controls; > - num_controls = ARRAY_SIZE(rx_macro_def_snd_controls); > - widgets = rx_macro_def_dapm_widgets; > - num_widgets = ARRAY_SIZE(rx_macro_def_dapm_widgets); > + if (rx->codec_version >= LPASS_CODEC_VERSION_2_5) { > + controls = rx_macro_2_5_snd_controls; > + num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); > + widgets = rx_macro_2_5_dapm_widgets; > + num_widgets = ARRAY_SIZE(rx_macro_2_5_dapm_widgets); > + } else { > + controls = rx_macro_def_snd_controls; > + num_controls = ARRAY_SIZE(rx_macro_def_snd_controls); > + widgets = rx_macro_def_dapm_widgets; > + num_widgets = ARRAY_SIZE(rx_macro_def_dapm_widgets); > + } > > rx->component = component; > > @@ -3609,15 +3790,28 @@ static int rx_macro_probe(struct platform_device *pdev) > goto err; > } > rx->codec_version = lpass_macro_get_codec_version(); > - > - rx->rxn_reg_stride = 0x80; > - def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults); > - reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); > - if (!reg_defaults) > - return -ENOMEM; > - memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); > - memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], > - rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); > + switch (rx->codec_version) { > + case LPASS_CODEC_VERSION_2_5 ... LPASS_CODEC_VERSION_2_8: I don't like that the next 2.9 version will end up in a default bucket. It might be better to have an explicit list of versions instead and then return -EINVAL in the default case. > + rx->rxn_reg_stride = 0xc0; > + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); > + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); > + if (!reg_defaults) > + return -ENOMEM; > + memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); > + memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], > + rx_2_5_defaults, sizeof(rx_2_5_defaults)); > + break; > + default: > + rx->rxn_reg_stride = 0x80; > + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults); > + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); > + if (!reg_defaults) > + return -ENOMEM; > + memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); > + memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], > + rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); > + break; > + } > > rx_regmap_config.reg_defaults = reg_defaults; > rx_regmap_config.num_reg_defaults = def_count; > > -- > 2.25.1 >
On 12/06/2024 19:18, Dmitry Baryshkov wrote: >> - memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); >> - memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], >> - rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); >> + switch (rx->codec_version) { >> + case LPASS_CODEC_VERSION_2_5 ... LPASS_CODEC_VERSION_2_8: > I don't like that the next 2.9 version will end up in a default bucket. > It might be better to have an explicit list of versions instead and then > return -EINVAL in the default case. makes sense --srini
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 8beeacbd6ae6..7e8bb005b0b9 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -262,6 +262,53 @@ #define CDC_RX_RX2_RX_PATH_MIX_SEC0 (0x0544) #define CDC_RX_RX2_RX_PATH_MIX_SEC1 (0x0548) #define CDC_RX_RX2_RX_PATH_DSM_CTL (0x054C) + +/* LPASS CODEC version 2.5 rx reg offsets */ +#define CDC_2_5_RX_RX1_RX_PATH_CTL (0x04c0) +#define CDC_2_5_RX_RX1_RX_PATH_CFG0 (0x04c4) +#define CDC_2_5_RX_RX1_RX_PATH_CFG1 (0x04c8) +#define CDC_2_5_RX_RX1_RX_PATH_CFG2 (0x04cC) +#define CDC_2_5_RX_RX1_RX_PATH_CFG3 (0x04d0) +#define CDC_2_5_RX_RX1_RX_VOL_CTL (0x04d4) +#define CDC_2_5_RX_RX1_RX_PATH_MIX_CTL (0x04d8) +#define CDC_2_5_RX_RX1_RX_PATH_MIX_CFG (0x04dC) +#define CDC_2_5_RX_RX1_RX_VOL_MIX_CTL (0x04e0) +#define CDC_2_5_RX_RX1_RX_PATH_SEC1 (0x04e4) +#define CDC_2_5_RX_RX1_RX_PATH_SEC2 (0x04e8) +#define CDC_2_5_RX_RX1_RX_PATH_SEC3 (0x04eC) +#define CDC_2_5_RX_RX1_RX_PATH_SEC4 (0x04f0) +#define CDC_2_5_RX_RX1_RX_PATH_SEC7 (0x04f4) +#define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0 (0x04f8) +#define CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1 (0x04fC) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_CTL (0x0500) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1 (0x0504) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2 (0x0508) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3 (0x050C) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4 (0x0510) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5 (0x0514) +#define CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6 (0x0518) + +#define CDC_2_5_RX_RX2_RX_PATH_CTL (0x0580) +#define CDC_2_5_RX_RX2_RX_PATH_CFG0 (0x0584) +#define CDC_2_5_RX_RX2_RX_PATH_CFG1 (0x0588) +#define CDC_2_5_RX_RX2_RX_PATH_CFG2 (0x058C) +#define CDC_2_5_RX_RX2_RX_PATH_CFG3 (0x0590) +#define CDC_2_5_RX_RX2_RX_VOL_CTL (0x0594) +#define CDC_2_5_RX_RX2_RX_PATH_MIX_CTL (0x0598) +#define CDC_2_5_RX_RX2_RX_PATH_MIX_CFG (0x059C) +#define CDC_2_5_RX_RX2_RX_VOL_MIX_CTL (0x05a0) +#define CDC_2_5_RX_RX2_RX_PATH_SEC0 (0x05a4) +#define CDC_2_5_RX_RX2_RX_PATH_SEC1 (0x05a8) +#define CDC_2_5_RX_RX2_RX_PATH_SEC2 (0x05aC) +#define CDC_2_5_RX_RX2_RX_PATH_SEC3 (0x05b0) +#define CDC_2_5_RX_RX2_RX_PATH_SEC4 (0x05b4) +#define CDC_2_5_RX_RX2_RX_PATH_SEC5 (0x05b8) +#define CDC_2_5_RX_RX2_RX_PATH_SEC6 (0x05bC) +#define CDC_2_5_RX_RX2_RX_PATH_SEC7 (0x05c0) +#define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0 (0x05c4) +#define CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1 (0x05c8) +#define CDC_2_5_RX_RX2_RX_PATH_DSM_CTL (0x05cC) + #define CDC_RX_IDLE_DETECT_PATH_CTL (0x0780) #define CDC_RX_IDLE_DETECT_CFG0 (0x0784) #define CDC_RX_IDLE_DETECT_CFG1 (0x0788) @@ -764,6 +811,8 @@ static SOC_ENUM_SINGLE_DECL(rx_int0_dem_inp_enum, CDC_RX_RX0_RX_PATH_CFG1, 0, rx_int_dem_inp_mux_text); static SOC_ENUM_SINGLE_DECL(rx_int1_dem_inp_enum, CDC_RX_RX1_RX_PATH_CFG1, 0, rx_int_dem_inp_mux_text); +static SOC_ENUM_SINGLE_DECL(rx_2_5_int1_dem_inp_enum, CDC_2_5_RX_RX1_RX_PATH_CFG1, 0, + rx_int_dem_inp_mux_text); static SOC_ENUM_SINGLE_DECL(rx_macro_rx0_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); static SOC_ENUM_SINGLE_DECL(rx_macro_rx1_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); @@ -1083,6 +1132,52 @@ static const struct reg_default rx_defaults[] = { { CDC_RX_DSD1_CFG2, 0x96 }, }; +static const struct reg_default rx_2_5_defaults[] = { + { CDC_2_5_RX_RX1_RX_PATH_CTL, 0x04 }, + { CDC_2_5_RX_RX1_RX_PATH_CFG0, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_CFG1, 0x64 }, + { CDC_2_5_RX_RX1_RX_PATH_CFG2, 0x8F }, + { CDC_2_5_RX_RX1_RX_PATH_CFG3, 0x00 }, + { CDC_2_5_RX_RX1_RX_VOL_CTL, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_MIX_CTL, 0x04 }, + { CDC_2_5_RX_RX1_RX_PATH_MIX_CFG, 0x7E }, + { CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_SEC1, 0x08 }, + { CDC_2_5_RX_RX1_RX_PATH_SEC2, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_SEC3, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_SEC4, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_SEC7, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0, 0x08 }, + { CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_CTL, 0x08 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3, 0x00 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4, 0x55 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5, 0x55 }, + { CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6, 0x55 }, + { CDC_2_5_RX_RX2_RX_PATH_CTL, 0x04 }, + { CDC_2_5_RX_RX2_RX_PATH_CFG0, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_CFG1, 0x64 }, + { CDC_2_5_RX_RX2_RX_PATH_CFG2, 0x8F }, + { CDC_2_5_RX_RX2_RX_PATH_CFG3, 0x00 }, + { CDC_2_5_RX_RX2_RX_VOL_CTL, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_MIX_CTL, 0x04 }, + { CDC_2_5_RX_RX2_RX_PATH_MIX_CFG, 0x7E }, + { CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC0, 0x04 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC1, 0x08 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC2, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC3, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC4, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC5, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC6, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_SEC7, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0, 0x08 }, + { CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1, 0x00 }, + { CDC_2_5_RX_RX2_RX_PATH_DSM_CTL, 0x00 }, +}; + static const struct reg_default rx_pre_2_5_defaults[] = { { CDC_RX_RX1_RX_PATH_CTL, 0x04 }, { CDC_RX_RX1_RX_PATH_CFG0, 0x00 }, @@ -1236,8 +1331,62 @@ static bool rx_pre_2_5_is_rw_register(struct device *dev, unsigned int reg) return false; } +static bool rx_2_5_is_rw_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_2_5_RX_RX1_RX_PATH_CTL: + case CDC_2_5_RX_RX1_RX_PATH_CFG0: + case CDC_2_5_RX_RX1_RX_PATH_CFG1: + case CDC_2_5_RX_RX1_RX_PATH_CFG2: + case CDC_2_5_RX_RX1_RX_PATH_CFG3: + case CDC_2_5_RX_RX1_RX_VOL_CTL: + case CDC_2_5_RX_RX1_RX_PATH_MIX_CTL: + case CDC_2_5_RX_RX1_RX_PATH_MIX_CFG: + case CDC_2_5_RX_RX1_RX_VOL_MIX_CTL: + case CDC_2_5_RX_RX1_RX_PATH_SEC1: + case CDC_2_5_RX_RX1_RX_PATH_SEC2: + case CDC_2_5_RX_RX1_RX_PATH_SEC3: + case CDC_2_5_RX_RX1_RX_PATH_SEC4: + case CDC_2_5_RX_RX1_RX_PATH_SEC7: + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC0: + case CDC_2_5_RX_RX1_RX_PATH_MIX_SEC1: + case CDC_2_5_RX_RX1_RX_PATH_DSM_CTL: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA1: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA2: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA3: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA4: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA5: + case CDC_2_5_RX_RX1_RX_PATH_DSM_DATA6: + case CDC_2_5_RX_RX2_RX_PATH_CTL: + case CDC_2_5_RX_RX2_RX_PATH_CFG0: + case CDC_2_5_RX_RX2_RX_PATH_CFG1: + case CDC_2_5_RX_RX2_RX_PATH_CFG2: + case CDC_2_5_RX_RX2_RX_PATH_CFG3: + case CDC_2_5_RX_RX2_RX_VOL_CTL: + case CDC_2_5_RX_RX2_RX_PATH_MIX_CTL: + case CDC_2_5_RX_RX2_RX_PATH_MIX_CFG: + case CDC_2_5_RX_RX2_RX_VOL_MIX_CTL: + case CDC_2_5_RX_RX2_RX_PATH_SEC0: + case CDC_2_5_RX_RX2_RX_PATH_SEC1: + case CDC_2_5_RX_RX2_RX_PATH_SEC2: + case CDC_2_5_RX_RX2_RX_PATH_SEC3: + case CDC_2_5_RX_RX2_RX_PATH_SEC4: + case CDC_2_5_RX_RX2_RX_PATH_SEC5: + case CDC_2_5_RX_RX2_RX_PATH_SEC6: + case CDC_2_5_RX_RX2_RX_PATH_SEC7: + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC0: + case CDC_2_5_RX_RX2_RX_PATH_MIX_SEC1: + case CDC_2_5_RX_RX2_RX_PATH_DSM_CTL: + return true; + } + + return false; +} + static bool rx_is_rw_register(struct device *dev, unsigned int reg) { + struct rx_macro *rx = dev_get_drvdata(dev); + switch (reg) { case CDC_RX_TOP_TOP_CFG0: case CDC_RX_TOP_SWR_CTRL: @@ -1453,6 +1602,9 @@ static bool rx_is_rw_register(struct device *dev, unsigned int reg) return true; } + if (rx->codec_version >= LPASS_CODEC_VERSION_2_5) + return rx_2_5_is_rw_register(dev, reg); + return rx_pre_2_5_is_rw_register(dev, reg); } @@ -1551,6 +1703,10 @@ static const struct snd_kcontrol_new rx_int1_dem_inp_mux = SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_int1_dem_inp_enum, snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); +static const struct snd_kcontrol_new rx_2_5_int1_dem_inp_mux = + SOC_DAPM_ENUM_EXT("rx_int1_dem_inp", rx_2_5_int1_dem_inp_enum, + snd_soc_dapm_get_enum_double, rx_macro_int_dem_inp_mux_put); + static int rx_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, int rate_reg_val, u32 sample_rate) { @@ -2835,6 +2991,18 @@ static const struct snd_kcontrol_new rx_macro_def_snd_controls[] = { -84, 40, digital_gain), }; +static const struct snd_kcontrol_new rx_macro_2_5_snd_controls[] = { + + SOC_SINGLE_S8_TLV("RX_RX1 Digital Volume", CDC_2_5_RX_RX1_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Digital Volume", CDC_2_5_RX_RX2_RX_VOL_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX1 Mix Digital Volume", CDC_2_5_RX_RX1_RX_VOL_MIX_CTL, + -84, 40, digital_gain), + SOC_SINGLE_S8_TLV("RX_RX2 Mix Digital Volume", CDC_2_5_RX_RX2_RX_VOL_MIX_CTL, + -84, 40, digital_gain), +}; + static const struct snd_kcontrol_new rx_macro_snd_controls[] = { SOC_SINGLE_S8_TLV("RX_RX0 Digital Volume", CDC_RX_RX0_RX_VOL_CTL, -84, 40, digital_gain), @@ -2956,6 +3124,12 @@ static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w, return 0; } + +static const struct snd_soc_dapm_widget rx_macro_2_5_dapm_widgets[] = { + SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, + &rx_2_5_int1_dem_inp_mux), +}; + static const struct snd_soc_dapm_widget rx_macro_def_dapm_widgets[] = { SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0, &rx_int1_dem_inp_mux), @@ -3454,10 +3628,17 @@ static int rx_macro_component_probe(struct snd_soc_component *component) CDC_RX_DC_COEFF_SEL_MASK, CDC_RX_DC_COEFF_SEL_TWO); - controls = rx_macro_def_snd_controls; - num_controls = ARRAY_SIZE(rx_macro_def_snd_controls); - widgets = rx_macro_def_dapm_widgets; - num_widgets = ARRAY_SIZE(rx_macro_def_dapm_widgets); + if (rx->codec_version >= LPASS_CODEC_VERSION_2_5) { + controls = rx_macro_2_5_snd_controls; + num_controls = ARRAY_SIZE(rx_macro_2_5_snd_controls); + widgets = rx_macro_2_5_dapm_widgets; + num_widgets = ARRAY_SIZE(rx_macro_2_5_dapm_widgets); + } else { + controls = rx_macro_def_snd_controls; + num_controls = ARRAY_SIZE(rx_macro_def_snd_controls); + widgets = rx_macro_def_dapm_widgets; + num_widgets = ARRAY_SIZE(rx_macro_def_dapm_widgets); + } rx->component = component; @@ -3609,15 +3790,28 @@ static int rx_macro_probe(struct platform_device *pdev) goto err; } rx->codec_version = lpass_macro_get_codec_version(); - - rx->rxn_reg_stride = 0x80; - def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults); - reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); - if (!reg_defaults) - return -ENOMEM; - memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); - memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], - rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); + switch (rx->codec_version) { + case LPASS_CODEC_VERSION_2_5 ... LPASS_CODEC_VERSION_2_8: + rx->rxn_reg_stride = 0xc0; + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults); + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); + if (!reg_defaults) + return -ENOMEM; + memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); + memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], + rx_2_5_defaults, sizeof(rx_2_5_defaults)); + break; + default: + rx->rxn_reg_stride = 0x80; + def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults); + reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL); + if (!reg_defaults) + return -ENOMEM; + memcpy(®_defaults[0], rx_defaults, sizeof(rx_defaults)); + memcpy(®_defaults[ARRAY_SIZE(rx_defaults)], + rx_pre_2_5_defaults, sizeof(rx_pre_2_5_defaults)); + break; + } rx_regmap_config.reg_defaults = reg_defaults; rx_regmap_config.num_reg_defaults = def_count;
LPASS Codec v2.5 has significant changes in the rx register strides. Due to this headset playback on SM8550, SM8650, x1e80100 and all SoCs after SM8450 have only Left working. This patch adjusts the registers to accomdate 2.5 changes. With this fixed now L and R are functional on Headset playback. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> --- sound/soc/codecs/lpass-rx-macro.c | 220 +++++++++++++++++++++++++++++++++++--- 1 file changed, 207 insertions(+), 13 deletions(-)