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.

639 lines
17 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
* Description: aflt device and driver
* Author: audio
* Create: 2019-05-30
*/
#include "hal_aflt.h"
#include "osal_ext.h"
#include "drv_sys_ext.h"
#include "audsp_aflt_ext.h"
#include "drv_aflt_debug.h"
#include "drv_ioctl_aflt.h"
#include "soc_errno.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
static volatile ext_aflt_chan_reg *g_aflt_chn_reg[AFLT_MAX_CHAN_NUM] = { TD_NULL };
static td_bool g_sw_aflt_flag = TD_TRUE; /* TD_TRUE: sw; TD_FALSE: hw */
static td_void aflt_io_address_map(td_u8 *reg)
{
td_u32 id;
if (reg == TD_NULL) {
soc_log_fatal("reg is NULL\n");
return;
}
reg += DSP0_SHARESRAM_AFLT_OFFSET + AFLT_CHN_REG_OFFSET;
for (id = 0; id < AFLT_MAX_CHAN_NUM; id++) {
g_aflt_chn_reg[id] = (ext_aflt_chan_reg *)(reg + AFLT_CHN_REG_BANDSIZE * id);
}
}
static td_void aflt_io_address_unmap(td_void)
{
td_u32 id;
for (id = 0; id < AFLT_MAX_CHAN_NUM; id++) {
g_aflt_chn_reg[id] = TD_NULL;
}
}
static ext_aflt_chan_reg *aflt_hal_get_chan_reg(td_u32 aflt_id)
{
if (aflt_id >= AFLT_MAX_CHAN_NUM) {
return TD_NULL;
}
return (ext_aflt_chan_reg *)g_aflt_chn_reg[aflt_id];
}
static aflt_cmd_ret i_hal_aflt_ack_cmd(const ext_aflt_chan_reg *aflt_reg)
{
volatile td_u32 loop_outer;
volatile td_u32 loop_inner;
for (loop_outer = 0; loop_outer < 100; loop_outer++) { /* 100 is a number */
for (loop_inner = 0; loop_inner < 8; loop_inner++) { /* 8 is a number */
if (aflt_reg->ctrl.bits.cmd_done) {
return (aflt_cmd_ret)aflt_reg->ctrl.bits.cmd_return_value;
}
osal_udelay(10); /* 10us */
}
osal_msleep(1);
}
return AFLT_CMD_ERR_TIMEOUT;
}
static td_s32 i_hal_aflt_set_cmd(td_u32 aflt_id, aflt_cmd cmd)
{
aflt_cmd_ret ack;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
switch (cmd) {
case AFLT_CMD_CREATE:
case AFLT_CMD_DESTROY:
case AFLT_CMD_START:
case AFLT_CMD_STOP:
case AFLT_CMD_SETPARAM:
case AFLT_CMD_GETPARAM:
case AFLT_CMD_SETCONFIG:
case AFLT_CMD_GETCONFIG:
case AFLT_CMD_RESTORESETTING:
case AFLT_CMD_STORESETTING:
case AFLT_CMD_INITINBUF:
case AFLT_CMD_DEINITINBUF:
case AFLT_CMD_INITOUTBUF:
case AFLT_CMD_DEINITOUTBUF:
aflt_reg->ctrl.bits.cmd = (td_u32)cmd;
break;
default:
soc_log_err("aflt CMD ERR!\n");
soc_err_print_u32(cmd);
return TD_FAILURE;
}
aflt_reg->ctrl.bits.cmd_done = 0;
ack = i_hal_aflt_ack_cmd(aflt_reg);
if (ack != AFLT_CMD_DONE) {
soc_log_err("aflt ack cmd failed");
soc_err_print_u32(aflt_id);
soc_err_print_u32(cmd);
soc_err_print_h32(ack);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_void aflt_hal_init(td_u8 *reg_base, td_bool sw_aflt)
{
aflt_io_address_map(reg_base);
g_sw_aflt_flag = sw_aflt;
}
td_void aflt_hal_deinit(td_void)
{
aflt_io_address_unmap();
}
td_s32 aflt_hal_create(td_u32 aflt_id, const aflt_create_attr *attr)
{
td_s32 ret;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (attr == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
aflt_reg->attr.bits.master_flag = (attr->master == TD_TRUE) ? 1 : 0;
aflt_reg->attr.bits.filter_id = (td_u32)attr->aflt_comp_id;
aflt_reg->auth_key[0] = attr->auth_key[0];
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_CREATE);
if (ret != TD_SUCCESS) {
soc_log_err("set alft create cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_destroy(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_DESTROY);
if (ret != TD_SUCCESS) {
soc_log_err("set alft destroy cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_start(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_START);
if (ret != TD_SUCCESS) {
soc_log_err("set alft start cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_stop(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_STOP);
if (ret != TD_SUCCESS) {
soc_log_err("set alft stop cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_set_param(td_u32 aflt_id, const aflt_param *param)
{
td_s32 ret;
u_aflt_ctrl ctrl;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (param == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
ctrl.u32 = aflt_reg->ctrl.u32;
ctrl.bits.param_index = param->param_index;
ctrl.bits.param_wordsize = param->param_struct_size;
aflt_reg->ctrl.u32 = ctrl.u32;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_SETPARAM);
if (ret != TD_SUCCESS) {
soc_log_err("set alft param cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_get_param(td_u32 aflt_id, aflt_param *param)
{
td_s32 ret;
u_aflt_ctrl ctrl;
ext_aflt_chan_reg *reg = aflt_hal_get_chan_reg(aflt_id);
if (reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (param == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
ctrl.u32 = reg->ctrl.u32;
ctrl.bits.param_index = param->param_index;
reg->ctrl.u32 = ctrl.u32;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_GETPARAM);
if (ret != TD_SUCCESS) {
soc_log_err("get alft param cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
param->param_struct_size = reg->ctrl.bits.param_wordsize;
return TD_SUCCESS;
}
td_s32 aflt_hal_set_config(td_u32 aflt_id, const aflt_config *cfg)
{
td_s32 ret;
u_aflt_ctrl ctrl;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (cfg == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
ctrl.u32 = aflt_reg->ctrl.u32;
ctrl.bits.param_index = cfg->config_index;
ctrl.bits.param_wordsize = cfg->config_struct_size;
aflt_reg->ctrl.u32 = ctrl.u32;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_SETCONFIG);
if (ret != TD_SUCCESS) {
soc_log_err("set alft config cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_get_config(td_u32 aflt_id, aflt_config *cfg)
{
td_s32 ret;
u_aflt_ctrl ctrl;
ext_aflt_chan_reg *reg = aflt_hal_get_chan_reg(aflt_id);
if (reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (cfg == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
ctrl.u32 = reg->ctrl.u32;
ctrl.bits.param_index = cfg->config_index;
reg->ctrl.u32 = ctrl.u32;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_GETCONFIG);
if (ret != TD_SUCCESS) {
soc_log_err("get alft cfg cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
cfg->config_struct_size = reg->ctrl.bits.param_wordsize;
return TD_SUCCESS;
}
td_s32 aflt_hal_restore_setting(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_RESTORESETTING);
if (ret != TD_SUCCESS) {
soc_log_err("restore alft setting cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_store_setting(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_STORESETTING);
if (ret != TD_SUCCESS) {
soc_log_err("store alft setting cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_void aflt_hal_set_msg_pool_attr(td_u32 aflt_id, hal_aflt_msgpool_attr *msg_pool_attr)
{
u_aflt_attr attr;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if ((aflt_reg == TD_NULL) || (msg_pool_attr == TD_NULL)) {
return;
}
attr.u32 = aflt_reg->attr.u32;
if (g_sw_aflt_flag == TD_TRUE) {
adsp_write_addr(msg_pool_attr->virt_addr, aflt_reg->msg_pool_addr);
} else {
adsp_write_addr(msg_pool_attr->phys_addr, aflt_reg->msg_pool_addr);
}
attr.bits.msgpool_size = msg_pool_attr->size;
aflt_reg->attr.u32 = attr.u32;
}
td_s32 aflt_hal_init_inbuf(td_u32 aflt_id, hal_aflt_inbuf_attr *in_buf_attr)
{
td_s32 ret;
u_ip_buf_size ip_buf_size;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (in_buf_attr == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
ip_buf_size.u32 = aflt_reg->ip_buf_size.u32;
if (g_sw_aflt_flag == TD_TRUE) {
adsp_write_addr(in_buf_attr->virt_addr, aflt_reg->ip_buf_addr);
} else {
adsp_write_addr(in_buf_attr->phys_addr, aflt_reg->ip_buf_addr);
}
ip_buf_size.bits.inbuff_size = in_buf_attr->size;
ip_buf_size.bits.inbuff_flag = in_buf_attr->buf_flag;
ip_buf_size.bits.inbuff_eos_flag = (in_buf_attr->eos == TD_TRUE) ? 1 : 0;
aflt_reg->ip_buf_size.u32 = ip_buf_size.u32;
aflt_reg->ip_buf_wptr = in_buf_attr->write;
aflt_reg->ip_buf_rptr = in_buf_attr->read;
aflt_reg->read_pos = in_buf_attr->stream_read_pos;
aflt_reg->ip_buf_boundary = in_buf_attr->pts_boundary;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_INITINBUF);
if (ret != TD_SUCCESS) {
soc_log_err("init alft inbuf cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_deinit_inbuf(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_DEINITINBUF);
if (ret != TD_SUCCESS) {
soc_log_err("deinit alft inbuf cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_init_outbuf(td_u32 aflt_id, hal_aflt_outbuf_attr *out_buf_attr)
{
td_s32 ret;
u_op_buf_size op_buf_size;
u_op_buf_widx op_buf_widx;
u_op_buf_ridx op_buf_ridx;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return SOC_ERR_AFLT_INVALID_PARA;
}
if (out_buf_attr == TD_NULL) {
return SOC_ERR_AFLT_NULL_PTR;
}
op_buf_size.u32 = aflt_reg->op_buf_size.u32;
if (g_sw_aflt_flag == TD_TRUE) {
adsp_write_addr(out_buf_attr->virt_addr, aflt_reg->op_buf_addr);
} else {
adsp_write_addr(out_buf_attr->phys_addr, aflt_reg->op_buf_addr);
}
op_buf_widx.u32 = aflt_reg->op_buf_widx.u32;
op_buf_ridx.u32 = aflt_reg->op_buf_ridx.u32;
op_buf_size.bits.periond_size = out_buf_attr->period_buf_size;
op_buf_size.bits.periond_num = out_buf_attr->period_number;
op_buf_widx.bits.periond_write_idx = out_buf_attr->write;
op_buf_widx.bits.periond_write_wrap = out_buf_attr->write_wrap;
op_buf_ridx.bits.periond_read_idx = out_buf_attr->read;
op_buf_ridx.bits.periond_read_wrap = out_buf_attr->read_wrap;
aflt_reg->op_buf_size.u32 = op_buf_size.u32;
aflt_reg->op_buf_widx.u32 = op_buf_widx.u32;
aflt_reg->op_buf_ridx.u32 = op_buf_ridx.u32;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_INITOUTBUF);
if (ret != TD_SUCCESS) {
soc_log_err("init alft outbuf cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_s32 aflt_hal_deinit_outbuf(td_u32 aflt_id)
{
td_s32 ret;
ret = i_hal_aflt_set_cmd(aflt_id, AFLT_CMD_DEINITOUTBUF);
if (ret != TD_SUCCESS) {
soc_log_err("deinit alft outbuf cmd failed\n");
soc_err_print_u32(aflt_id);
soc_err_print_h32(ret);
return ret;
}
return TD_SUCCESS;
}
td_void aflt_hal_get_inbuf_write_pos(td_u32 aflt_id, td_u32 *write_pos)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if ((aflt_reg == TD_NULL) || (write_pos == TD_NULL)) {
return;
}
*write_pos = aflt_reg->ip_buf_wptr;
}
td_void aflt_hal_get_inbuf_read_pos(td_u32 aflt_id, td_u32 *read_pos)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if ((aflt_reg == TD_NULL) || (read_pos == TD_NULL)) {
return;
}
*read_pos = aflt_reg->ip_buf_rptr;
}
td_void aflt_hal_get_inbuf_stream_read_pos(td_u32 aflt_id, td_u32 *stream_read_pos)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if ((aflt_reg == TD_NULL) || (stream_read_pos == TD_NULL)) {
return;
}
*stream_read_pos = aflt_reg->read_pos;
}
td_void aflt_hal_set_inbuf_write_pos(td_u32 aflt_id, td_u32 write_pos)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
aflt_reg->ip_buf_wptr = write_pos;
}
td_void aflt_hal_get_outbuf_write_idx_and_wrap(td_u32 aflt_id, td_u32 *write_idx, td_u32 *write_wrap)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
if (write_idx != TD_NULL) {
*write_idx = aflt_reg->op_buf_widx.bits.periond_write_idx;
}
if (write_wrap != TD_NULL) {
*write_wrap = aflt_reg->op_buf_widx.bits.periond_write_wrap;
}
}
td_void aflt_hal_get_outbuf_read_idx_and_wrap(td_u32 aflt_id, td_u32 *read_idx, td_u32 *read_wrap)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
if (read_idx != TD_NULL) {
*read_idx = aflt_reg->op_buf_ridx.bits.periond_read_idx;
}
if (read_wrap != TD_NULL) {
*read_wrap = aflt_reg->op_buf_ridx.bits.periond_read_wrap;
}
}
td_void aflt_hal_get_exe_frame_statistics_info(td_u32 aflt_id,
td_u32 *try_exe_cnt, td_u32 *frame_cnt, td_u32 *err_frame_cnt)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
if (try_exe_cnt != TD_NULL) {
*try_exe_cnt = aflt_reg->try_exe_cnt;
}
if (frame_cnt != TD_NULL) {
*frame_cnt = aflt_reg->status_0.bits.frame_cnt;
}
if (err_frame_cnt != TD_NULL) {
*err_frame_cnt = aflt_reg->status_0.bits.frame_err_cnt;
}
}
td_void aflt_hal_get_time_out_statistics_info(td_u32 aflt_id,
td_u32 *sche_time_out_cnt, td_u32 *exe_time_out_cnt)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
if (sche_time_out_cnt != TD_NULL) {
*sche_time_out_cnt = aflt_reg->time_out.bits.sche_timeout_cnt;
}
if (exe_time_out_cnt != TD_NULL) {
*exe_time_out_cnt = aflt_reg->time_out.bits.exe_timeout_cnt;
}
}
td_void aflt_hal_set_out_buf_rptr_and_wrap(td_u32 aflt_id, td_u32 read_idx)
{
td_u32 read_wrap;
td_u32 period_num;
u_op_buf_ridx op_buf_ridx;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
period_num = aflt_reg->op_buf_size.bits.periond_num;
op_buf_ridx.u32 = aflt_reg->op_buf_ridx.u32;
if (read_idx == period_num) {
op_buf_ridx.bits.periond_read_idx = 0;
read_wrap = op_buf_ridx.bits.periond_read_wrap;
read_wrap ^= 1; /* readidx wrap */
op_buf_ridx.bits.periond_read_wrap = read_wrap;
} else {
op_buf_ridx.bits.periond_read_idx = read_idx;
}
aflt_reg->op_buf_ridx.u32 = op_buf_ridx.u32;
}
td_void aflt_hal_set_eos_flag(td_u32 aflt_id, td_bool eos)
{
u_aflt_attr attr;
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if (aflt_reg == TD_NULL) {
return;
}
attr.u32 = aflt_reg->attr.u32;
attr.bits.eos_flag = !!eos;
attr.bits.end_of_frame = 0;
aflt_reg->attr.u32 = attr.u32;
}
td_void aflt_hal_get_end_of_frame(td_u32 aflt_id, td_bool *end_of_frame)
{
ext_aflt_chan_reg *aflt_reg = aflt_hal_get_chan_reg(aflt_id);
if ((aflt_reg == TD_NULL) || (end_of_frame == TD_NULL)) {
return;
}
*end_of_frame = !!aflt_reg->attr.bits.end_of_frame;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */