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

Commit dc148417 authored by Chaithanya Krishna Bacharaju's avatar Chaithanya Krishna Bacharaju Committed by Revathi Uddaraju
Browse files

ASoC: msm-cpe: Add timestamp support for lsm event status



Add timestamp support in cases where event status requires
timestamp corresponding to detection.
Timestamp mode is not supported currently in CPE SVA.

Change-Id: I157c77bba5aa2b9d0cc9dcbdfaba405554301611
Signed-off-by: default avatarChaithanya Krishna Bacharaju <chaithan@codeaurora.org>
Signed-off-by: default avatarRevathi Uddaraju <revathiu@codeaurora.org>
parent cc7fe306
Loading
Loading
Loading
Loading
+213 −27
Original line number Diff line number Diff line
@@ -1066,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;

@@ -1342,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
@@ -1374,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,
@@ -1385,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:
@@ -1561,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;
@@ -1614,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;
@@ -2211,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);
	}
@@ -2326,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;
@@ -2365,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,
@@ -2533,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);