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

Commit 29857371 authored by Bhalchandra Gajare's avatar Bhalchandra Gajare Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: msm-cpe-lsm: Add support for listen output configuration



Add support in the CPE LSM platform driver to accept the configuration
parameters for listen buffering output data. This is required when the
buffering data is transmitted to userspace with configuration that is
different from the actual underlying stream hardware parameters.

Change-Id: Ibdefda04ff7197c111bc416b1216933ad9ab851e
Signed-off-by: default avatarBhalchandra Gajare <gajare@codeaurora.org>
parent 9b7e0a0f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@
#define CPE_LSM_SESSION_CMD_SHARED_MEM_ALLOC	(0x2008)
#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)

/* LSM Service module and param IDs */
#define CPE_LSM_MODULE_ID_VOICE_WAKEUP		(0x00012C00)
@@ -333,6 +334,13 @@ struct cpe_lsm_conf_level {
	u8 num_active_models;
} __packed;

struct cpe_lsm_output_format_cfg {
	struct cmi_hdr hdr;
	u8 format;
	u8 packing;
	u8 data_path_events;
} __packed;

struct cpe_lsm_params {
	struct cmi_hdr hdr;
	struct cpe_lsm_operation_mode op_mode;
@@ -394,4 +402,7 @@ struct cpe_lsm_lab_latency_config {

#define SHMEM_DEALLOC_CMD_PLD_SIZE (sizeof(struct cpe_cmd_shmem_dealloc) - \
				      sizeof(struct cmi_hdr))
#define OUT_FMT_CFG_CMD_PAYLOAD_SIZE ( \
		sizeof(struct cpe_lsm_output_format_cfg) - \
		sizeof(struct cmi_hdr))
#endif /* __CPE_CMI_H__ */
+10 −0
Original line number Diff line number Diff line
@@ -39,6 +39,13 @@ struct wcd_cpe_afe_port_cfg {
	u32 sample_rate;
};

struct lsm_out_fmt_cfg {
	u8 format;
	u8 pack_mode;
	u8 data_path_events;
	u8 transfer_mode;
};

struct cpe_lsm_session {
	/* sound model related */
	void *snd_model_data;
@@ -65,6 +72,7 @@ struct cpe_lsm_session {
	bool started;

	u32 lab_enable;
	struct lsm_out_fmt_cfg out_fmt_cfg;
};

struct wcd_cpe_afe_ops {
@@ -132,6 +140,8 @@ struct wcd_cpe_lsm_ops {
			struct cpe_lsm_session *session,
			enum lsm_detection_mode detect_mode,
			bool detect_failure);
	int (*lsm_set_fmt_cfg)(void *core_handle,
			struct cpe_lsm_session *session);
};

int wcd_cpe_get_lsm_ops(struct wcd_cpe_lsm_ops *);
+38 −0
Original line number Diff line number Diff line
@@ -2922,6 +2922,43 @@ done:
	return rc;
}

static int wcd_cpe_lsm_set_fmt_cfg(void *core_handle,
			struct cpe_lsm_session *session)
{
	int ret;
	struct cpe_lsm_output_format_cfg out_fmt_cfg;
	struct wcd_cpe_core *core = core_handle;

	ret = wcd_cpe_is_valid_lsm_session(core, session, __func__);
	if (ret)
		goto done;

	WCD_CPE_GRAB_LOCK(&session->lsm_lock, "lsm");

	memset(&out_fmt_cfg, 0, sizeof(out_fmt_cfg));
	if (fill_lsm_cmd_header_v0_inband(&out_fmt_cfg.hdr,
			session->id, OUT_FMT_CFG_CMD_PAYLOAD_SIZE,
			CPE_LSM_SESSION_CMD_TX_BUFF_OUTPUT_CONFIG)) {
		ret = -EINVAL;
		goto err_ret;
	}

	out_fmt_cfg.format = session->out_fmt_cfg.format;
	out_fmt_cfg.packing = session->out_fmt_cfg.pack_mode;
	out_fmt_cfg.data_path_events = session->out_fmt_cfg.data_path_events;

	ret = wcd_cpe_cmi_send_lsm_msg(core, session, &out_fmt_cfg);
	if (ret)
		dev_err(core->dev,
			"%s: lsm_set_output_format_cfg failed, err = %d\n",
			__func__, ret);

err_ret:
	WCD_CPE_REL_LOCK(&session->lsm_lock, "lsm");
done:
	return ret;
}

