Merge "asoc: Add codec entry node for wcd937x to support ADIE RTAC"
diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c
index 51e56df..749f87b 100644
--- a/asoc/codecs/bolero/bolero-cdc.c
+++ b/asoc/codecs/bolero/bolero-cdc.c
@@ -23,6 +23,8 @@
 #include "internal.h"
 
 #define BOLERO_VERSION_1_0 0x0001
+#define BOLERO_VERSION_1_1 0x0002
+#define BOLERO_VERSION_1_2 0x0003
 #define BOLERO_VERSION_ENTRY_SIZE 32
 
 static struct snd_soc_codec_driver bolero;
@@ -412,6 +414,12 @@
 	case BOLERO_VERSION_1_0:
 		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_0\n");
 		break;
+	case BOLERO_VERSION_1_1:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_1\n");
+		break;
+	case BOLERO_VERSION_1_2:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_2\n");
+		break;
 	default:
 		len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
 	}
@@ -499,7 +507,20 @@
 		}
 	}
 	priv->codec = codec;
-	priv->version = BOLERO_VERSION_1_0;
+	/*
+	 * In order for the ADIE RTC to differentiate between targets
+	 * version info is used.
+	 * Assign 1.0 for target with only one macro
+	 * Assign 1.1 for target with two macros
+	 * Assign 1.2 for target with more than two macros
+	 */
+	if (priv->num_macros_registered == 1)
+		priv->version = BOLERO_VERSION_1_0;
+	else if (priv->num_macros_registered == 2)
+		priv->version = BOLERO_VERSION_1_1;
+	else if (priv->num_macros_registered > 2)
+		priv->version = BOLERO_VERSION_1_2;
+
 	dev_dbg(codec->dev, "%s: bolero soc codec probe success\n", __func__);
 err:
 	return ret;
diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c
index ecfe28f..c0af520 100644
--- a/asoc/codecs/bolero/wsa-macro.c
+++ b/asoc/codecs/bolero/wsa-macro.c
@@ -229,6 +229,10 @@
 	"ZERO", "AIF1_PB", "AIF_MIX1_PB"
 };
 
+static const char *const rx_sidetone_mix_text[] = {
+	"ZERO", "SRC0"
+};
+
 static const char * const wsa_macro_ear_spkr_pa_gain_text[] = {
 	"G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
 	"G_4_DB", "G_5_DB", "G_6_DB"
@@ -260,6 +264,9 @@
 	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT0_CFG1,
 		0, 5, rx_mix_text);
 
+static const struct soc_enum rx0_sidetone_mix_enum =
+	SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text);
+
 static const struct snd_kcontrol_new rx0_prim_inp0_mux =
 	SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum);
 
@@ -272,6 +279,9 @@
 static const struct snd_kcontrol_new rx0_mix_mux =
 	SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum);
 
+static const struct snd_kcontrol_new rx0_sidetone_mix_mux =
+	SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum);
+
 /* RX INT1 */
 static const struct soc_enum rx1_prim_inp0_chain_enum =
 	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_INT1_CFG0,
