Browse Source

Merge 4e4aec5874abd5edcdfcacac5ba563d4aa507c01 on remote branch

Change-Id: I11ecf1e1308715c9e7f8f3a7c52fd3cb38e7f78b
Linux Build Service Account 2 years ago
parent
commit
446afb3a63

+ 3 - 0
asoc/codecs/lpass-cdc/internal.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _LPASS_CDC_INTERNAL_H
@@ -17,6 +18,7 @@ enum {
 	LPASS_CDC_WCD_EVT_SSR_UP,
 	LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK,
 	LPASS_CDC_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB,
+	LPASS_CDC_WCD_EVT_CLK_NOTIFY,
 };
 
 enum {
@@ -50,6 +52,7 @@ struct lpass_cdc_priv {
 	struct device *dev;
 	struct snd_soc_component *component;
 	struct regmap *regmap;
+	struct mutex macro_lock;
 	struct mutex io_lock;
 	struct mutex clk_lock;
 	struct mutex vote_lock;

+ 75 - 8
asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -485,6 +485,7 @@ enum {
 struct lpass_cdc_rx_macro_priv {
 	struct device *dev;
 	int comp_enabled[LPASS_CDC_RX_MACRO_COMP_MAX];
+	u8 is_pcm_enabled;
 	/* Main path clock users count */
 	int main_clk_users[INTERP_MAX];
 	int rx_port_value[LPASS_CDC_RX_MACRO_PORTS_MAX];
@@ -535,6 +536,7 @@ struct lpass_cdc_rx_macro_priv {
 	struct clk *hifi_fir_clk;
 	int8_t rx0_gain_val;
 	int8_t rx1_gain_val;
+	int pcm_select_users;
 };
 
 static struct snd_soc_dai_driver lpass_cdc_rx_macro_dai[];
@@ -1827,11 +1829,15 @@ static int lpass_cdc_rx_macro_enable_main_path(struct snd_soc_dapm_widget *w,
 }
 
 static void lpass_cdc_rx_macro_droop_setting(struct snd_soc_component *component,
-					    int interp_n, int event)
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					int interp_n, int event)
 {
 	u8 pcm_rate = 0, val = 0;
 	u16 rx0_path_ctl_reg = 0, rx_path_cfg3_reg = 0;
 
+	if (rx_priv->is_pcm_enabled)
+		return;
+
 	rx_path_cfg3_reg = LPASS_CDC_RX_RX0_RX_PATH_CFG3 +
 					(interp_n * LPASS_CDC_RX_MACRO_RX_PATH_OFFSET);
 	rx0_path_ctl_reg = LPASS_CDC_RX_RX0_RX_PATH_CTL +
@@ -1869,7 +1875,7 @@ static int lpass_cdc_rx_macro_config_compander(struct snd_soc_component *compone
 		return 0;
 
 	comp = interp_n;
-	if (!rx_priv->comp_enabled[comp])
+	if (!rx_priv->comp_enabled[comp] && rx_priv->is_pcm_enabled)
 		return 0;
 
 	if (rx_priv->is_ear_mode_on && interp_n == INTERP_HPHL)
@@ -2083,11 +2089,15 @@ static int lpass_cdc_rx_macro_config_classh(struct snd_soc_component *component,
 }
 
 static void lpass_cdc_rx_macro_hd2_control(struct snd_soc_component *component,
-				 u16 interp_idx, int event)
+					struct lpass_cdc_rx_macro_priv *rx_priv,
+					u16 interp_idx, int event)
 {
 	u16 hd2_scale_reg = 0;
 	u16 hd2_enable_reg = 0;
 
+	if (rx_priv->is_pcm_enabled)
+		return;
+
 	switch (interp_idx) {
 	case INTERP_HPHL:
 		hd2_scale_reg = LPASS_CDC_RX_RX0_RX_PATH_SEC3;
@@ -2148,6 +2158,36 @@ static int lpass_cdc_rx_macro_hph_idle_detect_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int lpass_cdc_rx_macro_get_pcm_path(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = rx_priv->is_pcm_enabled;
+	return 0;
+}
+
+static int lpass_cdc_rx_macro_put_pcm_path(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct device *rx_dev = NULL;
+	struct lpass_cdc_rx_macro_priv *rx_priv = NULL;
+
+	if (!lpass_cdc_rx_macro_get_data(component, &rx_dev, &rx_priv, __func__))
+		return -EINVAL;
+
+	rx_priv->is_pcm_enabled = ucontrol->value.integer.value[0];
+	return 0;
+}
+
 static int lpass_cdc_rx_macro_get_compander(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
@@ -2618,6 +2658,9 @@ static void lpass_cdc_rx_macro_idle_detect_control(struct snd_soc_component *com
 	if (!rx_priv->idle_det_cfg.hph_idle_detect_en)
 		return;
 
+	if (!rx_priv->is_pcm_enabled)
+		return;
+
 	if (interp == INTERP_HPHL) {
 		reg = LPASS_CDC_RX_IDLE_DETECT_PATH_CTL;
 		mask = 0x01;
@@ -2647,6 +2690,9 @@ static void lpass_cdc_rx_macro_hphdelay_lutbypass(struct snd_soc_component *comp
 	u16 hph_lut_bypass_reg = 0;
 	u16 hph_comp_ctrl7 = 0;
 
+	if (rx_priv->is_pcm_enabled)
+		return;
+
 	switch (interp_idx) {
 	case INTERP_HPHL:
 		hph_lut_bypass_reg = LPASS_CDC_RX_TOP_HPHL_COMP_LUT;
@@ -2732,11 +2778,11 @@ static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *compon
 					interp_idx, event);
 			if (rx_priv->hph_hd2_mode)
 				lpass_cdc_rx_macro_hd2_control(
-					component, interp_idx, event);
+					component, rx_priv, interp_idx, event);
 			lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv,
 						    interp_idx, event);
 			lpass_cdc_rx_macro_droop_setting(component,
-						interp_idx, event);
+						rx_priv, interp_idx, event);
 			lpass_cdc_rx_macro_config_compander(component, rx_priv,
 						interp_idx, event);
 			if (interp_idx == INTERP_AUX) {
@@ -2747,6 +2793,14 @@ static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *compon
 			}
 			lpass_cdc_rx_macro_config_classh(component, rx_priv,
 						interp_idx, event);
+			/*select PCM path and swr clk is 9.6MHz*/
+			if (rx_priv->is_pcm_enabled && !rx_priv->is_native_on) {
+				if (rx_priv->pcm_select_users == 0)
+					snd_soc_component_update_bits(component,
+						LPASS_CDC_RX_TOP_SWR_CTRL, 0x02, 0x02);
+				++rx_priv->pcm_select_users;
+			}
+			lpass_cdc_notify_wcd_rx_clk(rx_dev, rx_priv->is_native_on);
 		}
 		rx_priv->main_clk_users[interp_idx]++;
 	}
@@ -2758,6 +2812,16 @@ static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *compon
 			/* Main path PGA mute enable */
 			snd_soc_component_update_bits(component, main_reg,
 					0x10, 0x10);
+			/*Unselect PCM path*/
+			if (rx_priv->is_pcm_enabled && !rx_priv->is_native_on) {
+				if (rx_priv->pcm_select_users == 1)
+					snd_soc_component_update_bits(component,
+						LPASS_CDC_RX_TOP_SWR_CTRL, 0x02, 0x00);
+				--rx_priv->pcm_select_users;
+				if (rx_priv->pcm_select_users < 0)
+					rx_priv->pcm_select_users = 0;
+			}
+
 			/* Clk Disable */
 			snd_soc_component_update_bits(component, dsm_reg,
 						0x01, 0x00);
@@ -2786,8 +2850,8 @@ static int lpass_cdc_rx_macro_enable_interp_clk(struct snd_soc_component *compon
 			lpass_cdc_rx_macro_hphdelay_lutbypass(component, rx_priv,
 						interp_idx, event);
 			if (rx_priv->hph_hd2_mode)
-				lpass_cdc_rx_macro_hd2_control(component, interp_idx,
-						event);
+				lpass_cdc_rx_macro_hd2_control(component,
+					rx_priv, interp_idx, event);
 			lpass_cdc_rx_macro_idle_detect_control(component, rx_priv,
 					interp_idx, event);
 		}
@@ -3670,6 +3734,9 @@ static const struct snd_kcontrol_new lpass_cdc_rx_macro_snd_controls[] = {
 	SOC_SINGLE_EXT("RX_COMP2 Switch", SND_SOC_NOPM, LPASS_CDC_RX_MACRO_COMP2, 1, 0,
 		lpass_cdc_rx_macro_get_compander, lpass_cdc_rx_macro_set_compander),
 
+	SOC_SINGLE_EXT("RX_HPH PCM", SND_SOC_NOPM, 0, 1, 0,
+			lpass_cdc_rx_macro_get_pcm_path, lpass_cdc_rx_macro_put_pcm_path),
+
 	SOC_SINGLE_EXT("RX0 FIR Coeff Num", SND_SOC_NOPM, RX0_PATH,
 			(LPASS_CDC_RX_MACRO_FIR_COEFF_MAX * GRP_MAX), 0,
 			lpass_cdc_rx_macro_fir_coeff_num_get, lpass_cdc_rx_macro_fir_coeff_num_put),

+ 1 - 1
asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -212,7 +212,7 @@ static int lpass_cdc_wsa_macro_enable_vi_decimator(struct snd_soc_component *com
 	.put = lpass_cdc_wsa_macro_set_digital_volume, \
 	.private_value = (unsigned long)&(struct soc_mixer_control) \
 	{.reg = xreg, .rreg = xreg,  \
-	.min = xmin, .max = xmax, .platform_max = xmax, \
+	.min = xmin, .max = xmax, \
 	.sign_bit = 7,} }
 
 struct lpass_cdc_wsa_macro_swr_ctrl_platform_data {

+ 1 - 1
asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c

@@ -212,7 +212,7 @@ static int lpass_cdc_wsa2_macro_enable_vi_decimator(struct snd_soc_component *co
 	.put = lpass_cdc_wsa2_macro_set_digital_volume, \
 	.private_value = (unsigned long)&(struct soc_mixer_control) \
 	{.reg = xreg, .rreg = xreg,  \
-	.min = xmin, .max = xmax, .platform_max = xmax, \
+	.min = xmin, .max = xmax, \
 	.sign_bit = 7,} }
 
 struct lpass_cdc_wsa2_macro_swr_ctrl_platform_data {

+ 37 - 1
asoc/codecs/lpass-cdc/lpass-cdc.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/of_platform.h>
@@ -663,6 +663,7 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
 	if (macro_id == VA_MACRO)
 		priv->macro_params[macro_id].reg_wake_irq =
 						ops->reg_wake_irq;
+	mutex_lock(&priv->macro_lock);
 	priv->num_dais += ops->num_dais;
 	priv->num_macros_registered++;
 	priv->macros_supported[macro_id] = true;
@@ -673,6 +674,7 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
 		ret = lpass_cdc_copy_dais_from_macro(priv);
 		if (ret < 0) {
 			dev_err(dev, "%s: copy_dais failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
 			return ret;
 		}
 		if (priv->macros_supported[TX_MACRO] == false) {
@@ -685,9 +687,11 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
 				priv->lpass_cdc_dais, priv->num_dais);
 		if (ret < 0) {
 			dev_err(dev, "%s: register codec failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
 			return ret;
 		}
 	}
+	mutex_unlock(&priv->macro_lock);
 	return 0;
 }
 EXPORT_SYMBOL(lpass_cdc_register_macro);
@@ -740,6 +744,36 @@ void lpass_cdc_unregister_macro(struct device *dev, u16 macro_id)
 }
 EXPORT_SYMBOL(lpass_cdc_unregister_macro);
 
+void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on)
+{
+	struct lpass_cdc_priv *priv;
+	u32 val;
+
+	if (!dev) {
+		pr_err_ratelimited("%s: dev is null\n", __func__);
+		return;
+	}
+	if (!lpass_cdc_is_valid_child_dev(dev)) {
+		dev_err_ratelimited(dev, "%s: not a valid child dev\n",
+			__func__);
+		return;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err_ratelimited(dev, "%s: priv is null\n", __func__);
+		return;
+	}
+	if (is_native_on)
+		val = 0x2;  /* 11.2896M */
+	else
+		val = 0x0; /* 9.6M */
+
+	lpass_cdc_notifier_call(priv,
+		((val << 16) | LPASS_CDC_WCD_EVT_CLK_NOTIFY));
+
+}
+EXPORT_SYMBOL(lpass_cdc_notify_wcd_rx_clk);
+
 void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb)
 {
 	struct lpass_cdc_priv *priv;
@@ -1323,6 +1357,7 @@ static int lpass_cdc_probe(struct platform_device *pdev)
 	priv->core_audio_vote_count = 0;
 
 	dev_set_drvdata(&pdev->dev, priv);
+	mutex_init(&priv->macro_lock);
 	mutex_init(&priv->io_lock);
 	mutex_init(&priv->clk_lock);
 	mutex_init(&priv->vote_lock);
@@ -1363,6 +1398,7 @@ static int lpass_cdc_remove(struct platform_device *pdev)
 		return -EINVAL;
 
 	of_platform_depopulate(&pdev->dev);
+	mutex_destroy(&priv->macro_lock);
 	mutex_destroy(&priv->io_lock);
 	mutex_destroy(&priv->clk_lock);
 	mutex_destroy(&priv->vote_lock);

+ 6 - 0
asoc/codecs/lpass-cdc/lpass-cdc.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef LPASS_CDC_H
@@ -273,6 +274,7 @@ int lpass_cdc_set_port_map(struct snd_soc_component *component, u32 size, void *
 int lpass_cdc_register_event_listener(struct snd_soc_component *component,
 				   bool enable);
 void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb);
+void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on);
 bool lpass_cdc_check_core_votes(struct device *dev);
 int lpass_cdc_tx_mclk_enable(struct snd_soc_component *c, bool enable);
 int lpass_cdc_get_version(struct device *dev);
@@ -357,6 +359,10 @@ static void lpass_cdc_wsa_pa_on(struct device *dev, bool adie_lb)
 {
 }
 
+static void lpass_cdc_notify_wcd_rx_clk(struct device *dev, bool is_native_on)
+{
+}
+
 static inline bool lpass_cdc_check_core_votes(struct device *dev)
 {
 	return false;

+ 8 - 0
asoc/codecs/wcd-mbhc-v2.c

@@ -1786,6 +1786,14 @@ int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg)
 		}
 	}
 
+	/* Disable moisture detect and duty cycle for WCD USB AATC HS*/
+	if (mbhc_cfg->enable_usbc_analog) {
+		mbhc_cfg->moisture_en = false;
+		mbhc_cfg->moisture_duty_cycle_en = false;
+		pr_debug("%s: Disable moisture detect and duty cycle of AATC",
+			__func__);
+	}
+
 	/* Set btn key code */
 	if ((!mbhc->is_btn_already_regd) && wcd_mbhc_set_keycode(mbhc))
 		pr_err("Set btn key code error!!!\n");

+ 5 - 1
asoc/codecs/wcd937x/wcd937x.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -27,6 +27,7 @@
 #include "wcd937x.h"
 #include "internal.h"
 #include "asoc/bolero-slave-internal.h"
+#include <linux/qti-regmap-debugfs.h>
 
 #define WCD9370_VARIANT 0
 #define WCD9375_VARIANT 5
@@ -2839,6 +2840,9 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
 
 	wcd937x->component = component;
 	snd_soc_component_init_regmap(component, wcd937x->regmap);
+
+	devm_regmap_qti_debugfs_register(&wcd937x->tx_swr_dev->dev, wcd937x->regmap);
+
 	variant = (snd_soc_component_read(
 			component, WCD937X_DIGITAL_EFUSE_REG_0) & 0x1E) >> 1;
 	wcd937x->variant = variant;

+ 24 - 0
asoc/codecs/wcd939x/internal.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _WCD939X_INTERNAL_H
@@ -24,6 +25,18 @@
 #define TX_ADC_MAX 4
 #define SWR_NUM_PORTS	4
 
+enum {
+	RX_CLK_9P6MHZ,
+	RX_CLK_12P288MHZ,
+	RX_CLK_11P2896MHZ,
+};
+
+enum {
+	WCD939X_HPHL,
+	WCD939X_HPHR,
+	WCD939X_HPH_MAX,
+};
+
 enum {
 	TX_HDR12 = 0,
 	TX_HDR34,
@@ -32,6 +45,11 @@ enum {
 
 extern struct regmap_config wcd939x_regmap_config;
 
+struct comp_coeff_val {
+	u8 lsb;
+	u8 msb;
+};
+
 struct codec_port_info {
 	u32 slave_port_type;
 	u32 master_port_type;
@@ -69,6 +87,11 @@ struct wcd939x_priv {
 	/* mbhc module */
 	struct wcd939x_mbhc *mbhc;
 
+	/*compander and xtalk*/
+	int compander_enabled[WCD939X_HPH_MAX];
+	int xtalk_enabled[WCD939X_HPH_MAX];
+	u8 hph_pcm_enabled;
+
 	u32 hph_mode;
 	u32 tx_mode[TX_ADC_MAX];
 	s32 adc_count;
@@ -111,6 +134,7 @@ struct wcd939x_priv {
 	bool dev_up;
 	u8 tx_master_ch_map[WCD939X_MAX_SLAVE_CH_TYPES];
 	bool usbc_hs_status;
+	u8 rx_clk_config;
 	/* wcd to swr dmic notification */
 	bool notify_swr_dmic;
 	struct blocking_notifier_head notifier;

+ 611 - 72
asoc/codecs/wcd939x/wcd939x.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -22,7 +22,6 @@
 #include <asoc/msm-cdc-supply.h>
 #include <bindings/audio-codec-port-types.h>
 #include <linux/qti-regmap-debugfs.h>
-
 #include "wcd939x-registers.h"
 #include "wcd939x.h"
 #include "internal.h"
@@ -45,6 +44,8 @@
 #define ADC_MODE_VAL_ULP2     0x0B
 
 #define NUM_ATTEMPTS 5
+#define COMP_MAX_COEFF 25
+#define HPH_MODE_MAX 4
 
 #define DAPM_MICBIAS1_STANDALONE "MIC BIAS1 Standalone"
 #define DAPM_MICBIAS2_STANDALONE "MIC BIAS2 Standalone"
@@ -66,6 +67,72 @@
 #define REG_FIELD_VALUE(register_name, field_name, value) \
 WCD939X_##register_name, FIELD_MASK(register_name, field_name), \
 value << FIELD_SHIFT(register_name, field_name)
+
+#define WCD939X_COMP_OFFSET \
+		(WCD939X_R_BASE - WCD939X_COMPANDER_HPHL_BASE)
+
+#define WCD939X_XTALK_OFFSET \
+		(WCD939X_HPHR_RX_PATH_SEC0 - WCD939X_HPHL_RX_PATH_SEC0)
+
+static struct comp_coeff_val
+		comp_coeff_table [HPH_MODE_MAX][COMP_MAX_COEFF] = {
+	{
+		{0x40, 0x00},
+		{0x4C, 0x00},
+		{0x5A, 0x00},
+		{0x6B, 0x00},
+		{0x7F, 0x00},
+		{0x97, 0x00},
+		{0xB3, 0x00},
+		{0xD5, 0x00},
+		{0xFD, 0x00},
+		{0x2D, 0x01},
+		{0x66, 0x01},
+		{0xA7, 0x01},
+		{0xF8, 0x01},
+		{0x57, 0x02},
+		{0xC7, 0x02},
+		{0x4B, 0x03},
+		{0xE9, 0x03},
+		{0xA3, 0x04},
+		{0x7D, 0x05},
+		{0x90, 0x06},
+		{0xD1, 0x07},
+		{0x49, 0x09},
+		{0x00, 0x0B},
+		{0x01, 0x0D},
+		{0x59, 0x0F},
+	},
+	{
+	/*HPH_HIFI, HPH_LOHIFI, HPH_LP*/
+		{0x40, 0x00},
+		{0x4C, 0x00},
+		{0x5A, 0x00},
+		{0x6B, 0x00},
+		{0x80, 0x00},
+		{0x98, 0x00},
+		{0xB4, 0x00},
+		{0xD5, 0x00},
+		{0xFE, 0x00},
+		{0x2E, 0x01},
+		{0x66, 0x01},
+		{0xA9, 0x01},
+		{0xF8, 0x01},
+		{0x56, 0x02},
+		{0xC4, 0x02},
+		{0x4F, 0x03},
+		{0xF0, 0x03},
+		{0xAE, 0x04},
+		{0x8B, 0x05},
+		{0x8E, 0x06},
+		{0xBC, 0x07},
+		{0x56, 0x09},
+		{0x0F, 0x0B},
+		{0x13, 0x0D},
+		{0x6F, 0x0F},
+	},
+};
+
 enum {
 	CODEC_TX = 0,
 	CODEC_RX,
@@ -165,6 +232,131 @@ static int wcd939x_handle_post_irq(void *data)
 
 	return IRQ_HANDLED;
 }
+int wcd939x_load_compander_coeff(struct snd_soc_component *component,
+					u16 lsb_reg, u16 msb_reg,
+					struct comp_coeff_val *comp_coeff_table,
+					u16 arr_size)
+{
+	int i = 0;
+
+	/* Load Compander Coeff */
+	for (i = 0; i < arr_size; i++) {
+		snd_soc_component_write(component, lsb_reg,
+			comp_coeff_table[i].lsb);
+		snd_soc_component_write(component, msb_reg,
+			comp_coeff_table[i].msb);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(wcd939x_load_compander_coeff);
+
+
+static int wcd939x_hph_compander_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	int compander = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] = wcd939x->compander_enabled[compander];
+	return 0;
+}
+
+
+static int wcd939x_hph_compander_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	int compander = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+
+	int value = ucontrol->value.integer.value[0];
+
+	if (value < WCD939X_HPH_MAX && value >= 0)
+		wcd939x->compander_enabled[compander] = value;
+	else {
+		dev_err(component->dev, "%s: Invalid comp value = %d\n", __func__, value);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: Compander %d  value %d\n",
+			__func__, wcd939x->compander_enabled[compander], value);
+	return 0;
+}
+
+static int wcd939x_hph_xtalk_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	int xtalk = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+
+	int value = ucontrol->value.integer.value[0];
+
+	if (value < WCD939X_HPH_MAX && value >= 0)
+		wcd939x->xtalk_enabled[xtalk] = value;
+	else {
+		dev_err(component->dev, "%s: Invalid xtalk value = %d\n", __func__, value);
+		return -EINVAL;
+	}
+
+	 dev_dbg(component->dev, "%s: xtalk %d  value %d\n",
+			 __func__, wcd939x->xtalk_enabled[xtalk], value);
+
+	return 0;
+
+}
+
+static int wcd939x_hph_xtalk_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	int xtalk = ((struct soc_multi_mixer_control *)
+			kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] = wcd939x->xtalk_enabled[xtalk];
+
+	return 0;
+}
+
+static int wcd939x_hph_pcm_enable_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	wcd939x->hph_pcm_enabled = ucontrol->value.integer.value[0];
+	dev_dbg(component->dev, "%s: pcm enabled %d \n",
+			 __func__, wcd939x->hph_pcm_enabled);
+	return 0;
+
+}
+
+static int wcd939x_hph_pcm_enable_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+					snd_soc_kcontrol_component(kcontrol);
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	ucontrol->value.integer.value[0] = wcd939x->hph_pcm_enabled;
+
+	return 0;
+}
 
 static int wcd939x_swr_slv_get_current_bank(struct swr_device *dev, u8 devnum)
 {
@@ -238,8 +430,11 @@ static int wcd939x_set_swr_clk_rate(struct snd_soc_component *component,
 static int wcd939x_init_reg(struct snd_soc_component *component)
 {
 
-	snd_soc_component_update_bits(component,
-					REG_FIELD_VALUE(VBG_FINE_ADJ, VBG_FINE_ADJ, 0x04));
+	struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd939x->hph_pcm_enabled)
+		snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(VBG_FINE_ADJ, VBG_FINE_ADJ, 0x04));
 	snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(BIAS, ANALOG_BIAS_EN, 0x01));
 	snd_soc_component_update_bits(component,
@@ -284,6 +479,8 @@ static int wcd939x_init_reg(struct snd_soc_component *component)
 	snd_soc_component_update_bits(component,
 			REG_FIELD_VALUE(HPHLR_SURGE_EN, EN_SURGE_PROTECTION_HPHR, 0x01));
 
+	snd_soc_component_write(component, WCD939X_CFG0, 0x05);
+
 	return 0;
 }
 
@@ -573,6 +770,12 @@ static int wcd939x_rx_clk_enable(struct snd_soc_component *component)
 		snd_soc_component_update_bits(component,
 				REG_FIELD_VALUE(CDC_DIG_CLK_CTL, RXD2_CLK_EN, 0x01));
 
+		if (wcd939x->hph_pcm_enabled) {
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(PA_GAIN_CTL_L, RX_SUPPLY_LEVEL, 0x01));
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(VNEG_CTRL_4, ILIM_SEL, 0x02));
+		}
 	}
 	wcd939x->rx_clk_cnt++;
 
