decoder: optimize code and sync from iptv

PD#170744: decoder:
1. fix mh264 mosaic when play mjpeg at sametime in frame mode;
2. sync the mjpeg multi play code;
3. add the mpeg2&mpeg4 multi play code;
4. force exit when load ucode fail;
5. set time out for vdec_disconnet wait_for_completion;
6. reset core when active vdec to disconnect list and before run;
7. fix some coverity error;
8. remove ucode load when mmu enable in vmh264 init.

Change-Id: Ic8f296526ddac5b3904a323ce2850b1d9178a284
Signed-off-by: shihong.zheng <shihong.zheng@amlogic.com>
This commit is contained in:
shihong.zheng
2018-08-27 15:14:58 +08:00
committed by Dongjin Kim
parent 48ee09ae0d
commit 1a63229ef3
13 changed files with 3189 additions and 320 deletions

View File

@@ -5,6 +5,7 @@ KERNEL_ARCH := arm64
endif
CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \
CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI=m \
CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \
CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \
CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \

View File

@@ -5411,6 +5411,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
amhevc_disable();
avs2_print(dec, 0,
"%s: Error amvdec_loadmc fail\n", __func__);
dec->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&dec->work);
return;
} else
vdec->mc_loaded = 1;

View File

@@ -770,8 +770,10 @@ struct vdec_h264_hw_s {
struct mh264_ud_record_wait_node_t free_nodes[MAX_FREE_USERDATA_NODES];
int wait_for_udr_send;
#endif
u32 no_mem_count;
bool is_used_v4l;
void *v4l2_ctx;
wait_queue_head_t wait_q;
};
static u32 again_threshold = 0x40;
@@ -1514,6 +1516,9 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
PAGE_ALIGN(buf_size), DRIVER_NAME,
&hw->buffer_spec[i].cma_alloc_addr) < 0) {
hw->buffer_spec[i].cma_alloc_addr = 0;
if (hw->no_mem_count++ > 3) {
hw->stat |= DECODER_FATAL_ERROR_NO_MEM;
}
dpb_print(DECODE_ID(hw), 0,
"%s, fail to alloc buf for bufspec%d, try later\n",
__func__, i
@@ -4084,6 +4089,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
if (dec_dpb_status == H264_CONFIG_REQUEST) {
WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE);
reset_process_time(hw);
hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
hw->dec_result = DEC_RESULT_CONFIG_PARAM;
vdec_schedule_work(&hw->work);
} else if (dec_dpb_status == H264_SLICE_HEAD_DONE) {
@@ -4663,6 +4669,7 @@ send_again:
"%s H264_DATA_REQUEST (%d)\n",
__func__, hw->get_data_count);
hw->dec_result = DEC_RESULT_GET_DATA;
hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
hw->get_data_start_time = jiffies;
hw->get_data_count++;
if (hw->get_data_count >= frame_max_data_packet)
@@ -5279,6 +5286,7 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw)
hw->reg_rv_ai_mb_count = 0;
hw->vld_dec_control = 0;
hw->decode_timeout_count = 0;
hw->no_mem_count = 0;
hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio;
/* vh264_ratio = 0x100; */
@@ -5345,12 +5353,14 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw)
hw->vh264_stream_switching_state = SWITCHING_STATE_OFF;
hw->hevc_cur_buf_idx = 0xffff;
init_waitqueue_head(&hw->wait_q);
return;
}
static s32 vh264_init(struct vdec_h264_hw_s *hw)
{
int ret = 0, size = -1;
int size = -1;
int fw_size = 0x1000 * 16;
int fw_mmu_size = 0x1000 * 16;
struct firmware_s *fw = NULL, *fw_mmu = NULL;
@@ -5471,28 +5481,6 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
/*slice*/
memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000,
fw->data + 0x5000, 0x1000);
if (hw->mmu_enable)
ret = amhevc_loadmc_ex(VFORMAT_HEVC,
NULL, fw_mmu->data);
if (ret < 0) {
amvdec_disable();
if (hw->mmu_enable)
amhevc_disable();
if (hw->mc_cpu_addr) {
dma_free_coherent(amports_get_dma_device(),
MC_TOTAL_SIZE, hw->mc_cpu_addr,
hw->mc_dma_handle);
hw->mc_cpu_addr = NULL;
}
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"MH264: the %s fw loading failed, err: %x\n",
tee_enabled() ? "TEE" : "local", ret);
return -EBUSY;
}
}
#if 1 /* #ifdef BUFFER_MGR_IN_C */
@@ -6541,7 +6529,7 @@ result_done:
/* mark itself has all HW resource released and input released */
vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
wake_up_interruptible(&hw->wait_q);
if (hw->vdec_cb)
hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
}
@@ -6575,6 +6563,9 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (hw->eos)
return 0;
if (hw->stat & DECODER_FATAL_ERROR_NO_MEM)
return 0;
if (disp_vframe_valve_level &&
kfifo_len(&hw->display_q) >=
disp_vframe_valve_level) {
@@ -6628,6 +6619,7 @@ static void run(struct vdec_s *vdec, unsigned long mask,
int size, ret = -1;
run_count[DECODE_ID(hw)]++;
vdec_reset_core(vdec);
if (hw->mmu_enable)
hevc_reset_core(vdec);
hw->vdec_cb_arg = arg;
@@ -6743,6 +6735,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"MH264 the %s fw loading failed, err: %x\n",
tee_enabled() ? "TEE" : "local", ret);
hw->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hw->work);
return;
}
@@ -6756,6 +6750,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"MH264_MMU the %s fw loading failed, err: %x\n",
tee_enabled() ? "TEE" : "local", ret);
hw->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hw->work);
return;
}
}
@@ -7254,6 +7250,17 @@ static int ammvdec_h264_remove(struct platform_device *pdev)
(struct vdec_h264_hw_s *)
(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
int i;
struct vdec_s *vdec = hw_to_vdec(hw);
if (vdec->next_status == VDEC_STATUS_DISCONNECTED
&& (vdec->status == VDEC_STATUS_ACTIVE)) {
pr_info("%s force exit %d\n", __func__, __LINE__);
hw->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hw->work);
wait_event_interruptible_timeout(hw->wait_q,
(vdec->status == VDEC_STATUS_CONNECTED),
msecs_to_jiffies(50)); /* wait for work done */
}
for (i = 0; i < BUFSPEC_POOL_SIZE; i++)
release_aux_data(hw, i);

