Merge "ASoC: wsa881x: Avoid query temp during suspend" into audio-drivers.lnx.3.0
diff --git a/asoc/Kbuild b/asoc/Kbuild
index 893d95b..8c37917 100644
--- a/asoc/Kbuild
+++ b/asoc/Kbuild
@@ -35,7 +35,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/asoc/codecs/Kbuild b/asoc/codecs/Kbuild
index d3789b5..10b8096 100644
--- a/asoc/codecs/Kbuild
+++ b/asoc/codecs/Kbuild
@@ -34,7 +34,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/asoc/codecs/aqt1000/Kbuild b/asoc/codecs/aqt1000/Kbuild
index d870c1d..2b002df 100644
--- a/asoc/codecs/aqt1000/Kbuild
+++ b/asoc/codecs/aqt1000/Kbuild
@@ -28,7 +28,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/asoc/codecs/wcd934x/Kbuild b/asoc/codecs/wcd934x/Kbuild
index 4032611..1287dd7 100644
--- a/asoc/codecs/wcd934x/Kbuild
+++ b/asoc/codecs/wcd934x/Kbuild
@@ -31,7 +31,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sdm670autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/asoc/codecs/wcd9360/Kbuild b/asoc/codecs/wcd9360/Kbuild
index e815e24..5b87cde 100644
--- a/asoc/codecs/wcd9360/Kbuild
+++ b/asoc/codecs/wcd9360/Kbuild
@@ -21,7 +21,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/asoc/codecs/wcd9360/wcd9360.c b/asoc/codecs/wcd9360/wcd9360.c
index cb13e47..075a77f 100644
--- a/asoc/codecs/wcd9360/wcd9360.c
+++ b/asoc/codecs/wcd9360/wcd9360.c
@@ -7122,7 +7122,7 @@
 	return pahu_vote_svs(pahu, vote);
 }
 
-struct wcd_dsp_cdc_cb cdc_cb = {
+static struct wcd_dsp_cdc_cb cdc_cb = {
 	.cdc_clk_en = pahu_codec_internal_rco_ctrl,
 	.cdc_vote_svs = pahu_cdc_vote_svs,
 };
diff --git a/asoc/codecs/wcd9360/wcd9360.h b/asoc/codecs/wcd9360/wcd9360.h
index 2c70a68..04fb76d 100644
--- a/asoc/codecs/wcd9360/wcd9360.h
+++ b/asoc/codecs/wcd9360/wcd9360.h
@@ -127,6 +127,7 @@
 	u8 val;
 };
 
+#if IS_ENABLED(CONFIG_SND_SOC_WCD9360)
 extern void *pahu_get_afe_config(struct snd_soc_codec *codec,
 				  enum afe_config_type config_type);
 extern int pahu_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable);
@@ -138,4 +139,42 @@
 extern int pahu_codec_info_create_codec_entry(
 				struct snd_info_entry *codec_root,
 				struct snd_soc_codec *codec);
+#else
+extern void *pahu_get_afe_config(struct snd_soc_codec *codec,
+				  enum afe_config_type config_type)
+{
+	return NULL;
+}
+extern int pahu_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable)
+{
+	return 0;
+}
+extern int pahu_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable)
+{
+	return 0;
+}
+extern int pahu_set_spkr_mode(struct snd_soc_codec *codec, int mode)
+{
+	return 0;
+}
+extern int pahu_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset)
+{
+	return 0;
+}
+extern void *pahu_get_wcd_dsp_cntl(struct device *dev)
+{
+	return NULL;
+}
+extern int wcd9360_get_micb_vout_ctl_val(u32 micb_mv)
+{
+	return 0;
+}
+extern int pahu_codec_info_create_codec_entry(
+				struct snd_info_entry *codec_root,
+				struct snd_soc_codec *codec)
+{
+	return 0;
+}
+#endif
+
 #endif
diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c
index c00f5c2..6f51236 100644
--- a/asoc/msm-lsm-client.c
+++ b/asoc/msm-lsm-client.c
@@ -79,6 +79,7 @@
 	struct snd_pcm_substream *substream;
 	struct lsm_client *lsm_client;
 	struct snd_lsm_event_status_v3 *event_status;
+	struct snd_lsm_event_status *det_event;
 	spinlock_t event_lock;
 	wait_queue_head_t event_wait;
 	unsigned long event_avail;
@@ -294,6 +295,46 @@
 			payload_size);
 		break;
 