@@ -634,22 +837,288 @@ struct wcd939x_mbhc *wcd939x_soc_get_mbhc(struct snd_soc_component *component)
 }
 EXPORT_SYMBOL(wcd939x_soc_get_mbhc);
 
+static int  wcd939x_config_power_mode(struct snd_soc_component *component,
+				int event, int index, int mode)
+{
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (mode == CLS_H_ULP) {
+			if (index == WCD939X_HPHL) {
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL12, ZONE3_RMS, 0x21));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL13, ZONE4_RMS, 0x30));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL14, ZONE5_RMS, 0x3F));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL15, ZONE6_RMS, 0x48));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL17, PATH_GAIN, 0x0C));
+			} else if (index == WCD939X_HPHR) {
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL12, ZONE3_RMS, 0x21));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL13, ZONE4_RMS, 0x30));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL14, ZONE5_RMS, 0x3F));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL15, ZONE6_RMS, 0x48));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL17, PATH_GAIN, 0x0C));
+			}
+		} else {
+			if (index == WCD939X_HPHL) {
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL12, ZONE3_RMS, 0x1E));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL13, ZONE4_RMS, 0x2A));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL14, ZONE5_RMS, 0x36));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL15, ZONE6_RMS, 0x3C));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(CTL17, PATH_GAIN, 0x00));
+			} else if (index == WCD939X_HPHR) {
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL12, ZONE3_RMS, 0x1E));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL13, ZONE4_RMS, 0x2A));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL14, ZONE5_RMS, 0x36));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL15, ZONE6_RMS, 0x2C));
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(R_CTL17, PATH_GAIN, 0x00));
+			}
+		}
+	}
+	return 0;
+}
+
+static int wcd939x_enable_hph_pcm_index(struct snd_soc_component *component,
+				int event, int hph)
+{
+	struct wcd939x_priv *wcd939x = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: Invalid params, NULL component\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd939x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd939x->hph_pcm_enabled)
+		return 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (hph == WCD939X_HPHL) {
+			if (wcd939x->rx_clk_config == RX_CLK_11P2896MHZ)
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(HPHL_RX_PATH_CFG1,
+					RX_DC_DROOP_COEFF_SEL, 0x2));
+			else if (wcd939x->rx_clk_config == RX_CLK_9P6MHZ)
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(HPHL_RX_PATH_CFG1,
+					RX_DC_DROOP_COEFF_SEL, 0x3));
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPHL_RX_PATH_CFG0,
+				DLY_ZN_EN, 0x1));
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPHL_RX_PATH_CFG0,
+				INT_EN, 0x3));
+		} else if (hph == WCD939X_HPHR) {
+			if (wcd939x->rx_clk_config == RX_CLK_11P2896MHZ)
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(HPHR_RX_PATH_CFG1,
+					RX_DC_DROOP_COEFF_SEL, 0x2));
+			else if (wcd939x->rx_clk_config == RX_CLK_9P6MHZ)
+				snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(HPHR_RX_PATH_CFG1,
+					RX_DC_DROOP_COEFF_SEL, 0x3));
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPHR_RX_PATH_CFG0,
+				DLY_ZN_EN, 0x1));
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPHR_RX_PATH_CFG0,
+				INT_EN, 0x3));
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		break;
+	}
+
+	return 0;
+}
+
+static int wcd939x_config_compander(struct snd_soc_component *component,
+				int event, int compander_indx)
+{
+	u16 comp_coeff_lsb_reg = 0, comp_coeff_msb_reg = 0;
+	u16 comp_ctl7_reg = 0, comp_ctl0_reg  = 0;
+	u16 comp_en_mask_val = 0;
+	struct wcd939x_priv *wcd939x;
+	int hph_mode;
+
+
+	if (compander_indx >= WCD939X_HPH_MAX || compander_indx < 0) {
+		pr_err_ratelimited("%s: Invalid compander value: %d\n",
+				__func__, compander_indx);
+		return -EINVAL;
+	}
+
+	if (!component) {
+		pr_err_ratelimited("%s: Invalid params, NULL component\n", __func__);
+		return -EINVAL;
+	}
+	wcd939x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd939x->compander_enabled[compander_indx])
+		return 0;
+
+	hph_mode = wcd939x->hph_mode;
+	dev_dbg(component->dev, "%s compander_index = %d hph mode = %d\n",
+				__func__, compander_indx, wcd939x->hph_mode);
+
+	if (compander_indx == WCD939X_HPHL) {
+		comp_coeff_lsb_reg = WCD939X_HPHL_COMP_WR_LSB;
+		comp_coeff_msb_reg = WCD939X_HPHL_COMP_WR_MSB;
+		comp_en_mask_val = 1 << 1;
+	} else if (compander_indx == WCD939X_HPHR) {
+		comp_coeff_lsb_reg = WCD939X_HPHR_COMP_WR_LSB;
+		comp_coeff_msb_reg = WCD939X_HPHR_COMP_WR_MSB;
+		comp_en_mask_val = 1 << 0;
+	} else {
+		return 0;
+	}
+
+	comp_ctl0_reg  = WCD939X_CTL0 + (compander_indx * WCD939X_COMP_OFFSET);
+	comp_ctl7_reg = WCD939X_CTL7 + (compander_indx * WCD939X_COMP_OFFSET);
+
+	if (SND_SOC_DAPM_EVENT_ON(event)){
+
+		snd_soc_component_update_bits(component,
+			comp_ctl7_reg, 0x1E, 0x00);
+		/* Enable compander clock*/
+		snd_soc_component_update_bits(component,
+			comp_ctl0_reg , 0x01, 0x01);
+
+			/* 250us sleep required as per HW Sequence */
+			usleep_range(250, 260);
+		snd_soc_component_update_bits(component,
+			comp_ctl0_reg , 0x02, 0x01);
+		snd_soc_component_update_bits(component,
+			comp_ctl0_reg , 0x02, 0x00);
+
+		/* Compander coeff values are same for below modes */
+		if (wcd939x->hph_mode == CLS_H_HIFI || wcd939x->hph_mode == CLS_H_LOHIFI
+				|| wcd939x->hph_mode == CLS_H_LP)
+			hph_mode = 1;
+		else if (wcd939x->hph_mode == CLS_H_ULP)
+			hph_mode = 0;
+
+		wcd939x_load_compander_coeff(component, comp_coeff_lsb_reg,
+				comp_coeff_msb_reg, comp_coeff_table[hph_mode],
+				COMP_MAX_COEFF);
+
+		/* Enable compander*/
+		snd_soc_component_update_bits(component,
+				WCD939X_CDC_COMP_CTL_0, comp_en_mask_val, comp_en_mask_val);
+
+	} if (SND_SOC_DAPM_EVENT_OFF(event)) {
+			snd_soc_component_update_bits(component,
+				WCD939X_CDC_COMP_CTL_0, comp_en_mask_val, 0x00);
+			snd_soc_component_update_bits(component,
+			comp_ctl0_reg , 0x01, 0x00);
+	}
+
+	return 0;
+}
+
+static int wcd939x_config_xtalk(struct snd_soc_component *component,
+					int event, int xtalk_indx)
+{
+	u16 xtalk_sec0 = 0, xtalk_sec1 = 0, xtalk_sec2 = 0, xtalk_sec3 = 0;
+	struct wcd939x_priv *wcd939x = NULL;
+
+	if (!component) {
+		pr_err_ratelimited("%s: Invalid params, NULL component\n", __func__);
+		return -EINVAL;
+	}
+
+	 wcd939x = snd_soc_component_get_drvdata(component);
+
+	if (!wcd939x->xtalk_enabled[xtalk_indx])
+		return 0;
+
+	dev_dbg(component->dev, "%s xtalk_indx = %d event = %d\n",
+					__func__, xtalk_indx, event);
+
+	switch(event) {
+
+	case SND_SOC_DAPM_PRE_PMU:
+
+		xtalk_sec0 = WCD939X_HPHL_RX_PATH_SEC0 + (xtalk_indx * WCD939X_XTALK_OFFSET);
+		xtalk_sec1 = WCD939X_HPHL_RX_PATH_SEC1 + (xtalk_indx * WCD939X_XTALK_OFFSET);
+		xtalk_sec2 = WCD939X_HPHL_RX_PATH_SEC2 + (xtalk_indx * WCD939X_XTALK_OFFSET);
+		xtalk_sec3 = WCD939X_HPHL_RX_PATH_SEC3 + (xtalk_indx * WCD939X_XTALK_OFFSET);
+
+		snd_soc_component_update_bits(component, xtalk_sec1, 0xFF, 0xFE);
+		snd_soc_component_update_bits(component, xtalk_sec0, 0x1F, 0x06);
+		snd_soc_component_update_bits(component, xtalk_sec3, 0xFF, 0x4F);
+		snd_soc_component_update_bits(component, xtalk_sec2, 0x1F, 0x11);
+
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		/* enable xtalk for L and R channels*/
+		snd_soc_component_update_bits(component, WCD939X_RX_PATH_CFG2,
+					0x0F, 0x0F);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		/* Disable Xtalk for L and R channels*/
+		snd_soc_component_update_bits(component, WCD939X_RX_PATH_CFG2,
+				0x00, 0x00);
+		break;
+	}
+
+	return 0;
+}
+
 static int wcd939x_rx_mux(struct snd_soc_dapm_widget *w,
 			struct snd_kcontrol *kcontrol,
 			int event)
 {
 
+	int hph_mode = 0;
+	struct wcd939x_priv *wcd939x = NULL;
 	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 
+	wcd939x = snd_soc_component_get_drvdata(component);
+	hph_mode = wcd939x->hph_mode;
+
+	dev_dbg(component->dev, "%s event: %d wshift: %d wname: %s\n",
+					__func__, event, w->shift, w->name);
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		dev_err(component->dev, "before rx clk enable %s wname: %s event: %d\n", __func__,
-			w->name, event);
 		wcd939x_rx_clk_enable(component);
+		if (wcd939x->hph_pcm_enabled)
+			wcd939x_config_power_mode(component, event, w->shift, hph_mode);
+		wcd939x_config_compander(component, event, w->shift);
+		wcd939x_config_xtalk(component, event, w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		wcd939x_config_xtalk(component, event, w->shift);
+		/*TBD: need to revisit , for both L & R we are updating, but in QCRG only once*/
+		if (wcd939x->hph_pcm_enabled)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(TOP_CFG0, HPH_DAC_RATE_SEL, 0x1));
+		wcd939x_enable_hph_pcm_index(component, event, w->shift);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		dev_err(component->dev, "%s wname: %s event: %d\n", __func__,
-			w->name, event);
+		wcd939x_config_xtalk(component, event, w->shift);
+		wcd939x_config_compander(component, event, w->shift);
 		wcd939x_rx_clk_disable(component);
 		break;
 
@@ -670,37 +1139,42 @@ static int wcd939x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(CDC_DIG_CLK_CTL, RXD0_CLK_EN, 0x01));
+		if (!wcd939x->hph_pcm_enabled)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(RDAC_CLK_CTL1, OPAMP_CHOP_CLK_EN, 0x00));
 		snd_soc_component_update_bits(component,
 				REG_FIELD_VALUE(CDC_HPH_GAIN_CTL, HPHL_RX_EN, 0x01));
