Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61806f1d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm-cpe-lsm: Add support for openCPE"

parents cf4f4c7a 493f6fe4
Loading
Loading
Loading
Loading
+62 −17
Original line number Diff line number Diff line
@@ -57,9 +57,14 @@
#define CPE_LSM_SESSION_CMDRSP_SHARED_MEM_ALLOC (0x2009)
#define CPE_LSM_SESSION_CMD_SHARED_MEM_DEALLOC	(0x200A)
#define CPE_LSM_SESSION_CMD_TX_BUFF_OUTPUT_CONFIG (0x200f)
#define CPE_LSM_SESSION_CMD_OPEN_TX_V2		(0x200D)
#define CPE_LSM_SESSION_CMD_SET_PARAMS_V2	(0x200E)

/* LSM Service module and param IDs */
#define CPE_LSM_MODULE_ID_VOICE_WAKEUP		(0x00012C00)
#define CPE_LSM_MODULE_ID_VOICE_WAKEUP_V2	(0x00012C0D)
#define CPE_LSM_MODULE_FRAMEWORK		(0x00012C0E)

#define CPE_LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD (0x00012C01)
#define CPE_LSM_PARAM_ID_OPERATION_MODE		(0x00012C02)
#define CPE_LSM_PARAM_ID_GAIN			(0x00012C03)
@@ -73,6 +78,8 @@
#define CPE_LSM_PARAM_ID_LAB_ENABLE	0x00012C09
/* used for T in LAB config DSP internal buffer*/
#define CPE_LSM_PARAM_ID_LAB_CONFIG	0x00012C0A
#define CPE_LSM_PARAM_ID_REGISTER_SOUND_MODEL	(0x00012C14)
#define CPE_LSM_PARAM_ID_DEREGISTER_SOUND_MODEL	(0x00012C15)

/* AFE Service command opcodes */
#define CPE_AFE_PORT_CMD_START			(0x1001)
@@ -263,6 +270,11 @@ struct cpe_lsm_cmd_open_tx {
	u32 sampling_rate;
} __packed;

struct cpe_lsm_cmd_open_tx_v2 {
	struct cmi_hdr hdr;
	u32 topology_id;
} __packed;

struct cpe_cmd_shmem_alloc {
	struct cmi_hdr hdr;
	u32 size;
@@ -285,10 +297,35 @@ struct cpe_lsm_event_detect_v2 {
	u8 payload[0];
} __packed;

struct cpe_lsm_psize_res {
	u16 param_size;
	u16 reserved;
} __packed;

union cpe_lsm_param_size {
	u32 param_size;
	struct cpe_lsm_psize_res sr;
} __packed;

struct cpe_param_data {
	u32 module_id;
	u32 param_id;
	u16 param_size;
	union cpe_lsm_param_size p_size;
} __packed;

struct cpe_lsm_param_epd_thres {
	struct cmi_hdr hdr;
	struct cpe_param_data param;
	u32 minor_version;
	u32 epd_begin;
	u32 epd_end;
} __packed;

struct cpe_lsm_param_gain {
	struct cmi_hdr hdr;
	struct cpe_param_data param;
	u32 minor_version;
	u16 gain;
	u16 reserved;
} __packed;

@@ -319,21 +356,23 @@ struct cpe_afe_params {
	struct cmi_hdr hdr;
	struct cpe_afe_hw_mad_ctrl hw_mad_ctrl;
	struct cpe_afe_port_cfg port_cfg;
};
} __packed;

struct cpe_afe_svc_cmd_mode {
	struct cmi_hdr hdr;
	u8 mode;
} __packed;

