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

Commit d69fcba5 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 listen output configuration"

parents 392ae82e 29857371
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",