-		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(RDAC_CLK_CTL1, OPAMP_CHOP_CLK_EN, 0x00));
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(RDAC_HD2_CTL_L, HD2_RES_DIV_CTL_L, 0x0f));
-		if (wcd939x->comp1_enable) {
-			snd_soc_component_update_bits(component,
+			REG_FIELD_VALUE(RDAC_HD2_CTL_L, HD2_RES_DIV_CTL_L, 0x1D));
+		if (!wcd939x->hph_pcm_enabled) {
+			if (wcd939x->comp1_enable) {
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(CDC_COMP_CTL_0, HPHL_COMP_EN, 0x01));
-
-			/* 5msec compander delay as per HW requirement */
-			if (!wcd939x->comp2_enable ||
-				(snd_soc_component_read(component,
-					WCD939X_CDC_COMP_CTL_0) & 0x01))
-			usleep_range(5000, 5010);
-			snd_soc_component_update_bits(component,
+				 /* 5msec compander delay as per HW requirement */
+				if (!wcd939x->comp2_enable ||
+					(snd_soc_component_read(component,
+						WCD939X_CDC_COMP_CTL_0) & 0x01))
+				usleep_range(5000, 5010);
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(HPH_TIMER1, AUTOCHOP_TIMER_CTL_EN, 0x00));
-		} else {
-			snd_soc_component_update_bits(component,
+			} else {
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(CDC_COMP_CTL_0, HPHL_COMP_EN, 0x00));
-			snd_soc_component_update_bits(component,
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(L_EN, GAIN_SOURCE_SEL, 0x01));
+			}
 		}
