summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--drivers/amvdec_ports/Makefile13
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c22
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h3
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c534
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h39
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c57
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h11
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.c18
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.h8
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.c9
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.h6
-rw-r--r--drivers/amvdec_ports/decoder/aml_h264_parser.c662
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_h264_parser.h226
-rw-r--r--drivers/amvdec_ports/decoder/aml_hevc_parser.c1274
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_hevc_parser.h137
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.c397
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.h163
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.c198
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.h74
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.c1233
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.h250
-rw-r--r--drivers/amvdec_ports/decoder/aml_vp9_parser.c299
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_vp9_parser.h279
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.c389
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.h141
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.c111
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.h39
-rw-r--r--drivers/amvdec_ports/decoder/vdec_h264_if.c357
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c477
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c498
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c490
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c499
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c461
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/vdec_vp9_trigger.h0
-rw-r--r--drivers/amvdec_ports/test/vcodec_m2m_test.c18
-rw-r--r--drivers/amvdec_ports/utils/common.c221
-rw-r--r--drivers/amvdec_ports/utils/common.h72
-rw-r--r--drivers/amvdec_ports/utils/get_bits.h590
-rw-r--r--drivers/amvdec_ports/utils/golomb.c147
-rw-r--r--drivers/amvdec_ports/utils/golomb.h500
-rw-r--r--drivers/amvdec_ports/utils/pixfmt.h470
-rw-r--r--drivers/amvdec_ports/utils/put_bits.h323
-rw-r--r--drivers/amvdec_ports/vdec_drv_base.h11
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.c45
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h10
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c219
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c308
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c334
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c233
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c317
-rw-r--r--drivers/frame_provider/decoder/utils/Makefile1
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_input.c19
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c131
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h22
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c388
55 files changed, 11471 insertions, 2282 deletions
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index a466b2a..6643f41 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -47,6 +47,7 @@
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/firmware.h"
+#include "../utils/vdec_v4l2_buffer_ops.h"
#define MEM_NAME "codec_mmpeg12"
@@ -197,6 +198,7 @@ struct pic_info_t {
u32 pts;
u64 pts64;
bool pts_valid;
+ ulong v4l_ref_buf_addr;
};
struct vdec_mpeg12_hw_s {
@@ -295,6 +297,9 @@ struct vdec_mpeg12_hw_s {
u32 reference[MAX_UD_RECORDS];
#endif
int tvp_flag;
+ bool is_used_v4l;
+ void *v4l2_ctx;
+ bool v4l_params_parsed;
};
static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -310,7 +315,7 @@ unsigned int mpeg12_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_UCODE_DETAIL 0x0004
#define PRINT_FLAG_VLD_DETAIL 0x0008
#define PRINT_FLAG_DEC_DETAIL 0x0010
#define PRINT_FLAG_BUFFER_DETAIL 0x0020
@@ -322,7 +327,8 @@ unsigned int mpeg12_debug_mask = 0xff;
#define PRINT_FLAG_VDEC_STATUS 0x0800
#define PRINT_FLAG_PARA_DATA 0x1000
#define PRINT_FLAG_USERDATA_DETAIL 0x2000
-#define PRINT_FLAG_TIMEOUT_STATUS 0x4000
+#define PRINT_FLAG_TIMEOUT_STATUS 0x4000
+#define PRINT_FLAG_V4L_DETAIL 0x8000
@@ -364,17 +370,114 @@ static const u32 frame_rate_tab[16] = {
96000 / 24, 96000 / 24, 96000 / 24
};
+static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int i)
+{
+ int ret;
+ u32 canvas;
+ ulong decbuf_start = 0;
+ int decbuf_y_size = 0;
+ u32 canvas_width = 0, canvas_height = 0;
+ struct vdec_s *vdec = hw_to_vdec(hw);
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ if (hw->pics[i].v4l_ref_buf_addr)
+ return 0;
+
+ ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+ if (ret) {
+ debug_print(DECODE_ID(hw), 0,
+ "[%d] get fb fail.\n",
+ ((struct aml_vcodec_ctx *)
+ (hw->v4l2_ctx))->id);
+ return ret;
+ }
+
+ hw->pics[i].v4l_ref_buf_addr = (ulong)fb;
+ if (fb->num_planes == 1) {
+ decbuf_start = fb->m.mem[0].addr;
+ decbuf_y_size = fb->m.mem[0].offset;
+ canvas_width = ALIGN(hw->frame_width, 64);
+ canvas_height = ALIGN(hw->frame_height, 32);
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ } else if (fb->num_planes == 2) {
+ decbuf_start = fb->m.mem[0].addr;
+ decbuf_y_size = fb->m.mem[0].size;
+ canvas_width = ALIGN(hw->frame_width, 64);
+ canvas_height = ALIGN(hw->frame_height, 32);
+ fb->m.mem[0].bytes_used = decbuf_y_size;
+ fb->m.mem[1].bytes_used = decbuf_y_size << 1;
+ }
+
+ debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n",
+ ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb);
-static u32 find_buffer(struct vdec_mpeg12_hw_s *hw)
+ if (vdec->parallel_dec == 1) {
+ u32 tmp;
+ if (canvas_y(hw->canvas_spec[i]) == 0xff) {
+ tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+ hw->canvas_spec[i] &= ~0xff;
+ hw->canvas_spec[i] |= tmp;
+ }
+ if (canvas_u(hw->canvas_spec[i]) == 0xff) {
+ tmp = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+ hw->canvas_spec[i] &= ~(0xffff << 8);
+ hw->canvas_spec[i] |= tmp << 8;
+ hw->canvas_spec[i] |= tmp << 16;
+ }
+ canvas = hw->canvas_spec[i];
+ } else {
+ canvas = vdec->get_canvas(i, 2);
+ hw->canvas_spec[i] = canvas;
+ }
+
+ hw->canvas_config[i][0].phy_addr = decbuf_start;
+ hw->canvas_config[i][0].width = canvas_width;
+ hw->canvas_config[i][0].height = canvas_height;
+ hw->canvas_config[i][0].block_mode = hw->canvas_mode;
+ hw->canvas_config[i][0].endian =
+ (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
+ canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]);
+
+ hw->canvas_config[i][1].phy_addr = decbuf_start + decbuf_y_size;
+ hw->canvas_config[i][1].width = canvas_width;
+ hw->canvas_config[i][1].height = canvas_height / 2;
+ hw->canvas_config[i][1].block_mode = hw->canvas_mode;
+ hw->canvas_config[i][1].endian =
+ (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
+ canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]);
+
+ return 0;
+}
+
+
+static bool is_enough_free_buffer(struct vdec_mpeg12_hw_s *hw)
{
- u32 i;
+ int i;
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
if (hw->vfbuf_use[i] == 0)
- return i;
+ break;
}
- return DECODE_BUFFER_NUM_MAX;
+ return i == DECODE_BUFFER_NUM_MAX ? false : true;
+}
+
+static int find_free_buffer(struct vdec_mpeg12_hw_s *hw)
+{
+ int i;
+
+ for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ if (hw->vfbuf_use[i] == 0)
+ break;
+ }
+
+ if (i == DECODE_BUFFER_NUM_MAX)
+ return -1;
+
+ if (hw->is_used_v4l)
+ if (vmpeg12_v4l_alloc_buff_config_canvas(hw, i))
+ return -1;
+ return i;
}
static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec)
@@ -1269,6 +1372,21 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
vdec_schedule_work(&hw->work);
return -1;
}
+
+ if (hw->is_used_v4l) {
+ vf->v4l_mem_handle
+ = hw->pics[index].v4l_ref_buf_addr;
+ if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
+ debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+ "v4l: binding vf fail.\n");
+ return -1;
+ }
+ debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+ "[%d] %s(), v4l mem handle: 0x%lx\n",
+ ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
+ __func__, vf->v4l_mem_handle);
+ }
+
hw->vfbuf_use[index]++;
vf->index = index;
set_frame_info(hw, vf);
@@ -1509,6 +1627,26 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
hw->frame_height = tmp;
}
+ if (hw->is_used_v4l) {
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
+ struct aml_vdec_pic_infos info;
+
+ info.visible_width = hw->frame_width;
+ info.visible_height = hw->frame_height;
+ info.coded_width = ALIGN(hw->frame_width, 64);
+ info.coded_height = ALIGN(hw->frame_height, 64);
+ info.dpb_size = MAX_BMMU_BUFFER_NUM - 1;
+ hw->v4l_params_parsed = true;
+ vdec_v4l_set_pic_infos(ctx, &info);
+ }
+
+ if (!ctx->v4l_codec_ready)
+ return IRQ_HANDLED;
+ }
+
new_pic->buffer_info = info;
new_pic->offset = offset;
new_pic->index = index;
@@ -1660,6 +1798,40 @@ static void flush_output(struct vdec_mpeg12_hw_s *hw)
prepare_display_buf(hw, &hw->pics[index]);
}
+static int notify_v4l_eos(struct vdec_s *vdec)
+{
+ struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)vdec->private;
+ struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+ struct vframe_s *vf = NULL;
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ if (hw->is_used_v4l && hw->eos) {
+ if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
+ debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+ "%s fatal error, no available buffer slot.\n",
+ __func__);
+ return -1;
+ }
+
+ if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
+ pr_err("[%d] get fb fail.\n", ctx->id);
+ return -1;
+ }
+
+ vf->timestamp = ULONG_MAX;
+ vf->v4l_mem_handle = (unsigned long)fb;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+
+ kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+ vf_notify_receiver(vdec->vf_provider_name,
+ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+ pr_info("[%d] mpeg12 EOS notify.\n", ctx->id);
+ }
+
+ return 0;
+}
+
static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw,
struct vdec_s *vdec, int from)
{
@@ -1720,6 +1892,9 @@ static void vmpeg12_work_implement(struct vdec_mpeg12_hw_s *hw,
hw->chunk = NULL;
vdec_clean_input(vdec);
flush_output(hw);
+ if (hw->is_used_v4l)
+ notify_v4l_eos(vdec);
+
debug_print(DECODE_ID(hw), 0,
"%s: end of stream, num %d(%d)\n",
__func__, hw->disp_num, hw->dec_num);
@@ -1903,16 +2078,21 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
}
for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) {
-
unsigned canvas;
+
if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */
decbuf_size = WORKSPACE_SIZE;
- ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
- decbuf_size, DRIVER_NAME, &decbuf_start);
- if (ret < 0) {
- pr_err("mmu alloc failed! size 0x%d idx %d\n",
- decbuf_size, i);
- return;
+
+ if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) {
+ continue;
+ } else {
+ ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
+ decbuf_size, DRIVER_NAME, &decbuf_start);
+ if (ret < 0) {
+ pr_err("mmu alloc failed! size 0x%d idx %d\n",
+ decbuf_size, i);
+ return;
+ }
}
if (i == (MAX_BMMU_BUFFER_NUM - 1)) {
@@ -2181,18 +2361,20 @@ static void check_timer_func(unsigned long arg)
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
{
u32 index, i;
- index = find_buffer(hw);
+ index = find_free_buffer(hw);
if (index >= DECODE_BUFFER_NUM_MAX)
return -1;
if (!hw->init_flag)
vmpeg12_canvas_init(hw);
else {
- WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
- canvas_config_config(canvas_y(hw->canvas_spec[i]),
- &hw->canvas_config[i][0]);
- canvas_config_config(canvas_u(hw->canvas_spec[i]),
- &hw->canvas_config[i][1]);
+ if (!hw->is_used_v4l) {
+ WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
+ for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ canvas_config_config(canvas_y(hw->canvas_spec[i]),
+ &hw->canvas_config[i][0]);
+ canvas_config_config(canvas_u(hw->canvas_spec[i]),
+ &hw->canvas_config[i][1]);
+ }
}
}
@@ -2393,8 +2575,6 @@ static s32 vmpeg12_init(struct vdec_mpeg12_hw_s *hw)
static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
- int index;
-
struct vdec_mpeg12_hw_s *hw =
(struct vdec_mpeg12_hw_s *)vdec->private;
if (hw->eos)
@@ -2433,8 +2613,7 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
}
#endif
- index = find_buffer(hw);
- if (index >= DECODE_BUFFER_NUM_MAX) {
+ if (!is_enough_free_buffer(hw)) {
hw->buffer_not_ready++;
return 0;
}
@@ -2619,6 +2798,9 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /* the ctx from v4l2 driver. */
+ hw->v4l2_ctx = pdata->private;
+
pdata->private = hw;
pdata->dec_status = vmmpeg12_dec_status;
pdata->run_ready = run_ready;
@@ -2683,6 +2865,9 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
reset_user_data_buf(hw);
#endif
+ hw->is_used_v4l = (((unsigned long)
+ hw->vmpeg12_amstream_dec_info.param & 0x80) >> 7);
+
/*INIT_WORK(&userdata_push_work, userdata_push_do_work);*/
return 0;
}