Merge "soc: swr-mstr: Register for wakeup irq after disabling clk"
diff --git a/asoc/codecs/wcd934x/wcd934x.c b/asoc/codecs/wcd934x/wcd934x.c
index e268a73..44f741e 100644
--- a/asoc/codecs/wcd934x/wcd934x.c
+++ b/asoc/codecs/wcd934x/wcd934x.c
@@ -3174,8 +3174,6 @@
 		/* Undo reset for MAD */
 		snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
 				    0x02, 0x00);
-		snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
-					0x04, 0x04);
 	} else {
 		snd_soc_update_bits(codec, WCD934X_SOC_MAD_AUDIO_CTL_2,
 				    0x03, 0x00);
@@ -3185,8 +3183,6 @@
 		/* Turn off MAD clk */
 		snd_soc_update_bits(codec, WCD934X_CPE_SS_MAD_CTL,
 				    0x01, 0x00);
-		snd_soc_update_bits(codec, WCD934X_CODEC_RPM_CLK_MCLK_CFG,
-					0x04, 0x00);
 	}
 done:
 	return rc;
@@ -9416,6 +9412,7 @@
 	{WCD934X_HPH_R_TEST, 0x01, 0x01},
 	{WCD934X_CPE_FLL_CONFIG_CTL_2, 0xFF, 0x20},
 	{WCD934X_MBHC_NEW_CTL_2, 0x0C, 0x00},
+	{WCD934X_CODEC_RPM_CLK_MCLK_CFG, 0x04, 0x04},
 };
 
 static const struct tavil_reg_mask_val tavil_codec_reg_init_1_1_val[] = {
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index fe279fa..83bba1c 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -2704,7 +2704,8 @@
 			break;
 
 	if (i-- == ARRAY_SIZE(lsm_port_text)) {
-		WARN(1, "Invalid id name %s\n", kcontrol->id.name);
+		pr_warn("%s: Invalid id name %s\n", __func__,
+			kcontrol->id.name);
 		return -EINVAL;
 	}
 
@@ -2751,7 +2752,7 @@
 		ucontrol->value.integer.value[0] = MADSWAUDIO;
 	break;
 	default:
-		WARN(1, "Unknown\n");
+		pr_warn("%s: Unknown\n", __func__);
 		return -EINVAL;
 	}
 	return 0;
@@ -2771,7 +2772,8 @@
 			break;
 
 	if (i-- == ARRAY_SIZE(lsm_port_text)) {
-		WARN(1, "Invalid id name %s\n", kcontrol->id.name);
+		pr_warn("%s: Invalid id name %s\n", __func__,
+			kcontrol->id.name);
 		return -EINVAL;
 	}
 
@@ -2793,7 +2795,7 @@
 		mad_type = MAD_SW_AUDIO;
 		break;
 	default:
-		WARN(1, "Unknown\n");
+		pr_warn("%s: Unknown\n", __func__);
 		return -EINVAL;
 	}
 
diff --git a/asoc/sm6150.c b/asoc/sm6150.c
index a3c455b..8bd1d6f 100644
--- a/asoc/sm6150.c
+++ b/asoc/sm6150.c
@@ -22,6 +22,7 @@
 #include <linux/input.h>
 #include <linux/of_device.h>
 #include <linux/pm_qos.h>
+#include <linux/soc/qcom/fsa4480-i2c.h>
 #include <sound/core.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
@@ -202,6 +203,7 @@
 	struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
 	struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
 	bool is_afe_config_done;