+                if (wcd939x->hph_pcm_enabled)
+		    snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPH_TIMER1, AUTOCHOP_TIMER_CTL_EN, 0x00));
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(RDAC_HD2_CTL_L, HD2_RES_DIV_CTL_L, 0x01));
 		snd_soc_component_update_bits(component,
-			REG_FIELD_VALUE(RDAC_HD2_CTL_R, HD2_RES_DIV_CTL_R, 0x01));
+				REG_FIELD_VALUE(CDC_HPH_GAIN_CTL, HPHL_RX_EN, 0x00));
 		break;
 	}
 
@@ -719,36 +1193,39 @@ static int wcd939x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(CDC_DIG_CLK_CTL, RXD1_CLK_EN, 0x01));
+		if (!wcd939x->hph_pcm_enabled)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(RDAC_CLK_CTL1, OPAMP_CHOP_CLK_EN, 0x00));
 		snd_soc_component_update_bits(component,
 				REG_FIELD_VALUE(CDC_HPH_GAIN_CTL, HPHR_RX_EN, 0x01));
-		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(RDAC_CLK_CTL1, OPAMP_CHOP_CLK_EN, 0x00));
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		snd_soc_component_update_bits(component,
-				REG_FIELD_VALUE(RDAC_HD2_CTL_R, HD2_RES_DIV_CTL_R, 0x02));
-		if (wcd939x->comp2_enable) {
-			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(RDAC_HD2_CTL_R, HD2_RES_DIV_CTL_R, 0x1D));
+		if (!wcd939x->hph_pcm_enabled) {
+			if (wcd939x->comp1_enable) {
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(CDC_COMP_CTL_0, HPHR_COMP_EN, 0x01));
-			/* 5msec compander delay as per HW requirement */
-			if (!wcd939x->comp1_enable ||
-				(snd_soc_component_read(component,
-					WCD939X_CDC_COMP_CTL_0) & 0x02))
+				 /* 5msec compander delay as per HW requirement */
+				if (!wcd939x->comp2_enable ||
+					(snd_soc_component_read(component,
+						WCD939X_CDC_COMP_CTL_0) & 0x02))
 				usleep_range(5000, 5010);
-			snd_soc_component_update_bits(component,
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(HPH_TIMER1, AUTOCHOP_TIMER_CTL_EN, 0x00));
-		} else {
-			snd_soc_component_update_bits(component,
+			} else {
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(CDC_COMP_CTL_0, HPHR_COMP_EN, 0x00));
-			snd_soc_component_update_bits(component,
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(R_EN, GAIN_SOURCE_SEL, 0x01));
+			}
 		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+			snd_soc_component_update_bits(component,
+					REG_FIELD_VALUE(RDAC_HD2_CTL_R, HD2_RES_DIV_CTL_R, 0x01));
 		snd_soc_component_update_bits(component,
-			REG_FIELD_VALUE(RDAC_HD2_CTL_R, HD2_RES_DIV_CTL_R, 0x01));
+				REG_FIELD_VALUE(CDC_HPH_GAIN_CTL, HPHR_RX_EN, 0x00));
 		break;
 	}
 
