mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
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:
committed by
Dongjin Kim
parent
48ee09ae0d
commit
1a63229ef3
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user