Pārlūkot izejas kodu

Merge "asoc: codecs: Update WSA2 Macro to Match WSA Macro"

qctecmdr 2 gadi atpakaļ
vecāks
revīzija
2205759439

+ 5 - 4
asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -1722,14 +1722,14 @@ static void lpass_cdc_macro_idle_detect_control(struct snd_soc_component *compon
 
 	if (reg && SND_SOC_DAPM_EVENT_ON(event)) {
 		snd_soc_component_update_bits(component, reg, mask, val);
-		dev_dbg(component->dev, "%s: Idle detect clks ON \n", __func__);
+		dev_dbg(component->dev, "%s: Idle detect clks ON\n", __func__);
 	}
 
 	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
 		snd_soc_component_update_bits(component, reg, mask, 0x00);
 		snd_soc_component_write(component,
 				LPASS_CDC_WSA_IDLE_DETECT_CFG3, 0x0);
-		dev_dbg(component->dev, "%s: Idle detect clks OFF \n", __func__);
+		dev_dbg(component->dev, "%s: Idle detect clks OFF\n", __func__);
 	}
 }
 
@@ -1808,7 +1808,7 @@ static int lpass_cdc_wsa_macro_enable_interpolator(struct snd_soc_dapm_widget *w
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component,
-				LPASS_CDC_WSA_RX0_RX_PATH_CFG1,	0x08, 0x08);
+				LPASS_CDC_WSA_RX0_RX_PATH_CFG1, 0x08, 0x08);
 		lpass_cdc_wsa_macro_config_compander(component, w->shift, event);
 		lpass_cdc_macro_idle_detect_control(component, wsa_priv,
 				w->shift, event);
@@ -3279,6 +3279,7 @@ static const struct lpass_cdc_wsa_macro_reg_mask_val
 	{LPASS_CDC_WSA_ILIM_CFG2_1, 0xFF, 0x2A},
 	{LPASS_CDC_WSA_ILIM_CFG2, 0x3F, 0x1B},
 	{LPASS_CDC_WSA_ILIM_CFG9, 0x0F, 0x05},
+	{LPASS_CDC_WSA_IDLE_DETECT_CFG1, 0xFF, 0x1D},
 };
 
 static void lpass_cdc_wsa_macro_init_reg(struct snd_soc_component *component)