@@ -836,12 +1313,17 @@ static int wcd939x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 		wcd_clsh_set_hph_mode(component, CLS_H_HIFI);
 		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
 		    hph_mode == CLS_H_ULP) {
-			snd_soc_component_update_bits(component,
+			if (!wcd939x->hph_pcm_enabled)
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(REFBUFF_LP_CTL, PREREF_FILT_BYPASS, 0x01));
 		}
 		snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(HPH, HPHR_REF_ENABLE, 0x01));
 		wcd_clsh_set_hph_mode(component, hph_mode);
+		/* update Mode for LOHIFI */
+		if (hph_mode == CLS_H_LOHIFI)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPH, PWR_LEVEL, 0x00));
 		/* 100 usec delay as per HW requirement */
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd939x->status_mask);
@@ -862,7 +1344,8 @@ static int wcd939x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 			if (hph_mode == CLS_H_LP ||
 			    hph_mode == CLS_H_LOHIFI ||
 			    hph_mode == CLS_H_ULP)
-				snd_soc_component_update_bits(component,
+				if (!wcd939x->hph_pcm_enabled)
+					snd_soc_component_update_bits(component,
 						REG_FIELD_VALUE(REFBUFF_LP_CTL, PREREF_FILT_BYPASS, 0x00));
 			clear_bit(HPH_PA_DELAY, &wcd939x->status_mask);
 		}
