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.

735 lines
21 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
* Description: drv aenc
* Author: audio
* Create: 2019-05-30
*/
#include "drv_aenc_debug.h"
#include "osal_ext.h"
#include "drv_base_ext.h"
#include "drv_dev_ext.h"
#include "drv_ioctl_aenc.h"
#include "drv_adsp_ext.h"
#include "drv_aenc_ext.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define AENC_NAME "SOC_AENC"
#define AENC_PROC_NAME_LENGTH 16
#define AENC_PERCENTAGE 100
#define AENC_PROC_LINE_LENGTH 46
typedef struct {
td_u32 id;
aenc_proc_item *proc_addr;
ext_audio_buffer proc_buf;
struct osal_list_head list;
} aenc_instance;
static OSAL_LIST_HEAD(g_aenc_list);
static osal_semaphore g_aenc_mutex = {TD_NULL};
static td_void aenc_unreg_proc(const aenc_instance *aenc);
static td_void aenc_reg_proc(const aenc_instance *aenc);
static aenc_instance *aenc_find_by_id(td_u32 id)
{
aenc_instance *aenc = TD_NULL;
osal_list_for_each_entry(aenc, &g_aenc_list, list) {
if (aenc->id == id) {
return aenc;
}
}
return TD_NULL;
}
static inline td_u32 aenc_find_free_id(td_void)
{
td_u32 id;
for (id = 0; id < AENC_INSTANCE_MAXNUM; id++) {
if (aenc_find_by_id(id) == TD_NULL) {
return id;
}
}
return AENC_INSTANCE_MAXNUM;
}
static td_void aenc_destroy_instance(aenc_instance *aenc)
{
osal_list_del(&aenc->list);
osal_kfree(aenc);
}
static aenc_instance *aenc_create_instance(td_void)
{
td_u32 id;
td_s32 ret;
aenc_instance *aenc = TD_NULL;
id = aenc_find_free_id();
if (id >= AENC_INSTANCE_MAXNUM) {
soc_log_err("aenc_find_free_id failed\n");
return TD_NULL;
}
aenc = (aenc_instance *)osal_kmalloc(sizeof(*aenc), OSAL_GFP_KERNEL);
if (aenc == TD_NULL) {
soc_log_err("osal_kmalloc aenc_instance failed\n");
return TD_NULL;
}
ret = memset_s(aenc, sizeof(*aenc), 0, sizeof(*aenc));
if (ret != EOK) {
soc_log_err("call memset_s failed(0x%x)\n", ret);
osal_kfree(aenc);
return TD_NULL;
}
aenc->id = id;
osal_list_add(&aenc->list, &g_aenc_list);
return aenc;
}
static adsp_export_func *aenc_get_audio_mem_func(td_void)
{
td_s32 ret;
adsp_export_func *mem_func = TD_NULL;
ret = osal_exportfunc_get(SOC_ID_ADSP, (td_void **)&mem_func);
if (ret != TD_SUCCESS) {
soc_log_fatal("get audio mem function failed(0x%x)\n", ret);
return TD_NULL;
}
if ((mem_func == TD_NULL) ||
(mem_func->smmu_alloc == TD_NULL) ||
(mem_func->smmu_release == TD_NULL)) {
soc_log_fatal("audio mem function is invalid\n");
return TD_NULL;
}
return mem_func;
}
static td_void aenc_free_proc_buf(ext_audio_buffer *buf)
{
td_s32 ret;
adsp_export_func *mem_func = aenc_get_audio_mem_func();
if (mem_func == TD_NULL) {
return;
}
if (buf->fd >= 0) {
ret = osal_mem_close_fd(buf->fd);
if (ret != 0) {
soc_warn_print_s32(buf->fd);
soc_warn_print_call_fun_err(osal_mem_close_fd, ret);
}
buf->fd = -1;
}
if (buf->virt_addr != TD_NULL) {
mem_func->smmu_release(buf);
buf->virt_addr = TD_NULL;
}
}
static td_s32 aenc_alloc_proc_buf(td_char *name, td_u32 name_len, ext_audio_buffer *buf)
{
td_s32 ret;
adsp_export_func *mem_func = aenc_get_audio_mem_func();
if (mem_func == TD_NULL) {
return SOC_ERR_AENC_NULL_PTR;
}
TD_UNUSED(name_len);
ret = mem_func->smmu_alloc(name, sizeof(aenc_proc_item), TD_FALSE, buf);
if (ret != TD_SUCCESS) {
soc_log_err("call smmu_alloc failed(0x%x)\n", ret);
return ret;
}
if (buf->dma_buf == TD_NULL) {
goto out;
}
buf->fd = osal_mem_create_fd(buf->dma_buf, OSAL_O_CLOEXEC);
if (buf->fd < 0) {
soc_log_err("call osal_mem_create_fd failed\n");
goto out;
}
return TD_SUCCESS;
out:
mem_func->smmu_release(buf);
return SOC_ERR_AENC_NULL_PTR;
}
static td_s32 aenc_proc_buf_init(aenc_instance *aenc)
{
td_s32 ret;
td_char name[AENC_PROC_NAME_LENGTH];
ret = snprintf_s(name, sizeof(name), sizeof(name) - 1, "aenc_proc%02d", aenc->id);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return ret;
}
aenc->proc_addr = TD_NULL;
ret = aenc_alloc_proc_buf(name, sizeof(name), &aenc->proc_buf);
if (ret != TD_SUCCESS) {
soc_err_print_call_fun_err(aenc_alloc_proc_buf, ret);
return ret;
}
if (aenc->proc_buf.virt_addr == TD_NULL) {
aenc_free_proc_buf(&aenc->proc_buf);
return SOC_ERR_AENC_NULL_PTR;
}
ret = memset_s(aenc->proc_buf.virt_addr, sizeof(aenc_proc_item),
0, sizeof(aenc_proc_item));
if (ret != EOK) {
soc_err_print_call_fun_err(memset_s, ret);
aenc_free_proc_buf(&aenc->proc_buf);
return ret;
}
aenc->proc_addr = (aenc_proc_item *)aenc->proc_buf.virt_addr;
aenc->proc_addr->pcm_ctrl_state = AENC_CMD_CTRL_STOP;
aenc->proc_addr->es_ctrl_state = AENC_CMD_CTRL_STOP;
return TD_SUCCESS;
}
static td_void aenc_proc_buf_deinit(aenc_instance *aenc)
{
if (aenc->proc_addr == TD_NULL) {
return;
}
aenc_free_proc_buf(&aenc->proc_buf);
aenc->proc_addr = TD_NULL;
}
static td_s32 aenc_ioctl_proc_init(td_void *private_data, td_void *arg)
{
td_s32 ret;
aenc_instance *aenc = TD_NULL;
aenc_proc_param* proc_param = (aenc_proc_param *)arg;
if ((private_data == TD_NULL) || (arg == TD_NULL)) {
return SOC_ERR_AENC_NULL_PTR;
}
aenc = aenc_create_instance();
if (aenc == TD_NULL) {
soc_log_err("call aenc_create_instance failed\n");
return TD_FAILURE;
}
ret = aenc_proc_buf_init(aenc);
if (ret != TD_SUCCESS) {
soc_log_err("call aenc_proc_buf_init failed(0x%x)\n", ret);
aenc_destroy_instance(aenc);
return ret;
}
aenc_reg_proc(aenc);
*((aenc_instance **)private_data) = aenc;
proc_param->id = aenc->id;
proc_param->map_fd = aenc->proc_buf.fd;
proc_param->proc_phys_addr = aenc->proc_buf.phys_addr;
return TD_SUCCESS;
}
static td_s32 aenc_ioctl_proc_deinit(td_void *private_data)
{
aenc_instance *aenc = TD_NULL;
if (private_data == TD_NULL) {
return SOC_ERR_AENC_NULL_PTR;
}
aenc = *((aenc_instance **)private_data);
if (aenc == TD_NULL) {
return TD_SUCCESS;
}
aenc_unreg_proc(aenc);
aenc_proc_buf_deinit(aenc);
aenc_destroy_instance(aenc);
*((aenc_instance **)private_data) = TD_NULL;
return TD_SUCCESS;
}
static td_s32 aenc_drv_open(td_void *private_data)
{
if (private_data == TD_NULL) {
return SOC_ERR_AENC_NULL_PTR;
}
*((aenc_instance **)private_data) = TD_NULL;
return TD_SUCCESS;
}
static td_s32 aenc_drv_release(td_void *private_data)
{
td_s32 ret;
ret = osal_sem_down_interruptible(&g_aenc_mutex);
if (ret != TD_SUCCESS) {
soc_log_err("lock g_aenc_mutex failed\n");
return ret;
}
ret = aenc_ioctl_proc_deinit(private_data);
if (ret != TD_SUCCESS) {
soc_log_err("aenc_ioctl_proc_deinit failed!\n");
}
osal_sem_up(&g_aenc_mutex);
return ret;
}
static td_s32 aenc_process_cmd(td_void *private_data, td_u32 cmd, td_void *arg)
{
td_s32 ret;
switch (cmd) {
case DRV_AENC_PROC_INIT: {
ret = aenc_ioctl_proc_init(private_data, arg);
if (ret != TD_SUCCESS) {
soc_log_err("aenc_ioctl_proc_init failed(0x%x)\n", ret);
}
break;
}
case DRV_AENC_PROC_EXIT: {
ret = aenc_ioctl_proc_deinit(private_data);
if (ret != TD_SUCCESS) {
soc_log_err("aenc_ioctl_proc_deinit failed(0x%x)\n", ret);
}
break;
}
default: {
ret = SOC_ERR_AENC_INVALID_PARA;
soc_log_err("invalid cmd!\n");
break;
}
}
return ret;
}
static td_s32 aenc_drv_ioctl(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret;
ret = osal_sem_down_interruptible(&g_aenc_mutex);
if (ret != TD_SUCCESS) {
soc_log_err("lock g_aenc_mutex failed(0x%x)\n", ret);
return ret;
}
ret = aenc_process_cmd(private_data, cmd, arg);
osal_sem_up(&g_aenc_mutex);
return ret;
}
static const td_char *aenc_proc_get_attach_source_name(aenc_source_type type)
{
const td_char *name[] = {
"ai",
"cast",
"vir_track",
};
if ((type >= 0) && (type < ARRAY_SIZE(name))) {
return name[type];
}
return "none";
}
static td_void aenc_read_proc_encoder_info(td_void *file, const aenc_proc_item *aenc_proc)
{
td_s32 ret;
const td_char *attach_name = aenc_proc_get_attach_source_name(aenc_proc->attach.type);
td_char tmp[AENC_PROC_LINE_LENGTH];
osal_seq_printf(file, "%-33s:%-11s|\n",
"status", (aenc_proc->aenc_work_enable == TD_TRUE) ? "start" : "stop");
osal_seq_printf(file, "%-33s:0x%-9x|\n", "codec_id", aenc_proc->codec_id);
osal_seq_printf(file, "%-33s:%-11s|\n", "description", aenc_proc->codec_type);
osal_seq_printf(file, "%-33s:%-11d|\n", "sample_rate", aenc_proc->sample_rate);
osal_seq_printf(file, "%-33s:%-11d|\n", "channels", aenc_proc->channels);
osal_seq_printf(file, "%-33s:%-11d|\n", "bit_width", aenc_proc->bit_width);
if (aenc_proc->attach.type == ANEC_SOURCE_MAX) {
osal_seq_printf(file, "%-33s:%-11s|\n", "attach_source", attach_name);
} else {
ret = snprintf_s(tmp, AENC_PROC_LINE_LENGTH,
AENC_PROC_LINE_LENGTH - 1, "%s%02d", attach_name, (aenc_proc->attach.src & 0xff));
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
osal_seq_printf(file, "%-33s:%-11s|\n", "attach_source", tmp);
}
osal_seq_printf(file, "%-33s:%-11d|\n", "try_encode_times", aenc_proc->dbg_try_encode_count);
osal_seq_printf(file, "%-33s:%-11d|\n", "encode_frame_num_total_cnt", aenc_proc->enc_frame);
osal_seq_printf(file, "%-33s:%-11d|\n", "encode_frame_num_error_cnt", aenc_proc->err_frame);
}
static td_void aenc_read_proc_input_buf(td_void *file, const aenc_proc_item *aenc_proc)
{
td_s32 ret;
td_u64 data_size = 0;
td_u64 buf_percent = 0;
td_char tmp[AENC_PROC_LINE_LENGTH];
if (aenc_proc->in_buf_size != 0) {
if (aenc_proc->in_buf_write >= aenc_proc->in_buf_read) {
data_size = aenc_proc->in_buf_write - aenc_proc->in_buf_read;
} else {
data_size = aenc_proc->in_buf_size + aenc_proc->in_buf_write - aenc_proc->in_buf_read;
}
buf_percent = data_size * AENC_PERCENTAGE / aenc_proc->in_buf_size;
}
osal_seq_printf(file, "%-33s:%-11d|\n", "frame_buf_total_bytes", aenc_proc->in_buf_size);
osal_seq_printf(file, "%-33s:%-11llu|\n", "frame_buf_use_bytes", data_size);
ret = snprintf_s(tmp, AENC_PROC_LINE_LENGTH, AENC_PROC_LINE_LENGTH - 1, "%llu%%", buf_percent);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
osal_seq_printf(file, "%-33s:%-11s|\n", "frame_buf_total_percent", tmp);
}
static td_void aenc_read_proc_output_buf(td_void *file, const aenc_proc_item *aenc_proc)
{
td_s32 ret;
td_u32 frame_percent = 0;
td_u32 frame_num = 0;
td_char tmp[AENC_PROC_LINE_LENGTH];
if (aenc_proc->out_frame_num) {
if (aenc_proc->out_frame_w_idx >= aenc_proc->out_frame_r_idx) {
frame_num = aenc_proc->out_frame_w_idx - aenc_proc->out_frame_r_idx;
} else {
frame_num = aenc_proc->out_frame_num - aenc_proc->out_frame_r_idx + aenc_proc->out_frame_w_idx;
}
frame_percent = frame_num * AENC_PERCENTAGE / aenc_proc->out_frame_num;
}
osal_seq_printf(file, "%-33s:%-11d|\n", "stream_buf_total_num", aenc_proc->out_frame_num);
osal_seq_printf(file, "%-33s:%-11d|\n", "stream_buf_use_num", frame_num);
ret = snprintf_s(tmp, AENC_PROC_LINE_LENGTH, AENC_PROC_LINE_LENGTH - 1, "%llu%%", frame_percent);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
osal_seq_printf(file, "%-33s:%-11s|\n", "stream_buf_percent", tmp);
}
static td_void aenc_read_proc_dbg_count(td_void *file, const aenc_proc_item *aenc_proc)
{
osal_seq_printf(file, "%-33s:%-11d|\n", "send_frame_try_cnt", aenc_proc->dbg_send_buf_count_try);
osal_seq_printf(file, "%-33s:%-11d|\n", "send_frame_ok_cnt", aenc_proc->dbg_send_buf_count);
osal_seq_printf(file, "%-33s:%-11d|\n", "receive_stream_try_cnt", aenc_proc->dbg_receive_stream_count_try);
osal_seq_printf(file, "%-33s:%-11d|\n", "receive_stream_ok_cnt", aenc_proc->dbg_receive_stream_count);
osal_seq_printf(file, "%-33s:%-11d|\n", "release_stream_try_cnt", aenc_proc->dbg_release_stream_count_try);
osal_seq_printf(file, "%-33s:%-11d|\n", "release_stream_ok_cnt", aenc_proc->dbg_release_stream_count);
}
static td_s32 aenc_read_proc(td_void *file, td_void *private)
{
aenc_instance *aenc = (aenc_instance *)private;
if (aenc == TD_NULL) {
return SOC_ERR_ADEC_NULL_PTR;
}
if (aenc->proc_addr == TD_NULL) {
osal_seq_printf(file, "aenc[%02d] proc not init\n", aenc->id);
return TD_SUCCESS;
}
osal_seq_printf(file, "[aenc]%s\n", VERSION_STRING);
osal_seq_printf(file, "-----------------aenc%02d state-----------------\n", aenc->id);
aenc_read_proc_encoder_info(file, aenc->proc_addr);
aenc_read_proc_input_buf(file, aenc->proc_addr);
aenc_read_proc_output_buf(file, aenc->proc_addr);
aenc_read_proc_dbg_count(file, aenc->proc_addr);
osal_seq_printf(file, "==============================================\n");
return TD_SUCCESS;
}
static td_s32 aenc_proc_how_help(td_u32 argc, td_char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private)
{
aenc_instance *aenc = (aenc_instance *)private;
if (aenc == TD_NULL) {
return SOC_ERR_ADEC_NULL_PTR;
}
osal_proc_echo("=======================================aenc=======================================\n");
osal_proc_echo("%-82s\n", "echo command para path explanation ");
osal_proc_echo("%-82s\n", "echo save_pcm start > /proc/msp/aenc00 start save pcm data before audio encode");
osal_proc_echo("%-82s\n", "echo save_pcm stop > /proc/msp/aenc00 stop save pcm data before audio encode");
osal_proc_echo("%-82s\n", "echo save_es start > /proc/msp/aenc00 start save es data after audio encode");
osal_proc_echo("%-82s\n", "echo save_es stop > /proc/msp/aenc00 stop save es data after audio encode");
osal_proc_echo("==================================================================================\n");
return TD_SUCCESS;
}
static td_s32 aenc_write_proc_save_es(td_u32 argc, td_char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
td_s32 ret;
aenc_proc_item *aenc_proc = TD_NULL;
aenc_instance *aenc = (aenc_instance *)private;
if ((aenc == TD_NULL) || (aenc->proc_addr == TD_NULL)) {
soc_log_err("AENC PROC not init\n");
return SOC_ERR_AENC_NULL_PTR;
}
aenc_proc = aenc->proc_addr;
if (osal_strncmp("save_es", argv[0], strlen(argv[0])) != 0) {
return SOC_ERR_AENC_INVALID_PARA;
}
if (osal_strncmp("start", argv[1], strlen(argv[1])) == 0) {
ret = snprintf_s(aenc_proc->file_path, sizeof(aenc_proc->file_path),
sizeof(aenc_proc->file_path) - 1, "/mnt/aenc%02d.es", aenc->id);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return ret;
}
if (aenc_proc->es_ctrl_state != AENC_CMD_CTRL_START) {
aenc_proc->save_es_cnt++;
aenc_proc->es_ctrl_state = AENC_CMD_CTRL_START;
osal_printk("started saving aenc es data to %s\n", aenc_proc->file_path);
} else {
osal_printk("started saving aenc es data already.\n");
}
return TD_SUCCESS;
}
if (osal_strncmp("stop", argv[1], strlen(argv[1])) == 0) {
osal_printk("finished saving aenc es data.\n");
aenc_proc->es_ctrl_state = AENC_CMD_CTRL_STOP;
return TD_SUCCESS;
}
return SOC_ERR_AENC_INVALID_PARA;
}
static td_s32 aenc_write_proc_save_pcm(td_u32 argc,
td_char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private)
{
td_s32 ret;
aenc_proc_item *aenc_proc = TD_NULL;
aenc_instance *aenc = (aenc_instance *)private;
if ((aenc == TD_NULL) || (aenc->proc_addr == TD_NULL)) {
soc_log_err("aenc proc not init\n");
return SOC_ERR_AENC_NULL_PTR;
}
aenc_proc = aenc->proc_addr;
if (osal_strncmp("save_pcm", argv[0], strlen(argv[0])) != 0) {
return SOC_ERR_ADEC_INVALID_PARA;
}
if (osal_strncmp("start", argv[1], strlen(argv[1])) == 0) {
ret = snprintf_s(aenc_proc->file_path, sizeof(aenc_proc->file_path),
sizeof(aenc_proc->file_path) - 1, "/mnt/aenc%02d.pcm", aenc->id);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return ret;
}
if (aenc_proc->pcm_ctrl_state != AENC_CMD_CTRL_START) {
aenc_proc->save_pcm_cnt++;
aenc_proc->pcm_ctrl_state = AENC_CMD_CTRL_START;
osal_printk("started saving aenc pcm data to %s\n", aenc_proc->file_path);
} else {
osal_printk("started saving aenc pcm data already.\n");
}
return TD_SUCCESS;
}
if (osal_strncmp("stop", argv[1], strlen(argv[1])) == 0) {
osal_printk("finished saving aenc pcm data.\n");
aenc_proc->pcm_ctrl_state = AENC_CMD_CTRL_STOP;
return TD_SUCCESS;
}
return SOC_ERR_AENC_INVALID_PARA;
}
static osal_proc_cmd g_aenc_proc_cmd[] = {
{ "save_es", aenc_write_proc_save_es },
{ "save_pcm", aenc_write_proc_save_pcm },
{ "help", aenc_proc_how_help },
};
static td_void aenc_unreg_proc(const aenc_instance *aenc)
{
td_s32 ret;
td_char buf[AENC_PROC_NAME_LENGTH];
ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "aenc%02d", aenc->id);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
osal_proc_remove(buf, strlen(buf));
}
static td_void aenc_reg_proc(const aenc_instance *aenc)
{
td_s32 ret;
td_char buf[AENC_PROC_NAME_LENGTH];
osal_proc_entry *item = TD_NULL;
/* create proc */
ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "aenc%02d", aenc->id);
if (ret < 0) {
soc_err_print_call_fun_err(snprintf_s, ret);
return;
}
item = osal_proc_add(buf, strlen(buf));
if (item == TD_NULL) {
soc_log_fatal("create aenc proc entry fail!\n");
return;
}
/* set functions */
item->read = aenc_read_proc;
item->cmd_list = g_aenc_proc_cmd;
item->cmd_cnt = sizeof(g_aenc_proc_cmd) / sizeof(g_aenc_proc_cmd[0]);
item->private = (td_void *)aenc;
soc_log_info("create aenc proc entry OK!\n");
}
static osal_ioctl_cmd g_aenc_cmd_list[] = {
{ DRV_AENC_PROC_INIT, aenc_drv_ioctl },
{ DRV_AENC_PROC_EXIT, aenc_drv_ioctl },
};
static osal_fileops g_aenc_fops = {
.open = aenc_drv_open,
.write = TD_NULL,
.llseek = TD_NULL,
.release = aenc_drv_release,
.poll = TD_NULL,
.mmap = TD_NULL,
.cmd_list = g_aenc_cmd_list,
.cmd_cnt = sizeof(g_aenc_cmd_list) / sizeof(g_aenc_cmd_list[0]),
};
static osal_dev g_aenc_dev = {
.name = SOC_DEV_AENC_NAME,
.minor = SOC_DEV_AENC_MINOR,
.fops = &g_aenc_fops,
.pmops = TD_NULL,
.dev = TD_NULL,
};
td_s32 aenc_drv_mod_init(td_void)
{
td_s32 ret;
ret = osal_sem_init(&g_aenc_mutex, 1);
if (ret != TD_SUCCESS) {
soc_log_err("call osal_sem_init failed\n");
return ret;
}
ret = osal_exportfunc_register(SOC_ID_AENC, AENC_NAME, TD_NULL);
if (ret != TD_SUCCESS) {
soc_log_err("call osal_exportfunc_register failed(0x%x)\n", ret);
goto out0;
}
ret = osal_dev_register(&g_aenc_dev);
if (ret != TD_SUCCESS) {
soc_log_err("call osal_dev_register failed(0x%x)\n", ret);
goto out1;
}
#ifdef MODULE
soc_print("Load soc_aenc.ko success. \t(%s)\n", VERSION_STRING);
#endif
return TD_SUCCESS;
out1:
osal_exportfunc_unregister(SOC_ID_AENC);
out0:
osal_sem_destroy(&g_aenc_mutex);
return ret;
}
td_void aenc_drv_mod_exit(td_void)
{
osal_dev_unregister(&g_aenc_dev);
osal_exportfunc_unregister(SOC_ID_AENC);
osal_sem_destroy(&g_aenc_mutex);
}
#ifdef MODULE
module_init(aenc_drv_mod_init);
module_exit(aenc_drv_mod_exit);
#else
#ifndef CONFIG_SOCT_RECOVERY_SUPPORT
#ifdef CONFIG_SOCT_AENC_SUPPORT
soc_initcall(aenc_drv_mod_init);
#endif
#endif
#endif
MODULE_AUTHOR("HUANGLONG");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AENC DRIVER");
#ifdef __cplusplus
}
#endif /* __cplusplus */