@@ -3879,7 +3880,7 @@ static int lpass_cdc_wsa_macro_probe(struct platform_device *pdev)
 			__func__, "qcom,noise-gate-mode");
 		wsa_priv->noise_gate_mode = IDLE_DETECT;
 	} else {
-		if (IDLE_DETECT <= noise_gate_mode && noise_gate_mode <= NG3)
+		if (noise_gate_mode >= IDLE_DETECT && noise_gate_mode <= NG3)
 			wsa_priv->noise_gate_mode = noise_gate_mode;
 		else
 			wsa_priv->noise_gate_mode = IDLE_DETECT;

+ 556 - 91
asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c

@@ -12,6 +12,7 @@
 #include <linux/pm_runtime.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
 #include <sound/tlv.h>
 #include <soc/swr-common.h>
 #include <soc/swr-wcd.h>
@@ -74,6 +75,9 @@ enum {
 	LPASS_CDC_WSA2_MACRO_RX_MIX1,
 	LPASS_CDC_WSA2_MACRO_RX4,
 	LPASS_CDC_WSA2_MACRO_RX5,
+	LPASS_CDC_WSA2_MACRO_RX6,
+	LPASS_CDC_WSA2_MACRO_RX7,
+	LPASS_CDC_WSA2_MACRO_RX8,
 	LPASS_CDC_WSA2_MACRO_RX_MAX,
 };
 
@@ -109,6 +113,9 @@ enum {
 	INTn_1_INP_SEL_RX3,
 	INTn_1_INP_SEL_RX4,
 	INTn_1_INP_SEL_RX5,
+	INTn_1_INP_SEL_RX6,
+	INTn_1_INP_SEL_RX7,
+	INTn_1_INP_SEL_RX8,
 	INTn_1_INP_SEL_DEC0,
 	INTn_1_INP_SEL_DEC1,
 };
@@ -121,23 +128,19 @@ enum {
 	INTn_2_INP_SEL_RX3,
 	INTn_2_INP_SEL_RX4,
 	INTn_2_INP_SEL_RX5,
+	INTn_2_INP_SEL_RX6,
+	INTn_2_INP_SEL_RX7,
+	INTn_2_INP_SEL_RX8,
 };
 
 enum {
-	WSA2_MODE_21DB,
-	WSA2_MODE_19P5DB,
-	WSA2_MODE_18DB,
-	WSA2_MODE_16P5DB,
-	WSA2_MODE_15DB,
-	WSA2_MODE_13P5DB,
-	WSA2_MODE_12DB,
-	WSA2_MODE_10P5DB,
-	WSA2_MODE_9DB,
-	WSA2_MODE_MAX
+	IDLE_DETECT,
+	NG1,
+	NG2,
+	NG3,
 };
 
-static struct lpass_cdc_comp_setting comp_setting_table[WSA2_MODE_MAX] =
-{
+static struct lpass_cdc_comp_setting comp_setting_table[G_MAX_DB] = {
 	{42, 0, 42},
 	{39, 0, 42},
 	{36, 0, 42},
@@ -192,6 +195,8 @@ static int lpass_cdc_wsa2_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 lpass_cdc_wsa2_macro_mute_stream(struct snd_soc_dai *dai, int mute, int stream);
+
+#define LPASS_CDC_WSA2_MACRO_VTH_TO_REG(vth) ((vth) == 0 ? 255 : (vth))
 /* Hold instance to soundwire platform device */
 struct lpass_cdc_wsa2_macro_swr_ctrl_data {
 	struct platform_device *wsa2_swr_pdev;
@@ -233,6 +238,7 @@ enum {
 	LPASS_CDC_WSA2_MACRO_MAX_DAIS,
 };
 
+
 #define LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX 3
 
 /*
@@ -256,6 +262,9 @@ enum {
  * @active_ch_cnt: channel count of all AIF DAIs
  * @rx_port_value: mixer ctl value of WSA2 RX MUXes
  * @wsa2_io_base: Base address of WSA2 macro addr space
+ * @wsa2_sys_gain System gain value, see wsa2 driver
+ * @wsa2_bat_cfg Battery Configuration value, see wsa2 driver
+ * @wsa2_rload Resistor load value for WSA2 Speaker, see wsa2 driver
  */
 struct lpass_cdc_wsa2_macro_priv {
 	struct device *dev;
@@ -277,14 +286,17 @@ struct lpass_cdc_wsa2_macro_priv {
 	struct snd_soc_component *component;
 	int rx_0_count;
 	int rx_1_count;
-	int wsa_spkrrecv;
 	unsigned long active_ch_mask[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
 	unsigned long active_ch_cnt[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
+	u16 bit_width[LPASS_CDC_WSA2_MACRO_MAX_DAIS];
 	int rx_port_value[LPASS_CDC_WSA2_MACRO_RX_MAX];
 	char __iomem *wsa2_io_base;
 	struct platform_device *pdev_child_devices
 			[LPASS_CDC_WSA2_MACRO_CHILD_DEVICES_MAX];
 	int child_count;
+	int wsa2_spkrrecv;
+	int spkr_gain_offset;
+	int spkr_mode;
 	int is_softclip_on[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
 	int softclip_clk_users[LPASS_CDC_WSA2_MACRO_SOFTCLIP_MAX];
 	char __iomem *mclk_mode_muxsel;
@@ -297,17 +309,24 @@ struct lpass_cdc_wsa2_macro_priv {
 	uint32_t thermal_cur_state;
 	uint32_t thermal_max_state;
 	struct work_struct lpass_cdc_wsa2_macro_cooling_work;
+	bool pbr_enable;
+	u32 wsa2_sys_gain[2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1)];
+	u32 wsa2_bat_cfg[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u32 wsa2_rload[LPASS_CDC_WSA2_MACRO_RX1 + 1];
+	u8 idle_detect_en;
+	int noise_gate_mode;
 };
 
 static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[];
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 
 static const char *const rx_text[] = {
-	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "DEC0", "DEC1"
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4",
+	"RX5", "RX6", "RX7", "RX8", "DEC0", "DEC1"
 };
 
 static const char *const rx_mix_text[] = {
-	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5",
+	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "RX4", "RX5", "RX6", "RX7", "RX8"
 };
 
 static const char *const rx_mix_ec_text[] = {
@@ -326,10 +345,6 @@ static const char * const lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text[] = {
 	"OFF", "ON"
 };
 
-static const char *const lpass_cdc_wsa2_macro_ear_spkrrecv_text[] = {
-	"OFF", "ON"
-};
-
 static const char * const lpass_cdc_wsa2_macro_comp_mode_text[] = {
 	"G_21_DB", "G_19P5_DB", "G_18_DB", "G_16P5_DB", "G_15_DB",
 	"G_13P5_DB", "G_12_DB", "G_10P5_DB", "G_9_DB"
@@ -343,8 +358,7 @@ static const struct snd_kcontrol_new wsa2_int1_vbat_mix_switch[] = {
 	SOC_DAPM_SINGLE("WSA2 RX1 VBAT Enable", SND_SOC_NOPM, 0, 1, 0)
 };
 
-static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
-				lpass_cdc_wsa2_macro_ear_spkrrecv_text);
+
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
 			lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_text);
 static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
@@ -353,19 +367,19 @@ static SOC_ENUM_SINGLE_EXT_DECL(lpass_cdc_wsa2_macro_comp_mode_enum,
 /* RX INT0 */
 static const struct soc_enum rx0_prim_inp0_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
-		0, 9, rx_text);
+		0, 12, rx_text);
 
 static const struct soc_enum rx0_prim_inp1_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG0,
-		3, 9, rx_text);
+		3, 12, rx_text);
 
 static const struct soc_enum rx0_prim_inp2_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
-		3, 9, rx_text);
+		3, 12, rx_text);
 
 static const struct soc_enum rx0_mix_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT0_CFG1,
-		0, 7, rx_mix_text);
+		0, 10, rx_mix_text);
 
 static const struct soc_enum rx0_sidetone_mix_enum =
 	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
@@ -388,19 +402,19 @@ static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
 /* RX INT1 */
 static const struct soc_enum rx1_prim_inp0_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
-		0, 9, rx_text);
+		0, 12, rx_text);
 
 static const struct soc_enum rx1_prim_inp1_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG0,
-		3, 9, rx_text);
+		3, 12, rx_text);
 
 static const struct soc_enum rx1_prim_inp2_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
-		3, 9, rx_text);
+		3, 12, rx_text);
 
 static const struct soc_enum rx1_mix_chain_enum =
 	SOC_ENUM_SINGLE(LPASS_CDC_WSA2_RX_INP_MUX_RX_INT1_CFG1,
-		0, 7, rx_mix_text);
+		0, 10, rx_mix_text);
 
 static const struct snd_kcontrol_new rx1_prim_inp0_mux =
 	SOC_DAPM_ENUM("WSA2_RX1 INP0 Mux", rx1_prim_inp0_chain_enum);
@@ -748,10 +762,37 @@ static int lpass_cdc_wsa2_macro_hw_params(struct snd_pcm_substream *substream,
 				__func__, params_rate(params));
 			return ret;
 		}
+		switch (params_width(params)) {
+		case 16:
+			wsa2_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa2_priv->bit_width[dai->id] = 24;
+			break;
+		case 32:
+			wsa2_priv->bit_width[dai->id] = 32;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+		}
 		break;
 	case SNDRV_PCM_STREAM_CAPTURE:
 		if (dai->id == LPASS_CDC_WSA2_MACRO_AIF_VI)
 			wsa2_priv->pcm_rate_vi = params_rate(params);
+		switch (params_width(params)) {
+		case 16:
+			wsa2_priv->bit_width[dai->id] = 16;
+			break;
+		case 24:
+			wsa2_priv->bit_width[dai->id] = 24;
+			break;
+		default:
+			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
+				__func__, params_width(params));
+			return -EINVAL;
+			}
 	default:
 		break;
 	}