struct cpe_lsm_operation_mode {
struct cpe_lsm_param_opmode {
	struct cmi_hdr hdr;
	struct cpe_param_data param;
	u32 minor_version;
	u16 mode;
	u16 reserved;
} __packed;

struct cpe_lsm_connect_to_port {
struct cpe_lsm_param_connectport {
	struct cmi_hdr hdr;
	struct cpe_param_data param;
	u32 minor_version;
	u16 afe_port_id;
@@ -357,12 +396,6 @@ struct cpe_lsm_output_format_cfg {
	u8 data_path_events;
} __packed;

struct cpe_lsm_params {
	struct cmi_hdr hdr;
	struct cpe_lsm_operation_mode op_mode;
	struct cpe_lsm_connect_to_port connect_port;
} __packed;

struct cpe_lsm_lab_enable {
	struct cpe_param_data param;
	u16 enable;
@@ -397,12 +430,6 @@ struct cpe_lsm_lab_latency_config {
				sizeof(struct cmi_hdr))
#define PARAM_SIZE_LSM_CONTROL_SIZE (sizeof(struct cpe_lsm_lab_enable) - \
					sizeof(struct cpe_param_data))
#define PARAM_SIZE_LSM_OP_MODE (sizeof(struct cpe_lsm_operation_mode) - \
				sizeof(struct cpe_param_data))
#define PARAM_SIZE_LSM_CONNECT_PORT (sizeof(struct cpe_lsm_connect_to_port) - \
				sizeof(struct cpe_param_data))
#define CPE_PARAM_PAYLOAD_SIZE (sizeof(struct cpe_lsm_params) - \
				sizeof(struct cmi_hdr))
#define PARAM_SIZE_AFE_HW_MAD_CTRL (sizeof(struct cpe_afe_hw_mad_ctrl) - \
				sizeof(struct cpe_param_data))
#define PARAM_SIZE_AFE_PORT_CFG (sizeof(struct cpe_afe_port_cfg) - \
@@ -412,7 +439,8 @@ struct cpe_lsm_lab_latency_config {

#define OPEN_CMD_PAYLOAD_SIZE (sizeof(struct cpe_lsm_cmd_open_tx) - \
			       sizeof(struct cmi_hdr))

#define OPEN_V2_CMD_PAYLOAD_SIZE (sizeof(struct cpe_lsm_cmd_open_tx_v2) - \
			       sizeof(struct cmi_hdr))
#define SHMEM_ALLOC_CMD_PLD_SIZE (sizeof(struct cpe_cmd_shmem_alloc) - \
				      sizeof(struct cmi_hdr))

@@ -429,4 +457,21 @@ struct cpe_lsm_lab_latency_config {
#define CPE_AFE_CMD_MODE_PAYLOAD_SIZE \
		(sizeof(struct cpe_afe_svc_cmd_mode) - \
		 sizeof(struct cmi_hdr))
#define CPE_CMD_EPD_THRES_PLD_SIZE (sizeof(struct cpe_lsm_param_epd_thres) - \
				    sizeof(struct cmi_hdr))
#define CPE_EPD_THRES_PARAM_SIZE ((CPE_CMD_EPD_THRES_PLD_SIZE) - \
				  sizeof(struct cpe_param_data))
#define CPE_CMD_OPMODE_PLD_SIZE (sizeof(struct cpe_lsm_param_opmode) - \
				 sizeof(struct cmi_hdr))
#define CPE_OPMODE_PARAM_SIZE ((CPE_CMD_OPMODE_PLD_SIZE) -\
			       sizeof(struct cpe_param_data))
#define CPE_CMD_CONNECTPORT_PLD_SIZE \
	(sizeof(struct cpe_lsm_param_connectport) - \
	 sizeof(struct cmi_hdr))
#define CPE_CONNECTPORT_PARAM_SIZE ((CPE_CMD_CONNECTPORT_PLD_SIZE) - \
				    sizeof(struct cpe_param_data))
#define CPE_CMD_GAIN_PLD_SIZE (sizeof(struct cpe_lsm_param_gain) - \
			       sizeof(struct cmi_hdr))
#define CPE_GAIN_PARAM_SIZE ((CPE_CMD_GAIN_PLD_SIZE) - \
			     sizeof(struct cpe_param_data))
#endif /* __CPE_CMI_H__ */
+9 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ struct cpe_lsm_session {

	u32 lab_enable;
	struct lsm_out_fmt_cfg out_fmt_cfg;

	bool is_topology_used;
};

struct wcd_cpe_afe_ops {
@@ -146,6 +148,13 @@ struct wcd_cpe_lsm_ops {
			bool detect_failure);
	int (*lsm_set_fmt_cfg)(void *core_handle,
			struct cpe_lsm_session *session);
	int (*lsm_set_one_param)(void *core_handle,
			struct cpe_lsm_session *session,
			struct lsm_params_info *p_info,
			void *data, enum LSM_PARAM_TYPE param_type);
	void (*lsm_get_snd_model_offset)
		(void *core_handle, struct cpe_lsm_session *,
		 size_t *offset);
};

