You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
376 lines
9.1 KiB
376 lines
9.1 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2012-2019. All rights reserved.
|
|
* Description: drv adsp
|
|
* Author: Audio
|
|
* Create: 2012-05-30
|
|
*/
|
|
|
|
#include "adsp_debug_ext.h"
|
|
|
|
#include "osal_ext.h"
|
|
|
|
#include "drv_adsp_private.h"
|
|
#include "drv_adsp_ext.h"
|
|
#include "dsp_resampler_ext.h"
|
|
|
|
#include "drv_adsp_hal.h"
|
|
#include "drv_adsp_cmd.h"
|
|
|
|
#include "drv_adsp_trace.h"
|
|
#include "audio_mem.h"
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
#include "drv_sys_ext.h"
|
|
#include "drv_sys_struct.h"
|
|
#include "drv_adsp_trace_proc.h"
|
|
#include "drv_adsp_fault_check.h"
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
static osal_semaphore g_adsp_mutex = {TD_NULL};
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
typedef enum {
|
|
ADSP_FC_ENABLE_STATE_UNKNOWN = -1,
|
|
ADSP_FC_ENABLE_STATE_DISABLE = 0,
|
|
ADSP_FC_ENABLE_STATE_ENABLE = 1,
|
|
} adsp_fault_check_enable_state;
|
|
|
|
static volatile aoe_regs_type *g_aoe_reg = TD_NULL;
|
|
static volatile adsp_fault_check_enable_state g_fault_check_state = ADSP_FC_ENABLE_STATE_UNKNOWN;
|
|
|
|
static ext_chip_revision get_chip_revision(td_void)
|
|
{
|
|
td_s32 ret;
|
|
ext_chip_revision chip_revision = CHIP_REVISION_MAX;
|
|
|
|
ret = ext_drv_sys_get_chip_revision(&chip_revision);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(ext_drv_sys_get_chip_revision, ret);
|
|
return CHIP_REVISION_MAX;
|
|
}
|
|
|
|
return chip_revision;
|
|
}
|
|
|
|
/* must be called after adsp_hal_load_fw */
|
|
static td_bool is_enable_fault_check(td_void)
|
|
{
|
|
if (g_fault_check_state == ADSP_FC_ENABLE_STATE_UNKNOWN) {
|
|
int ret;
|
|
aoe_fw_info fw_info;
|
|
ext_chip_revision revision = get_chip_revision();
|
|
if (revision != CHIP_REVISION_B && revision != CHIP_REVISION_C) {
|
|
g_fault_check_state = ADSP_FC_ENABLE_STATE_DISABLE;
|
|
return TD_FALSE;
|
|
}
|
|
|
|
memset_s(&fw_info, sizeof(fw_info), 0, sizeof(aoe_fw_info));
|
|
ret = adsp_hal_get_aoe_fw_info(&fw_info);
|
|
if (ret != TD_SUCCESS || fw_info.aoe_sw_flag == TD_TRUE) {
|
|
g_fault_check_state = ADSP_FC_ENABLE_STATE_DISABLE;
|
|
soc_log_info("disable faultcheck becasue of get_aoe_fw_info ret %d, aoe_sw_flag=%d\n",
|
|
ret, fw_info.aoe_sw_flag);
|
|
return TD_FALSE;
|
|
}
|
|
g_fault_check_state = ADSP_FC_ENABLE_STATE_ENABLE;
|
|
return TD_TRUE;
|
|
}
|
|
|
|
return (g_fault_check_state == ADSP_FC_ENABLE_STATE_ENABLE ? TD_TRUE : TD_FALSE);
|
|
}
|
|
#endif
|
|
|
|
static td_void drv_adsp_unload_aoe(td_void)
|
|
{
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
if (is_enable_fault_check() == TD_TRUE) {
|
|
adfc_deinit();
|
|
g_aoe_reg = TD_NULL;
|
|
}
|
|
#endif
|
|
|
|
adsp_hal_unload_aoe();
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
if (is_enable_fault_check() == TD_TRUE) {
|
|
trace_proc_deinit();
|
|
trace_adsp_deinit();
|
|
}
|
|
#endif
|
|
|
|
adsp_hal_unload_fw();
|
|
}
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
static td_s32 get_dsp_status(adfc_dsp_status *status)
|
|
{
|
|
volatile adsp_chn_regs_type *adsp_sys = TD_NULL;
|
|
|
|
if (status == TD_NULL) {
|
|
return TD_FAILURE;
|
|
}
|
|
|
|
if (g_aoe_reg == TD_NULL) {
|
|
aoe_fw_info fw_info;
|
|
td_s32 ret;
|
|
|
|
ret = adsp_hal_get_aoe_fw_info(&fw_info);
|
|
if (ret != TD_SUCCESS) {
|
|
return ret;
|
|
}
|
|
g_aoe_reg = (aoe_regs_type *)fw_info.aoe_reg.virt_addr;
|
|
if (g_aoe_reg == TD_NULL) {
|
|
soc_log_err("aoe_reg is NULL\n");
|
|
return TD_FAILURE;
|
|
}
|
|
}
|
|
adsp_sys = (volatile adsp_chn_regs_type *)((td_u8 *)g_aoe_reg + DSP0_SHARESRAM_SYS_OFFSET);
|
|
status->counter_value = adsp_sys->adsp_run_cnt;
|
|
status->run_position = g_aoe_reg->aoe_status0;
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
static td_s32 drv_adsp_load_aoe(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = adsp_hal_load_fw();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_hal_load_fw, ret);
|
|
return ret;
|
|
}
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
if (is_enable_fault_check() == TD_TRUE) {
|
|
trace_adsp_init();
|
|
trace_proc_init();
|
|
}
|
|
#endif
|
|
|
|
ret = adsp_hal_load_aoe();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_hal_load_aoe, ret);
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
if (is_enable_fault_check() == TD_TRUE) {
|
|
trace_proc_deinit();
|
|
trace_adsp_deinit();
|
|
}
|
|
#endif
|
|
adsp_hal_unload_fw();
|
|
return ret;
|
|
}
|
|
|
|
#if defined(ENABLE_FAULT_CHECK)
|
|
if (is_enable_fault_check() == TD_TRUE) {
|
|
adfc_param local_dfc_param;
|
|
|
|
memset_s(&local_dfc_param, sizeof(local_dfc_param), 0, sizeof(local_dfc_param));
|
|
local_dfc_param.get_dsp_status = get_dsp_status;
|
|
ret = adfc_init(&local_dfc_param);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("adfc_init return error %d\n", ret);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_void drv_adsp_unload_aflt(td_void)
|
|
{
|
|
adsp_hal_unload_aflt();
|
|
adsp_hal_unload_fw();
|
|
}
|
|
|
|
static td_s32 drv_adsp_load_aflt(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = adsp_hal_load_fw();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_hal_load_fw, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = adsp_hal_load_aflt();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_hal_load_aflt, ret);
|
|
adsp_hal_unload_fw();
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_adsp_load_firmware(adsp_code_id dsp_code_id)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = osal_sem_down_interruptible(&g_adsp_mutex);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(osal_sem_down_interruptible, ret);
|
|
return ret;
|
|
}
|
|
|
|
switch (dsp_code_id) {
|
|
case ADSP_CODE_AOE:
|
|
ret = drv_adsp_load_aoe();
|
|
break;
|
|
|
|
case ADSP_CODE_AFLT:
|
|
ret = drv_adsp_load_aflt();
|
|
break;
|
|
|
|
default:
|
|
soc_log_warn("unsupport dsp code id\n");
|
|
soc_warn_print_h32(dsp_code_id);
|
|
ret = SOC_ERR_ADSP_INVALID_PARA;
|
|
break;
|
|
}
|
|
|
|
osal_sem_up(&g_adsp_mutex);
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 drv_adsp_unload_firmware(adsp_code_id dsp_code_id)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = osal_sem_down_interruptible(&g_adsp_mutex);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(osal_sem_down_interruptible, ret);
|
|
return ret;
|
|
}
|
|
|
|
switch (dsp_code_id) {
|
|
case ADSP_CODE_AOE:
|
|
drv_adsp_unload_aoe();
|
|
break;
|
|
|
|
case ADSP_CODE_AFLT:
|
|
drv_adsp_unload_aflt();
|
|
break;
|
|
|
|
default:
|
|
soc_log_warn("unsupport dsp code id\n");
|
|
soc_warn_print_h32(dsp_code_id);
|
|
osal_sem_up(&g_adsp_mutex);
|
|
return SOC_ERR_ADSP_INVALID_PARA;
|
|
}
|
|
|
|
osal_sem_up(&g_adsp_mutex);
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
static td_s32 drv_adsp_get_aoe_fw_info(adsp_code_id dsp_code_id, aoe_fw_info *info)
|
|
{
|
|
td_s32 ret;
|
|
|
|
if (dsp_code_id != ADSP_CODE_AOE) {
|
|
return SOC_ERR_ADSP_INVALID_PARA;
|
|
}
|
|
|
|
ret = osal_sem_down_interruptible(&g_adsp_mutex);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(osal_sem_down_interruptible, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = adsp_hal_get_aoe_fw_info(info);
|
|
osal_sem_up(&g_adsp_mutex);
|
|
return ret;
|
|
}
|
|
|
|
static const adsp_export_func g_adsp_func = {
|
|
.adsp_load_firmware = drv_adsp_load_firmware,
|
|
.adsp_unload_firmware = drv_adsp_unload_firmware,
|
|
.adsp_get_aoe_fw_info = drv_adsp_get_aoe_fw_info,
|
|
.adsp_write_cmd = drv_adsp_write_cmd,
|
|
|
|
.mmz_alloc = ext_drv_audio_mmz_alloc,
|
|
.mmz_release = ext_drv_audio_mmz_release,
|
|
.sec_mmz_alloc = ext_drv_audio_sec_mmz_alloc,
|
|
.sec_mmz_release = ext_drv_audio_sec_mmz_release,
|
|
|
|
.smmu_alloc = ext_drv_audio_smmu_alloc,
|
|
.smmu_release = ext_drv_audio_smmu_release,
|
|
.sec_smmu_alloc = ext_drv_audio_sec_smmu_alloc,
|
|
.sec_smmu_release = ext_drv_audio_sec_smmu_release,
|
|
|
|
.adsp_src_create = drv_resampler_create,
|
|
.adsp_src_process = drv_resampler_process_frame,
|
|
.adsp_src_destroy = drv_resampler_destroy,
|
|
};
|
|
|
|
static inline td_void adsp_osal_deinit(td_void)
|
|
{
|
|
osal_sem_destroy(&g_adsp_mutex);
|
|
}
|
|
|
|
static inline td_s32 adsp_osal_init(td_void)
|
|
{
|
|
return osal_sem_init(&g_adsp_mutex, 1);
|
|
}
|
|
|
|
td_s32 adsp_drv_init(td_void)
|
|
{
|
|
td_s32 ret;
|
|
|
|
ret = osal_exportfunc_register(SOC_ID_ADSP, "SOC_ADSP", (td_void *)&g_adsp_func);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(osal_exportfunc_register, ret);
|
|
return ret;
|
|
}
|
|
|
|
ret = adsp_osal_init();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_osal_init, ret);
|
|
goto out0;
|
|
}
|
|
|
|
ret = adsp_hal_init();
|
|
if (ret != TD_SUCCESS) {
|
|
soc_fatal_print_call_fun_err(adsp_hal_init, ret);
|
|
goto out1;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
out1:
|
|
adsp_osal_deinit();
|
|
out0:
|
|
if (osal_exportfunc_unregister(SOC_ID_ADSP) != TD_SUCCESS) {
|
|
soc_log_err("call osal_exportfunc_unregister failed");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
td_void adsp_drv_exit(td_void)
|
|
{
|
|
adsp_hal_deinit();
|
|
adsp_osal_deinit();
|
|
|
|
if (osal_exportfunc_unregister(SOC_ID_ADSP) != TD_SUCCESS) {
|
|
soc_log_err("call osal_exportfunc_unregister failed");
|
|
}
|
|
}
|
|
|
|
td_s32 ext_drv_adsp_init(td_void)
|
|
{
|
|
return adsp_drv_init();
|
|
}
|
|
|
|
td_void ext_drv_adsp_deinit(td_void)
|
|
{
|
|
adsp_drv_exit();
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|