@@ -1038,16 +1079,16 @@ static int lpass_cdc_wsa2_macro_enable_vi_feedback(struct snd_soc_dapm_widget *w
 		return -EINVAL;
 
 	switch (wsa2_priv->pcm_rate_vi) {
-		case 48000:
-			val = 0x04;
-			break;
-		case 24000:
-			val = 0x02;
-			break;
-		case 8000:
-		default:
-			val = 0x00;
-			break;
+	case 48000:
+		val = 0x04;
+		break;
+	case 24000:
+		val = 0x02;
+		break;
+	case 8000:
+	default:
+		val = 0x00;
+		break;
 	}
 
 	switch (event) {
@@ -1275,7 +1316,9 @@ static int lpass_cdc_wsa2_macro_config_compander(struct snd_soc_component *compo
 	u16 comp_ctl0_reg, comp_ctl8_reg, rx_path_cfg0_reg;
 	struct device *wsa2_dev = NULL;
 	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct lpass_cdc_comp_setting *comp_settings = NULL;
 	u16 mode = 0;
+	int sys_gain, bat_cfg, sys_gain_int, upper_gain, lower_gain;
 
 	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
 		return -EINVAL;
@@ -1293,11 +1336,49 @@ static int lpass_cdc_wsa2_macro_config_compander(struct snd_soc_component *compo
 					(comp * LPASS_CDC_WSA2_MACRO_RX_COMP_OFFSET);
 	rx_path_cfg0_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG0 +
 					(comp * LPASS_CDC_WSA2_MACRO_RX_PATH_OFFSET);
+	comp_settings = &comp_setting_table[mode];
+
+	/* If System has battery configuration */
+	if (wsa2_priv->wsa2_bat_cfg[comp]) {
+		sys_gain = wsa2_priv->wsa2_sys_gain[comp * 2 + wsa2_priv->wsa2_spkrrecv];
+		bat_cfg = wsa2_priv->wsa2_bat_cfg[comp];
+		/* Convert enum to value and
+		 * multiply all values by 10 to avoid float
+		 */
+		sys_gain_int = -15 * sys_gain + 210;
+		switch (bat_cfg) {
+		case CONFIG_1S:
+		case EXT_1S:
+			if (sys_gain > G_13P5_DB) {
+				upper_gain = sys_gain_int + 60;
+				lower_gain = 0;
+			} else {
+				upper_gain = 210;
+				lower_gain = 0;
+			}
+			break;
+		case CONFIG_3S:
+		case EXT_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 75;
+		case EXT_ABOVE_3S:
+			upper_gain = sys_gain_int;
+			lower_gain = 120;
+			break;
+		default:
+			upper_gain = sys_gain_int;
+			lower_gain = 0;
+			break;
+		}
+		/* Truncate after calculation */
+		comp_settings->lower_gain_int = (lower_gain * 2) / 10;
+		comp_settings->upper_gain_int = (upper_gain * 2) / 10;
+	}
 
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
 		lpass_cdc_update_compander_setting(component,
 					comp_ctl8_reg,
-					&comp_setting_table[mode]);
+					comp_settings);
 		/* Enable Compander Clock */
 		snd_soc_component_update_bits(component, comp_ctl0_reg,
 						0x01, 0x01);
@@ -1405,6 +1486,63 @@ static int lpass_cdc_wsa2_macro_config_softclip(struct snd_soc_component *compon
 	return 0;
 }
 
+static int lpass_cdc_was_macro_config_pbr(struct snd_soc_component *component,
+					  int path, int event)
+{
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	u16 reg1 = 0, reg2 = 0, reg3 = 0;
+	int softclip_path = 0;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (path == LPASS_CDC_WSA2_MACRO_COMP1) {
+		reg1 = LPASS_CDC_WSA2_COMPANDER0_CTL0;
+		reg2 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA2_RX0_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP0;
+	} else if (path == LPASS_CDC_WSA2_MACRO_COMP2) {
+		reg1 = LPASS_CDC_WSA2_COMPANDER1_CTL0;
+		reg2 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
+		reg3 = LPASS_CDC_WSA2_RX1_RX_PATH_CFG1;
+		softclip_path = LPASS_CDC_WSA2_MACRO_SOFTCLIP1;
+	}
+	if (!wsa2_priv->pbr_enable || wsa2_priv->wsa2_bat_cfg[path] >= EXT_1S ||
+	    wsa2_priv->wsa2_sys_gain[path * 2] > G_12_DB ||
+	    wsa2_priv->wsa2_spkrrecv || !reg1 || !reg2 || !reg3)
+		return 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x08);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x40);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x80);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+					softclip_path, true);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_PBR_PATH_CTL,
+			0x01, 0x01);
+	}
+
+	if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_PBR_PATH_CTL,
+			0x01, 0x00);
+		lpass_cdc_wsa2_macro_enable_softclip_clk(component, wsa2_priv,
+					softclip_path, false);
+		snd_soc_component_update_bits(component,
+			reg1, 0x08, 0x00);
+		snd_soc_component_update_bits(component,
+			reg2, 0x40, 0x00);
+		snd_soc_component_update_bits(component,
+			reg3, 0x80, 0x00);
+	}
+	return 0;
+}
+
 static bool lpass_cdc_wsa2_macro_adie_lb(struct snd_soc_component *component,
 			      int interp_idx)
 {
@@ -1543,6 +1681,57 @@ static int lpass_cdc_wsa2_macro_enable_prim_interpolator(
 	return 0;
 }
 
+static void lpass_cdc_macro_idle_detect_control(struct snd_soc_component *component,
+					 struct lpass_cdc_wsa2_macro_priv *wsa2_priv,
+					 int interp, int event)
+{
+	int reg = 0, mask = 0, val = 0, source_reg = 0;
+	u16 mode = 0;
+
+	dev_dbg(component->dev, "%s: Idle_detect_en value: %d\n", __func__,
+		wsa2_priv->idle_detect_en);
+
+	if (!wsa2_priv->idle_detect_en)
+		return;
+
+	if (interp == LPASS_CDC_WSA2_MACRO_COMP1) {
+		source_reg = LPASS_CDC_WSA2_RX0_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
+		mask = 0x01;
+		val = 0x01;
+	}
+	if (interp == LPASS_CDC_WSA2_MACRO_COMP2) {
+		source_reg = LPASS_CDC_WSA2_RX1_RX_PATH_CFG3;
+		reg = LPASS_CDC_WSA2_IDLE_DETECT_PATH_CTL;
+		mask = 0x02;
+		val = 0x02;
+	}
+
+	mode = wsa2_priv->comp_mode[interp];
+
+	if ((wsa2_priv->noise_gate_mode == NG2 && mode >= G_13P5_DB) ||
+			wsa2_priv->noise_gate_mode == IDLE_DETECT || !wsa2_priv->pbr_enable ||
+			wsa2_priv->wsa2_spkrrecv) {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x00);
+		dev_dbg(component->dev, "%s: Idle detect source: Legacy\n", __func__);
+	} else {
+		snd_soc_component_update_bits(component, source_reg, 0x80, 0x80);
+		dev_dbg(component->dev, "%s: Idle detect source: PRE-LA\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_ON(event)) {
+		snd_soc_component_update_bits(component, reg, mask, val);
+		dev_dbg(component->dev, "%s: Idle detect clks ON\n", __func__);
+	}
+
+	if (reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+		snd_soc_component_update_bits(component, reg, mask, 0x00);
+		snd_soc_component_write(component,
+				LPASS_CDC_WSA2_IDLE_DETECT_CFG3, 0x0);
+		dev_dbg(component->dev, "%s: Idle detect clks OFF\n", __func__);
+	}
+}
+
 static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *w,
 					 struct snd_kcontrol *kcontrol,
 					 int event)
@@ -1607,8 +1796,11 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
 		}
 
 		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
+				w->shift, event);
 		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
-		if(wsa2_priv->wsa_spkrrecv)
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
+		if (wsa2_priv->wsa2_spkrrecv)
 			snd_soc_component_update_bits(component,
 					LPASS_CDC_WSA2_RX0_RX_PATH_CFG1,
 					0x08, 0x00);
@@ -1617,7 +1809,10 @@ static int lpass_cdc_wsa2_macro_enable_interpolator(struct snd_soc_dapm_widget *
 		snd_soc_component_update_bits(component,
 				LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08);
 		lpass_cdc_wsa2_macro_config_compander(component, w->shift, event);
+		lpass_cdc_macro_idle_detect_control(component, wsa2_priv,
+				w->shift, event);
 		lpass_cdc_wsa2_macro_config_softclip(component, w->shift, event);
+		lpass_cdc_was_macro_config_pbr(component, w->shift, event);
 		lpass_cdc_wsa2_macro_enable_prim_interpolator(component, reg, event);
 		break;
 	}
@@ -1752,24 +1947,24 @@ static int lpass_cdc_wsa2_macro_enable_vbat(struct snd_soc_dapm_widget *w,
 		snd_soc_component_update_bits(component,
 			LPASS_CDC_WSA2_VBAT_BCL_VBAT_BCL_GAIN_UPD9,
 			0xFF, 0x00);
-                /* Enable CB decode block clock */
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
-                /* Enable BCL path */
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
-                /* Request for BCL data */
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
+		/* Enable CB decode block clock */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x01);
+		/* Enable BCL path */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x01);
+		/* Request for BCL data */
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x01);
 		break;
 
 	case SND_SOC_DAPM_POST_PMD:
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
-                snd_soc_component_update_bits(component,
-                        LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL3, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL2, 0x01, 0x00);
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_CB_DECODE_CB_DECODE_CTL1, 0x01, 0x00);
 		snd_soc_component_update_bits(component, vbat_path_cfg,
 			0x80, 0x00);
 		snd_soc_component_update_bits(component,
@@ -2075,7 +2270,7 @@ static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
 	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
 		return -EINVAL;
 
-	ucontrol->value.integer.value[0] = wsa2_priv->wsa_spkrrecv;
+	ucontrol->value.integer.value[0] = wsa2_priv->wsa2_spkrrecv;
 
 	dev_dbg(component->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
 		 __func__, ucontrol->value.integer.value[0]);
@@ -2084,21 +2279,54 @@ static int lpass_cdc_wsa2_macro_ear_spkrrecv_get(struct snd_kcontrol *kcontrol,
 }
 
 static int lpass_cdc_wsa2_macro_ear_spkrrecv_put(struct snd_kcontrol *kcontrol,
-                                        struct snd_ctl_elem_value *ucontrol)
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->wsa2_spkrrecv = ucontrol->value.integer.value[0];
+
+	dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
+		__func__, wsa2_priv->wsa2_spkrrecv);
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_idle_detect_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct device *wsa2_dev = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->idle_detect_en;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_idle_detect_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
 {
-        struct snd_soc_component *component =
-                                snd_soc_kcontrol_component(kcontrol);
-        struct device *wsa2_dev = NULL;
-        struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+	struct device *wsa2_dev = NULL;
 
-        if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
-                return -EINVAL;
-        wsa2_priv->wsa_spkrrecv = ucontrol->value.integer.value[0];
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
 
-        dev_dbg(component->dev, "%s:spkrrecv status = %d\n",
-                 __func__, wsa2_priv->wsa_spkrrecv);
+	wsa2_priv->idle_detect_en = ucontrol->value.integer.value[0];
 
-        return 0;
+	return 0;
 }
 
 static int lpass_cdc_wsa2_macro_comp_mode_get(struct snd_kcontrol *kcontrol,
@@ -2311,10 +2539,41 @@ static int lpass_cdc_wsa2_macro_soft_clip_enable_put(struct snd_kcontrol *kcontr
 	return 0;
 }
 
+static int lpass_cdc_wsa2_macro_pbr_enable_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa2_priv->pbr_enable;
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_pbr_enable_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	wsa2_priv->pbr_enable = ucontrol->value.integer.value[0];
+	return 0;
+
+}
+
+
 static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
-	SOC_ENUM_EXT("WSA2 SPKRRECV", lpass_cdc_wsa2_macro_ear_spkrrecv_enum,
-			lpass_cdc_wsa2_macro_ear_spkrrecv_get,
-			lpass_cdc_wsa2_macro_ear_spkrrecv_put),
 	SOC_ENUM_EXT("WSA2_GSM mode Enable", lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_enum,
 		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_get,
 		     lpass_cdc_wsa2_macro_vbat_bcl_gsm_mode_func_put),
@@ -2324,6 +2583,12 @@ static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
 	SOC_ENUM_EXT("WSA2_RX1 comp_mode", lpass_cdc_wsa2_macro_comp_mode_enum,
 		     lpass_cdc_wsa2_macro_comp_mode_get,
 		     lpass_cdc_wsa2_macro_comp_mode_put),