int wcd_cpe_get_lsm_ops(struct wcd_cpe_lsm_ops *);
+557 −90

File changed.

Preview size limit exceeded, changes collapsed.

+655 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define LISTEN_MAX_PERIOD_SIZE     4096
#define LISTEN_MIN_PERIOD_SIZE     320
#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
#define MSM_CPE_MAX_CUSTOM_PARAM_SIZE 2048

#define MSM_CPE_LAB_THREAD_TIMEOUT (3 * (HZ/10))

@@ -1577,6 +1578,446 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	return 0;
}

static bool msm_cpe_lsm_is_valid_stream(struct snd_pcm_substream *substream,
		const char *func)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;

	if (!substream || !substream->private_data) {
		pr_err("%s: invalid substream (%p)\n",
			func, substream);
		return false;
	}

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);

	if (!cpe || !cpe->core_handle) {
		dev_err(rtd->dev,
			"%s: Invalid private data\n",
			func);
		return false;
	}

	if (!lsm_d || !lsm_d->lsm_session) {
		dev_err(rtd->dev,
			"%s: Invalid session data\n",
			func);
		return false;
	}

	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	if (!lsm_ops) {
		dev_err(rtd->dev,
			"%s: Invalid lsm_ops\n", func);
		return false;
	}

	return true;
}

static int msm_cpe_lsm_set_epd(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	struct snd_lsm_ep_det_thres epd_thres;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	if (p_info->param_size != sizeof(epd_thres)) {
		dev_err(rtd->dev,
			"%s: Invalid param_size %d\n",
			__func__, p_info->param_size);
		rc = -EINVAL;
		goto done;
	}

	if (copy_from_user(&epd_thres, p_info->param_data,
			   p_info->param_size)) {
		dev_err(rtd->dev,
			"%s: copy_from_user failed, size = %d\n",
			__func__, p_info->param_size);
		rc = -EFAULT;
		goto done;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, &epd_thres,
				LSM_ENDPOINT_DETECT_THRESHOLD);
	if (unlikely(rc))
		dev_err(rtd->dev,
			"%s: set_one_param(epd_threshold) failed, rc %d\n",
			__func__, rc);
done:
	return rc;
}

static int msm_cpe_lsm_set_mode(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	struct snd_lsm_detect_mode det_mode;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	if (p_info->param_size != sizeof(det_mode)) {
		dev_err(rtd->dev,
			"%s: Invalid param_size %d\n",
			__func__, p_info->param_size);
		rc = -EINVAL;
		goto done;
	}

	if (copy_from_user(&det_mode, p_info->param_data,
			   p_info->param_size)) {
		dev_err(rtd->dev,
			"%s: copy_from_user failed, size = %d\n",
			__func__, p_info->param_size);
		rc = -EFAULT;
		goto done;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, &det_mode,
				LSM_OPERATION_MODE);
	if (unlikely(rc))
		dev_err(rtd->dev,
			"%s: set_one_param(epd_threshold) failed, rc %d\n",
			__func__, rc);
done:
	return rc;
}

static int msm_cpe_lsm_set_gain(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	struct snd_lsm_gain gain;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	if (p_info->param_size != sizeof(gain)) {
		dev_err(rtd->dev,
			"%s: Invalid param_size %d\n",
			__func__, p_info->param_size);
		rc = -EINVAL;
		goto done;
	}

	if (copy_from_user(&gain, p_info->param_data,
			   p_info->param_size)) {
		dev_err(rtd->dev,
			"%s: copy_from_user failed, size = %d\n",
			__func__, p_info->param_size);
		rc = -EFAULT;
		goto done;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, &gain,
				LSM_GAIN);
	if (unlikely(rc))
		dev_err(rtd->dev,
			"%s: set_one_param(epd_threshold) failed, rc %d\n",
			__func__, rc);
done:
	return rc;

}

static int msm_cpe_lsm_set_conf(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	session->num_confidence_levels =
			p_info->param_size;
	rc = msm_cpe_lsm_get_conf_levels(session,
			p_info->param_data);
	if (rc) {
		dev_err(rtd->dev,
			"%s: get_conf_levels failed, err = %d\n",
			__func__, rc);
		goto done;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, NULL,
				LSM_MIN_CONFIDENCE_LEVELS);
	if (unlikely(rc))
		dev_err(rtd->dev,
			"%s: set_one_param(conf_levels) failed, rc %d\n",
			__func__, rc);
done:
	return rc;
}