@@ -876,7 +1359,9 @@ static int wcd939x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 			wcd939x->update_wcd_event(wcd939x->handle,
 						SLV_BOLERO_EVT_RX_MUTE,
 						(WCD_RX2 << 0x10));
-		wcd_enable_irq(&wcd939x->irq_info,
+		/*Enable PDM INT for PDM data path only*/
+		if (!wcd939x->hph_pcm_enabled)
+			wcd_enable_irq(&wcd939x->irq_info,
 					WCD939X_IRQ_HPHR_PDM_WD_INT);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
@@ -971,12 +1456,17 @@ static int wcd939x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 		wcd_clsh_set_hph_mode(component, CLS_H_HIFI);
 		if (hph_mode == CLS_H_LP || hph_mode == CLS_H_LOHIFI ||
 		    hph_mode == CLS_H_ULP) {
-			snd_soc_component_update_bits(component,
+			if (!wcd939x->hph_pcm_enabled)
+				snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(REFBUFF_LP_CTL, PREREF_FILT_BYPASS, 0x01));
 		}
 		snd_soc_component_update_bits(component,
 					REG_FIELD_VALUE(HPH, HPHL_REF_ENABLE, 0x01));
 		wcd_clsh_set_hph_mode(component, hph_mode);
+		/* update Mode for LOHIFI */
+		if (hph_mode == CLS_H_LOHIFI)
+			snd_soc_component_update_bits(component,
+				REG_FIELD_VALUE(HPH, PWR_LEVEL, 0x00));
 		/* 100 usec delay as per HW requirement */
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd939x->status_mask);
@@ -997,8 +1487,9 @@ static int wcd939x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 			if (hph_mode == CLS_H_LP ||
 			    hph_mode == CLS_H_LOHIFI ||
 			    hph_mode == CLS_H_ULP)