+	case LSM_SESSION_DETECTION_ENGINE_GENERIC_EVENT: {
+		struct snd_lsm_event_status *tmp;
+
+		status = ((uint16_t *)payload)[0];
+		payload_size = ((uint16_t *)payload)[1];
+
+		spin_lock_irqsave(&prtd->event_lock, flags);
+		tmp = krealloc(prtd->det_event,
+			       sizeof(struct snd_lsm_event_status) +
+			       payload_size, GFP_ATOMIC);
+		if (!tmp) {
+			spin_unlock_irqrestore(&prtd->event_lock, flags);
+			dev_err(rtd->dev,
+				"%s: Failed to allocate memory for %s, size = %lu\n",
+				__func__,
+				"LSM_SESSION_DETECTION_ENGINE_GENERIC_EVENT",
+				sizeof(struct snd_lsm_event_status) +
+				payload_size);
+			return;
+		}
+
+		prtd->det_event = tmp;
+		prtd->det_event->status = status;
+		prtd->det_event->payload_size = payload_size;
+		memcpy(prtd->det_event->payload, &((uint8_t *)payload)[4],
+		       payload_size);
+		prtd->event_avail = 1;
+		spin_unlock_irqrestore(&prtd->event_lock, flags);
+		wake_up(&prtd->event_wait);
+
+		if (substream->timer_running)
+			snd_timer_interrupt(substream->timer, 1);
+
+		dev_dbg(rtd->dev,
+			"%s: Generic det event status = %d payload size = %d\n",
+			__func__, prtd->det_event->status,
+			prtd->det_event->payload_size);
+		break;
+	}
+
 	default:
 		break;
 	}
@@ -719,6 +760,46 @@
 	return rc;
 }
 
+static int msm_lsm_set_det_event_type(struct snd_pcm_substream *substream,
+				      struct lsm_params_info *p_info)
+{
+	struct snd_lsm_det_event_type det_event_type;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct lsm_priv *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int rc = 0;
+
+	if (p_info->param_size != sizeof(det_event_type)) {
+		dev_err(rtd->dev,
+			"%s: Invalid param_size %d\n",
+			__func__, p_info->param_size);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	if (copy_from_user(&det_event_type, p_info->param_data,
+			   sizeof(det_event_type))) {
+		dev_err(rtd->dev,
+			"%s: copy_from_user failed, size = %zd\n",
+			__func__, sizeof(det_event_type));
+		rc = -EFAULT;
+		goto done;
+	}
+
+	rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
+				 &det_event_type, LSM_DET_EVENT_TYPE);
+	if (!rc)
+		prtd->lsm_client->event_type = det_event_type.event_type;
+	else
+		dev_err(rtd->dev,
+			"%s: Failed to set detection event type %s, err = %d\n",
+			__func__, (det_event_type.event_type ?
+			"LSM_DET_EVENT_TYPE_GENERIC" :
+			"LSM_DET_EVENT_TYPE_LEGACY"), rc);
+done:
+	return rc;
+}
+
 static int msm_lsm_process_params(struct snd_pcm_substream *substream,
 		struct snd_lsm_module_params *p_data,
 		void *params)
@@ -762,6 +843,9 @@
 		case LSM_POLLING_ENABLE:
 			rc = msm_lsm_set_poll_enable(substream, p_info);
 			break;
+		case LSM_DET_EVENT_TYPE:
+			rc = msm_lsm_set_det_event_type(substream, p_info);
+			break;
 		default:
 			dev_err(rtd->dev,
 				"%s: Invalid param_type %d\n",
@@ -781,6 +865,30 @@
 	return rc;
 }
 
+static int msm_lsm_start_lab_buffer(struct lsm_priv *prtd, uint16_t status)
+{
+	struct lsm_client *lsm_client = prtd->lsm_client;
+	int rc = 0;
+
+	if (lsm_client && lsm_client->lab_enable &&
+	    !lsm_client->lab_started &&
+	    status == LSM_VOICE_WAKEUP_STATUS_DETECTED) {
+		atomic_set(&prtd->read_abort, 0);
+		atomic_set(&prtd->buf_count, 0);
+		prtd->appl_cnt = 0;
+		prtd->dma_write = 0;
+
+		rc = msm_lsm_queue_lab_buffer(prtd, 0);
+		if (rc)
+			pr_err("%s: Queue buffer failed for lab rc = %d\n",
+				__func__, rc);
+		else
+			prtd->lsm_client->lab_started = true;
+	}
+
+	return rc;
+}
+
 static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
 			 unsigned int cmd, void *arg)
 {
@@ -1026,26 +1134,9 @@
 						payload_size);
 				}
 			}