/*
 * wcd_cpe_get_lsm_ops: register lsm driver to codec
 * @lsm_ops: structure with lsm callbacks
@@ -2942,6 +2979,7 @@ int wcd_cpe_get_lsm_ops(struct wcd_cpe_lsm_ops *lsm_ops)
	lsm_ops->lsm_lab_control = wcd_cpe_lsm_lab_control;
	lsm_ops->lab_ch_setup = wcd_cpe_lab_ch_setup;
	lsm_ops->lsm_set_data = wcd_cpe_lsm_set_data;
	lsm_ops->lsm_set_fmt_cfg = wcd_cpe_lsm_set_fmt_cfg;
	return 0;
}
EXPORT_SYMBOL(wcd_cpe_get_lsm_ops);
+93 −0
Original line number Diff line number Diff line
@@ -881,6 +881,60 @@ done:
	return rc;
}

static int msm_cpe_lsm_validate_out_format(
	struct snd_pcm_substream *substream,
	struct snd_lsm_output_format_cfg *cfg)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	int rc = 0;

	if (!cfg) {
		dev_err(rtd->dev,
			"%s: Invalid lsm out cfg\n", __func__);
		rc = -EINVAL;
		goto done;
	}

	if (cfg->format != LSM_OUT_FORMAT_PCM &&
	    cfg->format != LSM_OUT_FORMAT_ADPCM) {
		dev_err(rtd->dev,
			"%s: Invalid format %u\n",
			__func__, cfg->format);
		rc = -EINVAL;
		goto done;
	}

	if (cfg->packing != LSM_OUT_DATA_RAW &&
	    cfg->packing != LSM_OUT_DATA_PACKED) {
		dev_err(rtd->dev,
			"%s: Invalid packing method %u\n",
			__func__, cfg->packing);
		rc = -EINVAL;
		goto done;
	}

	if (cfg->events != LSM_OUT_DATA_EVENTS_DISABLED &&
	    cfg->events != LSM_OUT_DATA_EVENTS_ENABLED) {
		dev_err(rtd->dev,
			"%s: Invalid events provided %u\n",
			__func__, cfg->events);
		rc = -EINVAL;
		goto done;
	}

	if (cfg->mode != LSM_OUT_TRANSFER_MODE_RT &&
	    cfg->mode != LSM_OUT_TRANSFER_MODE_FTRT) {
		dev_err(rtd->dev,
			"%s: Invalid transfer mode %u\n",
			__func__, cfg->mode);
		rc = -EINVAL;
		goto done;
	}

done:
	return rc;
}

/*
 * msm_cpe_lsm_ioctl_shared: Shared IOCTL for this platform driver
 * @substream: ASoC substream for which the operation is invoked
@@ -1333,6 +1387,45 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,

		break;

		case SNDRV_LSM_OUT_FORMAT_CFG: {
			struct snd_lsm_output_format_cfg u_fmt_cfg;

			if (!arg) {
				dev_err(rtd->dev,
					"%s: Invalid argument to ioctl %s\n",
					__func__, "SNDRV_LSM_OUT_FORMAT_CFG");
				return -EINVAL;
			}

			if (copy_from_user(&u_fmt_cfg, arg,
					   sizeof(u_fmt_cfg))) {
				dev_err(rtd->dev,
					"%s: copy_from_user failed for out_fmt_cfg\n",
					__func__);
				return -EFAULT;
			}

			if (msm_cpe_lsm_validate_out_format(substream,
							    &u_fmt_cfg))
				return -EINVAL;

			session->out_fmt_cfg.format = u_fmt_cfg.format;
			session->out_fmt_cfg.pack_mode = u_fmt_cfg.packing;
			session->out_fmt_cfg.data_path_events =
						u_fmt_cfg.events;
			session->out_fmt_cfg.transfer_mode = u_fmt_cfg.mode;

			rc = lsm_ops->lsm_set_fmt_cfg(cpe->core_handle,
						      session);
			if (rc) {
				dev_err(rtd->dev,
					"%s: lsm_set_fmt_cfg failed, err = %d\n",
					__func__, rc);
				return rc;
			}
		}
		break;

	default:
		dev_dbg(rtd->dev,
			"%s: Default snd_lib_ioctl cmd 0x%x\n",