ASoC: audio: add APIs to query for AVS version
Add APIs to query for the AVS framework and services versions. Cache the information retrieved for use by HLOS services. CRs-Fixed: 2018143 Signed-off-by: Siena Richard <sienar@codeaurora.org> Change-Id: I6c262e7302a9b69f5fdd22762122a8db72c8c274
This commit is contained in:
parent
812c879d35
commit
4edea86ce5
3 changed files with 202 additions and 7 deletions
|
@ -9349,6 +9349,73 @@ struct asm_aptx_dec_fmt_blk_v2 {
|
|||
*/
|
||||
} __packed;
|
||||
|
||||
/* Q6Core Specific */
|
||||
#define AVCS_CMD_GET_FWK_VERSION (0x0001292C)
|
||||
#define AVCS_CMDRSP_GET_FWK_VERSION (0x0001292D)
|
||||
|
||||
#define AVCS_SERVICE_ID_ALL (0xFFFFFFFF)
|
||||
|
||||
struct avcs_get_fwk_version {
|
||||
/*
|
||||
* Indicates the major version of the AVS build.
|
||||
* This value is incremented on chipset family boundaries.
|
||||
*/
|
||||
uint32_t build_major_version;
|
||||
|
||||
/*
|
||||
* Minor version of the AVS build.
|
||||
* This value represents the mainline to which the AVS build belongs.
|
||||
*/
|
||||
uint32_t build_minor_version;
|
||||
|
||||
/* Indicates the AVS branch version to which the image belongs. */
|
||||
uint32_t build_branch_version;
|
||||
|
||||
/* Indicates the AVS sub-branch or customer product line information. */
|
||||
uint32_t build_subbranch_version;
|
||||
|
||||
/* Number of supported AVS services in the current build. */
|
||||
uint32_t num_services;
|
||||
};
|
||||
|
||||
struct avs_svc_api_info {
|
||||
/*
|
||||
* APRV2 service IDs for the individual static services.
|
||||
*
|
||||
* @values
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_CORE_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_AFE_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_ASM_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_ADM_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_MVM_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_CVS_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_CVP_V
|
||||
* - APRV2_IDS_SERVICE_ID_ADSP_LSM_V
|
||||
*/
|
||||
uint32_t service_id;
|
||||
|
||||
/*
|
||||
* Indicates the API version of the service.
|
||||
*
|
||||
* Each new API update that warrants a change on the HLOS side triggers
|
||||
* an increment in the version.
|
||||
*/
|
||||
uint32_t api_version;
|
||||
|
||||
/*
|
||||
* Indicates the API increments on a sub-branch (not on the mainline).
|
||||
*
|
||||
* API branch version numbers can increment independently on different
|
||||
* sub-branches.
|
||||
*/
|
||||
uint32_t api_branch_version;
|
||||
};
|
||||
|
||||
struct avcs_fwk_ver_info {
|
||||
struct avcs_get_fwk_version avcs_build;
|
||||
struct avs_svc_api_info services[0];
|
||||
};
|
||||
|
||||
/* LSM Specific */
|
||||
#define VW_FEAT_DIM (39)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2012-2016, 2017 The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -13,6 +13,7 @@
|
|||
#ifndef __Q6CORE_H__
|
||||
#define __Q6CORE_H__
|
||||
#include <linux/qdsp6v2/apr.h>
|
||||
#include <sound/apr_audio-v2.h>
|
||||
|
||||
|
||||
|
||||
|
@ -23,6 +24,9 @@ bool q6core_is_adsp_ready(void);
|
|||
int q6core_add_remove_pool_pages(phys_addr_t buf_add, uint32_t bufsz,
|
||||
uint32_t mempool_id, bool add_pages);
|
||||
|
||||
int q6core_get_avcs_fwk_ver_info(uint32_t service_id,
|
||||
struct avcs_fwk_ver_info *ver_info);
|
||||
|
||||
#define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919
|
||||
#define DTS_EAGLE_LICENSE_ID 0x00028346
|
||||
struct adsp_dts_eagle {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <soc/qcom/smd.h>
|
||||
#include <sound/q6core.h>
|
||||
#include <sound/audio_cal_utils.h>
|
||||
#include <sound/adsp_err.h>
|
||||
|
||||
#define TIMEOUT_MS 1000
|
||||
/*
|
||||
|
@ -37,16 +38,30 @@ enum {
|
|||
CORE_MAX_CAL
|
||||
};
|
||||
|
||||
enum ver_query_status {
|
||||
VER_QUERY_UNATTEMPTED,
|
||||
VER_QUERY_UNSUPPORTED,
|
||||
VER_QUERY_SUPPORTED
|
||||
};
|
||||
|
||||
struct q6core_avcs_ver_info {
|
||||
enum ver_query_status status;
|
||||
struct avcs_fwk_ver_info avcs_fwk_ver_info;
|
||||
};
|
||||
|
||||
struct q6core_str {
|
||||
struct apr_svc *core_handle_q;
|
||||
wait_queue_head_t bus_bw_req_wait;
|
||||
wait_queue_head_t cmd_req_wait;
|
||||
wait_queue_head_t avcs_fwk_ver_req_wait;
|
||||
u32 bus_bw_resp_received;
|
||||
enum cmd_flags {
|
||||
FLAG_NONE,
|
||||
FLAG_CMDRSP_LICENSE_RESULT
|
||||
} cmd_resp_received_flag;
|
||||
u32 avcs_fwk_ver_resp_received;
|
||||
struct mutex cmd_lock;
|
||||
struct mutex ver_lock;
|
||||
union {
|
||||
struct avcs_cmdrsp_get_license_validation_result
|
||||
cmdrsp_license_result;
|
||||
|
@ -55,6 +70,7 @@ struct q6core_str {
|
|||
struct cal_type_data *cal_data[CORE_MAX_CAL];
|
||||
uint32_t mem_map_cal_handle;
|
||||
int32_t adsp_status;
|
||||
struct q6core_avcs_ver_info q6core_avcs_ver_info;
|
||||
};
|
||||
|
||||
static struct q6core_str q6core_lcl;
|
||||
|
@ -131,6 +147,17 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
|
|||
q6core_lcl.bus_bw_resp_received = 1;
|
||||
wake_up(&q6core_lcl.bus_bw_req_wait);
|
||||
break;
|
||||
case AVCS_CMD_GET_FWK_VERSION:
|
||||
pr_debug("%s: Cmd = AVCS_CMD_GET_FWK_VERSION status[%s]\n",
|
||||
__func__, adsp_err_get_err_str(payload1[1]));
|
||||
/* ADSP status to match Linux error standard */
|
||||
q6core_lcl.adsp_status = -payload1[1];
|
||||
if (payload1[1] == ADSP_EUNSUPPORTED)
|
||||
q6core_lcl.q6core_avcs_ver_info.status =
|
||||
VER_QUERY_UNSUPPORTED;
|
||||
q6core_lcl.avcs_fwk_ver_resp_received = 1;
|
||||
wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
|
||||
__func__,
|
||||
|
@ -174,6 +201,13 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
|
|||
q6core_lcl.cmd_resp_received_flag = FLAG_CMDRSP_LICENSE_RESULT;
|
||||
wake_up(&q6core_lcl.cmd_req_wait);
|
||||
break;
|
||||
case AVCS_CMDRSP_GET_FWK_VERSION:
|
||||
pr_debug("%s: Received AVCS_CMDRSP_GET_FWK_VERSION\n",
|
||||
__func__);
|
||||
q6core_lcl.q6core_avcs_ver_info.status = VER_QUERY_SUPPORTED;
|
||||
q6core_lcl.avcs_fwk_ver_resp_received = 1;
|
||||
wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Message id from adsp core svc: 0x%x\n",
|
||||
__func__, data->opcode);
|
||||
|
@ -230,6 +264,97 @@ struct cal_block_data *cal_utils_get_cal_block_by_key(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int q6core_send_get_avcs_fwk_ver_cmd(void)
|
||||
{
|
||||
struct apr_hdr avcs_ver_cmd;
|
||||
int ret;
|
||||
|
||||
avcs_ver_cmd.hdr_field =
|
||||
APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
|
||||
APR_PKT_VER);
|
||||
avcs_ver_cmd.pkt_size = sizeof(struct apr_hdr);
|
||||
avcs_ver_cmd.src_port = 0;
|
||||
avcs_ver_cmd.dest_port = 0;
|
||||
avcs_ver_cmd.token = 0;
|
||||
avcs_ver_cmd.opcode = AVCS_CMD_GET_FWK_VERSION;
|
||||
|
||||
q6core_lcl.adsp_status = 0;
|
||||
q6core_lcl.avcs_fwk_ver_resp_received = 0;
|
||||
|
||||
ret = apr_send_pkt(q6core_lcl.core_handle_q,
|
||||
(uint32_t *) &avcs_ver_cmd);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to send apr packet, ret=%d\n", __func__,
|
||||
ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = wait_event_timeout(q6core_lcl.avcs_fwk_ver_req_wait,
|
||||
(q6core_lcl.avcs_fwk_ver_resp_received == 1),
|
||||
msecs_to_jiffies(TIMEOUT_MS));
|
||||
if (!ret) {
|
||||
pr_err("%s: wait_event timeout for AVCS fwk version info\n",
|
||||
__func__);
|
||||
ret = -ETIMEDOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (q6core_lcl.adsp_status < 0) {
|
||||
/*
|
||||
* adsp_err_get_err_str expects a positive value but we store
|
||||
* the DSP error as negative to match the Linux error standard.
|
||||
* Pass in the negated value so adsp_err_get_err_str returns
|
||||
* the correct string.
|
||||
*/
|
||||
pr_err("%s: DSP returned error[%s]\n", __func__,
|
||||
adsp_err_get_err_str(-q6core_lcl.adsp_status));
|
||||
ret = adsp_err_get_lnx_err_code(q6core_lcl.adsp_status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int q6core_get_avcs_fwk_ver_info(uint32_t service_id,
|
||||
struct avcs_fwk_ver_info *ver_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&(q6core_lcl.ver_lock));
|
||||
pr_debug("%s: q6core_avcs_ver_info.status(%d)\n", __func__,
|
||||
q6core_lcl.q6core_avcs_ver_info.status);
|
||||
|
||||
switch (q6core_lcl.q6core_avcs_ver_info.status) {
|
||||
case VER_QUERY_SUPPORTED:
|
||||
ret = 0;
|
||||
break;
|
||||
case VER_QUERY_UNSUPPORTED:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
case VER_QUERY_UNATTEMPTED:
|
||||
if (q6core_is_adsp_ready()) {
|
||||
ret = q6core_send_get_avcs_fwk_ver_cmd();
|
||||
} else {
|
||||
pr_err("%s: ADSP is not ready to query version\n",
|
||||
__func__);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid version query status %d\n", __func__,
|
||||
q6core_lcl.q6core_avcs_ver_info.status);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&(q6core_lcl.ver_lock));
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(q6core_get_avcs_fwk_ver_info);
|
||||
|
||||
int32_t core_set_license(uint32_t key, uint32_t module_id)
|
||||
{
|
||||
struct avcs_cmd_set_license *cmd_setl = NULL;
|
||||
|
@ -887,18 +1012,16 @@ err:
|
|||
|
||||
static int __init core_init(void)
|
||||
{
|
||||
memset(&q6core_lcl, 0, sizeof(struct q6core_str));
|
||||
init_waitqueue_head(&q6core_lcl.bus_bw_req_wait);
|
||||
q6core_lcl.bus_bw_resp_received = 0;
|
||||
|
||||
q6core_lcl.core_handle_q = NULL;
|
||||
|
||||
init_waitqueue_head(&q6core_lcl.cmd_req_wait);
|
||||
init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait);
|
||||
q6core_lcl.cmd_resp_received_flag = FLAG_NONE;
|
||||
mutex_init(&q6core_lcl.cmd_lock);
|
||||
q6core_lcl.mem_map_cal_handle = 0;
|
||||
q6core_lcl.adsp_status = 0;
|
||||
mutex_init(&q6core_lcl.ver_lock);
|
||||
|
||||
q6core_init_cal_data();
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(core_init);
|
||||
|
@ -906,6 +1029,7 @@ module_init(core_init);
|
|||
static void __exit core_exit(void)
|
||||
{
|
||||
mutex_destroy(&q6core_lcl.cmd_lock);
|
||||
mutex_destroy(&q6core_lcl.ver_lock);
|
||||
q6core_delete_cal_data();
|
||||
}
|
||||
module_exit(core_exit);
|
||||
|
|
Loading…
Add table
Reference in a new issue