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

Commit fbe01a99 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 output AFE port for listen"

parents d69fcba5 92d6d441
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) ==