+	struct device_node *fsa_handle;
 };
 
 struct msm_asoc_wcd93xx_codec {
@@ -4601,88 +4603,14 @@
 
 static bool msm_usbc_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
 {
-	int value = 0;
-	bool ret = 0;
 	struct snd_soc_card *card = codec->component.card;
-	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct pinctrl_state *en2_pinctrl_active;
-	struct pinctrl_state *en2_pinctrl_sleep;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(card);
 
-	if (!pdata->usbc_en2_gpio_p) {
-		if (active) {
-			/* if active and usbc_en2_gpio undefined, get pin */
-			pdata->usbc_en2_gpio_p = devm_pinctrl_get(card->dev);
-			if (IS_ERR_OR_NULL(pdata->usbc_en2_gpio_p)) {
-				dev_err(card->dev,
-					"%s: Can't get EN2 gpio pinctrl:%ld\n",
-					__func__,
-					PTR_ERR(pdata->usbc_en2_gpio_p));
-				pdata->usbc_en2_gpio_p = NULL;
-				return false;
-			}
-		} else {
-			/* if not active and usbc_en2_gpio undefined, return */
-			return false;
-		}
-	}
-
-	pdata->usbc_en2_gpio = of_get_named_gpio(card->dev->of_node,
-				    "qcom,usbc-analog-en2-gpio", 0);
-	if (!gpio_is_valid(pdata->usbc_en2_gpio)) {
-		dev_err(card->dev, "%s, property %s not in node %s",
-			__func__, "qcom,usbc-analog-en2-gpio",
-			card->dev->of_node->full_name);
+	if (!pdata->fsa_handle)
 		return false;
-	}
 
-	en2_pinctrl_active = pinctrl_lookup_state(
-					pdata->usbc_en2_gpio_p, "aud_active");
-	if (IS_ERR_OR_NULL(en2_pinctrl_active)) {
-		dev_err(card->dev,
-			"%s: Cannot get aud_active pinctrl state:%ld\n",
-			__func__, PTR_ERR(en2_pinctrl_active));
-		ret = false;
-		goto err_lookup_state;
-	}
-
-	en2_pinctrl_sleep = pinctrl_lookup_state(
-					pdata->usbc_en2_gpio_p, "aud_sleep");
-	if (IS_ERR_OR_NULL(en2_pinctrl_sleep)) {
-		dev_err(card->dev,
-			"%s: Cannot get aud_sleep pinctrl state:%ld\n",
-			__func__, PTR_ERR(en2_pinctrl_sleep));
-		ret = false;
-		goto err_lookup_state;
-	}
-
-	/* if active and usbc_en2_gpio_p defined, swap using usbc_en2_gpio_p */
-	if (active) {
-		dev_dbg(codec->dev, "%s: enter\n", __func__);
-		if (pdata->usbc_en2_gpio_p) {
-			value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
-			if (value)
-				pinctrl_select_state(pdata->usbc_en2_gpio_p,
-							en2_pinctrl_sleep);
-			else
-				pinctrl_select_state(pdata->usbc_en2_gpio_p,
-							en2_pinctrl_active);
-		} else if (pdata->usbc_en2_gpio >= 0) {
-			value = gpio_get_value_cansleep(pdata->usbc_en2_gpio);
-			gpio_set_value_cansleep(pdata->usbc_en2_gpio, !value);
-		}
-		pr_debug("%s: swap select switch %d to %d\n", __func__,
-			value, !value);
-		ret = true;
-	} else {
-		/* if not active, release usbc_en2_gpio_p pin */
-		pinctrl_select_state(pdata->usbc_en2_gpio_p,
-					en2_pinctrl_sleep);
-	}
-
-err_lookup_state:
-	devm_pinctrl_put(pdata->usbc_en2_gpio_p);
-	pdata->usbc_en2_gpio_p = NULL;
-	return ret;
+	return fsa4480_switch_event(pdata->fsa_handle, FSA_MIC_GND_SWAP);
 }
 
 static bool msm_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
@@ -8595,6 +8523,18 @@
 			"qcom,us-euro-gpios");
 		wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
 	}
