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

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

ASoC: msm-cpe-lsm: Add output AFE port for listen



In order for the buffering to be captured from CPE, the output AFE port
needs to be configured and started. Add support for configuring and
starting the output AFE port once buffering is started and stop the AFE
port when buffering is stopped.

Change-Id: Ie4e6460745cf3328d20d77317f314b3553f137eb
Signed-off-by: default avatarBhalchandra Gajare <gajare@codeaurora.org>
parent 29857371
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/types.h>

#define CPE_AFE_PORT_1_TX 1
#define CPE_AFE_PORT_ID_2_OUT 0x02
#define CMI_INBAND_MESSAGE_SIZE 127

/*
@@ -81,6 +82,7 @@
#define CPE_AFE_PORT_CMD_SHARED_MEM_ALLOC	(0x1005)
#define CPE_AFE_PORT_CMDRSP_SHARED_MEM_ALLOC	(0x1006)
#define CPE_AFE_PORT_CMD_SHARED_MEM_DEALLOC	(0x1007)
#define CPE_AFE_PORT_CMD_GENERIC_CONFIG		(0x1008)

/* AFE Service module and param IDs */
#define CPE_AFE_CMD_SET_PARAM			(0x1000)
@@ -304,6 +306,14 @@ struct cpe_afe_port_cfg {
	u32 sample_rate;
} __packed;

struct cpe_afe_cmd_port_cfg {
	struct cmi_hdr hdr;
	u8 bit_width;
	u8 num_channels;
	u16 buffer_size;
	u32 sample_rate;
} __packed;

struct cpe_afe_params {
	struct cmi_hdr hdr;
	struct cpe_afe_hw_mad_ctrl hw_mad_ctrl;
@@ -405,4 +415,8 @@ struct cpe_lsm_lab_latency_config {
#define OUT_FMT_CFG_CMD_PAYLOAD_SIZE ( \
		sizeof(struct cpe_lsm_output_format_cfg) - \
		sizeof(struct cmi_hdr))

#define CPE_AFE_CMD_PORT_CFG_PAYLOAD_SIZE \
		(sizeof(struct cpe_afe_cmd_port_cfg) - \
		 sizeof(struct cmi_hdr))
#endif /* __CPE_CMI_H__ */
+4 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct cpe_lsm_session {

	struct completion cmd_comp;
	struct wcd_cpe_afe_port_cfg afe_port_cfg;
	struct wcd_cpe_afe_port_cfg afe_out_port_cfg;
	struct mutex lsm_lock;

	u32 snd_model_size;
@@ -90,6 +91,9 @@ struct wcd_cpe_afe_ops {

	int (*afe_port_resume) (void *core_handle,
			       struct wcd_cpe_afe_port_cfg *cfg);

	int (*afe_port_cmd_cfg)(void *core_handle,
				struct wcd_cpe_afe_port_cfg *cfg);
};

struct wcd_cpe_lsm_ops {
+54 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@

#define CMI_CMD_TIMEOUT (10 * HZ)
#define WCD_CPE_LSM_MAX_SESSIONS 1
#define WCD_CPE_AFE_MAX_PORTS 1
#define WCD_CPE_AFE_MAX_PORTS 2
#define WCD_CPE_DRAM_SIZE 0x30000
#define WCD_CPE_DRAM_OFFSET 0x50000

@@ -67,6 +67,15 @@
#define CPE_ERR_IRQ_CB(core) \
	(core->cpe_cdc_cb->cpe_err_irq_control)

#define AFE_OUT_BUF_SAMPLES 8

/*
 * AFE output buffer size is always
 * AFE_OUT_BUF_SAMPLES * number of bytes per sample
 */
#define AFE_OUT_BUF_SIZE(bit_width) \
	(AFE_OUT_BUF_SAMPLES * (bit_width / BITS_PER_BYTE))

enum afe_port_state {
	AFE_PORT_STATE_DEINIT = 0,
	AFE_PORT_STATE_INIT,
@@ -3300,6 +3309,49 @@ static int wcd_cpe_is_valid_port(struct wcd_cpe_core *core,
	return 0;
}

static int wcd_cpe_afe_cmd_port_cfg(void *core_handle,
		struct wcd_cpe_afe_port_cfg *afe_cfg)
{
	struct cpe_afe_cmd_port_cfg port_cfg_cmd;
	struct wcd_cpe_core *core = core_handle;
	struct wcd_cmi_afe_port_data *afe_port_d;
	int ret;

	ret = wcd_cpe_is_valid_port(core, afe_cfg, __func__);
	if (ret)
		goto done;

	afe_port_d = &afe_ports[afe_cfg->port_id];
	afe_port_d->port_id = afe_cfg->port_id;

	WCD_CPE_GRAB_LOCK(&afe_port_d->afe_lock, "afe");
	memset(&port_cfg_cmd, 0, sizeof(port_cfg_cmd));
	if (fill_afe_cmd_header(&port_cfg_cmd.hdr,
			afe_cfg->port_id,
			CPE_AFE_PORT_CMD_GENERIC_CONFIG,
			CPE_AFE_CMD_PORT_CFG_PAYLOAD_SIZE,
			false)) {
		ret = -EINVAL;
		goto err_ret;
	}

	port_cfg_cmd.bit_width = afe_cfg->bit_width;
	port_cfg_cmd.num_channels = afe_cfg->num_channels;
	port_cfg_cmd.sample_rate = afe_cfg->sample_rate;
	port_cfg_cmd.buffer_size = AFE_OUT_BUF_SIZE(afe_cfg->bit_width);

	ret = wcd_cpe_cmi_send_afe_msg(core, afe_port_d, &port_cfg_cmd);
	if (ret)
		dev_err(core->dev,
			"%s: afe_port_config failed, err = %d\n",
			__func__, ret);

err_ret:
	WCD_CPE_REL_LOCK(&afe_port_d->afe_lock, "afe");
done:
	return ret;
}

/*
 * wcd_cpe_afe_set_params: set the parameters for afe port
 * @afe_cfg: configuration data for the port for which the
@@ -3529,6 +3581,7 @@ int wcd_cpe_get_afe_ops(struct wcd_cpe_afe_ops *afe_ops)
	afe_ops->afe_port_stop = wcd_cpe_afe_port_stop;
	afe_ops->afe_port_suspend = wcd_cpe_afe_port_suspend;
	afe_ops->afe_port_resume = wcd_cpe_afe_port_resume;
	afe_ops->afe_port_cmd_cfg = wcd_cpe_afe_cmd_port_cfg;

	return 0;
}
+54 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <sound/msm-slim-dma.h>

#define LSM_VOICE_WAKEUP_APP_V2 2
#define AFE_OUT_PORT_2 2
#define LISTEN_MIN_NUM_PERIODS     2
#define LISTEN_MAX_NUM_PERIODS     8
#define LISTEN_MAX_PERIOD_SIZE     4096
@@ -104,6 +105,7 @@ struct cpe_hw_params {
	u16 sample_size;
	u32 buf_sz;
	u32 period_count;
	u16 channels;
};

struct cpe_data_pcm_buf {
@@ -239,10 +241,14 @@ static int msm_cpe_afe_port_cntl(
	int rc = 0;

	if (!afe_cfg->port_id) {
		dev_err(rtd->dev,
		/*
		 * It is possible driver can get closed without prepare,
		 * in which case afe ports will not be initialized.
		 */
		dev_dbg(rtd->dev,
			"%s: Invalid afe port id\n",
			__func__);
		return -EINVAL;
		return 0;
	}

	switch (cmd) {
@@ -285,6 +291,7 @@ static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
	struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
	struct cpe_priv *cpe = cpe_get_private_data(substream);
	struct wcd_cpe_lsm_ops *lsm_ops;
	struct wcd_cpe_afe_ops *afe_ops;
	struct cpe_lsm_session *session;
	struct cpe_lsm_lab *lab_d = &lsm_d->lab;
	struct msm_slim_dma_data *dma_data = NULL;
@@ -317,6 +324,7 @@ static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
	}

	lsm_ops = &cpe->lsm_ops;
	afe_ops = &cpe->afe_ops;
	session = lsm_d->lsm_session;
	if (rtd->cpu_dai)
		dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai,
@@ -371,6 +379,18 @@ static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
		dev_err(rtd->dev,
			"%s: POST ch teardown failed, err = %d\n",
			__func__, rc);
	lab_d->thread_status = MSM_LSM_LAB_THREAD_STOP;

	/*
	 * Even though LAB stop failed,
	 * output AFE port needs to be stopped
	 */
	rc = afe_ops->afe_port_stop(cpe->core_handle,
				    &session->afe_out_port_cfg);
	if (rc)
		dev_err(rtd->dev,
			"%s: AFE out port stop failed, err = %d\n",
			__func__, rc);
	return 0;
}

@@ -1444,7 +1464,11 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	struct cpe_priv *cpe = NULL;
	struct cpe_lsm_session *session = NULL;
	struct cpe_lsm_lab *lab_d = NULL;
	struct cpe_hw_params *hw_params;
	struct wcd_cpe_lsm_ops *lsm_ops;
	struct wcd_cpe_afe_ops *afe_ops;
	struct wcd_cpe_afe_port_cfg *out_port;
	int rc;

	if (!substream || !substream->private_data) {
		pr_err("%s: invalid substream (%p)\n",
@@ -1473,6 +1497,8 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	session = lsm_d->lsm_session;
	lsm_ops = &cpe->lsm_ops;
	lab_d = &lsm_d->lab;
	afe_ops = &cpe->afe_ops;
	hw_params = &lsm_d->hw_params;

	if (!session->started) {
		dev_dbg(rtd->dev,
@@ -1487,6 +1513,30 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	    event_status->status ==
	    LSM_VOICE_WAKEUP_STATUS_DETECTED) {


		out_port = &session->afe_out_port_cfg;
		out_port->port_id = AFE_OUT_PORT_2;
		out_port->bit_width = hw_params->sample_size;
		out_port->num_channels = hw_params->channels;
		out_port->sample_rate = hw_params->sample_rate;

		rc = afe_ops->afe_port_cmd_cfg(cpe->core_handle,
					       out_port);
		if (rc) {
			dev_err(rtd->dev,
				"%s: Failed afe generic config v2, err = %d\n",
				__func__, rc);
			return rc;
		}

		rc = afe_ops->afe_port_start(cpe->core_handle, out_port);
		if (rc) {
			dev_err(rtd->dev,
				"%s: AFE out port start failed, err = %d\n",
				__func__, rc);
			return rc;
		}

		atomic_set(&lab_d->abort_read, 0);
		dev_dbg(rtd->dev,
			"%s: KW detected, scheduling LAB thread\n",
@@ -2052,7 +2102,9 @@ static int msm_cpe_lsm_hwparams(struct snd_pcm_substream *substream,
	hw_params->buf_sz = (params_buffer_bytes(params)
				/ params_periods(params));
	hw_params->period_count = params_periods(params);
	hw_params->channels = params_channels(params);
	hw_params->sample_rate = params_rate(params);

	if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
		hw_params->sample_size = 16;
	else if (params_format(params) ==