@@ -1825,6 +1835,15 @@
 	SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_MIXER("WSA_RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
 
+	SND_SOC_DAPM_MUX_E("WSA_RX0 INT0 SIDETONE MIX",
+			   BOLERO_CDC_WSA_RX0_RX_PATH_CFG1, 4, 0,
+			   &rx0_sidetone_mix_mux, wsa_macro_enable_swr,
+			  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_INPUT("WSA SRC0_INP"),
+
+	SND_SOC_DAPM_INPUT("WSA_TX DEC0_INP"),
+	SND_SOC_DAPM_INPUT("WSA_TX DEC1_INP"),
+
 	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 INTERP", SND_SOC_NOPM,
 		WSA_MACRO_COMP1, 0, NULL, 0, wsa_macro_enable_interpolator,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
@@ -1889,18 +1908,24 @@
 	{"WSA_RX0 INP0", "RX1", "WSA RX1"},
 	{"WSA_RX0 INP0", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX0 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP0", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP0"},
 
 	{"WSA_RX0 INP1", "RX0", "WSA RX0"},
 	{"WSA_RX0 INP1", "RX1", "WSA RX1"},
 	{"WSA_RX0 INP1", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX0 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP1", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP1"},
 
 	{"WSA_RX0 INP2", "RX0", "WSA RX0"},
 	{"WSA_RX0 INP2", "RX1", "WSA RX1"},
 	{"WSA_RX0 INP2", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX0 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX0 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX0 INP2", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT0 MIX", NULL, "WSA_RX0 INP2"},
 
 	{"WSA_RX0 MIX INP", "RX0", "WSA RX0"},
@@ -1911,6 +1936,8 @@
 
 	{"WSA_RX INT0 SEC MIX", NULL, "WSA_RX INT0 MIX"},
 	{"WSA_RX INT0 INTERP", NULL, "WSA_RX INT0 SEC MIX"},
+	{"WSA_RX0 INT0 SIDETONE MIX", "SRC0", "WSA SRC0_INP"},
+	{"WSA_RX INT0 INTERP", NULL, "WSA_RX0 INT0 SIDETONE MIX"},
 	{"WSA_RX INT0 CHAIN", NULL, "WSA_RX INT0 INTERP"},
 	{"WSA_SPK1 OUT", NULL, "WSA_RX INT0 CHAIN"},
 	{"WSA_SPK1 OUT", NULL, "WSA_MCLK"},
@@ -1919,18 +1946,24 @@
 	{"WSA_RX1 INP0", "RX1", "WSA RX1"},
 	{"WSA_RX1 INP0", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX1 INP0", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP0", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP0", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP0"},
 
 	{"WSA_RX1 INP1", "RX0", "WSA RX0"},
 	{"WSA_RX1 INP1", "RX1", "WSA RX1"},
 	{"WSA_RX1 INP1", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX1 INP1", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP1", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP1", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP1"},
 
 	{"WSA_RX1 INP2", "RX0", "WSA RX0"},
 	{"WSA_RX1 INP2", "RX1", "WSA RX1"},
 	{"WSA_RX1 INP2", "RX_MIX0", "WSA RX_MIX0"},
 	{"WSA_RX1 INP2", "RX_MIX1", "WSA RX_MIX1"},
+	{"WSA_RX1 INP2", "DEC0", "WSA_TX DEC0_INP"},
+	{"WSA_RX1 INP2", "DEC1", "WSA_TX DEC1_INP"},
 	{"WSA_RX INT1 MIX", NULL, "WSA_RX1 INP2"},
 
 	{"WSA_RX1 MIX INP", "RX0", "WSA RX0"},
diff --git a/asoc/codecs/wcd937x/internal.h b/asoc/codecs/wcd937x/internal.h
index f85c7f6..81b1e5d 100644
--- a/asoc/codecs/wcd937x/internal.h
+++ b/asoc/codecs/wcd937x/internal.h
@@ -82,7 +82,9 @@
 struct wcd937x_micbias_setting {
 	u8 ldoh_v;
 	u32 cfilt1_mv;
+	u32 micb1_mv;
 	u32 micb2_mv;
+	u32 micb3_mv;
 	u8 bias1_cfilt_sel;
 };
 
diff --git a/asoc/codecs/wcd937x/wcd937x-mbhc.c b/asoc/codecs/wcd937x/wcd937x-mbhc.c
index 4a2fa61..e547107 100644
--- a/asoc/codecs/wcd937x/wcd937x-mbhc.c
+++ b/asoc/codecs/wcd937x/wcd937x-mbhc.c
@@ -757,7 +757,7 @@
 	/* If moisture_en is already enabled, then skip to plug type
 	 * detection.
 	 */
-	if ((snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2) & 0x0C))
+	if ((snd_soc_read(codec, WCD937X_MBHC_NEW_CTL_2) & 0x0C))
 		goto done;
 
 	wcd937x_mbhc_moisture_detect_en(mbhc, true);
@@ -773,6 +773,8 @@
 static void wcd937x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc,
 						bool enable)
 {
+	struct snd_soc_codec *codec = mbhc->codec;
+
 	snd_soc_update_bits(codec,
 			WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL,
 			0x04, (enable << 2));
diff --git a/asoc/codecs/wcd937x/wcd937x.c b/asoc/codecs/wcd937x/wcd937x.c
index 9e033ca..9ef0045 100644
--- a/asoc/codecs/wcd937x/wcd937x.c
+++ b/asoc/codecs/wcd937x/wcd937x.c
@@ -1807,6 +1807,65 @@
 	return rc;
 }
 