+
+	if (wcd_mbhc_cfg.enable_usbc_analog) {
+		wcd_mbhc_cfg.swap_gnd_mic = msm_usbc_swap_gnd_mic;
+
+		pdata->fsa_handle = of_parse_phandle(pdev->dev.of_node,
+						"fsa4480-i2c-handle", 0);
+		if (!pdata->fsa_handle)
+			dev_err(&pdev->dev,
+				"property %s not detected in node %s\n",
+				"fsa4480-i2c-handle",
+				pdev->dev.of_node->full_name);
+	}
 	/* Parse pinctrl info from devicetree */
 	ret = msm_get_pinctrl(pdev);
 	if (!ret) {
diff --git a/dsp/adsp-loader.c b/dsp/adsp-loader.c
index cc995db..5afd48c 100644
--- a/dsp/adsp-loader.c
+++ b/dsp/adsp-loader.c
@@ -26,12 +26,17 @@
 
 #define Q6_PIL_GET_DELAY_MS 100
 #define BOOT_CMD 1
+#define SSR_RESET_CMD 1
 #define IMAGE_UNLOAD_CMD 0
 
 static ssize_t adsp_boot_store(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	const char *buf, size_t count);
 
+static ssize_t adsp_ssr_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf, size_t count);
+
 struct adsp_loader_private {
 	void *pil_h;
 	struct kobject *boot_adsp_obj;
@@ -41,8 +46,12 @@
 static struct kobj_attribute adsp_boot_attribute =
 	__ATTR(boot, 0220, NULL, adsp_boot_store);
 
+static struct kobj_attribute adsp_ssr_attribute =
+	__ATTR(ssr, 0220, NULL, adsp_ssr_store);
+
 static struct attribute *attrs[] = {
 	&adsp_boot_attribute.attr,
+	&adsp_ssr_attribute.attr,
 	NULL,
 };
 
@@ -151,6 +160,46 @@
 	schedule_work(&adsp_ldr_work);
 }
 
+static ssize_t adsp_ssr_store(struct kobject *kobj,
+	struct kobj_attribute *attr,
+	const char *buf,
+	size_t count)
+{
+	int ssr_command = 0;
+	struct subsys_device *adsp_dev = NULL;
+	struct platform_device *pdev = adsp_private;
+	struct adsp_loader_private *priv = NULL;
+	int rc;
+
+	dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__);
+
+	if (kstrtoint(buf, 10, &ssr_command) < 0)
+		return -EINVAL;
+
+	if (ssr_command != SSR_RESET_CMD)
+		return -EINVAL;
+
+	priv = platform_get_drvdata(pdev);
+	if (!priv)
+		return -EINVAL;
+
+	adsp_dev = (struct subsys_device *)priv->pil_h;
+	if (!adsp_dev)
+		return -EINVAL;
+
+	dev_err(&pdev->dev, "requesting for ADSP restart\n");
+
+	/* subsystem_restart_dev has worker queue to handle */
+	rc = subsystem_restart_dev(adsp_dev);
+	if (rc) {
+		dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
+		return rc;
+	}
+
+	dev_dbg(&pdev->dev, "ADSP restarted\n");
+	return count;
+}
+
 static ssize_t adsp_boot_store(struct kobject *kobj,
 	struct kobj_attribute *attr,
 	const char *buf,
diff --git a/dsp/codecs/audio_utils_aio.c b/dsp/codecs/audio_utils_aio.c
index 298a77d..445bd3f 100644
--- a/dsp/codecs/audio_utils_aio.c
+++ b/dsp/codecs/audio_utils_aio.c
@@ -1181,7 +1181,13 @@
 			kfree(buf_node);
 			return -EINVAL;
 		}
