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

Commit 117249d9 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: Add timestamp support for lsm event status"

parents b6177ffc dc148417
Loading
Loading
Loading
Loading
+28 −2
Original line number Diff line number Diff line
#ifndef _UAPI_LSM_PARAMS_H__
#define _UAPI_LSM_PARAMS_H__

#define LSM_POLLING_ENABLE_SUPPORT
#define LSM_EVENT_TIMESTAMP_MODE_SUPPORT

#include <linux/types.h>
#include <sound/asound.h>

@@ -18,6 +21,9 @@
#define LSM_OUT_TRANSFER_MODE_RT (0)
#define LSM_OUT_TRANSFER_MODE_FTRT (1)

#define LSM_EVENT_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1)

enum lsm_app_id {
	LSM_VOICE_WAKEUP_APP_ID = 1,
	LSM_VOICE_WAKEUP_APP_ID_V2 = 2,
@@ -43,8 +49,7 @@ enum LSM_PARAM_TYPE {
	LSM_REG_SND_MODEL,
	LSM_DEREG_SND_MODEL,
	LSM_CUSTOM_PARAMS,
	/* driver ioctl will parse only so many params */
	LSM_PARAMS_MAX,
	LSM_POLLING_ENABLE,
};

/*
@@ -75,6 +80,14 @@ struct snd_lsm_gain {
	__u16 gain;
};

/*
 * Data for LSM_POLLING_ENABLE param_type
 * @poll_en: Polling enable or disable
 */
struct snd_lsm_poll_enable {
	bool poll_en;
};


struct snd_lsm_sound_model_v2 {
	__u8 __user *data;
@@ -95,11 +108,20 @@ struct snd_lsm_event_status {
	__u8 payload[0];
};

struct snd_lsm_event_status_v3 {
	__u32 timestamp_lsw;
	__u32 timestamp_msw;
	__u16 status;
	__u16 payload_size;
	__u8 payload[0];
};

struct snd_lsm_detection_params {
	__u8 *conf_level;
	enum lsm_detection_mode detect_mode;
	__u8 num_confidence_levels;
	bool detect_failure;
	bool poll_enable;
};

/*
@@ -171,5 +193,9 @@ struct snd_lsm_output_format_cfg {
					struct snd_lsm_module_params)
#define SNDRV_LSM_OUT_FORMAT_CFG _IOW('U', 0x0C, \
				      struct snd_lsm_output_format_cfg)
#define SNDRV_LSM_SET_PORT	_IO('U', 0x0D)
#define SNDRV_LSM_SET_FWK_MODE_CONFIG	_IOW('U', 0x0E, uint32_t)
#define SNDRV_LSM_EVENT_STATUS_V3	_IOW('U', 0x0F, \
					struct snd_lsm_event_status_v3)

#endif
+2 −18
Original line number Diff line number Diff line
@@ -3051,25 +3051,9 @@ static int wcd_cpe_set_one_param(void *core_handle,
		rc = wcd_cpe_send_param_epd_thres(core, session,
						data, &ids);
		break;
	case LSM_OPERATION_MODE: {
		struct cpe_lsm_ids connectport_ids;

		rc = wcd_cpe_send_param_opmode(core, session,
					data, &ids);
		if (rc)
	case LSM_OPERATION_MODE:
		rc = wcd_cpe_send_param_opmode(core, session, data, &ids);
		break;

		connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
		connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT;

		rc = wcd_cpe_send_param_connectport(core, session, NULL,
				       &connectport_ids, CPE_AFE_PORT_1_TX);
		if (rc)
			dev_err(core->dev,
				"%s: send_param_connectport failed, err %d\n",
				__func__, rc);
		break;
	}
	case LSM_GAIN:
		rc = wcd_cpe_send_param_gain(core, session, data, &ids);
		break;
+233 −27
Original line number Diff line number Diff line
@@ -43,6 +43,12 @@

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

/*
 * Driver ioctl will parse only so many params
 * size of LSM_PARAMS_MAX is last LSM_PARAM_TYPE + 1
 */
#define LSM_PARAMS_MAX (LSM_POLLING_ENABLE + 1)

#define MSM_CPE_LSM_GRAB_LOCK(lock, name)		\
{						\
	pr_debug("%s: %s lock acquire\n",	\
@@ -1060,7 +1066,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
	struct cpe_lsm_lab *lab_d = &lsm_d->lab;
	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
	struct msm_slim_dma_data *dma_data = NULL;
	struct snd_lsm_event_status *user;
	struct snd_lsm_detection_params det_params;
	int rc = 0;

@@ -1336,19 +1341,21 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
		break;

	case SNDRV_LSM_EVENT_STATUS:
	case SNDRV_LSM_EVENT_STATUS_V3: {
		struct snd_lsm_event_status *user;
		struct snd_lsm_event_status_v3 *user_v3;

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

		user = arg;

		/*
		 * Release the api lock before wait to allow
		 * other IOCTLs to be invoked while waiting
@@ -1368,6 +1375,9 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
			if (atomic_read(&lsm_d->event_avail) == 1) {
				rc = 0;
				atomic_set(&lsm_d->event_avail, 0);

				if (cmd == SNDRV_LSM_EVENT_STATUS) {
					user = arg;
					if (lsm_d->ev_det_pld_size >
						user->payload_size) {
						dev_err(rtd->dev,
@@ -1379,20 +1389,48 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
					}

					user->status = lsm_d->ev_det_status;
				user->payload_size = lsm_d->ev_det_pld_size;

					user->payload_size =
							lsm_d->ev_det_pld_size;
					memcpy(user->payload,
					       lsm_d->ev_det_payload,
					       lsm_d->ev_det_pld_size);

				} else {
					user_v3 = arg;
					if (lsm_d->ev_det_pld_size >
						user_v3->payload_size) {
						dev_err(rtd->dev,
							"%s: avail pld_bytes = %u, needed = %u\n",
							__func__,
							user_v3->payload_size,
							lsm_d->ev_det_pld_size);
						return -EINVAL;
					}
					/* event status timestamp not supported
					 * on CPE mode. Set msw and lsw to 0.
					 */
					user_v3->timestamp_lsw = 0;
					user_v3->timestamp_msw = 0;
					user_v3->status = lsm_d->ev_det_status;
					user_v3->payload_size =
							lsm_d->ev_det_pld_size;
					memcpy(user_v3->payload,
					       lsm_d->ev_det_payload,
					       lsm_d->ev_det_pld_size);
				}
			} else if (atomic_read(&lsm_d->event_stop) == 1) {
				dev_dbg(rtd->dev,
					"%s: wait_aborted\n", __func__);
				if (cmd == SNDRV_LSM_EVENT_STATUS) {
					user = arg;
					user->payload_size = 0;
				} else {
					user_v3 = arg;
					user_v3->payload_size = 0;
				}
				rc = 0;
			}
		}

	}
		break;

	case SNDRV_LSM_ABORT_EVENT:
@@ -1530,6 +1568,20 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
		}
		break;

	case SNDRV_LSM_SET_PORT: {
		u32 port_id = cpe->input_port_id;

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

	default:
		dev_dbg(rtd->dev,
			"%s: Default snd_lib_ioctl cmd 0x%x\n",
@@ -1541,7 +1593,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
}

static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
		struct snd_lsm_event_status *event_status)
		u16 event_det_status)
{
	struct snd_soc_pcm_runtime *rtd;
	struct cpe_lsm_data *lsm_d = NULL;
@@ -1594,7 +1646,7 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
	reinit_completion(&lab_d->thread_complete);

	if (session->lab_enable &&
	    event_status->status ==
	    event_det_status ==
	    LSM_VOICE_WAKEUP_STATUS_DETECTED) {
		out_port = &session->afe_out_port_cfg;
		out_port->port_id = session->afe_out_port_id;
@@ -2191,7 +2243,60 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
			goto done;
		}

		msm_cpe_lsm_lab_start(substream, event_status);
		msm_cpe_lsm_lab_start(substream, event_status->status);
		msm_cpe_process_event_status_done(lsm_d);
		kfree(event_status);
	}
		break;
	case SNDRV_LSM_EVENT_STATUS_V3: {
		struct snd_lsm_event_status_v3 u_event_status;
		struct snd_lsm_event_status_v3 *event_status = NULL;
		int u_pld_size = 0;

		if (copy_from_user(&u_event_status, (void *)arg,
				   sizeof(struct snd_lsm_event_status_v3))) {
			dev_err(rtd->dev,
				"%s: event status copy from user failed, size %zd\n",
				__func__,
				sizeof(struct snd_lsm_event_status_v3));
			err = -EFAULT;
			goto done;
		}

		if (u_event_status.payload_size >
		    LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
			dev_err(rtd->dev,
				"%s: payload_size %d is invalid, max allowed = %d\n",
				__func__, u_event_status.payload_size,
				LISTEN_MAX_STATUS_PAYLOAD_SIZE);
			err = -EINVAL;
			goto done;
		}

		u_pld_size = sizeof(struct snd_lsm_event_status_v3) +
				u_event_status.payload_size;

		event_status = kzalloc(u_pld_size, GFP_KERNEL);
		if (!event_status) {
			err = -ENOMEM;
			goto done;
		} else {
			event_status->payload_size =
				u_event_status.payload_size;
			err = msm_cpe_lsm_ioctl_shared(substream,
						       cmd, event_status);
		}

		if (!err  && copy_to_user(arg, event_status, u_pld_size)) {
			dev_err(rtd->dev,
				"%s: copy to user failed\n",
				__func__);
			kfree(event_status);
			err = -EFAULT;
			goto done;
		}

		msm_cpe_lsm_lab_start(substream, event_status->status);
		msm_cpe_process_event_status_done(lsm_d);
		kfree(event_status);
	}
@@ -2306,6 +2411,14 @@ struct snd_lsm_event_status32 {
	u8 payload[0];
};

struct snd_lsm_event_status_v3_32 {
	u32 timestamp_lsw;
	u32 timestamp_msw;
	u16 status;
	u16 payload_size;
	u8 payload[0];
};

struct snd_lsm_sound_model_v2_32 {
	compat_uptr_t data;
	compat_uptr_t confidence_level;
@@ -2345,6 +2458,8 @@ enum {
		_IOW('U', 0x0A, struct snd_lsm_detection_params_32),
	SNDRV_LSM_SET_MODULE_PARAMS_32 =
		_IOW('U', 0x0B, struct snd_lsm_module_params_32),
	SNDRV_LSM_EVENT_STATUS_V3_32 =
		_IOW('U', 0x0F, struct snd_lsm_event_status_v3_32),
};

static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
@@ -2513,7 +2628,98 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
			goto done;
		}

		msm_cpe_lsm_lab_start(substream, event_status);
		msm_cpe_lsm_lab_start(substream, event_status->status);
		msm_cpe_process_event_status_done(lsm_d);
		kfree(event_status);
		kfree(udata_32);
	}
		break;
	case SNDRV_LSM_EVENT_STATUS_V3_32: {
		struct snd_lsm_event_status_v3 *event_status = NULL;
		struct snd_lsm_event_status_v3_32 u_event_status32;
		struct snd_lsm_event_status_v3_32 *udata_32 = NULL;
		int u_pld_size = 0;

		dev_dbg(rtd->dev,
			"%s: ioctl %s\n", __func__,
			"SNDRV_LSM_EVENT_STATUS_V3_32");

		if (copy_from_user(&u_event_status32, (void *)arg,
				   sizeof(struct snd_lsm_event_status_v3))) {
			dev_err(rtd->dev,
				"%s: event status copy from user failed, size %zd\n",
				__func__,
				sizeof(struct snd_lsm_event_status_v3));
			err = -EFAULT;
			goto done;
		}

		if (u_event_status32.payload_size >
		   LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
			dev_err(rtd->dev,
				"%s: payload_size %d is invalid, max allowed = %d\n",
				__func__, u_event_status32.payload_size,
				LISTEN_MAX_STATUS_PAYLOAD_SIZE);
			err = -EINVAL;
			goto done;
		}

		u_pld_size = sizeof(struct snd_lsm_event_status_v3) +
				u_event_status32.payload_size;
		event_status = kzalloc(u_pld_size, GFP_KERNEL);
		if (!event_status) {
			dev_err(rtd->dev,
				"%s: No memory for event status\n",
				__func__);
			err = -ENOMEM;
			goto done;
		} else {
			event_status->payload_size =
				u_event_status32.payload_size;
			cmd = SNDRV_LSM_EVENT_STATUS_V3;
			err = msm_cpe_lsm_ioctl_shared(substream,
						       cmd, event_status);
			if (err)
				dev_err(rtd->dev,
					"%s: %s failed, error = %d\n",
					__func__,
					"SNDRV_LSM_EVENT_STATUS_V3_32",
					err);
		}

		if (!err) {
			udata_32 = kzalloc(u_pld_size, GFP_KERNEL);
			if (!udata_32) {
				dev_err(rtd->dev,
					"%s: nomem for udata\n",
					__func__);
				err = -EFAULT;
			} else {
				udata_32->timestamp_lsw =
					event_status->timestamp_lsw;
				udata_32->timestamp_msw =
					event_status->timestamp_msw;
				udata_32->status = event_status->status;
				udata_32->payload_size =
					event_status->payload_size;
				memcpy(udata_32->payload,
				       event_status->payload,
				       u_pld_size);
			}
		}

		if (!err  && copy_to_user(arg, udata_32,
					  u_pld_size)) {
			dev_err(rtd->dev,
				"%s: copy to user failed\n",
				__func__);
			kfree(event_status);
			kfree(udata_32);
			err = -EFAULT;
			goto done;
		}

		msm_cpe_lsm_lab_start(substream, event_status->status);
		msm_cpe_process_event_status_done(lsm_d);
		kfree(event_status);
		kfree(udata_32);
+6 −0
Original line number Diff line number Diff line
@@ -42,6 +42,12 @@
#define LAB_BUFFER_ALLOC 1
#define LAB_BUFFER_DEALLOC 0

/*
 * Driver ioctl will parse only so many params
 * size of LSM_PARAMS_MAX is last LSM_PARAM_TYPE + 1
 */
#define LSM_PARAMS_MAX (LSM_POLLING_ENABLE + 1)

static struct snd_pcm_hardware msm_pcm_hardware_capture = {
	.info =                 (SNDRV_PCM_INFO_MMAP |
				SNDRV_PCM_INFO_BLOCK_TRANSFER |