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.
258 lines
6.2 KiB
258 lines
6.2 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
|
|
* Description: adec event
|
|
* Author: audio
|
|
* Create: 2019-05-30
|
|
*/
|
|
|
|
#include "adec_event.h"
|
|
#include "soc_errno.h"
|
|
#include "mpi_memory_ext.h"
|
|
#include "mpi_adec_debug.h"
|
|
#include "adec_common.h"
|
|
#include "drv_ioctl_adec.h"
|
|
|
|
#define ADEC_EVENT_SCH_TIME_MS 10LL
|
|
#define ADEC_EVENT_FIFO_SIZE 0x1000 /* 4k */
|
|
|
|
typedef struct {
|
|
ext_adec_event_type event;
|
|
td_u8 *arg;
|
|
td_u32 arg_size;
|
|
} adec_event_prefix;
|
|
|
|
static td_void adec_event_call_back(adec_event *event, adec_event_prefix *event_prefix)
|
|
{
|
|
td_s32 ret;
|
|
|
|
td_handle user_handle;
|
|
ext_mpi_adec_event_fn fun;
|
|
|
|
adec_mutex_lock(&event->mutex);
|
|
user_handle = event->user_handle;
|
|
fun = event->fun;
|
|
adec_mutex_unlock(&event->mutex);
|
|
|
|
if (fun == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
ret = fun(user_handle,
|
|
event_prefix->event, event_prefix->arg, event_prefix->arg_size);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("report event 0x%x failed\n", event_prefix->event);
|
|
}
|
|
}
|
|
|
|
static inline td_void event_prefix_reset(adec_event_prefix *event_prefix)
|
|
{
|
|
event_prefix->event = EXT_ADEC_EVENT_TYPE_MAX;
|
|
event_prefix->arg = TD_NULL;
|
|
event_prefix->arg_size = 0;
|
|
}
|
|
|
|
static td_void adec_event_process(adec_event *event, td_u8 *arg)
|
|
{
|
|
td_u32 len;
|
|
kfifo *fifo = &event->event_fifo.fifo;
|
|
adec_event_prefix event_prefix;
|
|
|
|
while (event->alive == TD_TRUE) {
|
|
event_prefix_reset(&event_prefix);
|
|
len = kfifo_peek(fifo, &event_prefix, sizeof(adec_event_prefix));
|
|
if (len != sizeof(adec_event_prefix)) {
|
|
break;
|
|
}
|
|
|
|
if (kfifo_used(fifo) < sizeof(adec_event_prefix) + event_prefix.arg_size) {
|
|
break;
|
|
}
|
|
|
|
kfifo_poke(fifo, sizeof(adec_event_prefix));
|
|
|
|
if (event_prefix.arg_size > 0) {
|
|
event_prefix.arg = arg;
|
|
len = kfifo_out(fifo, arg, event_prefix.arg_size);
|
|
if (len != event_prefix.arg_size) {
|
|
soc_log_err("call kfifo_out failed!\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
adec_event_call_back(event, &event_prefix);
|
|
}
|
|
}
|
|
|
|
static td_void *adec_event_thread(td_void *arg)
|
|
{
|
|
td_u8 *buf = TD_NULL;
|
|
adec_event *event = (adec_event *)arg;
|
|
|
|
if (event == TD_NULL) {
|
|
return TD_NULL;
|
|
}
|
|
|
|
buf = (td_u8 *)malloc(ADEC_EVENT_FIFO_SIZE);
|
|
if (buf == TD_NULL) {
|
|
soc_log_err("call malloc( failed!\n");
|
|
return TD_NULL;
|
|
}
|
|
|
|
while (event->alive == TD_TRUE) {
|
|
adec_event_process(event, buf);
|
|
adec_sleep(ADEC_EVENT_SCH_TIME_MS);
|
|
}
|
|
|
|
free(buf);
|
|
return TD_NULL;
|
|
}
|
|
|
|
static td_void adec_event_fifo_deinit(adec_event_fifo *event_fifo)
|
|
{
|
|
if (event_fifo->buffer == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
free(event_fifo->buffer);
|
|
event_fifo->buffer = TD_NULL;
|
|
}
|
|
|
|
static td_s32 adec_event_fifo_init(adec_event_fifo *event_fifo)
|
|
{
|
|
td_s32 ret;
|
|
|
|
event_fifo->buffer = (td_u8 *)malloc(ADEC_EVENT_FIFO_SIZE);
|
|
if (event_fifo->buffer == TD_NULL) {
|
|
soc_log_err("call malloc( failed!\n");
|
|
return SOC_ERR_ADEC_ALLOC_MEM_FAILED;
|
|
}
|
|
|
|
event_fifo->write = 0;
|
|
event_fifo->read = 0;
|
|
|
|
ret = kfifo_init(
|
|
&event_fifo->fifo,
|
|
&event_fifo->write,
|
|
&event_fifo->read,
|
|
event_fifo->buffer,
|
|
ADEC_EVENT_FIFO_SIZE);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_log_err("call kfifo_init failed!\n");
|
|
adec_event_fifo_deinit(event_fifo);
|
|
return ret;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 adec_event_init(adec_event *event)
|
|
{
|
|
td_s32 ret;
|
|
|
|
check_adec_null_ptr(event);
|
|
|
|
ret = adec_event_fifo_init(&event->event_fifo);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(adec_event_fifo_init, ret);
|
|
return ret;
|
|
}
|
|
|
|
adec_mutex_init(&event->mutex);
|
|
|
|
event->alive = TD_TRUE;
|
|
ret = pthread_create(&event->thread, TD_NULL,
|
|
adec_event_thread, event);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(pthread_create, ret);
|
|
goto out;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
|
|
out:
|
|
adec_mutex_deinit(&event->mutex);
|
|
adec_event_fifo_deinit(&event->event_fifo);
|
|
return ret;
|
|
}
|
|
|
|
td_s32 adec_event_deinit(adec_event *event)
|
|
{
|
|
td_s32 ret;
|
|
|
|
check_adec_null_ptr(event);
|
|
|
|
event->alive = TD_FALSE;
|
|
ret = pthread_join(event->thread, TD_NULL);
|
|
if (ret != TD_SUCCESS) {
|
|
soc_err_print_call_fun_err(pthread_join, ret);
|
|
return ret;
|
|
}
|
|
|
|
adec_mutex_deinit(&event->mutex);
|
|
adec_event_fifo_deinit(&event->event_fifo);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 adec_event_register_call_back(adec_event *event, td_handle user_handle, ext_mpi_adec_event_fn fun)
|
|
{
|
|
check_adec_null_ptr(event);
|
|
|
|
if (event->alive == TD_FALSE) {
|
|
soc_log_err("event->mutex is not init!\n");
|
|
return SOC_ERR_ADEC_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
adec_mutex_lock(&event->mutex);
|
|
event->user_handle = user_handle;
|
|
event->fun = fun;
|
|
adec_mutex_unlock(&event->mutex);
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_void adec_event_report(adec_event *event, ext_adec_event_type event_type, td_u8 *param, td_u32 param_size)
|
|
{
|
|
td_u32 len;
|
|
kfifo *fifo = TD_NULL;
|
|
td_bool set_event_prefix_done = TD_FALSE;
|
|
td_u32 size = param_size;
|
|
adec_event_prefix event_prefix = {
|
|
.event = event_type,
|
|
.arg = TD_NULL,
|
|
.arg_size = 0,
|
|
};
|
|
|
|
if (event == TD_NULL) {
|
|
return;
|
|
}
|
|
|
|
fifo = &event->event_fifo.fifo;
|
|
|
|
if (param == TD_NULL) {
|
|
size = 0;
|
|
}
|
|
event_prefix.arg = param; /* kfifo is not written immediately, stack variables cannot be used as param */
|
|
event_prefix.arg_size = size;
|
|
while (event->alive == TD_TRUE) {
|
|
if (set_event_prefix_done == TD_FALSE) {
|
|
len = kfifo_in(fifo, &event_prefix, sizeof(adec_event_prefix));
|
|
if (len != sizeof(adec_event_prefix)) {
|
|
adec_sleep(ADEC_EVENT_SCH_TIME_MS);
|
|
continue;
|
|
}
|
|
set_event_prefix_done = TD_TRUE;
|
|
}
|
|
|
|
if (event_prefix.arg_size == 0) {
|
|
break;
|
|
}
|
|
len = kfifo_in(fifo, event_prefix.arg, event_prefix.arg_size);
|
|
if (len == event_prefix.arg_size) {
|
|
break;
|
|
}
|
|
|
|
adec_sleep(ADEC_EVENT_SCH_TIME_MS);
|
|
}
|
|
}
|