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

Commit 2fdf19ac authored by Harshal Ahire's avatar Harshal Ahire
Browse files

dsp: Add support for GET_PARAMS



Add support to query module parameters from ADSP.

Change-Id: Ie63dd95cf27277f9c836becc98952d48971a3ec3
Signed-off-by: default avatarHarshal Ahire <hahire@codeaurora.org>
parent d6f802b1
Loading
Loading
Loading
Loading
+177 −0
Original line number Diff line number Diff line
@@ -1894,6 +1894,17 @@ struct lsm_params_info_v2_32 {
	u32 model_id;
};

struct lsm_params_get_info_32 {
	u32 module_id;
	u16 instance_id;
	u16 reserved;
	u32 param_id;
	u32 param_size;
	uint32_t param_type;
	__u16 stage_idx;
	u8 payload[0];
} __packed;

struct snd_lsm_module_params_32 {
	compat_uptr_t params;
	u32 num_params;
@@ -1911,6 +1922,8 @@ enum {
		_IOW('U', 0x0F, struct snd_lsm_event_status_v3_32),
	SNDRV_LSM_SET_MODULE_PARAMS_V2_32 =
		_IOW('U', 0x13, struct snd_lsm_module_params_32),
	SNDRV_LSM_GET_MODULE_PARAMS_32 =
		_IOWR('U', 0x14, struct lsm_params_get_info_32),
};

#if IS_ENABLED(CONFIG_AUDIO_QGKI)
@@ -2300,6 +2313,95 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
		kfree(params32);
		break;
	}
	case SNDRV_LSM_GET_MODULE_PARAMS_32: {
		struct lsm_params_get_info_32 p_info_32, *param_info_rsp = NULL;
		struct lsm_params_get_info *p_info = NULL;

		memset(&p_info_32, 0 , sizeof(p_info_32));
		if (!prtd->lsm_client->use_topology) {
			dev_err(rtd->dev,
				"%s: %s: not supported if not using topology\n",
				__func__, "GET_MODULE_PARAMS_32");
			err = -EINVAL;
			goto done;
		}

		if (copy_from_user(&p_info_32, arg, sizeof(p_info_32))) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %zd\n",
				__func__, "GET_MODULE_PARAMS_32",
				sizeof(p_info_32));
			err = -EFAULT;
			goto done;
		}
		size = sizeof(p_info_32);
		p_info = kzalloc(size, GFP_KERNEL);

		if (!p_info) {
			err = -ENOMEM;
			goto done;
		}

		p_info->module_id = p_info_32.module_id;
		p_info->param_id = p_info_32.param_id;
		p_info->param_size = p_info_32.param_size;
		p_info->param_type = p_info_32.param_type;
		p_info->instance_id = p_info_32.instance_id;
		p_info->stage_idx = p_info_32.stage_idx;

		prtd->lsm_client->get_param_payload = kzalloc(p_info_32.param_size,
							      GFP_KERNEL);
		if (!prtd->lsm_client->get_param_payload) {
			err = -ENOMEM;
			kfree(p_info);
			goto done;
		}
		prtd->lsm_client->param_size = p_info_32.param_size;

		err = q6lsm_get_one_param(prtd->lsm_client, p_info,
					  LSM_GET_CUSTOM_PARAMS);
		if (err) {
			dev_err(rtd->dev,
				"%s: Failed to get custom param, err=%d\n",
				__func__, err);
			kfree(p_info);
			kfree(prtd->lsm_client->get_param_payload);
			goto done;
		}

		size = sizeof(p_info_32) + p_info_32.param_size;
		param_info_rsp = kzalloc(size, GFP_KERNEL);

		if (!param_info_rsp) {
			err = -ENOMEM;
			kfree(p_info);
			kfree(prtd->lsm_client->get_param_payload);
			goto done;
		}

		if (!access_ok(arg, size)) {
			dev_err(rtd->dev,
				"%s: Failed to verify write, size = %d\n",
				__func__, size);
			err = -EFAULT;
			goto free;
		}

		memcpy(param_info_rsp, &p_info_32, sizeof(p_info_32));
		memcpy(param_info_rsp->payload, prtd->lsm_client->get_param_payload,
			p_info_32.param_size);

		if (copy_to_user(arg, param_info_rsp, size)) {
			dev_err(rtd->dev, "%s: Failed to copy payload to user, size = %d\n",
				__func__, size);
			err = -EFAULT;
		}
free:
		kfree(p_info);
		kfree(param_info_rsp);
		kfree(prtd->lsm_client->get_param_payload);
		break;
	}
	case SNDRV_LSM_REG_SND_MODEL_V2:
	case SNDRV_LSM_SET_PARAMS:
	case SNDRV_LSM_SET_MODULE_PARAMS:
@@ -2522,6 +2624,81 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
		break;
	}

	case SNDRV_LSM_GET_MODULE_PARAMS: {
		struct lsm_params_get_info temp_p_info, *p_info = NULL;

		memset(&temp_p_info, 0, sizeof(temp_p_info));
		if (!prtd->lsm_client->use_topology) {
			dev_err(rtd->dev,
				"%s: %s: not supported if not using topology\n",
				__func__, "GET_MODULE_PARAMS_32");
			err = -EINVAL;
			goto done;
		}

		if (copy_from_user(&temp_p_info, arg, sizeof(temp_p_info))) {
			dev_err(rtd->dev,
				"%s: %s: copy_from_user failed, size = %zd\n",
				__func__, "GET_MODULE_PARAMS_32",
				sizeof(temp_p_info));
			err = -EFAULT;
			goto done;
		}
		size = sizeof(temp_p_info) +  temp_p_info.param_size;
		p_info = kzalloc(size, GFP_KERNEL);

		if (!p_info) {
			err = -ENOMEM;
			goto done;
		}

		p_info->module_id = temp_p_info.module_id;
		p_info->param_id = temp_p_info.param_id;
		p_info->param_size = temp_p_info.param_size;
		p_info->param_type = temp_p_info.param_type;
		p_info->instance_id = temp_p_info.instance_id;
		p_info->stage_idx = temp_p_info.stage_idx;

		prtd->lsm_client->get_param_payload = kzalloc(temp_p_info.param_size,
							      GFP_KERNEL);
		if (!prtd->lsm_client->get_param_payload) {
			err = -ENOMEM;
			kfree(p_info);
			goto done;
		}

		prtd->lsm_client->param_size =  p_info->param_size;
		err = q6lsm_get_one_param(prtd->lsm_client, p_info,
					  LSM_GET_CUSTOM_PARAMS);
		if (err) {
			dev_err(rtd->dev,
				"%s: Failed to get custom param, err=%d\n",
				__func__, err);
			goto free;
		}

		if (!access_ok(arg, size)) {
			dev_err(rtd->dev,
				"%s: Failed to verify write, size = %d\n",
				__func__, size);
			err = -EFAULT;
			goto free;
		}

		memcpy(p_info->payload, prtd->lsm_client->get_param_payload,
			temp_p_info.param_size);

		if (copy_to_user(arg, p_info, sizeof(struct lsm_params_get_info) +
				 p_info->param_size)) {
			dev_err(rtd->dev, "%s: Failed to copy payload to user, size = %d\n",
				__func__, size);
			err = -EFAULT;
		}
free:
		kfree(p_info);
		kfree(prtd->lsm_client->get_param_payload);
		break;
	}
	case SNDRV_LSM_EVENT_STATUS:
	case SNDRV_LSM_GENERIC_DET_EVENT: {
		struct snd_lsm_event_status *user = NULL;
+147 −0
Original line number Diff line number Diff line
@@ -190,6 +190,58 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
					client->priv);
		spin_unlock_irqrestore(&lsm_session_lock, flags);
		return 0;
	} else if (data->opcode == LSM_SESSION_CMDRSP_GET_PARAMS_V3 ||
		data->opcode == LSM_SESSION_CMDRSP_GET_PARAMS_V2) {

		uint32_t payload_min_size_expected = 0;
		uint32_t param_size = 0, ret = 0;
		/*
		 * sizeof(uint32_t) is added to accomodate the status field
		 * in adsp response payload
		 */

		if (data->opcode == LSM_SESSION_CMDRSP_GET_PARAMS_V3)
			payload_min_size_expected  =  sizeof(uint32_t) +
						sizeof(struct param_hdr_v3);
		else
			payload_min_size_expected  =  sizeof(uint32_t) +
						sizeof(struct param_hdr_v2);

		if (data->payload_size < payload_min_size_expected) {
			pr_err("%s: invalid payload size %d expected size %d\n",
				__func__, data->payload_size,
				payload_min_size_expected);
			ret = -EINVAL;
			goto done;
		}

		if (data->opcode == LSM_SESSION_CMDRSP_GET_PARAMS_V3)
			param_size = payload[4];
		else
			param_size = payload[3];

		if (data->payload_size != payload_min_size_expected + param_size) {
			pr_err("%s: cmdrsp_get_params error payload size %d expected size %d\n",
				__func__, data->payload_size,
				payload_min_size_expected + param_size);
			ret = -EINVAL;
			goto done;
		}

		if (client->param_size != param_size) {
			pr_err("%s: response payload size %d mismatched with user requested %d\n",
			    __func__, param_size, client->param_size);
			ret = -EINVAL;
			goto done;
		}

		memcpy((u8 *)client->get_param_payload,
			(u8 *)payload + payload_min_size_expected, param_size);
done:
		spin_unlock_irqrestore(&lsm_session_lock, flags);
		atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
		wake_up(&client->cmd_wait);
		return ret;
	} else if (data->opcode == APR_BASIC_RSP_RESULT) {
		token = data->token;
		switch (payload[0]) {
@@ -208,6 +260,8 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
		case LSM_CMD_ADD_TOPOLOGIES:
		case LSM_SESSION_CMD_SET_PARAMS_V2:
		case LSM_SESSION_CMD_SET_PARAMS_V3:
		case LSM_SESSION_CMD_GET_PARAMS_V2:
		case LSM_SESSION_CMD_GET_PARAMS_V3:
			if (token != client->session &&
			    payload[0] !=
				LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL) {
@@ -623,6 +677,48 @@ static int q6lsm_set_params_v3(struct lsm_client *client,
	return ret;
}

static int q6lsm_get_params_v2(struct lsm_client *client,
				struct mem_mapping_hdr *mem_hdr,
				struct param_hdr_v2 *param_hdr)
{
	struct lsm_session_cmd_get_params_v2 lsm_get_param;
	uint16_t pkt_size = sizeof(lsm_get_param);

	memset(&lsm_get_param, 0, pkt_size);
	q6lsm_add_hdr(client, &lsm_get_param.apr_hdr, pkt_size, true);
	lsm_get_param.apr_hdr.opcode = LSM_SESSION_CMD_GET_PARAMS_V2;

	if (mem_hdr != NULL)
		lsm_get_param.mem_hdr = *mem_hdr;

	memcpy(&lsm_get_param.param_info, param_hdr,
		sizeof(struct param_hdr_v2));

	return q6lsm_apr_send_pkt(client, client->apr, &lsm_get_param, true,
				 NULL);
}

static int q6lsm_get_params_v3(struct lsm_client *client,
				struct mem_mapping_hdr *mem_hdr,
				struct param_hdr_v3 *param_hdr)
{
	struct lsm_session_cmd_get_params_v3 lsm_get_param;
	uint16_t pkt_size = sizeof(lsm_get_param);

	memset(&lsm_get_param, 0, pkt_size);
	q6lsm_add_hdr(client, &lsm_get_param.apr_hdr, pkt_size, true);
	lsm_get_param.apr_hdr.opcode = LSM_SESSION_CMD_GET_PARAMS_V3;

	if (mem_hdr != NULL)
		lsm_get_param.mem_hdr = *mem_hdr;

	memcpy(&lsm_get_param.param_info, param_hdr,
		sizeof(struct param_hdr_v3));

	return q6lsm_apr_send_pkt(client, client->apr, &lsm_get_param, true,
				 NULL);
}

static int q6lsm_set_params(struct lsm_client *client,
			    struct mem_mapping_hdr *mem_hdr,
			    uint8_t *param_data, uint32_t param_size,
@@ -665,6 +761,27 @@ static int q6lsm_pack_and_set_params(struct lsm_client *client,
	return ret;
}

static int q6lsm_get_params(struct lsm_client *client,
				struct mem_mapping_hdr *mem_hdr,
				struct param_hdr_v3 *param_info)

{
	struct param_hdr_v2 param_info_v2;
	int ret = 0;
	bool iid_supported = q6common_is_instance_id_supported();
	memset(&param_info_v2, 0, sizeof(struct param_hdr_v2));

	if (iid_supported)
		ret = q6lsm_get_params_v3(client, mem_hdr, param_info);
	else {
		param_info_v2.module_id = param_info->module_id;
		param_info_v2.param_id = param_info->param_id;
		param_info_v2.param_size = param_info->param_size;
		ret = q6lsm_get_params_v2(client, mem_hdr, &param_info_v2);
	}
	return ret;
}

static int q6lsm_send_custom_topologies(struct lsm_client *client)
{
	int rc;
@@ -2403,6 +2520,36 @@ int q6lsm_set_one_param(struct lsm_client *client,
}
EXPORT_SYMBOL(q6lsm_set_one_param);

int q6lsm_get_one_param(struct lsm_client *client,
		struct lsm_params_get_info *p_info,
		uint32_t param_type)
{
	struct param_hdr_v3 param_info;
	int rc = 0;

	memset(&param_info, 0, sizeof(param_info));

	switch (param_type) {
	case LSM_GET_CUSTOM_PARAMS: {
		param_info.module_id = p_info->module_id;
		param_info.instance_id = p_info->instance_id;
		param_info.param_id = p_info->param_id;
		param_info.param_size = p_info->param_size + sizeof(param_info);
		rc = q6lsm_get_params(client, NULL, &param_info);
		if (rc) {
			pr_err("%s: LSM_GET_CUSTOM_PARAMS failed, rc %d\n",
				__func__, rc);
		}
		break;

	}
	default:
		pr_err("%s: wrong param_type 0x%x\n",
			__func__, p_info->param_type);
	}
	return rc;
}
EXPORT_SYMBOL(q6lsm_get_one_param);

/**
 * q6lsm_start -
+4 −0
Original line number Diff line number Diff line
@@ -11717,6 +11717,10 @@ struct avcs_fwk_ver_info {
#define LSM_SESSION_CMD_SET_PARAMS			(0x00012A83)
#define LSM_SESSION_CMD_SET_PARAMS_V2			(0x00012A8F)
#define LSM_SESSION_CMD_SET_PARAMS_V3			(0x00012A92)
#define LSM_SESSION_CMD_GET_PARAMS_V2			(0x00012A90)
#define LSM_SESSION_CMDRSP_GET_PARAMS_V2		(0x00012A91)
#define LSM_SESSION_CMD_GET_PARAMS_V3			(0x00012A93)
#define LSM_SESSION_CMDRSP_GET_PARAMS_V3		(0x00012A94)
#define LSM_SESSION_CMD_REGISTER_SOUND_MODEL		(0x00012A84)
#define LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL		(0x00012A85)
#define LSM_SESSION_CMD_START				(0x00012A86)
+17 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ struct lsm_client {
	uint32_t	num_sound_models;
	uint32_t	num_keywords;
	uint32_t	*multi_snd_model_confidence_levels;
	void		*get_param_payload;
	size_t		param_size;
};

struct lsm_stream_cmd_open_tx {
@@ -163,6 +165,18 @@ struct lsm_session_cmd_set_params_v3 {
	u32 param_data[0];
} __packed;

struct lsm_session_cmd_get_params_v2 {
	struct apr_hdr apr_hdr;
	struct mem_mapping_hdr mem_hdr;
	struct param_hdr_v2 param_info;
} __packed;

struct lsm_session_cmd_get_params_v3 {
	struct apr_hdr apr_hdr;
	struct mem_mapping_hdr mem_hdr;
	struct param_hdr_v3 param_info;
} __packed;

struct lsm_param_op_mode {
	uint32_t	minor_version;
	uint16_t	mode;
@@ -304,6 +318,9 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc);
int q6lsm_set_one_param(struct lsm_client *client,
			struct lsm_params_info_v2 *p_info, void *data,
			uint32_t param_type);
int q6lsm_get_one_param(struct lsm_client *client,
			struct lsm_params_get_info *p_info,
			uint32_t param_type);
void q6lsm_sm_set_param_data(struct lsm_client *client,
		struct lsm_params_info_v2 *p_info, size_t *offset,
		struct lsm_sound_model *sm);
+27 −2
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@
#define LSM_REG_MULTI_SND_MODEL (10)
#define LSM_DEREG_MULTI_SND_MODEL (11)
#define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12)
#define LSM_PARAMS_MAX (LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS + 1)
#define LSM_GET_CUSTOM_PARAMS (13)
#define LSM_PARAMS_MAX (LSM_GET_CUSTOM_PARAMS + 1)

#define LSM_EVENT_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1)
@@ -288,6 +289,29 @@ struct snd_lsm_input_hw_params {
	__u16 num_channels;
} __packed;

/*
 * Param get info  for each parameter type
 * add "for SNDRV_LSM_GET_MODULE_PARAMS ioctl"
 * Existing member variables:
 * @module_id: Module to which parameter is to be set
 * @instance_id: instance id of the param to which parameter is to be set
 * @param_id: Parameter that is to be set
 * @param_size: size of requested param
 * @param_type: Parameter type as defined in values upto LSM_PARAMS_MAX
 * @stage_idx: detection stage for which the param is applicable
 * @payload: memory where requested param info will be populated
 */
struct lsm_params_get_info {
	__u32 module_id;
	__u16 instance_id;
	__u16 reserved;
	__u32 param_id;
	__u32 param_size;
	__u32 param_type;
	__u16 stage_idx;
	__u8 payload[0];
} __packed;

#define SNDRV_LSM_DEREG_SND_MODEL _IOW('U', 0x01, int)
#define SNDRV_LSM_EVENT_STATUS	_IOW('U', 0x02, struct snd_lsm_event_status)
#define SNDRV_LSM_ABORT_EVENT	_IOW('U', 0x03, int)
@@ -315,5 +339,6 @@ struct snd_lsm_input_hw_params {
					struct snd_lsm_session_data_v2)
#define SNDRV_LSM_SET_MODULE_PARAMS_V2 _IOW('U', 0x13, \
					struct snd_lsm_module_params)

#define SNDRV_LSM_GET_MODULE_PARAMS _IOWR('U', 0x14, \
					struct lsm_params_get_info)
#endif