View File

@@ -10009,6 +10009,8 @@ static void run(struct vdec_s *vdec, unsigned long mask,
amhevc_disable();
hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n",
tee_enabled() ? "TEE" : "local", loadr);
hevc->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hevc->work);
return;
}
@@ -10142,7 +10144,6 @@ static int amvdec_h265_probe(struct platform_device *pdev)
work_buf_size, DRIVER_NAME, &hevc->buf_start);
if (ret < 0) {
uninit_mmu_buffers(hevc);
devm_kfree(&pdev->dev, (void *)hevc);
vfree(hevc);
mutex_unlock(&vh265_mutex);
return ret;

View File

@@ -22,6 +22,7 @@
#include <linux/timer.h>
#include <linux/kfifo.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/amlogic/media/frame_sync/ptsserv.h>
#include <linux/amlogic/media/utils/amstream.h>
#include <linux/amlogic/media/canvas/canvas.h>
@@ -59,7 +60,10 @@
#define MREG_TO_AMRISC AV_SCRATCH_8
#define MREG_FROM_AMRISC AV_SCRATCH_9
#define MREG_FRAME_OFFSET AV_SCRATCH_A
#define DEC_STATUS_REG AV_SCRATCH_J
#define DEC_STATUS_REG AV_SCRATCH_F
#define MREG_PIC_WIDTH AV_SCRATCH_B
#define MREG_PIC_HEIGHT AV_SCRATCH_C
#define DECODE_STOP_POS AV_SCRATCH_K
#define PICINFO_BUF_IDX_MASK 0x0007
#define PICINFO_AVI1 0x0080
@@ -73,8 +77,15 @@
#define DEFAULT_MEM_SIZE (32*SZ_1M)
static int debug_enable;
static u32 udebug_flag;
#define DECODE_ID(hw) (hw_to_vdec(hw)->id)
static unsigned int radr;
static unsigned int rval;
#define VMJPEG_DEV_NUM 9
static unsigned int max_decode_instance_num = VMJPEG_DEV_NUM;
static unsigned int max_process_time[VMJPEG_DEV_NUM];
static unsigned int decode_timeout_val = 200;
static struct vframe_s *vmjpeg_vf_peek(void *);
static struct vframe_s *vmjpeg_vf_get(void *);
static void vmjpeg_vf_put(struct vframe_s *, void *);
@@ -82,6 +93,36 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *);
static int vmjpeg_event_cb(int type, void *data, void *private_data);
static void vmjpeg_work(struct work_struct *work);
static int pre_decode_buf_level = 0x800;
#undef pr_info
#define pr_info printk
unsigned int mmjpeg_debug_mask = 0xff;
#define PRINT_FLAG_ERROR 0x0
#define PRINT_FLAG_RUN_FLOW 0X0001
#define PRINT_FLAG_TIMEINFO 0x0002
#define PRINT_FLAG_UCODE_DETAIL 0x0004
#define PRINT_FLAG_VLD_DETAIL 0x0008
#define PRINT_FLAG_DEC_DETAIL 0x0010
#define PRINT_FLAG_BUFFER_DETAIL 0x0020
#define PRINT_FLAG_RESTORE 0x0040
#define PRINT_FRAME_NUM 0x0080
#define PRINT_FLAG_FORCE_DONE 0x0100
#define PRINT_FRAMEBASE_DATA 0x0400
int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...)
{
if (((debug_enable & debug_flag) &&
((1 << index) & mmjpeg_debug_mask))
|| (debug_flag == PRINT_FLAG_ERROR)) {
unsigned char buf[512];
int len = 0;
va_list args;
va_start(args, fmt);
len = sprintf(buf, "%d: ", index);
vsnprintf(buf + len, 512-len, fmt, args);
pr_info("%s", buf);
va_end(args);
}
return 0;
}
static const char vmjpeg_dec_id[] = "vmmjpeg-dev";
@@ -152,15 +193,33 @@ struct vdec_mjpeg_hw_s {
void *vdec_cb_arg;
struct firmware_s *fw;
struct timer_list check_timer;
unsigned decode_timeout_count;
u32 decode_timeout_count;
u32 start_process_time;
u32 last_vld_level;
u8 eos;
u32 frame_num, put_num;
u32 frame_num;
u32 put_num;
u32 run_count;
u32 not_run_ready;
u32 input_empty;
u32 peek_num;
u32 get_num;
};
static void reset_process_time(struct vdec_mjpeg_hw_s *hw);
static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf)
{
vf->width = hw->frame_width;
vf->height = hw->frame_height;
u32 temp;
temp = READ_VREG(MREG_PIC_WIDTH);
if (temp > 1920)
vf->width = hw->frame_width = 1920;
else if (temp > 0)
vf->width = hw->frame_width = temp;
temp = READ_VREG(MREG_PIC_HEIGHT);
if (temp > 1088)
vf->height = hw->frame_height = 1088;
else if (temp > 0)
vf->height = hw->frame_height = temp;
vf->duration = hw->frame_dur;
vf->ratio_control = 0;
vf->duration_pulldown = 0;
@@ -186,15 +245,21 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
u32 index, offset = 0, pts;
u64 pts_us64;
if (debug_enable & 0x1)
pr_info("%s: %d\n", __func__, __LINE__);
WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
if (!hw)
return IRQ_HANDLED;
if (hw->eos)
return IRQ_HANDLED;
reset_process_time(hw);
WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
if (READ_VREG(AV_SCRATCH_D) != 0 &&
(debug_enable & PRINT_FLAG_UCODE_DETAIL)) {
pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_D),
READ_VREG(AV_SCRATCH_E));
WRITE_VREG(AV_SCRATCH_D, 0);
return IRQ_HANDLED;
}
reg = READ_VREG(MREG_FROM_AMRISC);
index = READ_VREG(AV_SCRATCH_5);
@@ -237,13 +302,17 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
hw->frame_num++;
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM,
"%s:frame num:%d,pts=%d,pts64=%lld. dur=%d\n",
__func__, hw->frame_num,
vf->pts, vf->pts_us64, vf->duration);
vf_notify_receiver(vdec->vf_provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY,
NULL);
hw->dec_result = DEC_RESULT_DONE;
schedule_work(&hw->work);
vdec_schedule_work(&hw->work);
return IRQ_HANDLED;
}
@@ -256,7 +325,7 @@ static struct vframe_s *vmjpeg_vf_peek(void *op_arg)
if (!hw)
return NULL;
hw->peek_num++;
if (kfifo_peek(&hw->display_q, &vf))
return vf;
@@ -271,7 +340,7 @@ static struct vframe_s *vmjpeg_vf_get(void *op_arg)
if (!hw)
return NULL;
hw->get_num++;
if (kfifo_get(&hw->display_q, &vf))
return vf;
@@ -282,7 +351,8 @@ static void vmjpeg_vf_put(struct vframe_s *vf, void *op_arg)
{
struct vdec_s *vdec = op_arg;
struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)vdec->private;
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FRAME_NUM,
"%s:put_num:%d\n", __func__, hw->put_num);
hw->vfbuf_use[vf->index]--;
kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
hw->put_num++;
@@ -499,12 +569,120 @@ static void init_scaler(void)
WRITE_VREG(PSCALE_RST, 0x0);
}
static void vmjpeg_dump_state(struct vdec_s *vdec)
{
struct vdec_mjpeg_hw_s *hw =
(struct vdec_mjpeg_hw_s *)(vdec->private);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"====== %s\n", __func__);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"width/height (%d/%d)\n",
hw->frame_width,
hw->frame_height
);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d input_empty %d\n",
input_frame_based(vdec),
hw->eos,
hw->stat,
hw->dec_result,
hw->frame_num,
hw->put_num,
hw->run_count,
hw->not_run_ready,
hw->input_empty
);
if (vf_get_receiver(vdec->vf_provider_name)) {
enum receviver_start_e state =
vf_notify_receiver(vdec->vf_provider_name,
VFRAME_EVENT_PROVIDER_QUREY_STATE,
NULL);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"\nreceiver(%s) state %d\n",
vdec->vf_provider_name,
state);
}
mmjpeg_debug_print(DECODE_ID(hw), 0,
"%s, newq(%d/%d), dispq(%d/%d) vf peek/get/put (%d/%d/%d)\n",
__func__,
kfifo_len(&hw->newframe_q),
VF_POOL_SIZE,
kfifo_len(&hw->display_q),
VF_POOL_SIZE,
hw->peek_num,
hw->get_num,
hw->put_num
);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"VIFF_BIT_CNT=0x%x\n",
READ_VREG(VIFF_BIT_CNT));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"VLD_MEM_VIFIFO_LEVEL=0x%x\n",
READ_VREG(VLD_MEM_VIFIFO_LEVEL));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"VLD_MEM_VIFIFO_WP=0x%x\n",
READ_VREG(VLD_MEM_VIFIFO_WP));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"VLD_MEM_VIFIFO_RP=0x%x\n",
READ_VREG(VLD_MEM_VIFIFO_RP));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_RP=0x%x\n",
READ_PARSER_REG(PARSER_VIDEO_RP));
mmjpeg_debug_print(DECODE_ID(hw), 0,
"PARSER_VIDEO_WP=0x%x\n",
READ_PARSER_REG(PARSER_VIDEO_WP));
if (input_frame_based(vdec) &&
debug_enable & PRINT_FRAMEBASE_DATA
) {
int jj;
if (hw->chunk && hw->chunk->block &&
hw->chunk->size > 0) {
u8 *data =
((u8 *)hw->chunk->block->start_virt) +
hw->chunk->offset;
mmjpeg_debug_print(DECODE_ID(hw), 0,
"frame data size 0x%x\n",
hw->chunk->size);
for (jj = 0; jj < hw->chunk->size; jj++) {
if ((jj & 0xf) == 0)
mmjpeg_debug_print(DECODE_ID(hw),
PRINT_FRAMEBASE_DATA,
"%06x:", jj);
mmjpeg_debug_print(DECODE_ID(hw),
PRINT_FRAMEBASE_DATA,
"%02x ", data[jj]);
if (((jj + 1) & 0xf) == 0)
mmjpeg_debug_print(DECODE_ID(hw),
PRINT_FRAMEBASE_DATA,
"\n");
}
}
}
}
static void reset_process_time(struct vdec_mjpeg_hw_s *hw)
{
if (hw->start_process_time) {
unsigned process_time =
1000 * (jiffies - hw->start_process_time) / HZ;
hw->start_process_time = 0;
if (process_time > max_process_time[DECODE_ID(hw)])
max_process_time[DECODE_ID(hw)] = process_time;
}
}
static void start_process_time(struct vdec_mjpeg_hw_s *hw)
{
hw->decode_timeout_count = 2;
hw->start_process_time = jiffies;
}
static void timeout_process(struct vdec_mjpeg_hw_s *hw)
{
amvdec_stop();
pr_info("%s decoder timeout\n", __func__);
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"%s decoder timeout\n", __func__);
hw->dec_result = DEC_RESULT_DONE;
reset_process_time(hw);
vdec_schedule_work(&hw->work);
}
@@ -512,31 +690,43 @@ static void check_timer_func(unsigned long arg)
{
struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)arg;
struct vdec_s *vdec = hw_to_vdec(hw);
if ((debug_enable & 0x2) != 0) {
pr_info("%s: status:nstatus=%d:%d\n",
int timeout_val = decode_timeout_val;
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
"%s: status:nstatus=%d:%d\n",
__func__, vdec->status, vdec->next_status);
pr_info("%s: %d,buftl=%x:%x:%x:%x\n",
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_VLD_DETAIL,
"%s: %d,buftl=%x:%x:%x:%x\n",
__func__, __LINE__,
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
READ_PARSER_REG(PARSER_VIDEO_WP),
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP));
}
if ((debug_enable & 0x100) != 0) {
hw->dec_result = DEC_RESULT_DONE;
vdec_schedule_work(&hw->work);
pr_info("vdec %d is forced to be disconnected\n",
debug_enable & 0xff);
debug_enable = 0;
return;
if (radr != 0) {
if (rval != 0) {
WRITE_VREG(radr, rval);
pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
} else
pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
rval = 0;
radr = 0;
}
if (input_stream_based(vdec)
&& READ_VREG(VLD_MEM_VIFIFO_LEVEL) <= 0x80) {
if (hw->decode_timeout_count > 0)
hw->decode_timeout_count--;
if (hw->decode_timeout_count == 0)
timeout_process(hw);
if ((debug_enable == 0) &&
(input_frame_based(vdec) ||
(READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x100)) &&
(timeout_val > 0) &&
(hw->start_process_time > 0) &&
((1000 * (jiffies - hw->start_process_time) / HZ)
> timeout_val)) {
if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) {
if (hw->decode_timeout_count > 0)
hw->decode_timeout_count--;
if (hw->decode_timeout_count == 0)
timeout_process(hw);
}
hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
}
if (READ_VREG(DEC_STATUS_REG) == DEC_DECODE_TIMEOUT) {
@@ -556,6 +746,7 @@ static void check_timer_func(unsigned long arg)
}
mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
}
static void vmjpeg_hw_ctx_restore(struct vdec_s *vdec, int index)
{
struct vdec_mjpeg_hw_s *hw =
@@ -614,12 +805,18 @@ static s32 vmjpeg_init(struct vdec_s *vdec)
hw->frame_width = hw->vmjpeg_amstream_dec_info.width;
hw->frame_height = hw->vmjpeg_amstream_dec_info.height;
hw->frame_dur = hw->vmjpeg_amstream_dec_info.rate;
hw->frame_dur = ((hw->vmjpeg_amstream_dec_info.rate) ?
hw->vmjpeg_amstream_dec_info.rate : 3840);
hw->saved_resolution = 0;
hw->eos = 0;
hw->init_flag = 0;
hw->frame_num = 0;
hw->put_num = 0;
hw->run_count = 0;
hw->not_run_ready = 0;
hw->input_empty = 0;
hw->peek_num = 0;
hw->get_num = 0;
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
hw->vfbuf_use[i] = 0;
@@ -653,16 +850,20 @@ static s32 vmjpeg_init(struct vdec_s *vdec)
hw->check_timer.expires = jiffies + CHECK_INTERVAL;
/*add_timer(&hw->check_timer);*/
hw->stat |= STAT_TIMER_ARM;
hw->stat |= STAT_ISR_REG;
WRITE_VREG(DECODE_STOP_POS, udebug_flag);
INIT_WORK(&hw->work, vmjpeg_work);
pr_info("w:h=%d:%d\n", hw->frame_width, hw->frame_height);
return 0;
}
static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
static unsigned long run_ready(struct vdec_s *vdec,
unsigned long mask)
{
struct vdec_mjpeg_hw_s *hw =
(struct vdec_mjpeg_hw_s *)vdec->private;
hw->not_run_ready++;
if (hw->eos)
return 0;
if (vdec_stream_based(vdec) && (hw->init_flag == 0)
@@ -679,6 +880,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (level < pre_decode_buf_level)
return 0;
}
hw->not_run_ready = 0;
return CORE_MASK_VDEC_1 | CORE_MASK_HEVC;
}
@@ -687,11 +889,13 @@ static void run(struct vdec_s *vdec, unsigned long mask,
{
struct vdec_mjpeg_hw_s *hw =
(struct vdec_mjpeg_hw_s *)vdec->private;
int i,ret = -1;
int i, ret;
hw->vdec_cb_arg = arg;
hw->vdec_cb = callback;
hw->run_count++;
vdec_reset_core(vdec);
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
if (hw->vfbuf_use[i] == 0)
break;
@@ -699,30 +903,33 @@ static void run(struct vdec_s *vdec, unsigned long mask,
if (i == DECODE_BUFFER_NUM_MAX) {
hw->dec_result = DEC_RESULT_AGAIN;
schedule_work(&hw->work);
vdec_schedule_work(&hw->work);
return;
}
ret = vdec_prepare_input(vdec, &hw->chunk);
if (ret < 0) {
if (debug_enable & 0x1) {
pr_info("%s: %d,r=%d,buftl=%x:%x:%x\n",
if (ret <= 0) {
hw->input_empty++;
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
"%s: %d,r=%d,buftl=%x:%x:%x\n",
__func__, __LINE__, ret,
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
READ_PARSER_REG(PARSER_VIDEO_WP),
READ_VREG(VLD_MEM_VIFIFO_WP));
}
hw->dec_result = DEC_RESULT_AGAIN;
schedule_work(&hw->work);
vdec_schedule_work(&hw->work);
return;
}
hw->input_empty = 0;
hw->dec_result = DEC_RESULT_NONE;
ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data);
if (ret < 0) {
pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n",
vdec->id, tee_enabled() ? "TEE" : "local", ret);
hw->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hw->work);
return;
}
/* if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) {
@@ -735,42 +942,63 @@ static void run(struct vdec_s *vdec, unsigned long mask,
vdec_enable_input(vdec);
mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
#endif
hw->stat |= STAT_MC_LOAD;
start_process_time(hw);
hw->last_vld_level = 0;
mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
amvdec_start();
vdec_enable_input(vdec);
mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
hw->decode_timeout_count = 2;
hw->stat |= STAT_VDEC_RUN;
hw->init_flag = 1;
if (debug_enable&0x1) {
pr_info("%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
__func__,
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
READ_VREG(VLD_DECODE_CONTROL),
READ_VREG(VIFF_BIT_CNT),
READ_VREG(POWER_CTL_VLD),
READ_VREG(VLD_MEM_VIFIFO_START_PTR),
READ_VREG(VLD_MEM_VIFIFO_CURR_PTR),
READ_VREG(VLD_MEM_VIFIFO_CONTROL),
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
READ_VREG(VLD_MEM_VIFIFO_END_PTR));
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
"%s (0x%x 0x%x 0x%x) vldcrl 0x%x bitcnt 0x%x powerctl 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
__func__,
READ_VREG(VLD_MEM_VIFIFO_LEVEL),
READ_VREG(VLD_MEM_VIFIFO_WP),
READ_VREG(VLD_MEM_VIFIFO_RP),
READ_VREG(VLD_DECODE_CONTROL),
READ_VREG(VIFF_BIT_CNT),
READ_VREG(POWER_CTL_VLD),
READ_VREG(VLD_MEM_VIFIFO_START_PTR),
READ_VREG(VLD_MEM_VIFIFO_CURR_PTR),
READ_VREG(VLD_MEM_VIFIFO_CONTROL),
READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL),
READ_VREG(VLD_MEM_VIFIFO_END_PTR));
}
static void wait_vmjpeg_search_done(struct vdec_mjpeg_hw_s *hw)
{
u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
int count = 0;
}
do {
usleep_range(100, 500);
if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP))
break;
if (count > 1000) {
mmjpeg_debug_print(DECODE_ID(hw), 0,
"%s, count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n",
__func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP));
break;
} else
vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
count++;
} while (1);
}
static void vmjpeg_work(struct work_struct *work)
{
struct vdec_mjpeg_hw_s *hw = container_of(work,
struct vdec_mjpeg_hw_s, work);
if (debug_enable & 0x2)
pr_info("%s: result=%d,len=%d:%d\n",
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL,
"%s: result=%d,len=%d:%d\n",
__func__, hw->dec_result,
kfifo_len(&hw->newframe_q),
kfifo_len(&hw->display_q));
if (hw->dec_result == DEC_RESULT_DONE)
if (hw->dec_result == DEC_RESULT_DONE) {
vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
else if (hw->dec_result == DEC_RESULT_AGAIN) {
} else if (hw->dec_result == DEC_RESULT_AGAIN) {
/*
stream base: stream buf empty or timeout
frame base: vdec_prepare_input fail
@@ -783,16 +1011,29 @@ static void vmjpeg_work(struct work_struct *work)
return;
}
} else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) {
pr_info("%s: force exit\n",
__func__);
pr_info("%s: force exit\n", __func__);
if (hw->stat & STAT_ISR_REG) {
amvdec_stop();
/*disable mbox interrupt */
WRITE_VREG(ASSIST_MBOX1_MASK, 0);
vdec_free_irq(VDEC_IRQ_1, (void *)hw);
hw->stat &= ~STAT_ISR_REG;
}
} else if (hw->dec_result == DEC_RESULT_EOS) {
/*pr_info("%s: end of stream\n",
__func__);*/
if (READ_VREG(VLD_MEM_VIFIFO_LEVEL) < 0x100)
hw->eos = 1;
pr_info("%s: end of stream\n", __func__);
if (hw->stat & STAT_VDEC_RUN) {
amvdec_stop();
hw->stat &= ~STAT_VDEC_RUN;
}
hw->eos = 1;
vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
vdec_clean_input(hw_to_vdec(hw));
}
amvdec_stop();
if (hw->stat & STAT_VDEC_RUN) {
amvdec_stop();
hw->stat &= ~STAT_VDEC_RUN;
}
wait_vmjpeg_search_done(hw);
/* mark itself has all HW resource released and input released */
vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1
| CORE_MASK_HEVC);
@@ -803,13 +1044,48 @@ static void vmjpeg_work(struct work_struct *work)
hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
}
static int amvdec_mjpeg_probe(struct platform_device *pdev)
static int vmjpeg_stop(struct vdec_mjpeg_hw_s *hw)
{
pr_info("%s ...count = %d\n", __func__, hw->frame_num);
if (hw->stat & STAT_VDEC_RUN) {
amvdec_stop();
pr_info("%s amvdec_stop\n", __func__);
hw->stat &= ~STAT_VDEC_RUN;
}
if (hw->stat & STAT_ISR_REG) {
vdec_free_irq(VDEC_IRQ_1, (void *)hw);
hw->stat &= ~STAT_ISR_REG;
}
if (hw->stat & STAT_TIMER_ARM) {
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
}
cancel_work_sync(&hw->work);
hw->init_flag = 0;
if (hw->mm_blk_handle) {
decoder_bmmu_box_free(hw->mm_blk_handle);
hw->mm_blk_handle = NULL;
}
if (hw->fw) {
vfree(hw->fw);
hw->fw = NULL;
}
return 0;
}
static int ammvdec_mjpeg_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
struct vdec_mjpeg_hw_s *hw = NULL;
if (pdata == NULL) {
pr_info("amvdec_mjpeg memory resource undefined.\n");
pr_info("ammvdec_mjpeg memory resource undefined.\n");
return -EFAULT;
}
@@ -826,6 +1102,7 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev)
pdata->run = run;
pdata->run_ready = run_ready;
pdata->irq_handler = vmjpeg_isr;
pdata->dump_state = vmjpeg_dump_state;
if (pdata->use_vfm_path)
@@ -845,8 +1122,11 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev)
if (pdata->sys_info)
hw->vmjpeg_amstream_dec_info = *pdata->sys_info;
vdec_source_changed(VFORMAT_MJPEG,
1920, 1080, 60);
if (vmjpeg_init(pdata) < 0) {
pr_info("amvdec_mjpeg init failed.\n");
pr_info("ammvdec_mjpeg init failed.\n");
devm_kfree(&pdev->dev, (void *)hw);
return -ENODEV;
}
@@ -856,37 +1136,26 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev)
return 0;
}
static int amvdec_mjpeg_remove(struct platform_device *pdev)
static int ammvdec_mjpeg_remove(struct platform_device *pdev)
{
struct vdec_mjpeg_hw_s *hw =
(struct vdec_mjpeg_hw_s *)
(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
if (hw->stat & STAT_TIMER_ARM) {
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
}
cancel_work_sync(&hw->work);
if (hw->mm_blk_handle) {
decoder_bmmu_box_free(hw->mm_blk_handle);
hw->mm_blk_handle = NULL;
}
vfree(hw->fw);
hw->fw = NULL;
vmjpeg_stop(hw);
vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED);
pr_info("%s\n", __func__);
return 0;
}
/****************************************/
static struct platform_driver amvdec_mjpeg_driver = {
.probe = amvdec_mjpeg_probe,
.remove = amvdec_mjpeg_remove,
static struct platform_driver ammvdec_mjpeg_driver = {
.probe = ammvdec_mjpeg_probe,
.remove = ammvdec_mjpeg_remove,
#ifdef CONFIG_PM
.suspend = amvdec_suspend,
.resume = amvdec_resume,
@@ -896,24 +1165,24 @@ static struct platform_driver amvdec_mjpeg_driver = {
}
};
static struct codec_profile_t amvdec_mjpeg_profile = {
static struct codec_profile_t ammvdec_mjpeg_profile = {
.name = "mmjpeg",
.profile = ""
};
static int __init amvdec_mjpeg_driver_init_module(void)
static int __init ammvdec_mjpeg_driver_init_module(void)
{
if (platform_driver_register(&amvdec_mjpeg_driver)) {
pr_err("failed to register amvdec_mjpeg driver\n");
if (platform_driver_register(&ammvdec_mjpeg_driver)) {
pr_err("failed to register ammvdec_mjpeg driver\n");
return -ENODEV;
}
vcodec_profile_register(&amvdec_mjpeg_profile);
vcodec_profile_register(&ammvdec_mjpeg_profile);
return 0;
}
static void __exit amvdec_mjpeg_driver_remove_module(void)
static void __exit ammvdec_mjpeg_driver_remove_module(void)
{
platform_driver_unregister(&amvdec_mjpeg_driver);
platform_driver_unregister(&ammvdec_mjpeg_driver);
}
/****************************************/
@@ -922,8 +1191,23 @@ MODULE_PARM_DESC(debug_enable, "\n debug enable\n");
module_param(pre_decode_buf_level, int, 0664);
MODULE_PARM_DESC(pre_decode_buf_level,
"\n ammvdec_h264 pre_decode_buf_level\n");
module_init(amvdec_mjpeg_driver_init_module);
module_exit(amvdec_mjpeg_driver_remove_module);
module_param(udebug_flag, uint, 0664);
MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n");
module_param(decode_timeout_val, uint, 0664);
MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n");
module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
module_param(radr, uint, 0664);
MODULE_PARM_DESC(radr, "\nradr\n");
module_param(rval, uint, 0664);
MODULE_PARM_DESC(rval, "\nrval\n");
module_init(ammvdec_mjpeg_driver_init_module);
module_exit(ammvdec_mjpeg_driver_remove_module);
MODULE_DESCRIPTION("AMLOGIC MJMPEG Video Decoder Driver");
MODULE_LICENSE("GPL");

View File

@@ -1,2 +1,5 @@
obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12) += amvdec_mpeg12.o
amvdec_mpeg12-objs += vmpeg12.o
obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI) += amvdec_mmpeg12.o
amvdec_mmpeg12-objs += vmpeg12_multi.o

File diff suppressed because it is too large Load Diff

View File

@@ -397,7 +397,10 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name)
break;
case VFORMAT_MPEG12:
format = VIDEO_DEC_MPEG12;
if (!strcmp(name, "mpeg12"))
format = VIDEO_DEC_MPEG12;
else if (!strcmp(name, "mmpeg12"))
format = VIDEO_DEC_MPEG12_MULTI;
break;
case VFORMAT_MJPEG:
@@ -434,14 +437,19 @@ s32 optee_load_fw(enum vformat_e type, const char *fw_name)
break;
case VFORMAT_MPEG4:
if (!strcmp(name, "vmpeg4_mc_311"))
format = VIDEO_DEC_MPEG4_3;
else if (!strcmp(name, "vmpeg4_mc_4"))
format = VIDEO_DEC_MPEG4_4;
if (!strcmp(name, "mmpeg4_mc_5"))
format = VIDEO_DEC_MPEG4_5_MULTI;
else if ((!strcmp(name, "mh263_mc")))
format = VIDEO_DEC_H263_MULTI;
else if (!strcmp(name, "vmpeg4_mc_5"))
format = VIDEO_DEC_MPEG4_5;
else if (!strcmp(name, "h263_mc"))
format = VIDEO_DEC_H263;
/*not support now*/
else if (!strcmp(name, "vmpeg4_mc_311"))
format = VIDEO_DEC_MPEG4_3;
else if (!strcmp(name, "vmpeg4_mc_4"))
format = VIDEO_DEC_MPEG4_4;
break;
case VFORMAT_H264_4K2K:
@@ -803,6 +811,12 @@ void amvdec_stop(void)
break;
}
timeout = jiffies + HZ;
while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
if (time_after(jiffies, timeout))
break;
}
/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
READ_VREG(DOS_SW_RESET0);
@@ -876,6 +890,12 @@ void amhevc_stop(void)
break;
}
timeout = jiffies + HZ;
while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) {
if (time_after(jiffies, timeout))
break;
}
READ_VREG(DOS_SW_RESET3);
READ_VREG(DOS_SW_RESET3);
READ_VREG(DOS_SW_RESET3);

