summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarshal Ahire <hahire@codeaurora.org>2020-07-07 15:45:49 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2020-08-18 11:36:31 -0700
commit370519bcdeb6c1907d21498bceed51eba88c90a7 (patch)
tree42e832ad427be6636210957699f52d44afcd7ffe
parent316a9c27cb8d770c353a376b2bebaf53f7df0779 (diff)
downloadmsm-extra-370519bcdeb6c1907d21498bceed51eba88c90a7.tar.gz
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>
-rw-r--r--asoc/msm-lsm-client.c177
-rw-r--r--dsp/q6lsm.c147
-rw-r--r--include/dsp/apr_audio-v2.h4
-rw-r--r--include/dsp/q6lsm.h17
-rw-r--r--include/uapi/sound/lsm_params.h29
5 files changed, 372 insertions, 2 deletions
diff --git a/asoc/msm-lsm-client.c b/asoc/msm-lsm-client.c
index 8a179fde..77b25de1 100644
--- a/asoc/msm-lsm-client.c
+++ b/asoc/msm-lsm-client.c
@@ -1700,6 +1700,17 @@ struct lsm_params_info_v2_32 {
u16 stage_idx;
};
+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;
@@ -1717,6 +1728,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),
};
static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
@@ -2096,6 +2109,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(VERIFY_WRITE, 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:
@@ -2303,6 +2405,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(VERIFY_WRITE, 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;
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index c00bb940..cc57a253 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -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 @@ done:
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 @@ done:
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;
@@ -2313,6 +2430,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 -
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index 607b9101..eed5652f 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -11694,6 +11694,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)
diff --git a/include/dsp/q6lsm.h b/include/dsp/q6lsm.h
index 02897d98..d5d6ad63 100644
--- a/include/dsp/q6lsm.h
+++ b/include/dsp/q6lsm.h
@@ -106,6 +106,8 @@ struct lsm_client {
struct lsm_stage_config stage_cfg[LSM_MAX_STAGES_PER_SESSION];
uint64_t fe_id;
uint16_t unprocessed_data;
+ void *get_param_payload;
+ size_t param_size;
};
struct lsm_stream_cmd_open_tx {
@@ -153,6 +155,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;
@@ -289,6 +303,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);
diff --git a/include/uapi/sound/lsm_params.h b/include/uapi/sound/lsm_params.h
index 57dc3be5..8e1a3d6b 100644
--- a/include/uapi/sound/lsm_params.h
+++ b/include/uapi/sound/lsm_params.h
@@ -34,7 +34,8 @@
#define LSM_POLLING_ENABLE (7)
#define LSM_DET_EVENT_TYPE (8)
#define LSM_LAB_CONTROL (9)
-#define LSM_PARAMS_MAX (LSM_LAB_CONTROL + 1)
+#define LSM_GET_CUSTOM_PARAMS (10)
+#define LSM_PARAMS_MAX (LSM_GET_CUSTOM_PARAMS + 1)
#define LSM_EVENT_NON_TIME_STAMP_MODE (0)
#define LSM_EVENT_TIME_STAMP_MODE (1)
@@ -284,6 +285,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;
+ uint32_t 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)
@@ -311,5 +335,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