+	SOC_SINGLE_EXT("WSA2 SPKRRECV", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_get,
+			lpass_cdc_wsa2_macro_ear_spkrrecv_put),
+	SOC_SINGLE_EXT("WSA2 Idle Detect", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa2_macro_idle_detect_get,
+			lpass_cdc_wsa2_macro_idle_detect_put),
 	SOC_SINGLE_EXT("WSA2_Softclip0 Enable", SND_SOC_NOPM,
 			LPASS_CDC_WSA2_MACRO_SOFTCLIP0, 1, 0,
 			lpass_cdc_wsa2_macro_soft_clip_enable_get,
@@ -2358,6 +2623,9 @@ static const struct snd_kcontrol_new lpass_cdc_wsa2_macro_snd_controls[] = {
 			1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
 	SOC_SINGLE_EXT("WSA2_RX1 EC_HQ Switch", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_RX1,
 			1, 0, lpass_cdc_wsa2_macro_get_ec_hq, lpass_cdc_wsa2_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA2 PBR Enable", SND_SOC_NOPM, 0, 1,
+			0, lpass_cdc_wsa2_macro_pbr_enable_get,
+			lpass_cdc_wsa2_macro_pbr_enable_put),
 };
 
 static const struct soc_enum rx_mux_enum =
@@ -2828,14 +3096,150 @@ static const struct snd_soc_dapm_route wsa2_audio_map[] = {
 	{"WSA2_SPK2 OUT", NULL, "WSA2_MCLK"},
 };
 
+static void lpass_cdc_wsa2_macro_init_pbr(struct snd_soc_component *component)
+{
+	int sys_gain, bat_cfg, rload;
+	int vth1, vth2, vth3, vth4, vth5, vth6, vth7, vth8, vth9;
+	int vth10, vth11, vth12, vth13, vth14, vth15;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return;
+
+	/* RX0 */
+	sys_gain = wsa2_priv->wsa2_sys_gain[0];
+	bat_cfg = wsa2_priv->wsa2_bat_cfg[0];
+	rload = wsa2_priv->wsa2_rload[0];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG9, 0xC0, (bat_cfg - 1) << 0x6);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15, vth15);
+
+	/* RX1 */
+	sys_gain = wsa2_priv->wsa2_sys_gain[2];
+	bat_cfg = wsa2_priv->wsa2_bat_cfg[1];
+	rload = wsa2_priv->wsa2_rload[1];
+	/* ILIM */
+	switch (rload) {
+	case WSA_4_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x40);
+		break;
+	case WSA_6_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0x80);
+		break;
+	case WSA_8_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xC0);
+		break;
+	case WSA_32_OHMS:
+		snd_soc_component_update_bits(component,
+			LPASS_CDC_WSA2_ILIM_CFG0_1, 0xE0, 0xE0);
+		break;
+	default:
+		break;
+	}
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG1_1, 0x0F, sys_gain);
+	snd_soc_component_update_bits(component,
+		LPASS_CDC_WSA2_ILIM_CFG9, 0x30, (bat_cfg - 1) << 0x4);
+	/* Thesh */
+	vth1 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth1_data[sys_gain][bat_cfg][rload]);
+	vth2 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth2_data[sys_gain][bat_cfg][rload]);
+	vth3 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth3_data[sys_gain][bat_cfg][rload]);
+	vth4 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth4_data[sys_gain][bat_cfg][rload]);
+	vth5 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth5_data[sys_gain][bat_cfg][rload]);
+	vth6 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth6_data[sys_gain][bat_cfg][rload]);
+	vth7 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth7_data[sys_gain][bat_cfg][rload]);
+	vth8 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth8_data[sys_gain][bat_cfg][rload]);
+	vth9 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth9_data[sys_gain][bat_cfg][rload]);
+	vth10 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth10_data[sys_gain][bat_cfg][rload]);
+	vth11 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth11_data[sys_gain][bat_cfg][rload]);
+	vth12 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth12_data[sys_gain][bat_cfg][rload]);
+	vth13 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth13_data[sys_gain][bat_cfg][rload]);
+	vth14 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth14_data[sys_gain][bat_cfg][rload]);
+	vth15 = LPASS_CDC_WSA2_MACRO_VTH_TO_REG(pbr_vth15_data[sys_gain][bat_cfg][rload]);
+
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG1_1, vth1);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG2_1, vth2);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG3_1, vth3);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG4_1, vth4);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG5_1, vth5);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG6_1, vth6);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG7_1, vth7);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG8_1, vth8);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG9_1, vth9);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG10_1, vth10);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG11_1, vth11);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG12_1, vth12);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG13_1, vth13);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG14_1, vth14);
+	snd_soc_component_write(component, LPASS_CDC_WSA2_PBR_CFG15_1, vth15);
+}
+
 static const struct lpass_cdc_wsa2_macro_reg_mask_val
 				lpass_cdc_wsa2_macro_reg_init[] = {
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x1E, 0x18},
+	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x3E, 0x2e},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG1, 0x3F, 0x12},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CFG2, 0x1C, 0x08},
-	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x1E, 0x18},
+	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x3E, 0x2e},
 	{LPASS_CDC_WSA2_BOOST0_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA2_BOOST1_BOOST_CTL, 0x70, 0x58},
 	{LPASS_CDC_WSA2_RX0_RX_PATH_CFG1, 0x08, 0x08},
@@ -2846,12 +3250,28 @@ static const struct lpass_cdc_wsa2_macro_reg_mask_val
 	{LPASS_CDC_WSA2_TX1_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 	{LPASS_CDC_WSA2_TX2_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 	{LPASS_CDC_WSA2_TX3_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
-	{LPASS_CDC_WSA2_COMPANDER0_CTL7, 0x01, 0x01},
-	{LPASS_CDC_WSA2_COMPANDER1_CTL7, 0x01, 0x01},
 	{LPASS_CDC_WSA2_RX0_RX_PATH_CFG0, 0x01, 0x01},
 	{LPASS_CDC_WSA2_RX1_RX_PATH_CFG0, 0x01, 0x01},
 	{LPASS_CDC_WSA2_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
 	{LPASS_CDC_WSA2_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
+	{LPASS_CDC_WSA2_LA_CFG, 0x3F, 0xF},
+	{LPASS_CDC_WSA2_PBR_CFG16, 0xFF, 0x42},
+	{LPASS_CDC_WSA2_PBR_CFG19, 0xFF, 0xFC},
+	{LPASS_CDC_WSA2_PBR_CFG20, 0xF0, 0x60},
+	{LPASS_CDC_WSA2_ILIM_CFG1, 0x70, 0x40},
+	{LPASS_CDC_WSA2_ILIM_CFG0, 0x03, 0x01},
+	{LPASS_CDC_WSA2_ILIM_CFG3, 0x1F, 0x15},
+	{LPASS_CDC_WSA2_LA_CFG_1, 0x3F, 0x0F},
+	{LPASS_CDC_WSA2_PBR_CFG16_1, 0xFF, 0x42},
+	{LPASS_CDC_WSA2_PBR_CFG21, 0xFF, 0xFC},
+	{LPASS_CDC_WSA2_PBR_CFG22, 0xF0, 0x60},
+	{LPASS_CDC_WSA2_ILIM_CFG1_1, 0x70, 0x40},
+	{LPASS_CDC_WSA2_ILIM_CFG0_1, 0x03, 0x01},
+	{LPASS_CDC_WSA2_ILIM_CFG4, 0x1F, 0x15},
+	{LPASS_CDC_WSA2_ILIM_CFG2_1, 0xFF, 0x2A},
+	{LPASS_CDC_WSA2_ILIM_CFG2, 0x3F, 0x1B},
+	{LPASS_CDC_WSA2_ILIM_CFG9, 0x0F, 0x05},
+	{LPASS_CDC_WSA2_IDLE_DETECT_CFG1, 0xFF, 0x1D},
 };
 
 static void lpass_cdc_wsa2_macro_init_reg(struct snd_soc_component *component)
@@ -2863,6 +3283,7 @@ static void lpass_cdc_wsa2_macro_init_reg(struct snd_soc_component *component)
 				lpass_cdc_wsa2_macro_reg_init[i].reg,
 				lpass_cdc_wsa2_macro_reg_init[i].mask,
 				lpass_cdc_wsa2_macro_reg_init[i].val);
+	lpass_cdc_wsa2_macro_init_pbr(component);
 }
 
 static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
@@ -2884,6 +3305,7 @@ static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
 		pm_runtime_put_autosuspend(wsa2_priv->dev);
 		pm_runtime_mark_last_busy(wsa2_priv->dev);
 	}
+
 	return rc;
 }
 
@@ -3068,9 +3490,8 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
 		return -EINVAL;
 	}
 
-	ret = snd_soc_dapm_new_controls(dapm,
-				lpass_cdc_wsa2_macro_dapm_widgets,
-				ARRAY_SIZE(lpass_cdc_wsa2_macro_dapm_widgets));
+	ret = snd_soc_dapm_new_controls(dapm, lpass_cdc_wsa2_macro_dapm_widgets,
+					ARRAY_SIZE(lpass_cdc_wsa2_macro_dapm_widgets));
 	if (ret < 0) {
 		dev_err(wsa2_dev, "%s: Failed to add controls\n", __func__);
 		return ret;
@@ -3089,9 +3510,8 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
 		return ret;
 	}
 
-	ret = snd_soc_add_component_controls(component,
-				lpass_cdc_wsa2_macro_snd_controls,
-				ARRAY_SIZE(lpass_cdc_wsa2_macro_snd_controls));
+	ret = snd_soc_add_component_controls(component, lpass_cdc_wsa2_macro_snd_controls,
+				   ARRAY_SIZE(lpass_cdc_wsa2_macro_snd_controls));
 	if (ret < 0) {
 		dev_err(wsa2_dev, "%s: Failed to add snd_ctls\n", __func__);
 		return ret;
@@ -3109,6 +3529,7 @@ static int lpass_cdc_wsa2_macro_init(struct snd_soc_component *component)
 	snd_soc_dapm_sync(dapm);
 
 	wsa2_priv->component = component;
+	wsa2_priv->spkr_gain_offset = LPASS_CDC_WSA2_MACRO_GAIN_OFFSET_0_DB;
 	lpass_cdc_wsa2_macro_init_reg(component);
 
 	return 0;
@@ -3200,7 +3621,7 @@ static void lpass_cdc_wsa2_macro_add_child_devices(struct work_struct *work)
 			swr_ctrl_data[ctrl_num].wsa2_swr_pdev = pdev;
 			ctrl_num++;
 			dev_dbg(&pdev->dev,
-				"%s: Added soundwire ctrl device(s)\n",
+				"%s: Adding soundwire ctrl device(s)\n",
 				__func__);
 			wsa2_priv->swr_ctrl_data = swr_ctrl_data;
 		}
