summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2020-05-14 14:47:19 (GMT)
committer Nanxin Qin <nanxin.qin@amlogic.com>2020-06-29 09:52:25 (GMT)
commit87e53d07cebb868c4973843d0a374ec94d990e4f (patch)
treeedd2c95b0ba7fed22aa68f0dcd7cfab36eaf3363
parentff87bfb40c0c50fcc37a1c9932c3a09fac609ce1 (diff)
downloadmedia_modules-87e53d07cebb868c4973843d0a374ec94d990e4f.zip
media_modules-87e53d07cebb868c4973843d0a374ec94d990e4f.tar.gz
media_modules-87e53d07cebb868c4973843d0a374ec94d990e4f.tar.bz2
v4l: porting v4l codec from branch amlogic-4.9-dev. [1/1]
PD#SWPL-24949 Problem: v4l2 need support for kernel 5.4 Solution: porting v4l codec from branch amlogic-4.9-dev. commit base: 5f8edcbf Verify: u212 Change-Id: Ia8bf3087e85cd92ae1fb7ee1ecc647b369313a19 Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--[-rwxr-xr-x]Media.mk0
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c69
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h7
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c463
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h2
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c18
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_pm.c206
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_pm.h34
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h187
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.h5
-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.c152
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c135
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c165
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c170
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c264
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c126
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.c2
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h21
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c233
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c249
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c3
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c182
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c238
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c7
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.h3
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_input.c10
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_input.h3
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c82
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h3
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c176
35 files changed, 2202 insertions, 1695 deletions
diff --git a/Media.mk b/Media.mk
index 58db63b..58db63b 100755..100644
--- a/Media.mk
+++ b/Media.mk
diff --git a/drivers/Makefile b/drivers/Makefile
index 1af0482..b3ad95f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -2,4 +2,4 @@ obj-y += common/
obj-y += frame_provider/
obj-y += frame_sink/
obj-y += stream_input/
-#obj-y += amvdec_ports/
+obj-$(CONFIG_AMLOGIC_MEDIA_V4L_DEC) += amvdec_ports/
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
index 7bb8eea..a166c9c 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -52,8 +52,6 @@
#define PTS_OUTSIDE (1)
#define SYNC_OUTSIDE (2)
-#define USE_V4L_PORTS (0x80)
-#define SCATTER_MEM (0x100)
//#define DATA_DEBUG
@@ -114,9 +112,8 @@ extern bool aml_set_vfm_enable, aml_set_vdec_type_enable;
static void set_default_params(struct aml_vdec_adapt *vdec)
{
- ulong sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS);
+ ulong sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE);
- sync_mode |= vdec->ctx->scatter_mem_enable ? SCATTER_MEM : 0;
vdec->dec_prop.param = (void *)sync_mode;
vdec->dec_prop.format = vdec->format;
vdec->dec_prop.width = 1920;
@@ -465,7 +462,7 @@ static void set_vdec_properity(struct vdec_s *vdec,
{
vdec->sys_info = &ada_ctx->dec_prop;
vdec->port = &ada_ctx->port;
- vdec->format = ada_ctx->video_type;
+ vdec->format = ada_ctx->format;
vdec->sys_info_store = ada_ctx->dec_prop;
vdec->vf_receiver_name = ada_ctx->recv_name;
@@ -475,33 +472,25 @@ static void set_vdec_properity(struct vdec_s *vdec,
/* set video format, sys info and vfm map.*/
vdec->port->vformat = vdec->format;
vdec->port->type |= PORT_TYPE_VIDEO;
- vdec->port_flag |= PORT_FLAG_VFORMAT;
+ vdec->port_flag |= (vdec->port->flag | PORT_FLAG_VFORMAT);
if (vdec->slave) {
vdec->slave->format = ada_ctx->dec_prop.format;
vdec->slave->port_flag |= PORT_FLAG_VFORMAT;
}
- if (vdec->port->type & PORT_FLAG_DRM) {
- vdec->type = VDEC_TYPE_STREAM_PARSER;
- vdec->port->type |= PORT_TYPE_ES;
- vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO;
- } else {
- vdec->type = VDEC_TYPE_FRAME_BLOCK;
- vdec->port->type |= PORT_TYPE_FRAME;
- vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_OSD;
- }
+ vdec->type = VDEC_TYPE_FRAME_BLOCK;
+ vdec->port->type |= PORT_TYPE_FRAME;
+ vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_OSD;
if (aml_set_vdec_type_enable) {
if (aml_set_vdec_type == VDEC_TYPE_STREAM_PARSER) {
vdec->type = VDEC_TYPE_STREAM_PARSER;
vdec->port->type &= ~PORT_TYPE_FRAME;
vdec->port->type |= PORT_TYPE_ES;
- ada_ctx->ctx->is_stream_mode = true;
} else if (aml_set_vdec_type == VDEC_TYPE_FRAME_BLOCK) {
vdec->type = VDEC_TYPE_FRAME_BLOCK;
vdec->port->type &= ~PORT_TYPE_ES;
vdec->port->type |= PORT_TYPE_FRAME;
- ada_ctx->ctx->is_stream_mode = false;
}
}
@@ -700,6 +689,30 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
return ret;
}
+int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
+ ulong addr, u32 count, u64 timestamp, u32 handle)
+{
+ int ret = -1;
+ struct vdec_s *vdec = ada_ctx->vdec;
+
+ /* set timestamp */
+ vdec_set_timestamp(vdec, timestamp);
+
+ ret = vdec_write_vframe_with_dma(vdec, addr, count, handle);
+
+ if (slow_input) {
+ v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+ "slow_input: frame codec write size %d\n", ret);
+ msleep(30);
+ }
+
+ v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT,
+ "write frames, vbuf: %lx, size: %u, ret: %d\n",
+ addr, count, ret);
+
+ return ret;
+}
+
void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = ada_ctx->vdec;
@@ -714,12 +727,21 @@ int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *mode)
int ret = 0;
if (vdec) {
- vdec_set_eos(vdec, false);
-
+ if (!ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed)
+ vdec_set_eos(vdec, false);
if (*mode == V4L_RESET_MODE_NORMAL &&
- vdec->input.have_frame_num == 0)
+ vdec->input.have_frame_num == 0) {
+ v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+ "no input reset mode: %d\n", *mode);
*mode = V4L_RESET_MODE_LIGHT;
-
+ }
+ if (ada_ctx->ctx->param_sets_from_ucode &&
+ *mode == V4L_RESET_MODE_NORMAL &&
+ ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed == true) {
+ v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+ "resolution_changed reset mode: %d\n", *mode);
+ *mode = V4L_RESET_MODE_LIGHT;
+ }
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
"reset mode: %d\n", *mode);
@@ -764,3 +786,8 @@ void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len)
memcpy(vdec->config, data, vdec->config_len);
}
+u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor)
+{
+ return vdec_input_get_freed_handle(adaptor->vdec);
+}
+
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
index 1f8afdd..c96d0fb 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -27,6 +27,7 @@
struct aml_vdec_adapt {
enum vformat_e format;
+ enum VIDEO_DEC_TYPE dec_type;
void *vsi;
int32_t failure;
uint32_t inst_addr;
@@ -39,7 +40,6 @@ struct aml_vdec_adapt {
struct stream_port_s port;
struct dec_sysinfo dec_prop;
struct v4l2_config_parm config;
- int video_type;
char *recv_name;
int vfm_path;
};
@@ -54,6 +54,9 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count, u64 timestamp);
+int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
+ ulong addr, u32 count, u64 timestamp, u32 handle);
+
bool vdec_input_full(struct aml_vdec_adapt *ada_ctx);
void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx);
@@ -66,5 +69,7 @@ bool is_input_ready(struct aml_vdec_adapt *ada_ctx);
int vdec_frame_number(struct aml_vdec_adapt *ada_ctx);
+u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor);
+
#endif /* VDEC_ADAPT_H */
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index 880f3a5..2ffab91 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -29,6 +29,8 @@
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/crc32.h>
+#include <linux/sched.h>
+#include <uapi/linux/sched/types.h>
#include "aml_vcodec_adapt.h"
#include <linux/spinlock.h>
@@ -48,7 +50,7 @@
#define DFT_CFG_HEIGHT AML_VDEC_MIN_H
#define V4L2_CID_USER_AMLOGIC_BASE (V4L2_CID_USER_BASE + 0x1100)
-#define AML_V4L2_SET_DECMODE (V4L2_CID_USER_AMLOGIC_BASE + 0)
+#define AML_V4L2_SET_DRMMODE (V4L2_CID_USER_AMLOGIC_BASE + 0)
#define WORK_ITEMS_MAX (32)
@@ -121,38 +123,58 @@ static struct aml_video_fmt aml_video_formats[] = {
static const struct aml_codec_framesizes aml_vdec_framesizes[] = {
{
.fourcc = V4L2_PIX_FMT_H264,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_HEVC,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_VP9,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_MPEG1,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_MPEG2,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_MPEG4,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
{
.fourcc = V4L2_PIX_FMT_MJPEG,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 8,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 8 },
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV21M,
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+ },
+ {
+ .fourcc = V4L2_PIX_FMT_NV12M,
+ .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+ AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
};
@@ -206,7 +228,9 @@ void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes)
{
struct v4l2_event event = {0};
- if (ctx->receive_cmd_stop) {
+ if (ctx->receive_cmd_stop &&
+ changes != V4L2_EVENT_SRC_CH_RESOLUTION &&
+ changes != V4L2_EVENT_SEND_EOS) {
ctx->state = AML_STATE_ABORT;
ATRACE_COUNTER("v4l2_state", ctx->state);
changes = V4L2_EVENT_REQUEST_EXIT;
@@ -222,6 +246,9 @@ void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes)
event.type = V4L2_EVENT_SOURCE_CHANGE;
event.u.src_change.changes = changes;
break;
+ case V4L2_EVENT_SEND_EOS:
+ event.type = V4L2_EVENT_EOS;
+ break;
default:
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"unsupport dispatch event %x\n", changes);
@@ -365,28 +392,34 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
return -1;
}
- dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ //fixme
+ /*dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
if (!dst_buf) {
aml_vcodec_ctx_unlock(ctx, flags);
return -1;
+ }*/
+
+ dst_vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ if (!dst_vb2_v4l2) {
+ aml_vcodec_ctx_unlock(ctx, flags);
+ return -1;
}
+ dst_buf = (struct vb2_buffer *)dst_vb2_v4l2;
+
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
"vbuf idx: %d, state: %d, ready: %d\n",
dst_buf->index, dst_buf->state,
v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx));
- dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+ //fixme
+ //dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb);
- if (ctx->scatter_mem_enable) {
- pfb = &dst_buf_info->frame_buffer;
- pfb->mem_type = VDEC_SCATTER_MEMORY_TYPE;
- pfb->status = FB_ST_NORMAL;
- } else if (dst_buf->num_planes == 1) {
+ if (dst_buf->num_planes == 1) {
pfb = &dst_buf_info->frame_buffer;
pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
- pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
+ pfb->m.mem[0].addr = pfb->m.mem[0].dma_addr;
pfb->m.mem[0].size = ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz;
pfb->m.mem[0].offset = ctx->picinfo.y_len_sz;
pfb->num_planes = dst_buf->num_planes;
@@ -398,12 +431,12 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
} else if (dst_buf->num_planes == 2) {
pfb = &dst_buf_info->frame_buffer;
pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
- pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
+ pfb->m.mem[0].addr = pfb->m.mem[0].dma_addr;
pfb->m.mem[0].size = ctx->picinfo.y_len_sz;
pfb->m.mem[0].offset = 0;
pfb->m.mem[1].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
- pfb->m.mem[1].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[1].dma_addr);
+ pfb->m.mem[1].addr = pfb->m.mem[1].dma_addr;
pfb->m.mem[1].size = ctx->picinfo.c_len_sz;
pfb->m.mem[1].offset = ctx->picinfo.c_len_sz >> 1;
pfb->num_planes = dst_buf->num_planes;
@@ -416,17 +449,17 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
} else {
pfb = &dst_buf_info->frame_buffer;
pfb->m.mem[0].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
- pfb->m.mem[0].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
+ pfb->m.mem[0].addr = pfb->m.mem[0].dma_addr;
pfb->m.mem[0].size = ctx->picinfo.y_len_sz;
pfb->m.mem[0].offset = 0;
pfb->m.mem[1].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
- pfb->m.mem[1].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[2].dma_addr);
+ pfb->m.mem[1].addr = pfb->m.mem[1].dma_addr;
pfb->m.mem[1].size = ctx->picinfo.c_len_sz >> 1;
pfb->m.mem[1].offset = 0;
pfb->m.mem[2].dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 2);
- pfb->m.mem[2].addr = dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[3].dma_addr);
+ pfb->m.mem[2].addr = pfb->m.mem[2].dma_addr;
pfb->m.mem[2].size = ctx->picinfo.c_len_sz >> 1;
pfb->m.mem[2].offset = 0;
pfb->num_planes = dst_buf->num_planes;
@@ -530,7 +563,6 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
}
if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
- dstbuf->lastframe = true;
dstbuf->vb.flags = V4L2_BUF_FLAG_LAST;
if (dstbuf->frame_buffer.num_planes == 1) {
vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0);
@@ -551,6 +583,25 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
dstbuf->vb.vb2_buf.index,
dstbuf->vb.vb2_buf.state);
+ if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
+ if (ctx->q_data[AML_Q_DATA_SRC].resolution_changed) {
+ /* make the run to stanby until new buffs to enque. */
+ ctx->v4l_codec_dpb_ready = false;
+ ctx->reset_flag = V4L_RESET_MODE_LIGHT;
+
+ /*
+ * After all buffers containing decoded frames from
+ * before the resolution change point ready to be
+ * dequeued on the CAPTURE queue, the driver sends a
+ * V4L2_EVENT_SOURCE_CHANGE event for source change
+ * type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper
+ * layer will get new information from cts->picinfo.
+ */
+ aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
+ } else
+ aml_vdec_dispatch_event(ctx, V4L2_EVENT_SEND_EOS);
+ }
+
if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
/* binding vframe handle. */
vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
@@ -572,24 +623,6 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
}
mutex_unlock(&ctx->state_lock);
- if (dstbuf->lastframe &&
- ctx->q_data[AML_Q_DATA_SRC].resolution_changed) {
-
- /* make the run to stanby until new buffs to enque. */
- ctx->v4l_codec_dpb_ready = false;
- ctx->reset_flag = V4L_RESET_MODE_LIGHT;
-
- /*
- * After all buffers containing decoded frames from
- * before the resolution change point ready to be
- * dequeued on the CAPTURE queue, the driver sends a
- * V4L2_EVENT_SOURCE_CHANGE event for source change
- * type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper
- * layer will get new information from cts->picinfo.
- */
- aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
- }
-
ctx->decoded_frame_cnt++;
}
@@ -648,8 +681,6 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
if (ctx->state == AML_STATE_PROBE) {
ctx->state = AML_STATE_READY;
ATRACE_COUNTER("v4l2_state", ctx->state);
- ctx->v4l_codec_ready = true;
- wake_up_interruptible(&ctx->wq);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_READY)\n");
}
@@ -706,6 +737,30 @@ static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx)
}
}
+static void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx)
+{
+ struct vb2_v4l2_buffer *vb;
+ struct aml_video_dec_buf *buf;
+ struct vb2_queue *q;
+ u32 handle;
+
+ q = v4l2_m2m_get_vq(ctx->m2m_ctx,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+ while ((handle = aml_recycle_buffer(ctx->ada_ctx))) {
+ int index = handle & 0xf;
+
+ vb = to_vb2_v4l2_buffer(q->bufs[index]);
+ buf = container_of(vb, struct aml_video_dec_buf, vb);
+ v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
+ VB2_BUF_STATE_DONE);
+
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+ "recycle buff idx: %d, vbuf: %lx\n", index,
+ (ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0));
+ }
+}
+
static void aml_vdec_worker(struct work_struct *work)
{
struct aml_vcodec_ctx *ctx =
@@ -730,18 +785,29 @@ static void aml_vdec_worker(struct work_struct *work)
goto out;
}
- src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ //fixme
+ /*src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
if (src_buf == NULL) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"src_buf empty.\n");
goto out;
+ }*/
+
+ src_vb2_v4l2 = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ if (src_vb2_v4l2 == NULL) {
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+ "src_buf empty.\n");
+ goto out;
}
+ src_buf = (struct vb2_buffer *)src_vb2_v4l2;
+
/*this case for google, but some frames are droped on ffmpeg, so disabled temp.*/
if (0 && !is_enough_work_items(ctx))
goto out;
- src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
+ //fixme
+ //src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
src_buf_info = container_of(src_vb2_v4l2, struct aml_video_dec_buf, vb);
if (src_buf_info->lastframe) {
@@ -767,7 +833,7 @@ static void aml_vdec_worker(struct work_struct *work)
}
mutex_unlock(&ctx->state_lock);
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
/* sets eos data for vdec input. */
@@ -776,11 +842,13 @@ static void aml_vdec_worker(struct work_struct *work)
goto out;
}
- buf.vaddr = vb2_plane_vaddr(src_buf, 0);
- buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ buf.index = src_buf->index;
+ buf.vaddr = vb2_plane_vaddr(src_buf, 0);
+ buf.addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ buf.size = src_buf->planes[0].bytesused;
+ buf.model = src_buf->memory;
- buf.size = src_buf->planes[0].bytesused;
- if (!buf.vaddr) {
+ if (!buf.vaddr && !buf.addr) {
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"id=%d src_addr is NULL.\n", src_buf->index);
@@ -803,12 +871,21 @@ static void aml_vdec_worker(struct work_struct *work)
* we only return src buffer with VB2_BUF_STATE_DONE
* when decode success without resolution change.
*/
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+ if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)
+ aml_recycle_dma_buffers(ctx);
+ else
+ v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
} else if (ret && ret != -EAGAIN) {
src_buf_info->error = (ret == -EIO ? true : false);
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+ if (ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF)
+ aml_recycle_dma_buffers(ctx);
+ else
+ v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
+
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"error processing src data. %d.\n", ret);
} else if (res_chg) {
@@ -833,7 +910,9 @@ static void aml_vdec_worker(struct work_struct *work)
mutex_unlock(&ctx->state_lock);
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
- v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+ v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ }
aml_vdec_flush_decoder(ctx);
@@ -886,18 +965,22 @@ void wait_vcodec_ending(struct aml_vcodec_ctx *ctx)
{
struct aml_vcodec_dev *dev = ctx->dev;
- /* pause inject output data to vdec. */
- v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ /* disable queue output item to worker. */
+ ctx->output_thread_ready = false;
- /* flush worker. */
+ /* flush output buffer worker. */
flush_workqueue(dev->decode_workqueue);
- ctx->v4l_codec_ready = false;
- ctx->v4l_codec_dpb_ready = false;
-
- /* stop decoder. */
+ /* clean output cache and decoder status . */
if (ctx->state > AML_STATE_INIT)
aml_vdec_reset(ctx);
+
+ /* pause the job and clean trans status. */
+ while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+ v4l2_m2m_job_pause(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
+ }
+
+ ctx->v4l_codec_dpb_ready = false;
}
void try_to_capture(struct aml_vcodec_ctx *ctx)
@@ -954,6 +1037,7 @@ void aml_thread_notify(struct aml_vcodec_ctx *ctx,
{
struct aml_vdec_thread *thread = NULL;
+ mutex_lock(&ctx->lock);
list_for_each_entry(thread, &ctx->vdec_thread_list, node) {
if (thread->task == NULL)
continue;
@@ -961,6 +1045,7 @@ void aml_thread_notify(struct aml_vcodec_ctx *ctx,
if (thread->type == type)
up(&thread->sem);
}
+ mutex_unlock(&ctx->lock);
}
EXPORT_SYMBOL_GPL(aml_thread_notify);
@@ -1006,7 +1091,10 @@ void aml_thread_stop(struct aml_vcodec_ctx *ctx)
while (!list_empty(&ctx->vdec_thread_list)) {
thread = list_entry(ctx->vdec_thread_list.next,
struct aml_vdec_thread, node);
+ mutex_lock(&ctx->lock);
list_del(&thread->node);
+ mutex_unlock(&ctx->lock);
+
thread->stop = true;
up(&thread->sem);
kthread_stop(thread->task);
@@ -1121,7 +1209,6 @@ static int vidioc_decoder_streamon(struct file *file, void *priv,
(ctx->reset_flag == V4L_RESET_MODE_LIGHT)) {
ctx->state = AML_STATE_RESET;
ATRACE_COUNTER("v4l2_state", ctx->state);
- ctx->v4l_codec_ready = false;
ctx->v4l_codec_dpb_ready = false;
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
@@ -1171,7 +1258,8 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv,
vb2_queue_release(q);
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
- "%s, type: %d\n", __func__, q->type);
+ "%s, type: %d, count: %d\n",
+ __func__, q->type, rb->count);
if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
/* driver needs match v4l buffer number with dpb_size */
@@ -1179,7 +1267,13 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv,
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"reqbufs (st:%d) %d -> %d\n",
ctx->state, rb->count, ctx->dpb_size);
- rb->count = ctx->dpb_size;
+ //rb->count = ctx->dpb_size;
+ }
+ } else {
+ if (rb->memory == VB2_MEMORY_DMABUF) {
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+ "%s, output_dma_mode set", __func__);
+ ctx->output_dma_mode = true;
}
}
@@ -1225,6 +1319,7 @@ void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx)
void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx)
{
struct aml_q_data *q_data;
+ u32 width, height;
ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
ctx->fh.m2m_ctx = ctx->m2m_ctx;
@@ -1254,14 +1349,18 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx)
q_data->coded_height = DFT_CFG_HEIGHT;
q_data->fmt = &aml_video_formats[CAP_FMT_IDX];
q_data->field = V4L2_FIELD_NONE;
+ width = q_data->coded_width;
+ height = q_data->coded_height;
- v4l_bound_align_image(&q_data->coded_width,
+ v4l_bound_align_image(&width,
AML_VDEC_MIN_W,
AML_VDEC_MAX_W, 4,
- &q_data->coded_height,
+ &height,
AML_VDEC_MIN_H,
AML_VDEC_MAX_H, 5, 6);
+ q_data->coded_width = width;
+ q_data->coded_height = height;
q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
q_data->bytesperline[0] = q_data->coded_width;
q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
@@ -1324,7 +1423,7 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
ATRACE_COUNTER("v4l2_dqin_eagain", 0);
else
ATRACE_COUNTER("v4l2_dqin_ok", 0);
- } else if (!V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ } else {
if (ret == -EAGAIN)
ATRACE_COUNTER("v4l2_dqout_eagain", 0);
}
@@ -1335,7 +1434,9 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
struct aml_video_dec_buf *aml_buf = NULL;
struct file *file = NULL;
- mutex_lock(&ctx->lock);
+ if (ctx->is_drm_mode && ctx->output_dma_mode)
+ aml_recycle_dma_buffers(ctx);
+
vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
vb2_v4l2 = to_vb2_v4l2_buffer(vq->bufs[buf->index]);
aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
@@ -1354,7 +1455,6 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
(ulong) v4l_get_vf_handle(vb2_v4l2->private));
}
fput(file);
- mutex_unlock(&ctx->lock);
}
return ret;
@@ -1406,6 +1506,7 @@ static int vidioc_vdec_event_unsubscribe(struct v4l2_fh *fh,
static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt)
{
struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+ u32 width, height;
int i;
pix_fmt_mp->field = V4L2_FIELD_NONE;
@@ -1431,13 +1532,19 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt)
*/
tmp_w = pix_fmt_mp->width;
tmp_h = pix_fmt_mp->height;
- v4l_bound_align_image(&pix_fmt_mp->width,
+ width = pix_fmt_mp->width;
+ height = pix_fmt_mp->height;
+
+ v4l_bound_align_image(&width,
AML_VDEC_MIN_W,
AML_VDEC_MAX_W, 6,
- &pix_fmt_mp->height,
+ &height,
AML_VDEC_MIN_H,
AML_VDEC_MAX_H, 6, 9);
+ pix_fmt_mp->width = width;
+ pix_fmt_mp->height = height;
+
if (pix_fmt_mp->width < tmp_w &&
(pix_fmt_mp->width + 64) <= AML_VDEC_MAX_W)
pix_fmt_mp->width += 64;
@@ -1586,6 +1693,40 @@ static int vidioc_vdec_s_selection(struct file *file, void *priv,
return 0;
}
+static void copy_v4l2_format_dimention(struct v4l2_pix_format_mplane *pix_mp,
+ struct aml_q_data *q_data, u32 type)
+{
+ if (!pix_mp || !q_data)
+ return;
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ pix_mp->width = q_data->visible_width;
+ pix_mp->height = q_data->visible_height;
+ } else {
+ /*
+ * Width and height are set to the dimensions
+ * of the movie, the buffer is bigger and
+ * further processing stages should crop to this
+ * rectangle.
+ */
+ pix_mp->width = q_data->coded_width;
+ pix_mp->height = q_data->coded_height;
+ }
+
+ /*
+ * Set pixelformat to the format in which mt vcodec
+ * outputs the decoded frame
+ */
+ pix_mp->num_planes = q_data->fmt->num_planes;
+ pix_mp->pixelformat = q_data->fmt->fourcc;
+ pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+ pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+ if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+ pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+ }
+}
+
static int vidioc_vdec_s_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -1633,6 +1774,8 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
q_data->fmt = fmt;
vidioc_try_fmt(f, q_data->fmt);
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (ctx->is_drm_mode)
+ pix_mp->plane_fmt[0].sizeimage = 1;
q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
q_data->coded_width = pix_mp->width;
q_data->coded_height = pix_mp->height;
@@ -1664,6 +1807,12 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
mutex_unlock(&ctx->state_lock);
}
+ if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
+ ctx->cap_pix_fmt = pix_mp->pixelformat;
+ if (ctx->state >= AML_STATE_PROBE)
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
+ }
+
return 0;
}
@@ -1673,7 +1822,8 @@ static int vidioc_enum_framesizes(struct file *file, void *priv,
int i = 0;
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, idx: %d, pix fmt: %x\n",
+ __func__, fsize->index, fsize->pixel_format);
if (fsize->index != 0)
return -EINVAL;
@@ -1791,25 +1941,7 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
q_data->bytesperline[0] = ctx->picinfo.coded_width;
q_data->bytesperline[1] = ctx->picinfo.coded_width;
- /*
- * Width and height are set to the dimensions
- * of the movie, the buffer is bigger and
- * further processing stages should crop to this
- * rectangle.
- */
- pix_mp->width = q_data->coded_width;
- pix_mp->height = q_data->coded_height;
-
- /*
- * Set pixelformat to the format in which mt vcodec
- * outputs the decoded frame
- */
- pix_mp->num_planes = q_data->fmt->num_planes;
- pix_mp->pixelformat = q_data->fmt->fourcc;
- pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
- pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
- pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
- pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
/*
* This is run on OUTPUT
@@ -1817,21 +1949,9 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv,
* so width and height have no meaning.
* Assign value here to pass v4l2-compliance test
*/
- pix_mp->width = q_data->visible_width;
- pix_mp->height = q_data->visible_height;
- pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
- pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
- pix_mp->pixelformat = q_data->fmt->fourcc;
- pix_mp->num_planes = q_data->fmt->num_planes;
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
} else {
- pix_mp->width = q_data->coded_width;
- pix_mp->height = q_data->coded_height;
- pix_mp->num_planes = q_data->fmt->num_planes;
- pix_mp->pixelformat = q_data->fmt->fourcc;
- pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
- pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
- pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
- pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
"type=%d state=%d Format information could not be read, not ready yet!\n",
@@ -1864,8 +1984,13 @@ static int vidioc_vdec_create_bufs(struct file *file, void *priv,
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+ "%s, id: %d\n", __func__, a->id);
+
if (a->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE)
- a->value = 20;
+ a->value = 4;
+ else if (a->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT)
+ a->value = 8;
return 0;
}*/
@@ -1904,6 +2029,8 @@ static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
for (i = 0; i < *nplanes; i++) {
sizes[i] = q_data->sizeimage[i];
+ if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->output_dma_mode)
+ sizes[i] = 0;
//alloc_devs[i] = &ctx->dev->plat_dev->dev;
alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm
}
@@ -1926,6 +2053,10 @@ static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
"%s, type: %d, idx: %d\n",
__func__, vb->vb2_queue->type, vb->index);
+ if (vb->memory == VB2_MEMORY_DMABUF
+ && V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+ return 0;
+
q_data = aml_vdec_get_q_data(ctx, vb->vb2_queue->type);
for (i = 0; i < q_data->fmt->num_planes; i++) {
@@ -2015,15 +2146,31 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
return;
}
- src_mem.vaddr = vb2_plane_vaddr(vb, 0);
- src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
- src_mem.size = vb->planes[0].bytesused;
+ src_mem.index = vb->index;
+ src_mem.vaddr = vb2_plane_vaddr(vb, 0);
+ src_mem.addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ src_mem.size = vb->planes[0].bytesused;
+ src_mem.model = vb->memory;
+
if (vdec_if_probe(ctx, &src_mem, NULL)) {
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE);
+
+ if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF)
+ aml_recycle_dma_buffers(ctx);
+ else
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE);
return;
}
+ /*
+ * If on model dmabuf must remove the buffer
+ * because this data has been consumed by hw.
+ */
+ if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) {
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ aml_recycle_dma_buffers(ctx);
+ }
+
if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"GET_PARAM_PICTURE_INFO err\n");
@@ -2107,17 +2254,19 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
/* codec_mm buffers count */
if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
- size = vb->planes[0].length;
- phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
- snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id);
- strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer));
- buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0';
+ if (vb->memory == VB2_MEMORY_MMAP) {
+ size = vb->planes[0].length;
+ phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id);
+ strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer));
+ buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0';
- buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
+ buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
+ phy_addr, size, vb->index);
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+ "IN alloc, addr: %x, size: %u, idx: %u\n",
phy_addr, size, vb->index);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "IN alloc, addr: %x, size: %u, idx: %u\n",
- phy_addr, size, vb->index);
+ }
} else {
snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id);
strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer));
@@ -2223,9 +2372,13 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
if (V4L2_TYPE_IS_OUTPUT(q->type)) {
while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+
+ if (ctx->is_drm_mode && q->memory == VB2_MEMORY_DMABUF)
+ aml_recycle_dma_buffers(ctx);
} else {
- /* stop decoder. */
- wait_vcodec_ending(ctx);
+ /* clean output cache and decoder status . */
+ if (ctx->state > AML_STATE_INIT)
+ aml_vdec_reset(ctx);
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
@@ -2241,6 +2394,7 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
q->bufs[i]->index, q->bufs[i]->state);*/
}
}
+
ctx->buf_used_count = 0;
ctx->cap_pool.in = 0;
ctx->cap_pool.out = 0;
@@ -2251,7 +2405,8 @@ static void m2mops_vdec_device_run(void *priv)
struct aml_vcodec_ctx *ctx = priv;
struct aml_vcodec_dev *dev = ctx->dev;
- queue_work(dev->decode_workqueue, &ctx->decode_work);
+ if (ctx->output_thread_ready)
+ queue_work(dev->decode_workqueue, &ctx->decode_work);
}
void vdec_device_vf_run(struct aml_vcodec_ctx *ctx)
@@ -2286,7 +2441,8 @@ static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
int ret = 0;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+ "%s, id: %d\n", __func__, ctrl->id);
switch (ctrl->id) {
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
@@ -2299,6 +2455,9 @@ static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
ret = -EINVAL;
}
break;
+ case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+ ctrl->val = 4;
+ break;
default:
ret = -EINVAL;
}
@@ -2311,9 +2470,10 @@ static int aml_vdec_try_s_v_ctrl(struct v4l2_ctrl *ctrl)
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
- if (ctrl->id == AML_V4L2_SET_DECMODE) {
+ if (ctrl->id == AML_V4L2_SET_DRMMODE) {
ctx->is_drm_mode = ctrl->val;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+ ctx->param_sets_from_ucode = true;
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
"set stream mode: %x\n", ctrl->val);
}
@@ -2326,8 +2486,8 @@ static const struct v4l2_ctrl_ops aml_vcodec_dec_ctrl_ops = {
};
static const struct v4l2_ctrl_config ctrl_st_mode = {
- .name = "stream mode",
- .id = AML_V4L2_SET_DECMODE,
+ .name = "drm mode",
+ .id = AML_V4L2_SET_DRMMODE,
.ops = &aml_vcodec_dec_ctrl_ops,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.flags = V4L2_CTRL_FLAG_WRITE_ONLY,
@@ -2342,11 +2502,21 @@ int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx)
int ret;
struct v4l2_ctrl *ctrl;
- v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1);
+ v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 3);
ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
&aml_vcodec_dec_ctrl_ops,
V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
- 0, 32, 1, 1);
+ 0, 32, 1, 2);
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ if (ctx->ctrl_hdl.error) {
+ ret = ctx->ctrl_hdl.error;
+ goto err;
+ }
+
+ ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+ &aml_vcodec_dec_ctrl_ops,
+ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
+ 0, 32, 1, 8);
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
if (ctx->ctrl_hdl.error) {
ret = ctx->ctrl_hdl.error;
@@ -2420,6 +2590,8 @@ static int vidioc_vdec_s_parm(struct file *file, void *fh,
return 0;
}
+//fixme
+/*
static void m2mops_vdec_lock(void *m2m_priv)
{
struct aml_vcodec_ctx *ctx = m2m_priv;
@@ -2433,13 +2605,13 @@ static void m2mops_vdec_unlock(void *m2m_priv)
mutex_unlock(&ctx->dev->dev_mutex);
}
-
+*/
const struct v4l2_m2m_ops aml_vdec_m2m_ops = {
.device_run = m2mops_vdec_device_run,
.job_ready = m2mops_vdec_job_ready,
.job_abort = m2mops_vdec_job_abort,
- .lock = m2mops_vdec_lock,
- .unlock = m2mops_vdec_unlock,
+ //.lock = m2mops_vdec_lock, //fixme
+ //.unlock = m2mops_vdec_unlock,
};
static const struct vb2_ops aml_vdec_vb2_ops = {
@@ -2459,7 +2631,7 @@ const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_streamoff = vidioc_decoder_streamoff,
.vidioc_reqbufs = vidioc_decoder_reqbufs,
.vidioc_querybuf = vidioc_vdec_querybuf,
- .vidioc_expbuf = vidioc_vdec_expbuf,//??
+ .vidioc_expbuf = vidioc_vdec_expbuf,
//.vidioc_g_ctrl = vidioc_vdec_g_ctrl,
.vidioc_qbuf = vidioc_vdec_qbuf,
@@ -2481,17 +2653,18 @@ const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_create_bufs = vidioc_vdec_create_bufs,
- .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane,
+ //fixme
+ //.vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane,
+ //.vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane,
.vidioc_enum_fmt_vid_cap = vidioc_vdec_enum_fmt_vid_cap_mplane,
- .vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane,
.vidioc_enum_fmt_vid_out = vidioc_vdec_enum_fmt_vid_out_mplane,
.vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_querycap = vidioc_vdec_querycap,
.vidioc_subscribe_event = vidioc_vdec_subscribe_evt,
.vidioc_unsubscribe_event = vidioc_vdec_event_unsubscribe,
- .vidioc_g_selection = vidioc_vdec_g_selection,
- .vidioc_s_selection = vidioc_vdec_s_selection,
+ .vidioc_g_selection = vidioc_vdec_g_selection,
+ .vidioc_s_selection = vidioc_vdec_s_selection,
.vidioc_decoder_cmd = vidioc_decoder_cmd,
.vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
index 68f878a..3406e9f 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -38,8 +38,6 @@
#define VDEC_GATHER_MEMORY_TYPE 0
#define VDEC_SCATTER_MEMORY_TYPE 1
-#define AML_V4L2_SET_DECMODE (V4L2_CID_USER_AMLOGIC_BASE + 0)
-
/**
* struct vdec_fb - decoder frame buffer
* @mem_type : gather or scatter memory.
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
index beb5c00..7758ca8 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -48,8 +48,8 @@
#define V4LVIDEO_IOCTL_SET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x04, struct v4l2_config_parm)
#define V4LVIDEO_IOCTL_GET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x05, struct v4l2_config_parm)
-bool scatter_mem_enable;
-bool param_sets_from_ucode;
+bool param_sets_from_ucode = 1;
+bool enable_drm_mode;
static int fops_vcodec_open(struct file *file)
{
@@ -82,12 +82,15 @@ static int fops_vcodec_open(struct file *file)
mutex_init(&ctx->state_lock);
mutex_init(&ctx->lock);
spin_lock_init(&ctx->slock);
- init_waitqueue_head(&ctx->wq);
init_completion(&ctx->comp);
- ctx->scatter_mem_enable = scatter_mem_enable ? 1 : 0;
ctx->param_sets_from_ucode = param_sets_from_ucode ? 1 : 0;
+ if (enable_drm_mode) {
+ ctx->is_drm_mode = true;
+ ctx->param_sets_from_ucode = true;
+ }
+
ctx->type = AML_INST_DECODER;
ret = aml_vcodec_dec_ctrls_setup(ctx);
if (ret) {
@@ -105,6 +108,7 @@ static int fops_vcodec_open(struct file *file)
}
src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ ctx->output_thread_ready = true;
ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
ctx->empty_flush_buf->lastframe = true;
aml_vcodec_dec_set_default_params(ctx);
@@ -612,12 +616,12 @@ bool dump_capture_frame;
EXPORT_SYMBOL(dump_capture_frame);
module_param(dump_capture_frame, bool, 0644);
-EXPORT_SYMBOL(scatter_mem_enable);
-module_param(scatter_mem_enable, bool, 0644);
-
EXPORT_SYMBOL(param_sets_from_ucode);
module_param(param_sets_from_ucode, bool, 0644);
+EXPORT_SYMBOL(enable_drm_mode);
+module_param(enable_drm_mode, bool, 0644);
+
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("AML video codec V4L2 decoder driver");
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_pm.c b/drivers/amvdec_ports/aml_vcodec_dec_pm.c
deleted file mode 100644
index c801e87..0000000
--- a/drivers/amvdec_ports/aml_vcodec_dec_pm.c
+++ b/dev/null
@@ -1,206 +0,0 @@
-/*
-* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but WITHOUT
-* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-* more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with this program; if not, write to the Free Software Foundation, Inc.,
-* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*
-* Description:
-*/
-#include <linux/clk.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/pm_runtime.h>
-
-#include "aml_vcodec_dec_pm.h"
-#include "aml_vcodec_util.h"
-//#include "aml_vpu.h"
-
-int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *amldev)
-{
- struct device_node *node;
- struct platform_device *pdev;
- struct aml_vcodec_pm *pm;
- int ret = 0;
-
- pdev = amldev->plat_dev;
- pm = &amldev->pm;
- pm->amldev = amldev;
- node = of_parse_phandle(pdev->dev.of_node, "larb", 0);
- if (!node) {
- aml_v4l2_err("of_parse_phandle larb fail!");
- return -1;
- }
-
- pdev = of_find_device_by_node(node);
- if (WARN_ON(!pdev)) {
- of_node_put(node);
- return -1;
- }
- pm->larbvdec = &pdev->dev;
- pdev = amldev->plat_dev;
- pm->dev = &pdev->dev;
-
- pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
- if (IS_ERR(pm->vcodecpll)) {
- aml_v4l2_err("devm_clk_get vcodecpll fail");
- ret = PTR_ERR(pm->vcodecpll);
- }
-
- pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
- if (IS_ERR(pm->univpll_d2)) {
- aml_v4l2_err("devm_clk_get univpll_d2 fail");
- ret = PTR_ERR(pm->univpll_d2);
- }
-
- pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
- if (IS_ERR(pm->clk_cci400_sel)) {
- aml_v4l2_err("devm_clk_get clk_cci400_sel fail");
- ret = PTR_ERR(pm->clk_cci400_sel);
- }
-
- pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
- if (IS_ERR(pm->vdec_sel)) {
- aml_v4l2_err("devm_clk_get vdec_sel fail");
- ret = PTR_ERR(pm->vdec_sel);
- }
-
- pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
- if (IS_ERR(pm->vdecpll)) {
- aml_v4l2_err("devm_clk_get vdecpll fail");
- ret = PTR_ERR(pm->vdecpll);
- }
-
- pm->vencpll = devm_clk_get(&pdev->dev, "vencpll");
- if (IS_ERR(pm->vencpll)) {
- aml_v4l2_err("devm_clk_get vencpll fail");
- ret = PTR_ERR(pm->vencpll);
- }
-
- pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
- if (IS_ERR(pm->venc_lt_sel)) {
- aml_v4l2_err("devm_clk_get venc_lt_sel fail");
- ret = PTR_ERR(pm->venc_lt_sel);
- }
-
- pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src");
- if (IS_ERR(pm->vdec_bus_clk_src)) {
- aml_v4l2_err("devm_clk_get vdec_bus_clk_src");
- ret = PTR_ERR(pm->vdec_bus_clk_src);
- }
-
- pm_runtime_enable(&pdev->dev);
-
- return ret;
-}
-
-void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev)
-{
- pm_runtime_disable(dev->pm.dev);
-}
-
-void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm)
-{
- int ret;
-
- ret = pm_runtime_get_sync(pm->dev);
- if (ret)
- aml_v4l2_err("pm_runtime_get_sync fail %d", ret);
-}
-
-void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm)
-{
- int ret;
-
- ret = pm_runtime_put_sync(pm->dev);
- if (ret)
- aml_v4l2_err("pm_runtime_put_sync fail %d", ret);
-}
-
-void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm)
-{
- int ret;
-
- ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000);
- if (ret)
- aml_v4l2_err("clk_set_rate vcodecpll fail %d", ret);
-
- ret = clk_set_rate(pm->vencpll, 800 * 1000000);
- if (ret)
- aml_v4l2_err("clk_set_rate vencpll fail %d", ret);
-
- ret = clk_prepare_enable(pm->vcodecpll);
- if (ret)
- aml_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret);
-
- ret = clk_prepare_enable(pm->vencpll);
- if (ret)
- aml_v4l2_err("clk_prepare_enable vencpll fail %d", ret);
-
- ret = clk_prepare_enable(pm->vdec_bus_clk_src);
- if (ret)
- aml_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d",
- ret);
-
- ret = clk_prepare_enable(pm->venc_lt_sel);
- if (ret)
- aml_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret);
-
- ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src);
- if (ret)
- aml_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d",
- ret);
-
- ret = clk_prepare_enable(pm->univpll_d2);
- if (ret)
- aml_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret);
-
- ret = clk_prepare_enable(pm->clk_cci400_sel);
- if (ret)
- aml_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret);
-
- ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
- if (ret)
- aml_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d",
- ret);
-
- ret = clk_prepare_enable(pm->vdecpll);
- if (ret)
- aml_v4l2_err("clk_prepare_enable vdecpll fail %d", ret);
-
- ret = clk_prepare_enable(pm->vdec_sel);
- if (ret)
- aml_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret);
-
- ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
- if (ret)
- aml_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret);
-
- //ret = aml_smi_larb_get(pm->larbvdec);
- if (ret)
- aml_v4l2_err("aml_smi_larb_get larbvdec fail %d", ret);
-
-}
-
-void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm)
-{
- //aml_smi_larb_put(pm->larbvdec);
- clk_disable_unprepare(pm->vdec_sel);
- clk_disable_unprepare(pm->vdecpll);
- clk_disable_unprepare(pm->univpll_d2);
- clk_disable_unprepare(pm->clk_cci400_sel);
- clk_disable_unprepare(pm->venc_lt_sel);
- clk_disable_unprepare(pm->vdec_bus_clk_src);
- clk_disable_unprepare(pm->vencpll);
- clk_disable_unprepare(pm->vcodecpll);
-}
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_pm.h b/drivers/amvdec_ports/aml_vcodec_dec_pm.h
deleted file mode 100644
index ccdf313..0000000
--- a/drivers/amvdec_ports/aml_vcodec_dec_pm.h
+++ b/dev/null
@@ -1,34 +0,0 @@
-/*
-* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but WITHOUT
-* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-* more details.
-*
-* You should have received a copy of the GNU General Public License along
-* with this program; if not, write to the Free Software Foundation, Inc.,
-* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*
-* Description:
-*/
-
-#ifndef _AML_VCODEC_DEC_PM_H_
-#define _AML_VCODEC_DEC_PM_H_
-
-#include "aml_vcodec_drv.h"
-
-int aml_vcodec_init_dec_pm(struct aml_vcodec_dev *dev);
-void aml_vcodec_release_dec_pm(struct aml_vcodec_dev *dev);
-
-void aml_vcodec_dec_pw_on(struct aml_vcodec_pm *pm);
-void aml_vcodec_dec_pw_off(struct aml_vcodec_pm *pm);
-void aml_vcodec_dec_clock_on(struct aml_vcodec_pm *pm);
-void aml_vcodec_dec_clock_off(struct aml_vcodec_pm *pm);
-
-#endif /* _AML_VCODEC_DEC_PM_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
index d3d8284..f28dc51 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -58,6 +58,9 @@
#define V4L2_EVENT_REQUEST_RESET (1 << 8)
#define V4L2_EVENT_REQUEST_EXIT (1 << 9)
+/* eos event */
+#define V4L2_EVENT_SEND_EOS (1 << 16)
+
/* v4l buffer pool */
#define V4L_CAP_BUFF_MAX (32)
#define V4L_CAP_BUFF_INVALID (0)
@@ -68,6 +71,14 @@
#define V4L_RESET_MODE_NORMAL (1 << 0) /* reset vdec_input and decoder. */
#define V4L_RESET_MODE_LIGHT (1 << 1) /* just only reset decoder. */
+/* m2m job queue's status */
+/* Instance is already queued on the job_queue */
+#define TRANS_QUEUED (1 << 0)
+/* Instance is currently running in hardware */
+#define TRANS_RUNNING (1 << 1)
+/* Instance is currently aborting */
+#define TRANS_ABORT (1 << 2)
+
/**
* enum aml_hw_reg_idx - AML hw register base index
*/
@@ -370,101 +381,93 @@ struct aml_vdec_thread {
/**
* struct aml_vcodec_ctx - Context (instance) private data.
*
- * @type: type of the instance - decoder or encoder
- * @dev: pointer to the aml_vcodec_dev of the device
- * @list: link to ctx_list of aml_vcodec_dev
- * @fh: struct v4l2_fh
- * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context
- * @q_data: store information of input and output queue
- * of the context
- * @id: index of the context that this structure describes
- * @state: state of the context
- * @param_change: indicate encode parameter type
- * @enc_params: encoding parameters
- * @dec_if: hooked decoder driver interface
- * @enc_if: hoooked encoder driver interface
- * @drv_handle: driver handle for specific decode/encode instance
- *
- * @picinfo: store picture info after header parsing
+ * @id: index of the context that this structure describes.
+ * @type: type of the instance - decoder or encoder.
+ * @dev: pointer to the aml_vcodec_dev of the device.
+ * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context.
+ * @ada_ctx: pointer to the aml_vdec_adapt of the context.
+ * @dec_if: hooked decoder driver interface.
+ * @drv_handle: driver handle for specific decode instance
+ * @fh: struct v4l2_fh.
+ * @ctrl_hdl: handler for v4l2 framework.
+ * @slock: protect v4l2 codec context.
+ * @empty_flush_buf: a fake size-0 capture buffer that indicates flush.
+ * @list: link to ctx_list of aml_vcodec_dev.
+ * @q_data: store information of input and output queue of the context.
+ * @queue: waitqueue that can be used to wait for this context to finish.
+ * @lock: protect the vdec thread.
+ * @state_lock: protect the codec status.
+ * @state: state of the context.
+ * @decode_work: decoder work be used to output buffer.
+ * @output_thread_ready: indicate the output thread ready.
+ * @cap_pool: capture buffers are remark in the pool.
+ * @vdec_thread_list: vdec thread be used to capture.
* @dpb_size: store dpb count after header parsing
- * @int_cond: variable used by the waitqueue
- * @int_type: type of the last interrupt
- * @queue: waitqueue that can be used to wait for this context to
- * finish
- * @irq_status: irq status
- *
- * @ctrl_hdl: handler for v4l2 framework
- * @decode_work: worker for the decoding
- * @encode_work: worker for the encoding
- * @last_decoded_picinfo: pic information get from latest decode
- * @empty_flush_buf: a fake size-0 capture buffer that indicates flush
- *
- * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
- * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
- * @quantization: enum v4l2_quantization, colorspace quantization
- * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
- * @lock: protect variables accessed by V4L2 threads and worker thread such as
- * aml_video_dec_buf.
+ * @param_change: indicate encode parameter type
+ * @param_sets_from_ucode: if true indicate ps from ucode.
+ * @v4l_codec_dpb_ready: queue buffer number greater than dpb.
+ * @comp: comp be used for sync picture information with decoder.
+ * @config: used to set or get parms for application.
+ * @picinfo: store picture info after header parsing.
+ * @last_decoded_picinfo: pic information get from latest decode.
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat.
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding.
+ * @quantization: enum v4l2_quantization, colorspace quantization.
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function.
+ * @cap_pix_fmt: the picture format used to switch nv21 or nv12.
+ * @has_receive_eos: if receive last frame of capture that be set.
+ * @is_drm_mode: decoding work on drm mode if that set.
+ * @is_stream_mode: vdec input used to stream mode, default frame mode.
+ * @is_stream_off: the value used to handle reset active.
+ * @receive_cmd_stop: if receive the cmd flush decoder.
+ * @reset_flag: reset mode includes lightly and normal mode.
+ * @decoded_frame_cnt: the capture buffer deque number to be count.
+ * @buf_used_count: means that decode allocate how many buffs from v4l.
*/
struct aml_vcodec_ctx {
- enum aml_instance_type type;
- struct aml_vcodec_dev *dev;
- struct list_head list;
-
- struct v4l2_fh fh;
- struct v4l2_m2m_ctx *m2m_ctx;
- struct aml_vdec_adapt *ada_ctx;
- struct aml_q_data q_data[2];
- int id;
- struct mutex state_lock;
- enum aml_instance_state state;
- enum aml_encode_param param_change;
- struct aml_enc_params enc_params;
-
- const struct vdec_common_if *dec_if;
- const struct venc_common_if *enc_if;
- unsigned long drv_handle;
-
- struct vdec_pic_info picinfo;
- int dpb_size;
-
- int int_cond;
- int int_type;
- wait_queue_head_t queue;
- unsigned int irq_status;
-
- struct v4l2_ctrl_handler ctrl_hdl;
- struct work_struct decode_work;
- struct work_struct encode_work;
- struct vdec_pic_info last_decoded_picinfo;
- struct aml_video_dec_buf *empty_flush_buf;
-
- enum v4l2_colorspace colorspace;
- enum v4l2_ycbcr_encoding ycbcr_enc;
- enum v4l2_quantization quantization;
- enum v4l2_xfer_func xfer_func;
-
- int decoded_frame_cnt;
- struct mutex lock;
- struct completion comp;
- bool has_receive_eos;
- struct list_head vdec_thread_list;
- bool is_drm_mode;
- bool is_stream_mode;
- int buf_used_count;
- bool receive_cmd_stop;
- bool scatter_mem_enable;
- bool param_sets_from_ucode;
- bool v4l_codec_ready;
- bool v4l_codec_dpb_ready;
- wait_queue_head_t wq;
- spinlock_t slock;
- struct v4l2_config_parm config;
- bool is_stream_off;
- int reset_flag;
- int stop_cmd;
- u32 display_count;
- struct v4l_buff_pool cap_pool;
+ int id;
+ enum aml_instance_type type;
+ struct aml_vcodec_dev *dev;
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct aml_vdec_adapt *ada_ctx;
+ const struct vdec_common_if *dec_if;
+ ulong drv_handle;
+ struct v4l2_fh fh;
+ struct v4l2_ctrl_handler ctrl_hdl;
+ spinlock_t slock;
+ struct aml_video_dec_buf *empty_flush_buf;
+ struct list_head list;
+
+ struct aml_q_data q_data[2];
+ wait_queue_head_t queue;
+ struct mutex lock, state_lock;
+ enum aml_instance_state state;
+ struct work_struct decode_work;
+ bool output_thread_ready;
+ struct v4l_buff_pool cap_pool;
+ struct list_head vdec_thread_list;
+
+ int dpb_size;
+ bool param_sets_from_ucode;
+ bool v4l_codec_dpb_ready;
+ struct completion comp;
+ struct v4l2_config_parm config;
+ struct vdec_pic_info picinfo;
+ struct vdec_pic_info last_decoded_picinfo;
+ enum v4l2_colorspace colorspace;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_quantization quantization;
+ enum v4l2_xfer_func xfer_func;
+ u32 cap_pix_fmt;
+
+ bool has_receive_eos;
+ bool is_drm_mode;
+ bool output_dma_mode;
+ bool is_stream_off;
+ bool receive_cmd_stop;
+ int reset_flag;
+ int decoded_frame_cnt;
+ int buf_used_count;
};
/**
diff --git a/drivers/amvdec_ports/aml_vcodec_util.h b/drivers/amvdec_ports/aml_vcodec_util.h
index da8d725..8e479a6 100644
--- a/drivers/amvdec_ports/aml_vcodec_util.h
+++ b/drivers/amvdec_ports/aml_vcodec_util.h
@@ -34,13 +34,18 @@ typedef unsigned char u8;
#define CODEC_MODE(a, b, c, d)\
(((u8)(a) << 24) | ((u8)(b) << 16) | ((u8)(c) << 8) | (u8)(d))
+#define BUFF_IDX(h, i)\
+ (((ulong)(h) << 8) | (u8)(i))
+
struct aml_vcodec_mem {
+ int index;
ulong addr;
u32 size;
void *vaddr;
u32 bytes_used;
u32 offset;
dma_addr_t dma_addr;
+ u32 model;
};
struct aml_vcodec_ctx;
diff --git a/drivers/amvdec_ports/decoder/h264_parse.c b/drivers/amvdec_ports/decoder/h264_parse.c
deleted file mode 100644
index 1c3b73d..0000000
--- a/drivers/amvdec_ports/decoder/h264_parse.c
+++ b/dev/null
@@ -1,389 +0,0 @@
-/*
- * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.c
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/kernel.h>
-#include "h264_parse.h"
-#include "h264_stream.h"
-
-static unsigned char h264_exp_golomb_bits[256] = {
- 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,
-};
-
-static unsigned char ZZ_SCAN[16] = {
- 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
-};
-
-static unsigned char ZZ_SCAN8[64] = {
- 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
- 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
- 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
- 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
-};
-
-unsigned int h264_u(struct h264_stream_t *s, unsigned int n)
-{
- //if (n % 8 == 0) {
- // return h264_stream_read_bytes(s, n / 8);
- //}
- return h264_stream_read_bits(s, n);
-}
-
-unsigned int h264_ue(struct h264_stream_t *s)
-{
- unsigned int bits, read;
- unsigned char coded;
-
- bits = 0;
- while (true) {
- if (h264_stream_bytes_remaining(s) < 1) {
- read = h264_stream_peek_bits(s, s->bit_pos) <<
- (8 - s->bit_pos);
- break;
- }
-
- read = h264_stream_peek_bits(s, 8);
- if (bits > 16)
- break;
-
- if (read)
- break;
-
- h264_stream_read_bits(s, 8);
- bits += 8;
- }
-
- coded = h264_exp_golomb_bits[read];
- h264_stream_read_bits(s, coded);
- bits += coded;
- return h264_stream_read_bits(s, bits + 1) - 1;
-}
-
-int h264_se(struct h264_stream_t *s)
-{
- unsigned int ret;
-
- ret = h264_ue(s);
- if (!(ret & 0x1)) {
- ret >>= 1;
- return (int)(-ret);
- }
-
- return (ret + 1) >> 1;
-}
-
-void h264_f(struct h264_stream_t *s, unsigned int n, unsigned int pattern)
-{
- unsigned int val = h264_u(s, n);
-
- if (val != pattern) {
- pr_err("fixed-pattern doesn't match. expected: %x actual: %x\n",
- pattern, (unsigned int)val);
- return;
- }
-}
-
-void h264_rbsp_trailing_bits(struct h264_stream_t *s)
-{
- h264_f(s, 1, 1);
- h264_f(s, s->bit_pos, 0);
-}
-
-// syntax for scaling list matrix values
-void Scaling_List(int *scalingList, int sizeOfScalingList,
- bool *UseDefaultScalingMatrix, struct h264_stream_t *s)
-{
- int j, scanj;
- int delta_scale, lastScale, nextScale;
-
- lastScale = 8;
- nextScale = 8;
-
- for (j = 0; j < sizeOfScalingList; j++) {
- scanj = (sizeOfScalingList == 16) ? ZZ_SCAN[j] : ZZ_SCAN8[j];
-
- if (nextScale != 0) {
- delta_scale = h264_ue(s);
- nextScale = (lastScale + delta_scale + 256) % 256;
- *UseDefaultScalingMatrix =
- (bool) (scanj == 0 && nextScale == 0);
- }
-
- scalingList[scanj] = (nextScale == 0) ? lastScale : nextScale;
- lastScale = scalingList[scanj];
- }
-}
-
-void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps)
-{
- unsigned int i, n_ScalingList;
-
- sps->profile_idc = h264_u(s, 8);
-
- if ((sps->profile_idc != BASELINE) &&
- (sps->profile_idc != MAIN) &&
- (sps->profile_idc != EXTENDED) &&
- (sps->profile_idc != FREXT_HP) &&
- (sps->profile_idc != FREXT_Hi10P) &&
- (sps->profile_idc != FREXT_Hi422) &&
- (sps->profile_idc != FREXT_Hi444) &&
- (sps->profile_idc != FREXT_CAVLC444)
- && (sps->profile_idc != MVC_HIGH)
- && (sps->profile_idc != STEREO_HIGH)) {
- pr_err("Invalid Profile IDC (%d) encountered.\n",
- sps->profile_idc);
- return;
- }
-
- sps->constrained_set0_flag = h264_u(s, 1);
- sps->constrained_set1_flag = h264_u(s, 1);
- sps->constrained_set2_flag = h264_u(s, 1);
- h264_u(s, 5); // reserved_zero_5bits
- sps->level_idc = h264_u(s, 8);
- sps->seq_parameter_set_id = h264_ue(s);
-
- // Fidelity Range Extensions stuff
- sps->chroma_format_idc = 1;
- sps->bit_depth_luma_minus8 = 0;
- sps->bit_depth_chroma_minus8 = 0;
- sps->lossless_qpprime_flag = 0;
- sps->separate_colour_plane_flag = 0;
-
- if ((sps->profile_idc == FREXT_HP) ||
- (sps->profile_idc == FREXT_Hi10P) ||
- (sps->profile_idc == FREXT_Hi422) ||
- (sps->profile_idc == FREXT_Hi444) ||
- (sps->profile_idc == FREXT_CAVLC444)) {
- sps->chroma_format_idc = h264_ue(s);
-
- if (sps->chroma_format_idc == YUV444)
- sps->separate_colour_plane_flag = h264_u(s, 1);
-
- sps->bit_depth_luma_minus8 = h264_ue(s);
- sps->bit_depth_chroma_minus8 = h264_ue(s);
- //checking;
- if ((sps->bit_depth_luma_minus8 + 8 > sizeof(unsigned short) * 8) ||
- (sps->bit_depth_chroma_minus8 + 8 > sizeof(unsigned short) * 8)) {
- pr_err("Source picture has higher bit depth than imgpel data type.\n");
- pr_err("Please recompile with larger data type for imgpel.\n");
- }
-
- sps->lossless_qpprime_flag = h264_u(s, 1);
- sps->seq_scaling_matrix_present_flag = h264_u(s, 1);
- if (sps->seq_scaling_matrix_present_flag) {
- n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;
- for (i = 0; i < n_ScalingList; i++) {
- sps->seq_scaling_list_present_flag[i] = h264_u(s, 1);
- if (sps->seq_scaling_list_present_flag[i]) {
- if (i < 6)
- Scaling_List(sps->ScalingList4x4[i], 16,
- &sps->UseDefaultScalingMatrix4x4Flag[i], s);
- else
- Scaling_List(sps->ScalingList8x8[i - 6],
- 64, &sps->UseDefaultScalingMatrix8x8Flag[i - 6], s);
- }
- }
- }
- }
-
- sps->log2_max_frame_num_minus4 = h264_ue(s);
- sps->pic_order_cnt_type = h264_ue(s);
- if (sps->pic_order_cnt_type == 0) {
- sps->log2_max_pic_order_cnt_lsb_minus4 = h264_ue(s);
- } else if (sps->pic_order_cnt_type == 1) {
- sps->delta_pic_order_always_zero_flag = h264_se(s);
- sps->offset_for_non_ref_pic = h264_se(s);
- sps->offset_for_top_to_bottom_field = h264_se(s);
- sps->num_ref_frames_in_poc_cycle = h264_se(s);
- for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i)
- sps->offset_for_ref_frame[i] = h264_se(s);
- }
-
- sps->num_ref_frames = h264_ue(s);
- sps->gaps_in_frame_num_value_allowed_flag = h264_u(s, 1);
- sps->pic_width_in_mbs_minus1 = h264_ue(s);
- sps->pic_height_in_map_units_minus1 = h264_ue(s);
- sps->frame_mbs_only_flag = h264_u(s, 1);
- if (!sps->frame_mbs_only_flag)
- sps->mb_adaptive_frame_field_flag = h264_u(s, 1);
-
- sps->direct_8x8_inference_flag = h264_u(s, 1);
- sps->frame_cropping_flag = h264_u(s, 1);
- if (sps->frame_cropping_flag) {
- sps->frame_crop_left_offset = h264_ue(s);
- sps->frame_crop_right_offset = h264_ue(s);
- sps->frame_crop_top_offset = h264_ue(s);
- sps->frame_crop_bottom_offset = h264_ue(s);
- }
-
- sps->vui_parameters_present_flag = h264_u(s, 1);
- //if (sps->vui_parameters_present_flag) {
- // sps->vui_parameters = h264_vui_parameters(s);
- //}
- h264_rbsp_trailing_bits(s);
-}
-
-void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps)
-{
- pps->pic_parameter_set_id = h264_ue(s);
- pps->seq_parameter_set_id = h264_ue(s);
- pps->entropy_coding_mode_flag = h264_u(s, 1);
- pps->pic_order_present_flag = h264_u(s, 1);
- pps->num_slice_groups_minus1 = h264_ue(s);
- if (pps->num_slice_groups_minus1 > 0) {
- pps->slice_group_map_type = h264_ue(s);
- if (pps->slice_group_map_type == 0) {
- pps->run_length_minus1 = h264_ue(s);
- } else if (pps->slice_group_map_type == 2) {
- pps->top_left = h264_ue(s);
- pps->bottom_right = h264_ue(s);
- } else if (pps->slice_group_map_type == 3 ||
- pps->slice_group_map_type == 4 ||
- pps->slice_group_map_type == 5) {
- pps->slice_group_change_direction_flag = h264_u(s, 1);
- pps->slice_group_change_rate_minus1 = h264_ue(s);
- } else if (pps->slice_group_map_type == 6) {
- pps->pic_size_in_map_units_minus1 = h264_ue(s);
- pps->slice_group_id = h264_ue(s);
- }
- }
- pps->num_ref_idx_l0_active_minus1 = h264_ue(s);
- pps->num_ref_idx_l1_active_minus1 = h264_ue(s);
- pps->weighted_pred_flag = h264_u(s, 1);
- pps->weighted_bipred_idc = h264_u(s, 2);
- pps->pic_init_qp_minus26 = h264_se(s);
- pps->pic_init_qs_minus26 = h264_se(s);
- pps->chroma_qp_index_offset = h264_se(s);
- pps->deblocking_filter_control_present_flag = h264_u(s, 1);
- pps->constrained_intra_pred_flag = h264_u(s, 1);
- pps->redundant_pic_cnt_present_flag = h264_u(s, 1);
- h264_rbsp_trailing_bits(s);
-}
-
-void h264_sps_info(struct h264_SPS_t *sps)
-{
- int i;
-
- pr_info("sequence_parameter_set {\n");
- pr_info(" profile_idc: %d\n", sps->profile_idc);
- pr_info(" constraint_set0_flag: %d\n", sps->constrained_set0_flag);
- pr_info(" constraint_set1_flag: %d\n", sps->constrained_set1_flag);
- pr_info(" constraint_set2_flag: %d\n", sps->constrained_set2_flag);
- pr_info(" level_idc: %d\n", sps->level_idc);
- pr_info(" seq_parameter_set_id: %d\n", sps->seq_parameter_set_id);
-
- pr_info(" log2_max_frame_num_minus4: %d\n",
- sps->log2_max_frame_num_minus4);
- pr_info(" pic_order_cnt_type: %d\n", sps->pic_order_cnt_type);
- if (sps->pic_order_cnt_type == 0) {
- pr_info(" log2_max_pic_order_cnt_lsb_minus4: %d\n",
- sps->log2_max_pic_order_cnt_lsb_minus4);
- } else if (sps->pic_order_cnt_type == 1) {
- pr_info(" delta_pic_order_always_zero_flag: %d\n",
- sps->delta_pic_order_always_zero_flag);
- pr_info(" offset_for_non_ref_pic: %d\n",
- sps->offset_for_non_ref_pic);
- pr_info(" offset_for_top_to_bottom_field: %d\n",
- sps->offset_for_top_to_bottom_field);
- pr_info(" num_ref_frames_in_pic_order_cnt_cycle: %d\n",
- sps->num_ref_frames_in_poc_cycle);
- for (i = 0; i < sps->num_ref_frames_in_poc_cycle; ++i) {
- pr_info(" offset_for_ref_frame[%d]: %d\n", i,
- sps->offset_for_ref_frame[i]);
- }
- }
- pr_info(" num_ref_frames: %d\n", sps->num_ref_frames);
- pr_info(" gaps_in_frame_num_value_allowed_flag: %d\n",
- sps->gaps_in_frame_num_value_allowed_flag);
- pr_info(" pic_width_in_mbs_minus1: %d\n",
- sps->pic_width_in_mbs_minus1);
- pr_info(" pic_height_in_map_units_minus1: %d\n",
- sps->pic_height_in_map_units_minus1);
- pr_info(" frame_mbs_only_flag: %d\n",
- sps->frame_mbs_only_flag);
- pr_info(" mb_adaptive_frame_field_flag: %d\n",
- sps->mb_adaptive_frame_field_flag);
- pr_info(" direct_8x8_inference_flag: %d\n",
- sps->direct_8x8_inference_flag);
- pr_info(" frame_cropping_flag: %d\n",
- sps->frame_cropping_flag);
- if (sps->frame_cropping_flag) {
- pr_info(" frame_crop_left_offset: %d\n",
- sps->frame_crop_left_offset);
- pr_info(" frame_crop_right_offset: %d\n",
- sps->frame_crop_right_offset);
- pr_info(" frame_crop_top_offset: %d\n",
- sps->frame_crop_top_offset);
- pr_info(" frame_crop_bottom_offset: %d\n",
- sps->frame_crop_bottom_offset);
- }
- pr_info(" vui_parameters_present_flag: %d\n",
- sps->vui_parameters_present_flag);
- //if (sps->vui_parameters_present_flag) {
- // h264_print_vui_parameters(sps->vui_parameters);
- //}
-
- pr_info(" }\n");
-}
-
-void h264_pps_info(struct h264_PPS_t *pps)
-{
- pr_info("pic_parameter_set {\n");
- pr_info(" pic_parameter_set_id: %d\n",
- pps->pic_parameter_set_id);
- pr_info(" seq_parameter_set_id: %d\n",
- pps->seq_parameter_set_id);
- pr_info(" entropy_coding_mode_flag: %d\n",
- pps->entropy_coding_mode_flag);
- pr_info(" pic_order_present_flag: %d\n",
- pps->pic_order_present_flag);
- pr_info(" num_slice_groups_minus1: %d\n",
- pps->num_slice_groups_minus1);
- // FIXME: Code for slice groups is missing here.
- pr_info(" num_ref_idx_l0_active_minus1: %d\n",
- pps->num_ref_idx_l0_active_minus1);
- pr_info(" num_ref_idx_l1_active_minus1: %d\n",
- pps->num_ref_idx_l1_active_minus1);
- pr_info(" weighted_pred_flag: %d\n", pps->weighted_pred_flag);
- pr_info(" weighted_bipred_idc: %d\n", pps->weighted_bipred_idc);
- pr_info(" pic_init_qp_minus26: %d\n", pps->pic_init_qp_minus26);
- pr_info(" pic_init_qs_minus26: %d\n", pps->pic_init_qs_minus26);
- pr_info(" chroma_qp_index_offset: %d\n",
- pps->chroma_qp_index_offset);
- pr_info(" deblocking_filter_control_present_flag: %d\n",
- pps->deblocking_filter_control_present_flag);
- pr_info(" constrained_intra_pred_flag: %d\n",
- pps->constrained_intra_pred_flag);
- pr_info(" redundant_pic_cnt_present_flag: %d\n",
- pps->redundant_pic_cnt_present_flag);
- pr_info(" }\n");
-}
-
diff --git a/drivers/amvdec_ports/decoder/h264_parse.h b/drivers/amvdec_ports/decoder/h264_parse.h
deleted file mode 100644
index e54e4d3..0000000
--- a/drivers/amvdec_ports/decoder/h264_parse.h
+++ b/dev/null
@@ -1,141 +0,0 @@
-/*
- * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_parse.h
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#ifndef _H264_PARSE_H
-#define _H264_PARSE_H
-
-#include "h264_stream.h"
-
-enum color_model {
- CM_UNKNOWN = -1,
- CM_YUV = 0,
- CM_RGB = 1,
- CM_XYZ = 2
-};
-
-enum color_format {
- CF_UNKNOWN = -1, //!< Unknown color format
- YUV400 = 0, //!< Monochrome
- YUV420 = 1, //!< 4:2:0
- YUV422 = 2, //!< 4:2:2
- YUV444 = 3 //!< 4:4:4
-};
-
-enum pixel_format {
- PF_UNKNOWN = -1, //!< Unknown color ordering
- UYVY = 0, //!< UYVY
- YUY2 = 1, //!< YUY2
- YUYV = 1, //!< YUYV
- YVYU = 2, //!< YVYU
- BGR = 3, //!< BGR
- V210 = 4 //!< Video Clarity 422 format (10 bits)
-};
-
-//AVC Profile IDC definitions
-enum profile_idc{
- NO_PROFILE = 0, //!< disable profile checking for experimental coding (enables FRExt, but disables MV)
- FREXT_CAVLC444 = 44, //!< YUV 4:4:4/14 "CAVLC 4:4:4"
- BASELINE = 66, //!< YUV 4:2:0/8 "Baseline"
- MAIN = 77, //!< YUV 4:2:0/8 "Main"
- EXTENDED = 88, //!< YUV 4:2:0/8 "Extended"
- FREXT_HP = 100, //!< YUV 4:2:0/8 "High"
- FREXT_Hi10P = 110, //!< YUV 4:2:0/10 "High 10"
- FREXT_Hi422 = 122, //!< YUV 4:2:2/10 "High 4:2:2"
- FREXT_Hi444 = 244, //!< YUV 4:4:4/14 "High 4:4:4"
- MVC_HIGH = 118, //!< YUV 4:2:0/8 "Multiview High"
- STEREO_HIGH = 128 //!< YUV 4:2:0/8 "Stereo High"
-};
-
-/* sequence parameter set */
-struct h264_SPS_t {
- bool vailid;
- unsigned int profile_idc;
- bool constrained_set0_flag;
- bool constrained_set1_flag;
- bool constrained_set2_flag;
- bool constrained_set3_flag;
- unsigned int level_idc;
- unsigned int seq_parameter_set_id;
- unsigned int chroma_format_idc;
- bool seq_scaling_matrix_present_flag;
- int seq_scaling_list_present_flag[12];
- int ScalingList4x4[6][16];
- int ScalingList8x8[6][64];
- bool UseDefaultScalingMatrix4x4Flag[6];
- bool UseDefaultScalingMatrix8x8Flag[6];
- unsigned int bit_depth_luma_minus8;
- unsigned int bit_depth_chroma_minus8;
- unsigned int log2_max_frame_num_minus4;
- unsigned int pic_order_cnt_type;
- unsigned int log2_max_pic_order_cnt_lsb_minus4;
- bool delta_pic_order_always_zero_flag;
- int offset_for_non_ref_pic;
- int offset_for_top_to_bottom_field;
- unsigned int num_ref_frames_in_poc_cycle;
- int offset_for_ref_frame[255];
- int num_ref_frames;
- bool gaps_in_frame_num_value_allowed_flag;
- unsigned int pic_width_in_mbs_minus1;
- unsigned int pic_height_in_map_units_minus1;
- bool frame_mbs_only_flag;
- bool mb_adaptive_frame_field_flag;
- bool direct_8x8_inference_flag;
- bool frame_cropping_flag;
- unsigned int frame_crop_left_offset;
- unsigned int frame_crop_right_offset;
- unsigned int frame_crop_top_offset;
- unsigned int frame_crop_bottom_offset;
- bool vui_parameters_present_flag;
- //h264_vui_parameters_t *vui_parameters;
- unsigned separate_colour_plane_flag;
- int lossless_qpprime_flag;
-};
-
-/* pic parameter set */
-struct h264_PPS_t {
- int pic_parameter_set_id;
- int seq_parameter_set_id;
- int entropy_coding_mode_flag;
- int pic_order_present_flag;
- int num_slice_groups_minus1;
- int slice_group_map_type;
- int run_length_minus1;
- int top_left;
- int bottom_right;
- int slice_group_change_direction_flag;
- int slice_group_change_rate_minus1;
- int pic_size_in_map_units_minus1;
- int slice_group_id;
- int num_ref_idx_l0_active_minus1;
- int num_ref_idx_l1_active_minus1;
- int weighted_pred_flag;
- int weighted_bipred_idc;
- int pic_init_qp_minus26;
- int pic_init_qs_minus26;
- int chroma_qp_index_offset;
- int deblocking_filter_control_present_flag;
- int constrained_intra_pred_flag;
- int redundant_pic_cnt_present_flag;
-};
-
-void h264_sps_parse(struct h264_stream_t *s, struct h264_SPS_t *sps);
-void h264_pps_parse(struct h264_stream_t *s, struct h264_PPS_t *pps);
-
-void h264_sps_info(struct h264_SPS_t *sps);
-void h264_pps_info(struct h264_PPS_t *pps);
-
-#endif //_H264_PARSE_H
diff --git a/drivers/amvdec_ports/decoder/h264_stream.c b/drivers/amvdec_ports/decoder/h264_stream.c
deleted file mode 100644
index 3061568..0000000
--- a/drivers/amvdec_ports/decoder/h264_stream.c
+++ b/dev/null
@@ -1,111 +0,0 @@
-/*
- * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.c
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include "h264_stream.h"
-
-void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size)
-{
- s->data = data;
- s->size = size;
- s->bit_pos = 7;
- s->byte_pos = 0;
-}
-
-unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n)
-{
- unsigned int ret = 0;
- unsigned char b = 0;
- int i;
-
- if (n == 0)
- return 0;
-
- for (i = 0; i < n; ++i) {
- if (h264_stream_bits_remaining(s) == 0)
- ret <<= n - i - 1;
-
- b = s->data[s->byte_pos];
- if (n - i <= 32)
- ret = ret << 1 | BITAT(b, s->bit_pos);
-
- if (s->bit_pos == 0) {
- s->bit_pos = 7;
- s->byte_pos++;
- } else
- s->bit_pos--;
- }
-
- return ret;
-}
-
-unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n)
-{
- int prev_bit_pos = s->bit_pos;
- int prev_byte_pos = s->byte_pos;
- unsigned int ret = h264_stream_read_bits(s, n);
-
- s->bit_pos = prev_bit_pos;
- s->byte_pos = prev_byte_pos;
-
- return ret;
-}
-
-unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n)
-{
- unsigned int ret = 0;
- int i;
-
- if (n == 0)
- return 0;
-
- for (i = 0; i < n; ++i) {
- if (h264_stream_bytes_remaining(s) == 0) {
- ret <<= (n - i - 1) * 8;
- break;
- }
-
- if (n - i <= 4)
- ret = ret << 8 | s->data[s->byte_pos];
-
- s->byte_pos++;
- }
-
- return ret;
-}
-
-unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n)
-{
- int prev_byte_pos = s->byte_pos;
- unsigned int ret = h264_stream_read_bytes(s, n);
-
- s->byte_pos = prev_byte_pos;
-
- return ret;
-}
-
-int h264_stream_bits_remaining(struct h264_stream_t *s)
-{
- return (s->size - s->byte_pos) * 8 + s->bit_pos;
-}
-
-int h264_stream_bytes_remaining(struct h264_stream_t *s)
-{
- return s->size - s->byte_pos;
-}
-
diff --git a/drivers/amvdec_ports/decoder/h264_stream.h b/drivers/amvdec_ports/decoder/h264_stream.h
deleted file mode 100644
index d6d2eac..0000000
--- a/drivers/amvdec_ports/decoder/h264_stream.h
+++ b/dev/null
@@ -1,39 +0,0 @@
-/*
- * drivers/amlogic/media_modules/amvdec_ports/decoder/h264_stream.h
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#ifndef _H264_STREAM_H
-#define _H264_STREAM_H
-
-#include "utils.h"
-
-struct h264_stream_t {
- unsigned char *data;
- unsigned int size;
- int bit_pos;
- int byte_pos;
-};
-
-void h264_stream_set(struct h264_stream_t *s, unsigned char *data, int size);
-unsigned int h264_stream_read_bits(struct h264_stream_t *s, unsigned int n);
-unsigned int h264_stream_peek_bits(struct h264_stream_t *s, unsigned int n);
-unsigned int h264_stream_read_bytes(struct h264_stream_t *s, unsigned int n);
-unsigned int h264_stream_peek_bytes(struct h264_stream_t *s, unsigned int n);
-int h264_stream_bits_remaining(struct h264_stream_t *s);
-int h264_stream_bytes_remaining(struct h264_stream_t *s);
-
-#endif //_H264_STREAM_H
-
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
index b1e4945..cc2d880 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -211,11 +211,11 @@ static void get_pic_info(struct vdec_h264_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n", pic->y_bs_sz,
pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
}
@@ -227,7 +227,7 @@ static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
@@ -235,7 +235,7 @@ static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
{
*dpb_sz = inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
}
static void skip_aud_data(u8 **data, u32 *size)
@@ -300,7 +300,7 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_H264;
+ inst->vdec.format = VFORMAT_H264;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.ctx = ctx;
@@ -338,7 +338,7 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
}
@@ -509,7 +509,7 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps
vdec_config_dw_mode(pic, dw);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
dw, pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height,
@@ -559,7 +559,7 @@ static int vdec_search_startcode(u8 *buf, u32 range)
return pos;
}
-static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
@@ -578,7 +578,27 @@ static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size)
return inst->vsi->dec.dpb_sz ? 0 : -1;
}
-static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode_dma(struct vdec_h264_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct h264_param_sets *ps;
@@ -619,26 +639,38 @@ static int vdec_h264_probe(unsigned long h_vdec,
{
struct vdec_h264_inst *inst =
(struct vdec_h264_inst *)h_vdec;
- struct stream_info *st;
- u8 *buf = (u8 *)bs->vaddr;
+ u8 *buf = (u8 *) bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
-
- if (st->magic == NORe || st->magic == NORn) {
- buf = st->data;
- size = st->length;
- }
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
- skip_aud_data(&buf, &size);
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
- if (inst->ctx->param_sets_from_ucode)
- ret = stream_parse_by_ucode(inst, buf, size);
- else
- ret = stream_parse(inst, buf, size);
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ skip_aud_data((u8 **)&s->data, &s->len);
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ skip_aud_data(&buf, &size);
+ ret = parse_stream_cpu(inst, buf, size);
+ }
+ }
inst->vsi->cur_pic = inst->vsi->pic;
@@ -699,8 +731,10 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_v4l2_buffe
atomic_set(&vf->use_cnt, 1);
fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
- fb->vf_handle = (unsigned long)vf;
- fb->status = FB_ST_DISPLAY;
+ if (fb) {
+ fb->vf_handle = (unsigned long)vf;
+ fb->status = FB_ST_DISPLAY;
+ }
*out = fb;
@@ -805,7 +839,7 @@ static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size)
break;
if (type == NAL_H264_SPS) {
- ret = stream_parse(inst, p, len);
+ ret = parse_stream_cpu(inst, p, len);
if (ret)
break;
}
@@ -835,9 +869,8 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
int ret = -1;
if (bs == NULL)
@@ -846,23 +879,44 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
if (vdec_input_full(vdec))
return -EAGAIN;
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else {
- /*checked whether the resolution changes.*/
- if ((*res_chg = monitor_res_change(inst, buf, size)))
- return 0;
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+ if (!inst->ctx->param_sets_from_ucode &&
+ (s->type == V4L_STREAM_TYPE_MATEDATA)) {
+ if ((*res_chg = monitor_res_change(inst,
+ s->data, s->len)))
+ return 0;
+ }
+
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ int nal_idx = 0;
+ /* if the st compose from csd + slice that is the combine data. */
+ inst->vsi->is_combine = check_frame_combine(buf, size, &nal_idx);
+ /*if (nal_idx < 0)
+ return -1;*/
+ } else {
+ /*checked whether the resolution changes.*/
+ if ((*res_chg = monitor_res_change(inst, buf, size))) {
+ return 0;
+ }
+ }
ret = vdec_write_nalu(inst, buf, size, timestamp);
}
@@ -943,6 +997,7 @@ static void set_param_ps_info(struct vdec_h264_inst *inst,
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_h264_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
+ int dw = inst->parms.cfg.double_write_mode;
/* fill visible area size that be used for EGL. */
pic->visible_width = ps->visible_width;
@@ -959,13 +1014,16 @@ static void set_param_ps_info(struct vdec_h264_inst *inst,
pic->coded_height = ps->coded_height;
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
-
+ pic->profile_idc = ps->profile;
+ pic->ref_frame_count = ps->ref_frames;
dec->dpb_sz = ps->dpb_size;
inst->parms.ps = *ps;
inst->parms.parms_status |=
V4L2_CONFIG_PARM_DECODE_PSINFO;
+ vdec_config_dw_mode(pic, dw);
+
/*wake up*/
complete(&inst->comp);
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index 025d521..e47acb9 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -122,11 +122,11 @@ static void get_pic_info(struct vdec_hevc_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n", pic->y_bs_sz,
pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
}
@@ -138,7 +138,7 @@ static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
@@ -146,7 +146,7 @@ static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
{
*dpb_sz = inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
}
static u32 vdec_config_default_parms(u8 *parm)
@@ -206,7 +206,7 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_HEVC;
+ inst->vdec.format = VFORMAT_HEVC;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.ctx = ctx;
@@ -247,7 +247,7 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
}
@@ -292,7 +292,7 @@ static int refer_buffer_num(struct h265_SPS_t *sps)
used_buf_num = sps->temporal_layer[0].num_reorder_pics;
sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering -
- sps->temporal_layer[0].num_reorder_pics + 1;
+ sps->temporal_layer[0].num_reorder_pics - 1;
if (sps_pic_buf_diff >= 4)
used_buf_num += 1;
@@ -402,14 +402,14 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps
inst->parms.ps.dpb_size = dec->dpb_sz;
inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
dw, pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height,
dec->dpb_sz - margin, margin);
}
-static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
@@ -428,7 +428,27 @@ static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
return inst->vsi->dec.dpb_sz ? 0 : -1;
}
-static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode_dma(struct vdec_hevc_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct h265_param_sets *ps = NULL;
@@ -459,22 +479,35 @@ static int vdec_hevc_probe(unsigned long h_vdec,
{
struct vdec_hevc_inst *inst =
(struct vdec_hevc_inst *)h_vdec;
- struct stream_info *st;
u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
-
- if (st->magic == NORe || st->magic == NORn)
- ret = stream_parse(inst, st->data, st->length);
- else {
- if (inst->ctx->param_sets_from_ucode)
- ret = stream_parse_by_ucode(inst, buf, size);
- else
- ret = stream_parse(inst, buf, size);
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
+
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ ret = parse_stream_cpu(inst, buf, size);
+ }
}
inst->vsi->cur_pic = inst->vsi->pic;
@@ -577,7 +610,7 @@ static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
break;
if (type == HEVC_NAL_SPS) {
- ret = stream_parse(inst, p, len);
+ ret = parse_stream_cpu(inst, p, len);
if (ret)
break;
}
@@ -602,9 +635,8 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
int ret = -1;
if (bs == NULL)
@@ -613,23 +645,37 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
if (vdec_input_full(vdec))
return -EAGAIN;
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else {
- /*checked whether the resolution changes.*/
- if ((*res_chg = monitor_res_change(inst, buf, size)))
- return 0;
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+
+ if (!inst->ctx->param_sets_from_ucode &&
+ (s->type == V4L_STREAM_TYPE_MATEDATA)) {
+ if ((*res_chg = monitor_res_change(inst,
+ s->data, s->len)))
+ return 0;
+ }
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (!inst->ctx->param_sets_from_ucode) {
+ /*checked whether the resolution changes.*/
+ if ((*res_chg = monitor_res_change(inst, buf, size)))
+ return 0;
+ }
ret = vdec_write_nalu(inst, buf, size, timestamp);
}
@@ -722,8 +768,9 @@ static void set_param_ps_info(struct vdec_hevc_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(ps->coded_width, 64);
- pic->coded_height = ALIGN(ps->coded_height, 64);
+
+ pic->coded_width = ps->coded_width;
+ pic->coded_height = ps->coded_height;
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
index 6a7a4d8..c4c9fa7 100644
--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -93,6 +93,7 @@ struct vdec_mjpeg_vsi {
int head_offset;
struct vdec_mjpeg_dec_info dec;
struct vdec_pic_info pic;
+ struct vdec_pic_info cur_pic;
struct v4l2_rect crop;
bool is_combine;
int nalu_pos;
@@ -111,6 +112,7 @@ struct vdec_mjpeg_inst {
struct aml_vdec_adapt vdec;
struct vdec_mjpeg_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct completion comp;
};
static void get_pic_info(struct vdec_mjpeg_inst *inst,
@@ -118,11 +120,11 @@ static void get_pic_info(struct vdec_mjpeg_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n",
pic->y_bs_sz, pic->y_len_sz,
pic->c_bs_sz, pic->c_len_sz);
@@ -135,7 +137,7 @@ static void get_crop_info(struct vdec_mjpeg_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
@@ -143,7 +145,7 @@ static void get_crop_info(struct vdec_mjpeg_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_mjpeg_inst *inst, unsigned int *dpb_sz)
{
*dpb_sz = 20;//inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"sz=%d\n", *dpb_sz);
}
@@ -156,7 +158,7 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_MJPEG;
+ inst->vdec.format = VFORMAT_MJPEG;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.config = ctx->config;
@@ -173,27 +175,32 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* init vfm */
inst->vfm.ctx = ctx;
inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "init vfm failed.\n");
+ goto err;
+ }
ret = video_decoder_init(&inst->vdec);
if (ret) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"vdec_mjpeg init err=%d\n", ret);
- goto error_free_inst;
+ goto err;
}
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_mjpeg_vsi), GFP_KERNEL);
if (!inst->vsi) {
ret = -ENOMEM;
- goto error_free_inst;
+ goto err;
}
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
- goto error_free_vsi;
+ goto err;
}
inst->vsi->pic.visible_width = 1920;
@@ -215,10 +222,15 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
return 0;
-error_free_vsi:
- kfree(inst->vsi);
-error_free_inst:
- kfree(inst);
+err:
+ if (inst)
+ vcodec_vfm_release(&inst->vfm);
+ if (inst && inst->vsi && inst->vsi->header_buf)
+ kfree(inst->vsi->header_buf);
+ if (inst && inst->vsi)
+ kfree(inst->vsi);
+ if (inst)
+ kfree(inst);
*h_vdec = 0;
return ret;
@@ -259,13 +271,52 @@ static void fill_vdec_params(struct vdec_mjpeg_inst *inst,
/* calc DPB size */
dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height, dec->dpb_sz);
}
-static int stream_parse(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write(vdec, buf, size, 0);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mjpeg_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct mjpeg_param_sets *ps = NULL;
@@ -296,19 +347,38 @@ static int vdec_mjpeg_probe(unsigned long h_vdec,
{
struct vdec_mjpeg_inst *inst =
(struct vdec_mjpeg_inst *)h_vdec;
- struct stream_info *st;
u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
+
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ ret = parse_stream_cpu(inst, buf, size);
+ }
+ }
- if (st->magic == NORe || st->magic == NORn)
- ret = stream_parse(inst, st->data, st->length);
- else
- ret = stream_parse(inst, buf, size);
+ inst->vsi->cur_pic = inst->vsi->pic;
return ret;
}
@@ -393,29 +463,34 @@ static int vdec_mjpeg_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
- int ret = 0;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
+ int ret = -1;
- /* bs NULL means flush decoder */
- if (bs == NULL)
- return 0;
-
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else
+ if (vdec_input_full(vdec))
+ return -EAGAIN;
+
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
ret = vdec_write_nalu(inst, buf, size, timestamp);
+ }
return ret;
}
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
index 89725fa..804296b 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -93,6 +93,7 @@ struct vdec_mpeg12_vsi {
int head_offset;
struct vdec_mpeg12_dec_info dec;
struct vdec_pic_info pic;
+ struct vdec_pic_info cur_pic;
struct v4l2_rect crop;
bool is_combine;
int nalu_pos;
@@ -120,11 +121,11 @@ static void get_pic_info(struct vdec_mpeg12_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n",
pic->y_bs_sz, pic->y_len_sz,
pic->c_bs_sz, pic->c_len_sz);
@@ -137,7 +138,7 @@ static void get_crop_info(struct vdec_mpeg12_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
@@ -145,7 +146,7 @@ static void get_crop_info(struct vdec_mpeg12_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_mpeg12_inst *inst, unsigned int *dpb_sz)
{
*dpb_sz = inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
}
static u32 vdec_config_default_parms(u8 *parm)
@@ -181,6 +182,7 @@ static void vdec_parser_parms(struct vdec_mpeg12_inst *inst)
inst->parms.cfg = ctx->config.parm.dec.cfg;
inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
}
+
static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_mpeg12_inst *inst = NULL;
@@ -190,7 +192,7 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_MPEG12;
+ inst->vdec.format = VFORMAT_MPEG12;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.config = ctx->config;
@@ -209,41 +211,37 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* init vfm */
inst->vfm.ctx = ctx;
inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "init vfm failed.\n");
+ goto err;
+ }
ret = video_decoder_init(&inst->vdec);
if (ret) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"vdec_mpeg12 init err=%d\n", ret);
- goto error_free_inst;
+ goto err;
}
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_mpeg12_vsi), GFP_KERNEL);
if (!inst->vsi) {
ret = -ENOMEM;
- goto error_free_inst;
+ goto err;
}
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
- goto error_free_vsi;
+ goto err;
}
- inst->vsi->pic.visible_width = 1920;
- inst->vsi->pic.visible_height = 1080;
- inst->vsi->pic.coded_width = 1920;
- inst->vsi->pic.coded_height = 1088;
- inst->vsi->pic.y_bs_sz = 0;
- inst->vsi->pic.y_len_sz = (1920 * 1088);
- inst->vsi->pic.c_bs_sz = 0;
- inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
-
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"mpeg12 Instance >> %lx\n", (ulong) inst);
-
+ init_completion(&inst->comp);
ctx->ada_ctx = &inst->vdec;
*h_vdec = (unsigned long)inst;
@@ -251,10 +249,15 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
return 0;
-error_free_vsi:
- kfree(inst->vsi);
-error_free_inst:
- kfree(inst);
+err:
+ if (inst)
+ vcodec_vfm_release(&inst->vfm);
+ if (inst && inst->vsi && inst->vsi->header_buf)
+ kfree(inst->vsi->header_buf);
+ if (inst && inst->vsi)
+ kfree(inst->vsi);
+ if (inst)
+ kfree(inst);
*h_vdec = 0;
return ret;
@@ -284,23 +287,44 @@ static void fill_vdec_params(struct vdec_mpeg12_inst *inst,
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
- /*1(EOS) + 8(DECODE_BUFFER_NUM_DEF)*/
- dec->dpb_sz = 9;
+ /*7(parm_v4l_buffer_margin) + 8(DECODE_BUFFER_NUM_DEF)*/
+ dec->dpb_sz = 15;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height, dec->dpb_sz);
}
-static int stream_parse_by_ucode(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
ret = vdec_vframe_write(vdec, buf, size, 0);
if (ret < 0) {
- pr_err("write frame data failed. err: %d\n", ret);
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mpeg12_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
return ret;
}
@@ -311,7 +335,7 @@ static int stream_parse_by_ucode(struct vdec_mpeg12_inst *inst, u8 *buf, u32 siz
return inst->vsi->dec.dpb_sz ? 0 : -1;
}
-static int stream_parse(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
+static int parse_stream_cpu(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct mpeg12_param_sets *ps = NULL;
@@ -342,21 +366,38 @@ static int vdec_mpeg12_probe(unsigned long h_vdec,
{
struct vdec_mpeg12_inst *inst =
(struct vdec_mpeg12_inst *)h_vdec;
- struct stream_info *st;
u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
+
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ ret = parse_stream_cpu(inst, buf, size);
+ }
+ }
- if (inst->ctx->param_sets_from_ucode)
- ret = stream_parse_by_ucode(inst, buf, size);
- else if (st->magic == NORe || st->magic == NORn)
- ret = stream_parse(inst, st->data, st->length);
- else
- ret = stream_parse(inst, buf, size);
+ inst->vsi->cur_pic = inst->vsi->pic;
return ret;
}
@@ -441,29 +482,34 @@ static int vdec_mpeg12_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
- int ret = 0;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
+ int ret = -1;
- /* bs NULL means flush decoder */
- if (bs == NULL)
- return 0;
-
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else
+ if (vdec_input_full(vdec))
+ return -EAGAIN;
+
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
ret = vdec_write_nalu(inst, buf, size, timestamp);
+ }
return ret;
}
@@ -538,7 +584,7 @@ static void set_param_ps_info(struct vdec_mpeg12_inst *inst,
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
- dec->dpb_sz = ps->dpb_size + 1;
+ dec->dpb_sz = ps->dpb_size;
inst->parms.ps = *ps;
inst->parms.parms_status |=
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
index d031c0e..660178c 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -93,6 +93,7 @@ struct vdec_mpeg4_vsi {
int head_offset;
struct vdec_mpeg4_dec_info dec;
struct vdec_pic_info pic;
+ struct vdec_pic_info cur_pic;
struct v4l2_rect crop;
bool is_combine;
int nalu_pos;
@@ -111,6 +112,8 @@ struct vdec_mpeg4_inst {
struct aml_vdec_adapt vdec;
struct vdec_mpeg4_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
+ struct completion comp;
};
static void get_pic_info(struct vdec_mpeg4_inst *inst,
@@ -118,11 +121,11 @@ static void get_pic_info(struct vdec_mpeg4_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n",
pic->y_bs_sz, pic->y_len_sz,
pic->c_bs_sz, pic->c_len_sz);
@@ -135,17 +138,52 @@ static void get_crop_info(struct vdec_mpeg4_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
static void get_dpb_size(struct vdec_mpeg4_inst *inst, unsigned int *dpb_sz)
{
- *dpb_sz = 9;//inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
+ *dpb_sz = inst->vsi->dec.dpb_sz;
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:0;");
+
+ return pbuf - parm;
}
+static void vdec_parser_parms(struct vdec_mpeg4_inst *inst)
+{
+ struct aml_vcodec_ctx *ctx = inst->ctx;
+
+ if (ctx->config.parm.dec.parms_status &
+ V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+ u8 *pbuf = ctx->config.buf;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ ctx->config.parm.dec.cfg.ref_buf_margin);
+ ctx->config.length = pbuf - ctx->config.buf;
+ } else {
+ ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+ }
+
+ inst->vdec.config = ctx->config;
+ inst->parms.cfg = ctx->config.parm.dec.cfg;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+
static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_mpeg4_inst *inst = NULL;
@@ -155,14 +193,15 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_MPEG4;
- inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5;
+ inst->vdec.format = VFORMAT_MPEG4;
+ inst->vdec.dec_type = VIDEO_DEC_FORMAT_MPEG4_5;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.config = ctx->config;
inst->vdec.ctx = ctx;
inst->ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
@@ -173,41 +212,38 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* init vfm */
inst->vfm.ctx = ctx;
inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "init vfm failed.\n");
+ goto err;
+ }
ret = video_decoder_init(&inst->vdec);
if (ret) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"vdec_mpeg4 init err=%d\n", ret);
- goto error_free_inst;
+ goto err;
}
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
if (!inst->vsi) {
ret = -ENOMEM;
- goto error_free_inst;
+ goto err;
}
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
- goto error_free_vsi;
+ goto err;
}
- inst->vsi->pic.visible_width = 1920;
- inst->vsi->pic.visible_height = 1080;
- inst->vsi->pic.coded_width = 1920;
- inst->vsi->pic.coded_height = 1088;
- inst->vsi->pic.y_bs_sz = 0;
- inst->vsi->pic.y_len_sz = (1920 * 1088);
- inst->vsi->pic.c_bs_sz = 0;
- inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
-
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"mpeg4 Instance >> %lx\n", (ulong) inst);
+ init_completion(&inst->comp);
ctx->ada_ctx = &inst->vdec;
*h_vdec = (unsigned long)inst;
@@ -215,10 +251,15 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
return 0;
-error_free_vsi:
- kfree(inst->vsi);
-error_free_inst:
- kfree(inst);
+err:
+ if (inst)
+ vcodec_vfm_release(&inst->vfm);
+ if (inst && inst->vsi && inst->vsi->header_buf)
+ kfree(inst->vsi->header_buf);
+ if (inst && inst->vsi)
+ kfree(inst->vsi);
+ if (inst)
+ kfree(inst);
*h_vdec = 0;
return ret;
@@ -256,16 +297,55 @@ static void fill_vdec_params(struct vdec_mpeg4_inst *inst,
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
- /* calc DPB size */
- dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+ /*8(DECODE_BUFFER_NUM_DEF) */
+ dec->dpb_sz = 8;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height, dec->dpb_sz);
}
-static int stream_parse(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write(vdec, buf, size, 0);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct mpeg4_param_sets *ps = NULL;
@@ -296,19 +376,38 @@ static int vdec_mpeg4_probe(unsigned long h_vdec,
{
struct vdec_mpeg4_inst *inst =
(struct vdec_mpeg4_inst *)h_vdec;
- struct stream_info *st;
u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
+
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ ret = parse_stream_cpu(inst, buf, size);
+ }
+ }
- if (st->magic == NORe || st->magic == NORn)
- ret = stream_parse(inst, st->data, st->length);
- else
- ret = stream_parse(inst, buf, size);
+ inst->vsi->cur_pic = inst->vsi->pic;
return ret;
}
@@ -393,29 +492,34 @@ static int vdec_mpeg4_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
- int ret = 0;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
+ int ret = -1;
- /* bs NULL means flush decoder */
- if (bs == NULL)
- return 0;
-
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else
+ if (vdec_input_full(vdec))
+ return -EAGAIN;
+
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
ret = vdec_write_nalu(inst, buf, size, timestamp);
+ }
return ret;
}
@@ -465,7 +569,46 @@ static int vdec_mpeg4_get_param(unsigned long h_vdec,
static void set_param_ps_info(struct vdec_mpeg4_inst *inst,
struct aml_vdec_ps_infos *ps)
{
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "\n");
+ struct vdec_pic_info *pic = &inst->vsi->pic;
+ struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec;
+ struct v4l2_rect *rect = &inst->vsi->crop;
+
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "%s in\n", __func__);
+ /* fill visible area size that be used for EGL. */
+ pic->visible_width = ps->visible_width;
+ pic->visible_height = ps->visible_height;
+
+ /* calc visible ares. */
+ rect->left = 0;
+ rect->top = 0;
+ rect->width = pic->visible_width;
+ rect->height = pic->visible_height;
+
+ /* config canvas size that be used for decoder. */
+ pic->coded_width = ps->coded_width;
+ pic->coded_height = ps->coded_height;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+
+ dec->dpb_sz = ps->dpb_size;
+
+ inst->parms.ps = *ps;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+ /*wake up*/
+ complete(&inst->comp);
+
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
+ ps->visible_width, ps->visible_height,
+ ps->coded_width, ps->coded_height,
+ dec->dpb_sz);
+}
+
+static void set_param_write_sync(struct vdec_mpeg4_inst *inst)
+{
+ complete(&inst->comp);
}
static int vdec_mpeg4_set_param(unsigned long h_vdec,
@@ -481,6 +624,9 @@ static int vdec_mpeg4_set_param(unsigned long h_vdec,
}
switch (type) {
+ case SET_PARAM_WRITE_FRAME_SYNC:
+ set_param_write_sync(inst);
+ break;
case SET_PARAM_PS_INFO:
set_param_ps_info(inst, in);
break;
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
index 3952ae7..2cb568d 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -136,11 +136,11 @@ static void get_pic_info(struct vdec_vp9_inst *inst,
{
*pic = inst->vsi->pic;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"pic(%d, %d), buf(%d, %d)\n",
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"Y(%d, %d), C(%d, %d)\n",
pic->y_bs_sz, pic->y_len_sz,
pic->c_bs_sz, pic->c_len_sz);
@@ -153,7 +153,7 @@ static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
cr->width = inst->vsi->crop.width;
cr->height = inst->vsi->crop.height;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
"l=%d, t=%d, w=%d, h=%d\n",
cr->left, cr->top, cr->width, cr->height);
}
@@ -161,7 +161,7 @@ static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz)
{
*dpb_sz = inst->vsi->dec.dpb_sz;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "sz=%d\n", *dpb_sz);
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
}
static u32 vdec_config_default_parms(u8 *parm)
@@ -261,7 +261,7 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->vdec.video_type = VFORMAT_VP9;
+ inst->vdec.format = VFORMAT_VP9;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.ctx = ctx;
@@ -295,7 +295,7 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
- if (!inst->vsi) {
+ if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
}
@@ -432,14 +432,14 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst,
inst->parms.ps.dpb_size = dec->dpb_sz;
inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
dw, pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height,
dec->dpb_sz - margin, margin);
}
-static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
@@ -457,7 +457,27 @@ static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
return inst->vsi->dec.dpb_sz ? 0 : -1;
}
-static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
+static int parse_stream_ucode_dma(struct vdec_vp9_inst *inst,
+ ulong buf, u32 size, u32 handle)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
+ if (ret < 0) {
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ "write frame data failed. err: %d\n", ret);
+ return ret;
+ }
+
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
+
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct vp9_param_sets *ps = NULL;
@@ -488,22 +508,35 @@ static int vdec_vp9_probe(unsigned long h_vdec,
{
struct vdec_vp9_inst *inst =
(struct vdec_vp9_inst *)h_vdec;
- struct stream_info *st;
u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
- st = (struct stream_info *)buf;
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- return 0;
-
- if (st->magic == NORe || st->magic == NORn)
- ret = stream_parse(inst, st->data, st->length);
- else {
- if (inst->ctx->param_sets_from_ucode)
- ret = stream_parse_by_ucode(inst, buf, size);
- else
- ret = stream_parse(inst, buf, size);
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if ((s->magic != AML_VIDEO_MAGIC) &&
+ (s->type != V4L_STREAM_TYPE_MATEDATA))
+ return -1;
+
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, s->data, s->len);
+ } else {
+ ret = parse_stream_cpu(inst, s->data, s->len);
+ }
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = parse_stream_ucode_dma(inst, bs->addr, size,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
+ if (inst->ctx->param_sets_from_ucode) {
+ ret = parse_stream_ucode(inst, buf, size);
+ } else {
+ ret = parse_stream_cpu(inst, buf, size);
+ }
}
inst->vsi->cur_pic = inst->vsi->pic;
@@ -698,7 +731,7 @@ static bool monitor_res_change(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
((p[17] << 16) | (p[18] << 8) | p[19]);
if (synccode == SYNC_CODE) {
- ret = stream_parse(inst, p, len);
+ ret = parse_stream_cpu(inst, p, len);
if (!ret && (inst->vsi->cur_pic.coded_width !=
inst->vsi->pic.coded_width ||
inst->vsi->cur_pic.coded_height !=
@@ -716,9 +749,8 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
{
struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- struct stream_info *st;
- u8 *buf;
- u32 size;
+ u8 *buf = (u8 *) bs->vaddr;
+ u32 size = bs->size;
int ret = -1;
if (bs == NULL)
@@ -729,21 +761,35 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return -EAGAIN;
}
- buf = (u8 *)bs->vaddr;
- size = bs->size;
- st = (struct stream_info *)buf;
-
- if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
- ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
- else if (st->magic == NORe)
- ret = vdec_vbuf_write(vdec, st->data, st->length);
- else if (st->magic == NORn)
- ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
- else if (inst->ctx->is_stream_mode)
- ret = vdec_vbuf_write(vdec, buf, size);
- else {
+ if (inst->ctx->is_drm_mode) {
+ if (bs->model == VB2_MEMORY_MMAP) {
+ struct aml_video_stream *s =
+ (struct aml_video_stream *) buf;
+
+ if (s->magic != AML_VIDEO_MAGIC)
+ return -1;
+
+ if (!inst->ctx->param_sets_from_ucode &&
+ (s->type == V4L_STREAM_TYPE_MATEDATA)) {
+ if ((*res_chg = monitor_res_change(inst,
+ s->data, s->len)))
+ return 0;
+ }
+
+ ret = vdec_vframe_write(vdec,
+ s->data,
+ s->len,
+ timestamp);
+ } else if (bs->model == VB2_MEMORY_DMABUF ||
+ bs->model == VB2_MEMORY_USERPTR) {
+ ret = vdec_vframe_write_with_dma(vdec,
+ bs->addr, size, timestamp,
+ BUFF_IDX(bs, bs->index));
+ }
+ } else {
/*checked whether the resolution changes.*/
- if ((*res_chg = monitor_res_change(inst, buf, size)))
+ if ((!inst->ctx->param_sets_from_ucode) &&
+ (*res_chg = monitor_res_change(inst, buf, size)))
return 0;
ret = vdec_write_nalu(inst, buf, size, timestamp);
@@ -846,7 +892,7 @@ static void set_param_ps_info(struct vdec_vp9_inst *inst,
pic->c_len_sz = pic->y_len_sz >> 1;
/* calc DPB size */
- dec->dpb_sz = 5;
+ dec->dpb_sz = ps->dpb_size;
inst->parms.ps = *ps;
inst->parms.parms_status |=
diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c
index 96b0c93..e870da4 100644
--- a/drivers/amvdec_ports/vdec_drv_if.c
+++ b/drivers/amvdec_ports/vdec_drv_if.c
@@ -82,7 +82,7 @@ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs,
int ret = 0;
if (bs) {
- if ((bs->dma_addr & 63) != 0) {
+ if ((bs->addr & 63) != 0) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"bs dma_addr should 64 byte align\n");
return -EINVAL;
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index d3ccef2..a5ab735 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -25,19 +25,26 @@
#include "aml_vcodec_util.h"
#include "../stream_input/parser/streambuf.h"
-#define NORe CODEC_MODE('N', 'O', 'R', 'e') // normal es
-#define NORn CODEC_MODE('N', 'O', 'R', 'n') // normal nalu
-#define DRMe CODEC_MODE('D', 'R', 'M', 'e') // drm es
-#define DRMn CODEC_MODE('D', 'R', 'M', 'n') // drm nalu
+#define AML_VIDEO_MAGIC CODEC_MODE('A', 'M', 'L', 'V')
+
+#define V4L_STREAM_TYPE_MATEDATA (0)
+#define V4L_STREAM_TYPE_FRAME (1)
struct stream_info {
+ u32 stream_width;
+ u32 stream_height;
+ u32 stream_field;
+ u32 stream_dpb;
+};
+
+struct aml_video_stream {
u32 magic;
u32 type;
union {
- struct drm_info drm;
- u8 buf[128];
+ struct stream_info s;
+ u8 buf[64];
} m;
- u32 length;
+ u32 len;
u8 data[0];
};
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
index a850134..2cef4da 100644
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -874,6 +874,7 @@ struct vdec_h264_hw_s {
unsigned int last_picture_slice_count;
unsigned int first_pre_frame_num;
#endif
+ unsigned int res_ch_flag;
};
static u32 again_threshold;
@@ -2609,6 +2610,8 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
struct vframe_s *vf = NULL;
int buffer_index = frame->buf_spec_num;
+ struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+ ulong nv_order = VIDTYPE_VIU_NV21;
int vf_count = 1;
int i;
int bForceInterlace = 0;
@@ -2619,6 +2622,14 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
__func__, buffer_index);
return -1;
}
+
+ /* swap uv */
+ if (hw->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
+
if (force_disp_bufspec_num & 0x100) {
/*recycle directly*/
if (hw->buffer_spec[frame->buf_spec_num].used != 3 &&
@@ -2780,7 +2791,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
if (hw->double_write_mode) {
vf->type |= VIDTYPE_PROGRESSIVE
| VIDTYPE_VIU_FIELD;
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
if (hw->double_write_mode == 3)
vf->type |= VIDTYPE_COMPRESS;
@@ -2813,7 +2824,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
vf->compHeight = hw->frame_height;
} else {
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
- VIDTYPE_VIU_NV21;
+ nv_order;
vf->canvas0Addr = vf->canvas1Addr =
spec2canvas(&hw->buffer_spec[buffer_index]);
@@ -3827,10 +3838,19 @@ static struct vframe_s *vh264_vf_get(void *op_arg)
struct vframe_s *vf;
struct vdec_s *vdec = op_arg;
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+ struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+ ulong nv_order = VIDTYPE_VIU_NV21;
if (!hw)
return NULL;
+ /* swap uv */
+ if (hw->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
+
if (force_disp_bufspec_num & 0x100) {
int buffer_index = force_disp_bufspec_num & 0xff;
if (force_disp_bufspec_num & 0x200)
@@ -3861,7 +3881,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg)
if (hw->double_write_mode) {
vf->type |= VIDTYPE_PROGRESSIVE
| VIDTYPE_VIU_FIELD;
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
if (hw->double_write_mode == 3)
vf->type |= VIDTYPE_COMPRESS;
@@ -3899,7 +3919,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg)
}
} else {
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
- VIDTYPE_VIU_NV21;
+ nv_order;
vf->canvas0Addr = vf->canvas1Addr =
spec2canvas(&hw->buffer_spec[buffer_index]);
}
@@ -5767,17 +5787,6 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
unsigned short *p = (unsigned short *)hw->lmem_addr;
reset_process_time(hw);
- if (hw->is_used_v4l) {
- struct aml_vcodec_ctx *ctx =
- (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
-
- if (ctx->param_sets_from_ucode && !ctx->v4l_codec_ready) {
- //amvdec_stop();
- hw->dec_result = DEC_RESULT_DONE;
- vdec_schedule_work(&hw->work);
- return IRQ_HANDLED;
- }
- }
#ifdef DETECT_WRONG_MULTI_SLICE
hw->cur_picture_slice_count++;
if (hw->multi_slice_pic_flag == 1 &&
@@ -6765,7 +6774,8 @@ static void check_timer_func(struct timer_list *timer)
return;
}
- if (vdec->next_status == VDEC_STATUS_DISCONNECTED) {
+ if (vdec->next_status == VDEC_STATUS_DISCONNECTED &&
+ !hw->is_used_v4l) {
hw->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hw->work);
pr_debug("vdec requested to be disconnected\n");
@@ -6937,6 +6947,8 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw)
&& (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21
|| v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+ else
+ CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);
CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);
@@ -8087,6 +8099,117 @@ static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec)
#endif
+static int vmh264_get_ps_info(struct vdec_h264_hw_s *hw, u32 param1, u32 param4, struct aml_vdec_ps_infos *ps)
+{
+ struct vdec_s *vdec = hw_to_vdec(hw);
+ int mb_width, mb_total;
+ int mb_height = 0;
+ int active_buffer_spec_num;
+ int max_reference_size ,level_idc;
+ unsigned int used_reorder_dpb_size_margin
+ = hw->reorder_dpb_size_margin;
+ int reorder_pic_num;
+
+ level_idc = param4 & 0xff;
+ max_reference_size = (param4 >> 8) & 0xff;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+ if (vdec->master || vdec->slave)
+ used_reorder_dpb_size_margin =
+ reorder_dpb_size_margin_dv;
+#endif
+ mb_width = param1 & 0xff;
+ mb_total = (param1 >> 8) & 0xffff;
+ if (!mb_width && mb_total) /*for 4k2k*/
+ mb_width = 256;
+ if (mb_width)
+ mb_height = mb_total/mb_width;
+ if (mb_width <= 0 || mb_height <= 0 ||
+ is_oversize(mb_width << 4, mb_height << 4)) {
+ dpb_print(DECODE_ID(hw), 0,
+ "!!!wrong param1 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
+ param1,
+ mb_width,
+ mb_height);
+ return -1;
+ }
+
+ reorder_pic_num =
+ get_max_dec_frame_buf_size(level_idc,
+ max_reference_size, mb_width, mb_height);
+
+ if ((hw->bitstream_restriction_flag) &&
+ (hw->max_dec_frame_buffering <
+ reorder_pic_num)) {
+ reorder_pic_num = hw->max_dec_frame_buffering;
+ dpb_print(DECODE_ID(hw), 0,
+ "set reorder_pic_num to %d\n",
+ reorder_pic_num);
+ }
+
+ active_buffer_spec_num =
+ reorder_pic_num
+ + used_reorder_dpb_size_margin;
+
+ if (active_buffer_spec_num > MAX_VF_BUF_NUM) {
+ active_buffer_spec_num = MAX_VF_BUF_NUM;
+ reorder_pic_num = active_buffer_spec_num
+ - used_reorder_dpb_size_margin;
+ }
+
+ if (hw->no_poc_reorder_flag)
+ reorder_pic_num = 1;
+
+ ps->profile = level_idc;
+ ps->ref_frames = max_reference_size;
+ ps->mb_width = mb_width;
+ ps->mb_height = mb_height;
+ ps->visible_width = mb_width << 4;
+ ps->visible_height = mb_height << 4;
+ ps->coded_width = ALIGN(mb_width << 4, 64);
+ ps->coded_height = ALIGN(mb_height << 4, 64);
+ ps->reorder_frames = reorder_pic_num;
+ ps->dpb_size = active_buffer_spec_num;
+
+ return 0;
+}
+
+static int v4l_res_change(struct vdec_h264_hw_s *hw, u32 param1, u32 param4)
+{
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+ struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+ int ret = 0;
+
+ if (ctx->param_sets_from_ucode &&
+ hw->res_ch_flag == 0) {
+ if (param1 != 0 &&
+ hw->seq_info2 != (param1 & (~0x80000000)) &&
+ hw->seq_info2 != 0) /*picture size changed*/ {
+ struct aml_vdec_ps_infos ps;
+ dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, "h264 res_change\n");
+ if (vmh264_get_ps_info(hw, param1, param4, &ps) < 0) {
+ dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
+ }
+ hw->v4l_params_parsed = false;
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ vdec_v4l_res_ch_event(ctx);
+ hw->res_ch_flag = 1;
+ amvdec_stop();
+ if (hw->mmu_enable)
+ amhevc_stop();
+ hw->eos = 1;
+ flush_dpb(p_H264_Dpb);
+ //del_timer_sync(&hw->check_timer);
+ if (hw->is_used_v4l)
+ notify_v4l_eos(hw_to_vdec(hw));
+ ret = 1;
+ }
+ }
+
+ return ret;
+
+}
static void vh264_work_implement(struct vdec_h264_hw_s *hw,
struct vdec_s *vdec, int from)
@@ -8112,34 +8235,48 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw,
u32 param2 = READ_VREG(AV_SCRATCH_2);
u32 param3 = READ_VREG(AV_SCRATCH_6);
u32 param4 = READ_VREG(AV_SCRATCH_B);
-
- if (vh264_set_params(hw, param1,
- param2, param3, param4) < 0)
- dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
-
- WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) |
- (hw->dpb.mDPB.size<<16) |
- (hw->dpb.mDPB.size<<8));
-
- if (hw->is_used_v4l) {
- struct aml_vcodec_ctx *ctx =
+ 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_ps_infos ps;
-
- ps.visible_width = hw->frame_width;
- ps.visible_height = hw->frame_height;
- ps.coded_width = ALIGN(hw->frame_width, 64);
- ps.coded_height = ALIGN(hw->frame_height, 64);
- ps.dpb_size = hw->dpb.mDPB.size;
- hw->v4l_params_parsed = true;
- vdec_v4l_set_ps_infos(ctx, &ps);
+ if (hw->is_used_v4l &&
+ ctx->param_sets_from_ucode) {
+ if (!v4l_res_change(hw, param1, param4)) {
+ if (!hw->v4l_params_parsed) {
+ struct aml_vdec_ps_infos ps;
+ dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL, "h264 parsered csd data\n");
+ if (vmh264_get_ps_info(hw, param1, param4, &ps) < 0) {
+ dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
+ }
+ hw->v4l_params_parsed = true;
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ amvdec_stop();
+ if (hw->mmu_enable)
+ amhevc_stop();
+ }
+ else {
+ if (vh264_set_params(hw, param1,
+ param2, param3, param4) < 0)
+ dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
+
+ WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) |
+ (hw->dpb.mDPB.size<<16) |
+ (hw->dpb.mDPB.size<<8));
+ hw->res_ch_flag = 0;
+ start_process_time(hw);
+ return;
+ }
}
- }
+ } else {
+ if (vh264_set_params(hw, param1,
+ param2, param3, param4) < 0)
+ dpb_print(DECODE_ID(hw), 0, "set parameters error\n");
- start_process_time(hw);
- return;
+ WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) |
+ (hw->dpb.mDPB.size<<16) |
+ (hw->dpb.mDPB.size<<8));
+ start_process_time(hw);
+ return;
+ }
} else
if (((hw->dec_result == DEC_RESULT_GET_DATA) ||
(hw->dec_result == DEC_RESULT_GET_DATA_RETRY))
@@ -8520,10 +8657,18 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
struct aml_vcodec_ctx *ctx =
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
- if (ctx->param_sets_from_ucode &&
- !ctx->v4l_codec_ready &&
- hw->v4l_params_parsed) {
- ret = 0; /*the params has parsed.*/
+ if (ctx->param_sets_from_ucode) {
+ if (hw->v4l_params_parsed) {
+ if (!ctx->v4l_codec_dpb_ready &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
+ } else {
+ if ((hw->res_ch_flag == 1) &&
+ ((ctx->state <= AML_STATE_INIT) ||
+ (ctx->state >= AML_STATE_FLUSHING)))
+ ret = 0;
+ }
} else if (!ctx->v4l_codec_dpb_ready) {
if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
run_ready_min_buf_num)
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
index 4edefe1..790cc9a 100644
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -1740,6 +1740,7 @@ struct hevc_state_s {
bool v4l_params_parsed;
u32 mem_map_mode;
struct vdec_info *gvs;
+ unsigned int res_ch_flag;
} /*hevc_stru_t */;
#ifdef AGAIN_HAS_THRESHOLD
@@ -1951,6 +1952,31 @@ static int get_double_write_mode(struct hevc_state_s *hevc)
return dw;
}
+static int v4l_parser_get_double_write_mode(struct hevc_state_s *hevc, int w, int h)
+{
+ u32 valid_dw_mode = get_valid_double_write_mode(hevc);
+ u32 dw = 0x1; /*1:1*/
+ switch (valid_dw_mode) {
+ case 0x100:
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ break;
+ case 0x200:
+ if (w > 1920 && h > 1088)
+ dw = 0x2; /*1:4*/
+ break;
+ case 0x300:
+ if (w > 1280 && h > 720)
+ dw = 0x4; /*1:2*/
+ break;
+ default:
+ dw = valid_dw_mode;
+ break;
+ }
+ return dw;
+}
+
+
static int get_double_write_ratio(struct hevc_state_s *hevc,
int dw_mode)
{
@@ -3286,7 +3312,57 @@ static int get_work_pic_num(struct hevc_state_s *hevc)
sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0
- hevc->sps_num_reorder_pics_0;
+#ifdef MULTI_INSTANCE_SUPPORT
+ /*
+ need one more for multi instance, as
+ apply_ref_pic_set() has no chanch to run to
+ to clear referenced flag in some case
+ */
+ if (hevc->m_ins_flag)
+ used_buf_num++;
+#endif
+ } else
+ used_buf_num = max_buf_num;
+
+ if (hevc->save_buffer_mode)
+ hevc_print(hevc, 0,
+ "save buf _mode : dynamic_buf_num_margin %d ----> %d \n",
+ dynamic_buf_num_margin, hevc->dynamic_buf_num_margin);
+
+ if (sps_pic_buf_diff >= 4)
+ used_buf_num += sps_pic_buf_diff;
+
+ if (hevc->is_used_v4l) {
+ /* for eos add more buffer to flush.*/
+ used_buf_num++;
+ }
+
+ if (used_buf_num > MAX_BUF_NUM)
+ used_buf_num = MAX_BUF_NUM;
+ return used_buf_num;
+}
+
+static int v4l_parser_work_pic_num(struct hevc_state_s *hevc)
+{
+ int used_buf_num = 0;
+ int sps_pic_buf_diff = 0;
+ pr_debug("margin = %d, sps_max_dec_pic_buffering_minus1_0 = %d, sps_num_reorder_pics_0 = %d\n",
+ get_dynamic_buf_num_margin(hevc),
+ hevc->param.p.sps_max_dec_pic_buffering_minus1_0,
+ hevc->param.p.sps_num_reorder_pics_0);
+ if (get_dynamic_buf_num_margin(hevc) > 0) {
+ if ((!hevc->param.p.sps_num_reorder_pics_0) &&
+ (hevc->param.p.sps_max_dec_pic_buffering_minus1_0)) {
+ /* the range of sps_num_reorder_pics_0 is in
+ [0, sps_max_dec_pic_buffering_minus1_0] */
+ used_buf_num = get_dynamic_buf_num_margin(hevc) +
+ hevc->param.p.sps_max_dec_pic_buffering_minus1_0;
+ } else
+ used_buf_num = hevc->param.p.sps_num_reorder_pics_0
+ + get_dynamic_buf_num_margin(hevc);
+ sps_pic_buf_diff = hevc->param.p.sps_max_dec_pic_buffering_minus1_0
+ - hevc->param.p.sps_num_reorder_pics_0;
#ifdef MULTI_INSTANCE_SUPPORT
/*
need one more for multi instance, as
@@ -3309,6 +3385,9 @@ static int get_work_pic_num(struct hevc_state_s *hevc)
used_buf_num += 1;
}
+ /* for eos add more buffer to flush.*/
+ used_buf_num++;
+
if (used_buf_num > MAX_BUF_NUM)
used_buf_num = MAX_BUF_NUM;
return used_buf_num;
@@ -5268,8 +5347,8 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
/* swap uv */
if (hevc->is_used_v4l) {
- if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) ||
- (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21M))
data32 &= ~(1 << 8); /* NV21 */
else
data32 |= (1 << 8); /* NV12 */
@@ -5311,8 +5390,8 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
/* swap uv */
if (hevc->is_used_v4l) {
- if ((v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21) ||
- (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21M))
data32 |= (1 << 12); /* NV21 */
else
data32 &= ~(1 << 12); /* NV12 */
@@ -6693,6 +6772,11 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
int lcu_y_num_div;
int Col_ref;
int dbg_skip_flag = 0;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+
+ if (hevc->is_used_v4l && ctx->param_sets_from_ucode)
+ hevc->res_ch_flag = 0;
if (hevc->wait_buf == 0) {
hevc->sps_num_reorder_pics_0 =
@@ -8549,7 +8633,16 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
struct vframe_s *vf = NULL;
int stream_offset = pic->stream_offset;
unsigned short slice_type = pic->slice_type;
+ ulong nv_order = VIDTYPE_VIU_NV21;
u32 frame_size = 0;
+ struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx;
+
+ /* swap uv */
+ if (hevc->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
if (force_disp_pic_index & 0x100) {
/*recycle directly*/
@@ -8709,7 +8802,8 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
}
if (pic->double_write_mode) {
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
+
if ((pic->double_write_mode == 3) &&
(!(IS_8K_SIZE(pic->width, pic->height)))) {
vf->type |= VIDTYPE_COMPRESS;
@@ -8774,7 +8868,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->bitdepth |= BITDEPTH_SAVING_MODE;
#else
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
vf->canvas0Addr = vf->canvas1Addr = spec2canvas(pic);
#endif
set_frame_info(hevc, vf, pic);
@@ -8875,14 +8969,14 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
if (pic->pic_struct == 3) {
vf->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf2->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21;
+ | nv_order;
} else {
vf->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf2->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21;
+ | nv_order;
}
hevc->vf_pre_count++;
decoder_do_frame_check(vdec, vf);
@@ -8920,18 +9014,18 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
if (pic->pic_struct == 5) {
vf->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf2->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf3->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21;
+ | nv_order;
} else {
vf->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf2->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21;
+ | nv_order;
vf3->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21;
+ | nv_order;
}
hevc->vf_pre_count++;
decoder_do_frame_check(vdec, vf);
@@ -8967,12 +9061,12 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->height <<= 1;
if (pic->pic_struct == 9) {
vf->type = VIDTYPE_INTERLACE_TOP
- | VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
+ | nv_order | VIDTYPE_VIU_FIELD;
process_pending_vframe(hevc,
hevc->pre_bot_pic, 0);
} else {
vf->type = VIDTYPE_INTERLACE_BOTTOM |
- VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
+ nv_order | VIDTYPE_VIU_FIELD;
vf->index = (pic->index << 8) | 0xff;
process_pending_vframe(hevc,
hevc->pre_top_pic, 1);
@@ -9003,10 +9097,10 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->height <<= 1;
if (pic->pic_struct == 11)
vf->type = VIDTYPE_INTERLACE_TOP |
- VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
+ nv_order | VIDTYPE_VIU_FIELD;
else {
vf->type = VIDTYPE_INTERLACE_BOTTOM |
- VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
+ nv_order | VIDTYPE_VIU_FIELD;
vf->index = (pic->index << 8) | 0xff;
}
decoder_do_frame_check(vdec, vf);
@@ -9040,14 +9134,14 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
case 1:
vf->height <<= 1;
vf->type = VIDTYPE_INTERLACE_TOP |
- VIDTYPE_VIU_NV21 | VIDTYPE_VIU_FIELD;
+ nv_order | VIDTYPE_VIU_FIELD;
process_pending_vframe(hevc, pic, 1);
hevc->pre_top_pic = pic;
break;
case 2:
vf->height <<= 1;
vf->type = VIDTYPE_INTERLACE_BOTTOM
- | VIDTYPE_VIU_NV21
+ | nv_order
| VIDTYPE_VIU_FIELD;
process_pending_vframe(hevc, pic, 0);
hevc->pre_bot_pic = pic;
@@ -9468,6 +9562,59 @@ static void read_decode_info(struct hevc_state_s *hevc)
hevc->rps_set_id = (decode_info >> 8) & 0xff;
}
+static int vh265_get_ps_info(struct hevc_state_s *hevc, int width, int height, struct aml_vdec_ps_infos *ps)
+{
+ int dw_mode = v4l_parser_get_double_write_mode(hevc, width, height);
+
+ ps->visible_width = width / get_double_write_ratio(hevc, dw_mode);
+ ps->visible_height = height / get_double_write_ratio(hevc, dw_mode);
+ ps->coded_width = ALIGN(width, 32) / get_double_write_ratio(hevc, dw_mode);
+ ps->coded_height = ALIGN(height, 32) / get_double_write_ratio(hevc, dw_mode);
+ ps->dpb_size = v4l_parser_work_pic_num(hevc);
+
+ return 0;
+}
+
+static int v4l_res_change(struct hevc_state_s *hevc, union param_u *rpm_param)
+{
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+ int ret = 0;
+
+ if (ctx->param_sets_from_ucode &&
+ hevc->res_ch_flag == 0) {
+ struct aml_vdec_ps_infos ps;
+ int width = rpm_param->p.pic_width_in_luma_samples;
+ int height = rpm_param->p.pic_height_in_luma_samples;
+ if ((hevc->pic_w != 0 &&
+ hevc->pic_h != 0) &&
+ (hevc->pic_w != width ||
+ hevc->pic_h != height)) {
+ hevc_print(hevc, 0,
+ "v4l_res_change Pic Width/Height Change (%d,%d)=>(%d,%d), interlace %d\n",
+ hevc->pic_w, hevc->pic_h,
+ width,
+ height,
+ hevc->interlace_flag);
+
+ vh265_get_ps_info(hevc, width, height, &ps);
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ vdec_v4l_res_ch_event(ctx);
+ hevc->v4l_params_parsed = false;
+ hevc->res_ch_flag = 1;
+ hevc->eos = 1;
+ flush_output(hevc, NULL);
+ //del_timer_sync(&hevc->timer);
+ notify_v4l_eos(hw_to_vdec(hevc));
+
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+
static irqreturn_t vh265_isr_thread_fn(int irq, void *data)
{
struct hevc_state_s *hevc = (struct hevc_state_s *) data;
@@ -10147,20 +10294,33 @@ force_output:
if (hevc->is_used_v4l) {
struct aml_vcodec_ctx *ctx =
(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+ if (!v4l_res_change(hevc, &hevc->param)) {
+ if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) {
+ struct aml_vdec_ps_infos ps;
+ int width = hevc->param.p.pic_width_in_luma_samples;
+ int height = hevc->param.p.pic_height_in_luma_samples;
+
+ pr_debug("set ucode parse\n");
+ vh265_get_ps_info(hevc, width, height, &ps);
+ /*notice the v4l2 codec.*/
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ hevc->v4l_params_parsed = true;
+ hevc->dec_result = DEC_RESULT_AGAIN;
+ amhevc_stop();
+ restore_decode_state(hevc);
+ reset_process_time(hevc);
+ vdec_schedule_work(&hevc->work);
+ return IRQ_HANDLED;
+ }
+ }else {
+ pr_debug("resolution change\n");
+ hevc->dec_result = DEC_RESULT_AGAIN;
+ amhevc_stop();
+ restore_decode_state(hevc);
+ reset_process_time(hevc);
+ vdec_schedule_work(&hevc->work);
+ return IRQ_HANDLED;
- if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) {
- struct aml_vdec_ps_infos ps;
-
- hevc->frame_width = hevc->param.p.pic_width_in_luma_samples;
- hevc->frame_height = hevc->param.p.pic_height_in_luma_samples;
- ps.visible_width = hevc->frame_width;
- ps.visible_height = hevc->frame_height;
- ps.coded_width = ALIGN(hevc->frame_width, 32);
- ps.coded_height = ALIGN(hevc->frame_height, 32);
- ps.dpb_size = get_work_pic_num(hevc);
- hevc->v4l_params_parsed = true;
- /*notice the v4l2 codec.*/
- vdec_v4l_set_ps_infos(ctx, &ps);
}
}
@@ -10536,7 +10696,8 @@ static void vh265_check_timer_func(struct timer_list *timer)
(get_dbg_flag(hevc) &
H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP) == 0 &&
hw_to_vdec(hevc)->next_status ==
- VDEC_STATUS_DISCONNECTED) {
+ VDEC_STATUS_DISCONNECTED &&
+ !hevc->is_used_v4l) {
hevc->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&hevc->work);
hevc_print(hevc,
@@ -12247,10 +12408,18 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
struct aml_vcodec_ctx *ctx =
(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
- if (ctx->param_sets_from_ucode &&
- !ctx->v4l_codec_ready &&
- hevc->v4l_params_parsed) {
- ret = 0; /*the params has parsed.*/
+ if (ctx->param_sets_from_ucode) {
+ if (hevc->v4l_params_parsed) {
+ if (!ctx->v4l_codec_dpb_ready &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
+ } else {
+ if ((hevc->res_ch_flag == 1) &&
+ ((ctx->state <= AML_STATE_INIT) ||
+ (ctx->state >= AML_STATE_FLUSHING)))
+ ret = 0;
+ }
} else if (!ctx->v4l_codec_dpb_ready) {
if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
run_ready_min_buf_num)
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index 5c9884c..35a6c75 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -313,9 +313,6 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
hw->v4l_params_parsed = true;
vdec_v4l_set_ps_infos(ctx, &ps);
}
-
- if (!ctx->v4l_codec_ready)
- return IRQ_HANDLED;
}
if (hw->is_used_v4l) {
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index c806cde..92abc02 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -50,6 +50,7 @@
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
#include "../utils/config_parser.h"
+#include <media/v4l2-mem2mem.h>
#define MEM_NAME "codec_mmpeg12"
#define CHECK_INTERVAL (HZ/100)
@@ -171,6 +172,9 @@ static struct vframe_s *vmpeg_vf_get(void *);
static void vmpeg_vf_put(struct vframe_s *, void *);
static int vmpeg_vf_states(struct vframe_states *states, void *);
static int vmpeg_event_cb(int type, void *data, void *private_data);
+static int notify_v4l_eos(struct vdec_s *vdec);
+
+
struct mmpeg2_userdata_record_t {
struct userdata_meta_info_t meta_info;
@@ -311,16 +315,19 @@ struct vdec_mpeg12_hw_s {
u32 dynamic_buf_num_margin;
struct vdec_info gvs;
struct vframe_qos_s vframe_qos;
+ unsigned int res_ch_flag;
};
static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
static void reset_process_time(struct vdec_mpeg12_hw_s *hw);
+static void flush_output(struct vdec_mpeg12_hw_s *hw);
static int debug_enable;
/*static struct work_struct userdata_push_work;*/
#undef pr_info
#define pr_info printk
unsigned int mpeg12_debug_mask = 0xff;
/*static int counter_max = 5;*/
+static u32 run_ready_min_buf_num = 2;
#define PRINT_FLAG_ERROR 0x0
#define PRINT_FLAG_RUN_FLOW 0X0001
@@ -412,8 +419,8 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
if (!hw->frame_width || !hw->frame_height) {
struct vdec_pic_info pic;
vdec_v4l_get_pic_info(ctx, &pic);
- hw->frame_width = pic.coded_width;
- hw->frame_height = pic.coded_height;
+ hw->frame_width = pic.visible_width;
+ hw->frame_height = pic.visible_height;
debug_print(DECODE_ID(hw), 0,
"[%d] set %d x %d from IF layer\n", ctx->id,
hw->frame_width, hw->frame_height);
@@ -523,9 +530,17 @@ static int find_free_buffer(struct vdec_mpeg12_hw_s *hw)
if (i == hw->buf_num)
return -1;
- if (hw->is_used_v4l)
- if (vmpeg12_v4l_alloc_buff_config_canvas(hw, i))
- return -1;
+ 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) {
+ /*run to parser csd data*/
+ i = 0;
+ } else {
+ if (vmpeg12_v4l_alloc_buff_config_canvas(hw, i))
+ return -1;
+ }
+ }
return i;
}
@@ -1504,15 +1519,22 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
u32 index = pic->index;
u32 info = pic->buffer_info;
struct vdec_s *vdec = hw_to_vdec(hw);
-
+ struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+ ulong nv_order = VIDTYPE_VIU_NV21;
user_data_ready_notify(hw, pic->pts, pic->pts_valid);
#ifdef NV21
- type = VIDTYPE_VIU_NV21;
+ type = nv_order;
#endif
+ /* swap uv */
+ if (hw->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
if (hw->frame_prog & PICINFO_PROG) {
field_num = 1;
- type |= VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
+ type |= VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | nv_order;
} else {
#ifdef INTERLACE_SEQ_ALWAYS
/* once an interlace seq, force interlace, to make di easy. */
@@ -1551,7 +1573,7 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
vf->duration_pulldown = (field_num == 3) ?
(vf->duration >> 1):0;
if (i > 0)
- type = VIDTYPE_VIU_NV21;
+ type = nv_order;
if (i == 1) /* second field*/
type |= (first_field_type == VIDTYPE_INTERLACE_TOP) ?
VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP;
@@ -1699,6 +1721,52 @@ static bool is_ref_error(struct vdec_mpeg12_hw_s *hw)
return 0;
}
+static int vmpeg2_get_ps_info(struct vdec_mpeg12_hw_s *hw, int width, int height, struct aml_vdec_ps_infos *ps)
+{
+ ps->visible_width = width;
+ ps->visible_height = height;
+ ps->coded_width = ALIGN(width, 64);
+ ps->coded_height = ALIGN(height, 32);
+ ps->dpb_size = hw->buf_num;
+
+ return 0;
+}
+
+static int v4l_res_change(struct vdec_mpeg12_hw_s *hw, int width, int height)
+{
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+ int ret = 0;
+
+ if (ctx->param_sets_from_ucode &&
+ hw->res_ch_flag == 0) {
+ struct aml_vdec_ps_infos ps;
+
+ if ((hw->frame_width != 0 &&
+ hw->frame_height != 0) &&
+ (hw->frame_width != width ||
+ hw->frame_height != height)) {
+ debug_print(DECODE_ID(hw), 0,
+ "v4l_res_change Pic Width/Height Change (%d,%d)=>(%d,%d)\n",
+ hw->frame_width, hw->frame_height,
+ width,
+ height);
+ vmpeg2_get_ps_info(hw, width, height, &ps);
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ vdec_v4l_res_ch_event(ctx);
+ hw->v4l_params_parsed = false;
+ hw->res_ch_flag = 1;
+ hw->eos = 1;
+ flush_output(hw);
+ notify_v4l_eos(hw_to_vdec(hw));
+
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
{
@@ -1722,6 +1790,38 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
return IRQ_HANDLED;
}
+ reg = READ_VREG(AV_SCRATCH_G);
+ if (reg == 1) {
+ if (hw->is_used_v4l) {
+ int frame_width = READ_VREG(MREG_PIC_WIDTH);
+ int frame_height = READ_VREG(MREG_PIC_HEIGHT);
+ if (!v4l_res_change(hw, frame_width, frame_height)) {
+ 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_ps_infos ps;
+
+ vmpeg2_get_ps_info(hw, frame_width, frame_height, &ps);
+ hw->v4l_params_parsed = true;
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ userdata_pushed_drop(hw);
+ reset_process_time(hw);
+ hw->dec_result = DEC_RESULT_AGAIN;
+ vdec_schedule_work(&hw->work);
+ } else {
+ WRITE_VREG(AV_SCRATCH_G, 0);
+ }
+ } else {
+ userdata_pushed_drop(hw);
+ reset_process_time(hw);
+ hw->dec_result = DEC_RESULT_AGAIN;
+ vdec_schedule_work(&hw->work);
+ }
+ } else
+ WRITE_VREG(AV_SCRATCH_G, 0);
+ return IRQ_HANDLED;
+ }
+
reg = READ_VREG(AV_SCRATCH_J);
if (reg & (1<<16)) {
vdec_schedule_work(&hw->userdata_push_work);
@@ -1794,26 +1894,6 @@ 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_ps_infos ps;
-
- ps.visible_width = hw->frame_width;
- ps.visible_height = hw->frame_height;
- ps.coded_width = ALIGN(hw->frame_width, 64);
- ps.coded_height = ALIGN(hw->frame_height, 32);
- ps.dpb_size = hw->buf_num;
- hw->v4l_params_parsed = true;
- vdec_v4l_set_ps_infos(ctx, &ps);
- }
-
- if (!ctx->v4l_codec_ready)
- return IRQ_HANDLED;
- }
-
new_pic->buffer_info = info;
new_pic->offset = offset;
new_pic->index = index;
@@ -1976,6 +2056,7 @@ static int notify_v4l_eos(struct vdec_s *vdec)
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
struct vframe_s *vf = NULL;
struct vdec_v4l2_buffer *fb = NULL;
+ int index;
if (hw->is_used_v4l && hw->eos) {
if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -1984,14 +2065,17 @@ static int notify_v4l_eos(struct vdec_s *vdec)
__func__);
return -1;
}
-
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
+ index = find_free_buffer(hw);
+ if ((index == -1) &&
+ vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
pr_err("[%d] get fb fail.\n", ctx->id);
return -1;
}
+ vf->type |= VIDTYPE_V4L_EOS;
vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
+ vf->v4l_mem_handle = (index == -1) ? (ulong)fb :
+ hw->pics[index].v4l_ref_buf_addr;
vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
@@ -2632,7 +2716,13 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
/* clear error count */
WRITE_VREG(MREG_ERROR_COUNT, 0);
- WRITE_VREG(MREG_FATAL_ERROR, 0);
+ /*Use MREG_FATAL_ERROR bit1, the ucode determine
+ whether to report the interruption of width and
+ height information,in order to be compatible
+ with the old version of ucode.
+ 1: Report the width and height information
+ 0: Not Report*/
+ WRITE_VREG(MREG_FATAL_ERROR, 1 << 1);
/* clear wait buffer status */
WRITE_VREG(MREG_WAIT_BUFFER, 0);
#ifdef NV21
@@ -2644,6 +2734,8 @@ static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
&& (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21
|| v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+ else
+ CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
if (!hw->ctx_valid)
WRITE_VREG(AV_SCRATCH_J, hw->userdata_wp_ctx);
@@ -2815,6 +2907,30 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
}
#endif
+ if (hw->is_used_v4l) {
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ if (ctx->param_sets_from_ucode) {
+ if (hw->v4l_params_parsed) {
+ if (!ctx->v4l_codec_dpb_ready &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ if (!ctx->v4l_codec_dpb_ready)
+ return 0;
+ } else {
+ if ((hw->res_ch_flag == 1) &&
+ ((ctx->state <= AML_STATE_INIT) ||
+ (ctx->state >= AML_STATE_FLUSHING)))
+ return 0;
+ }
+ } else if (!ctx->v4l_codec_dpb_ready) {
+ if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ return 0;
+ }
+ }
+
if (!is_enough_free_buffer(hw)) {
hw->buffer_not_ready++;
return 0;
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index b1a5911..d53689d 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -48,6 +48,7 @@
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
#include "../utils/config_parser.h"
+#include <media/v4l2-mem2mem.h>
#define DRIVER_NAME "ammvdec_mpeg4"
#define MODULE_NAME "ammvdec_mpeg4"
@@ -82,6 +83,7 @@
#define MP4_OFFSET_REG AV_SCRATCH_C
#define MP4_SYS_RATE AV_SCRATCH_E
#define MEM_OFFSET_REG AV_SCRATCH_F
+#define MP4_PIC_INFO AV_SCRATCH_H
#define PARC_FORBIDDEN 0
#define PARC_SQUARE 1
@@ -137,6 +139,8 @@ static struct vframe_s *vmpeg_vf_get(void *);
static void vmpeg_vf_put(struct vframe_s *, void *);
static int vmpeg_vf_states(struct vframe_states *states, void *);
static int vmpeg_event_cb(int type, void *data, void *private_data);
+static int notify_v4l_eos(struct vdec_s *vdec);
+
static int pre_decode_buf_level = 0x800;
static int start_decode_buf_level = 0x4000;
static int debug_enable;
@@ -156,6 +160,8 @@ static u32 without_display_mode;
#undef pr_info
#define pr_info printk
unsigned int mpeg4_debug_mask = 0xff;
+static u32 run_ready_min_buf_num = 2;
+
#define PRINT_FLAG_ERROR 0x0
#define PRINT_FLAG_RUN_FLOW 0X0001
@@ -313,11 +319,13 @@ struct vdec_mpeg4_hw_s {
bool v4l_params_parsed;
u32 buf_num;
u32 dynamic_buf_num_margin;
+ unsigned int res_ch_flag;
};
static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw);
static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw);
static unsigned char
get_data_check_sum(struct vdec_mpeg4_hw_s *hw, int size);
+static void flush_output(struct vdec_mpeg4_hw_s * hw);
#define PROVIDER_NAME "vdec.mpeg4"
@@ -361,11 +369,13 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i
{
int ret;
u32 canvas;
- ulong decbuf_start = 0;
- int decbuf_y_size = 0;
+ ulong decbuf_start = 0, decbuf_uv_start = 0;
+ int decbuf_y_size = 0, decbuf_uv_size = 0;
u32 canvas_width = 0, canvas_height = 0;
struct vdec_s *vdec = hw_to_vdec(hw);
struct vdec_v4l2_buffer *fb = NULL;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (hw->pic[i].v4l_ref_buf_addr)
return 0;
@@ -379,20 +389,34 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i
return ret;
}
+ if (!hw->frame_width || !hw->frame_height) {
+ struct vdec_pic_info pic;
+ vdec_v4l_get_pic_info(ctx, &pic);
+ hw->frame_width = pic.visible_width;
+ hw->frame_height = pic.visible_height;
+ mmpeg4_debug_print(DECODE_ID(hw), 0,
+ "[%d] set %d x %d from IF layer\n", ctx->id,
+ hw->frame_width, hw->frame_height);
+ }
+
hw->pic[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;
+ decbuf_uv_start = decbuf_start + decbuf_y_size;
+ decbuf_uv_size = decbuf_y_size / 2;
canvas_width = ALIGN(hw->frame_width, 64);
- canvas_height = ALIGN(hw->frame_height, 32);
+ canvas_height = ALIGN(hw->frame_height, 64);
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;
+ decbuf_uv_start = fb->m.mem[1].addr;
+ decbuf_uv_size = fb->m.mem[1].size;
canvas_width = ALIGN(hw->frame_width, 64);
- canvas_height = ALIGN(hw->frame_height, 32);
+ canvas_height = ALIGN(hw->frame_height, 64);
fb->m.mem[0].bytes_used = decbuf_y_size;
- fb->m.mem[1].bytes_used = decbuf_y_size << 1;
+ fb->m.mem[1].bytes_used = decbuf_uv_size;
}
mmpeg4_debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n",
@@ -429,7 +453,7 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i
&hw->canvas_config[i][0]);
hw->canvas_config[i][1].phy_addr =
- decbuf_start + decbuf_y_size;
+ decbuf_uv_start;
hw->canvas_config[i][1].width = canvas_width;
hw->canvas_config[i][1].height = (canvas_height >> 1);
hw->canvas_config[i][1].block_mode = hw->blkmode;
@@ -467,9 +491,18 @@ static int find_free_buffer(struct vdec_mpeg4_hw_s *hw)
if (i == hw->buf_num)
return -1;
- if (hw->is_used_v4l)
- if (vmpeg4_v4l_alloc_buff_config_canvas(hw, i))
- return -1;
+ 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) {
+ /*run to parser csd data*/
+ i = 0;
+ } else {
+ if (vmpeg4_v4l_alloc_buff_config_canvas(hw, i))
+ return -1;
+ }
+ }
+
return i;
}
@@ -618,8 +651,17 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
{
struct vframe_s *vf = NULL;
struct vdec_s *vdec = hw_to_vdec(hw);
+ struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+ ulong nv_order = VIDTYPE_VIU_NV21;
int index = pic->index;
+ /* swap uv */
+ if (hw->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
+
if (pic->pic_info & INTERLACE_FLAG) {
if (kfifo_get(&hw->newframe_q, &vf) == 0) {
mmpeg4_debug_print(DECODE_ID(hw), 0,
@@ -649,7 +691,7 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ?
VIDTYPE_INTERLACE_TOP : VIDTYPE_INTERLACE_BOTTOM;
#ifdef NV21
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
#endif
set_frame_info(hw, vf, pic->index);
@@ -701,7 +743,7 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ?
VIDTYPE_INTERLACE_BOTTOM : VIDTYPE_INTERLACE_TOP;
#ifdef NV21
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
#endif
set_frame_info(hw, vf, pic->index);
@@ -762,7 +804,7 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
pic->duration;
#ifdef NV21
vf->type = VIDTYPE_PROGRESSIVE |
- VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21;
+ VIDTYPE_VIU_FIELD | nv_order;
#else
vf->type = VIDTYPE_PROGRESSIVE |
VIDTYPE_VIU_FIELD;
@@ -867,6 +909,53 @@ static void vmpeg4_prepare_input(struct vdec_mpeg4_hw_s *hw)
}
}
+static int vmpeg4_get_ps_info(struct vdec_mpeg4_hw_s *hw, int width, int height, struct aml_vdec_ps_infos *ps)
+{
+ ps->visible_width = width;
+ ps->visible_height = height;
+ ps->coded_width = ALIGN(width, 64);
+ ps->coded_height = ALIGN(height, 64);
+ ps->dpb_size = hw->buf_num;
+
+ return 0;
+}
+
+static int v4l_res_change(struct vdec_mpeg4_hw_s *hw, int width, int height)
+{
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+ int ret = 0;
+
+ if (ctx->param_sets_from_ucode &&
+ hw->res_ch_flag == 0) {
+ struct aml_vdec_ps_infos ps;
+
+ if ((hw->frame_width != 0 &&
+ hw->frame_height != 0) &&
+ (hw->frame_width != width ||
+ hw->frame_height != height)) {
+ mmpeg4_debug_print(DECODE_ID(hw), 0,
+ "v4l_res_change Pic Width/Height Change (%d,%d)=>(%d,%d)\n",
+ hw->frame_width, hw->frame_height,
+ width,
+ height);
+ vmpeg4_get_ps_info(hw, width, height, &ps);
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ vdec_v4l_res_ch_event(ctx);
+ hw->v4l_params_parsed = false;
+ hw->res_ch_flag = 1;
+ hw->eos = 1;
+ flush_output(hw);
+ notify_v4l_eos(hw_to_vdec(hw));
+
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+
static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
{
u32 reg;
@@ -882,6 +971,35 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
if (hw->eos)
return IRQ_HANDLED;
+ if (READ_VREG(MP4_PIC_INFO) == 1) {
+ if (hw->is_used_v4l) {
+ int frame_width = READ_VREG(MP4_PIC_WH)>> 16;
+ int frame_height = READ_VREG(MP4_PIC_WH) & 0xffff;
+ if (!v4l_res_change(hw, frame_width, frame_height)) {
+ 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_ps_infos ps;
+
+ vmpeg4_get_ps_info(hw, frame_width, frame_height, &ps);
+ hw->v4l_params_parsed = true;
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ reset_process_time(hw);
+ hw->dec_result = DEC_RESULT_AGAIN;
+ vdec_schedule_work(&hw->work);
+ } else {
+ WRITE_VREG(MP4_PIC_INFO, 0);
+ }
+ } else {
+ reset_process_time(hw);
+ hw->dec_result = DEC_RESULT_AGAIN;
+ vdec_schedule_work(&hw->work);
+ }
+ } else
+ WRITE_VREG(MP4_PIC_INFO, 0);
+ return IRQ_HANDLED;
+ }
+
WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
if (READ_VREG(AV_SCRATCH_M) != 0 &&
(debug_enable & PRINT_FLAG_UCODE_DETAIL)) {
@@ -979,26 +1097,6 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
if (dec_h != 0)
hw->frame_height = dec_h;
- 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_ps_infos ps;
-
- ps.visible_width = hw->frame_width;
- ps.visible_height = hw->frame_height;
- ps.coded_width = ALIGN(hw->frame_width, 64);
- ps.coded_height = ALIGN(hw->frame_height, 64);
- ps.dpb_size = hw->buf_num;
- hw->v4l_params_parsed = true;
- vdec_v4l_set_ps_infos(ctx, &ps);
- }
-
- if (!ctx->v4l_codec_ready)
- return IRQ_HANDLED;
- }
-
if (hw->vmpeg4_amstream_dec_info.rate == 0) {
if (vop_time_inc < hw->last_vop_time_inc) {
duration = vop_time_inc +
@@ -1293,6 +1391,7 @@ static int notify_v4l_eos(struct vdec_s *vdec)
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
struct vframe_s *vf = NULL;
struct vdec_v4l2_buffer *fb = NULL;
+ int index;
if (hw->is_used_v4l && hw->eos) {
if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -1302,13 +1401,18 @@ static int notify_v4l_eos(struct vdec_s *vdec)
return -1;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
+ index = find_free_buffer(hw);
+
+ if ((index == -1) &&
+ vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
pr_err("[%d] get fb fail.\n", ctx->id);
return -1;
}
+ vf->type |= VIDTYPE_V4L_EOS;
vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
+ vf->v4l_mem_handle = (index == -1) ? (ulong)fb :
+ hw->pic[index].v4l_ref_buf_addr;;
vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
@@ -1393,6 +1497,15 @@ static void vmpeg4_work(struct work_struct *work)
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
+ 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)
+ vdec_v4l_write_frame_sync(ctx);
+ }
+
/* mark itself has all HW resource released and input released */
if (vdec->parallel_dec == 1)
vdec_core_finish_run(vdec, CORE_MASK_VDEC_1);
@@ -1929,8 +2042,14 @@ static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw)
hw->vmpeg4_rotation =
(((unsigned long)hw->vmpeg4_amstream_dec_info.param) >> 16) & 0xffff;
hw->sys_mp4_rate = hw->vmpeg4_amstream_dec_info.rate;
- hw->frame_width = hw->vmpeg4_amstream_dec_info.width;
- hw->frame_height = hw->vmpeg4_amstream_dec_info.height;
+ if (hw->is_used_v4l) {
+ hw->frame_width = 0;
+ hw->frame_height = 0;
+ } else {
+ hw->frame_width = hw->vmpeg4_amstream_dec_info.width;
+ hw->frame_height = hw->vmpeg4_amstream_dec_info.height;
+ }
+
hw->frame_dur = 0;
hw->frame_prog = 0;
hw->unstable_pts =
@@ -2072,6 +2191,29 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
}
}
+ if (hw->is_used_v4l) {
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ if (ctx->param_sets_from_ucode) {
+ if (hw->v4l_params_parsed) {
+ if (!ctx->v4l_codec_dpb_ready &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ return 0;
+ } else {
+ if ((hw->res_ch_flag == 1) &&
+ ((ctx->state <= AML_STATE_INIT) ||
+ (ctx->state >= AML_STATE_FLUSHING)))
+ return 0;
+ }
+ } else if (!ctx->v4l_codec_dpb_ready) {
+ if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ return 0;
+ }
+ }
+
if (!is_enough_free_buffer(hw)) {
hw->buffer_not_ready++;
return 0;
@@ -2348,9 +2490,29 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
hw->vmpeg4_amstream_dec_info.width,
hw->vmpeg4_amstream_dec_info.height,
hw->vmpeg4_amstream_dec_info.rate);
- hw->is_used_v4l = (((unsigned long)
- hw->vmpeg4_amstream_dec_info.param & 0x80) >> 7);
}
+ if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
+ mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
+ "pdata->config: %s\n", pdata->config);
+ if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ hw->dynamic_buf_num_margin = config_val;
+ else
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ hw->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_canvas_mem_mode",
+ &config_val) == 0)
+ hw->blkmode = config_val;
+ } else
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+
+ hw->buf_num = vmpeg4_get_buf_num(hw);
if (vmmpeg4_init(hw) < 0) {
pr_err("%s init failed.\n", __func__);
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index 983869f..a8a4b74 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -1171,6 +1171,13 @@ int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count)
}
EXPORT_SYMBOL(vdec_write_vframe);
+int vdec_write_vframe_with_dma(struct vdec_s *vdec,
+ ulong addr, size_t count, u32 handle)
+{
+ return vdec_input_add_frame_with_dma(&vdec->input, addr, count, handle);
+}
+EXPORT_SYMBOL(vdec_write_vframe_with_dma);
+
/* add a work queue thread for vdec*/
void vdec_schedule_work(struct work_struct *work)
{
diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h
index 8b0aaf2..9d1045a 100644
--- a/drivers/frame_provider/decoder/utils/vdec.h
+++ b/drivers/frame_provider/decoder/utils/vdec.h
@@ -323,6 +323,9 @@ extern int vdec_set_receive_id(struct vdec_s *vdec, int receive_id);
extern int vdec_write_vframe(struct vdec_s *vdec, const char *buf,
size_t count);
+extern int vdec_write_vframe_with_dma(struct vdec_s *vdec,
+ ulong addr, size_t count, u32 handle);
+
/* mark the vframe_chunk as consumed */
extern void vdec_vframe_dirty(struct vdec_s *vdec,
struct vframe_chunk_s *chunk);
diff --git a/drivers/frame_provider/decoder/utils/vdec_input.c b/drivers/frame_provider/decoder/utils/vdec_input.c
index 4965cff..da663b6 100644
--- a/drivers/frame_provider/decoder/utils/vdec_input.c
+++ b/drivers/frame_provider/decoder/utils/vdec_input.c
@@ -973,6 +973,16 @@ int vdec_input_add_frame(struct vdec_input_s *input, const char *buf,
}
EXPORT_SYMBOL(vdec_input_add_frame);
+int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr,
+ size_t count, u32 handle)
+{
+ struct vdec_s *vdec = input->vdec;
+
+ return vdec_secure(vdec) ?
+ vdec_input_add_chunk(input, (char *)addr, count, handle) : -1;
+}
+EXPORT_SYMBOL(vdec_input_add_frame_with_dma);
+
struct vframe_chunk_s *vdec_input_next_chunk(struct vdec_input_s *input)
{
struct vframe_chunk_s *chunk = NULL;
diff --git a/drivers/frame_provider/decoder/utils/vdec_input.h b/drivers/frame_provider/decoder/utils/vdec_input.h
index 26ccb49..4e871e7 100644
--- a/drivers/frame_provider/decoder/utils/vdec_input.h
+++ b/drivers/frame_provider/decoder/utils/vdec_input.h
@@ -143,6 +143,9 @@ extern int vdec_input_set_buffer(struct vdec_input_s *input, u32 start,
extern int vdec_input_add_frame(struct vdec_input_s *input, const char *buf,
size_t count);
+extern int vdec_input_add_frame_with_dma(struct vdec_input_s *input, ulong addr,
+ size_t count, u32 handle);
+
/* Peek next frame data from decoder's input */
extern struct vframe_chunk_s *vdec_input_next_chunk(
struct vdec_input_s *input);
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
index 88d2947..e99d59b 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -1,4 +1,11 @@
#include "vdec_v4l2_buffer_ops.h"
+#include <media/v4l2-mem2mem.h>
+#include <linux/printk.h>
+
+#ifndef CONFIG_AMLOGIC_MEDIA_V4L_DEC
+static void v4l2_m2m_job_pause(struct v4l2_m2m_dev *m2m_dev,
+ struct v4l2_m2m_ctx *m2m_ctx) { return; }
+#endif
int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
struct vdec_v4l2_buffer **out)
@@ -60,6 +67,52 @@ int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx,
}
EXPORT_SYMBOL(vdec_v4l_set_hdr_infos);
+static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx)
+{
+ ulong expires;
+
+ expires = jiffies + msecs_to_jiffies(1000);
+ while (!ctx->v4l_codec_dpb_ready) {
+ u32 ready_num = 0;
+
+ if (time_after(jiffies, expires)) {
+ pr_err("the DPB state has not ready.\n");
+ break;
+ }
+
+ ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+ if ((ready_num + ctx->buf_used_count) >= ctx->dpb_size)
+ ctx->v4l_codec_dpb_ready = true;
+ }
+}
+
+void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
+{
+ unsigned int dpbsize = 0;
+ int ret;
+
+ if (ctx->dec_if->get_param(ctx->drv_handle, GET_PARAM_PIC_INFO, &ctx->last_decoded_picinfo)) {
+ pr_err("Cannot get param : GET_PARAM_PICTURE_INFO ERR\n");
+ return;
+ }
+
+ if (ctx->last_decoded_picinfo.visible_width == 0 ||
+ ctx->last_decoded_picinfo.visible_height == 0 ||
+ ctx->last_decoded_picinfo.coded_width == 0 ||
+ ctx->last_decoded_picinfo.coded_height == 0) {
+ pr_err("Cannot get correct pic info\n");
+ return;
+ }
+
+ ret = ctx->dec_if->get_param(ctx->drv_handle, GET_PARAM_DPB_SIZE, &dpbsize);
+ if (dpbsize == 0)
+ pr_err("Incorrect dpb size, ret=%d\n", ret);
+
+ /* update picture information */
+ ctx->dpb_size = dpbsize;
+ ctx->picinfo = ctx->last_decoded_picinfo;
+}
+
int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event)
{
int ret = 0;
@@ -75,6 +128,35 @@ int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event)
}
EXPORT_SYMBOL(vdec_v4l_post_evet);
+int vdec_v4l_res_ch_event(struct aml_vcodec_ctx *ctx)
+{
+ int ret = 0;
+ struct aml_vcodec_dev *dev = ctx->dev;
+
+ if (ctx->drv_handle == 0)
+ return -EIO;
+
+ /* wait the DPB state to be ready. */
+ aml_wait_dpb_ready(ctx);
+
+ aml_vdec_pic_info_update(ctx);
+
+ mutex_lock(&ctx->state_lock);
+
+ ctx->state = AML_STATE_FLUSHING;/*prepare flushing*/
+
+ pr_info("[%d]: vcodec state (AML_STATE_FLUSHING-RESCHG)\n", ctx->id);
+
+ mutex_unlock(&ctx->state_lock);
+
+ ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
+ v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+
+ return ret;
+}
+EXPORT_SYMBOL(vdec_v4l_res_ch_event);
+
+
int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx)
{
int ret = 0;
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
index 6254509..8bedb88 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
@@ -27,4 +27,7 @@ int vdec_v4l_post_evet(
struct aml_vcodec_ctx *ctx,
u32 event);
+int vdec_v4l_res_ch_event(
+ struct aml_vcodec_ctx *ctx);
+
#endif
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index 43f1376..d27b6ef 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -1197,6 +1197,7 @@ struct VP9Decoder_s {
u32 mem_map_mode;
u32 dynamic_buf_num_margin;
struct vframe_s vframe_dummy;
+ unsigned int res_ch_flag;
};
static int vp9_print(struct VP9Decoder_s *pbi,
@@ -1595,6 +1596,41 @@ static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi)
(double_write_mode & 0x7fffffff);
}
+static int v4l_parser_get_double_write_mode(struct VP9Decoder_s *pbi)
+{
+ u32 valid_dw_mode = get_valid_double_write_mode(pbi);
+ u32 dw;
+ int w, h;
+
+ /* mask for supporting double write value bigger than 0x100 */
+ if (valid_dw_mode & 0xffffff00) {
+ w = pbi->frame_width;
+ h = pbi->frame_height;
+
+ dw = 0x1; /*1:1*/
+ switch (valid_dw_mode) {
+ case 0x100:
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ break;
+ case 0x200:
+ if (w > 1920 && h > 1088)
+ dw = 0x2; /*1:4*/
+ break;
+ case 0x300:
+ if (w > 1280 && h > 720)
+ dw = 0x4; /*1:2*/
+ break;
+ default:
+ break;
+ }
+ return dw;
+ }
+
+ return valid_dw_mode;
+}
+
+
static int get_double_write_mode(struct VP9Decoder_s *pbi)
{
u32 valid_dw_mode = get_valid_double_write_mode(pbi);
@@ -7038,6 +7074,8 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
struct vdec_s *pvdec = hw_to_vdec(pbi);
int stream_offset = pic_config->stream_offset;
unsigned short slice_type = pic_config->slice_type;
+ struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx;
+ ulong nv_order = VIDTYPE_VIU_NV21;
u32 pts_valid = 0, pts_us64_valid = 0;
u32 pts_save;
u64 pts_us64_save;
@@ -7050,6 +7088,13 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
return -1;
}
+ /* swap uv */
+ if (pbi->is_used_v4l) {
+ if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+ (v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+ nv_order = VIDTYPE_VIU_NV12;
+ }
+
if (pic_config->double_write_mode)
set_canvas(pbi, pic_config);
@@ -7199,7 +7244,7 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
if (pic_config->double_write_mode) {
vf->type = VIDTYPE_PROGRESSIVE |
VIDTYPE_VIU_FIELD;
- vf->type |= VIDTYPE_VIU_NV21;
+ vf->type |= nv_order;
if ((pic_config->double_write_mode == 3) &&
(!IS_8K_SIZE(pic_config->y_crop_width,
pic_config->y_crop_height))) {
@@ -7515,8 +7560,11 @@ int continue_decoding(struct VP9Decoder_s *pbi)
int ret;
int i;
struct VP9_Common_s *const cm = &pbi->common;
+ struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
debug_buffer_mgr_more(pbi);
+ if (pbi->is_used_v4l && ctx->param_sets_from_ucode)
+ pbi->res_ch_flag = 0;
bit_depth_luma = vp9_param.p.bit_depth;
bit_depth_chroma = vp9_param.p.bit_depth;
@@ -8150,6 +8198,54 @@ static void get_picture_qos_info(struct VP9Decoder_s *pbi)
}
}
+static int vvp9_get_ps_info(struct VP9Decoder_s *pbi, struct aml_vdec_ps_infos *ps)
+{
+ int dw_mode = v4l_parser_get_double_write_mode(pbi);
+
+ ps->visible_width = pbi->frame_width / get_double_write_ratio(pbi, dw_mode);
+ ps->visible_height = pbi->frame_height / get_double_write_ratio(pbi, dw_mode);
+ ps->coded_width = ALIGN(pbi->frame_width, 32) / get_double_write_ratio(pbi, dw_mode);
+ ps->coded_height = ALIGN(pbi->frame_height, 32) / get_double_write_ratio(pbi, dw_mode);
+ ps->dpb_size = pbi->used_buf_num;
+
+ return 0;
+}
+
+
+static int v4l_res_change(struct VP9Decoder_s *pbi)
+{
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+ struct VP9_Common_s *const cm = &pbi->common;
+ int ret = 0;
+
+ if (ctx->param_sets_from_ucode &&
+ pbi->res_ch_flag == 0) {
+ struct aml_vdec_ps_infos ps;
+ if ((cm->width != 0 &&
+ cm->height != 0) &&
+ (pbi->frame_width != cm->width ||
+ pbi->frame_height != cm->height)) {
+
+ vp9_print(pbi, 0, "%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width,
+ cm->height, pbi->frame_width, pbi->frame_height);
+ vvp9_get_ps_info(pbi, &ps);
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ vdec_v4l_res_ch_event(ctx);
+ pbi->v4l_params_parsed = false;
+ pbi->res_ch_flag = 1;
+ pbi->eos = 1;
+ vp9_bufmgr_postproc(pbi);
+ //del_timer_sync(&pbi->timer);
+ notify_v4l_eos(hw_to_vdec(pbi));
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+
static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
{
struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data;
@@ -8376,27 +8472,31 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
pbi->frame_width = vp9_param.p.width;
pbi->frame_height = vp9_param.p.height;
- if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) {
- struct aml_vdec_ps_infos ps;
-
- ps.visible_width = pbi->frame_width;
- ps.visible_height = pbi->frame_height;
- ps.coded_width = ALIGN(pbi->frame_width, 32);
- ps.coded_height = ALIGN(pbi->frame_height, 32);
- ps.dpb_size = pbi->used_buf_num;
- pbi->v4l_params_parsed = true;
- vdec_v4l_set_ps_infos(ctx, &ps);
+ if (!v4l_res_change(pbi)) {
+ if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) {
+ struct aml_vdec_ps_infos ps;
+
+ pr_debug("set ucode parse\n");
+ vvp9_get_ps_info(pbi, &ps);
+ /*notice the v4l2 codec.*/
+ vdec_v4l_set_ps_infos(ctx, &ps);
+ pbi->v4l_params_parsed = true;
+ pbi->postproc_done = 0;
+ pbi->process_busy = 0;
+ dec_again_process(pbi);
+ return IRQ_HANDLED;
+ }
+ } else {
+ pbi->postproc_done = 0;
+ pbi->process_busy = 0;
+ dec_again_process(pbi);
+ return IRQ_HANDLED;
}
}
- if (pbi->is_used_v4l) {
- pbi->dec_result = DEC_V4L2_CONTINUE_DECODING;
- vdec_schedule_work(&pbi->work);
- } else {
- continue_decoding(pbi);
- pbi->postproc_done = 0;
- pbi->process_busy = 0;
- }
+ continue_decoding(pbi);
+ pbi->postproc_done = 0;
+ pbi->process_busy = 0;
#ifdef MULTI_INSTANCE_SUPPORT
if (pbi->m_ins_flag)
@@ -8567,7 +8667,8 @@ static void vvp9_put_timer_func(struct timer_list *timer)
if (pbi->m_ins_flag) {
if (hw_to_vdec(pbi)->next_status
- == VDEC_STATUS_DISCONNECTED) {
+ == VDEC_STATUS_DISCONNECTED &&
+ !pbi->is_used_v4l) {
#ifdef SUPPORT_FB_DECODING
if (pbi->run2_busy)
return;
@@ -9558,25 +9659,6 @@ static void vp9_work(struct work_struct *work)
return;
}
- if (pbi->dec_result == DEC_V4L2_CONTINUE_DECODING) {
- struct aml_vcodec_ctx *ctx =
- (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
-
- if (ctx->param_sets_from_ucode) {
- reset_process_time(pbi);
- if (wait_event_interruptible_timeout(ctx->wq,
- ctx->v4l_codec_ready,
- msecs_to_jiffies(500)) < 0)
- return;
- }
-
- continue_decoding(pbi);
- pbi->postproc_done = 0;
- pbi->process_busy = 0;
-
- return;
- }
-
if (((pbi->dec_result == DEC_RESULT_GET_DATA) ||
(pbi->dec_result == DEC_RESULT_GET_DATA_RETRY))
&& (hw_to_vdec(pbi)->next_status !=
@@ -9845,10 +9927,18 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
struct aml_vcodec_ctx *ctx =
(struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
- if (ctx->param_sets_from_ucode &&
- !ctx->v4l_codec_ready &&
- pbi->v4l_params_parsed) {
- ret = 0; /*the params has parsed.*/
+ if (ctx->param_sets_from_ucode) {
+ if (pbi->v4l_params_parsed) {
+ if ((ctx->cap_pool.in < pbi->used_buf_num) &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
+ } else {
+ if ((pbi->res_ch_flag == 1) &&
+ ((ctx->state <= AML_STATE_INIT) ||
+ (ctx->state >= AML_STATE_FLUSHING)))
+ ret = 0;
+ }
} else if (ctx->cap_pool.in < ctx->dpb_size) {
if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
run_ready_min_buf_num)