+static int wcd937x_read_of_property_u32(struct device *dev, const char *name,
+					u32 *val)
+{
+	int rc = 0;
+
+	rc = of_property_read_u32(dev->of_node, name, val);
+	if (rc)
+		dev_err(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, name, dev->of_node->full_name);
+
+	return rc;
+}
+
+static void wcd937x_dt_parse_micbias_info(struct device *dev,
+					  struct wcd937x_micbias_setting *mb)
+{
+	u32 prop_val = 0;
+	int rc = 0;
+
+	/* MB1 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias1-mv",
+				    NULL)) {
+		rc = wcd937x_read_of_property_u32(dev,
+						  "qcom,cdc-micbias1-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb1_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias1 DT property not found\n",
+			__func__);
+	}
+
+	/* MB2 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias2-mv",
+				    NULL)) {
+		rc = wcd937x_read_of_property_u32(dev,
+						  "qcom,cdc-micbias2-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb2_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias2 DT property not found\n",
+			__func__);
+	}
+
+	/* MB3 */
+	if (of_find_property(dev->of_node, "qcom,cdc-micbias3-mv",
+				    NULL)) {
+		rc = wcd937x_read_of_property_u32(dev,
+						  "qcom,cdc-micbias3-mv",
+						  &prop_val);
+		if (!rc)
+			mb->micb3_mv = prop_val;
+	} else {
+		dev_info(dev, "%s: Micbias3 DT property not found\n",
+			__func__);
+	}
+}
+
 struct wcd937x_pdata *wcd937x_populate_dt_data(struct device *dev)
 {
 	struct wcd937x_pdata *pdata = NULL;
@@ -1837,6 +1896,7 @@
 
 	pdata->rx_slave = of_parse_phandle(dev->of_node, "qcom,rx-slave", 0);
 	pdata->tx_slave = of_parse_phandle(dev->of_node, "qcom,tx-slave", 0);
+	wcd937x_dt_parse_micbias_info(dev, &pdata->micbias);
 
 	return pdata;
 }
@@ -1858,7 +1918,8 @@
 		dev_err(dev, "%s: Fail to obtain platform data\n", __func__);
 		return -EINVAL;
 	}
-
+	wcd937x->dev = dev;
+	wcd937x->dev->platform_data = pdata;
 	wcd937x->rst_np = pdata->rst_np;
 	ret = msm_cdc_init_supplies(dev, &wcd937x->supplies,
 				    pdata->regulator, pdata->num_supplies);