@@ -3236,12 +3657,12 @@ static void lpass_cdc_wsa2_macro_cooling_adjust_gain(struct work_struct *work)
 	wsa2_priv = container_of(work, struct lpass_cdc_wsa2_macro_priv,
 			     lpass_cdc_wsa2_macro_cooling_work);
 	if (!wsa2_priv) {
-		pr_err_ratelimited("%s: priv is null for macro!\n",
+		pr_err("%s: priv is null for macro!\n",
 			__func__);
 		return;
 	}
 	if (!wsa2_priv->dev || !wsa2_priv->dev->of_node) {
-		dev_err_ratelimited(wsa2_priv->dev,
+		dev_err(wsa2_priv->dev,
 			"%s: DT node for wsa2_priv does not exist\n", __func__);
 		return;
 	}
@@ -3270,6 +3691,31 @@ static void lpass_cdc_wsa2_macro_cooling_adjust_gain(struct work_struct *work)
 	return;
 }
 
+static int lpass_cdc_wsa2_macro_read_array(struct platform_device *pdev,
+					  const char *name, int num_values,
+					  u32 *output)
+{
+	u32 len, ret, size;
+
+	if (!of_find_property(pdev->dev.of_node, name, &size)) {
+		dev_info(&pdev->dev, "%s: missing %s\n", __func__, name);
+		return 0;
+	}
+
+	len = size / sizeof(u32);
+	if (len != num_values) {
+		dev_info(&pdev->dev, "%s: invalid number of %s\n", __func__, name);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node, name, output, len);
+	if (ret)
+		dev_info(&pdev->dev, "%s: Failed to read %s\n", __func__, name);
+
+	return 0;
+
+}
+
 static void lpass_cdc_wsa2_macro_init_ops(struct macro_ops *ops,
 			       char __iomem *wsa2_io_base)
 {
@@ -3291,6 +3737,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
 	char __iomem *wsa2_io_base;
 	int ret = 0;
 	u32 is_used_wsa2_swr_gpio = 1;
+	u32 noise_gate_mode;
 	const char *is_used_wsa2_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
 	if (!lpass_cdc_is_va_macro_registered(&pdev->dev)) {
@@ -3299,8 +3746,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
 		return -EPROBE_DEFER;
 	}
 
-	wsa2_priv = devm_kzalloc(&pdev->dev,
-				sizeof(struct lpass_cdc_wsa2_macro_priv),
+	wsa2_priv = devm_kzalloc(&pdev->dev, sizeof(struct lpass_cdc_wsa2_macro_priv),
 				GFP_KERNEL);
 	if (!wsa2_priv)
 		return -ENOMEM;
@@ -3341,12 +3787,20 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
 				wsa2_priv->wsa2_swr_gpio_p, false);
 
 	wsa2_io_base = devm_ioremap(&pdev->dev,
-				    wsa2_base_addr,
-				    LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
+				   wsa2_base_addr, LPASS_CDC_WSA2_MACRO_MAX_OFFSET);
 	if (!wsa2_io_base) {
 		dev_err(&pdev->dev, "%s: ioremap failed\n", __func__);
 		return -EINVAL;
 	}
+
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-rloads",
+		LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_rload);
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-system-gains",
+		2 * (LPASS_CDC_WSA2_MACRO_RX1 + 1), wsa2_priv->wsa2_sys_gain);
+	lpass_cdc_wsa2_macro_read_array(pdev, "qcom,wsa2-bat-cfgs",
+		LPASS_CDC_WSA2_MACRO_RX1 + 1, wsa2_priv->wsa2_bat_cfg);
+
+
 	wsa2_priv->wsa2_io_base = wsa2_io_base;
 	wsa2_priv->reset_swr = true;
 	INIT_WORK(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work,
@@ -3366,7 +3820,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
 	if (ret) {
 		dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
 			__func__, "qcom,mux0-clk-id");
-		default_clk_id = WSA_CORE_CLK;
+		default_clk_id = WSA2_CORE_CLK;
 	}
 
 	wsa2_priv->default_clk_id  = default_clk_id;
@@ -3409,14 +3863,25 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
 		}
 	}
 
+	ret = of_property_read_u32(pdev->dev.of_node,
+				"qcom,noise-gate-mode", &noise_gate_mode);
+	if (ret) {
+		dev_info(&pdev->dev, "%s: could not find %s entry in dt\n",
+			__func__, "qcom,noise-gate-mode");
+		wsa2_priv->noise_gate_mode = IDLE_DETECT;
+	} else {
+		if (noise_gate_mode >= IDLE_DETECT && noise_gate_mode <= NG3)
+			wsa2_priv->noise_gate_mode = noise_gate_mode;
+		else
+			wsa2_priv->noise_gate_mode = IDLE_DETECT;
+	}
+
 	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_DELAY);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	pm_suspend_ignore_children(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
-
 	schedule_work(&wsa2_priv->lpass_cdc_wsa2_macro_add_child_devices_work);
-
 	return ret;
 reg_macro_fail:
 	mutex_destroy(&wsa2_priv->mclk_lock);