-			if (!rc) {
-				if (prtd->lsm_client->lab_enable
-					&& !prtd->lsm_client->lab_started
-					&& prtd->event_status->status ==
-					LSM_VOICE_WAKEUP_STATUS_DETECTED) {
-					atomic_set(&prtd->read_abort, 0);
-					atomic_set(&prtd->buf_count, 0);
-					prtd->appl_cnt = 0;
-					prtd->dma_write = 0;
-					rc = msm_lsm_queue_lab_buffer(prtd,
-						0);
-					if (rc)
-						dev_err(rtd->dev,
-							"%s: Queue buffer failed for lab rc = %d\n",
-							__func__, rc);
-					else
-						prtd->lsm_client->lab_started
-						= true;
-				}
-			}
+
+			if (!rc)
+				rc = msm_lsm_start_lab_buffer(prtd, status);
 		} else if (xchg) {
 			dev_dbg(rtd->dev, "%s: Wait aborted\n", __func__);
 			rc = 0;
@@ -1053,6 +1144,76 @@
 		break;
 	}
 
+	case SNDRV_LSM_GENERIC_DET_EVENT: {
+		struct snd_lsm_event_status *user = arg;
+		uint16_t status = 0;
+		uint16_t payload_size = 0;
+
+		dev_dbg(rtd->dev,
+			"%s: SNDRV_LSM_GENERIC_DET_EVENT\n", __func__);
+
+		atomic_set(&prtd->event_wait_stop, 0);
+
+		/*
+		 * Release the api lock before wait to allow
+		 * other IOCTLs to be invoked while waiting
+		 * for event
+		 */
+		mutex_unlock(&prtd->lsm_api_lock);
+		rc = wait_event_freezable(prtd->event_wait,
+				(cmpxchg(&prtd->event_avail, 1, 0) ||
+				(xchg = atomic_cmpxchg(&prtd->event_wait_stop,
+							1, 0))));
+		mutex_lock(&prtd->lsm_api_lock);
+
+		dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n",
+			 __func__, rc, xchg);
+
+		if (!rc && !xchg) {
+			dev_dbg(rtd->dev, "%s: %s: New event available %ld\n",
+				__func__, "SNDRV_LSM_GENERIC_DET_EVENT",
+				prtd->event_avail);
+
+			spin_lock_irqsave(&prtd->event_lock, flags);
+
+			if (prtd->det_event) {
+				payload_size = prtd->det_event->payload_size;
+				status = prtd->det_event->status;
+				spin_unlock_irqrestore(&prtd->event_lock,
+						       flags);
+			} else {
+				spin_unlock_irqrestore(&prtd->event_lock,
+						       flags);
+				dev_err(rtd->dev,
+					"%s: %s: prtd->event_status is NULL\n",
+					__func__,
+					"SNDRV_LSM_GENERIC_DET_EVENT");
+				rc = -EINVAL;
+				break;
+			}
+
+			if (user->payload_size < payload_size) {
+				dev_err(rtd->dev,
+					"%s: provided %d bytes isn't enough, needs %d bytes\n",
+					__func__, user->payload_size,
+					payload_size);
+				rc = -ENOMEM;
+				break;
+			}
+			user->status = status;
+			user->payload_size = payload_size;
+			memcpy(user->payload, prtd->det_event->payload,
+			       payload_size);
+
+			rc = msm_lsm_start_lab_buffer(prtd, status);
+		} else if (xchg) {
+			dev_dbg(rtd->dev, "%s: %s: Wait aborted\n",
+				__func__, "SNDRV_LSM_GENERIC_DET_EVENT");
+			rc = 0;
+		}
+		break;
+	}
+
 	case SNDRV_LSM_ABORT_EVENT:
 		dev_dbg(rtd->dev, "%s: Aborting event status wait\n",
 			__func__);
@@ -1211,6 +1372,28 @@
 
 	return rc;
 }