@@ -1937,7 +1998,7 @@
 	ret = wcd_irq_init(&wcd937x->irq_info, &wcd937x->virq);
 
 	if (ret) {
-		dev_err(wcd937x->dev, "%s: IRQ init failed: %d\n",
+		dev_err(dev, "%s: IRQ init failed: %d\n",
 			__func__, ret);
 		goto err;
 	}
diff --git a/asoc/codecs/wsa881x-temp-sensor.c b/asoc/codecs/wsa881x-temp-sensor.c
index b2ed963..2a1291f 100644
--- a/asoc/codecs/wsa881x-temp-sensor.c
+++ b/asoc/codecs/wsa881x-temp-sensor.c
@@ -80,9 +80,11 @@
 	if (pdata->wsa_temp_reg_read) {
 		ret = pdata->wsa_temp_reg_read(codec, &reg);
 		if (ret) {
-			pr_err("%s: temperature register read failed: %d\n",
-				__func__, ret);
-			return ret;
+			pr_err("%s: temp read failed: %d, current temp: %d\n",
+				__func__, ret, pdata->curr_temp);
+			if (temp)
+				*temp = pdata->curr_temp;
+			return 0;
 		}
 	} else {
 		pr_err("%s: wsa_temp_reg_read is NULL\n", __func__);
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index bb10858..f8567b3 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -17017,6 +17017,9 @@
 	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
 					"VA_CDC_DMA_TX_0")) {
 		*port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_0;
+	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
+					"TX_CDC_DMA_TX_3")) {
+		*port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
 	} else {
 		pr_err("%s: mixer ctl name=%s, could not derive valid port id\n",
 			__func__, kcontrol->id.name);
@@ -17281,6 +17284,36 @@
 		.info	= msm_source_tracking_info,
 		.get	= msm_audio_source_tracking_get,
 	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name	= "Sound Focus Voice Tx TX_CDC_DMA_TX_3",
+		.info	= msm_sound_focus_info,
+		.get	= msm_voice_sound_focus_get,
+		.put	= msm_voice_sound_focus_put,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name	= "Source Tracking Voice Tx TX_CDC_DMA_TX_3",
+		.info	= msm_source_tracking_info,
+		.get	= msm_voice_source_tracking_get,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name	= "Sound Focus Audio Tx TX_CDC_DMA_TX_3",
+		.info	= msm_sound_focus_info,
+		.get	= msm_audio_sound_focus_get,
+		.put	= msm_audio_sound_focus_put,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name	= "Source Tracking Audio Tx TX_CDC_DMA_TX_3",
+		.info	= msm_source_tracking_info,
+		.get	= msm_audio_source_tracking_get,
+	},
 };
 
 static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol,
diff --git a/dsp/codecs/audio_utils_aio.c b/dsp/codecs/audio_utils_aio.c
index 7f332f4..db07d3f 100644
--- a/dsp/codecs/audio_utils_aio.c
+++ b/dsp/codecs/audio_utils_aio.c
@@ -1104,7 +1104,7 @@
 	buf_node->token = ac->session;
 	rc = q6asm_async_write(ac, &param);
 	if (rc < 0)
-		pr_err("%s[%pK]:failed\n", __func__, audio);
+		pr_err_ratelimited("%s[%pK]:failed\n", __func__, audio);
 	return rc;
 }
 
@@ -1157,7 +1157,7 @@
 	buf_node->token = ac->session;
 	rc = q6asm_async_read(ac, &param);
 	if (rc < 0)
-		pr_err("%s[%pK]:failed\n", __func__, audio);
+		pr_err_ratelimited("%s[%pK]:failed\n", __func__, audio);
 	return rc;
 }
 
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index faedfc1..b7d92ad 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -8625,7 +8625,7 @@
 		return -EINVAL;
 	}
 	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+		pr_err_ratelimited("%s: AC APR handle NULL\n", __func__);
 		return -EINVAL;
 	}
 
@@ -8718,7 +8718,7 @@
 		return -EINVAL;
 	}
 	if (ac->apr == NULL) {
-		pr_err("%s: AC APR handle NULL\n", __func__);
+		pr_err_ratelimited("%s: AC APR handle NULL\n", __func__);
 		return -EINVAL;
 	}
 
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 4ce9973..73304fb 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -2225,6 +2225,7 @@
 #define AFE_LINEAR_PCM_DATA_PACKED_60958 0x2
 #define AFE_NON_LINEAR_DATA_PACKED_60958 0x3
 #define AFE_GENERIC_COMPRESSED           0x8
+#define AFE_LINEAR_PCM_DATA_PACKED_16BIT 0X6
 
 /* This param id is used to configure I2S interface */
 #define AFE_PARAM_ID_I2S_CONFIG	0x0001020D