static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	int rc;
	size_t offset;
	u8 *snd_model_ptr;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	lsm_ops->lsm_get_snd_model_offset(cpe->core_handle,
			session, &offset);
	session->snd_model_size = p_info->param_size + offset;

	session->snd_model_data = vzalloc(session->snd_model_size);
	if (!session->snd_model_data)
			return -ENOMEM;
	snd_model_ptr = ((u8 *) session->snd_model_data) + offset;

	if (copy_from_user(snd_model_ptr,
			   p_info->param_data, p_info->param_size)) {
		dev_err(rtd->dev,
			"%s: copy_from_user for snd_model failed\n",
			__func__);
		rc = -EFAULT;
		goto free_snd_model_data;
	}

	rc = lsm_ops->lsm_shmem_alloc(cpe->core_handle, session,
				      session->snd_model_size);
	if (rc != 0) {
		dev_err(rtd->dev,
			"%s: shared memory allocation failed, err = %d\n",
		       __func__, rc);
		rc = -EINVAL;
		goto free_snd_model_data;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, NULL,
				LSM_REG_SND_MODEL);
	if (unlikely(rc)) {
		dev_err(rtd->dev,
			"%s: set_one_param(snd_model) failed, rc %d\n",
			__func__, rc);
		goto dealloc_shmem;
	}
	return 0;

dealloc_shmem:
	lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);

free_snd_model_data:
	vfree(session->snd_model_data);
	return rc;
}

static int msm_cpe_lsm_dereg_model(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, NULL,
				LSM_DEREG_SND_MODEL);
	if (rc)
		dev_err(rtd->dev,
			"%s: dereg_snd_model failed\n",
			__func__);
	return lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
}

static int msm_cpe_lsm_set_custom(struct snd_pcm_substream *substream,
		struct lsm_params_info *p_info)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct wcd_cpe_lsm_ops *lsm_ops;
	u8 *data;
	int rc;

	if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
		return -EINVAL;

	rtd = substream->private_data;
	lsm_d = cpe_get_lsm_data(substream);
	cpe = cpe_get_private_data(substream);
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;

	if (p_info->param_size > MSM_CPE_MAX_CUSTOM_PARAM_SIZE) {
		dev_err(rtd->dev,
			"%s: invalid size %d, max allowed %d\n",
			__func__, p_info->param_size,
			MSM_CPE_MAX_CUSTOM_PARAM_SIZE);
		return -EINVAL;
	}

	data = kzalloc(p_info->param_size, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	if (copy_from_user(data, p_info->param_data,
			   p_info->param_size)) {
		dev_err(rtd->dev,
			"%s: copy_from_user failed for custom params, size = %d\n",
			__func__, p_info->param_size);
		rc = -EFAULT;
		goto err_ret;
	}

	rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
				session, p_info, data,
				LSM_CUSTOM_PARAMS);
	if (rc)
		dev_err(rtd->dev,
			"%s: custom_params failed, err = %d\n",
			__func__, rc);
err_ret:
	kfree(data);
	return rc;
}

static int msm_cpe_lsm_process_params(struct snd_pcm_substream *substream,
		struct snd_lsm_module_params *p_data,
		void *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct lsm_params_info *p_info;
	int i;
	int rc = 0;

	p_info = (struct lsm_params_info *) params;

	for (i = 0; i < p_data->num_params; i++) {
		dev_dbg(rtd->dev,
			"%s: param (%d), module_id = 0x%x, param_id = 0x%x, param_size = 0x%x, param_type = 0x%x\n",
			__func__, i, p_info->module_id,
			p_info->param_id, p_info->param_size,
			p_info->param_type);

		switch (p_info->param_type) {
		case LSM_ENDPOINT_DETECT_THRESHOLD:
			rc = msm_cpe_lsm_set_epd(substream, p_info);
			break;
		case LSM_OPERATION_MODE:
			rc = msm_cpe_lsm_set_mode(substream, p_info);
			break;
		case LSM_GAIN:
			rc = msm_cpe_lsm_set_gain(substream, p_info);
			break;
		case LSM_MIN_CONFIDENCE_LEVELS:
			rc = msm_cpe_lsm_set_conf(substream, p_info);
			break;
		case LSM_REG_SND_MODEL:
			rc = msm_cpe_lsm_reg_model(substream, p_info);
			break;
		case LSM_DEREG_SND_MODEL:
			rc = msm_cpe_lsm_dereg_model(substream, p_info);
			break;
		case LSM_CUSTOM_PARAMS:
			rc = msm_cpe_lsm_set_custom(substream, p_info);
			break;
		default:
			dev_err(rtd->dev,
				"%s: Invalid param_type %d\n",
				__func__, p_info->param_type);
			rc = -EINVAL;
			break;
		}
		if (rc) {
			pr_err("%s: set_param fail for param_type %d\n",
				__func__, p_info->param_type);
			return rc;
		}

		p_info++;
	}

	return rc;
}