+
+static int msm_lsm_check_event_type(struct lsm_client *lsm_client,
+				    unsigned int cmd)
+{
+	int err = 0;
+	uint32_t event_type = lsm_client->event_type;
+
+	if (cmd == SNDRV_LSM_EVENT_STATUS &&
+	    event_type != LSM_DET_EVENT_TYPE_LEGACY) {
+		pr_err("%s: %s: Invalid event request\n",
+		       __func__, "SNDRV_LSM_EVENT_STATUS");
+		err = -EINVAL;
+	} else if (cmd == SNDRV_LSM_GENERIC_DET_EVENT &&
+		   event_type != LSM_DET_EVENT_TYPE_GENERIC) {
+		pr_err("%s: %s: Invalid event request\n",
+		       __func__, "SNDRV_LSM_GENERIC_DET_EVENT");
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
 #ifdef CONFIG_COMPAT
 
 struct snd_lsm_event_status32 {
@@ -1292,20 +1475,34 @@
 	mutex_lock(&prtd->lsm_api_lock);
 
 	switch (cmd) {
-	case SNDRV_LSM_EVENT_STATUS: {
-		struct snd_lsm_event_status *user = NULL, userarg32;
-		struct snd_lsm_event_status *user32 = NULL;
+	case SNDRV_LSM_EVENT_STATUS:
+	case SNDRV_LSM_GENERIC_DET_EVENT: {
+		struct snd_lsm_event_status userarg32, *user32 = NULL;
+		struct snd_lsm_event_status *user = NULL;
+
+		dev_dbg(rtd->dev,
+			"%s: %s\n", __func__,
+			(cmd == SNDRV_LSM_EVENT_STATUS) ?
+			"SNDRV_LSM_EVENT_STATUS" :
+			"SNDRV_LSM_GENERIC_DET_EVENT");
+
+		err = msm_lsm_check_event_type(prtd->lsm_client, cmd);
+		if (err)
+			goto done;
 
 		if (copy_from_user(&userarg32, arg, sizeof(userarg32))) {
-			dev_err(rtd->dev, "%s: err copyuser ioctl %s\n",
-				__func__, "SNDRV_LSM_EVENT_STATUS");
+			dev_err(rtd->dev, "%s: %s: Failed to copy from user\n",
+				__func__, (cmd == SNDRV_LSM_EVENT_STATUS) ?
+				"SNDRV_LSM_EVENT_STATUS" :
+				"SNDRV_LSM_GENERIC_DET_EVENT");
 			err = -EFAULT;
 			goto done;
 		}
 
 		if (userarg32.payload_size >
 		    LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
-			pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
+			dev_err(rtd->dev,
+				"%s: payload_size %d is invalid, max allowed = %d\n",
 				__func__, userarg32.payload_size,
 				LISTEN_MAX_STATUS_PAYLOAD_SIZE);
 			err = -EINVAL;
@@ -1315,49 +1512,50 @@
 		size = sizeof(*user) + userarg32.payload_size;
 		user = kzalloc(size, GFP_KERNEL);
 		if (!user) {
-			dev_err(rtd->dev,
-				"%s: Allocation failed event status size %d\n",
-				__func__, size);
-			err = -EFAULT;
+			err = -ENOMEM;
 			goto done;
-		} else {
-			cmd = SNDRV_LSM_EVENT_STATUS;
-			user->payload_size = userarg32.payload_size;
-			err = msm_lsm_ioctl_shared(substream, cmd, user);
+		}
+
+		user->payload_size = userarg32.payload_size;
+		err = msm_lsm_ioctl_shared(substream, cmd, user);
+		if (err) {
+			dev_err(rtd->dev,
+				"%s: msm_lsm_ioctl_shared() failed, err = %d",
+				__func__, err);
+			kfree(user);
+			goto done;
 		}
 
 		/* Update size with actual payload size */
 		size = sizeof(userarg32) + user->payload_size;
-		if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
+		if (!access_ok(VERIFY_WRITE, arg, size)) {
 			dev_err(rtd->dev,
-				"%s: write verify failed size %d\n",
+				"%s: Failed to verify write, size = %d\n",
 				__func__, size);
 			err = -EFAULT;
+			kfree(user);
+			goto done;
 		}
-		if (!err) {
-			user32 = kzalloc(size, GFP_KERNEL);
-			if (!user32) {
-				dev_err(rtd->dev,
-					"%s: Allocation event user status size %d\n",
-					__func__, size);
-				err = -EFAULT;
-			} else {
-				user32->status = user->status;
-				user32->payload_size = user->payload_size;
-				memcpy(user32->payload,
-				user->payload, user32->payload_size);
-			}
+
+		user32 = kzalloc(size, GFP_KERNEL);
+		if (!user32) {
+			err = -ENOMEM;
+			kfree(user);
+			goto done;
 		}
-		if (!err && (copy_to_user(arg, user32, size))) {
-			dev_err(rtd->dev, "%s: failed to copy payload %d",
+		user32->status = user->status;
+		user32->payload_size = user->payload_size;
+		memcpy(user32->payload, user->payload,
+		       user32->payload_size);
+
+		if (copy_to_user(arg, user32, size)) {
+			dev_err(rtd->dev,
+				"%s: Failed to copy payload to user, size = %d",
 				__func__, size);
 			err = -EFAULT;
 		}
 		kfree(user);
 		kfree(user32);
-		if (err)
-			dev_err(rtd->dev, "%s: lsmevent failed %d",
-				__func__, err);
 		break;
 	}
 
@@ -1365,10 +1563,19 @@
 		struct snd_lsm_event_status_v3_32 userarg32, *user32 = NULL;
 		struct snd_lsm_event_status_v3 *user = NULL;
 
+		if (prtd->lsm_client->event_type !=
+		    LSM_DET_EVENT_TYPE_LEGACY) {
+			dev_err(rtd->dev,
+				"%s: %s: Invalid event request\n",
+				__func__, "SNDRV_LSM_EVENT_STATUS_V3_32");
+			err = -EINVAL;
+			goto done;
+		}
+
 		if (copy_from_user(&userarg32, arg, sizeof(userarg32))) {
 			dev_err(rtd->dev, "%s: err copyuser ioctl %s\n",
 				__func__, "SNDRV_LSM_EVENT_STATUS_V3_32");
-			err = -EINVAL;
+			err = -EFAULT;
 			goto done;
 		}
 
@@ -1789,22 +1996,35 @@
 		break;
 	}
 
-	case SNDRV_LSM_EVENT_STATUS: {
-		struct snd_lsm_event_status *user = NULL, userarg;
+	case SNDRV_LSM_EVENT_STATUS:
+	case SNDRV_LSM_GENERIC_DET_EVENT: {
+		struct snd_lsm_event_status *user = NULL;
+		struct snd_lsm_event_status userarg;
 
 		dev_dbg(rtd->dev,
-			"%s: SNDRV_LSM_EVENT_STATUS\n", __func__);
+			"%s: %s\n", __func__,
+			(cmd == SNDRV_LSM_EVENT_STATUS) ?
+			"SNDRV_LSM_EVENT_STATUS" :
+			"SNDRV_LSM_GENERIC_DET_EVENT");
+
+		err = msm_lsm_check_event_type(prtd->lsm_client, cmd);
+		if (err)
+			goto done;
+
 		if (copy_from_user(&userarg, arg, sizeof(userarg))) {
 			dev_err(rtd->dev,
-				"%s: err copyuser event_status\n",
-				__func__);
+				"%s: %s: Copy from user failed\n", __func__,
+				(cmd == SNDRV_LSM_EVENT_STATUS) ?
+				"SNDRV_LSM_EVENT_STATUS" :
+				"SNDRV_LSM_GENERIC_DET_EVENT");
 			err = -EFAULT;
 			goto done;
 		}
 
 		if (userarg.payload_size >
 		    LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
-			pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
+			dev_err(rtd->dev,
+				"%s: payload_size %d is invalid, max allowed = %d\n",
 				__func__, userarg.payload_size,
 				LISTEN_MAX_STATUS_PAYLOAD_SIZE);
 			err = -EINVAL;
@@ -1812,37 +2032,40 @@
 		}
 
 		size = sizeof(struct snd_lsm_event_status) +
-		userarg.payload_size;
+			userarg.payload_size;
 		user = kzalloc(size, GFP_KERNEL);
 		if (!user) {
-			dev_err(rtd->dev,
-				"%s: Allocation failed event status size %d\n",
-				__func__, size);
-			err = -EFAULT;
+			err = -ENOMEM;
 			goto done;
 		}
+
 		user->payload_size = userarg.payload_size;
 		err = msm_lsm_ioctl_shared(substream, cmd, user);
+		if (err) {
+			dev_err(rtd->dev,
+				"%s: msm_lsm_ioctl_shared() failed, err = %d",
+				__func__, err);
+			kfree(user);
+			goto done;
+		}
 
 		/* Update size with actual payload size */
 		size = sizeof(*user) + user->payload_size;
-		if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
+		if (!access_ok(VERIFY_WRITE, arg, size)) {
 			dev_err(rtd->dev,
-				"%s: write verify failed size %d\n",
+				"%s: Failed to verify write, size = %d\n",
 				__func__, size);
 			err = -EFAULT;
 		}
-		if (!err && (copy_to_user(arg, user, size))) {
+		if (!err && copy_to_user(arg, user, size)) {
 			dev_err(rtd->dev,
-				"%s: failed to copy payload %d",
+				"%s: Failed to copy payload to user, size = %d\n",
 				__func__, size);
 			err = -EFAULT;
 		}
+
 		kfree(user);
-		if (err)
-			dev_err(rtd->dev,
-				"%s: lsmevent failed %d", __func__, err);
-		goto done;
+		break;
 	}
 
 	case SNDRV_LSM_EVENT_STATUS_V3: {
@@ -1851,6 +2074,16 @@
 
 		dev_dbg(rtd->dev,
 			"%s: SNDRV_LSM_EVENT_STATUS_V3\n", __func__);
+
+		if (prtd->lsm_client->event_type !=
+		    LSM_DET_EVENT_TYPE_LEGACY) {
+			dev_err(rtd->dev,
+				"%s: %s: Invalid event request\n",
+				__func__, "SNDRV_LSM_EVENT_STATUS_V3");
+			err = -EINVAL;
+			goto done;
+		}
+
 		if (!arg) {
 			dev_err(rtd->dev,
 				"%s: Invalid params event_status_v3\n",
@@ -1983,6 +2216,7 @@
 	prtd->lsm_client->poll_enable = true;
 	prtd->lsm_client->perf_mode = 0;
 	prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE;
+	prtd->lsm_client->event_type = LSM_DET_EVENT_TYPE_LEGACY;
 
 	return 0;
 }
@@ -2090,6 +2324,8 @@
 	spin_lock_irqsave(&prtd->event_lock, flags);
 	kfree(prtd->event_status);
 	prtd->event_status = NULL;
+	kfree(prtd->det_event);
+	prtd->det_event = NULL;
 	spin_unlock_irqrestore(&prtd->event_lock, flags);
 	mutex_destroy(&prtd->lsm_api_lock);
 	kfree(prtd);
diff --git a/dsp/Kbuild b/dsp/Kbuild
index e75dbd1..f225732 100644
--- a/dsp/Kbuild
+++ b/dsp/Kbuild
@@ -29,7 +29,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sdm670autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/dsp/codecs/Kbuild b/dsp/codecs/Kbuild
index 67ac30c..bdcc9dc 100644
--- a/dsp/codecs/Kbuild
+++ b/dsp/codecs/Kbuild
@@ -30,7 +30,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sdm670autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index 3d87a8d..46996d4 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -1905,6 +1905,32 @@
 				__func__, rc);
 		break;
 	}
+
+	case LSM_DET_EVENT_TYPE: {
+		struct lsm_param_det_event_type det_event_type;
+		struct snd_lsm_det_event_type *det_event_data =
+					(struct snd_lsm_det_event_type *)data;
+
+		param_info.module_id = p_info->module_id;
+		param_info.instance_id = INSTANCE_ID_0;
+		param_info.param_id = p_info->param_id;
+		param_info.param_size = sizeof(det_event_type);
+
+		memset(&det_event_type, 0, sizeof(det_event_type));
+
+		det_event_type.minor_version = QLSM_PARAM_ID_MINOR_VERSION;
+		det_event_type.event_type = det_event_data->event_type;
+		det_event_type.mode = det_event_data->mode;
+
+		rc = q6lsm_pack_and_set_params(client, &param_info,
+					       (uint8_t *)&det_event_type,
+					       LSM_SESSION_CMD_SET_PARAMS_V2);
+		if (rc)
+			pr_err("%s: DET_EVENT_TYPE cmd failed, rc %d\n",
+				 __func__, rc);
+		break;
+	}
+
 	default:
 		pr_err("%s: wrong param_type 0x%x\n",
 			__func__, p_info->param_type);
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 0d454c7..767c1a1 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -9674,6 +9674,7 @@
 #define LSM_DATA_EVENT_READ_DONE			(0x00012B02)
 #define LSM_DATA_EVENT_STATUS				(0x00012B03)
 #define LSM_SESSION_EVENT_DETECTION_STATUS_V3		(0x00012B04)
+#define LSM_SESSION_DETECTION_ENGINE_GENERIC_EVENT	(0x00012B06)
 
 #define LSM_MODULE_ID_VOICE_WAKEUP			(0x00012C00)
 #define LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD		(0x00012C01)
diff --git a/include/dsp/q6lsm.h b/include/dsp/q6lsm.h
index 73168d1..05cc350 100644
--- a/include/dsp/q6lsm.h
+++ b/include/dsp/q6lsm.h
@@ -88,6 +88,7 @@
 	bool		poll_enable;
 	int		perf_mode;
 	uint32_t	event_mode;
+	uint32_t	event_type;
 };
 
 struct lsm_stream_cmd_open_tx {
@@ -212,6 +213,12 @@
 	uint32_t flags;
 } __packed;
 
+struct lsm_param_det_event_type {
+	uint32_t minor_version;
+	uint32_t event_type;
+	uint32_t mode;
+} __packed;
+
 struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv);
 void q6lsm_client_free(struct lsm_client *client);
 int q6lsm_open(struct lsm_client *client, uint16_t app_id);
diff --git a/include/uapi/sound/lsm_params.h b/include/uapi/sound/lsm_params.h
index 9ca5930..67dc36f 100644
--- a/include/uapi/sound/lsm_params.h
+++ b/include/uapi/sound/lsm_params.h
@@ -29,11 +29,15 @@
 #define LSM_DEREG_SND_MODEL (5)
 #define LSM_CUSTOM_PARAMS (6)
 #define LSM_POLLING_ENABLE (7)
-#define LSM_PARAMS_MAX (LSM_POLLING_ENABLE + 1)
+#define LSM_DET_EVENT_TYPE (8)
+#define LSM_PARAMS_MAX (LSM_DET_EVENT_TYPE + 1)
 
 #define LSM_EVENT_NON_TIME_STAMP_MODE (0)
 #define LSM_EVENT_TIME_STAMP_MODE (1)
 
+#define LSM_DET_EVENT_TYPE_LEGACY (0)
+#define LSM_DET_EVENT_TYPE_GENERIC (1)
+
 enum lsm_app_id {
 	LSM_VOICE_WAKEUP_APP_ID = 1,
 	LSM_VOICE_WAKEUP_APP_ID_V2 = 2,
@@ -87,6 +91,15 @@
 	bool poll_en;
 };
 
+/*
+ * Data for LSM_DET_EVENT_TYPE param_type
+ * @event_type: LSM_DET_EVENT_TYPE_LEGACY or LSM_DET_EVENT_TYPE_GENERIC
+ * @mode: Type of information in detection event payload
+ */
+struct snd_lsm_det_event_type {
+	__u32 event_type;
+	__u32 mode;
+};
 
 struct snd_lsm_sound_model_v2 {
 	__u8 __user *data;
@@ -196,5 +209,6 @@
 #define SNDRV_LSM_SET_FWK_MODE_CONFIG	_IOW('U', 0x0E, uint32_t)
 #define SNDRV_LSM_EVENT_STATUS_V3	_IOW('U', 0x0F, \
 					struct snd_lsm_event_status_v3)
+#define SNDRV_LSM_GENERIC_DET_EVENT	_IOW('U', 0x10, struct snd_lsm_event_status)
 
 #endif
diff --git a/ipc/Kbuild b/ipc/Kbuild
index afcb967..a860a75 100644
--- a/ipc/Kbuild
+++ b/ipc/Kbuild
@@ -19,6 +19,9 @@
 ifeq ($(CONFIG_ARCH_SM8150), y)
 	TARGET_KERNEL_VERSION := 4.14
 endif
+ifeq ($(CONFIG_ARCH_SM6150), y)
+        TARGET_KERNEL_VERSION := 4.14
+endif
 
 ifeq ($(CONFIG_ARCH_SDMSHRIKE), y)
 	TARGET_KERNEL_VERSION := 4.14
@@ -46,6 +49,11 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sdm670autoconf.h
 	endif
+        ifeq ($(CONFIG_ARCH_SM6150), y)
+                include $(AUDIO_ROOT)/config/sm8150auto.conf
+                export
+                INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
+        endif
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
diff --git a/ipc/apr.c b/ipc/apr.c
index 3f07f6e..a8ff363 100644
--- a/ipc/apr.c
+++ b/ipc/apr.c
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/ipc_logging.h>
+#include <linux/of_platform.h>
 #include <soc/qcom/subsystem_restart.h>
 #include <soc/qcom/scm.h>
 #include <dsp/apr_audio-v2.h>
@@ -62,8 +63,6 @@
 	spinlock_t apr_lock;
 	bool is_initial_boot;
 	struct work_struct add_chld_dev_work;
-	spinlock_t apr_chld_lock;
-	struct list_head apr_chlds;
 };
 
 static struct apr_private *apr_priv;
@@ -290,7 +289,7 @@
 
 static void apr_adsp_down(unsigned long opcode)
 {
-	pr_debug("%s: Q6 is Down\n", __func__);
+	pr_info("%s: Q6 is Down\n", __func__);
 	apr_set_q6_state(APR_SUBSYS_DOWN);
 	dispatch_event(opcode, APR_DEST_QDSP6);
 }
@@ -298,49 +297,17 @@
 static void apr_add_child_devices(struct work_struct *work)
 {
 	int ret;
-	struct device_node *node;
-	struct platform_device *pdev;
-	struct apr_chld_device *apr_chld_dev;
 
-	for_each_child_of_node(apr_priv->dev->of_node, node) {
-		apr_chld_dev = kzalloc(sizeof(*apr_chld_dev), GFP_KERNEL);
-		if (!apr_chld_dev)
-			continue;
-		pdev = platform_device_alloc(node->name, -1);
-		if (!pdev) {
-			dev_err(apr_priv->dev,
-				"%s: pdev memory alloc failed for %s\n",
-				__func__, node->name);
-			kfree(apr_chld_dev);
-			continue;
-		}
-		pdev->dev.parent = apr_priv->dev;
-		pdev->dev.of_node = node;
-
-		ret = platform_device_add(pdev);
-		if (ret) {
-			dev_err(apr_priv->dev,
-				"%s: Cannot add platform device %s\n",
-				__func__, node->name);
-			platform_device_put(pdev);
-			kfree(apr_chld_dev);
-			continue;
-		}
-
-		apr_chld_dev->pdev = pdev;
-
-		spin_lock(&apr_priv->apr_chld_lock);
-		list_add_tail(&apr_chld_dev->node, &apr_priv->apr_chlds);
-		spin_unlock(&apr_priv->apr_chld_lock);
-
-		dev_dbg(apr_priv->dev, "%s: Added APR child dev: %s\n",
-			 __func__, dev_name(&pdev->dev));
-	}
+	ret = of_platform_populate(apr_priv->dev->of_node,
+			NULL, NULL, apr_priv->dev);
+	if (ret)
+		dev_err(apr_priv->dev, "%s: failed to add child nodes, ret=%d\n",
+			__func__, ret);
 }
 
 static void apr_adsp_up(void)
 {
-	pr_debug("%s: Q6 is Up\n", __func__);
+	pr_info("%s: Q6 is Up\n", __func__);
 	if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN, APR_SUBSYS_LOADED) ==
 							APR_SUBSYS_DOWN)
 		wake_up(&dsp_wait);
@@ -1165,6 +1132,7 @@
 {
 	int i, j, k;
 
+	of_platform_depopulate(apr_priv->dev);
 	subsys_notif_deregister("apr_modem");
 	subsys_notif_deregister("apr_adsp");
 	if (apr_reset_workqueue) {
@@ -1179,6 +1147,7 @@
 				mutex_destroy(&client[i][j].svc[k].m_lock);
 		}
 	}
+	debugfs_remove(debugfs_apr_debug);
 }
 
 static int apr_probe(struct platform_device *pdev)
@@ -1194,8 +1163,6 @@
 
 	apr_priv->dev = &pdev->dev;
 	spin_lock_init(&apr_priv->apr_lock);
-	spin_lock_init(&apr_priv->apr_chld_lock);
-	INIT_LIST_HEAD(&apr_priv->apr_chlds);
 	INIT_WORK(&apr_priv->add_chld_dev_work, apr_add_child_devices);
 
 	for (i = 0; i < APR_DEST_MAX; i++)
@@ -1233,17 +1200,8 @@
 
 static int apr_remove(struct platform_device *pdev)
 {
-	struct apr_chld_device *chld, *tmp;
-
 	apr_cleanup();
 	apr_tal_exit();
-	spin_lock(&apr_priv->apr_chld_lock);
-	list_for_each_entry_safe(chld, tmp, &apr_priv->apr_chlds, node) {
-		platform_device_unregister(chld->pdev);
-		list_del(&chld->node);
-		kfree(chld);
-	}
-	spin_unlock(&apr_priv->apr_chld_lock);
 	apr_priv = NULL;
 	return 0;
 }
diff --git a/soc/Kbuild b/soc/Kbuild
index 5ea1093..3aaa388 100644
--- a/soc/Kbuild
+++ b/soc/Kbuild
@@ -34,7 +34,7 @@
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 	endif
-	ifeq ($(CONFIG_ARCH_SDM640), y)
+	ifeq ($(CONFIG_ARCH_SM6150), y)
 		include $(AUDIO_ROOT)/config/sm8150auto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h