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

/*
* 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 */