View File

@@ -1213,7 +1213,7 @@ void vdec_clean_input(struct vdec_s *vdec)
while (!list_empty(&input->vframe_chunk_list)) {
struct vframe_chunk_s *chunk =
vdec_input_next_chunk(input);
if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED)
if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED))
vdec_input_release_chunk(input, chunk);
else
break;
@@ -1372,13 +1372,23 @@ int vdec_disconnect(struct vdec_s *vdec)
mutex_unlock(&vdec_mutex);
up(&vdec_core->sem);
wait_for_completion(&vdec->inactive_done);
if(!wait_for_completion_timeout(&vdec->inactive_done,
msecs_to_jiffies(2000)))
goto discon_timeout;
if (vdec->slave)
wait_for_completion(&vdec->slave->inactive_done);
else if (vdec->master)
wait_for_completion(&vdec->master->inactive_done);
if (vdec->slave) {
if(!wait_for_completion_timeout(&vdec->slave->inactive_done,
msecs_to_jiffies(2000)))
goto discon_timeout;
} else if (vdec->master) {
if(!wait_for_completion_timeout(&vdec->master->inactive_done,
msecs_to_jiffies(2000)))
goto discon_timeout;
}
return 0;
discon_timeout:
pr_err("%s timeout!!! status: 0x%x\n", __func__, vdec->status);
return 0;
}
EXPORT_SYMBOL(vdec_disconnect);
@@ -2021,6 +2031,20 @@ static void vdec_route_interrupt(struct vdec_s *vdec, unsigned long mask,
}
}
static void vdec_remove_reset(struct vdec_s *vdec)
{
struct vdec_input_s *input = &vdec->input;
if (input->target == VDEC_INPUT_TARGET_VLD) {
amvdec_stop();
vdec_reset_core(vdec);
} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
amhevc_stop();
hevc_reset_core(vdec);
}
pr_info(" %s vdec %p\n", __func__, vdec);
}
/*
* Set up secure protection for each decoder instance running.
* Note: The operation from REE side only resets memory access
@@ -2102,8 +2126,8 @@ static int vdec_core_thread(void *data)
&input->vframe_chunk_list)) {
struct vframe_chunk_s *chunk =
vdec_input_next_chunk(input);
if (chunk->flag &
VFRAME_CHUNK_FLAG_CONSUMED)
if (chunk && (chunk->flag &
VFRAME_CHUNK_FLAG_CONSUMED))
vdec_input_release_chunk(input,
chunk);
else
@@ -2137,8 +2161,10 @@ static int vdec_core_thread(void *data)
&core->connected_vdec_list, list) {
if ((vdec->status == VDEC_STATUS_CONNECTED) &&
(vdec->next_status == VDEC_STATUS_DISCONNECTED)) {
if (core->active_vdec == vdec)
if (core->active_vdec == vdec) {
vdec_remove_reset(vdec);
core->active_vdec = NULL;
}
list_move(&vdec->list, &disconnecting_list);
}
}
@@ -2773,6 +2799,45 @@ int vdec_source_changed(int format, int width, int height, int fps)
}
EXPORT_SYMBOL(vdec_source_changed);
void vdec_reset_core(struct vdec_s *vdec)
{
unsigned long flags;
spin_lock_irqsave(&vdec_spin_lock, flags);
codec_dmcbus_write(DMC_REQ_CTRL,
codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13)));
spin_unlock_irqrestore(&vdec_spin_lock, flags);
while (!(codec_dmcbus_read(DMC_CHAN_STS)
& (1 << 13)))
;
/*
* 2: assist
* 3: vld_reset
* 4: vld_part_reset
* 5: vfifo reset
* 6: iqidct
* 7: mc
* 8: dblk
* 9: pic_dc
* 10: psc
* 11: mcpu
* 12: ccpu
* 13: ddr
* 14: afifo
*/
WRITE_VREG(DOS_SW_RESET0,
(1<<3)|(1<<4)|(1<<5));
WRITE_VREG(DOS_SW_RESET0, 0);
spin_lock_irqsave(&vdec_spin_lock, flags);
codec_dmcbus_write(DMC_REQ_CTRL,
codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13));
spin_unlock_irqrestore(&vdec_spin_lock, flags);
}
EXPORT_SYMBOL(vdec_reset_core);
void hevc_reset_core(struct vdec_s *vdec)
{
unsigned long flags;

View File

@@ -385,6 +385,8 @@ extern void vdec_count_info(struct vdec_info *vs, unsigned int err,
extern bool vdec_need_more_data(struct vdec_s *vdec);
extern void vdec_reset_core(struct vdec_s *vdec);
extern void hevc_reset_core(struct vdec_s *vdec);
extern void vdec_set_suspend_clk(int mode, int hevc);

View File

@@ -802,11 +802,10 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf,
/*nopts*/
input->last_in_nopts_cnt++;
}
vdec_input_unlock(input, flags);
if (chunk->size > input->frame_max_size)
input->frame_max_size = chunk->size;
input->total_wr_count += count;
vdec_input_unlock(input, flags);
#if 0
if (add_count == 2)
input->total_wr_count += 38;

View File

@@ -6998,8 +6998,7 @@ int continue_decoding(struct VP9Decoder_s *pbi)
}
pbi->process_state = PROC_STATE_DECODESLICE;
if (pbi->mmu_enable) {
if (pbi->last_put_idx >= 0 &&
pbi->last_put_idx < pbi->used_buf_num) {
if (pbi->last_put_idx < pbi->used_buf_num) {
struct RefCntBuffer_s *frame_bufs =
cm->buffer_pool->frame_bufs;
int i = pbi->last_put_idx;
@@ -8663,6 +8662,8 @@ static void run_front(struct vdec_s *vdec)
vp9_print(pbi, PRINT_FLAG_ERROR,
"VP9: the %s fw loading failed, err: %x\n",
tee_enabled() ? "TEE" : "local", ret);
pbi->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&pbi->work);
return;
}