-				snd_soc_component_update_bits(component,
-					REG_FIELD_VALUE(REFBUFF_LP_CTL, PREREF_FILT_BYPASS, 0x00));
+				if (!wcd939x->hph_pcm_enabled)
+					snd_soc_component_update_bits(component,
+						REG_FIELD_VALUE(REFBUFF_LP_CTL, PREREF_FILT_BYPASS, 0x00));
 			clear_bit(HPH_PA_DELAY, &wcd939x->status_mask);
 		}
 		snd_soc_component_update_bits(component,
@@ -1011,7 +1502,9 @@ static int wcd939x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 			wcd939x->update_wcd_event(wcd939x->handle,
 						SLV_BOLERO_EVT_RX_MUTE,
 						(WCD_RX1 << 0x10));
-		wcd_enable_irq(&wcd939x->irq_info,
+		/*Enable PDM INT for PDM data path only*/
+		if (!wcd939x->hph_pcm_enabled)
+			wcd_enable_irq(&wcd939x->irq_info,
 					WCD939X_IRQ_HPHL_PDM_WD_INT);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
@@ -1185,14 +1678,22 @@ static int wcd939x_enable_rx1(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		wcd939x_rx_connect_port(component, HPH_L, true);
-		if (wcd939x->comp1_enable)
-			wcd939x_rx_connect_port(component, COMP_L, true);
+		if (wcd939x->hph_pcm_enabled)
+			wcd939x_rx_connect_port(component, HIFI_PCM_L, true);
+		else {
+			wcd939x_rx_connect_port(component, HPH_L, true);
+			if (wcd939x->comp1_enable)
+				wcd939x_rx_connect_port(component, COMP_L, true);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		wcd939x_rx_connect_port(component, HPH_L, false);
-		if (wcd939x->comp1_enable)
-			wcd939x_rx_connect_port(component, COMP_L, false);
+		if (wcd939x->hph_pcm_enabled)
+			wcd939x_rx_connect_port(component, HIFI_PCM_L, false);
+		else {
+			wcd939x_rx_connect_port(component, HPH_L, false);
+			if (wcd939x->comp1_enable)
+				wcd939x_rx_connect_port(component, COMP_L, false);
+		}
 		break;
 	};
 
@@ -1211,14 +1712,22 @@ static int wcd939x_enable_rx2(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		wcd939x_rx_connect_port(component, HPH_R, true);
-		if (wcd939x->comp2_enable)
-			wcd939x_rx_connect_port(component, COMP_R, true);
+		if (wcd939x->hph_pcm_enabled)
+			wcd939x_rx_connect_port(component, HIFI_PCM_R, true);
+		else {
+			wcd939x_rx_connect_port(component, HPH_R, true);
+			if (wcd939x->comp2_enable)
+				wcd939x_rx_connect_port(component, COMP_R, true);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		wcd939x_rx_connect_port(component, HPH_R, false);
-		if (wcd939x->comp2_enable)
-			wcd939x_rx_connect_port(component, COMP_R, false);
+		if (wcd939x->hph_pcm_enabled)
+			wcd939x_rx_connect_port(component, HIFI_PCM_R, false);
+		else {
+			wcd939x_rx_connect_port(component, HPH_R, false);
+			if (wcd939x->comp2_enable)
+				wcd939x_rx_connect_port(component, COMP_R, false);
+		}
 		break;
 	};
 
@@ -2041,6 +2550,7 @@ static int wcd939x_event_notify(struct notifier_block *block,
 {
 	u16 event = (val & 0xffff);
 	int ret = 0;
+	int rx_clk_type;
 	struct wcd939x_priv *wcd939x = dev_get_drvdata((struct device *)data);
 	struct snd_soc_component *component = wcd939x->component;
 	struct wcd_mbhc *mbhc;
@@ -2126,6 +2636,21 @@ static int wcd939x_event_notify(struct notifier_block *block,
 		snd_soc_component_update_bits(component,
 				WCD939X_TOP_CLK_CFG, 0x06,
 				((val >> 0x10) << 0x01));
+
+		rx_clk_type = (val >> 0x10);
+
+		switch(rx_clk_type) {
+		case RX_CLK_12P288MHZ:
+			wcd939x->rx_clk_config = RX_CLK_12P288MHZ;
+			break;
+		case RX_CLK_11P2896MHZ:
+			wcd939x->rx_clk_config = RX_CLK_11P2896MHZ;
+			break;
+		default:
+			wcd939x->rx_clk_config = RX_CLK_9P6MHZ;
+			break;
+		}
+		dev_dbg(component->dev, "%s: rx clk config %d\n", __func__, wcd939x->rx_clk_config);
 		break;
 	default:
 		dev_dbg(component->dev, "%s: invalid event %d\n", __func__, event);
@@ -2970,6 +3495,19 @@ static const struct snd_kcontrol_new wcd939x_snd_controls[] = {
 	SOC_SINGLE_TLV("ADC4 Volume", WCD939X_TX_CH4, 0, 20, 0,
 			analog_gain),
 
+	SOC_SINGLE_EXT("HPHL Compander", SND_SOC_NOPM, WCD939X_HPHL, 1, 0,
+		wcd939x_hph_compander_get, wcd939x_hph_compander_put),
+	SOC_SINGLE_EXT("HPHR Compander", SND_SOC_NOPM, WCD939X_HPHR, 1, 0,
+		wcd939x_hph_compander_get, wcd939x_hph_compander_put),
+
+	SOC_SINGLE_EXT("HPHL XTALK", SND_SOC_NOPM, WCD939X_HPHL, 1, 0,
+		wcd939x_hph_xtalk_get, wcd939x_hph_xtalk_put),
+	SOC_SINGLE_EXT("HPHR XTALK", SND_SOC_NOPM, WCD939X_HPHR, 1, 0,
+		wcd939x_hph_xtalk_get, wcd939x_hph_xtalk_put),
+
+	SOC_SINGLE_EXT("HPH PCM Enable", SND_SOC_NOPM, 0, 1, 0,
+			wcd939x_hph_pcm_enable_get, wcd939x_hph_pcm_enable_put),
+
 	SOC_ENUM_EXT("ADC1 ChMap", tx_master_ch_enum,
 			wcd939x_tx_master_ch_get, wcd939x_tx_master_ch_put),
 	SOC_ENUM_EXT("ADC2 ChMap", tx_master_ch_enum,
@@ -3158,19 +3696,19 @@ static const struct snd_kcontrol_new rx_rdac3_mux =
 static const char * const rx1_mux_text[] = {
 	"ZERO", "RX1 MUX"
 };
-static const struct soc_enum rx_rx1_enum =
+static const struct soc_enum rx1_enum =
 		SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 0, rx1_mux_text);
-static const struct snd_kcontrol_new rx_rx1_mux =
-	SOC_DAPM_ENUM("RX1 MUX Mux", rx_rx1_enum);
+static const struct snd_kcontrol_new rx1_mux =
+	SOC_DAPM_ENUM("RX1 MUX Mux", rx1_enum);
 
 
 static const char * const rx2_mux_text[] = {
 	"ZERO", "RX2 MUX"
 };
-static const struct soc_enum rx_rx2_enum =
+static const struct soc_enum rx2_enum =
 		SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 0, rx2_mux_text);
-static const struct snd_kcontrol_new rx_rx2_mux =
-	SOC_DAPM_ENUM("RX2 MUX Mux", rx_rx2_enum);
+static const struct snd_kcontrol_new rx2_mux =
+	SOC_DAPM_ENUM("RX2 MUX Mux", rx2_enum);
 
 static const struct snd_soc_dapm_widget wcd939x_dapm_widgets[] = {
 
@@ -3401,11 +3939,12 @@ static const struct snd_soc_dapm_widget wcd939x_dapm_widgets[] = {
 
 	SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),
 
-	SND_SOC_DAPM_MUX_E("RX1 MUX", SND_SOC_NOPM,  WCD_RX1, 0, &rx_rx1_mux,
-		wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_MUX_E("RX2 MUX", SND_SOC_NOPM, WCD_RX2, 0, &rx_rx2_mux,
-			wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX1 MUX", SND_SOC_NOPM,  WCD_RX1, 0, &rx1_mux,
+		wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU
+				| SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("RX2 MUX", SND_SOC_NOPM, WCD_RX2, 0, &rx2_mux,
+			wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU
+				| SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0,
 				wcd939x_enable_rx1, SND_SOC_DAPM_PRE_PMU |

+ 5 - 5
asoc/pineapple-port-config.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _PINEAPPLE_PORT_CONFIG
@@ -56,7 +56,7 @@ static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
 	{3,     1,    0,    0xFF, 0xFF, 0xFF, 0xFF, 3,    0,    0x00, 0x00}, /* DSD */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* GPPO */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HAPT */
-	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HIFI */
+	{49,    0,    0,    0,    15,   24,   1,    0,    1,    0x00, 0x01}, /* HIFI */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HPHT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* CMPT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* IPCM */
@@ -65,14 +65,14 @@ static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
 /* Headset + PCM Haptics */
 static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
 	{3,     0,    0,    0xFF, 0xFF, 1,    0xFF, 0xFF, 1,    0x00, 0x00}, /* HPH/EAR */
-	{31,    0,    0,    3,    6,    7,    0,    0xFF, 0,    0x00, 0x02}, /* HPH_CLH */
+	{63,    0,    0,    3,    6,    7,    0,    0xFF, 0,    0x00, 0x02}, /* HPH_CLH */
 	{31,    11,   11,   0xFF, 0xFF, 4,    1,    0xFF, 0,    0x00, 0x02}, /* HPH_CMP */
 	{7,     1,    0,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0,    0x00, 0x00}, /* LO/AUX */
 	{0,     0,    0,    0xFF, 0xFF, 0xFF, 0xFF, 0,    0,    0x00, 0x00}, /* DSD */
 	{0x18F, 0,    0,    0x8,  0x8,  0x0F, 0x00, 0,    0,    0x00, 0x01}, /* PCM_OUT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* GPPO */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HAPT */
-	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HIFI */
+	{49,    0,    0,    0,    15,   24,   1,    0,    1,    0x00, 0x01}, /* HIFI */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HPHT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* CMPT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* IPCM */
@@ -89,7 +89,7 @@ static struct port_params rx_frame_params_44p1KHz[SWR_MSTR_PORT_LEN] = {
 	{0x1FF, 0,    0,    0x8,  0x8,  0x0F, 0,    0,    0,    0x00, 0x01}, /* PCM_OUT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* GPPO */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HAPT */
-	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HIFI */
+	{63,    0,    0,    0,    15,   31,   1,    0,    1,    0x00, 0x01}, /* HIFI */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* HPHT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* CMPT */
 	{0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, /* IPCM */

+ 4 - 1
asoc/pineapple.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023. Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/clk.h>
@@ -213,6 +213,9 @@ static void msm_set_upd_config(struct snd_soc_pcm_runtime *rtd)
 					"wsa-codec.1");
 				return;
 			}
+		} else {
+			pr_err("%s wsa_max_devs are NULL\n", __func__);
+			return;
 		}
 	} else {
 		component = snd_soc_rtdcom_lookup(rtd, WCD939X_DRV_NAME);

+ 19 - 2
dsp/adsp-loader.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2012-2014, 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -137,6 +138,20 @@ load_adsp:
 	{
 		adsp_state = spf_core_is_apm_ready();
 		if (adsp_state == SPF_SUBSYS_DOWN) {
+			if (!priv->adsp_fw_name) {
+				dev_info(&pdev->dev, "%s: Load default ADSP\n",
+					__func__);
+			} else {
+				dev_info(&pdev->dev, "%s: Load ADSP with fw name %s\n",
+					__func__, priv->adsp_fw_name);
+				rc = rproc_set_firmware(priv->pil_h,
+					priv->adsp_fw_name);
+				if (rc) {
+					dev_err(&pdev->dev, "%s: rproc set firmware failed,\n",
+						__func__);
+					goto fail;
+				}
+			}
 			rc = rproc_boot(priv->pil_h);
 			if (rc) {
 				dev_err(&pdev->dev, "%s: pil get failed,\n",
@@ -144,8 +159,8 @@ load_adsp:
 				goto fail;
 			}
 		} else if (adsp_state == SPF_SUBSYS_LOADED) {
-		dev_dbg(&pdev->dev,
-			"%s: ADSP state = %x\n", __func__, adsp_state);
+			dev_dbg(&pdev->dev,
+				"%s: ADSP state = %x\n", __func__, adsp_state);
 		}
 
 		dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
@@ -409,6 +424,8 @@ static int adsp_loader_probe(struct platform_device *pdev)
 		goto wqueue;
 	}
 	memcpy(&adsp_var_idx, buf, len);
+	dev_info(&pdev->dev, "%s: adsp variant fuse reg value: 0x%x\n",
+		__func__, adsp_var_idx);
 	kfree(buf);
 
 	/* Get count of fw images */

+ 4 - 2
dsp/msm_audio_ion.c

@@ -444,11 +444,12 @@ int msm_audio_get_phy_addr(int fd, dma_addr_t *paddr, size_t *pa_len)
 }
 EXPORT_SYMBOL(msm_audio_get_phy_addr);
 
-int msm_audio_set_hyp_assign(int fd, bool assign)
+static int msm_audio_set_hyp_assign(int fd, bool assign)
 {
 	struct msm_audio_fd_data *msm_audio_fd_data = NULL;
 	int status = -EINVAL;
 	pr_debug("%s, fd %d\n", __func__, fd);
+
 	mutex_lock(&(msm_audio_ion_fd_list.list_mutex));
 	list_for_each_entry(msm_audio_fd_data,
 			&msm_audio_ion_fd_list.fd_list, list) {
@@ -577,7 +578,8 @@ static int msm_audio_ion_free(struct dma_buf *dma_buf, struct msm_audio_ion_priv
 	return 0;
 }
 
-int msm_audio_hyp_unassign(struct msm_audio_fd_data *msm_audio_fd_data) {
+static int msm_audio_hyp_unassign(struct msm_audio_fd_data *msm_audio_fd_data)
+{
 	int ret = 0;
 	int dest_perms_unmap[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
 	int source_vm_unmap[3] = {VMID_LPASS, VMID_ADSP_HEAP, VMID_HLOS};

+ 3 - 1
include/bindings/audio-codec-port-types.h

@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */
+/* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.*/
 
 #ifndef __AUDIO_CODEC_PORT_TYPES_H
 #define __AUDIO_CODEC_PORT_TYPES_H
@@ -93,5 +94,6 @@
 #define SWRM_TX3_CH3 56
 #define SWRM_TX3_CH4 57
 #define SWRM_TX_PCM_IN 58
-
+#define HIFI_PCM_L 59
+#define HIFI_PCM_R 60
 #endif /* __AUDIO_CODEC_PORT_TYPES_H */

+ 5 - 17
soc/swr-mstr-ctrl.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/irq.h>
@@ -800,19 +800,9 @@ static int swrm_pcm_port_config(struct swr_mstr_ctrl *swrm, u8 port_num,
 	reg_addr = ((dir) ? SWRM_DIN_DP_PCM_PORT_CTRL(port_num) : \
 			SWRM_DOUT_DP_PCM_PORT_CTRL(port_num));
 	reg_val = enable ? 0x3 : 0x0;
-	if (enable) {
-		if (swrm->pcm_enable_count == 0)
-			swr_master_write(swrm, reg_addr, reg_val);
-		swrm->pcm_enable_count++;
-	} else {
-		if (swrm->pcm_enable_count > 0)
-			swrm->pcm_enable_count--;
-		if (swrm->pcm_enable_count == 0)
-			swr_master_write(swrm, reg_addr, reg_val);
-	}
-	dev_dbg(swrm->dev, "%s : pcm port %s, reg_val = %d, for addr %x, pcm_enable_cnt:%d\n",
-			__func__, enable ? "Enabled" : "disabled", reg_val, reg_addr,
-			swrm->pcm_enable_count);
+	swr_master_write(swrm, reg_addr, reg_val);
+	dev_dbg(swrm->dev, "%s : pcm port %s, reg_val = %d, for addr %x\n",
+			__func__, enable ? "Enabled" : "disabled", reg_val, reg_addr);
 	return 0;
 }
 
@@ -1710,8 +1700,6 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
 		}
 		clear_bit(DISABLE_PENDING, &swrm->port_req_pending);
 		swrm_cleanup_disabled_port_reqs(master);
-		/* reset enable_count to 0 in SSR if master is already down */
-		swrm->pcm_enable_count = 0;
 		if (!swrm_is_port_en(master)) {
 			dev_dbg(&master->dev, "%s: pm_runtime auto suspend triggered\n",
 				__func__);
@@ -2846,7 +2834,7 @@ static int swrm_probe(struct platform_device *pdev)
 		dev_err(swrm->dev, "missing port mapping\n");
 		goto err_pdata_fail;
 	}
-	swrm->pcm_enable_count = 0;
+
 	map_length = map_size / (3 * sizeof(u32));
 	if (num_ports > SWR_MSTR_PORT_LEN) {
 		dev_err(&pdev->dev, "%s:invalid number of swr ports\n",

+ 1 - 1
soc/swr-mstr-ctrl.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _SWR_WCD_CTRL_H
@@ -185,7 +186,6 @@ struct swr_mstr_ctrl {
 	struct clk *lpass_core_hw_vote;
 	struct clk *lpass_core_audio;
 	u8 num_usecase;
-	u32 pcm_enable_count;
 	u32 swr_irq_wakeup_capable;
 	int hw_core_clk_en;
 	int aud_core_clk_en;