dsp: Add support for GET_PARAMS

Add support to query module parameters from ADSP.

Change-Id: Ie63dd95cf27277f9c836becc98952d48971a3ec3
Signed-off-by: Harshal Ahire <hahire@codeaurora.org>
This commit is contained in:
Harshal Ahire 2020-08-04 13:17:51 +05:30
parent d6f802b1cb
commit 2fdf19ac8e
5 changed files with 372 additions and 2 deletions

View File

@ -1894,6 +1894,17 @@ struct lsm_params_info_v2_32 {
u32 model_id; 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 { struct snd_lsm_module_params_32 {
compat_uptr_t params; compat_uptr_t params;
u32 num_params; u32 num_params;
@ -1911,6 +1922,8 @@ enum {
_IOW('U', 0x0F, struct snd_lsm_event_status_v3_32), _IOW('U', 0x0F, struct snd_lsm_event_status_v3_32),
SNDRV_LSM_SET_MODULE_PARAMS_V2_32 = SNDRV_LSM_SET_MODULE_PARAMS_V2_32 =
_IOW('U', 0x13, struct snd_lsm_module_params_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) #if IS_ENABLED(CONFIG_AUDIO_QGKI)
@ -2300,6 +2313,95 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
kfree(params32); kfree(params32);
break; 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_REG_SND_MODEL_V2:
case SNDRV_LSM_SET_PARAMS: case SNDRV_LSM_SET_PARAMS:
case SNDRV_LSM_SET_MODULE_PARAMS: case SNDRV_LSM_SET_MODULE_PARAMS:
@ -2522,6 +2624,81 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
break; 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_EVENT_STATUS:
case SNDRV_LSM_GENERIC_DET_EVENT: { case SNDRV_LSM_GENERIC_DET_EVENT: {
struct snd_lsm_event_status *user = NULL; struct snd_lsm_event_status *user = NULL;

View File

@ -190,6 +190,58 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
client->priv); client->priv);
spin_unlock_irqrestore(&lsm_session_lock, flags); spin_unlock_irqrestore(&lsm_session_lock, flags);
return 0; 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) { } else if (data->opcode == APR_BASIC_RSP_RESULT) {
token = data->token; token = data->token;
switch (payload[0]) { 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_CMD_ADD_TOPOLOGIES:
case LSM_SESSION_CMD_SET_PARAMS_V2: case LSM_SESSION_CMD_SET_PARAMS_V2:
case LSM_SESSION_CMD_SET_PARAMS_V3: 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 && if (token != client->session &&
payload[0] != payload[0] !=
LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL) { LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL) {
@ -623,6 +677,48 @@ done:
return ret; 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, static int q6lsm_set_params(struct lsm_client *client,
struct mem_mapping_hdr *mem_hdr, struct mem_mapping_hdr *mem_hdr,
uint8_t *param_data, uint32_t param_size, uint8_t *param_data, uint32_t param_size,
@ -665,6 +761,27 @@ done:
return ret; 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) static int q6lsm_send_custom_topologies(struct lsm_client *client)
{ {
int rc; int rc;
@ -2403,6 +2520,36 @@ int q6lsm_set_one_param(struct lsm_client *client,
} }
EXPORT_SYMBOL(q6lsm_set_one_param); 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 - * q6lsm_start -

View File

@ -11717,6 +11717,10 @@ struct avcs_fwk_ver_info {
#define LSM_SESSION_CMD_SET_PARAMS (0x00012A83) #define LSM_SESSION_CMD_SET_PARAMS (0x00012A83)
#define LSM_SESSION_CMD_SET_PARAMS_V2 (0x00012A8F) #define LSM_SESSION_CMD_SET_PARAMS_V2 (0x00012A8F)
#define LSM_SESSION_CMD_SET_PARAMS_V3 (0x00012A92) #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_REGISTER_SOUND_MODEL (0x00012A84)
#define LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL (0x00012A85) #define LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL (0x00012A85)
#define LSM_SESSION_CMD_START (0x00012A86) #define LSM_SESSION_CMD_START (0x00012A86)

View File

@ -116,6 +116,8 @@ struct lsm_client {
uint32_t num_sound_models; uint32_t num_sound_models;
uint32_t num_keywords; uint32_t num_keywords;
uint32_t *multi_snd_model_confidence_levels; uint32_t *multi_snd_model_confidence_levels;
void *get_param_payload;
size_t param_size;
}; };
struct lsm_stream_cmd_open_tx { struct lsm_stream_cmd_open_tx {
@ -163,6 +165,18 @@ struct lsm_session_cmd_set_params_v3 {
u32 param_data[0]; u32 param_data[0];
} __packed; } __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 { struct lsm_param_op_mode {
uint32_t minor_version; uint32_t minor_version;
uint16_t mode; 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, int q6lsm_set_one_param(struct lsm_client *client,
struct lsm_params_info_v2 *p_info, void *data, struct lsm_params_info_v2 *p_info, void *data,
uint32_t param_type); 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, void q6lsm_sm_set_param_data(struct lsm_client *client,
struct lsm_params_info_v2 *p_info, size_t *offset, struct lsm_params_info_v2 *p_info, size_t *offset,
struct lsm_sound_model *sm); struct lsm_sound_model *sm);

View File

@ -36,7 +36,8 @@
#define LSM_REG_MULTI_SND_MODEL (10) #define LSM_REG_MULTI_SND_MODEL (10)
#define LSM_DEREG_MULTI_SND_MODEL (11) #define LSM_DEREG_MULTI_SND_MODEL (11)
#define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12) #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_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1) #define LSM_EVENT_TIME_STAMP_MODE (1)
@ -288,6 +289,29 @@ struct snd_lsm_input_hw_params {
__u16 num_channels; __u16 num_channels;
} __packed; } __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_DEREG_SND_MODEL _IOW('U', 0x01, int)
#define SNDRV_LSM_EVENT_STATUS _IOW('U', 0x02, struct snd_lsm_event_status) #define SNDRV_LSM_EVENT_STATUS _IOW('U', 0x02, struct snd_lsm_event_status)
#define SNDRV_LSM_ABORT_EVENT _IOW('U', 0x03, int) #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) struct snd_lsm_session_data_v2)
#define SNDRV_LSM_SET_MODULE_PARAMS_V2 _IOW('U', 0x13, \ #define SNDRV_LSM_SET_MODULE_PARAMS_V2 _IOW('U', 0x13, \
struct snd_lsm_module_params) struct snd_lsm_module_params)
#define SNDRV_LSM_GET_MODULE_PARAMS _IOWR('U', 0x14, \
struct lsm_params_get_info)
#endif #endif