static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
			 unsigned int cmd, void *arg)
{
@@ -1620,6 +2061,14 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
	switch (cmd) {
	case SNDRV_LSM_REG_SND_MODEL_V2: {
		struct snd_lsm_sound_model_v2 snd_model;

		if (session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if using topology\n",
				__func__, "LSM_REG_SND_MODEL_V2");
			return -EINVAL;
		}

		if (copy_from_user(&snd_model, (void *)arg,
				   sizeof(struct snd_lsm_sound_model_v2))) {
			dev_err(rtd->dev,
@@ -1693,6 +2142,13 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
	case SNDRV_LSM_SET_PARAMS: {
		struct snd_lsm_detection_params det_params;

		if (session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if using topology\n",
				__func__, "SNDRV_LSM_SET_PARAMS");
			return -EINVAL;
		}

		if (copy_from_user(&det_params, (void *) arg,
				   sizeof(det_params))) {
			dev_err(rtd->dev,
@@ -1707,6 +2163,74 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
					       &det_params);
	}
		break;

	case SNDRV_LSM_SET_MODULE_PARAMS: {
		struct snd_lsm_module_params p_data;
		size_t p_size;
		u8 *params;

		if (!session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if not using topology\n",
				__func__, "SET_MODULE_PARAMS");
			return -EINVAL;
		}

		if (!arg) {
			dev_err(rtd->dev,
				"%s: %s: No Param data to set\n",
				__func__, "SET_MODULE_PARAMS");
			return -EINVAL;
		}

		if (copy_from_user(&p_data, arg,
				   sizeof(p_data))) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %zd\n",
				__func__, "p_data", sizeof(p_data));
			return -EFAULT;
		}

		if (p_data.num_params > LSM_PARAMS_MAX) {
			dev_err(rtd->dev,
				"%s: %s: Invalid num_params %d\n",
				__func__, "SET_MODULE_PARAMS",
				p_data.num_params);
			return -EINVAL;
		}

		p_size = p_data.num_params *
			 sizeof(struct lsm_params_info);

		if (p_data.data_size != p_size) {
			dev_err(rtd->dev,
				"%s: %s: Invalid size %zd\n",
				__func__, "SET_MODULE_PARAMS", p_size);

			return -EFAULT;
		}

		params = kzalloc(p_size, GFP_KERNEL);
		if (!params)
			return -ENOMEM;

		if (copy_from_user(params, p_data.params,
				   p_data.data_size)) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %d\n",
				__func__, "params", p_data.data_size);
			kfree(params);
			return -EFAULT;
		}

		err = msm_cpe_lsm_process_params(substream, &p_data, params);
		if (err)
			dev_err(rtd->dev,
				"%s: %s: Failed to set params, err = %d\n",
				__func__, "SET_MODULE_PARAMS", err);
		kfree(params);
		break;
	}
	default:
		err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg);
		break;
@@ -1741,6 +2265,20 @@ struct snd_lsm_detection_params_32 {
	bool detect_failure;
};

struct lsm_params_info_32 {
	u32 module_id;
	u32 param_id;
	u32 param_size;
	compat_uptr_t param_data;
	enum LSM_PARAM_TYPE param_type;
};

struct snd_lsm_module_params_32 {
	compat_uptr_t params;
	u32 num_params;
	u32 data_size;
};