-		extract_meta_out_info(audio, buf_node, 1);
+		ret = extract_meta_out_info(audio, buf_node, 1);
+		if (ret) {
+			pr_debug("%s: extract meta failed with %d\n",
+				  __func__, ret);
+			kfree(buf_node);
+			return ret;
+		}
 		/* Not a EOS buffer */
 		if (!(buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOS_SET)) {
 			spin_lock_irqsave(&audio->dsp_lock, flags);
@@ -1683,7 +1689,7 @@
 	case AUDIO_SET_CONFIG: {
 		struct msm_audio_config config;
 
-		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		pr_debug("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
 		mutex_lock(&audio->lock);
 		if (copy_from_user(&config, (void *)arg, sizeof(config))) {
 			pr_err(
@@ -2010,7 +2016,7 @@
 			mutex_unlock(&audio->lock);
 			break;
 		}
-		pr_err("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
+		pr_debug("%s[%pK]:AUDIO_SET_CONFIG\n", __func__, audio);
 		if (copy_from_user(&config_32, (void *)arg,
 					sizeof(config_32))) {
 			pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
diff --git a/dsp/codecs/audio_utils_aio.h b/dsp/codecs/audio_utils_aio.h
index 1993f60..bd99c36 100644
--- a/dsp/codecs/audio_utils_aio.h
+++ b/dsp/codecs/audio_utils_aio.h
@@ -210,7 +210,7 @@
 int insert_eos_buf(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node);
 
-void extract_meta_out_info(struct q6audio_aio *audio,
+int extract_meta_out_info(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node, int dir);
 
 int audio_aio_open(struct q6audio_aio *audio, struct file *file);
diff --git a/dsp/codecs/q6audio_v2_aio.c b/dsp/codecs/q6audio_v2_aio.c
index 9f76458..973108d 100644
--- a/dsp/codecs/q6audio_v2_aio.c
+++ b/dsp/codecs/q6audio_v2_aio.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -118,19 +118,26 @@
 	}
 }
 
-void extract_meta_out_info(struct q6audio_aio *audio,
+int extract_meta_out_info(struct q6audio_aio *audio,
 		struct audio_aio_buffer_node *buf_node, int dir)
 {
 	struct dec_meta_out *meta_data = buf_node->kvaddr;
 	uint32_t temp;
 
 	if (dir) { /* input buffer - Write */
-		if (audio->buf_cfg.meta_info_enable)
+		if (audio->buf_cfg.meta_info_enable) {
+			if (buf_node->buf.buf_len <
+				sizeof(struct dec_meta_in)) {
+				pr_debug("%s: invalid buf len %d\n",
+					 __func__, buf_node->buf.buf_len);
+				return -EINVAL;
+			}
 			memcpy(&buf_node->meta_info.meta_in,
 			(char *)buf_node->kvaddr, sizeof(struct dec_meta_in));
-		else
+		} else {
 			memset(&buf_node->meta_info.meta_in,
 			0, sizeof(struct dec_meta_in));
+		}
 		pr_debug("%s[%pK]:i/p: msw_ts %d lsw_ts %d nflags 0x%8x\n",
 			__func__, audio,
 			buf_node->meta_info.meta_in.ntimestamp.highpart,
@@ -156,6 +163,7 @@
 			meta_out_dsp[0].nflags,
 		((struct dec_meta_out *)buf_node->kvaddr)->num_of_frames);
 	}
+	return 0;
 }
 
 /* Read buffer from DSP / Handle Ack from DSP */
@@ -165,6 +173,7 @@
 	unsigned long flags;
 	union msm_audio_event_payload event_payload;
 	struct audio_aio_buffer_node *filled_buf;
+	int ret;
 
 	pr_debug("%s\n", __func__);
 
@@ -208,7 +217,7 @@
 				__func__, audio,
 				filled_buf->meta_info.meta_out.num_of_frames,
 				event_payload.aio_buf.data_len);
-			extract_meta_out_info(audio, filled_buf, 0);
+			ret = extract_meta_out_info(audio, filled_buf, 0);
 			audio->eos_rsp = 0;
 		}
 		pr_debug("%s, posting read done to the app here\n", __func__);
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 50cd104..6f46a23 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -3185,8 +3185,22 @@
 			this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id);
 	}
 
-	/* Also send the topology id here: */
 	port_index = afe_get_port_index(port_id);
+
+	if (q6core_get_avcs_api_version_per_service(
+		APRV2_IDS_SERVICE_ID_ADSP_AFE_V) >= AFE_API_VERSION_V4) {
+		/* send VAD configuration if enabled */
+		if (this_afe.vad_cfg[port_index].is_enable) {
+			ret = afe_send_port_vad_cfg_params(port_id);
+			if (ret) {
+				pr_err("%s: afe send VAD config failed %d\n",
+					__func__, ret);
+				goto fail_cmd;
+			}
+		}
+	}
+
+	/* Also send the topology id here: */
 	if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
 		/* One time call: only for first time */
 		afe_send_custom_topology();