On Thu, Jun 06, 2024 at 01:25:59PM +0100, srinivas.kandagatla@xxxxxxxxxx wrote: > From: Srinivas Kandagatla <srinivas.kandagatla@xxxxxxxxxx> > > LPASS Codec v2.5 has significant changes in the rx register offsets. > 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@xxxxxxxxxx> > --- > sound/soc/codecs/lpass-rx-macro.c | 565 ++++++++++++++++++++++-------- > 1 file changed, 410 insertions(+), 155 deletions(-) > > diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c > index f35187d69cac..bb8ede0e7076 100644 > --- a/sound/soc/codecs/lpass-rx-macro.c > +++ b/sound/soc/codecs/lpass-rx-macro.c > @@ -158,7 +158,7 @@ > #define CDC_RX_INTR_CTRL_LEVEL0 (0x03C0) > #define CDC_RX_INTR_CTRL_BYPASS0 (0x03C8) > #define CDC_RX_INTR_CTRL_SET0 (0x03D0) > -#define CDC_RX_RXn_RX_PATH_CTL(n) (0x0400 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_CTL(rx, n) (0x0400 + rx->rxn_reg_offset * n) It's probably a stride or pitch, not an offset. > #define CDC_RX_RX0_RX_PATH_CTL (0x0400) > #define CDC_RX_PATH_RESET_EN_MASK BIT(6) > #define CDC_RX_PATH_CLK_EN_MASK BIT(5) > @@ -166,45 +166,47 @@ > #define CDC_RX_PATH_PGA_MUTE_MASK BIT(4) > #define CDC_RX_PATH_PGA_MUTE_ENABLE BIT(4) > #define CDC_RX_PATH_PCM_RATE_MASK GENMASK(3, 0) > -#define CDC_RX_RXn_RX_PATH_CFG0(n) (0x0404 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_CFG0(rx, n) (0x0404 + rx->rxn_reg_offset * n) > #define CDC_RX_RXn_COMP_EN_MASK BIT(1) > #define CDC_RX_RX0_RX_PATH_CFG0 (0x0404) > #define CDC_RX_RXn_CLSH_EN_MASK BIT(6) > #define CDC_RX_DLY_ZN_EN_MASK BIT(3) > #define CDC_RX_DLY_ZN_ENABLE BIT(3) > #define CDC_RX_RXn_HD2_EN_MASK BIT(2) > -#define CDC_RX_RXn_RX_PATH_CFG1(n) (0x0408 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_CFG1(rx, n) (0x0408 + rx->rxn_reg_offset * n) > #define CDC_RX_RXn_SIDETONE_EN_MASK BIT(4) > #define CDC_RX_RX0_RX_PATH_CFG1 (0x0408) > #define CDC_RX_RX0_HPH_L_EAR_SEL_MASK BIT(1) > -#define CDC_RX_RXn_RX_PATH_CFG2(n) (0x040C + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_CFG2(rx, n) (0x040C + rx->rxn_reg_offset * n) > #define CDC_RX_RXn_HPF_CUT_FREQ_MASK GENMASK(1, 0) > #define CDC_RX_RX0_RX_PATH_CFG2 (0x040C) > -#define CDC_RX_RXn_RX_PATH_CFG3(n) (0x0410 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_CFG3(rx, n) (0x0410 + rx->rxn_reg_offset * n) > #define CDC_RX_RX0_RX_PATH_CFG3 (0x0410) > #define CDC_RX_DC_COEFF_SEL_MASK GENMASK(1, 0) > #define CDC_RX_DC_COEFF_SEL_TWO 0x2 > -#define CDC_RX_RXn_RX_VOL_CTL(n) (0x0414 + 0x80 * n) > +#define CDC_RX_RXn_RX_VOL_CTL(rx, n) (0x0414 + rx->rxn_reg_offset * n) > #define CDC_RX_RX0_RX_VOL_CTL (0x0414) > -#define CDC_RX_RXn_RX_PATH_MIX_CTL(n) (0x0418 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_MIX_CTL(rx, n) (0x0418 + rx->rxn_reg_offset * n) > #define CDC_RX_RXn_MIX_PCM_RATE_MASK GENMASK(3, 0) > #define CDC_RX_RXn_MIX_RESET_MASK BIT(6) > #define CDC_RX_RXn_MIX_RESET BIT(6) > #define CDC_RX_RXn_MIX_CLK_EN_MASK BIT(5) > #define CDC_RX_RX0_RX_PATH_MIX_CTL (0x0418) > #define CDC_RX_RX0_RX_PATH_MIX_CFG (0x041C) > -#define CDC_RX_RXn_RX_VOL_MIX_CTL(n) (0x0420 + 0x80 * n) > +#define CDC_RX_RXn_RX_VOL_MIX_CTL(rx, n) (0x0420 + rx->rxn_reg_offset * n) > #define CDC_RX_RX0_RX_VOL_MIX_CTL (0x0420) > #define CDC_RX_RX0_RX_PATH_SEC1 (0x0424) > #define CDC_RX_RX0_RX_PATH_SEC2 (0x0428) > #define CDC_RX_RX0_RX_PATH_SEC3 (0x042C) > +#define CDC_RX_RXn_RX_PATH_SEC3(rx, n) (0x042c + rx->rxn_reg_offset * n) > #define CDC_RX_RX0_RX_PATH_SEC4 (0x0430) > #define CDC_RX_RX0_RX_PATH_SEC7 (0x0434) > +#define CDC_RX_RXn_RX_PATH_SEC7(rx, n) (0x0434 + rx->rxn_reg_offset * n) > #define CDC_RX_DSM_OUT_DELAY_SEL_MASK GENMASK(2, 0) > #define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE 0x2 > #define CDC_RX_RX0_RX_PATH_MIX_SEC0 (0x0438) > #define CDC_RX_RX0_RX_PATH_MIX_SEC1 (0x043C) > -#define CDC_RX_RXn_RX_PATH_DSM_CTL(n) (0x0440 + 0x80 * n) > +#define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) (0x0440 + rx->rxn_reg_offset * n) > #define CDC_RX_RXn_DSM_CLK_EN_MASK BIT(0) > #define CDC_RX_RX0_RX_PATH_DSM_CTL (0x0440) > #define CDC_RX_RX0_RX_PATH_DSM_DATA1 (0x0444) > @@ -213,6 +215,7 @@ > #define CDC_RX_RX0_RX_PATH_DSM_DATA4 (0x0450) > #define CDC_RX_RX0_RX_PATH_DSM_DATA5 (0x0454) > #define CDC_RX_RX0_RX_PATH_DSM_DATA6 (0x0458) > +/* RX offsets prior to 2.5 codec version */ > #define CDC_RX_RX1_RX_PATH_CTL (0x0480) > #define CDC_RX_RX1_RX_PATH_CFG0 (0x0484) > #define CDC_RX_RX1_RX_PATH_CFG1 (0x0488) > @@ -259,10 +262,58 @@ > #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 */ Please separate 2.5 support into a separate patch. > +#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) > #define CDC_RX_IDLE_DETECT_CFG2 (0x078C) > + > #define CDC_RX_IDLE_DETECT_CFG3 (0x0790) > #define CDC_RX_COMPANDERn_CTL0(n) (0x0800 + 0x40 * n) > #define CDC_RX_COMPANDERn_CLK_EN_MASK BIT(0) > @@ -598,6 +649,8 @@ struct rx_macro { > int rx_mclk_users; > int clsh_users; > int rx_mclk_cnt; > + int codec_version; > + int rxn_reg_offset; > bool is_ear_mode_on; > bool hph_pwr_mode; > bool hph_hd2_mode; > @@ -755,11 +808,15 @@ static SOC_ENUM_SINGLE_DECL(rx_int1_2_interp_enum, SND_SOC_NOPM, 0, > rx_int1_2_interp_mux_text); > static SOC_ENUM_SINGLE_DECL(rx_int2_2_interp_enum, SND_SOC_NOPM, 0, > rx_int2_2_interp_mux_text); > + unrelated? > 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); > static SOC_ENUM_SINGLE_DECL(rx_macro_rx2_enum, SND_SOC_NOPM, 0, rx_macro_mux_text); [skipped all split default + add 2.5] chunks > static int rx_macro_component_probe(struct snd_soc_component *component) > { > + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); > struct rx_macro *rx = snd_soc_component_get_drvdata(component); > + const struct snd_soc_dapm_widget *widgets; > + const struct snd_kcontrol_new *controls; > + unsigned int num_controls; > + int ret, num_widgets; > > snd_soc_component_init_regmap(component, rx->regmap); > > - snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_SEC7, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 0), > CDC_RX_DSM_OUT_DELAY_SEL_MASK, > CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); > - snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_SEC7, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 1), > CDC_RX_DSM_OUT_DELAY_SEL_MASK, > CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); > - snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_SEC7, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_SEC7(rx, 2), > CDC_RX_DSM_OUT_DELAY_SEL_MASK, > CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE); > - snd_soc_component_update_bits(component, CDC_RX_RX0_RX_PATH_CFG3, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 0), > CDC_RX_DC_COEFF_SEL_MASK, > CDC_RX_DC_COEFF_SEL_TWO); > - snd_soc_component_update_bits(component, CDC_RX_RX1_RX_PATH_CFG3, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 1), > CDC_RX_DC_COEFF_SEL_MASK, > CDC_RX_DC_COEFF_SEL_TWO); > - snd_soc_component_update_bits(component, CDC_RX_RX2_RX_PATH_CFG3, > + snd_soc_component_update_bits(component, CDC_RX_RXn_RX_PATH_CFG3(rx, 2), > CDC_RX_DC_COEFF_SEL_MASK, > CDC_RX_DC_COEFF_SEL_TWO); > > + 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; > > - return 0; > + ret = snd_soc_add_component_controls(component, controls, num_controls); > + if (ret) > + return ret; > + > + return snd_soc_dapm_new_controls(dapm, widgets, num_widgets); > } > > static int swclk_gate_enable(struct clk_hw *hw) > @@ -3523,11 +3748,12 @@ static const struct snd_soc_component_driver rx_macro_component_drv = { > > static int rx_macro_probe(struct platform_device *pdev) > { > + struct reg_default *reg_defaults; > struct device *dev = &pdev->dev; > kernel_ulong_t flags; > struct rx_macro *rx; > void __iomem *base; > - int ret; > + int ret, def_count; > > flags = (kernel_ulong_t)device_get_match_data(dev); > > @@ -3567,6 +3793,33 @@ static int rx_macro_probe(struct platform_device *pdev) > goto err; > } > > + rx->codec_version = lpass_macro_get_codec_version(); What guarantees that VA macro has been probed already? If I'm not mistaken, we might easily get a default '0' here instead of a correct version. > + switch (rx->codec_version) { > + case LPASS_CODEC_VERSION_2_5 ... LPASS_CODEC_VERSION_2_8: > + rx->rxn_reg_offset = 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_offset = 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; > + > rx->regmap = devm_regmap_init_mmio(dev, base, &rx_regmap_config); > if (IS_ERR(rx->regmap)) { > ret = PTR_ERR(rx->regmap); > @@ -3629,6 +3882,7 @@ static int rx_macro_probe(struct platform_device *pdev) > if (ret) > goto err_clkout; > > + kfree(reg_defaults); > return 0; > > err_clkout: > @@ -3642,6 +3896,7 @@ static int rx_macro_probe(struct platform_device *pdev) > err_dcodec: > clk_disable_unprepare(rx->macro); > err: > + kfree(reg_defaults); > lpass_macro_pds_exit(rx->pds); > > return ret; > -- > 2.21.0 > -- With best wishes Dmitry