enum {
	SNDRV_LSM_EVENT_STATUS32 =
		_IOW('U', 0x02, struct snd_lsm_event_status32),
@@ -1748,6 +2286,8 @@ enum {
		_IOW('U', 0x07, struct snd_lsm_sound_model_v2_32),
	SNDRV_LSM_SET_PARAMS32 =
		_IOW('U', 0x0A, struct snd_lsm_detection_params_32),
	SNDRV_LSM_SET_MODULE_PARAMS_32 =
		_IOW('U', 0x0B, struct snd_lsm_module_params_32),
};

static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
@@ -1795,6 +2335,13 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
		struct snd_lsm_sound_model_v2 snd_model;
		struct snd_lsm_sound_model_v2_32 snd_model32;

		if (session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if using topology\n",
				__func__, "LSM_REG_SND_MODEL_V2_32");
			return -EINVAL;
		}

		dev_dbg(rtd->dev,
			"%s: ioctl %s\n", __func__,
			"SNDRV_LSM_REG_SND_MODEL_V2_32");
@@ -1918,6 +2465,14 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
	case SNDRV_LSM_SET_PARAMS32: {
		struct snd_lsm_detection_params_32 det_params32;
		struct snd_lsm_detection_params det_params;

		if (session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if using topology\n",
				__func__, "SNDRV_LSM_SET_PARAMS32");
			return -EINVAL;
		}

		if (copy_from_user(&det_params32, arg,
				   sizeof(det_params32))) {
			err = -EFAULT;
@@ -1946,6 +2501,106 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
		break;
	}

	case SNDRV_LSM_SET_MODULE_PARAMS_32: {
		struct snd_lsm_module_params_32 p_data_32;
		struct snd_lsm_module_params p_data;
		u8 *params, *params32;
		size_t p_size;
		struct lsm_params_info_32 *p_info_32;
		struct lsm_params_info *p_info;
		int i;

		if (!session->is_topology_used) {
			dev_err(rtd->dev,
				"%s: %s: not supported if not using topology\n",
				__func__, "SET_MODULE_PARAMS_32");
			return -EINVAL;
		}

		if (!arg) {
			dev_err(rtd->dev,
				"%s: %s: No Param data to set\n",
				__func__, "SET_MODULE_PARAMS_32");
			return -EINVAL;
		}

		if (copy_from_user(&p_data_32, arg,
				   sizeof(p_data_32))) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %zd\n",
				__func__, "SET_MODULE_PARAMS_32",
				sizeof(p_data_32));
			return -EFAULT;
		}

		p_data.params = compat_ptr(p_data_32.params);
		p_data.num_params = p_data_32.num_params;
		p_data.data_size = p_data_32.data_size;

		if (p_data.num_params > LSM_PARAMS_MAX) {
			dev_err(rtd->dev,
				"%s: %s: Invalid num_params %d\n",
				__func__, "SET_MODULE_PARAMS_32",
				p_data.num_params);
			return -EINVAL;
		}

		if (p_data.data_size !=
		    (p_data.num_params * sizeof(struct lsm_params_info_32))) {
			dev_err(rtd->dev,
				"%s: %s: Invalid size %d\n",
				__func__, "SET_MODULE_PARAMS_32",
				p_data.data_size);
			return -EINVAL;
		}

		p_size = sizeof(struct lsm_params_info_32) *
			 p_data.num_params;

		params32 = kzalloc(p_size, GFP_KERNEL);
		if (!params32)
			return -ENOMEM;

		p_size = sizeof(struct lsm_params_info) * p_data.num_params;
		params = kzalloc(p_size, GFP_KERNEL);
		if (!params) {
			kfree(params32);
			return -ENOMEM;
		}

		if (copy_from_user(params32, p_data.params,
				   p_data.data_size)) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %d\n",
				__func__, "params32", p_data.data_size);
			kfree(params32);
			kfree(params);
			return -EFAULT;
		}

		p_info_32 = (struct lsm_params_info_32 *) params32;
		p_info = (struct lsm_params_info *) params;
		for (i = 0; i < p_data.num_params; i++) {
			p_info->module_id = p_info_32->module_id;
			p_info->param_id = p_info_32->param_id;
			p_info->param_size = p_info_32->param_size;
			p_info->param_data = compat_ptr(p_info_32->param_data);
			p_info->param_type = p_info_32->param_type;

			p_info_32++;
			p_info++;
		}

		err = msm_cpe_lsm_process_params(substream,
					     &p_data, params);
		if (err)
			dev_err(rtd->dev,
				"%s: Failed to process params, err = %d\n",
				__func__, err);
		kfree(params);
		kfree(params32);
		break;
	}
	default:
		err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg);
		break;