summaryrefslogtreecommitdiff
authorLiang Ji <liang.ji@amlogic.com>2020-01-16 07:32:35 (GMT)
committer Liang Ji <liang.ji@amlogic.com>2020-01-16 07:43:59 (GMT)
commitaac901b9cf2199375959d6ca4467ae09efa96898 (patch)
tree86717d325b4abbdea84edd1c407e17cf4bf07548
parentc94bdbfa64b4786a4f4984b5792155f216b8fe87 (diff)
parent49c06502c900f3fd27e878e04881d499b4788396 (diff)
downloadmedia_modules-aac901b9cf2199375959d6ca4467ae09efa96898.zip
media_modules-aac901b9cf2199375959d6ca4467ae09efa96898.tar.gz
media_modules-aac901b9cf2199375959d6ca4467ae09efa96898.tar.bz2
Merge branch 'amlogic/sabrina' into sabrina
Change-Id: I4b846532af1c37958576110282004672d7d8182e Signed-off-by: Liang Ji <liang.ji@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c37
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h5
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c466
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h16
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c226
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h120
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.c15
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.h1
-rw-r--r--drivers/amvdec_ports/decoder/aml_h264_parser.c32
-rw-r--r--drivers/amvdec_ports/decoder/aml_hevc_parser.c11
-rw-r--r--drivers/amvdec_ports/decoder/vdec_h264_if.c276
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c277
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c32
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c36
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c40
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c318
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h9
-rw-r--r--drivers/frame_provider/decoder/avs2/vavs2.c11
-rw-r--r--drivers/frame_provider/decoder/h264/vh264_mvc.c38
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c444
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c664
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c92
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c135
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c99
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_bmmu_box.c47
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_bmmu_box.h3
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_mmu_box.c55
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_mmu_box.h2
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c123
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.h2
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c111
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h14
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c481
-rw-r--r--drivers/frame_sink/encoder/h264/encoder.c58
-rw-r--r--drivers/stream_input/parser/hw_demux/aml_dmx.c89
-rw-r--r--firmware/video_ucode.bin454
36 files changed, 3563 insertions, 1276 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
index f4bfc55..da5637d 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -120,7 +120,7 @@ static void set_default_params(struct aml_vdec_adapt *vdec)
vdec->dec_prop.param = (void *)sync_mode;
vdec->dec_prop.format = vdec->format;
vdec->dec_prop.width = 1920;
- vdec->dec_prop.height = 1080;
+ vdec->dec_prop.height = 1088;
vdec->dec_prop.rate = 3200;
}
@@ -511,6 +511,11 @@ static void set_vdec_properity(struct vdec_s *vdec,
vdec->port->flag = vdec->port_flag;
ada_ctx->vfm_path = vdec->frame_base_video_path;
+
+ vdec->config_len = ada_ctx->config.length >
+ PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length;
+ memcpy(vdec->config, ada_ctx->config.buf, vdec->config_len);
+
ada_ctx->vdec = vdec;
}
@@ -660,14 +665,11 @@ int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
return ret;
}
-int is_need_to_buf(struct aml_vdec_adapt *ada_ctx)
+bool vdec_input_full(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = ada_ctx->vdec;
- if (vdec->input.have_frame_num > 8)
- return 0;
- else
- return 1;
+ return (vdec->input.have_frame_num > 600) ? true : false;
}
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
@@ -690,7 +692,7 @@ int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
/* dump to file */
dump_write(buf, count);
#endif
- aml_v4l2_debug(4, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x",
+ aml_v4l2_debug(3, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x",
ada_ctx->ctx->id, buf, count, ret, crc32_le(0, buf, count));
return ret;
@@ -704,14 +706,22 @@ void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx)
vdec_set_eos(vdec, true);
}
-int aml_codec_reset(struct aml_vdec_adapt *ada_ctx)
+int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *mode)
{
struct vdec_s *vdec = ada_ctx->vdec;
int ret = 0;
if (vdec) {
vdec_set_eos(vdec, false);
- ret = vdec_reset(vdec);
+
+ if (*mode == V4L_RESET_MODE_NORMAL &&
+ vdec->input.have_frame_num == 0)
+ *mode = V4L_RESET_MODE_LIGHT;
+
+ aml_v4l2_debug(2, "%s, reset mode: %d\n", __func__, *mode);
+
+ ret = vdec_v4l2_reset(vdec, *mode);
+ *mode = V4L_RESET_MODE_NORMAL;
}
return ret;
@@ -742,3 +752,12 @@ int vdec_frame_number(struct aml_vdec_adapt *ada_ctx)
else
return -1;
}
+
+void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len)
+{
+ struct vdec_s *vdec = ada_ctx->vdec;
+
+ vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len;
+ memcpy(vdec->config, data, vdec->config_len);
+}
+
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
index 5a69312..1f8afdd 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -38,6 +38,7 @@ struct aml_vdec_adapt {
struct vdec_s *vdec;
struct stream_port_s port;
struct dec_sysinfo dec_prop;
+ struct v4l2_config_parm config;
int video_type;
char *recv_name;
int vfm_path;
@@ -53,11 +54,11 @@ 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 is_need_to_buf(struct aml_vdec_adapt *ada_ctx);
+bool vdec_input_full(struct aml_vdec_adapt *ada_ctx);
void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx);
-int aml_codec_reset(struct aml_vdec_adapt *ada_ctx);
+int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *flag);
extern void dump_write(const char __user *buf, size_t count);
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index 9c34b49..ec6d6e3 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -34,6 +34,11 @@
#include <linux/spinlock.h>
#include "aml_vcodec_vfm.h"
+#include "../frame_provider/decoder/utils/decoder_bmmu_box.h"
+#include "../frame_provider/decoder/utils/decoder_mmu_box.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
#define OUT_FMT_IDX 0 //default h264
#define CAP_FMT_IDX 8 //capture nv21
@@ -157,6 +162,9 @@ static const struct aml_codec_framesizes aml_vdec_framesizes[] = {
extern bool multiplanar;
+extern int dmabuf_fd_install_data(int fd, void* data, u32 size);
+extern bool is_v4l2_buf_file(struct file *file);
+
static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx)
{
ulong flags;
@@ -198,16 +206,34 @@ static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx,
return &ctx->q_data[AML_Q_DATA_DST];
}
-static void aml_vdec_queue_res_chg_event(struct aml_vcodec_ctx *ctx)
+void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes)
{
- static const struct v4l2_event ev_src_ch = {
- .type = V4L2_EVENT_SOURCE_CHANGE,
- .u.src_change.changes =
- V4L2_EVENT_SRC_CH_RESOLUTION,
- };
+ struct v4l2_event event = {0};
- aml_v4l2_debug(4, "[%d] %s()", ctx->id, __func__);
- v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+ if (ctx->receive_cmd_stop) {
+ ctx->state = AML_STATE_ABORT;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
+ changes = V4L2_EVENT_REQUEST_EXIT;
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
+ ctx->id, __func__);
+ }
+
+ switch (changes) {
+ case V4L2_EVENT_SRC_CH_RESOLUTION:
+ case V4L2_EVENT_SRC_CH_HDRINFO:
+ case V4L2_EVENT_REQUEST_RESET:
+ case V4L2_EVENT_REQUEST_EXIT:
+ event.type = V4L2_EVENT_SOURCE_CHANGE;
+ event.u.src_change.changes = changes;
+ break;
+ default:
+ pr_err("unsupport dispatch event %x\n", changes);
+ return;
+ }
+
+ v4l2_event_queue_fh(&ctx->fh, &event);
+ aml_v4l2_debug(3, "[%d] %s() changes: %x",
+ ctx->id, __func__, changes);
}
static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx)
@@ -235,9 +261,9 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
return;
}
- if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) ||
+ /*if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) ||
(ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height))
- return;
+ return;*/
aml_v4l2_debug(4, "[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
ctx->id, ctx->last_decoded_picinfo.visible_width,
@@ -255,6 +281,33 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
ctx->picinfo = ctx->last_decoded_picinfo;
}
+void vdec_frame_buffer_release(void *data)
+{
+ struct file_private_data *priv_data =
+ (struct file_private_data *) data;
+ struct vframe_s *vf = &priv_data->vf;
+
+ if (decoder_bmmu_box_valide_check(vf->mm_box.bmmu_box)) {
+ decoder_bmmu_box_free_idx(vf->mm_box.bmmu_box,
+ vf->mm_box.bmmu_idx);
+ decoder_bmmu_try_to_release_box(vf->mm_box.bmmu_box);
+ }
+
+ if (decoder_mmu_box_valide_check(vf->mm_box.mmu_box)) {
+ decoder_mmu_box_free_idx(vf->mm_box.mmu_box,
+ vf->mm_box.mmu_idx);
+ decoder_mmu_try_to_release_box(vf->mm_box.mmu_box);
+ }
+
+ aml_v4l2_debug(2, "%s vf idx: %d, bmmu idx: %d, bmmu_box: %p",
+ __func__, vf->index, vf->mm_box.bmmu_idx, vf->mm_box.bmmu_box);
+ aml_v4l2_debug(2, "%s vf idx: %d, mmu_idx: %d, mmu_box: %p",
+ __func__, vf->index, vf->mm_box.mmu_idx, vf->mm_box.mmu_box);
+
+ memset(data, 0, sizeof(struct file_private_data));
+ kfree(data);
+}
+
int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb)
{
ulong flags;
@@ -265,6 +318,11 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
flags = aml_vcodec_ctx_lock(ctx);
+ if (ctx->state == AML_STATE_ABORT) {
+ aml_vcodec_ctx_unlock(ctx, flags);
+ return -1;
+ }
+
dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
if (!dst_buf) {
aml_vcodec_ctx_unlock(ctx, flags);
@@ -283,7 +341,7 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
pfb->mem_type = VDEC_SCATTER_MEMORY_TYPE;
pfb->status = FB_ST_NORMAL;
} else if (dst_buf->num_planes == 1) {
- pfb = &dst_buf_info->frame_buffer;
+ 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].size = ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz;
@@ -345,6 +403,8 @@ int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_
info = container_of(pfb, struct aml_video_dec_buf, frame_buffer);
+ ctx->cap_pool.seq[ctx->cap_pool.out++] =
+ (V4L_CAP_BUFF_IN_DEC << 16 | dst_buf->index);
v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
aml_vcodec_ctx_unlock(ctx, flags);
@@ -427,6 +487,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
pr_info("[%d] recevie a empty frame. idx: %d, state: %d\n",
ctx->id, dstbuf->vb.vb2_buf.index,
dstbuf->vb.vb2_buf.state);
+ ATRACE_COUNTER("v4l2_eos", 0);
}
aml_v4l2_debug(4, "[%d] receive vbuf idx: %d, state: %d",
@@ -435,8 +496,11 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
/* binding vframe handle. */
- if (fb->mem_type == VDEC_SCATTER_MEMORY_TYPE)
- dstbuf->vb.private = fb->m.vf_fd;
+ vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+ ATRACE_COUNTER("v4l2_from", vf->index_disp);
+ dstbuf->privdata.vf = *vf;
+ dstbuf->privdata.vf.omx_index =
+ dstbuf->vb.vb2_buf.index;
v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
}
@@ -445,6 +509,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
if (ctx->state == AML_STATE_FLUSHING &&
ctx->has_receive_eos) {
ctx->state = AML_STATE_FLUSHED;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHED)",
ctx->id, __func__);
}
@@ -452,6 +517,11 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
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
@@ -460,7 +530,7 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
* type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper
* layer will get new information from cts->picinfo.
*/
- aml_vdec_queue_res_chg_event(ctx);
+ aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
}
ctx->decoded_frame_cnt++;
@@ -486,6 +556,23 @@ static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffe
return ret;
}
+static void aml_check_dpb_ready(struct aml_vcodec_ctx *ctx)
+{
+ if (!ctx->v4l_codec_dpb_ready) {
+ /*
+ * make sure enough dst bufs for decoding, and
+ * the backend maybe hold 4 frms so need to minus 4.
+ */
+ if ((ctx->dpb_size) && (ctx->cap_pool.in >= ctx->dpb_size - 4))
+ ctx->v4l_codec_dpb_ready = true;
+
+ aml_v4l2_debug(2, "[%d] %s() dpb: %d, ready: %d, used: %d, dpb is ready: %s",
+ ctx->id, __func__, ctx->dpb_size,
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx),
+ ctx->cap_pool.out, ctx->v4l_codec_dpb_ready ? "yes" : "no");
+ }
+}
+
static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
{
struct aml_vcodec_dev *dev = ctx->dev;
@@ -498,22 +585,10 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
}
if (ctx->state == AML_STATE_PROBE) {
- int buf_ready_num;
-
- /* is there enough dst bufs for decoding? */
- buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
- if ((buf_ready_num + ctx->buf_used_count) < ctx->dpb_size) {
- aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.",
- ctx->id, buf_ready_num);
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
- v4l2_m2m_try_schedule(ctx->m2m_ctx);
- msleep(60);
- return 0;
- }
-
mutex_lock(&ctx->state_lock);
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);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_READY)",
@@ -527,12 +602,16 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
if (ctx->m2m_ctx->out_q_ctx.q.streaming &&
ctx->m2m_ctx->cap_q_ctx.q.streaming) {
ctx->state = AML_STATE_ACTIVE;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ACTIVE)",
ctx->id, __func__);
}
}
mutex_unlock(&ctx->state_lock);
+ /* check dpb ready */
+ //aml_check_dpb_ready(ctx);
+
return 1;
}
@@ -548,6 +627,25 @@ static bool is_enough_work_items(struct aml_vcodec_ctx *ctx)
return true;
}
+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;
+ }
+}
+
static void aml_vdec_worker(struct work_struct *work)
{
struct aml_vcodec_ctx *ctx =
@@ -589,22 +687,32 @@ static void aml_vdec_worker(struct work_struct *work)
if (src_buf_info->lastframe) {
/*the empty data use to flushed the decoder.*/
- aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id);
-
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+ aml_v4l2_debug(2, "[%d] Got empty flush input buffer.", ctx->id);
- /* sets eos data for vdec input. */
- aml_vdec_flush_decoder(ctx);
+ /*
+ * when inputs a small amount of src buff, then soon to
+ * switch state FLUSHING, must to wait the DBP to be ready.
+ */
+ if (!ctx->v4l_codec_dpb_ready) {
+ v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+ goto out;
+ }
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)",
+ ATRACE_COUNTER("v4l2_state", ctx->state);
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-LASTFRM)",
ctx->id, __func__);
}
mutex_unlock(&ctx->state_lock);
+ src_buf = 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. */
+ aml_vdec_flush_decoder(ctx);
+
goto out;
}
@@ -643,6 +751,9 @@ static void aml_vdec_worker(struct work_struct *work)
aml_v4l2_err("[%d] %s() error processing src data. %d.",
ctx->id, __func__, ret);
} else if (res_chg) {
+ /* wait the DPB state to be ready. */
+ aml_wait_dpb_ready(ctx);
+
src_buf_info->used = false;
aml_vdec_pic_info_update(ctx);
/*
@@ -651,11 +762,11 @@ static void aml_vdec_worker(struct work_struct *work)
* remaining buffers from before the resolution change
* point, so call flush decode here
*/
- aml_vdec_flush_decoder(ctx);
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)",
+ ATRACE_COUNTER("v4l2_state", ctx->state);
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-RESCHG)",
ctx->id, __func__);
}
mutex_unlock(&ctx->state_lock);
@@ -663,6 +774,8 @@ static void aml_vdec_worker(struct work_struct *work)
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ aml_vdec_flush_decoder(ctx);
+
goto out;
}
@@ -671,23 +784,6 @@ out:
return;
}
-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);
-
- /* flush worker. */
- flush_workqueue(dev->decode_workqueue);
-
- /* wait reset worker ending. */
- if (ctx->state == AML_STATE_RESET) {
- wait_for_completion_timeout(&ctx->comp,
- msecs_to_jiffies(200));
- }
-}
-
static void aml_vdec_reset(struct aml_vcodec_ctx *ctx)
{
if (ctx->state == AML_STATE_ABORT) {
@@ -696,8 +792,9 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx)
goto out;
}
- if (aml_codec_reset(ctx->ada_ctx)) {
+ if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) {
ctx->state = AML_STATE_ABORT;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
ctx->id, __func__);
goto out;
@@ -705,18 +802,42 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx)
if (ctx->state == AML_STATE_RESET) {
ctx->state = AML_STATE_PROBE;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)",
ctx->id, __func__);
+ aml_v4l2_debug(0, "[%d] %s() dpb: %d, ready: %d, used: %d",
+ ctx->id, __func__, ctx->dpb_size,
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx), ctx->buf_used_count);
+
/* vdec has ready to decode subsequence data of new resolution. */
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false;
v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
}
+
out:
complete(&ctx->comp);
return;
}
+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);
+
+ /* flush worker. */
+ flush_workqueue(dev->decode_workqueue);
+
+ ctx->v4l_codec_ready = false;
+ ctx->v4l_codec_dpb_ready = false;
+
+ /* stop decoder. */
+ if (ctx->state > AML_STATE_INIT)
+ aml_vdec_reset(ctx);
+}
+
void try_to_capture(struct aml_vcodec_ctx *ctx)
{
int ret = 0;
@@ -785,6 +906,7 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
enum aml_thread_type type, const char *thread_name)
{
struct aml_vdec_thread *thread;
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
int ret = 0;
thread = kzalloc(sizeof(*thread), GFP_KERNEL);
@@ -802,6 +924,7 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
thread->task = NULL;
goto err;
}
+ sched_setscheduler_nocheck(thread->task, SCHED_FIFO, &param);
list_add(&thread->node, &ctx->vdec_thread_list);
@@ -860,16 +983,25 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
if (ret)
return ret;
- aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u",
+ aml_v4l2_debug(2, "[%d] %s() [%d], cmd: %u",
ctx->id, __func__, __LINE__, cmd->cmd);
dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
V4L2_BUF_TYPE_VIDEO_CAPTURE);
switch (cmd->cmd) {
case V4L2_DEC_CMD_STOP:
-
- if (ctx->state != AML_STATE_ACTIVE)
- return 0;
+ ATRACE_COUNTER("v4l2_stop", 0);
+ if (ctx->state != AML_STATE_ACTIVE) {
+ if (ctx->state >= AML_STATE_IDLE &&
+ ctx->state <= AML_STATE_PROBE) {
+ ctx->state = AML_STATE_ABORT;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
+ aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT);
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
+ ctx->id, __func__);
+ return 0;
+ }
+ }
src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
@@ -886,10 +1018,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
/* flush src */
v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb);
v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention
-
- /* remark cmd use to distinguish stop or seek. */
ctx->receive_cmd_stop = true;
-
break;
case V4L2_DEC_CMD_START:
@@ -910,42 +1039,45 @@ static int vidioc_decoder_streamon(struct file *file, void *priv,
struct v4l2_fh *fh = file->private_data;
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
struct vb2_queue *q;
- int ret = 0;
-
- ret = v4l2_m2m_ioctl_streamon(file, priv, i);
q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
-
if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
- mutex_lock(&ctx->state_lock);
-
- /*
- * if receive the cmd is not V4L2_DEC_CMD_STOP
- * that request should be seek not stop, thus igorn status
- * AML_STATE_FLUSHING and AML_STATE_FLUSHED.
- */
-
- if (ctx->state == AML_STATE_FLUSHED ||
- ctx->state == AML_STATE_FLUSHING || //????
- (ctx->state == AML_STATE_ACTIVE &&
- !ctx->receive_cmd_stop)) {
- if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
- /*the short source will be fasted into flushing state.
- then switch to abort state that caused seek failed.*/
- if (ctx->state == AML_STATE_FLUSHING)
- ctx->receive_cmd_stop = false;
-
+ if (ctx->is_stream_off) {
+ mutex_lock(&ctx->state_lock);
+ if ((ctx->state == AML_STATE_ACTIVE ||
+ ctx->state == AML_STATE_FLUSHING ||
+ ctx->state == AML_STATE_FLUSHED) ||
+ (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;
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)",
ctx->id, __func__);
aml_vdec_reset(ctx);
}
+ mutex_unlock(&ctx->state_lock);
+
+ ctx->is_stream_off = false;
}
- mutex_unlock(&ctx->state_lock);
}
- return ret;
+ return v4l2_m2m_ioctl_streamon(file, priv, i);
+}
+
+static int vidioc_decoder_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type i)
+{
+ struct v4l2_fh *fh = file->private_data;
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+ struct vb2_queue *q;
+
+ q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
+ if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
+ ctx->is_stream_off = true;
+ }
+
+ return v4l2_m2m_ioctl_streamoff(file, priv, i);
}
static int vidioc_decoder_reqbufs(struct file *file, void *priv,
@@ -964,10 +1096,14 @@ static int vidioc_decoder_reqbufs(struct file *file, void *priv,
void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx)
{
+ ulong flags;
+
+ flags = aml_vcodec_ctx_lock(ctx);
ctx->state = AML_STATE_ABORT;
- ctx->v4l_codec_ready = false;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
ctx->id, __func__);
+ aml_vcodec_ctx_unlock(ctx, flags);
vdec_if_deinit(ctx);
}
@@ -1016,8 +1152,10 @@ void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx)
q_data->bytesperline[0] = q_data->coded_width;
q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
q_data->bytesperline[1] = q_data->coded_width;
+ ctx->reset_flag = V4L_RESET_MODE_NORMAL;
ctx->state = AML_STATE_IDLE;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_IDLE)",
ctx->id, __func__);
}
@@ -1026,6 +1164,7 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+ int ret;
if (ctx->state == AML_STATE_ABORT) {
aml_v4l2_err("[%d] Call on QBUF after unrecoverable error, type = %s",
@@ -1034,13 +1173,22 @@ static int vidioc_vdec_qbuf(struct file *file, void *priv,
return -EIO;
}
- return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+ ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+
+ if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ if (ret == -EAGAIN)
+ ATRACE_COUNTER("v4l2_qbuf_eagain", 0);
+ else
+ ATRACE_COUNTER("v4l2_qbuf_ok", 0);
+ }
+ return ret;
}
static int vidioc_vdec_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+ int ret;
if (ctx->state == AML_STATE_ABORT) {
aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error, type = %s",
@@ -1050,7 +1198,43 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
return -EIO;
}
- return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ if (ret == -EAGAIN)
+ ATRACE_COUNTER("v4l2_dqin_eagain", 0);
+ else
+ ATRACE_COUNTER("v4l2_dqin_ok", 0);
+ } else if (!V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ if (ret == -EAGAIN)
+ ATRACE_COUNTER("v4l2_dqout_eagain", 0);
+ }
+
+ if (!ret && !V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ struct vb2_queue *vq;
+ struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+ struct aml_video_dec_buf *aml_buf = NULL;
+ struct file *file = NULL;
+
+ mutex_lock(&ctx->lock);
+ 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);
+
+ file = fget(vb2_v4l2->private);
+ if (is_v4l2_buf_file(file)) {
+ dmabuf_fd_install_data(vb2_v4l2->private,
+ (void*)&aml_buf->privdata,
+ sizeof(struct file_private_data));
+ ATRACE_COUNTER("v4l2_dqout_ok", aml_buf->privdata.vf.index_disp);
+ aml_v4l2_debug(4, "[%d] %s, disp: %d, vf: %p\n", ctx->id,
+ __func__, aml_buf->privdata.vf.index_disp,
+ v4l_get_vf_handle(vb2_v4l2->private));
+ }
+ fput(file);
+ mutex_unlock(&ctx->lock);
+ }
+
+ return ret;
}
static int vidioc_vdec_querycap(struct file *file, void *priv,
@@ -1312,6 +1496,7 @@ static int vidioc_vdec_s_fmt(struct file *file, void *priv,
return -EINVAL;
}
ctx->state = AML_STATE_INIT;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_INIT)",
ctx->id, __func__);
}
@@ -1366,22 +1551,18 @@ static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
for (i = 0; i < NUM_FORMATS; i++) {
if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC))
continue;
- if (!output_queue &&
- (aml_video_formats[i].type != AML_FMT_FRAME))
+ if (!output_queue && (aml_video_formats[i].type != AML_FMT_FRAME))
continue;
- if (j == f->index)
- break;
+ if (j == f->index) {
+ fmt = &aml_video_formats[i];
+ f->pixelformat = fmt->fourcc;
+ return 0;
+ }
++j;
}
- if (i == NUM_FORMATS)
- return -EINVAL;
-
- fmt = &aml_video_formats[i];
- f->pixelformat = fmt->fourcc;
-
- return 0;
+ return -EINVAL;
}
static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
@@ -1584,14 +1765,26 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
__func__, __LINE__, buf->frame_buffer.m.mem[0].addr,
buf->frame_buffer.vf_handle, buf->frame_buffer.status);
- if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) {
- aml_v4l2_debug(2, "[%d] enque capture buf idx %d, %p",
- ctx->id, vb->index, vb);
+ if (vb->index >= ctx->dpb_size) {
+ aml_v4l2_debug(2, "[%d] enque capture buf idx %d is invalid.",
+ ctx->id, vb->index);
+ return;
+ }
+
+ if (!buf->que_in_m2m) {
+ aml_v4l2_debug(2, "[%d] enque capture buf idx %d, vf: %p",
+ ctx->id, vb->index, v4l_get_vf_handle(vb2_v4l2->private));
+
v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
buf->que_in_m2m = true;
buf->queued_in_vb2 = true;
buf->queued_in_v4l2 = true;
buf->ready_to_display = false;
+ ctx->cap_pool.seq[ctx->cap_pool.in++] =
+ (V4L_CAP_BUFF_IN_M2M << 16 | vb->index);
+
+ /* check dpb ready */
+ aml_check_dpb_ready(ctx);
} else if (buf->frame_buffer.status == FB_ST_DISPLAY) {
buf->queued_in_vb2 = false;
buf->queued_in_v4l2 = true;
@@ -1645,11 +1838,12 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
ctx->dpb_size = dpb;
ctx->last_decoded_picinfo = ctx->picinfo;
- aml_vdec_queue_res_chg_event(ctx);
+ aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_INIT) {
ctx->state = AML_STATE_PROBE;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)",
ctx->id, __func__);
}
@@ -1675,6 +1869,7 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
if (buf_error) {
aml_v4l2_err("[%d] Unrecoverable error on buffer.", ctx->id);
ctx->state = AML_STATE_ABORT;
+ ATRACE_COUNTER("v4l2_state", ctx->state);
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
ctx->id, __func__);
}
@@ -1810,21 +2005,26 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
} else {
- while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)))
- v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+ /* stop decoder. */
+ wait_vcodec_ending(ctx);
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
buf->frame_buffer.status = FB_ST_NORMAL;
buf->que_in_m2m = false;
+ ctx->cap_pool.seq[i] = 0;
+
+ if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+ v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
/*pr_info("idx: %d, state: %d\n",
q->bufs[i]->index, q->bufs[i]->state);*/
}
-
- ctx->buf_used_count = 0;
}
+ ctx->buf_used_count = 0;
+ ctx->cap_pool.in = 0;
+ ctx->cap_pool.out = 0;
}
static void m2mops_vdec_device_run(void *priv)
@@ -1841,7 +2041,7 @@ void vdec_device_vf_run(struct aml_vcodec_ctx *ctx)
{
aml_v4l2_debug(3, "[%d] %s() [%d]", ctx->id, __func__, __LINE__);
- if (ctx->state < AML_STATE_ACTIVE ||
+ if (ctx->state < AML_STATE_INIT ||
ctx->state > AML_STATE_FLUSHED)
return;
@@ -1955,6 +2155,51 @@ err:
return ret;
}
+static int vidioc_vdec_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO,
+ &ctx->config.parm.dec)) {
+ pr_err("[%d] GET_PARAM_CONFIG_INFO err\n", ctx->id);
+ return -1;
+ }
+ memcpy(a->parm.raw_data, ctx->config.parm.data,
+ sizeof(a->parm.raw_data));
+ }
+
+ return 0;
+}
+
+static int vidioc_vdec_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ struct aml_dec_params *in =
+ (struct aml_dec_params *) a->parm.raw_data;
+ struct aml_dec_params *dec = &ctx->config.parm.dec;
+
+ ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+
+ if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+ dec->cfg = in->cfg;
+ if (in->parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+ dec->ps = in->ps;
+ if (in->parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+ dec->hdr = in->hdr;
+ if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+ dec->cnt = in->cnt;
+
+ dec->parms_status |= in->parms_status;
+ }
+
+ return 0;
+}
+
static void m2mops_vdec_lock(void *m2m_priv)
{
struct aml_vcodec_ctx *ctx = m2m_priv;
@@ -1993,7 +2238,7 @@ static const struct vb2_ops aml_vdec_vb2_ops = {
const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_streamon = vidioc_decoder_streamon,
- .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_streamoff = vidioc_decoder_streamoff,
.vidioc_reqbufs = vidioc_decoder_reqbufs,
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//??
@@ -2032,6 +2277,9 @@ const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_decoder_cmd = vidioc_decoder_cmd,
.vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
+
+ .vidioc_g_parm = vidioc_vdec_g_parm,
+ .vidioc_s_parm = vidioc_vdec_s_parm,
};
int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
index 19923c0..68f878a 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -23,6 +23,7 @@
#include <media/videobuf2-core.h>
#include <media/videobuf2-v4l2.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
#include "aml_vcodec_util.h"
#define VCODEC_CAPABILITY_4K_DISABLED 0x10
@@ -83,6 +84,7 @@ struct aml_video_dec_buf {
struct list_head list;
struct vdec_v4l2_buffer frame_buffer;
+ struct file_private_data privdata;
struct codec_mm_s *mem[2];
char mem_onwer[32];
bool used;
@@ -94,18 +96,9 @@ struct aml_video_dec_buf {
bool error;
};
-struct aml_vdec_pic_infos {
- u32 visible_width;
- u32 visible_height;
- u32 coded_width;
- u32 coded_height;
- int dpb_size;
-};
-
extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops;
extern const struct v4l2_m2m_ops aml_vdec_m2m_ops;
-
/*
* aml_vdec_lock/aml_vdec_unlock are for ctx instance to
* get/release lock before/after access decoder hw.
@@ -119,9 +112,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx);
void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx);
int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx);
-
void vdec_device_vf_run(struct aml_vcodec_ctx *ctx);
-
void try_to_capture(struct aml_vcodec_ctx *ctx);
void aml_thread_notify(struct aml_vcodec_ctx *ctx,
enum aml_thread_type type);
@@ -129,5 +120,8 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
enum aml_thread_type type, const char *thread_name);
void aml_thread_stop(struct aml_vcodec_ctx *ctx);
void wait_vcodec_ending(struct aml_vcodec_ctx *ctx);
+void vdec_frame_buffer_release(void *data);
+void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes);
+void* v4l_get_vf_handle(int fd);
#endif /* _AML_VCODEC_DEC_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
index a50f9b1..43ff0c5 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -35,12 +35,20 @@
#include "aml_vcodec_dec_pm.h"
#include "aml_vcodec_util.h"
#include "aml_vcodec_vfm.h"
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
#define VDEC_HW_ACTIVE 0x10
#define VDEC_IRQ_CFG 0x11
#define VDEC_IRQ_CLR 0x10
#define VDEC_IRQ_CFG_REG 0xa4
+#define V4LVIDEO_IOC_MAGIC 'I'
+#define V4LVIDEO_IOCTL_ALLOC_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x02, int)
+#define V4LVIDEO_IOCTL_CHECK_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x03, int)
+#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;
@@ -68,7 +76,6 @@ static int fops_vcodec_open(struct file *file)
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
INIT_LIST_HEAD(&ctx->list);
- INIT_LIST_HEAD(&ctx->capture_list);
INIT_LIST_HEAD(&ctx->vdec_thread_list);
dev->filp = file;
ctx->dev = dev;
@@ -159,12 +166,227 @@ static int fops_vcodec_release(struct file *file)
return 0;
}
+static int v4l2video_file_release(struct inode *inode, struct file *file)
+{
+ aml_v4l2_debug(2,"%s: file: 0x%p, data: %p",
+ __func__, file, file->private_data);
+
+ if (file->private_data)
+ vdec_frame_buffer_release(file->private_data);
+
+ return 0;
+}
+
+const struct file_operations v4l2_file_fops = {
+ .release = v4l2video_file_release,
+};
+
+int v4l2_alloc_fd(int *fd)
+{
+ struct file *file = NULL;
+ int file_fd = get_unused_fd_flags(O_CLOEXEC);
+
+ if (file_fd < 0) {
+ pr_err("%s: get unused fd fail\n", __func__);
+ return -ENODEV;
+ }
+
+ file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
+ if (IS_ERR(file)) {
+ put_unused_fd(file_fd);
+ pr_err("%s: anon_inode_getfile fail\n", __func__);
+ return -ENODEV;
+ }
+
+ file->private_data =
+ kzalloc(sizeof(struct file_private_data), GFP_KERNEL);
+ if (!file->private_data) {
+ pr_err("%s: alloc priv data faild.\n", __func__);
+ return -ENOMEM;
+ }
+
+ aml_v4l2_debug(2, "%s: fd %d, file %p", __func__, file_fd, file);
+
+ fd_install(file_fd, file);
+ *fd = file_fd;
+
+ return 0;
+}
+
+extern const struct file_operations v4l2_file_fops;
+bool is_v4l2_buf_file(struct file *file)
+{
+ return file->f_op == &v4l2_file_fops;
+}
+
+int v4l2_check_fd(int fd)
+{
+ struct file *file;
+
+ file = fget(fd);
+
+ if (!file) {
+ pr_err("%s: fget fd %d fail!\n", __func__, fd);
+ return -EBADF;
+ }
+
+ if (!is_v4l2_buf_file(file)) {
+ fput(file);
+ pr_err("%s: is_v4l2_buf_file fail!\n", __func__);
+ return -1;
+ }
+
+ fput(file);
+
+ aml_v4l2_debug(5, "%s: ioctl ok, comm %s, pid %d",
+ __func__, current->comm, current->pid);
+
+ return 0;
+}
+
+int dmabuf_fd_install_data(int fd, void* data, u32 size)
+{
+ struct file *file;
+
+ file = fget(fd);
+
+ if (!file) {
+ pr_err("%s: fget fd %d fail!, comm %s, pid %d\n",
+ __func__, fd, current->comm, current->pid);
+ return -EBADF;
+ }
+
+ if (!is_v4l2_buf_file(file)) {
+ fput(file);
+ pr_err("%s the buf file checked fail!\n", __func__);
+ return -EBADF;
+ }
+
+ memcpy(file->private_data, data, size);
+
+ fput(file);
+
+ return 0;
+}
+
+void* v4l_get_vf_handle(int fd)
+{
+ struct file *file;
+ struct file_private_data *data = NULL;
+ void *vf_handle = 0;
+
+ file = fget(fd);
+
+ if (!file) {
+ pr_err("%s: fget fd %d fail!, comm %s, pid %d\n",
+ __func__, fd, current->comm, current->pid);
+ return NULL;
+ }
+
+ if (!is_v4l2_buf_file(file)) {
+ fput(file);
+ pr_err("%s the buf file checked fail!\n", __func__);
+ return NULL;
+ }
+
+ data = (struct file_private_data*) file->private_data;
+ if (data)
+ vf_handle = &data->vf;
+
+ fput(file);
+
+ return vf_handle;
+}
+
+
+static long v4l2_vcodec_ioctl(struct file *file,
+ unsigned int cmd,
+ ulong arg)
+{
+ long ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case V4LVIDEO_IOCTL_ALLOC_FD:
+ {
+ u32 v4lvideo_fd = 0;
+
+ ret = v4l2_alloc_fd(&v4lvideo_fd);
+ if (ret != 0)
+ break;
+ put_user(v4lvideo_fd, (u32 __user *)argp);
+ aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_ALLOC_FD fd %d",
+ __func__, v4lvideo_fd);
+ break;
+ }
+ case V4LVIDEO_IOCTL_CHECK_FD:
+ {
+ u32 v4lvideo_fd = 0;
+
+ get_user(v4lvideo_fd, (u32 __user *)argp);
+ ret = v4l2_check_fd(v4lvideo_fd);
+ if (ret != 0)
+ break;
+ aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_CHECK_FD fd %d",
+ __func__, v4lvideo_fd);
+ break;
+ }
+ case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
+ {
+ struct aml_vcodec_ctx *ctx = NULL;
+
+ if (is_v4l2_buf_file(file))
+ break;
+
+ ctx = fh_to_ctx(file->private_data);
+ if (copy_from_user((void *)&ctx->config,
+ (void *)argp, sizeof(ctx->config))) {
+ pr_err("[%s],set config parm err\n", __func__);
+ return -EFAULT;
+ }
+ break;
+ }
+ case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
+ {
+ struct aml_vcodec_ctx *ctx = NULL;
+
+ if (is_v4l2_buf_file(file))
+ break;
+
+ ctx = fh_to_ctx(file->private_data);
+ if (copy_to_user((void *)argp,
+ (void *)&ctx->config, sizeof(ctx->config))) {
+ pr_err("[%s],get config parm err\n", __func__);
+ return -EFAULT;
+ }
+ break;
+ }
+ default:
+ return video_ioctl2(file, cmd, arg);
+ }
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long v4l2_compat_ioctl(struct file *file,
+ unsigned int cmd, ulong arg)
+{
+ long ret = 0;
+
+ ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
+ return ret;
+}
+#endif
+
static const struct v4l2_file_operations aml_vcodec_fops = {
.owner = THIS_MODULE,
.open = fops_vcodec_open,
.release = fops_vcodec_release,
.poll = v4l2_m2m_fop_poll,
- .unlocked_ioctl = video_ioctl2,
+ .unlocked_ioctl = v4l2_vcodec_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = v4l2_compat_ioctl,
+#endif
.mmap = v4l2_m2m_fop_mmap,
};
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
index a7c9aaf..1baec44 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -26,6 +26,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
+#include <linux/amlogic/media/vfm/vframe.h>
#include "aml_vcodec_util.h"
#define AML_VCODEC_DRV_NAME "aml_vcodec_drv"
@@ -37,6 +38,36 @@
#define AML_V4L2_BENCHMARK 0
#define WAIT_INTR_TIMEOUT_MS 1000
+/* codec types of get/set parms. */
+#define V4L2_CONFIG_PARM_ENCODE (0)
+#define V4L2_CONFIG_PARM_DECODE (1)
+
+/* types of decode parms. */
+#define V4L2_CONFIG_PARM_DECODE_CFGINFO (1 << 0)
+#define V4L2_CONFIG_PARM_DECODE_PSINFO (1 << 1)
+#define V4L2_CONFIG_PARM_DECODE_HDRINFO (1 << 2)
+#define V4L2_CONFIG_PARM_DECODE_CNTINFO (1 << 3)
+
+/* amlogic event define. */
+/* #define V4L2_EVENT_SRC_CH_RESOLUTION (1 << 0) */
+#define V4L2_EVENT_SRC_CH_HDRINFO (1 << 1)
+#define V4L2_EVENT_SRC_CH_PSINFO (1 << 2)
+#define V4L2_EVENT_SRC_CH_CNTINFO (1 << 3)
+
+/* exception handing */
+#define V4L2_EVENT_REQUEST_RESET (1 << 8)
+#define V4L2_EVENT_REQUEST_EXIT (1 << 9)
+
+/* v4l buffer pool */
+#define V4L_CAP_BUFF_MAX (32)
+#define V4L_CAP_BUFF_INVALID (0)
+#define V4L_CAP_BUFF_IN_M2M (1)
+#define V4L_CAP_BUFF_IN_DEC (2)
+
+/* v4l reset mode */
+#define V4L_RESET_MODE_NORMAL (1 << 0) /* reset vdec_input and decoder. */
+#define V4L_RESET_MODE_LIGHT (1 << 1) /* just only reset decoder. */
+
/**
* enum aml_hw_reg_idx - AML hw register base index
*/
@@ -136,6 +167,7 @@ enum aml_q_type {
AML_Q_DATA_DST = 1,
};
+
/**
* struct aml_q_data - Structure used to store information about queue
*/
@@ -233,6 +265,86 @@ struct vdec_pic_info {
unsigned int c_bs_sz;
unsigned int y_len_sz;
unsigned int c_len_sz;
+ int profile_idc;
+};
+
+struct aml_vdec_cfg_infos {
+ u32 double_write_mode;
+ u32 init_width;
+ u32 init_height;
+ u32 ref_buf_margin;
+ u32 canvas_mem_mode;
+ u32 canvas_mem_endian;
+};
+
+struct aml_vdec_hdr_infos {
+ /*
+ * bit 29 : present_flag
+ * bit 28-26: video_format "component", "PAL", "NTSC", "SECAM", "MAC", "unspecified"
+ * bit 25 : range "limited", "full_range"
+ * bit 24 : color_description_present_flag
+ * bit 23-16: color_primaries "unknown", "bt709", "undef", "bt601",
+ * "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020"
+ * bit 15-8 : transfer_characteristic unknown", "bt709", "undef", "bt601",
+ * "bt470m", "bt470bg", "smpte170m", "smpte240m",
+ * "linear", "log100", "log316", "iec61966-2-4",
+ * "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12",
+ * "smpte-st-2084", "smpte-st-428"
+ * bit 7-0 : matrix_coefficient "GBR", "bt709", "undef", "bt601",
+ * "fcc", "bt470bg", "smpte170m", "smpte240m",
+ * "YCgCo", "bt2020nc", "bt2020c"
+ */
+ u32 signal_type;
+ struct vframe_master_display_colour_s color_parms;
+};
+
+struct aml_vdec_ps_infos {
+ u32 visible_width;
+ u32 visible_height;
+ u32 coded_width;
+ u32 coded_height;
+ u32 profile;
+ u32 mb_width;
+ u32 mb_height;
+ u32 dpb_size;
+ u32 ref_frames;
+ u32 reorder_frames;
+};
+
+struct aml_vdec_cnt_infos {
+ u32 bit_rate;
+ u32 frame_count;
+ u32 error_frame_count;
+ u32 drop_frame_count;
+ u32 total_data;
+};
+
+struct aml_dec_params {
+ u32 parms_status;
+ struct aml_vdec_cfg_infos cfg;
+ struct aml_vdec_ps_infos ps;
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vdec_cnt_infos cnt;
+};
+
+struct v4l2_config_parm {
+ u32 type;
+ u32 length;
+ union {
+ struct aml_dec_params dec;
+ struct aml_enc_params enc;
+ u8 data[200];
+ } parm;
+ u8 buf[4096];
+};
+
+struct v4l_buff_pool {
+ /*
+ * bit 31-16: buffer state
+ * bit 15- 0: buffer index
+ */
+ u32 seq[V4L_CAP_BUFF_MAX];
+ u32 in, out;
};
enum aml_thread_type {
@@ -335,7 +447,6 @@ struct aml_vcodec_ctx {
struct mutex lock;
struct completion comp;
bool has_receive_eos;
- struct list_head capture_list;
struct list_head vdec_thread_list;
bool is_drm_mode;
bool is_stream_mode;
@@ -344,8 +455,15 @@ struct aml_vcodec_ctx {
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;
};
/**
diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c
index e7b85fb..b64be0c 100644
--- a/drivers/amvdec_ports/aml_vcodec_vfm.c
+++ b/drivers/amvdec_ports/aml_vcodec_vfm.c
@@ -23,6 +23,9 @@
#include "aml_vcodec_adapt.h"
#include <media/v4l2-mem2mem.h>
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO_COMPOSER
+#include <trace/events/meson_atrace.h>
+
#define RECEIVER_NAME "v4l2-video"
#define PROVIDER_NAME "v4l2-video"
@@ -94,6 +97,7 @@ void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id)
aml_v4l2_debug(3, "[%d] TO (%s) vf: %p, idx: %d",
id, vfp->name, vf, vf->index);
+ ATRACE_COUNTER("v4l2_to", vf->index_disp);
aml_v4l2_debug(4, "[%d] TO Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)",
id, fb->m.mem[0].addr, fb->m.mem[0].size,
@@ -214,6 +218,8 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm)
int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
{
+ int ret;
+
snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d",
RECEIVER_NAME, vfm->ctx->id);
snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d",
@@ -222,13 +228,16 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
vfm->ada_ctx->recv_name = vfm->recv_name;
vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm);
- vf_reg_receiver(&vfm->vf_recv);
+ ret = vf_reg_receiver(&vfm->vf_recv);
- return 0;
+ vfm->vfm_initialized = ret ? false : true;
+
+ return ret;
}
void vcodec_vfm_release(struct vcodec_vfm_s *vfm)
{
- vf_unreg_receiver(&vfm->vf_recv);
+ if (vfm->vfm_initialized)
+ vf_unreg_receiver(&vfm->vf_recv);
}
diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.h b/drivers/amvdec_ports/aml_vcodec_vfm.h
index 9aaf266..141e9a7 100644
--- a/drivers/amvdec_ports/aml_vcodec_vfm.h
+++ b/drivers/amvdec_ports/aml_vcodec_vfm.h
@@ -41,6 +41,7 @@ struct vcodec_vfm_s {
char prov_name[VF_NAME_SIZE];
struct vframe_provider_s vf_prov;
struct vframe_receiver_s vf_recv;
+ bool vfm_initialized;
};
int vcodec_vfm_init(struct vcodec_vfm_s *vfm);
diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c
index cf4e0e8..602633b 100644
--- a/drivers/amvdec_ports/decoder/aml_h264_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c
@@ -100,10 +100,10 @@ static int decode_scaling_list(struct get_bits_context *gb,
for (i = 0; i < size; i++) {
if (next) {
int v = get_se_golomb(gb);
- if (v < -128 || v > 127) {
+ /*if (v < -128 || v > 127) { //JM19 has not check.
pr_err( "delta scale %d is invalid\n", v);
return -1;
- }
+ }*/
next = (last + v) & 0xff;
}
if (!i && !next) { /* matrix not written, we use the preset one */
@@ -495,6 +495,7 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s
goto out;
}
+#if 0
/* if the maximum delay is not stored in the SPS, derive it based on the level */
if (!sps->bitstream_restriction_flag && sps->ref_frame_count) {
sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1;
@@ -507,6 +508,28 @@ static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *s
}
}
}
+#endif
+
+ sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1;
+ for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) {
+ if (level_max_dpb_mbs[i][0] == sps->level_idc) {
+ sps->num_reorder_frames =
+ MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height),
+ sps->num_reorder_frames);
+ sps->num_reorder_frames += 1;
+ if (sps->max_dec_frame_buffering > sps->num_reorder_frames)
+ sps->num_reorder_frames = sps->max_dec_frame_buffering;
+ break;
+ }
+ }
+
+ if ((sps->bitstream_restriction_flag) &&
+ (sps->max_dec_frame_buffering <
+ sps->num_reorder_frames)) {
+ sps->num_reorder_frames = sps->max_dec_frame_buffering;
+ pr_info("set reorder_pic_num to %d\n",
+ sps->num_reorder_frames);
+ }
if (!sps->sar.den)
sps->sar.den = 1;
@@ -601,6 +624,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps)
goto out;
if (get_bits1(&gb) != 0) {
+ ret = -1;
pr_err("invalid h264 data,return!\n");
goto out;
}
@@ -651,6 +675,10 @@ int h264_decode_extradata_ps(u8 *buf, int size, struct h264_param_sets *ps)
pr_err("parse extra data failed. err: %d\n", ret);
return ret;
}
+
+ if (ps->sps_parsed)
+ break;
+
p += j;
}
p++;
diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.c b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
index 33d44f1..03b8356 100644
--- a/drivers/amvdec_ports/decoder/aml_hevc_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
@@ -1204,6 +1204,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps)
goto out;
if (get_bits1(&gb) != 0) {
+ ret = -1;
pr_err("invalid data, return!\n");
goto out;
}
@@ -1211,8 +1212,10 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps)
nal_type = get_bits(&gb, 6);
nuh_layer_id = get_bits(&gb, 6);
temporal_id = get_bits(&gb, 3) - 1;
- if (temporal_id < 0)
+ if (temporal_id < 0) {
+ ret = -1;
goto out;
+ }
/*pr_info("nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n",
nal_type, hevc_nal_unit_name(nal_type),
@@ -1246,7 +1249,7 @@ static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps)
out:
vfree(rbsp_buf);
- return 0;
+ return ret;
}
int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps)
@@ -1264,6 +1267,10 @@ int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps)
pr_err("parse extra data failed. err: %d\n", ret);
return ret;
}
+
+ if (ps->sps_parsed)
+ break;
+
p += j;
}
p++;
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
index 02848b8..eada4ea 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -27,6 +27,7 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
@@ -150,6 +151,7 @@ struct vdec_h264_inst {
struct aml_vdec_adapt vdec;
struct vdec_h264_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -244,6 +246,48 @@ static void skip_aud_data(u8 **data, u32 *size)
}
}
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "mh264_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_h264_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, "mh264_double_write_mode:%d;",
+ ctx->config.parm.dec.cfg.double_write_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ ctx->config.parm.dec.cfg.ref_buf_margin);
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_endian);
+ ctx->config.length = pbuf - ctx->config.buf;
+ } else {
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
+ ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+ 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_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_h264_inst *inst = NULL;
@@ -253,66 +297,66 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_H264;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_H264;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ pr_err("%s, init vfm failed.\n", __func__);
+ goto err;
+ }
ret = video_decoder_init(&inst->vdec);
if (ret) {
aml_vcodec_err(inst, "vdec_h264 init err=%d", ret);
- goto error_free_inst;
+ goto err;
}
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_h264_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) {
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "H264 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
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;
@@ -388,11 +432,32 @@ static int refer_buffer_num(int level_idc, int max_poc_cnt,
}
#endif
+static void vdec_config_dw_mode(struct vdec_pic_info *pic, int dw_mode)
+{
+ switch (dw_mode) {
+ case 0x1: /* (w x h) + (w/2 x h) */
+ pic->coded_width += pic->coded_width >> 1;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+ break;
+ case 0x2: /* (w x h) + (w/2 x h/2) */
+ pic->coded_width += pic->coded_width >> 1;
+ pic->coded_height += pic->coded_height >> 1;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+ break;
+ default: /* nothing to do */
+ break;
+ }
+}
+
static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps)
{
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;
+ int margin = inst->parms.cfg.ref_buf_margin;
u32 mb_w, mb_h, width, height;
mb_w = sps->mb_width;
@@ -419,13 +484,29 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps
pic->coded_height = ALIGN(mb_h, 4) << 4;
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
+ pic->profile_idc = sps->profile_idc;
/* calc DPB size */
- dec->dpb_sz = sps->ref_frame_count;
-
- aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
- inst->ctx->id, pic->coded_width, pic->coded_height,
- pic->visible_width, pic->visible_height, dec->dpb_sz);
+ dec->dpb_sz = sps->num_reorder_frames + margin;
+
+ inst->parms.ps.visible_width = pic->visible_width;
+ inst->parms.ps.visible_height = pic->visible_height;
+ inst->parms.ps.coded_width = pic->coded_width;
+ inst->parms.ps.coded_height = pic->coded_height;
+ inst->parms.ps.profile = sps->profile_idc;
+ inst->parms.ps.mb_width = sps->mb_width;
+ inst->parms.ps.mb_height = sps->mb_height;
+ inst->parms.ps.ref_frames = sps->ref_frame_count;
+ inst->parms.ps.reorder_frames = sps->num_reorder_frames;
+ inst->parms.ps.dpb_size = dec->dpb_sz;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+ vdec_config_dw_mode(pic, dw);
+
+ aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id, dw, pic->coded_width, pic->coded_height,
+ pic->visible_width, pic->visible_height,
+ dec->dpb_sz - margin, margin);
}
static bool check_frame_combine(u8 *buf, u32 size, int *pos)
@@ -453,6 +534,24 @@ static bool check_frame_combine(u8 *buf, u32 size, int *pos)
return combine;
}
+static int vdec_search_startcode(u8 *buf, u32 range)
+{
+ int pos = -1;
+ int i = 0, j = 0;
+ u8 *p = buf;
+
+ for (i = 4; i < range; i++) {
+ j = find_start_code(p, 7);
+ if (j > 0) {
+ pos = p - buf + j;
+ break;
+ }
+ p++;
+ }
+
+ return pos;
+}
+
static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
@@ -475,7 +574,6 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct h264_param_sets *ps;
- u32 nal_type;
int nal_idx = 0;
bool is_combine = false;
@@ -483,15 +581,11 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
if (nal_idx < 0)
return -1;
- nal_type = AVC_NAL_TYPE(buf[nal_idx]);
- if (nal_type != NAL_H264_SPS)
- return -1;
-
/* if the st compose from csd + slice that is the combine data. */
inst->vsi->is_combine = is_combine;
inst->vsi->nalu_pos = nal_idx;
- ps = kzalloc(sizeof(struct h264_param_sets), GFP_KERNEL);
+ ps = vzalloc(sizeof(struct h264_param_sets));
if (ps == NULL)
return -ENOMEM;
@@ -506,7 +600,7 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
ret = ps->sps_parsed ? 0 : -1;
out:
- kfree(ps);
+ vfree(ps);
return ret;
}
@@ -618,7 +712,9 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst,
int nalu_pos;
u32 nal_type;
- nalu_pos = find_start_code(buf, size);
+ /*print_hex_debug(buf, size, 32);*/
+
+ nalu_pos = vdec_search_startcode(buf, 16);
if (nalu_pos < 0)
goto err;
@@ -701,19 +797,25 @@ static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size)
if (type == NAL_H264_SPS) {
ret = stream_parse(inst, p, len);
- if (!ret && (inst->vsi->cur_pic.coded_width !=
- inst->vsi->pic.coded_width ||
- inst->vsi->cur_pic.coded_height !=
- inst->vsi->pic.coded_height)) {
- inst->vsi->cur_pic = inst->vsi->pic;
- return true;
- }
+ if (ret)
+ break;
}
p += j;
}
p++;
}
+ if (!ret && ((inst->vsi->cur_pic.coded_width !=
+ inst->vsi->pic.coded_width ||
+ inst->vsi->cur_pic.coded_height !=
+ inst->vsi->pic.coded_height) ||
+ (inst->vsi->pic.profile_idc !=
+ inst->vsi->cur_pic.profile_idc))) {
+ pr_info("res change\n");
+ inst->vsi->cur_pic = inst->vsi->pic;
+ return true;
+ }
+
return false;
}
@@ -727,10 +829,12 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
u32 size;
int ret = -1;
- /* bs NULL means flush decoder */
if (bs == NULL)
return -1;
+ if (vdec_input_full(vdec))
+ return -EAGAIN;
+
buf = (u8 *)bs->vaddr;
size = bs->size;
st = (struct stream_info *)buf;
@@ -754,6 +858,23 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return ret;
}
+static void get_param_config_info(struct vdec_h264_inst *inst,
+ struct aml_dec_params *parms)
+{
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+ parms->cfg = inst->parms.cfg;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+ parms->ps = inst->parms.ps;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+ parms->hdr = inst->parms.hdr;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+ parms->cnt = inst->parms.cnt;
+
+ parms->parms_status |= inst->parms.parms_status;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->parms_status);
+}
+
static int vdec_h264_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -786,6 +907,9 @@ static int vdec_h264_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -799,16 +923,16 @@ static void set_param_write_sync(struct vdec_h264_inst *inst)
complete(&inst->comp);
}
-static void set_param_pic_info(struct vdec_h264_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_h264_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_h264_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
/* fill visible area size that be used for EGL. */
- pic->visible_width = info->visible_width;
- pic->visible_height = info->visible_height;
+ pic->visible_width = ps->visible_width;
+ pic->visible_height = ps->visible_height;
/* calc visible ares. */
rect->left = 0;
@@ -817,20 +941,45 @@ static void set_param_pic_info(struct vdec_h264_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = info->coded_width;
- pic->coded_height = info->coded_height;
+ 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 = info->dpb_size;
+ dec->dpb_sz = ps->dpb_size;
+
+ inst->parms.ps = *ps;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PSINFO;
/*wake up*/
complete(&inst->comp);
pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
- info->visible_width, info->visible_height,
- info->coded_width, info->coded_height,
- info->dpb_size);
+ ps->visible_width, ps->visible_height,
+ ps->coded_width, ps->coded_height,
+ dec->dpb_sz);
+}
+
+static void set_param_hdr_info(struct vdec_h264_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ inst->parms.hdr = *hdr;
+ if (!(inst->parms.parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+ inst->parms.hdr = *hdr;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+ aml_vdec_dispatch_event(inst->ctx,
+ V4L2_EVENT_SRC_CH_HDRINFO);
+ pr_info("H264 set HDR infos\n");
+ }
+}
+
+static void set_param_post_event(struct vdec_h264_inst *inst, u32 *event)
+{
+ aml_vdec_dispatch_event(inst->ctx, *event);
+ pr_info("H264 post event: %d\n", *event);
}
static int vdec_h264_set_param(unsigned long h_vdec,
@@ -849,10 +998,17 @@ static int vdec_h264_set_param(unsigned long h_vdec,
set_param_write_sync(inst);
break;
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
+ break;
+
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
break;
+ case SET_PARAM_POST_EVENT:
+ set_param_post_event(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index 59ce85f..cd4d361 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -26,6 +26,7 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
@@ -112,6 +113,7 @@ struct vdec_hevc_inst {
struct aml_vdec_adapt vdec;
struct vdec_hevc_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -144,6 +146,54 @@ static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
aml_vcodec_debug(inst, "sz=%d", *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_buffer_margin:7;");
+ pbuf += sprintf(pbuf, "hevc_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
+ pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_hevc_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_buffer_margin:%d;",
+ ctx->config.parm.dec.cfg.ref_buf_margin);
+ pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;",
+ ctx->config.parm.dec.cfg.double_write_mode);
+ pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
+ pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_endian);
+ ctx->config.length = pbuf - ctx->config.buf;
+ } else {
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
+ ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+ 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_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_hevc_inst *inst = NULL;
@@ -153,12 +203,13 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_HEVC;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_HEVC;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -168,54 +219,53 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vdec.port.type = PORT_TYPE_HEVC;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ pr_err("%s, init vfm failed.\n", __func__);
+ goto err;
+ }
ret = video_decoder_init(&inst->vdec);
if (ret) {
aml_vcodec_err(inst, "vdec_hevc init err=%d", ret);
- goto error_free_inst;
+ goto err;
}
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_hevc_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) {
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "hevc Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
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;
@@ -252,17 +302,76 @@ static int refer_buffer_num(struct h265_SPS_t *sps)
return used_buf_num;
}
+static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode)
+{
+ u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
+ int w = inst->parms.cfg.init_width;
+ int h = inst->parms.cfg.init_height;
+ 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 vdec_pic_scale(struct vdec_hevc_inst *inst, int length, int dw_mode)
+{
+ int ret = 64;
+
+ switch (vdec_get_dw_mode(inst, dw_mode)) {
+ case 0x0: /* only afbc, output afbc */
+ ret = 64;
+ break;
+ case 0x1: /* afbc and (w x h), output YUV420 */
+ ret = length;
+ break;
+ case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+ case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+ ret = length >> 2;
+ break;
+ case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+ ret = length >> 1;
+ break;
+ case 0x10: /* (w x h), output YUV420-8bit)*/
+ default:
+ ret = length;
+ break;
+ }
+
+ return ret;
+}
+
static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
+ int dw = inst->parms.cfg.double_write_mode;
+ int margin = inst->parms.cfg.ref_buf_margin;
/* fill visible area size that be used for EGL. */
pic->visible_width = sps->width - (sps->output_window.left_offset +
sps->output_window.right_offset);
pic->visible_height = sps->height - (sps->output_window.top_offset +
sps->output_window.bottom_offset);
+ pic->visible_width = vdec_pic_scale(inst, pic->visible_width, dw);
+ pic->visible_height = vdec_pic_scale(inst, pic->visible_height, dw);
/* calc visible ares. */
rect->left = 0;
@@ -271,18 +380,26 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(sps->width, 32);
- pic->coded_height = ALIGN(sps->height, 32);
+ pic->coded_width = vdec_pic_scale(inst, ALIGN(sps->width, 32), dw);
+ pic->coded_height = vdec_pic_scale(inst, ALIGN(sps->height, 32), dw);
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 = refer_buffer_num(sps);
+ dec->dpb_sz = refer_buffer_num(sps) + margin;
- pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
- inst->ctx->id, pic->coded_width, pic->coded_height,
- pic->visible_width, pic->visible_height, dec->dpb_sz);
+ inst->parms.ps.visible_width = pic->visible_width;
+ inst->parms.ps.visible_height = pic->visible_height;
+ inst->parms.ps.coded_width = pic->coded_width;
+ inst->parms.ps.coded_height = pic->coded_height;
+ inst->parms.ps.dpb_size = dec->dpb_sz;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+ pr_info("[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id, 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)
@@ -308,7 +425,7 @@ static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
int ret = 0;
struct h265_param_sets *ps = NULL;
- ps = kzalloc(sizeof(struct h265_param_sets), GFP_KERNEL);
+ ps = vzalloc(sizeof(struct h265_param_sets));
if (ps == NULL)
return -ENOMEM;
@@ -323,7 +440,7 @@ static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
ret = ps->sps_parsed ? 0 : -1;
out:
- kfree(ps);
+ vfree(ps);
return ret;
}
@@ -452,19 +569,22 @@ static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
if (type == HEVC_NAL_SPS) {
ret = stream_parse(inst, p, len);
- if (!ret && (inst->vsi->cur_pic.coded_width !=
- inst->vsi->pic.coded_width ||
- inst->vsi->cur_pic.coded_height !=
- inst->vsi->pic.coded_height)) {
- inst->vsi->cur_pic = inst->vsi->pic;
- return true;
- }
+ if (ret)
+ break;
}
p += j;
}
p++;
}
+ if (!ret && (inst->vsi->cur_pic.coded_width !=
+ inst->vsi->pic.coded_width ||
+ inst->vsi->cur_pic.coded_height !=
+ inst->vsi->pic.coded_height)) {
+ inst->vsi->cur_pic = inst->vsi->pic;
+ return true;
+ }
+
return false;
}
@@ -478,10 +598,12 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
u32 size;
int ret = -1;
- /* bs NULL means flush decoder */
if (bs == NULL)
return -1;
+ if (vdec_input_full(vdec))
+ return -EAGAIN;
+
buf = (u8 *)bs->vaddr;
size = bs->size;
st = (struct stream_info *)buf;
@@ -505,6 +627,23 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return ret;
}
+ static void get_param_config_info(struct vdec_hevc_inst *inst,
+ struct aml_dec_params *parms)
+ {
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+ parms->cfg = inst->parms.cfg;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+ parms->ps = inst->parms.ps;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+ parms->hdr = inst->parms.hdr;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+ parms->cnt = inst->parms.cnt;
+
+ parms->parms_status |= inst->parms.parms_status;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->parms_status);
+ }
+
static int vdec_hevc_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -537,6 +676,9 @@ static int vdec_hevc_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -550,16 +692,16 @@ static void set_param_write_sync(struct vdec_hevc_inst *inst)
complete(&inst->comp);
}
-static void set_param_pic_info(struct vdec_hevc_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_hevc_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
/* fill visible area size that be used for EGL. */
- pic->visible_width = info->visible_width;
- pic->visible_height = info->visible_height;
+ pic->visible_width = ps->visible_width;
+ pic->visible_height = ps->visible_height;
/* calc visible ares. */
rect->left = 0;
@@ -568,12 +710,16 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(info->coded_width, 64);
- pic->coded_height = ALIGN(info->coded_height, 64);
+ pic->coded_width = ALIGN(ps->coded_width, 64);
+ pic->coded_height = ALIGN(ps->coded_height, 64);
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
- dec->dpb_sz = info->dpb_size;
+ dec->dpb_sz = ps->dpb_size;
+
+ inst->parms.ps = *ps;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PSINFO;
/*wake up*/
complete(&inst->comp);
@@ -584,6 +730,26 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst,
dec->dpb_sz);
}
+static void set_param_hdr_info(struct vdec_hevc_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ if (!(inst->parms.parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+ inst->parms.hdr = *hdr;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+ aml_vdec_dispatch_event(inst->ctx,
+ V4L2_EVENT_SRC_CH_HDRINFO);
+ pr_info("H265 set HDR infos\n");
+ }
+}
+
+static void set_param_post_event(struct vdec_hevc_inst *inst, u32 *event)
+{
+ aml_vdec_dispatch_event(inst->ctx, *event);
+ pr_info("H265 post event: %d\n", *event);
+}
+
static int vdec_hevc_set_param(unsigned long h_vdec,
enum vdec_set_param_type type, void *in)
{
@@ -600,10 +766,17 @@ static int vdec_hevc_set_param(unsigned long h_vdec,
set_param_write_sync(inst);
break;
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
break;
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
+ break;
+
+ case SET_PARAM_POST_EVENT:
+ set_param_post_event(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
index 8bc5faa..0db4eca 100644
--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -151,12 +151,12 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
-
- inst->vdec.video_type = VFORMAT_MJPEG;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ inst->vdec.video_type = VFORMAT_MJPEG;
+ 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;
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -194,15 +194,15 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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);
aml_vcodec_debug(inst, "mjpeg Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
@@ -451,8 +451,8 @@ static int vdec_mjpeg_get_param(unsigned long h_vdec,
return ret;
}
-static void set_param_pic_info(struct vdec_mjpeg_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_mjpeg_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
pr_info("---%s, %d\n", __func__, __LINE__);
}
@@ -469,8 +469,8 @@ static int vdec_mjpeg_set_param(unsigned long h_vdec,
}
switch (type) {
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
break;
default:
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
index cdde95b..5d5ca07 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -151,12 +151,12 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
-
- inst->vdec.video_type = VFORMAT_MPEG12;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ inst->vdec.video_type = VFORMAT_MPEG12;
+ 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;
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -166,8 +166,8 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vdec.port.type = PORT_TYPE_VIDEO;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -194,15 +194,15 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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);
aml_vcodec_debug(inst, "mpeg12 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
@@ -443,8 +443,8 @@ static int vdec_mpeg12_get_param(unsigned long h_vdec,
return ret;
}
-static void set_param_pic_info(struct vdec_mpeg12_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_mpeg12_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
pr_info("---%s, %d\n", __func__, __LINE__);
}
@@ -461,8 +461,8 @@ static int vdec_mpeg12_set_param(unsigned long h_vdec,
}
switch (type) {
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
break;
default:
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
index 7a40a4a..ab428af 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -151,24 +151,24 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
-
- inst->vdec.video_type = VFORMAT_MPEG4;
- inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ inst->vdec.video_type = VFORMAT_MPEG4;
+ inst->vdec.format = 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;
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
/* to eable mpeg4 hw.*/
- inst->vdec.port.type = PORT_TYPE_VIDEO;
+ inst->vdec.port.type = PORT_TYPE_VIDEO;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -195,15 +195,15 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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);
aml_vcodec_debug(inst, "mpeg4 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
@@ -452,8 +452,8 @@ static int vdec_mpeg4_get_param(unsigned long h_vdec,
return ret;
}
-static void set_param_pic_info(struct vdec_mpeg4_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_mpeg4_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
pr_info("---%s, %d\n", __func__, __LINE__);
}
@@ -470,8 +470,8 @@ static int vdec_mpeg4_set_param(unsigned long h_vdec,
}
switch (type) {
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
break;
default:
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
index 5b3bbab..7d395ba 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -26,12 +26,16 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
#include "aml_vp9_parser.h"
#include "vdec_vp9_trigger.h"
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
#define PREFIX_SIZE (16)
#define NAL_TYPE(value) ((value) & 0x1F)
@@ -120,6 +124,7 @@ struct vdec_vp9_inst {
struct aml_vdec_adapt vdec;
struct vdec_vp9_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -155,6 +160,94 @@ static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz)
aml_vcodec_debug(inst, "sz=%d", *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_buffer_margin:7;");
+ pbuf += sprintf(pbuf, "vp9_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "vp9_buf_width:1920;");
+ pbuf += sprintf(pbuf, "vp9_buf_height:1088;");
+ pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;");
+ pbuf += sprintf(pbuf, "vp9_max_pic_h:2304;");
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+ pbuf += sprintf(pbuf, "no_head:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_vp9_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_buffer_margin:%d;",
+ ctx->config.parm.dec.cfg.ref_buf_margin);
+ pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;",
+ ctx->config.parm.dec.cfg.double_write_mode);
+ pbuf += sprintf(pbuf, "vp9_buf_width:%d;",
+ ctx->config.parm.dec.cfg.init_width);
+ pbuf += sprintf(pbuf, "vp9_buf_height:%d;",
+ ctx->config.parm.dec.cfg.init_height);
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+ pbuf += sprintf(pbuf, "no_head:0;");
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+ ctx->config.parm.dec.cfg.canvas_mem_endian);
+ ctx->config.length = pbuf - ctx->config.buf;
+ } else {
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
+ ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+ ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+ }
+
+ if ((ctx->config.parm.dec.parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
+ inst->parms.hdr.color_parms.present_flag) {
+ u8 *pbuf = ctx->config.buf + ctx->config.length;
+
+ pbuf += sprintf(pbuf, "mG.x:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[0][0]);
+ pbuf += sprintf(pbuf, "mG.y:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[0][1]);
+ pbuf += sprintf(pbuf, "mB.x:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[1][0]);
+ pbuf += sprintf(pbuf, "mB.y:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[1][1]);
+ pbuf += sprintf(pbuf, "mR.x:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[2][0]);
+ pbuf += sprintf(pbuf, "mR.y:%d;",
+ ctx->config.parm.dec.hdr.color_parms.primaries[2][1]);
+ pbuf += sprintf(pbuf, "mW.x:%d;",
+ ctx->config.parm.dec.hdr.color_parms.white_point[0]);
+ pbuf += sprintf(pbuf, "mW.y:%d;",
+ ctx->config.parm.dec.hdr.color_parms.white_point[1]);
+ pbuf += sprintf(pbuf, "mMaxDL:%d;",
+ ctx->config.parm.dec.hdr.color_parms.luminance[0] / 1000);
+ pbuf += sprintf(pbuf, "mMinDL:%d;",
+ ctx->config.parm.dec.hdr.color_parms.luminance[1]);
+ pbuf += sprintf(pbuf, "mMaxCLL:%d;",
+ ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content);
+ pbuf += sprintf(pbuf, "mMaxFALL:%d;",
+ ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average);
+ ctx->config.length = pbuf - ctx->config.buf;
+ inst->parms.hdr = ctx->config.parm.dec.hdr;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO;
+ }
+
+ 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_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_vp9_inst *inst = NULL;
@@ -164,70 +257,70 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_VP9;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_VP9;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
/* to eable vp9 hw.*/
- inst->vdec.port.type = PORT_TYPE_HEVC;
+ inst->vdec.port.type = PORT_TYPE_HEVC;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
- vcodec_vfm_init(&inst->vfm);
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
+ ret = vcodec_vfm_init(&inst->vfm);
+ if (ret) {
+ pr_err("%s, init vfm failed.\n", __func__);
+ goto err;
+ }
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_vp9_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) {
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "vp9 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
/* init decoder. */
ret = video_decoder_init(&inst->vdec);
if (ret) {
aml_vcodec_err(inst, "vdec_vp9 init err=%d", ret);
- goto error_free_inst;
+ goto err;
}
//dump_init();
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;
@@ -241,16 +334,73 @@ static int refer_buffer_num(int level_idc, int poc_cnt,
}
#endif
+static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode)
+{
+ u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
+ int w = inst->parms.cfg.init_width;
+ int h = inst->parms.cfg.init_height;
+ 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 vdec_pic_scale(struct vdec_vp9_inst *inst, int length, int dw_mode)
+{
+ int ret = 64;
+
+ switch (vdec_get_dw_mode(inst, dw_mode)) {
+ case 0x0: /* only afbc, output afbc */
+ ret = 64;
+ break;
+ case 0x1: /* afbc and (w x h), output YUV420 */
+ ret = length;
+ break;
+ case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+ case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+ ret = length >> 2;
+ break;
+ case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+ ret = length >> 1;
+ break;
+ case 0x10: /* (w x h), output YUV420-8bit) */
+ default:
+ ret = length;
+ break;
+ }
+
+ return ret;
+}
+
static void fill_vdec_params(struct vdec_vp9_inst *inst,
struct VP9Context *vp9_ctx)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
+ int dw = inst->parms.cfg.double_write_mode;
+ int margin = inst->parms.cfg.ref_buf_margin;
/* fill visible area size that be used for EGL. */
- pic->visible_width = vp9_ctx->render_width;
- pic->visible_height = vp9_ctx->render_height;
+ pic->visible_width = vdec_pic_scale(inst, vp9_ctx->render_width, dw);
+ pic->visible_height = vdec_pic_scale(inst, vp9_ctx->render_height, dw);
/* calc visible ares. */
rect->left = 0;
@@ -259,18 +409,26 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(vp9_ctx->width, 32);
- pic->coded_height = ALIGN(vp9_ctx->height, 32);
+ pic->coded_width = vdec_pic_scale(inst, ALIGN(vp9_ctx->width, 32), dw);
+ pic->coded_height = vdec_pic_scale(inst, ALIGN(vp9_ctx->height, 32), dw);
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 = 5;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
-
- aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
- inst->ctx->id, pic->coded_width, pic->coded_height,
- pic->visible_width, pic->visible_height, dec->dpb_sz);
+ dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+
+ inst->parms.ps.visible_width = pic->visible_width;
+ inst->parms.ps.visible_height = pic->visible_height;
+ inst->parms.ps.coded_width = pic->coded_width;
+ inst->parms.ps.coded_height = pic->coded_height;
+ inst->parms.ps.dpb_size = dec->dpb_sz;
+ inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+ aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id, 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)
@@ -295,7 +453,7 @@ static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
int ret = 0;
struct vp9_param_sets *ps = NULL;
- ps = kzalloc(sizeof(struct vp9_param_sets), GFP_KERNEL);
+ ps = vzalloc(sizeof(struct vp9_param_sets));
if (ps == NULL)
return -ENOMEM;
@@ -310,7 +468,7 @@ static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
ret = ps->head_parsed ? 0 : -1;
out:
- kfree(ps);
+ vfree(ps);
return ret;
}
@@ -550,10 +708,14 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
u32 size;
int ret = -1;
- /* bs NULL means flush decoder */
if (bs == NULL)
return -1;
+ if (vdec_input_full(vdec)) {
+ ATRACE_COUNTER("vdec_input_full", 0);
+ return -EAGAIN;
+ }
+
buf = (u8 *)bs->vaddr;
size = bs->size;
st = (struct stream_info *)buf;
@@ -573,10 +735,28 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
ret = vdec_write_nalu(inst, buf, size, timestamp);
}
+ ATRACE_COUNTER("v4l2_decode_write", ret);
return ret;
}
+ static void get_param_config_info(struct vdec_vp9_inst *inst,
+ struct aml_dec_params *parms)
+ {
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+ parms->cfg = inst->parms.cfg;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+ parms->ps = inst->parms.ps;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+ parms->hdr = inst->parms.hdr;
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+ parms->cnt = inst->parms.cnt;
+
+ parms->parms_status |= inst->parms.parms_status;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->parms_status);
+ }
+
static int vdec_vp9_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -609,6 +789,9 @@ static int vdec_vp9_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -622,16 +805,16 @@ static void set_param_write_sync(struct vdec_vp9_inst *inst)
complete(&inst->comp);
}
-static void set_param_pic_info(struct vdec_vp9_inst *inst,
- struct aml_vdec_pic_infos *info)
+static void set_param_ps_info(struct vdec_vp9_inst *inst,
+ struct aml_vdec_ps_infos *ps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
/* fill visible area size that be used for EGL. */
- pic->visible_width = info->visible_width;
- pic->visible_height = info->visible_height;
+ pic->visible_width = ps->visible_width;
+ pic->visible_height = ps->visible_height;
/* calc visible ares. */
rect->left = 0;
@@ -640,22 +823,46 @@ static void set_param_pic_info(struct vdec_vp9_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = info->coded_width;
- pic->coded_height = info->coded_height;
+ 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;
/* calc DPB size */
- dec->dpb_sz = 5;
+ dec->dpb_sz = 5;
+
+ inst->parms.ps = *ps;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PSINFO;
/*wake up*/
complete(&inst->comp);
pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
- info->visible_width, info->visible_height,
- info->coded_width, info->coded_height,
- info->dpb_size);
+ ps->visible_width, ps->visible_height,
+ ps->coded_width, ps->coded_height,
+ ps->dpb_size);
+}
+
+static void set_param_hdr_info(struct vdec_vp9_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ if ((inst->parms.parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+ inst->parms.hdr = *hdr;
+ inst->parms.parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+ aml_vdec_dispatch_event(inst->ctx,
+ V4L2_EVENT_SRC_CH_HDRINFO);
+ pr_info("VP9 set HDR infos\n");
+ }
+}
+
+static void set_param_post_event(struct vdec_vp9_inst *inst, u32 *event)
+{
+ aml_vdec_dispatch_event(inst->ctx, *event);
+ pr_info("VP9 post event: %d\n", *event);
}
static int vdec_vp9_set_param(unsigned long h_vdec,
@@ -674,10 +881,17 @@ static int vdec_vp9_set_param(unsigned long h_vdec,
set_param_write_sync(inst);
break;
- case SET_PARAM_PIC_INFO:
- set_param_pic_info(inst, in);
+ case SET_PARAM_PS_INFO:
+ set_param_ps_info(inst, in);
break;
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
+ break;
+
+ case SET_PARAM_POST_EVENT:
+ set_param_post_event(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index 29e48d3..d3ccef2 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -68,15 +68,18 @@ enum vdec_get_param_type {
GET_PARAM_FREE_FRAME_BUFFER,
GET_PARAM_PIC_INFO,
GET_PARAM_CROP_INFO,
- GET_PARAM_DPB_SIZE
+ GET_PARAM_DPB_SIZE,
+ GET_PARAM_CONFIG_INFO
};
/*
- * SET_PARAM_PIC_INFO : set picture info, data parsed from ucode.
+ * SET_PARAM_PS_INFO : set picture parms, data parsed from ucode.
*/
enum vdec_set_param_type {
SET_PARAM_WRITE_FRAME_SYNC,
- SET_PARAM_PIC_INFO,
+ SET_PARAM_PS_INFO,
+ SET_PARAM_HDR_INFO,
+ SET_PARAM_POST_EVENT
};
/**
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c
index 6258a75..f90fee6 100644
--- a/drivers/frame_provider/decoder/avs2/vavs2.c
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -761,6 +761,7 @@ struct AVS2Decoder_s {
#endif
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
+ u32 dynamic_buf_margin;
};
static int compute_losless_comp_body_size(
@@ -3885,7 +3886,7 @@ static int avs2_local_init(struct AVS2Decoder_s *dec)
#ifndef AVS2_10B_MMU
init_buf_list(dec);
#else
- dec->used_buf_num = max_buf_num;
+ dec->used_buf_num = max_buf_num + dec->dynamic_buf_margin;
if (dec->used_buf_num > MAX_BUF_NUM)
dec->used_buf_num = MAX_BUF_NUM;
if (dec->used_buf_num > FRAME_BUFFERS)
@@ -7318,6 +7319,13 @@ static int ammvdec_avs2_probe(struct platform_device *pdev)
dec->double_write_mode = config_val;
else
dec->double_write_mode = double_write_mode;
+
+ if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ dec->dynamic_buf_margin = config_val;
+ else
+ dec->dynamic_buf_margin = 0;
+
if (get_config_int(pdata->config, "HDRStaticInfo",
&vf_dp.present_flag) == 0
&& vf_dp.present_flag == 1) {
@@ -7363,6 +7371,7 @@ static int ammvdec_avs2_probe(struct platform_device *pdev)
dec->vavs2_amstream_dec_info.height = 0;
dec->vavs2_amstream_dec_info.rate = 30;*/
dec->double_write_mode = double_write_mode;
+ dec->dynamic_buf_margin = dynamic_buf_num_margin;
}
video_signal_type = dec->video_signal_type;
diff --git a/drivers/frame_provider/decoder/h264/vh264_mvc.c b/drivers/frame_provider/decoder/h264/vh264_mvc.c
index fdb0535..821b3c1 100644
--- a/drivers/frame_provider/decoder/h264/vh264_mvc.c
+++ b/drivers/frame_provider/decoder/h264/vh264_mvc.c
@@ -46,6 +46,7 @@
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/firmware.h"
#include <linux/amlogic/tee.h>
+#include "../utils/config_parser.h"
#define TIME_TASK_PRINT_ENABLE 0x100
#define PUT_PRINT_ENABLE 0x200
@@ -185,9 +186,11 @@ static s32 vh264mvc_init(void);
unsigned int DECODE_BUFFER_START = 0x00200000;
unsigned int DECODE_BUFFER_END = 0x05000000;
+/* #define DISPLAY_BUFFER_NUM 4 */
+static unsigned int dynamic_buf_num_margin = 8;
+
#define DECODE_BUFFER_NUM_MAX 16
-#define DISPLAY_BUFFER_NUM 4
-#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + DISPLAY_BUFFER_NUM)
+#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + dynamic_buf_num_margin)
#define TOTAL_BMMU_BUFF_NUM (MAX_BMMU_BUFFER_NUM * 2 + 3)
#define VF_BUFFER_IDX(n) (2 + n)
@@ -223,8 +226,12 @@ struct buffer_spec_s {
unsigned long phy_addr;
int alloc_count;
};
+/*
static struct buffer_spec_s buffer_spec0[MAX_BMMU_BUFFER_NUM];
static struct buffer_spec_s buffer_spec1[MAX_BMMU_BUFFER_NUM];
+*/
+static struct buffer_spec_s *buffer_spec0;
+static struct buffer_spec_s *buffer_spec1;
static void *mm_blk_handle;
/*
@@ -741,7 +748,7 @@ static void do_alloc_work(struct work_struct *work)
mb_width, mb_height);
total_dec_frame_buffering[0] =
- max_dec_frame_buffering[0] + DISPLAY_BUFFER_NUM;
+ max_dec_frame_buffering[0] + dynamic_buf_num_margin;
mb_width = (mb_width + 3) & 0xfffffffc;
mb_height = (mb_height + 3) & 0xfffffffc;
@@ -822,7 +829,7 @@ static void do_alloc_work(struct work_struct *work)
}
total_dec_frame_buffering[1] =
- max_dec_frame_buffering[1] + DISPLAY_BUFFER_NUM;
+ max_dec_frame_buffering[1] + dynamic_buf_num_margin;
mb_width = (mb_width + 3) & 0xfffffffc;
mb_height = (mb_height + 3) & 0xfffffffc;
@@ -1369,6 +1376,7 @@ static int vh264mvc_local_init(void)
max_dec_frame_buffering[1] = -1;
fill_ptr = get_ptr = put_ptr = putting_ptr = 0;
dirty_frame_num = 0;
+
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
view0_vfbuf_use[i] = 0;
view1_vfbuf_use[i] = 0;
@@ -1412,7 +1420,6 @@ static s32 vh264mvc_init(void)
{
int ret = -1;
char *buf = vmalloc(0x1000 * 16);
-
if (buf == NULL)
return -ENOMEM;
@@ -1582,6 +1589,7 @@ static void error_do_work(struct work_struct *work)
static int amvdec_h264mvc_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+ int config_val = 0;
pr_info("amvdec_h264mvc probe start.\n");
mutex_lock(&vh264_mvc_mutex);
@@ -1603,13 +1611,28 @@ static int amvdec_h264mvc_probe(struct platform_device *pdev)
if (pdata->sys_info)
vh264mvc_amstream_dec_info = *pdata->sys_info;
+ if (pdata->config_len) {
+ pr_info("pdata->config: %s\n", pdata->config);
+ if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ dynamic_buf_num_margin = config_val;
+ }
+
pdata->dec_status = vh264mvc_dec_status;
/* pdata->set_trickmode = vh264mvc_set_trickmode; */
+ buffer_spec0 = (struct buffer_spec_s *)vzalloc(
+ sizeof(struct buffer_spec_s) * MAX_BMMU_BUFFER_NUM * 2);
+ if (NULL == buffer_spec0)
+ return -ENOMEM;
+ buffer_spec1 = &buffer_spec0[MAX_BMMU_BUFFER_NUM];
+
if (vh264mvc_init() < 0) {
pr_info("\namvdec_h264mvc init failed.\n");
kfree(gvs);
gvs = NULL;
+ vfree(buffer_spec0);
+ buffer_spec0 = NULL;
mutex_unlock(&vh264_mvc_mutex);
return -ENODEV;
}
@@ -1649,6 +1672,8 @@ static int amvdec_h264mvc_remove(struct platform_device *pdev)
#ifdef DEBUG_SKIP
pr_info("view_total = %ld, dropped %ld\n", view_total, view_dropped);
#endif
+ vfree(buffer_spec0);
+ buffer_spec0 = NULL;
kfree(gvs);
gvs = NULL;
@@ -1734,6 +1759,9 @@ MODULE_PARM_DESC(stat, "\n amvdec_h264mvc stat\n");
module_param(dbg_mode, uint, 0664);
MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc dbg mode\n");
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n amvdec_h264mvc dynamic_buf_num_margin\n");
+
module_param(view_mode, uint, 0664);
MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n");
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
index 35d67ad..c2e0e91 100644
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -61,6 +61,7 @@
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
#include <linux/crc32.h>
+#include <media/v4l2-mem2mem.h>
#undef pr_info
#define pr_info printk
@@ -117,6 +118,7 @@
#define H264_MMU
#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000
+#define INVALID_IDX -1 /* Invalid buffer index.*/
static int mmu_enable;
/*mmu do not support mbaff*/
@@ -158,6 +160,8 @@ static u32 run_ready_display_q_num;
static u32 run_ready_max_buf_num = 0xff;
#endif
+static u32 run_ready_min_buf_num = 2;
+
#define VDEC_ASSIST_CANVAS_BLK32 0x5
@@ -845,6 +849,7 @@ struct vdec_h264_hw_s {
bool new_iframe_flag;
bool ref_err_flush_dpb_flag;
unsigned int first_i_policy;
+ u32 reorder_dpb_size_margin;
};
static u32 again_threshold;
@@ -854,7 +859,7 @@ static void dump_bufspec(struct vdec_h264_hw_s *hw,
const char *caller);
static void h264_reconfig(struct vdec_h264_hw_s *hw);
static void h264_reset_bufmgr(struct vdec_s *vdec);
-static void vh264_local_init(struct vdec_h264_hw_s *hw);
+static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset);
static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw);
static int vh264_stop(struct vdec_h264_hw_s *hw);
static s32 vh264_init(struct vdec_h264_hw_s *hw);
@@ -947,11 +952,10 @@ static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx,
}
return decoder_mmu_box_alloc_idx(
- hw->mmu_box,
- cur_buf_idx,
- cur_mmu_4k_number,
- mmu_index_adr);
-
+ hw->mmu_box,
+ cur_buf_idx,
+ cur_mmu_4k_number,
+ mmu_index_adr);
}
static int compute_losless_comp_body_size(int width,
@@ -1061,7 +1065,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore)
int num_buff = hw->dpb.mDPB.size;
int dw_size = 0;
u32 dw_buffer_size_u_v_h;
- u32 blkmode = mem_map_mode;
+ u32 blkmode = hw->canvas_mode;
int dw_mode = hw->double_write_mode;
canvas_addr = ANC0_CANVAS_ADDR;
@@ -1115,7 +1119,7 @@ static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore)
canvas_h = hw->frame_height /
get_double_write_ratio(hw);
- if (mem_map_mode == 0)
+ if (hw->canvas_mode == 0)
canvas_w = ALIGN(canvas_w, 32);
else
canvas_w = ALIGN(canvas_w, 64);
@@ -1315,7 +1319,7 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw,
#endif
data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
data32 &= (~0x30);
- data32 |= (mem_map_mode << 4);
+ data32 |= (hw->canvas_mode << 4);
WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,
@@ -1360,9 +1364,9 @@ static void hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw,
data32 |= endian; /* Big-Endian per 64-bit */
if (hw->mmu_enable && dw_mode)
- data32 |= ((mem_map_mode << 12));
+ data32 |= ((hw->canvas_mode << 12));
else
- data32 |= ((mem_map_mode << 12)|2);
+ data32 |= ((hw->canvas_mode << 12)|2);
WRITE_VREG(HEVC_SAO_CTRL1, data32);
@@ -1603,10 +1607,36 @@ static void buf_spec_init(struct vdec_h264_hw_s *hw)
int i;
unsigned long flags;
spin_lock_irqsave(&hw->bufspec_lock, flags);
+
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i];
+ u32 ref_idx = BUFSPEC_INDEX(vf->index);
+ if ((vf->index != -1) &&
+ (hw->buffer_spec[ref_idx].vf_ref == 0) &&
+ (hw->buffer_spec[ref_idx].used != -1)) {
+ vf->index = -1;
+ }
+ }
+
+ hw->cur_pool++;
+ if (hw->cur_pool >= VF_POOL_NUM)
+ hw->cur_pool = 0;
+
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i];
+ u32 ref_idx = BUFSPEC_INDEX(vf->index);
+ if ((vf->index != -1) &&
+ (hw->buffer_spec[ref_idx].vf_ref == 0) &&
+ (hw->buffer_spec[ref_idx].used != -1)) {
+ vf->index = -1;
+ }
+ }
+
for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
hw->buffer_spec[i].used = -1;
hw->buffer_spec[i].canvas_pos = -1;
}
+
if (dpb_is_debug(DECODE_ID(hw),
PRINT_FLAG_DUMP_BUFSPEC))
dump_bufspec(hw, __func__);
@@ -1654,7 +1684,7 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
if (IS_VDEC_DW(hw) == 1)
buf_size += (hw->mb_total << 7) + (hw->mb_total << 6);
else if (IS_VDEC_DW(hw) == 2)
- buf_size += (hw->mb_total << 6) + (hw->mb_total << 6);
+ buf_size += (hw->mb_total << 6) + (hw->mb_total << 5);
#endif
if (hw->buffer_spec[i].cma_alloc_addr)
return 0;
@@ -1798,7 +1828,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
(hw->mb_total << 8) + (hw->mb_total << 7));
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] get fb fail.\n", ctx->id);
return ret;
@@ -1837,7 +1867,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
y_canvas_cfg->phy_addr = y_addr;
y_canvas_cfg->width = hw->mb_width << 4;
y_canvas_cfg->height = hw->mb_height << 4;
- y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR;
+ y_canvas_cfg->block_mode = hw->canvas_mode;
//fb->m.mem[0].bytes_used = y_canvas_cfg->width * y_canvas_cfg->height;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__,
@@ -1846,7 +1876,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
c_canvas_cfg->phy_addr = c_addr;
c_canvas_cfg->width = hw->mb_width << 4;
c_canvas_cfg->height = hw->mb_height << 3;
- c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR;
+ c_canvas_cfg->block_mode = hw->canvas_mode;
//fb->m.mem[1].bytes_used = c_canvas_cfg->width * c_canvas_cfg->height;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__,
@@ -1860,24 +1890,18 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
{
- struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
- int blkmode = CANVAS_BLKMODE_32X32;
+ int blkmode = hw->canvas_mode;
int endian = 0;
- if (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) {
- blkmode = CANVAS_BLKMODE_LINEAR;
+ if (blkmode == CANVAS_BLKMODE_LINEAR) {
if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0)
endian = 7;
else
endian = 0;
}
- if (hw->is_used_v4l) {
- blkmode = CANVAS_BLKMODE_LINEAR;
- if (v4l2_ctx->ada_ctx->vfm_path
- != FRAME_BASE_PATH_V4L_VIDEO)
+ if (hw->is_used_v4l)
endian = 7;
- }
canvas_config_ex(hw->buffer_spec[i].
y_canvas_index,
@@ -1990,7 +2014,7 @@ static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i)
{
- u32 blkmode = mem_map_mode;
+ u32 blkmode = hw->canvas_mode;
int canvas_w;
int canvas_h;
@@ -1999,7 +2023,7 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i)
canvas_h = hw->frame_height /
get_double_write_ratio(hw);
- if (mem_map_mode == 0)
+ if (hw->canvas_mode == 0)
canvas_w = ALIGN(canvas_w, 32);
else
canvas_w = ALIGN(canvas_w, 64);
@@ -2024,6 +2048,55 @@ static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i)
7);
}
+static int v4l_get_free_buf_idx(struct vdec_s *vdec)
+{
+ struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+ struct aml_vcodec_ctx * v4l = hw->v4l2_ctx;
+ struct v4l_buff_pool *pool = &v4l->cap_pool;
+ struct buffer_spec_s *pic = NULL;
+ int i, idx = INVALID_IDX;
+ ulong flags;
+
+ spin_lock_irqsave(&hw->bufspec_lock, flags);
+ for (i = 0; i < pool->in; ++i) {
+ u32 state = (pool->seq[i] >> 16);
+ u32 index = (pool->seq[i] & 0xffff);
+
+ switch (state) {
+ case V4L_CAP_BUFF_IN_DEC:
+ pic = &hw->buffer_spec[i];
+ if ((pic->vf_ref == 0) &&
+ (pic->used == 0) &&
+ pic->cma_alloc_addr) {
+ idx = i;
+ }
+ break;
+ case V4L_CAP_BUFF_IN_M2M:
+ pic = &hw->buffer_spec[index];
+ if (!alloc_one_buf_spec_from_queue(hw, index)) {
+ config_decode_canvas(hw, index);
+ idx = index;
+ }
+ break;
+ default:
+ pr_err("v4l buffer state err %d.\n", state);
+ break;
+ }
+
+ if (idx != INVALID_IDX) {
+ pic->used = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+
+ if (idx < 0) {
+ dpb_print(DECODE_ID(hw), 0, "%s fail\n", __func__);
+ vmh264_dump_state(vdec);
+ }
+
+ return idx;
+}
int get_free_buf_idx(struct vdec_s *vdec)
{
@@ -2034,23 +2107,18 @@ int get_free_buf_idx(struct vdec_s *vdec)
int buf_total = BUFSPEC_POOL_SIZE;
if (hw->is_used_v4l)
- buf_total = hw->dpb.mDPB.size;
+ return v4l_get_free_buf_idx(vdec);
spin_lock_irqsave(&hw->bufspec_lock, flags);
/*hw->start_search_pos = 0;*/
for (i = hw->start_search_pos; i < buf_total; i++) {
if (hw->mmu_enable)
addr = hw->buffer_spec[i].alloc_header_addr;
- else {
+ else
addr = hw->buffer_spec[i].cma_alloc_addr;
- if (hw->is_used_v4l && !addr) {
- if (!alloc_one_buf_spec_from_queue(hw, i)) {
- config_decode_canvas(hw, i);
- addr = hw->buffer_spec[i].cma_alloc_addr;
- }
- }
- }
- if (hw->buffer_spec[i].used == 0 && addr) {
+
+ if (hw->buffer_spec[i].vf_ref == 0 &&
+ hw->buffer_spec[i].used == 0 && addr) {
hw->buffer_spec[i].used = 1;
hw->start_search_pos = i+1;
index = i;
@@ -2061,16 +2129,11 @@ int get_free_buf_idx(struct vdec_s *vdec)
for (i = 0; i < hw->start_search_pos; i++) {
if (hw->mmu_enable)
addr = hw->buffer_spec[i].alloc_header_addr;
- else {
+ else
addr = hw->buffer_spec[i].cma_alloc_addr;
- if (hw->is_used_v4l && !addr) {
- if (!alloc_one_buf_spec_from_queue(hw, i)) {
- config_decode_canvas(hw, i);
- addr = hw->buffer_spec[i].cma_alloc_addr;
- }
- }
- }
- if (hw->buffer_spec[i].used == 0 && addr) {
+
+ if (hw->buffer_spec[i].vf_ref == 0 &&
+ hw->buffer_spec[i].used == 0 && addr) {
hw->buffer_spec[i].used = 1;
hw->start_search_pos = i+1;
index = i;
@@ -2325,16 +2388,35 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec)
int i;
unsigned long addr;
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+ struct aml_vcodec_ctx * v4l = hw->v4l2_ctx;
int canvas_pos_min = BUFSPEC_POOL_SIZE;
int index = -1;
int ret = 0;
int allocated_count = 0;
+
+ if (hw->is_used_v4l) {
+ for (i = 0; i < hw->dpb.mDPB.size; i++) {
+ if (hw->buffer_spec[i].used == 0 &&
+ hw->buffer_spec[i].vf_ref == 0 &&
+ hw->buffer_spec[i].cma_alloc_addr) {
+ return 1;
+ }
+ }
+
+ if (v4l2_m2m_num_dst_bufs_ready(v4l->m2m_ctx)
+ >= run_ready_min_buf_num)
+ return 1;
+
+ return 0;
+ }
+
for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
if (hw->mmu_enable)
addr = hw->buffer_spec[i].alloc_header_addr;
else
addr = hw->buffer_spec[i].cma_alloc_addr;
- if (hw->buffer_spec[i].used == 0) {
+ if (hw->buffer_spec[i].used == 0 &&
+ hw->buffer_spec[i].vf_ref == 0) {
if (addr)
return 1;
@@ -2351,13 +2433,12 @@ unsigned char have_free_buf_spec(struct vdec_s *vdec)
dealloc_buf_specs(hw, 0);
if (max_alloc_buf_count == 0 ||
allocated_count < max_alloc_buf_count) {
- if (hw->is_used_v4l)
- ret = 1;
- else if (alloc_one_buf_spec(hw, index) >= 0)
+ if (alloc_one_buf_spec(hw, index) >= 0)
ret = 1;
}
mutex_unlock(&vmh264_mutex);
}
+
return ret;
}
@@ -2611,18 +2692,6 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->buffer_spec[buffer_index].cma_alloc_addr;
- if (hw->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- dpb_print(DECODE_ID(hw),
- PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
- }
- dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%x\n",
- ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
if (hw->mmu_enable) {
@@ -2759,26 +2828,31 @@ int notify_v4l_eos(struct vdec_s *vdec)
{
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
- struct vframe_s *vf = NULL;
+ struct vframe_s *vf = &hw->vframe_dummy;
struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
- if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
- dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
- "%s fatal error, no available buffer slot.\n",
- __func__);
- return -1;
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = v4l_get_free_buf_idx(vdec))) {
+ if (time_after(jiffies, expires) ||
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+ break;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
- return -1;
+ if (index == INVALID_IDX) {
+ if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
+ return -1;
+ }
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb :
+ hw->buffer_spec[index].cma_alloc_addr;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
@@ -3775,6 +3849,7 @@ static struct vframe_s *vh264_vf_get(void *op_arg)
= frame_interval;
}
hw->last_frame_time = time;
+ vf->index_disp = hw->vf_get_count;
hw->vf_get_count++;
if (kfifo_peek(&hw->display_q, &next_vf)) {
vf->next_vf_pts_valid = true;
@@ -3791,6 +3866,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
{
struct vdec_s *vdec = op_arg;
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+ unsigned long flags;
int buf_spec_num;
int frame_index;
@@ -3815,6 +3891,7 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
}
/*get_buf_spec_idx_by_canvas_config(hw,
&vf->canvas0_config[0]);*/
+ spin_lock_irqsave(&hw->bufspec_lock, flags);
if (hw->buffer_spec[buf_spec_num].used == 2) {
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
@@ -3828,13 +3905,11 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
if (hw->buffer_spec[buf_spec_num].vf_ref <= 0)
set_frame_output_flag(&hw->dpb, frame_index);
} else {
- unsigned long flags;
dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
"%s %p isolated vf, buf_spec_num %d used %d vf_ref %d\n",
__func__, vf, buf_spec_num,
hw->buffer_spec[buf_spec_num].used,
hw->buffer_spec[buf_spec_num].vf_ref);
- spin_lock_irqsave(&hw->bufspec_lock, flags);
hw->buffer_spec[buf_spec_num].vf_ref--;
if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) {
if (hw->buffer_spec[buf_spec_num].used == 3)
@@ -3842,12 +3917,12 @@ static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
else if (hw->buffer_spec[buf_spec_num].used == 5)
hw->buffer_spec[buf_spec_num].used = 0;
}
- spin_unlock_irqrestore(&hw->bufspec_lock, flags);
if (dpb_is_debug(DECODE_ID(hw),
PRINT_FLAG_DUMP_BUFSPEC))
dump_bufspec(hw, __func__);
}
+ spin_unlock_irqrestore(&hw->bufspec_lock, flags);
hw->vf_put_count++;
kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
@@ -3866,7 +3941,13 @@ static int vh264_event_cb(int type, void *data, void *op_arg)
if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) {
struct provider_aux_req_s *req =
(struct provider_aux_req_s *)data;
- int buf_spec_num = BUFSPEC_INDEX(req->vf->index);
+ int buf_spec_num;
+
+ if (!req->vf) {
+ req->aux_size = hw->vf_put_count;
+ return 0;
+ }
+ buf_spec_num = BUFSPEC_INDEX(req->vf->index);
spin_lock_irqsave(&hw->lock, flags);
req->aux_buf = NULL;
req->aux_size = 0;
@@ -3905,6 +3986,21 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
"%s (%d,%d) dur %d, vf %p, index %d\n", __func__,
hw->frame_width, hw->frame_height, hw->frame_dur, vf, index);
+ /* signal_type */
+ if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) {
+ vf->signal_type = hw->video_signal_from_vui;
+ if (hw->is_used_v4l) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = hw->video_signal_from_vui;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
+ } else
+ vf->signal_type = 0;
+
vf->width = hw->frame_width;
vf->height = hw->frame_height;
if (force_rate) {
@@ -3918,8 +4014,10 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
(min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) <<
DISP_RATIO_ASPECT_RATIO_BIT;
vf->orientation = hw->vh264_rotation;
+
if (hw->mmu_enable)
return;
+
vf->canvas0Addr = vf->canvas1Addr = -1;
#ifdef NV21
vf->plane_num = 2;
@@ -3945,12 +4043,6 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
#ifndef NV21
vf->canvas1_config[2] = p_canvas_config[2];
#endif
- /* signal_type */
- if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK)
- vf->signal_type = hw->video_signal_from_vui;
- else
- vf->signal_type = 0;
-
}
static void get_picture_qos_info(struct StorablePicture *picture)
@@ -4413,8 +4505,9 @@ static int get_max_dec_frame_buf_size(int level_idc,
size /= pic_size;
size = size + 1; /* need one more buffer */
- if (max_reference_frame_num < size)
+ if (max_reference_frame_num > size)
size = max_reference_frame_num;
+ size = imin(size, 16);
return size;
}
@@ -4454,7 +4547,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
unsigned int chroma_format_idc, chroma444;
unsigned int crop_infor, crop_bottom, crop_right;
unsigned int used_reorder_dpb_size_margin
- = reorder_dpb_size_margin;
+ = hw->reorder_dpb_size_margin;
u8 *colocate_vaddr = NULL;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -4633,7 +4726,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
if (hw->is_used_v4l) {
if (i != -1) {
- pr_info("alloc the buf of v4l when it is about to decoding.\n");
+ pr_info("v4l: delay alloc the buffer.\n");
}
} else {
if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0)
@@ -4725,7 +4818,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
i = get_buf_spec_by_canvas_pos(hw, j);
if (hw->is_used_v4l) {
- pr_info("alloc the buf of v4l when it is about to decoding.\n");
+ pr_info("v4l: delay alloc the buffer.\n");
break;
} else if (alloc_one_buf_spec(hw, i) < 0)
break;
@@ -5090,6 +5183,8 @@ static bool is_buffer_available(struct vdec_s *vdec)
if (hw->reset_bufmgr_flag == 1)
buffer_available = 1;
+ else if (hw->is_used_v4l)
+ buffer_available = have_free_buf_spec(vdec);
}
return buffer_available;
@@ -5581,6 +5676,10 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt));
I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice)
? I_FLAG : 0;
+
+ if ((hw->i_only & 0x2) && (I_flag & I_FLAG))
+ flush_dpb(p_H264_Dpb);
+
if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) &&
(p_H264_Dpb->mSlice.structure == FRAME)) {
hw->data_flag = NULL_FLAG;
@@ -5607,7 +5706,8 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
true : false;
}
- if (!field_pic_flag && ((p_H264_Dpb->mSPS.profile_idc == BASELINE) ||
+ if (!field_pic_flag && (((p_H264_Dpb->mSPS.profile_idc == BASELINE) &&
+ (p_H264_Dpb->reorder_pic_num < 2)) ||
(((unsigned long)(hw->vh264_amstream_dec_info
.param)) & 0x8))) {
p_H264_Dpb->fast_output_enable =
@@ -5698,7 +5798,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
} else
hw->reflist_error_count = 0;
}
- if ((error_proc_policy & 0x800)
+ if ((error_proc_policy & 0x800) && (!(hw->i_only & 0x2))
&& p_H264_Dpb->dpb_error_flag != 0) {
dpb_print(DECODE_ID(hw), 0,
"dpb error %d\n",
@@ -5748,6 +5848,7 @@ pic_done_proc:
reset_process_time(hw);
if (input_frame_based(vdec) &&
+ (!(hw->i_only & 0x2)) &&
frmbase_cont_bitlevel != 0 &&
READ_VREG(VIFF_BIT_CNT) >
frmbase_cont_bitlevel) {
@@ -5822,6 +5923,7 @@ pic_done_proc:
}
mutex_unlock(&hw->chunks_mutex);
+
check_decoded_pic_error(hw);
#ifdef ERROR_HANDLE_TEST
if ((hw->data_flag & ERROR_FLAG)
@@ -6338,7 +6440,7 @@ static void vmh264_dump_state(struct vdec_s *vdec)
}
dpb_print(DECODE_ID(hw), 0,
- "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x\n",
+ "%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d) fast_output_enable %x \n",
__func__,
kfifo_len(&hw->newframe_q),
VF_POOL_SIZE,
@@ -6734,7 +6836,7 @@ static int vmh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
}
static unsigned char amvdec_enable_flag;
-static void vh264_local_init(struct vdec_h264_hw_s *hw)
+static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset)
{
int i;
hw->init_flag = 0;
@@ -6785,9 +6887,6 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw)
hw->first_i_policy = first_i_policy;
- if (hw->is_used_v4l)
- mem_map_mode = CANVAS_BLKMODE_LINEAR;
-
pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n",
hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside);
pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n",
@@ -6808,14 +6907,16 @@ static void vh264_local_init(struct vdec_h264_hw_s *hw)
else if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20)
hw->send_error_frame_flag = 0; /*Don't display mark err frames*/
- INIT_KFIFO(hw->display_q);
- INIT_KFIFO(hw->newframe_q);
+ if (!is_reset) {
+ INIT_KFIFO(hw->display_q);
+ INIT_KFIFO(hw->newframe_q);
- for (i = 0; i < VF_POOL_SIZE; i++) {
- const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
- hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
- hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
- kfifo_put(&hw->newframe_q, vf);
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
+ hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+ hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
+ kfifo_put(&hw->newframe_q, vf);
+ }
}
hw->duration_from_pts_done = 0;
@@ -6853,7 +6954,7 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
hw->stat |= STAT_ISR_REG;
mutex_init(&hw->chunks_mutex);
- vh264_local_init(hw);
+ vh264_local_init(hw, false);
INIT_WORK(&hw->work, vh264_work);
INIT_WORK(&hw->notify_work, vh264_notify_work);
INIT_WORK(&hw->timeout_work, vh264_timeout_work);
@@ -7822,15 +7923,15 @@ static void vh264_work_implement(struct vdec_h264_hw_s *hw,
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
- struct aml_vdec_pic_infos info;
+ struct aml_vdec_ps_infos ps;
- info.visible_width = hw->frame_width;
- info.visible_height = hw->frame_height;
- info.coded_width = ALIGN(hw->frame_width, 64);
- info.coded_height = ALIGN(hw->frame_height, 64);
- info.dpb_size = hw->dpb.mDPB.size;
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
}
@@ -8190,18 +8291,23 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
get_used_buf_count(hw) >=
run_ready_max_buf_num)
ret = 0;
+ }
+#endif
+ if (hw->is_used_v4l) {
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
- 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 &&
- hw->v4l_params_parsed)
- ret = 0; /*the params has parsed.*/
+ if (ctx->param_sets_from_ucode &&
+ !ctx->v4l_codec_ready &&
+ hw->v4l_params_parsed) {
+ ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready) {
+ if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
}
}
-#endif
+
if (ret)
not_run_ready[DECODE_ID(hw)] = 0;
else
@@ -8465,6 +8571,25 @@ static void run(struct vdec_s *vdec, unsigned long mask,
hw->init_flag = 1;
}
+static void clear_refer_bufs(struct vdec_h264_hw_s *hw)
+{
+ int i;
+
+ mutex_lock(&vmh264_mutex);
+ dealloc_buf_specs(hw, 1);
+ mutex_unlock(&vmh264_mutex);
+
+ INIT_KFIFO(hw->display_q);
+ INIT_KFIFO(hw->newframe_q);
+
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
+ hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+ hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
+ kfifo_put(&hw->newframe_q, vf);
+ }
+}
+
static void reset(struct vdec_s *vdec)
{
struct vdec_h264_hw_s *hw =
@@ -8486,6 +8611,8 @@ static void reset(struct vdec_s *vdec)
hw->eos = 0;
hw->decode_pic_count = 0;
hw->dec_result = DEC_RESULT_NONE;
+
+ clear_refer_bufs(hw);
reset_process_time(hw);
h264_reset_bufmgr(vdec);
@@ -8497,6 +8624,7 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw)
int i;
unsigned long flags;
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+ struct vdec_s *vdec = hw_to_vdec(hw);
dpb_print(DECODE_ID(hw), 0,
"%s\n", __func__);
/* after calling flush_dpb() and bufmgr_h264_remove_unused_frame(),
@@ -8520,6 +8648,24 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw)
}
spin_lock_irqsave(&hw->bufspec_lock, flags);
for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+ if (vdec->parallel_dec == 1) {
+ vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id);
+ vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id);
+ vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id);
+ hw->buffer_spec[i].y_canvas_index = -1;
+ hw->buffer_spec[i].u_canvas_index = -1;
+ hw->buffer_spec[i].v_canvas_index = -1;
+#ifdef VDEC_DW
+ if (IS_VDEC_DW(hw)) {
+ vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id);
+ vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id);
+ vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id);
+ hw->buffer_spec[i].vdec_dw_y_canvas_index = -1;
+ hw->buffer_spec[i].vdec_dw_u_canvas_index = -1;
+ hw->buffer_spec[i].vdec_dw_v_canvas_index = -1;
+#endif
+ }
+ }
/*make sure buffers not put back to bufmgr when
vf_put is called*/
if (hw->buffer_spec[i].used == 2)
@@ -8545,7 +8691,6 @@ static void h264_reconfig(struct vdec_h264_hw_s *hw)
if (dpb_is_debug(DECODE_ID(hw),
PRINT_FLAG_DUMP_BUFSPEC))
dump_bufspec(hw, "after h264_reconfig");
-
}
#ifdef ERROR_HANDLE_TEST
@@ -8568,7 +8713,6 @@ static void h264_clear_dpb(struct vdec_h264_hw_s *hw)
static void h264_reset_bufmgr(struct vdec_s *vdec)
{
- int i;
ulong timeout;
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
#if 0
@@ -8634,32 +8778,14 @@ static void h264_reset_bufmgr(struct vdec_s *vdec)
schedule();
}
- for (i = 0; i < VF_POOL_SIZE; i++)
- hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
-
- hw->cur_pool++;
- if (hw->cur_pool >= VF_POOL_NUM)
- hw->cur_pool = 0;
-
- for (i = 0; i < VF_POOL_SIZE; i++)
- hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
-
-
vf_notify_receiver(vdec->vf_provider_name, VFRAME_EVENT_PROVIDER_RESET, NULL);
buf_spec_init(hw);
- vh264_local_init(hw);
+ vh264_local_init(hw, true);
/*hw->decode_pic_count = 0;
hw->seq_info2 = 0;*/
- if (hw->is_used_v4l) {
- mutex_lock(&vmh264_mutex);
- /* detach relationship with v4l buffs.*/
- dealloc_buf_specs(hw, 1);
- mutex_unlock(&vmh264_mutex);
- }
-
if (vh264_set_params(hw,
hw->cfg_param1,
hw->cfg_param2,
@@ -8750,11 +8876,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
/* the ctx from v4l2 driver. */
hw->v4l2_ctx = pdata->private;
- if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0)
- hw->canvas_mode = pdata->canvas_mode;
- else
- hw->canvas_mode = mem_map_mode;
-
platform_set_drvdata(pdev, pdata);
hw->mmu_enable = 0;
@@ -8765,16 +8886,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
if (pdata->sys_info)
hw->vh264_amstream_dec_info = *pdata->sys_info;
- hw->is_used_v4l = (((unsigned long)
- hw->vh264_amstream_dec_info.param & 0x80) >> 7);
- if (hw->is_used_v4l) {
- hw->mmu_enable = (((unsigned long)
- hw->vh264_amstream_dec_info.param & 0x100) >> 8);
- dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "%s v4: enable mmu %d.\n",
- __func__, hw->mmu_enable);
- }
-
if (force_enable_mmu && pdata->sys_info &&
(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) &&
(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) &&
@@ -8802,9 +8913,32 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
hw->double_write_mode = config_val;
else
hw->double_write_mode = double_write_mode;
+
+ 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_buffer_margin",
+ &config_val) == 0)
+ hw->reorder_dpb_size_margin = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_canvas_mem_mode",
+ &config_val) == 0)
+ hw->canvas_mode = config_val;
} else
hw->double_write_mode = double_write_mode;
+ if (!hw->is_used_v4l) {
+ hw->reorder_dpb_size_margin = reorder_dpb_size_margin;
+ hw->canvas_mode = mem_map_mode;
+
+ if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0)
+ hw->canvas_mode = pdata->canvas_mode;
+ }
+
if (hw->mmu_enable)
hw->double_write_mode &= 0xffff;
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
index 37e6969..170cc22 100644
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -47,6 +47,7 @@
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
+#include <media/v4l2-mem2mem.h>
#define CONSTRAIN_MAX_BUF_NUM
@@ -128,6 +129,7 @@
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
#define SEI_UserDataITU_T_T35 4
+#define INVALID_IDX -1 /* Invalid buffer index.*/
static struct semaphore h265_sema;
@@ -182,6 +184,8 @@ static int start_decode_buf_level = 0x8000;
static unsigned int decode_timeout_val = 200;
+static u32 run_ready_min_buf_num = 2;
+
/*data_resend_policy:
bit 0, stream base resend data when decoding buf empty
*/
@@ -1301,11 +1305,13 @@ enum SliceType {
/*USE_BUF_BLOCK*/
struct BUF_s {
- unsigned long start_adr;
- unsigned int size;
- int used_flag;
- unsigned int y_size;
- ulong v4l_ref_buf_addr;
+ ulong start_adr;
+ u32 size;
+ u32 luma_size;
+ ulong header_addr;
+ u32 header_size;
+ int used_flag;
+ ulong v4l_ref_buf_addr;
} /*BUF_t */;
/* level 6, 6.1 maximum slice number is 800; other is 200 */
@@ -1396,6 +1402,8 @@ struct PIC_s {
int max_mv;
int min_mv;
int avg_mv;
+
+ bool vframe_bound;
} /*PIC_t */;
#define MAX_TILE_COL_NUM 10
@@ -1727,6 +1735,7 @@ struct hevc_state_s {
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
+ u32 mem_map_mode;
} /*hevc_stru_t */;
#ifdef AGAIN_HAS_THRESHOLD
@@ -2083,7 +2092,7 @@ static void restore_decode_state(struct hevc_state_s *hevc)
static void hevc_init_stru(struct hevc_state_s *hevc,
struct BuffInfo_s *buf_spec_i)
{
- //int i;
+ int i;
INIT_LIST_HEAD(&hevc->log_list);
hevc->work_space_buf = buf_spec_i;
hevc->prefix_aux_size = 0;
@@ -2140,10 +2149,14 @@ static void hevc_init_stru(struct hevc_state_s *hevc,
else
hevc->ignore_bufmgr_error = 0x0;
- hevc->dec_result = DEC_RESULT_FREE_CANVAS;
- vdec_schedule_work(&hevc->work);
- /*for (i = 0; i < MAX_REF_PIC_NUM; i++)
- hevc->m_PIC[i] = NULL;*/
+ if (hevc->is_used_v4l) {
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ if (hevc->m_PIC[i] != NULL) {
+ memset(hevc->m_PIC[i], 0 ,sizeof(struct PIC_s));
+ hevc->m_PIC[i]->index = i;
+ }
+ }
+ }
hevc->pic_num = 0;
hevc->lcu_x_num_pre = 0;
@@ -2575,6 +2588,32 @@ static void get_rpm_param(union param_u *params)
}
}
+static int get_free_buf_idx(struct hevc_state_s *hevc)
+{
+ int index = INVALID_IDX;
+ struct PIC_s *pic;
+ int i;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ pic = hevc->m_PIC[i];
+ if (pic == NULL ||
+ pic->index == -1 ||
+ pic->BUF_index == -1)
+ continue;
+
+ if (pic->output_mark == 0 &&
+ pic->referenced == 0 &&
+ pic->output_ready == 0 &&
+ pic->cma_alloc_addr) {
+ pic->output_ready = 1;
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+}
+
static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC)
{
int i;
@@ -2643,8 +2682,62 @@ static unsigned int log2i(unsigned int val)
}
static int init_buf_spec(struct hevc_state_s *hevc);
+
+static bool v4l_is_there_vframe_bound(struct hevc_state_s *hevc)
+{
+ int i;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic && pic->vframe_bound)
+ return true;
+ }
+
+ return false;
+}
+
+static void v4l_mmu_buffer_release(struct hevc_state_s *hevc)
+{
+ int i;
+
+ /* release workspace */
+ if (hevc->bmmu_box)
+ decoder_bmmu_box_free_idx(hevc->bmmu_box,
+ BMMU_WORKSPACE_ID);
+ /*
+ * it's only when vframe get back to driver, right now we can be sure
+ * that vframe and fd are related. if the playback exits, the capture
+ * requires the upper app to release when the fd is closed, and others
+ * buffers drivers are released by driver.
+ */
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic && !pic->vframe_bound) {
+ if (hevc->bmmu_box)
+ decoder_bmmu_box_free_idx(hevc->bmmu_box,
+ VF_BUFFER_IDX(i));
+ if (hevc->mmu_box)
+ decoder_mmu_box_free_idx(hevc->mmu_box, i);
+
+ hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
+ "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
+ __func__, i, hevc->bmmu_box, hevc->mmu_box);
+ }
+ }
+}
+
static void uninit_mmu_buffers(struct hevc_state_s *hevc)
{
+ if (hevc->is_used_v4l &&
+ v4l_is_there_vframe_bound(hevc)) {
+ if (get_double_write_mode(hevc) != 0x10) {
+ v4l_mmu_buffer_release(hevc);
+ return;
+ }
+ }
+
if (hevc->mmu_box)
decoder_mmu_box_free(hevc->mmu_box);
hevc->mmu_box = NULL;
@@ -2733,7 +2826,6 @@ static void dealloc_mv_bufs(struct hevc_state_s *hevc)
if (hevc->m_PIC[i] != NULL)
hevc->m_PIC[i]->mv_buf_index = -1;
}
-
}
static int alloc_mv_buf(struct hevc_state_s *hevc, int i)
@@ -2963,15 +3055,67 @@ static int cal_current_buf_size(struct hevc_state_s *hevc,
return buf_size;
}
+static int v4l_alloc_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
+{
+ int ret = -1;
+ int i = pic->index;
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
+ return ret;
+
+ ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb);
+ if (ret < 0) {
+ hevc_print(hevc, 0, "[%d] H265 get buffer fail.\n",
+ ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id);
+ return ret;
+ }
+
+ if (hevc->mmu_enable) {
+ if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (IS_8K_SIZE(hevc->pic_w, hevc->pic_h)))
+ hevc->m_BUF[i].header_size =
+ ALIGN(MMU_COMPRESS_8K_HEADER_SIZE, 0x10000);
+ else
+ hevc->m_BUF[i].header_size =
+ ALIGN(MMU_COMPRESS_HEADER_SIZE, 0x10000);
+
+ ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box,
+ VF_BUFFER_IDX(i), hevc->m_BUF[i].header_size,
+ DRIVER_NAME, &hevc->m_BUF[i].header_addr);
+ if (ret < 0) {
+ hevc_print(hevc, PRINT_FLAG_ERROR,
+ "%s[%d], header size: %d, no mem fatal err\n",
+ __func__, i, hevc->m_BUF[i].header_size);
+ return ret;
+ }
+ }
+
+ hevc->m_BUF[i].used_flag = 0;
+ hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
+ pic->cma_alloc_addr = hevc->m_BUF[i].v4l_ref_buf_addr;
+ if (fb->num_planes == 1) {
+ hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ hevc->m_BUF[i].size = fb->m.mem[0].size;
+ hevc->m_BUF[i].luma_size = fb->m.mem[0].offset;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ } else if (fb->num_planes == 2) {
+ hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
+ hevc->m_BUF[i].luma_size = fb->m.mem[0].size;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ fb->m.mem[1].bytes_used = fb->m.mem[1].size;
+ }
+
+ return ret;
+}
+
static int alloc_buf(struct hevc_state_s *hevc)
{
int i;
int ret = -1;
int buf_size = cal_current_buf_size(hevc, NULL);
- if (hevc->is_used_v4l)
- return 0;
-
if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
return ret;
@@ -2981,9 +3125,6 @@ static int alloc_buf(struct hevc_state_s *hevc)
}
if (i < BUF_POOL_SIZE) {
if (buf_size > 0) {
- /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/
- /*alloc compress header first*/
-
ret = decoder_bmmu_box_alloc_buf_phy
(hevc->bmmu_box,
VF_BUFFER_IDX(i), buf_size,
@@ -3043,6 +3184,7 @@ static int alloc_buf(struct hevc_state_s *hevc)
} else
ret = 0;
}
+
if (ret >= 0) {
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
hevc_print(hevc, 0,
@@ -3088,7 +3230,6 @@ static void dealloc_unused_buf(struct hevc_state_s *hevc)
hevc->m_BUF[i].size = 0;
}
}
-
}
static void dealloc_pic_buf(struct hevc_state_s *hevc,
@@ -3174,6 +3315,35 @@ static int get_alloc_pic_count(struct hevc_state_s *hevc)
return alloc_pic_count;
}
+static int v4l_config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
+{
+ int i = pic->index;
+ int dw_mode = get_double_write_mode(hevc);
+
+ if (hevc->mmu_enable)
+ pic->header_adr = hevc->m_BUF[i].header_addr;
+
+ pic->BUF_index = i;
+ pic->POC = INVALID_POC;
+ pic->mc_canvas_y = pic->index;
+ pic->mc_canvas_u_v = pic->index;
+
+ if (dw_mode & 0x10) {
+ pic->mc_y_adr = hevc->m_BUF[i].start_adr;
+ pic->mc_u_v_adr = pic->mc_y_adr + hevc->m_BUF[i].luma_size;
+ pic->mc_canvas_y = (pic->index << 1);
+ pic->mc_canvas_u_v = (pic->index << 1) + 1;
+
+ pic->dw_y_adr = pic->mc_y_adr;
+ pic->dw_u_v_adr = pic->mc_u_v_adr;
+ } else if (dw_mode) {
+ pic->dw_y_adr = hevc->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + hevc->m_BUF[i].luma_size;
+ }
+
+ return 0;
+}
+
static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
{
int ret = -1;
@@ -3189,45 +3359,8 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
struct buf_stru_s buf_stru;
int buf_size = cal_current_buf_size(hevc, &buf_stru);
int dw_mode = get_double_write_mode(hevc);
- struct vdec_v4l2_buffer *fb = NULL;
-
- if (hevc->is_used_v4l)
- buf_size = 0;
for (i = 0; i < BUF_POOL_SIZE; i++) {
- if (hevc->is_used_v4l && !hevc->m_BUF[i].start_adr) {
- ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb);
- if (ret) {
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] get fb fail.\n",
- ((struct aml_vcodec_ctx *)
- (hevc->v4l2_ctx))->id);
- return ret;
- }
-
- hevc->m_BUF[i].used_flag = 0;
- hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
- if (fb->num_planes == 1) {
- hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
- hevc->m_BUF[i].size = fb->m.mem[0].size;
- hevc->m_BUF[i].y_size = fb->m.mem[0].offset;
- fb->m.mem[0].bytes_used = fb->m.mem[0].size;
- } else if (fb->num_planes == 2) {
- hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
- hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
- hevc->m_BUF[i].y_size = fb->m.mem[0].size;
- fb->m.mem[0].bytes_used = fb->m.mem[0].size;
- fb->m.mem[1].bytes_used = fb->m.mem[1].size;
- }
-
- pic->BUF_index = i;
-
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l ref buf addr: 0x%x\n",
- ((struct aml_vcodec_ctx *)
- (hevc->v4l2_ctx))->id, __func__, fb);
- }
-
if (hevc->m_BUF[i].start_adr != 0 &&
hevc->m_BUF[i].used_flag == 0 &&
buf_size <= hevc->m_BUF[i].size) {
@@ -3251,8 +3384,7 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
} else
y_adr = hevc->m_BUF[i].start_adr;
- if (!hevc->is_used_v4l)
- y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/
+ y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/
pic->POC = INVALID_POC;
/*ensure get_pic_by_POC()
@@ -3268,15 +3400,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
pic->mc_canvas_y = pic->index;
pic->mc_canvas_u_v = pic->index;
if (dw_mode & 0x10) {
- if (hevc->is_used_v4l) {
- pic->mc_y_adr = y_adr;
- pic->mc_u_v_adr = y_adr + hevc->m_BUF[i].y_size;
- } else {
- pic->mc_y_adr = y_adr;
- pic->mc_u_v_adr = y_adr +
- ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
- }
-
+ pic->mc_y_adr = y_adr;
+ pic->mc_u_v_adr = y_adr +
+ ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
pic->mc_canvas_y = (pic->index << 1);
pic->mc_canvas_u_v = (pic->index << 1) + 1;
@@ -3285,10 +3411,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
} else if (dw_mode) {
pic->dw_y_adr = y_adr;
pic->dw_u_v_adr = pic->dw_y_adr +
- ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
+ ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
}
-
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
hevc_print(hevc, 0,
"%s index %d BUF_index %d mc_y_adr %x\n",
@@ -3299,8 +3424,6 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
hevc_print(hevc, 0,
"mmu double write adr %ld\n",
pic->cma_alloc_addr);
-
-
}
ret = 0;
@@ -3313,30 +3436,36 @@ static void init_pic_list(struct hevc_state_s *hevc)
int init_buf_num = get_work_pic_num(hevc);
int dw_mode = get_double_write_mode(hevc);
struct vdec_s *vdec = hw_to_vdec(hevc);
- /*alloc decoder buf*/
- for (i = 0; i < init_buf_num; i++) {
- if (alloc_buf(hevc) < 0) {
- if (i <= 8) {
- /*if alloced (i+1)>=9
- don't send errors.*/
- hevc->fatal_error |=
- DECODER_FATAL_ERROR_NO_MEM;
+ /*alloc decoder buf will be delay if work on v4l. */
+ if (!hevc->is_used_v4l) {
+ for (i = 0; i < init_buf_num; i++) {
+ if (alloc_buf(hevc) < 0) {
+ if (i <= 8) {
+ /*if alloced (i+1)>=9
+ don't send errors.*/
+ hevc->fatal_error |=
+ DECODER_FATAL_ERROR_NO_MEM;
+ }
+ break;
}
- break;
}
}
for (i = 0; i < init_buf_num; i++) {
- struct PIC_s *pic =
- vmalloc(sizeof(struct PIC_s));
- if (pic == NULL) {
- hevc_print(hevc, 0,
- "%s: alloc pic %d fail!!!\n",
- __func__, i);
- break;
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (!pic) {
+ pic = vmalloc(sizeof(struct PIC_s));
+ if (pic == NULL) {
+ hevc_print(hevc, 0,
+ "%s: alloc pic %d fail!!!\n",
+ __func__, i);
+ break;
+ }
+ hevc->m_PIC[i] = pic;
}
memset(pic, 0, sizeof(struct PIC_s));
- hevc->m_PIC[i] = pic;
+
pic->index = i;
pic->BUF_index = -1;
pic->mv_buf_index = -1;
@@ -3349,6 +3478,7 @@ static void init_pic_list(struct hevc_state_s *hevc)
pic->height = hevc->pic_h;
pic->double_write_mode = dw_mode;
+ /*config canvas will be delay if work on v4l. */
if (!hevc->is_used_v4l) {
if (config_pic(hevc, pic) < 0) {
if (get_dbg_flag(hevc))
@@ -3365,16 +3495,20 @@ static void init_pic_list(struct hevc_state_s *hevc)
}
for (; i < MAX_REF_PIC_NUM; i++) {
- struct PIC_s *pic =
- vmalloc(sizeof(struct PIC_s));
- if (pic == NULL) {
- hevc_print(hevc, 0,
- "%s: alloc pic %d fail!!!\n",
- __func__, i);
- break;
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (!pic) {
+ pic = vmalloc(sizeof(struct PIC_s));
+ if (pic == NULL) {
+ hevc_print(hevc, 0,
+ "%s: alloc pic %d fail!!!\n",
+ __func__, i);
+ break;
+ }
+ hevc->m_PIC[i] = pic;
}
memset(pic, 0, sizeof(struct PIC_s));
- hevc->m_PIC[i] = pic;
+
pic->index = -1;
pic->BUF_index = -1;
if (vdec->parallel_dec == 1) {
@@ -5121,7 +5255,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
#if 0
data32 = READ_VREG(HEVC_SAO_CTRL1);
data32 &= (~0x3000);
- data32 |= (mem_map_mode <<
+ data32 |= (hevc->mem_map_mode <<
12);
/* [13:12] axi_aformat,
@@ -5131,7 +5265,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
data32 &= (~0x30);
- data32 |= (mem_map_mode <<
+ data32 |= (hevc->mem_map_mode <<
4);
/* [5:4] -- address_format
@@ -5142,7 +5276,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
/* m8baby test1902 */
data32 = READ_VREG(HEVC_SAO_CTRL1);
data32 &= (~0x3000);
- data32 |= (mem_map_mode <<
+ data32 |= (hevc->mem_map_mode <<
12);
/* [13:12] axi_aformat, 0-Linear,
@@ -5213,7 +5347,7 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
data32 &= (~0x30);
/* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */
- data32 |= (mem_map_mode <<
+ data32 |= (hevc->mem_map_mode <<
4);
data32 &= (~0xF);
data32 |= 0xf; /* valid only when double write only */
@@ -5420,6 +5554,7 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc,
&& pic->output_ready == 0
&& pic->width == hevc->pic_w
&& pic->height == hevc->pic_h
+ && pic->vf_ref == 0
) {
if (new_pic) {
if (new_pic->POC != INVALID_POC) {
@@ -5532,6 +5667,124 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc,
return new_pic;
}
+static struct PIC_s *v4l_get_new_pic(struct hevc_state_s *hevc,
+ union param_u *rpm_param)
+{
+ int ret;
+ struct aml_vcodec_ctx * v4l = hevc->v4l2_ctx;
+ struct v4l_buff_pool *pool = &v4l->cap_pool;
+ struct PIC_s *new_pic = NULL;
+ struct PIC_s *pic = NULL;
+ int i;
+
+ for (i = 0; i < pool->in; ++i) {
+ u32 state = (pool->seq[i] >> 16);
+ u32 index = (pool->seq[i] & 0xffff);
+
+ switch (state) {
+ case V4L_CAP_BUFF_IN_DEC:
+ pic = hevc->m_PIC[i];
+ if (pic && (pic->index != -1) &&
+ (pic->output_mark == 0) &&
+ (pic->referenced == 0) &&
+ (pic->output_ready == 0) &&
+ (pic->width == hevc->pic_w) &&
+ (pic->height == hevc->pic_h) &&
+ (pic->vf_ref == 0) &&
+ pic->cma_alloc_addr) {
+ new_pic = pic;
+ }
+ break;
+ case V4L_CAP_BUFF_IN_M2M:
+ pic = hevc->m_PIC[index];
+ pic->width = hevc->pic_w;
+ pic->height = hevc->pic_h;
+ if ((pic->index != -1) &&
+ !v4l_alloc_buf(hevc, pic)) {
+ v4l_config_pic(hevc, pic);
+ init_pic_list_hw(hevc);
+ new_pic = pic;
+ }
+ break;
+ default:
+ pr_err("v4l buffer state err %d.\n", state);
+ break;
+ }
+
+ if (new_pic)
+ break;
+ }
+
+ if (new_pic == NULL)
+ return NULL;
+
+ new_pic->double_write_mode = get_double_write_mode(hevc);
+ if (new_pic->double_write_mode)
+ set_canvas(hevc, new_pic);
+
+ if (get_mv_buf(hevc, new_pic) < 0)
+ return NULL;
+
+ if (hevc->mmu_enable) {
+ ret = H265_alloc_mmu(hevc, new_pic,
+ rpm_param->p.bit_depth,
+ hevc->frame_mmu_map_addr);
+ if (ret != 0) {
+ put_mv_buf(hevc, new_pic);
+ hevc_print(hevc, 0,
+ "can't alloc need mmu1,idx %d ret =%d\n",
+ new_pic->decode_idx, ret);
+ return NULL;
+ }
+ }
+
+ new_pic->referenced = 1;
+ new_pic->decode_idx = hevc->decode_idx;
+ new_pic->slice_idx = 0;
+ new_pic->referenced = 1;
+ new_pic->output_mark = 0;
+ new_pic->recon_mark = 0;
+ new_pic->error_mark = 0;
+ new_pic->dis_mark = 0;
+ /* new_pic->output_ready = 0; */
+ new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0;
+ new_pic->losless_comp_body_size = hevc->losless_comp_body_size;
+ new_pic->POC = hevc->curr_POC;
+ new_pic->pic_struct = hevc->curr_pic_struct;
+
+ if (new_pic->aux_data_buf)
+ release_aux_data(hevc, new_pic);
+ new_pic->mem_saving_mode =
+ hevc->mem_saving_mode;
+ new_pic->bit_depth_luma =
+ hevc->bit_depth_luma;
+ new_pic->bit_depth_chroma =
+ hevc->bit_depth_chroma;
+ new_pic->video_signal_type =
+ hevc->video_signal_type;
+
+ new_pic->conformance_window_flag =
+ hevc->param.p.conformance_window_flag;
+ new_pic->conf_win_left_offset =
+ hevc->param.p.conf_win_left_offset;
+ new_pic->conf_win_right_offset =
+ hevc->param.p.conf_win_right_offset;
+ new_pic->conf_win_top_offset =
+ hevc->param.p.conf_win_top_offset;
+ new_pic->conf_win_bottom_offset =
+ hevc->param.p.conf_win_bottom_offset;
+ new_pic->chroma_format_idc =
+ hevc->param.p.chroma_format_idc;
+
+ hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+ "%s: index %d, buf_idx %d, decode_idx %d, POC %d\n",
+ __func__, new_pic->index,
+ new_pic->BUF_index, new_pic->decode_idx,
+ new_pic->POC);
+
+ return new_pic;
+}
+
static int get_display_pic_num(struct hevc_state_s *hevc)
{
int i;
@@ -6768,7 +7021,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
set_aux_data(hevc, hevc->cur_pic, 1, 0);
#endif
/* new pic */
- hevc->cur_pic = get_new_pic(hevc, rpm_param);
+ hevc->cur_pic = hevc->is_used_v4l ?
+ v4l_get_new_pic(hevc, rpm_param) :
+ get_new_pic(hevc, rpm_param);
if (hevc->cur_pic == NULL) {
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR)
dump_pic_list(hevc);
@@ -6829,7 +7084,9 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
} else {
if (hevc->wait_buf == 1) {
pic_list_process(hevc);
- hevc->cur_pic = get_new_pic(hevc, rpm_param);
+ hevc->cur_pic = hevc->is_used_v4l ?
+ v4l_get_new_pic(hevc, rpm_param) :
+ get_new_pic(hevc, rpm_param);
if (hevc->cur_pic == NULL)
return -1;
@@ -7127,17 +7384,17 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic,
return -1;
}
ret = decoder_mmu_box_alloc_idx(
- hevc->mmu_box,
- cur_buf_idx,
- cur_mmu_4k_number,
- mmu_index_adr);
+ hevc->mmu_box,
+ cur_buf_idx,
+ cur_mmu_4k_number,
+ mmu_index_adr);
if (ret == 0)
new_pic->scatter_alloc = 1;
+
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
- "%s pic index %d page count(%d) ret =%d\n",
- __func__, cur_buf_idx,
- cur_mmu_4k_number,
- ret);
+ "%s pic index %d page count(%d) ret =%d\n",
+ __func__, cur_buf_idx,
+ cur_mmu_4k_number, ret);
return ret;
}
@@ -7327,7 +7584,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
struct vdec_s *vdec = hw_to_vdec(hevc);
int canvas_w = ALIGN(pic->width, 64)/4;
int canvas_h = ALIGN(pic->height, 32)/4;
- int blkmode = mem_map_mode;
+ int blkmode = hevc->mem_map_mode;
/*CANVAS_BLKMODE_64X32*/
#ifdef SUPPORT_10BIT
@@ -7337,7 +7594,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_h = pic->height /
get_double_write_ratio(hevc, pic->double_write_mode);
- if (mem_map_mode == 0)
+ if (hevc->mem_map_mode == 0)
canvas_w = ALIGN(canvas_w, 32);
else
canvas_w = ALIGN(canvas_w, 64);
@@ -7355,10 +7612,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index,
pic->dw_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
#ifdef MULTI_INSTANCE_SUPPORT
pic->canvas_config[0].phy_addr =
pic->dw_y_adr;
@@ -7368,7 +7625,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_h;
pic->canvas_config[0].block_mode =
blkmode;
- pic->canvas_config[0].endian = 7;
+ pic->canvas_config[0].endian = hevc->is_used_v4l ? 0 : 7;
pic->canvas_config[1].phy_addr =
pic->dw_u_v_adr;
@@ -7378,7 +7635,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_h;
pic->canvas_config[1].block_mode =
blkmode;
- pic->canvas_config[1].endian = 7;
+ pic->canvas_config[1].endian = hevc->is_used_v4l ? 0 : 7;
#endif
} else {
if (!hevc->mmu_enable) {
@@ -7394,10 +7651,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index,
pic->mc_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
}
}
#else
@@ -7413,10 +7670,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
#endif
}
@@ -7732,6 +7989,20 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf,
vf_dp->content_light_level.present_flag = 1;
} else
vf_dp->content_light_level.present_flag = 0;
+
+ if (hevc->is_used_v4l &&
+ ((hevc->sei_present_flag & SEI_HDR10PLUS_MASK) ||
+ (vf_dp->present_flag) ||
+ (vf_dp->content_light_level.present_flag))) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = vf->signal_type;
+ hdr.color_parms = *vf_dp;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
}
static int vh265_vf_states(struct vframe_states *states, void *op_arg)
@@ -7907,6 +8178,7 @@ static struct vframe_s *vh265_vf_get(void *op_arg)
}
#endif
hevc->show_frame_num++;
+ vf->index_disp = hevc->vf_get_count;
hevc->vf_get_count++;
if (kfifo_peek(&hevc->display_q, &next_vf)) {
@@ -7962,6 +8234,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
if (index_top != 0xff
&& index_top < MAX_REF_PIC_NUM
&& hevc->m_PIC[index_top]) {
+ if (hevc->is_used_v4l)
+ hevc->m_PIC[index_top]->vframe_bound = true;
if (hevc->m_PIC[index_top]->vf_ref > 0) {
hevc->m_PIC[index_top]->vf_ref--;
@@ -7978,6 +8252,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
if (index_bot != 0xff
&& index_bot < MAX_REF_PIC_NUM
&& hevc->m_PIC[index_bot]) {
+ if (hevc->is_used_v4l)
+ hevc->m_PIC[index_bot]->vframe_bound = true;
if (hevc->m_PIC[index_bot]->vf_ref > 0) {
hevc->m_PIC[index_bot]->vf_ref--;
@@ -8021,6 +8297,10 @@ static int vh265_event_cb(int type, void *data, void *op_arg)
(struct provider_aux_req_s *)data;
unsigned char index;
+ if (!req->vf) {
+ req->aux_size = hevc->vf_put_count;
+ return 0;
+ }
spin_lock_irqsave(&lock, flags);
index = req->vf->index & 0xff;
req->aux_buf = NULL;
@@ -8310,16 +8590,11 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->v4l_mem_handle
= hevc->m_BUF[pic->BUF_index].v4l_ref_buf_addr;
if (hevc->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
+ vf->mm_box.bmmu_box = hevc->bmmu_box;
+ vf->mm_box.bmmu_idx = VF_BUFFER_IDX(pic->BUF_index);
+ vf->mm_box.mmu_box = hevc->mmu_box;
+ vf->mm_box.mmu_idx = pic->index;
}
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%lx\n",
- ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
#ifdef MULTI_INSTANCE_SUPPORT
@@ -8454,6 +8729,7 @@ 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;
+
if ((pic->double_write_mode == 3) &&
(!(IS_8K_SIZE(pic->width, pic->height)))) {
vf->type |= VIDTYPE_COMPRESS;
@@ -8840,27 +9116,31 @@ static int notify_v4l_eos(struct vdec_s *vdec)
{
struct hevc_state_s *hw = (struct hevc_state_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
- struct vframe_s *vf = NULL;
+ struct vframe_s *vf = &hw->vframe_dummy;
struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
- if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
- hevc_print(hw, 0,
- "%s fatal error, no available buffer slot.\n",
- __func__);
- return -1;
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = get_free_buf_idx(hw))) {
+ if (time_after(jiffies, expires) ||
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+ break;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
- return -1;
+ if (index == INVALID_IDX) {
+ if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
+ return -1;
+ }
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
-
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb :
+ hw->m_BUF[index].v4l_ref_buf_addr;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
vf_notify_receiver(vdec->vf_provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
@@ -9481,7 +9761,8 @@ pic_done:
check_pic_decoded_error(hevc,
READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff);
if (hevc->cur_pic != NULL &&
- (READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) == 0)
+ (READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) == 0
+ && (hevc->lcu_x_num * hevc->lcu_y_num != 1))
hevc->cur_pic->error_mark = 1;
force_output:
pic_display = output_pic(hevc, 1);
@@ -9877,18 +10158,18 @@ force_output:
(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
if (ctx->param_sets_from_ucode && !hevc->v4l_params_parsed) {
- struct aml_vdec_pic_infos info;
+ 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;
- info.visible_width = hevc->frame_width;
- info.visible_height = hevc->frame_height;
- info.coded_width = ALIGN(hevc->frame_width, 32);
- info.coded_height = ALIGN(hevc->frame_height, 32);
- info.dpb_size = get_work_pic_num(hevc);
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
}
@@ -11274,7 +11555,7 @@ static unsigned char is_new_pic_available(struct hevc_state_s *hevc)
/*decode. all reference frames are removed and setting error flag.*/
/*3 represents 2 filed are needed for back-end display and 1 filed is needed for decoding*/
/*when file is interlace.*/
- if ((new_pic == NULL) &&
+ if ((!hevc->is_used_v4l) && (new_pic == NULL) &&
(ref_pic >=
get_work_pic_num(hevc) -
hevc->sps_num_reorder_pics_0 - 3)) {
@@ -11334,6 +11615,14 @@ static int vmh265_stop(struct hevc_state_s *hevc)
hevc_local_uninit(hevc);
+ hevc->init_flag = 0;
+ hevc->first_sc_checked = 0;
+ cancel_work_sync(&hevc->notify_work);
+ cancel_work_sync(&hevc->set_clk_work);
+ cancel_work_sync(&hevc->timeout_work);
+
+ uninit_mmu_buffers(hevc);
+
if (use_cma) {
hevc->uninit_list = 1;
reset_process_time(hevc);
@@ -11349,13 +11638,7 @@ static int vmh265_stop(struct hevc_state_s *hevc)
msleep(20);
#endif
}
- hevc->init_flag = 0;
- hevc->first_sc_checked = 0;
- cancel_work_sync(&hevc->notify_work);
- cancel_work_sync(&hevc->set_clk_work);
cancel_work_sync(&hevc->work);
- cancel_work_sync(&hevc->timeout_work);
- uninit_mmu_buffers(hevc);
vfree(hevc->fw);
hevc->fw = NULL;
@@ -11971,11 +12254,15 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (ctx->param_sets_from_ucode &&
!ctx->v4l_codec_ready &&
- hevc->v4l_params_parsed)
+ hevc->v4l_params_parsed) {
ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready) {
+ if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
+ }
}
-
if (ret)
not_run_ready[hevc->index] = 0;
else
@@ -12162,9 +12449,26 @@ static void run(struct vdec_s *vdec, unsigned long mask,
hevc->stat |= STAT_VDEC_RUN;
}
-static void reset(struct vdec_s *vdec)
+static void aml_free_canvas(struct vdec_s *vdec)
{
+ int i;
+ struct hevc_state_s *hevc =
+ (struct hevc_state_s *)vdec->private;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic) {
+ if (vdec->parallel_dec == 1) {
+ vdec->free_canvas_ex(pic->y_canvas_index, vdec->id);
+ vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id);
+ }
+ }
+ }
+}
+static void reset(struct vdec_s *vdec)
+{
struct hevc_state_s *hevc =
(struct hevc_state_s *)vdec->private;
int i;
@@ -12185,6 +12489,7 @@ static void reset(struct vdec_s *vdec)
hevc->init_flag = 0;
hevc->pic_list_init_flag = 0;
dealloc_mv_bufs(hevc);
+ aml_free_canvas(vdec);
hevc_local_uninit(hevc);
if (vh265_local_init(hevc) < 0)
pr_debug(" %s local init fail\n", __func__);
@@ -12687,6 +12992,20 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc->max_pic_h = config_val;
}
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ hevc->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ hevc->dynamic_buf_num_margin = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_canvas_mem_mode",
+ &config_val) == 0)
+ hevc->mem_map_mode = config_val;
#endif
} else {
if (pdata->sys_info)
@@ -12698,10 +13017,14 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
}
hevc->double_write_mode = double_write_mode;
}
- if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
- hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
- else
- hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ if (!hevc->is_used_v4l) {
+ if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
+ hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
+ else
+ hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
+
+ hevc->mem_map_mode = mem_map_mode;
+ }
if (mmu_enable_force == 0) {
if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL)
@@ -12710,19 +13033,6 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc->mmu_enable = 1;
}
- hevc->is_used_v4l = (((unsigned long)
- hevc->vh265_amstream_dec_info.param & 0x80) >> 7);
- if (hevc->is_used_v4l) {
- hevc->mmu_enable = (((unsigned long) // scatter mem
- hevc->vh265_amstream_dec_info.param & 0x100) >> 8);
- if (!hevc->mmu_enable)
- hevc->double_write_mode = 0x10;
-
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "%s v4: enable mmu %d.\n",
- __func__, hevc->mmu_enable);
- }
-
if (init_mmu_buffers(hevc) < 0) {
hevc_print(hevc, 0,
"\n 265 mmu init failed!\n");
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index c8c3eaa..493231b 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -44,6 +44,7 @@
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
+#include "../utils/config_parser.h"
#define MEM_NAME "codec_mmjpeg"
@@ -72,8 +73,9 @@
#define PICINFO_INTERLACE_AVI1_BOT 0x0010
#define PICINFO_INTERLACE_FIRST 0x0010
-#define VF_POOL_SIZE 16
-#define DECODE_BUFFER_NUM_MAX 4
+#define VF_POOL_SIZE 64
+#define DECODE_BUFFER_NUM_MAX 16
+#define DECODE_BUFFER_NUM_DEF 4
#define MAX_BMMU_BUFFER_NUM DECODE_BUFFER_NUM_MAX
#define DEFAULT_MEM_SIZE (32*SZ_1M)
@@ -94,7 +96,9 @@ static int vmjpeg_vf_states(struct vframe_states *states, void *);
static int vmjpeg_event_cb(int type, void *data, void *private_data);
static void vmjpeg_work(struct work_struct *work);
static int pre_decode_buf_level = 0x800;
+static int start_decode_buf_level = 0x2000;
static u32 without_display_mode;
+static u32 dynamic_buf_num_margin;
#undef pr_info
#define pr_info printk
unsigned int mmjpeg_debug_mask = 0xff;
@@ -111,6 +115,7 @@ unsigned int mmjpeg_debug_mask = 0xff;
#define PRINT_FRAMEBASE_DATA 0x0400
#define PRINT_FLAG_TIMEOUT_STATUS 0x1000
#define PRINT_FLAG_V4L_DETAIL 0x8000
+#define IGNORE_PARAM_FROM_CONFIG 0x8000000
int mmjpeg_debug_print(int index, int debug_flag, const char *fmt, ...)
{
@@ -215,6 +220,8 @@ struct vdec_mjpeg_hw_s {
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
+ int buf_num;
+ int dynamic_buf_num_margin;
};
static void reset_process_time(struct vdec_mjpeg_hw_s *hw);
@@ -275,7 +282,7 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
reg = READ_VREG(MREG_FROM_AMRISC);
index = READ_VREG(AV_SCRATCH_5);
- if (index >= DECODE_BUFFER_NUM_MAX) {
+ if (index >= hw->buf_num) {
pr_err("fatal error, invalid buffer index.");
return IRQ_HANDLED;
}
@@ -291,15 +298,15 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
- struct aml_vdec_pic_infos info;
+ struct aml_vdec_ps_infos ps;
- info.visible_width = hw->frame_width;
- info.visible_height = hw->frame_height;
- info.coded_width = ALIGN(hw->frame_width, 64);
- info.coded_height = ALIGN(hw->frame_height, 64);
- info.dpb_size = MAX_BMMU_BUFFER_NUM - 1;
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
if (!ctx->v4l_codec_ready)
@@ -309,11 +316,6 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->buffer_spec[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -469,7 +471,7 @@ static void vmjpeg_canvas_init(struct vdec_mjpeg_hw_s *hw)
decbuf_uv_size = 0x80000;
decbuf_size = 0x300000;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
int canvas;
if (hw->is_used_v4l) {
@@ -645,9 +647,10 @@ static void vmjpeg_dump_state(struct vdec_s *vdec)
mmjpeg_debug_print(DECODE_ID(hw), 0,
"====== %s\n", __func__);
mmjpeg_debug_print(DECODE_ID(hw), 0,
- "width/height (%d/%d)\n",
+ "width/height (%d/%d) buf_num %d\n",
hw->frame_width,
- hw->frame_height
+ hw->frame_height,
+ hw->buf_num
);
mmjpeg_debug_print(DECODE_ID(hw), 0,
"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d input_empty %d\n",
@@ -839,7 +842,7 @@ static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
mmjpeg_debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
@@ -941,28 +944,40 @@ static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i
return 0;
}
+static int vmjpeg_get_buf_num(struct vdec_mjpeg_hw_s *hw)
+{
+ int buf_num = DECODE_BUFFER_NUM_DEF;
+
+ buf_num += hw->dynamic_buf_num_margin;
+
+ if (buf_num > DECODE_BUFFER_NUM_MAX)
+ buf_num = DECODE_BUFFER_NUM_MAX;
+
+ return buf_num;
+}
+
static bool is_enough_free_buffer(struct vdec_mjpeg_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- return i == DECODE_BUFFER_NUM_MAX ? false : true;
+ return i == hw->buf_num ? false : true;
}
static int find_free_buffer(struct vdec_mjpeg_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- if (i == DECODE_BUFFER_NUM_MAX)
+ if (i == hw->buf_num)
return -1;
if (hw->is_used_v4l)
@@ -975,7 +990,7 @@ static int find_free_buffer(struct vdec_mjpeg_hw_s *hw)
static int vmjpeg_hw_ctx_restore(struct vdec_mjpeg_hw_s *hw)
{
struct buffer_spec_s *buff_spec;
- u32 index, i;
+ int index, i;
index = find_free_buffer(hw);
if (index < 0)
@@ -988,7 +1003,7 @@ static int vmjpeg_hw_ctx_restore(struct vdec_mjpeg_hw_s *hw)
vmjpeg_canvas_init(hw);
} else {
if (!hw->is_used_v4l) {
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
buff_spec = &hw->buffer_spec[i];
canvas_config_config(buff_spec->y_canvas_index,
&buff_spec->canvas_config[0]);
@@ -1150,12 +1165,12 @@ static void run(struct vdec_s *vdec, unsigned long mask,
hw->run_count++;
vdec_reset_core(vdec);
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- if (i == DECODE_BUFFER_NUM_MAX) {
+ if (i == hw->buf_num) {
hw->dec_result = DEC_RESULT_AGAIN;
vdec_schedule_work(&hw->work);
return;
@@ -1395,14 +1410,13 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
struct vdec_mjpeg_hw_s *hw = NULL;
+ int config_val = 0;
if (pdata == NULL) {
pr_info("ammvdec_mjpeg memory resource undefined.\n");
return -EFAULT;
}
- hw = (struct vdec_mjpeg_hw_s *)devm_kzalloc(&pdev->dev,
- sizeof(struct vdec_mjpeg_hw_s), GFP_KERNEL);
hw = vzalloc(sizeof(struct vdec_mjpeg_hw_s));
if (hw == NULL) {
pr_info("\nammvdec_mjpeg device data allocation failed\n");
@@ -1436,6 +1450,19 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev)
snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
PROVIDER_NAME ".%02x", pdev->id & 0xff);
+ if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
+ mmjpeg_debug_print(DECODE_ID(hw), 0, "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;
+ } else {
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ }
+
+ hw->buf_num = vmjpeg_get_buf_num(hw);
+
vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
&vf_provider_ops, pdata);
@@ -1460,6 +1487,8 @@ static int ammvdec_mjpeg_probe(struct platform_device *pdev)
pdata->dec_status = NULL;
return -ENODEV;
}
+ vdec_set_prepare_level(pdata, start_decode_buf_level);
+
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
@@ -1559,6 +1588,8 @@ MODULE_PARM_DESC(pre_decode_buf_level,
module_param(udebug_flag, uint, 0664);
MODULE_PARM_DESC(udebug_flag, "\n amvdec_mmpeg12 udebug_flag\n");
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n");
module_param(decode_timeout_val, uint, 0664);
MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mjpeg decode_timeout_val\n");
@@ -1568,6 +1599,9 @@ module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
module_param(radr, uint, 0664);
MODULE_PARM_DESC(radr, "\nradr\n");
+module_param(start_decode_buf_level, uint, 0664);
+MODULE_PARM_DESC(start_decode_buf_level, "\nstart_decode_buf_level\n");
+
module_param(rval, uint, 0664);
MODULE_PARM_DESC(rval, "\nrval\n");
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index 6643f41..6f78276 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -48,6 +48,7 @@
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
+#include "../utils/config_parser.h"
#define MEM_NAME "codec_mmpeg12"
@@ -92,8 +93,11 @@
#define SEQINFO_PROG 0x00010000
#define CCBUF_SIZE (5*1024)
-#define VF_POOL_SIZE 32
-#define DECODE_BUFFER_NUM_MAX 8
+#define VF_POOL_SIZE 64
+#define DECODE_BUFFER_NUM_MAX 16
+#define DECODE_BUFFER_NUM_DEF 8
+#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1)
+
#define PUT_INTERVAL (HZ/100)
#define WORKSPACE_SIZE (4*SZ_64K) /*swap&ccbuf&matirx&MV*/
#define CTX_LMEM_SWAP_OFFSET 0
@@ -102,23 +106,23 @@
#define CTX_CO_MV_OFFSET (CTX_QUANT_MATRIX_OFFSET + 1*1024)
#define CTX_DECBUF_OFFSET (CTX_CO_MV_OFFSET + 0x11000)
-#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1)
#define DEFAULT_MEM_SIZE (32*SZ_1M)
static u32 buf_size = 32 * 1024 * 1024;
static int pre_decode_buf_level = 0x800;
+static int start_decode_buf_level = 0x4000;
static u32 dec_control;
static u32 error_frame_skip_level = 2;
-static u32 stat;
static u32 udebug_flag;
static unsigned int radr;
static unsigned int rval;
static u32 without_display_mode;
+static u32 dynamic_buf_num_margin;
#define VMPEG12_DEV_NUM 9
static unsigned int max_decode_instance_num = VMPEG12_DEV_NUM;
static unsigned int max_process_time[VMPEG12_DEV_NUM];
-static unsigned int decode_timeout_val = 100;
+static unsigned int decode_timeout_val = 200;
#define INCPTR(p) ptr_atomic_wrap_inc(&p)
#define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002
@@ -237,6 +241,7 @@ struct vdec_mpeg12_hw_s {
unsigned long int start_process_time;
u32 last_vld_level;
u32 eos;
+
struct pic_info_t pics[DECODE_BUFFER_NUM_MAX];
u32 canvas_spec[DECODE_BUFFER_NUM_MAX];
u64 lastpts64;
@@ -300,6 +305,8 @@ struct vdec_mpeg12_hw_s {
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
+ u32 buf_num;
+ u32 dynamic_buf_num_margin;
};
static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
@@ -329,6 +336,7 @@ unsigned int mpeg12_debug_mask = 0xff;
#define PRINT_FLAG_USERDATA_DETAIL 0x2000
#define PRINT_FLAG_TIMEOUT_STATUS 0x4000
#define PRINT_FLAG_V4L_DETAIL 0x8000
+#define IGNORE_PARAM_FROM_CONFIG 0x8000000
@@ -384,7 +392,7 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
@@ -450,28 +458,40 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
}
+static unsigned int vmpeg12_get_buf_num(struct vdec_mpeg12_hw_s *hw)
+{
+ unsigned int buf_num = DECODE_BUFFER_NUM_DEF;
+
+ buf_num += hw->dynamic_buf_num_margin;
+
+ if (buf_num > DECODE_BUFFER_NUM_MAX)
+ buf_num = DECODE_BUFFER_NUM_MAX;
+
+ return buf_num;
+}
+
static bool is_enough_free_buffer(struct vdec_mpeg12_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- return i == DECODE_BUFFER_NUM_MAX ? false : true;
+ return (i == hw->buf_num) ? false : true;
}
static int find_free_buffer(struct vdec_mpeg12_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- if (i == DECODE_BUFFER_NUM_MAX)
+ if (i == hw->buf_num)
return -1;
if (hw->is_used_v4l)
@@ -484,12 +504,12 @@ static u32 spec_to_index(struct vdec_mpeg12_hw_s *hw, u32 spec)
{
u32 i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->canvas_spec[i] == spec)
return i;
}
- return DECODE_BUFFER_NUM_MAX;
+ return hw->buf_num;
}
static void set_frame_info(struct vdec_mpeg12_hw_s *hw, struct vframe_s *vf)
@@ -1174,7 +1194,7 @@ static void userdata_push_do_work(struct work_struct *work)
reg = READ_VREG(AV_SCRATCH_J);
- hw->userdata_wp_ctx = reg;
+ hw->userdata_wp_ctx = reg & (~(1<<16));
meta_info.flags = ((reg >> 30) << 1);
meta_info.flags |= (VFORMAT_MPEG12 << 3);
/* check top_field_first flag */
@@ -1376,11 +1396,6 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->pics[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -1519,7 +1534,7 @@ static int update_reference(struct vdec_mpeg12_hw_s *hw,
hw->refs[0] = hw->refs[1];
hw->refs[1] = index;
/* second pic do not output */
- index = DECODE_BUFFER_NUM_MAX;
+ index = hw->buf_num;
} else {
hw->vfbuf_use[hw->refs[0]]--;
hw->refs[0] = hw->refs[1];
@@ -1599,7 +1614,7 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
(info & FRAME_PICTURE_MASK) != FRAME_PICTURE)
hw->first_i_frame_ready = 1; /* for field struct case*/
- if (index >= DECODE_BUFFER_NUM_MAX) {
+ if (index >= hw->buf_num) {
debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
"mmpeg12: invalid buf index: %d\n", index);
hw->dec_result = DEC_RESULT_ERROR;
@@ -1632,15 +1647,15 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
- struct aml_vdec_pic_infos info;
+ struct aml_vdec_ps_infos ps;
- info.visible_width = hw->frame_width;
- info.visible_height = hw->frame_height;
- info.coded_width = ALIGN(hw->frame_width, 64);
- info.coded_height = ALIGN(hw->frame_height, 64);
- info.dpb_size = MAX_BMMU_BUFFER_NUM - 1;
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
if (!ctx->v4l_codec_ready)
@@ -1697,11 +1712,11 @@ static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
} else {
/* drop b frame before reference pic ready */
if (hw->refs[0] == -1)
- index = DECODE_BUFFER_NUM_MAX;
+ index = hw->buf_num;
}
vmpeg12_save_hw_context(hw, reg);
- if (index >= DECODE_BUFFER_NUM_MAX) {
+ if (index >= hw->buf_num) {
if (hw->dec_num != 2) {
debug_print(DECODE_ID(hw), 0,
"mmpeg12: drop pic num %d, type %c, index %d, offset %x\n",
@@ -1794,7 +1809,7 @@ static void flush_output(struct vdec_mpeg12_hw_s *hw)
if (hw->dec_num < 2)
return;
- if (index >= 0 && index < DECODE_BUFFER_NUM_MAX)
+ if (index >= 0 && index < hw->buf_num)
prepare_display_buf(hw, &hw->pics[index]);
}
@@ -2077,13 +2092,13 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
decbuf_size = 0x300000;
}
- for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) {
+ for (i = 0; i < hw->buf_num + 1; i++) {
unsigned canvas;
- if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* SWAP&CCBUF&MATIRX&MV */
+ if (i == hw->buf_num) /* SWAP&CCBUF&MATIRX&MV */
decbuf_size = WORKSPACE_SIZE;
- if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) {
+ if (hw->is_used_v4l && !(i == hw->buf_num)) {
continue;
} else {
ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
@@ -2095,7 +2110,7 @@ static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
}
}
- if (i == (MAX_BMMU_BUFFER_NUM - 1)) {
+ if (i == hw->buf_num) {
if (hw->ccbuf_phyAddress_is_remaped_nocache)
codec_mm_unmap_phyaddr(hw->ccbuf_phyAddress_virt);
hw->ccbuf_phyAddress_virt = NULL;
@@ -2175,10 +2190,11 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
debug_print(DECODE_ID(hw), 0,
"====== %s\n", __func__);
debug_print(DECODE_ID(hw), 0,
- "width/height (%d/%d),i_first %d\n",
+ "width/height (%d/%d),i_first %d, buf_num %d\n",
hw->frame_width,
hw->frame_height,
- hw->first_i_frame_ready
+ hw->first_i_frame_ready,
+ hw->buf_num
);
debug_print(DECODE_ID(hw), 0,
"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n",
@@ -2193,7 +2209,7 @@ static void vmpeg2_dump_state(struct vdec_s *vdec)
hw->input_empty
);
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
debug_print(DECODE_ID(hw), 0,
"index %d, used %d\n", i, hw->vfbuf_use[i]);
}
@@ -2360,16 +2376,16 @@ static void check_timer_func(unsigned long arg)
static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
{
- u32 index, i;
+ int index, i;
index = find_free_buffer(hw);
- if (index >= DECODE_BUFFER_NUM_MAX)
+ if (index < 0 || index >= hw->buf_num)
return -1;
if (!hw->init_flag)
vmpeg12_canvas_init(hw);
else {
if (!hw->is_used_v4l) {
WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
canvas_config_config(canvas_y(hw->canvas_spec[i]),
&hw->canvas_config[i][0]);
canvas_config_config(canvas_u(hw->canvas_spec[i]),
@@ -2512,6 +2528,7 @@ static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw)
hw->start_process_time = 0;
hw->init_flag = 0;
hw->error_frame_skip_level = error_frame_skip_level;
+
if (dec_control)
hw->dec_control = dec_control;
}
@@ -2784,6 +2801,7 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
struct vdec_mpeg12_hw_s *hw = NULL;
+ int config_val = 0;
pr_info("ammvdec_mpeg12 probe start.\n");
@@ -2830,6 +2848,23 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
&vf_provider_ops, pdata);
+ if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
+ debug_print(DECODE_ID(hw), 0, "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;
+ } else {
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ }
+ hw->buf_num = vmpeg12_get_buf_num(hw);
+
+ if (pdata->parallel_dec == 1) {
+ int i;
+ for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
+ hw->canvas_spec[i] = 0xffffff;
+ }
platform_set_drvdata(pdev, pdata);
hw->canvas_mode = pdata->canvas_mode;
hw->platform_dev = pdev;
@@ -2854,6 +2889,8 @@ static int ammvdec_mpeg12_probe(struct platform_device *pdev)
pdata->dec_status = NULL;
return -ENODEV;
}
+ vdec_set_prepare_level(pdata, start_decode_buf_level);
+
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
else {
@@ -2983,12 +3020,20 @@ static struct codec_profile_t ammvdec_mpeg12_profile = {
};
static struct mconfig mmpeg12_configs[] = {
- MC_PU32("stat", &stat),
MC_PU32("radr", &radr),
MC_PU32("rval", &rval),
MC_PU32("dec_control", &dec_control),
MC_PU32("error_frame_skip_level", &error_frame_skip_level),
MC_PU32("decode_timeout_val", &decode_timeout_val),
+ MC_PU32("start_decode_buf_level", &start_decode_buf_level),
+ MC_PU32("pre_decode_buf_level", &pre_decode_buf_level),
+ MC_PU32("debug_enable", &debug_enable),
+ MC_PU32("udebug_flag", &udebug_flag),
+ MC_PU32("without_display_mode", &without_display_mode),
+ MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin),
+#ifdef AGAIN_HAS_THRESHOLD
+ MC_PU32("again_threshold", &again_threshold),
+#endif
};
static struct mconfig_node mmpeg12_node;
@@ -3031,9 +3076,17 @@ MODULE_PARM_DESC(debug_enable,
module_param(pre_decode_buf_level, int, 0664);
MODULE_PARM_DESC(pre_decode_buf_level,
"\n ammvdec_mpeg12 pre_decode_buf_level\n");
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+ "\n ammvdec_mpeg12 start_decode_buf_level\n");
+
module_param(decode_timeout_val, uint, 0664);
MODULE_PARM_DESC(decode_timeout_val, "\n ammvdec_mpeg12 decode_timeout_val\n");
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n ammvdec_mpeg12 dynamic_buf_num_margin\n");
+
module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
module_param(udebug_flag, uint, 0664);
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index 30e4072..c098a5e 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -46,6 +46,7 @@
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../utils/firmware.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
+#include "../utils/config_parser.h"
#define DRIVER_NAME "ammvdec_mpeg4"
#define MODULE_NAME "ammvdec_mpeg4"
@@ -91,8 +92,9 @@
/* values between 6 and 14 are reserved */
#define PARC_EXTENDED 15
-#define VF_POOL_SIZE 16
-#define DECODE_BUFFER_NUM_MAX 8
+#define VF_POOL_SIZE 64
+#define DECODE_BUFFER_NUM_MAX 16
+#define DECODE_BUFFER_NUM_DEF 8
#define PUT_INTERVAL (HZ/100)
#define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1)
#define WORKSPACE_SIZE (12*SZ_64K)
@@ -135,16 +137,18 @@ 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 pre_decode_buf_level = 0x800;
+static int start_decode_buf_level = 0x4000;
static int debug_enable;
static unsigned int radr;
static unsigned int rval;
/* 0x40bit = 8byte */
static unsigned int frmbase_cont_bitlevel = 0x40;
+static unsigned int dynamic_buf_num_margin;
#define VMPEG4_DEV_NUM 9
static unsigned int max_decode_instance_num = VMPEG4_DEV_NUM;
static unsigned int max_process_time[VMPEG4_DEV_NUM];
-static unsigned int decode_timeout_val = 100;
+static unsigned int decode_timeout_val = 200;
static u32 without_display_mode;
@@ -167,6 +171,7 @@ unsigned int mpeg4_debug_mask = 0xff;
#define PRINT_FLAG_VDEC_STATUS 0x0800
#define PRINT_FLAG_TIMEOUT_STATUS 0x1000
#define PRINT_FLAG_V4L_DETAIL 0x8000
+#define IGNORE_PARAM_FROM_CONFIG 0x8000000
int mmpeg4_debug_print(int index, int debug_flag, const char *fmt, ...)
{
@@ -298,6 +303,8 @@ struct vdec_mpeg4_hw_s {
bool is_used_v4l;
void *v4l2_ctx;
bool v4l_params_parsed;
+ u32 buf_num;
+ u32 dynamic_buf_num_margin;
};
static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw);
static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw);
@@ -331,6 +338,18 @@ static unsigned char aspect_ratio_table[16] = {
static void reset_process_time(struct vdec_mpeg4_hw_s *hw);
+
+static int vmpeg4_get_buf_num(struct vdec_mpeg4_hw_s *hw)
+{
+ int buf_num = DECODE_BUFFER_NUM_DEF;
+
+ buf_num += hw->dynamic_buf_num_margin;
+ if (buf_num > DECODE_BUFFER_NUM_MAX)
+ buf_num = DECODE_BUFFER_NUM_MAX;
+
+ return buf_num;
+}
+
static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i)
{
int ret;
@@ -345,7 +364,7 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
mmpeg4_debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
@@ -421,24 +440,24 @@ static bool is_enough_free_buffer(struct vdec_mpeg4_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- return i == DECODE_BUFFER_NUM_MAX ? false : true;
+ return i == hw->buf_num ? false : true;
}
static int find_free_buffer(struct vdec_mpeg4_hw_s *hw)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->vfbuf_use[i] == 0)
break;
}
- if (i == DECODE_BUFFER_NUM_MAX)
+ if (i == hw->buf_num)
return -1;
if (hw->is_used_v4l)
@@ -452,7 +471,7 @@ static int spec_to_index(struct vdec_mpeg4_hw_s *hw, u32 spec)
{
int i;
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
if (hw->canvas_spec[i] == spec)
return i;
}
@@ -717,11 +736,6 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->pic[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -909,7 +923,7 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
READ_VREG(VIFF_BIT_CNT));
if (vdec_frame_based(vdec)) {
- //vmpeg4_save_hw_context(hw);
+ vmpeg4_save_hw_context(hw);
hw->dec_result = DEC_RESULT_DONE;
vdec_schedule_work(&hw->work);
} else {
@@ -954,15 +968,15 @@ static irqreturn_t vmpeg4_isr_thread_fn(struct vdec_s *vdec, int irq)
(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
- struct aml_vdec_pic_infos info;
+ struct aml_vdec_ps_infos ps;
- info.visible_width = hw->frame_width;
- info.visible_height = hw->frame_height;
- info.coded_width = ALIGN(hw->frame_width, 64);
- info.coded_height = ALIGN(hw->frame_height, 64);
- info.dpb_size = MAX_BMMU_BUFFER_NUM - 1;
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
if (!ctx->v4l_codec_ready)
@@ -1516,14 +1530,14 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw)
}
}
- for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) {
+ for (i = 0; i < hw->buf_num + 1; i++) {
unsigned canvas;
- if (i == (MAX_BMMU_BUFFER_NUM - 1))
+ if (i == hw->buf_num)
decbuf_size = WORKSPACE_SIZE;
- if (hw->is_used_v4l && !(i == (MAX_BMMU_BUFFER_NUM - 1))) {
+ if (hw->is_used_v4l && !(i == hw->buf_num)) {
continue;
} else {
ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
@@ -1535,7 +1549,7 @@ static int vmpeg4_canvas_init(struct vdec_mpeg4_hw_s *hw)
}
}
- if (i == (MAX_BMMU_BUFFER_NUM - 1)) {
+ if (i == hw->buf_num) {
hw->buf_start = decbuf_start;
} else {
if (vdec->parallel_dec == 1) {
@@ -1595,13 +1609,14 @@ static void vmpeg4_dump_state(struct vdec_s *vdec)
mmpeg4_debug_print(DECODE_ID(hw), 0,
"====== %s\n", __func__);
mmpeg4_debug_print(DECODE_ID(hw), 0,
- "width/height (%d/%d), i_fram:%d, buffer_not_ready %d\n",
+ "width/height (%d/%d), i_fram:%d, buffer_not_ready %d, buf_num %d\n",
hw->frame_width,
hw->frame_height,
hw->first_i_frame_ready,
- hw->buffer_not_ready
+ hw->buffer_not_ready,
+ hw->buf_num
);
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
mmpeg4_debug_print(DECODE_ID(hw), 0,
"index %d, used %d\n", i, hw->vfbuf_use[i]);
}
@@ -1795,7 +1810,7 @@ static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw)
return -1;
} else {
if (!hw->is_used_v4l) {
- for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+ for (i = 0; i < hw->buf_num; i++) {
canvas_config_config(canvas_y(hw->canvas_spec[i]),
&hw->canvas_config[i][0]);
canvas_config_config(canvas_u(hw->canvas_spec[i]),
@@ -2239,6 +2254,7 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
struct vdec_mpeg4_hw_s *hw = NULL;
+ int config_val = 0;
if (pdata == NULL) {
pr_err("%s memory resource undefined.\n", __func__);
@@ -2272,6 +2288,19 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
PROVIDER_NAME ".%02x", pdev->id & 0xff);
+
+ if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
+ mmpeg4_debug_print(DECODE_ID(hw), 0, "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;
+ } else {
+ hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ }
+ hw->buf_num = vmpeg4_get_buf_num(hw);
+
if (pdata->parallel_dec == 1) {
int i;
for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
@@ -2317,6 +2346,7 @@ static int ammvdec_mpeg4_probe(struct platform_device *pdev)
pdata->dec_status = NULL;
return -ENODEV;
}
+ vdec_set_prepare_level(pdata, start_decode_buf_level);
if (pdata->parallel_dec == 1)
vdec_core_request(pdata, CORE_MASK_VDEC_1);
@@ -2433,6 +2463,9 @@ MODULE_PARM_DESC(debug_enable,
module_param(frmbase_cont_bitlevel, uint, 0664);
MODULE_PARM_DESC(frmbase_cont_bitlevel, "\nfrmbase_cont_bitlevel\n");
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n");
+
module_param(radr, uint, 0664);
MODULE_PARM_DESC(radr, "\nradr\n");
@@ -2446,7 +2479,11 @@ module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
module_param(pre_decode_buf_level, int, 0664);
MODULE_PARM_DESC(pre_decode_buf_level,
- "\n ammvdec_ mpeg4 pre_decode_buf_level\n");
+ "\n ammvdec_mpeg4 pre_decode_buf_level\n");
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+ "\n ammvdec_mpeg4 start_decode_buf_level\n");
module_param(udebug_flag, uint, 0664);
MODULE_PARM_DESC(udebug_flag, "\n ammvdec_mpeg4 udebug_flag\n");
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
index 590b812..461621b 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
@@ -41,6 +41,7 @@ struct decoder_bmmu_box {
struct mutex mutex;
struct list_head list;
int total_size;
+ int box_ref_cnt;
int change_size_on_need_smaller;
int align2n; /*can overwite on idx alloc */
int mem_flags; /*can overwite on idx alloc */
@@ -78,6 +79,25 @@ static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box)
return 0;
}
+bool decoder_bmmu_box_valide_check(void *box)
+{
+ struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
+ struct decoder_bmmu_box *bmmu_box = NULL;
+ bool is_valide = false;
+
+ mutex_lock(&mgr->mutex);
+ list_for_each_entry(bmmu_box, &mgr->box_list, list) {
+ if (bmmu_box && bmmu_box == box) {
+ is_valide = true;
+ break;
+ }
+ }
+ mutex_unlock(&mgr->mutex);
+
+ return is_valide;
+}
+EXPORT_SYMBOL(decoder_bmmu_box_valide_check);
+
void *decoder_bmmu_box_alloc_box(const char *name,
int channel_id, int max_num,
int aligned, int mem_flags)
@@ -169,6 +189,7 @@ int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n,
box->total_size += mm->buffer_size;
mm->ins_id = box->channel_id;
mm->ins_buffer_id = idx;
+ box->box_ref_cnt++;
}
}
mutex_unlock(&box->mutex);
@@ -193,6 +214,7 @@ int decoder_bmmu_box_free_idx(void *handle, int idx)
codec_mm_release(mm, box->name);
box->mm_list[idx] = NULL;
mm = NULL;
+ box->box_ref_cnt--;
}
mutex_unlock(&box->mutex);
return 0;
@@ -224,6 +246,31 @@ int decoder_bmmu_box_free(void *handle)
}
EXPORT_SYMBOL(decoder_bmmu_box_free);
+void decoder_bmmu_try_to_release_box(void *handle)
+{
+ struct decoder_bmmu_box *box = handle;
+ bool is_keep = false;
+ int i;
+
+ if (!box || box->box_ref_cnt)
+ return;
+
+ mutex_lock(&box->mutex);
+ for (i = 0; i < box->max_mm_num; i++) {
+ if (box->mm_list[i]) {
+ is_keep = true;
+ break;
+ }
+ }
+ mutex_unlock(&box->mutex);
+
+ if (!is_keep) {
+ decoder_bmmu_box_mgr_del_box(box);
+ kfree(box);
+ }
+}
+EXPORT_SYMBOL(decoder_bmmu_try_to_release_box);
+
void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx)
{
struct decoder_bmmu_box *box = box_handle;
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
index 8744da1..778cb8e 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
@@ -60,6 +60,9 @@ int decoder_bmmu_box_alloc_idx_wait(
int mem_flags,
int wait_flags);
+bool decoder_bmmu_box_valide_check(void *box);
+void decoder_bmmu_try_to_release_box(void *handle);
+
int decoder_bmmu_box_init(void);
void decoder_bmmu_box_exit(void);
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
index 5ab7c16..8389514 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
@@ -34,6 +34,7 @@ struct decoder_mmu_box {
const char *name;
int channel_id;
int tvp_mode;
+ int box_ref_cnt;
struct mutex mutex;
struct list_head list;
struct codec_mm_scatter *sc_list[1];
@@ -75,6 +76,51 @@ static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box)
return 0;
}
+bool decoder_mmu_box_valide_check(void *box)
+{
+ struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
+ struct decoder_mmu_box *mmu_box = NULL;
+ bool is_valide = false;
+
+ mutex_lock(&mgr->mutex);
+ list_for_each_entry(mmu_box, &mgr->box_list, list) {
+ if (mmu_box && mmu_box == box) {
+ is_valide = true;
+ break;
+ }
+ }
+ mutex_unlock(&mgr->mutex);
+
+ return is_valide;
+}
+EXPORT_SYMBOL(decoder_mmu_box_valide_check);
+
+void decoder_mmu_try_to_release_box(void *handle)
+{
+ struct decoder_mmu_box *box = handle;
+ bool is_keep = false;
+ int i;
+
+ if (!box || box->box_ref_cnt)
+ return;
+
+ mutex_lock(&box->mutex);
+ for (i = 0; i < box->max_sc_num; i++) {
+ if (box->sc_list[i]) {
+ is_keep = true;
+ break;
+ }
+ }
+ mutex_unlock(&box->mutex);
+
+ if (!is_keep) {
+ decoder_mmu_box_mgr_del_box(box);
+ codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
+ kfree(box);
+ }
+}
+EXPORT_SYMBOL(decoder_mmu_try_to_release_box);
+
int decoder_mmu_box_sc_check(void *handle, int is_tvp)
{
struct decoder_mmu_box *box = handle;
@@ -159,6 +205,7 @@ int decoder_mmu_box_alloc_idx(
return -1;
}
box->sc_list[idx] = sc;
+ box->box_ref_cnt++;
}
for (i = 0; i < num_pages; i++)
@@ -209,7 +256,13 @@ int decoder_mmu_box_free_idx(void *handle, int idx)
if (sc && sc->page_cnt > 0) {
codec_mm_scatter_dec_owner_user(sc, 0);
box->sc_list[idx] = NULL;
- } mutex_unlock(&box->mutex);
+ box->box_ref_cnt--;
+ }
+ mutex_unlock(&box->mutex);
+
+ if (sc && box->box_ref_cnt == 0)
+ codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
+
return 0;
}
EXPORT_SYMBOL(decoder_mmu_box_free_idx);
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
index 9f4e098..029f91a 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
@@ -42,6 +42,8 @@ int decoder_mmu_box_move_keep_idx(void *box_handle,
int decoder_mmu_box_free_keep(int keep_id);
int decoder_mmu_box_free_all_keep(void);
void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx);
+bool decoder_mmu_box_valide_check(void *box);
+void decoder_mmu_try_to_release_box(void *handle);
int decoder_mmu_box_init(void);
void decoder_mmu_box_exit(void);
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index 54f9051..41e84ba 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -33,6 +33,9 @@
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/video_sink/ionvideo_ext.h>
+#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
+#endif
#include <linux/amlogic/media/vfm/vfm_ext.h>
/*for VDEC_DEBUG_SUPPORT*/
#include <linux/time.h>
@@ -113,6 +116,9 @@ static DEFINE_SPINLOCK(vdec_spin_lock);
#define DISABLE_FRAME_INFO 2
static int frameinfo_flag = 0;
+static int v4lvideo_add_di = 1;
+static int max_di_instance = 2;
+
//static int path_debug = 0;
static struct vframe_qos_s *frame_info_buf_in = NULL;
@@ -1558,6 +1564,7 @@ EXPORT_SYMBOL(vdec_set_flag);
void vdec_set_eos(struct vdec_s *vdec, bool eos)
{
struct vdec_core_s *core = vdec_core;
+
vdec->input.eos = eos;
if (vdec->slave)
@@ -2203,12 +2210,64 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
"%s %s", vdec->vf_provider_name,
"amvideo");
+ snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
+ "vdec-map-%d", vdec->id);
} else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) {
snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
"%s %s %s", vdec->vf_provider_name,
vdec->vf_receiver_name, "amvideo");
snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
"vdec-map-%d", vdec->id);
+ } else if (p->frame_base_video_path ==
+ FRAME_BASE_PATH_DI_V4LVIDEO) {
+#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
+ r = v4lvideo_assign_map(&vdec->vf_receiver_name,
+ &vdec->vf_receiver_inst);
+#else
+ r = -1;
+#endif
+ if (r < 0) {
+ pr_err("V4lVideo frame receiver allocation failed.\n");
+ mutex_lock(&vdec_mutex);
+ inited_vcodec_num--;
+ mutex_unlock(&vdec_mutex);
+ goto error;
+ }
+ if (!v4lvideo_add_di || vdec_secure(vdec))
+ snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
+ "%s %s", vdec->vf_provider_name,
+ vdec->vf_receiver_name);
+ else {
+ if (vdec->vf_receiver_inst == 0)
+ snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
+ "%s %s %s", vdec->vf_provider_name,
+ "dimulti.1",
+ vdec->vf_receiver_name);
+ else if ((vdec->vf_receiver_inst <
+ max_di_instance) &&
+ (vdec->vf_receiver_inst == 1))
+ snprintf(vdec->vfm_map_chain,
+ VDEC_MAP_NAME_SIZE,
+ "%s %s %s",
+ vdec->vf_provider_name,
+ "deinterlace",
+ vdec->vf_receiver_name);
+ else if (vdec->vf_receiver_inst <
+ max_di_instance)
+ snprintf(vdec->vfm_map_chain,
+ VDEC_MAP_NAME_SIZE,
+ "%s %s%d %s",
+ vdec->vf_provider_name,
+ "dimulti.",
+ vdec->vf_receiver_inst,
+ vdec->vf_receiver_name);
+ else
+ snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
+ "%s %s", vdec->vf_provider_name,
+ vdec->vf_receiver_name);
+ }
+ snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
+ "vdec-map-%d", vdec->id);
}
if (vfm_map_add(vdec->vfm_map_id,
@@ -2419,6 +2478,59 @@ int vdec_reset(struct vdec_s *vdec)
}
EXPORT_SYMBOL(vdec_reset);
+int vdec_v4l2_reset(struct vdec_s *vdec, int flag)
+{
+ //trace_vdec_reset(vdec); /*DEBUG_TMP*/
+ pr_debug("vdec_v4l2_reset %d\n", flag);
+ vdec_disconnect(vdec);
+ if (flag != 2) {
+ if (vdec->vframe_provider.name)
+ vf_unreg_provider(&vdec->vframe_provider);
+
+ if ((vdec->slave) && (vdec->slave->vframe_provider.name))
+ vf_unreg_provider(&vdec->slave->vframe_provider);
+
+ if (vdec->reset) {
+ vdec->reset(vdec);
+ if (vdec->slave)
+ vdec->slave->reset(vdec->slave);
+ }
+ vdec->mc_loaded = 0;/*clear for reload firmware*/
+
+ vdec_input_release(&vdec->input);
+
+ vdec_input_init(&vdec->input, vdec);
+
+ vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
+ vdec->sys_info->height);
+
+ vf_reg_provider(&vdec->vframe_provider);
+ vf_notify_receiver(vdec->vf_provider_name,
+ VFRAME_EVENT_PROVIDER_START, vdec);
+
+ if (vdec->slave) {
+ vf_reg_provider(&vdec->slave->vframe_provider);
+ vf_notify_receiver(vdec->slave->vf_provider_name,
+ VFRAME_EVENT_PROVIDER_START, vdec->slave);
+ vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
+ }
+ } else {
+ if (vdec->reset) {
+ vdec->reset(vdec);
+ if (vdec->slave)
+ vdec->slave->reset(vdec->slave);
+ }
+ }
+
+ vdec_connect(vdec);
+
+ vdec_frame_check_init(vdec);
+
+ return 0;
+}
+EXPORT_SYMBOL(vdec_v4l2_reset);
+
+
void vdec_free_cmabuf(void)
{
mutex_lock(&vdec_mutex);
@@ -2647,6 +2759,7 @@ unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
inc_profi_count(mask, vdec->check_count);
#endif
if (vdec_core_with_input(mask)) {
+
/* check frame based input underrun */
if (input && !input->eos && input_frame_based(input)
&& (!vdec_input_next_chunk(input))) {
@@ -3744,7 +3857,7 @@ void vdec_reset_core(struct vdec_s *vdec)
*/
if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) {
- WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9));
+ WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<7)|(1<<8)|(1<<9));
} else {
WRITE_VREG(DOS_SW_RESET0,
(1<<3)|(1<<4)|(1<<5));
@@ -5081,6 +5194,14 @@ module_param(disable_switch_single_to_mult, int, 0664);
module_param(frameinfo_flag, int, 0664);
MODULE_PARM_DESC(frameinfo_flag,
"\n frameinfo_flag\n");
+module_param(v4lvideo_add_di, int, 0664);
+MODULE_PARM_DESC(v4lvideo_add_di,
+ "\n v4lvideo_add_di\n");
+
+module_param(max_di_instance, int, 0664);
+MODULE_PARM_DESC(max_di_instance,
+ "\n max_di_instance\n");
+
/*
*module_init(vdec_module_init);
*module_exit(vdec_module_exit);
diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h
index 80fa8dc..59ee2db 100644
--- a/drivers/frame_provider/decoder/utils/vdec.h
+++ b/drivers/frame_provider/decoder/utils/vdec.h
@@ -360,6 +360,8 @@ extern int vdec_destroy(struct vdec_s *vdec);
/* reset vdec */
extern int vdec_reset(struct vdec_s *vdec);
+extern int vdec_v4l2_reset(struct vdec_s *vdec, int flag);
+
extern void vdec_set_status(struct vdec_s *vdec, int status);
extern void vdec_set_next_status(struct vdec_s *vdec, int status);
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 763d62e..107efec 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -1,119 +1,64 @@
-#include <linux/file.h>
-#include <linux/anon_inodes.h>
#include "vdec_v4l2_buffer_ops.h"
-const struct file_operations v4l2_file_fops = {};
-
-static int is_v4l2_buf_file(struct file *file)
-{
- return file->f_op == &v4l2_file_fops;
-}
-
-static int vdec_v4l_alloc_fd(void)
-{
- int fd;
- struct file *file = NULL;
-
- fd = get_unused_fd_flags(O_CLOEXEC);
- if (fd < 0) {
- pr_err("v4l: get unused fd fail\n");
- return fd;
- }
-
- file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
- if (IS_ERR(file)) {
- put_unused_fd(fd);
- pr_err("v4l: get file faill\n");
- return PTR_ERR(file);
- }
-
- fd_install(fd, file);
-
- pr_info("v4l: fd %d, file %p, data %p\n",
- fd, file, file->private_data);
-
- return fd;
-}
-
-static int vdec_v4l_fd_install_data(int fd, void *data)
+int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
+ struct vdec_v4l2_buffer **out)
{
- struct file *file;
+ int ret = -1;
- file = fget(fd);
-
- if (!file) {
- pr_info("v4l: fget fd %d fail!, comm %s, pid %d\n",
- fd, current->comm, current->pid);
- return -EBADF;
- }
-
- if (!is_v4l2_buf_file(file)) {
- pr_info("v4l: v4l2 check fd fail!\n");
- return -EBADF;
- }
+ if (ctx->drv_handle == 0)
+ return -EIO;
- file->private_data = data;
+ ret = ctx->dec_if->get_param(ctx->drv_handle,
+ GET_PARAM_FREE_FRAME_BUFFER, out);
- return 0;
+ return ret;
}
+EXPORT_SYMBOL(vdec_v4l_get_buffer);
-int vdec_v4l_binding_fd_and_vf(ulong v4l_handle, void *vf)
+int vdec_v4l_set_ps_infos(struct aml_vcodec_ctx *ctx,
+ struct aml_vdec_ps_infos *ps)
{
- int ret = 0, fd = -1;
- struct vdec_v4l2_buffer *v4l_buf =
- (struct vdec_v4l2_buffer *) v4l_handle;
-
- if (v4l_buf->m.vf_fd > 0)
- return 0;
-
- fd = vdec_v4l_alloc_fd();
- if (fd < 0) {
- pr_err("v4l: alloc fd fail %d.\n", fd);
- return fd;
- }
+ int ret = 0;
- ret = vdec_v4l_fd_install_data(fd, vf);
- if (ret < 0) {
- put_unused_fd(fd);
- pr_err("v4l: fd install data fail %d.\n", ret);
- return ret;
- }
+ if (ctx->drv_handle == 0)
+ return -EIO;
- v4l_buf->m.vf_fd = fd;
+ ret = ctx->dec_if->set_param(ctx->drv_handle,
+ SET_PARAM_PS_INFO, ps);
- return 0;
+ return ret;
}
-EXPORT_SYMBOL(vdec_v4l_binding_fd_and_vf);
+EXPORT_SYMBOL(vdec_v4l_set_ps_infos);
-int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
- struct vdec_v4l2_buffer **out)
+int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx,
+ struct aml_vdec_hdr_infos *hdr)
{
int ret = 0;
if (ctx->drv_handle == 0)
return -EIO;
- ret = ctx->dec_if->get_param(ctx->drv_handle,
- GET_PARAM_FREE_FRAME_BUFFER, out);
+ ret = ctx->dec_if->set_param(ctx->drv_handle,
+ SET_PARAM_HDR_INFO, hdr);
return ret;
}
-EXPORT_SYMBOL(vdec_v4l_get_buffer);
+EXPORT_SYMBOL(vdec_v4l_set_hdr_infos);
-int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx,
- struct aml_vdec_pic_infos *info)
+int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event)
{
int ret = 0;
if (ctx->drv_handle == 0)
return -EIO;
-
+ if (event == 1)
+ ctx->reset_flag = 2;
ret = ctx->dec_if->set_param(ctx->drv_handle,
- SET_PARAM_PIC_INFO, info);
+ SET_PARAM_POST_EVENT, &event);
return ret;
}
-EXPORT_SYMBOL(vdec_v4l_set_pic_infos);
+EXPORT_SYMBOL(vdec_v4l_post_evet);
int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx)
{
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 6227a8b..13f3543 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
@@ -8,15 +8,19 @@ int vdec_v4l_get_buffer(
struct aml_vcodec_ctx *ctx,
struct vdec_v4l2_buffer **out);
-int vdec_v4l_set_pic_infos(
+int vdec_v4l_set_ps_infos(
struct aml_vcodec_ctx *ctx,
- struct aml_vdec_pic_infos *info);
+ struct aml_vdec_ps_infos *ps);
+
+int vdec_v4l_set_hdr_infos(
+ struct aml_vcodec_ctx *ctx,
+ struct aml_vdec_hdr_infos *hdr);
int vdec_v4l_write_frame_sync(
struct aml_vcodec_ctx *ctx);
-int vdec_v4l_binding_fd_and_vf(
- ulong v4l_handle,
- void *vf);
+int vdec_v4l_post_evet(
+ struct aml_vcodec_ctx *ctx,
+ u32 event);
#endif
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index 076d00d..6db0aa3 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -58,6 +58,7 @@
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
#include "../utils/vdec_v4l2_buffer_ops.h"
+#include <media/v4l2-mem2mem.h>
#define MIX_STREAM_SUPPORT
@@ -291,6 +292,9 @@ struct BUF_s {
unsigned int free_start_adr;
ulong v4l_ref_buf_addr;
+ ulong header_addr;
+ u32 header_size;
+ u32 luma_size;
} /*BUF_t */;
struct MVBUF_s {
@@ -577,6 +581,8 @@ struct PIC_BUFFER_CONFIG_s {
int max_mv;
int min_mv;
int avg_mv;
+
+ bool vframe_bound;
} PIC_BUFFER_CONFIG;
enum BITSTREAM_PROFILE {
@@ -1183,6 +1189,8 @@ struct VP9Decoder_s {
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
u32 mem_map_mode;
+ u32 dynamic_buf_num_margin;
+ struct vframe_s vframe_dummy;
};
static int vp9_print(struct VP9Decoder_s *pbi,
@@ -1221,8 +1229,8 @@ static int is_oversize(int w, int h)
return false;
}
-static int config_pic(struct VP9Decoder_s *pbi,
- struct PIC_BUFFER_CONFIG_s *pic_config);
+static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
+ struct PIC_BUFFER_CONFIG_s *pic);
static void resize_context_buffers(struct VP9Decoder_s *pbi,
struct VP9_Common_s *cm, int width, int height)
@@ -1235,26 +1243,6 @@ static void resize_context_buffers(struct VP9Decoder_s *pbi,
}
pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width,
cm->height, width, height);
-
- if (pbi->is_used_v4l) {
- struct PIC_BUFFER_CONFIG_s *pic = &cm->cur_frame->buf;
-
- /* resolution change happend need to reconfig buffs if true. */
- if (pic->y_crop_width != width || pic->y_crop_height != height) {
- int i;
- for (i = 0; i < pbi->used_buf_num; i++) {
- pic = &cm->buffer_pool->frame_bufs[i].buf;
- pic->y_crop_width = width;
- pic->y_crop_height = height;
- if (!config_pic(pbi, pic))
- set_canvas(pbi, pic);
- else
- vp9_print(pbi, 0,
- "v4l: reconfig buff fail.\n");
- }
- }
- }
-
cm->width = width;
cm->height = height;
}
@@ -1754,6 +1742,13 @@ static int alloc_mv_buf(struct VP9Decoder_s *pbi,
int i, int size)
{
int ret = 0;
+
+ if (pbi->m_mv_BUF[i].start_adr &&
+ size > pbi->m_mv_BUF[i].size) {
+ dealloc_mv_bufs(pbi);
+ } else if (pbi->m_mv_BUF[i].start_adr)
+ return 0;
+
if (decoder_bmmu_box_alloc_buf_phy
(pbi->bmmu_box,
MV_BUFFER_IDX(i), size,
@@ -2148,7 +2143,6 @@ static int get_free_fb(struct VP9Decoder_s *pbi)
{
struct VP9_Common_s *const cm = &pbi->common;
struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
- struct PIC_BUFFER_CONFIG_s *pic = NULL;
int i;
unsigned long flags;
@@ -2162,21 +2156,11 @@ static int get_free_fb(struct VP9Decoder_s *pbi)
}
}
for (i = 0; i < pbi->used_buf_num; ++i) {
- pic = &frame_bufs[i].buf;
if ((frame_bufs[i].ref_count == 0) &&
- (pic->vf_ref == 0) && (pic->index != -1)) {
- if (pbi->is_used_v4l && !pic->cma_alloc_addr) {
- pic->y_crop_width = pbi->frame_width;
- pic->y_crop_height = pbi->frame_height;
- if (!config_pic(pbi, pic)) {
- set_canvas(pbi, pic);
- init_pic_list_hw(pbi);
- } else
- i = pbi->used_buf_num;
- }
-
+ (frame_bufs[i].buf.vf_ref == 0) &&
+ (frame_bufs[i].buf.index != -1)
+ )
break;
- }
}
if (i != pbi->used_buf_num) {
frame_bufs[i].ref_count = 1;
@@ -2192,6 +2176,58 @@ static int get_free_fb(struct VP9Decoder_s *pbi)
return i;
}
+static int v4l_get_free_fb(struct VP9Decoder_s *pbi)
+{
+ struct VP9_Common_s *const cm = &pbi->common;
+ struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+ struct aml_vcodec_ctx * v4l = pbi->v4l2_ctx;
+ struct v4l_buff_pool *pool = &v4l->cap_pool;
+ struct PIC_BUFFER_CONFIG_s *pic = NULL;
+ int i, idx = INVALID_IDX;
+ ulong flags;
+
+ lock_buffer_pool(cm->buffer_pool, flags);
+
+ for (i = 0; i < pool->in; ++i) {
+ u32 state = (pool->seq[i] >> 16);
+ u32 index = (pool->seq[i] & 0xffff);
+
+ switch (state) {
+ case V4L_CAP_BUFF_IN_DEC:
+ pic = &frame_bufs[i].buf;
+ if ((frame_bufs[i].ref_count == 0) &&
+ (pic->vf_ref == 0) &&
+ (pic->index != -1) &&
+ pic->cma_alloc_addr) {
+ idx = i;
+ }
+ break;
+ case V4L_CAP_BUFF_IN_M2M:
+ pic = &frame_bufs[index].buf;
+ pic->y_crop_width = pbi->frame_width;
+ pic->y_crop_height = pbi->frame_height;
+ if (!v4l_alloc_and_config_pic(pbi, pic)) {
+ set_canvas(pbi, pic);
+ init_pic_list_hw(pbi);
+ idx = index;
+ }
+ break;
+ default:
+ pr_err("v4l buffer state err %d.\n", state);
+ break;
+ }
+
+ if (idx != INVALID_IDX) {
+ frame_bufs[idx].ref_count = 1;
+ break;
+ }
+ }
+
+ unlock_buffer_pool(cm->buffer_pool, flags);
+
+ return idx;
+}
+
static int get_free_buf_count(struct VP9Decoder_s *pbi)
{
struct VP9_Common_s *const cm = &pbi->common;
@@ -2353,7 +2389,9 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params)
if (debug & VP9_DEBUG_BUFMGR_DETAIL)
dump_pic_list(pbi);
#endif
- cm->new_fb_idx = get_free_fb(pbi);
+ cm->new_fb_idx = pbi->is_used_v4l ?
+ v4l_get_free_fb(pbi) :
+ get_free_fb(pbi);
if (cm->new_fb_idx == INVALID_IDX) {
pr_info("get_free_fb error\r\n");
return -1;
@@ -4648,12 +4686,64 @@ void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc,
}
+static bool v4l_is_there_vframe_bound(struct VP9Decoder_s *pbi)
+{
+ int i;
+ struct VP9_Common_s *const cm = &pbi->common;
+ struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
+
+ for (i = 0; i < pbi->used_buf_num; ++i) {
+ if (frame_bufs[i].buf.vframe_bound)
+ return true;
+ }
+
+ return false;
+}
+
+static void v4l_mmu_buffer_release(struct VP9Decoder_s *pbi)
+{
+ struct VP9_Common_s *const cm = &pbi->common;
+ struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
+ int i;
+
+ /* release workspace */
+ if (pbi->bmmu_box)
+ decoder_bmmu_box_free_idx(pbi->bmmu_box,
+ WORK_SPACE_BUF_ID);
+ /*
+ * it's only when vframe get back to driver, right now we can be sure
+ * that vframe and fd are related. if the playback exits, the capture
+ * requires the upper app to release when the fd is closed, and others
+ * buffers drivers are released by driver.
+ */
+ for (i = 0; i < pbi->used_buf_num; ++i) {
+ if (!frame_bufs[i].buf.vframe_bound) {
+ if (pbi->bmmu_box)
+ decoder_bmmu_box_free_idx(pbi->bmmu_box,
+ HEADER_BUFFER_IDX(i));
+ if (pbi->mmu_box)
+ decoder_mmu_box_free_idx(pbi->mmu_box, i);
+
+ vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
+ "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
+ __func__, i, pbi->bmmu_box, pbi->mmu_box);
+ }
+ }
+}
static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
{
#ifndef MV_USE_FIXED_BUF
dealloc_mv_bufs(pbi);
#endif
+ if (pbi->is_used_v4l &&
+ v4l_is_there_vframe_bound(pbi)) {
+ if (get_double_write_mode(pbi) != 0x10) {
+ v4l_mmu_buffer_release(pbi);
+ return;
+ }
+ }
+
if (pbi->mmu_box)
decoder_mmu_box_free(pbi->mmu_box);
pbi->mmu_box = NULL;
@@ -4663,14 +4753,118 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
pbi->bmmu_box = NULL;
}
+static int calc_luc_quantity(u32 w, u32 h)
+{
+ int lcu_size = 64; /*fixed 64*/
+ int pic_width_64 = (w + 63) & (~0x3f);
+ int pic_height_32 = (h + 31) & (~0x1f);
+ int pic_width_lcu = (pic_width_64 % lcu_size) ?
+ pic_width_64 / lcu_size + 1 : pic_width_64 / lcu_size;
+ int pic_height_lcu = (pic_height_32 % lcu_size) ?
+ pic_height_32 / lcu_size + 1 : pic_height_32 / lcu_size;
+
+ return pic_width_lcu * pic_height_lcu;
+}
+
+static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
+ struct PIC_BUFFER_CONFIG_s *pic)
+{
+ int ret = -1;
+ int i = pic->index;
+ int dw_mode = get_double_write_mode_init(pbi);
+ int lcu_total = calc_luc_quantity(pbi->frame_width, pbi->frame_height);
+#ifdef MV_USE_FIXED_BUF
+ u32 mpred_mv_end = pbi->work_space_buf->mpred_mv.buf_start +
+ pbi->work_space_buf->mpred_mv.buf_size;
+#endif
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb);
+ if (ret < 0) {
+ vp9_print(pbi, 0, "[%d] VP9 get buffer fail.\n",
+ ((struct aml_vcodec_ctx *) (pbi->v4l2_ctx))->id);
+ return ret;
+ }
+
+ if (pbi->mmu_enable) {
+ pbi->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr(
+ pbi->bmmu_box, HEADER_BUFFER_IDX(i));
+ if (debug & VP9_DEBUG_BUFMGR_MORE) {
+ pr_info("MMU header_adr %d: %ld\n",
+ i, pbi->m_BUF[i].header_addr);
+ }
+ }
+
+#ifdef MV_USE_FIXED_BUF
+ if ((pbi->work_space_buf->mpred_mv.buf_start +
+ (((i + 1) * lcu_total) * MV_MEM_UNIT))
+ <= mpred_mv_end) {
+#endif
+ pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
+ pic->cma_alloc_addr = fb->m.mem[0].addr;
+ if (fb->num_planes == 1) {
+ pbi->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ pbi->m_BUF[i].size = fb->m.mem[0].size;
+ pbi->m_BUF[i].luma_size = fb->m.mem[0].offset;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ } else if (fb->num_planes == 2) {
+ pbi->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ pbi->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
+ pbi->m_BUF[i].luma_size = fb->m.mem[0].size;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ fb->m.mem[1].bytes_used = fb->m.mem[1].size;
+ }
+
+ /* config frame buffer */
+ if (pbi->mmu_enable)
+ pic->header_adr = pbi->m_BUF[i].header_addr;
+
+ pic->BUF_index = i;
+ pic->lcu_total = lcu_total;
+ pic->mc_canvas_y = pic->index;
+ pic->mc_canvas_u_v = pic->index;
+
+ if (dw_mode & 0x10) {
+ pic->dw_y_adr = pbi->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size;
+ pic->mc_canvas_y = (pic->index << 1);
+ pic->mc_canvas_u_v = (pic->index << 1) + 1;
+ } else if (dw_mode) {
+ pic->dw_y_adr = pbi->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size;
+ }
+
+#ifdef MV_USE_FIXED_BUF
+ pic->mpred_mv_wr_start_addr =
+ pbi->work_space_buf->mpred_mv.buf_start +
+ ((pic->index * lcu_total) * MV_MEM_UNIT);
+#endif
+ if (debug) {
+ pr_info("%s index %d BUF_index %d ",
+ __func__, pic->index,
+ pic->BUF_index);
+ pr_info("comp_body_size %x comp_buf_size %x ",
+ pic->comp_body_size,
+ pic->buf_size);
+ pr_info("mpred_mv_wr_start_adr %ld\n",
+ pic->mpred_mv_wr_start_addr);
+ pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n",
+ pic->dw_y_adr,
+ pic->dw_u_v_adr);
+ }
+#ifdef MV_USE_FIXED_BUF
+ }
+#endif
+ return ret;
+}
static int config_pic(struct VP9Decoder_s *pbi,
struct PIC_BUFFER_CONFIG_s *pic_config)
{
int ret = -1;
int i;
- int pic_width = pbi->is_used_v4l ? pbi->frame_width : pbi->init_pic_w;
- int pic_height = pbi->is_used_v4l ? pbi->frame_height : pbi->init_pic_h;
+ int pic_width = pbi->init_pic_w;
+ int pic_height = pbi->init_pic_h;
int lcu_size = 64; /*fixed 64*/
int pic_width_64 = (pic_width + 63) & (~0x3f);
int pic_height_32 = (pic_height + 31) & (~0x1f);
@@ -4698,9 +4892,6 @@ static int config_pic(struct VP9Decoder_s *pbi,
int mc_buffer_size_u_v = 0;
int mc_buffer_size_u_v_h = 0;
int dw_mode = get_double_write_mode_init(pbi);
- int pic_width_align = 0;
- int pic_height_align = 0;
- struct vdec_v4l2_buffer *fb = NULL;
pbi->lcu_total = lcu_total;
@@ -4724,11 +4915,6 @@ static int config_pic(struct VP9Decoder_s *pbi,
/*64k alignment*/
buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
buf_size = ((buf_size + 0xffff) >> 16) << 16;
-
- if (pbi->is_used_v4l) {
- pic_width_align = ALIGN(pic_width_dw, 32);
- pic_height_align = ALIGN(pic_height_dw, 32);
- }
}
if (mc_buffer_size & 0xffff) /*64k alignment*/
@@ -4754,35 +4940,17 @@ static int config_pic(struct VP9Decoder_s *pbi,
) {
#endif
if (buf_size > 0) {
- if (pbi->is_used_v4l) {
- ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb);
- if (ret) {
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] get fb fail.\n",
- ((struct aml_vcodec_ctx *)
- (pbi->v4l2_ctx))->id);
- return ret;
- }
-
- pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
- pic_config->cma_alloc_addr = fb->m.mem[0].addr;
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l ref buf addr: 0x%x\n",
- ((struct aml_vcodec_ctx *)
- (pbi->v4l2_ctx))->id, __func__, fb);
- } else {
- ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
- VF_BUFFER_IDX(i),
- buf_size, DRIVER_NAME,
- &pic_config->cma_alloc_addr);
- if (ret < 0) {
- pr_info(
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return ret;
- }
+ ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
+ VF_BUFFER_IDX(i),
+ buf_size, DRIVER_NAME,
+ &pic_config->cma_alloc_addr);
+ if (ret < 0) {
+ pr_info(
+ "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
+ VF_BUFFER_IDX(i),
+ buf_size
+ );
+ return ret;
}
if (pic_config->cma_alloc_addr)
@@ -4808,27 +4976,9 @@ static int config_pic(struct VP9Decoder_s *pbi,
pic_config->mc_canvas_y = pic_config->index;
pic_config->mc_canvas_u_v = pic_config->index;
if (dw_mode & 0x10) {
- if (pbi->is_used_v4l) {
- if (fb->num_planes == 1) {
- fb->m.mem[0].bytes_used =
- pic_width_align * pic_height_align;
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- fb->m.mem[0].bytes_used;
- } else if (fb->num_planes == 2) {
- fb->m.mem[0].bytes_used =
- pic_width_align * pic_height_align;
- fb->m.mem[1].bytes_used =
- fb->m.mem[1].size;
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- fb->m.mem[0].bytes_used;
- }
- } else {
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
- }
+ pic_config->dw_y_adr = y_adr;
+ pic_config->dw_u_v_adr = y_adr +
+ ((mc_buffer_size_u_v_h << 16) << 1);
pic_config->mc_canvas_y =
(pic_config->index << 1);
@@ -6401,8 +6551,6 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
pbi->vvp9_amstream_dec_info.height :
pbi->work_space_buf->max_height));
- pbi->mem_map_mode = mem_map_mode ? mem_map_mode : 0;
-
/* video is not support unaligned with 64 in tl1
** vdec canvas mode will be linear when dump yuv is set
*/
@@ -6427,8 +6575,12 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
#endif
if (pbi->save_buffer_mode)
pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF;
- else
- pbi->used_buf_num = max_buf_num;
+ else {
+ if (pbi->is_used_v4l)
+ pbi->used_buf_num = 5 + pbi->dynamic_buf_num_margin;
+ else
+ pbi->used_buf_num = max_buf_num;
+ }
if (pbi->used_buf_num > MAX_BUF_NUM)
pbi->used_buf_num = MAX_BUF_NUM;
@@ -6566,10 +6718,10 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_config_ex(pic_config->y_canvas_index,
pic_config->dw_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
canvas_config_ex(pic_config->uv_canvas_index,
pic_config->dw_u_v_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
#ifdef MULTI_INSTANCE_SUPPORT
pic_config->canvas_config[0].phy_addr =
@@ -6580,7 +6732,7 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_h;
pic_config->canvas_config[0].block_mode =
blkmode;
- pic_config->canvas_config[0].endian = 7;
+ pic_config->canvas_config[0].endian = pbi->is_used_v4l ? 0 : 7;
pic_config->canvas_config[1].phy_addr =
pic_config->dw_u_v_adr;
@@ -6590,7 +6742,7 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_h;
pic_config->canvas_config[1].block_mode =
blkmode;
- pic_config->canvas_config[1].endian = 7;
+ pic_config->canvas_config[1].endian = pbi->is_used_v4l ? 0 : 7;
#endif
}
}
@@ -6609,6 +6761,16 @@ static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf)
ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX);
vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+ if (pbi->is_used_v4l && pbi->vf_dp.present_flag) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = vf->signal_type;
+ hdr.color_parms = pbi->vf_dp;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
}
static int vvp9_vf_states(struct vframe_states *states, void *op_arg)
@@ -6659,6 +6821,7 @@ static struct vframe_s *vvp9_vf_get(void *op_arg)
uint8_t index = vf->index & 0xff;
if (index < pbi->used_buf_num ||
(vf->type & VIDTYPE_V4L_EOS)) {
+ vf->index_disp = pbi->vf_get_count;
pbi->vf_get_count++;
if (debug & VP9_DEBUG_BUFMGR)
pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n",
@@ -6684,6 +6847,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg)
struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)op_arg;
uint8_t index = vf->index & 0xff;
+ if (vf == (&pbi->vframe_dummy))
+ return;
+
kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf);
pbi->vf_put_count++;
if (index < pbi->used_buf_num) {
@@ -6695,6 +6861,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg)
if (pool->frame_bufs[index].buf.vf_ref > 0)
pool->frame_bufs[index].buf.vf_ref--;
+ if (pbi->is_used_v4l)
+ pool->frame_bufs[index].buf.vframe_bound = true;
+
if (pbi->wait_buf)
WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
@@ -6864,16 +7033,11 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
vf->v4l_mem_handle
= pbi->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr;
if (pbi->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
+ vf->mm_box.bmmu_box = pbi->bmmu_box;
+ vf->mm_box.bmmu_idx = HEADER_BUFFER_IDX(pic_config->BUF_index);
+ vf->mm_box.mmu_box = pbi->mmu_box;
+ vf->mm_box.mmu_idx = pic_config->index;
}
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%lx\n",
- ((struct aml_vcodec_ctx *)(pbi->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
#ifdef MULTI_INSTANCE_SUPPORT
@@ -7126,26 +7290,31 @@ static int notify_v4l_eos(struct vdec_s *vdec)
{
struct VP9Decoder_s *hw = (struct VP9Decoder_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
- struct vframe_s *vf = NULL;
+ struct vframe_s *vf = &hw->vframe_dummy;
struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
- if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
- vp9_print(hw, 0,
- "%s fatal error, no available buffer slot.\n",
- __func__);
- return -1;
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = v4l_get_free_fb(hw))) {
+ if (time_after(jiffies, expires) ||
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+ break;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
- return -1;
+ if (index == INVALID_IDX) {
+ if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
+ return -1;
+ }
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb :
+ hw->m_BUF[index].v4l_ref_buf_addr;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
vf_notify_receiver(vdec->vf_provider_name,
@@ -8160,15 +8329,15 @@ 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_pic_infos info;
+ struct aml_vdec_ps_infos ps;
- info.visible_width = pbi->frame_width;
- info.visible_height = pbi->frame_height;
- info.coded_width = ALIGN(pbi->frame_width, 32);
- info.coded_height = ALIGN(pbi->frame_height, 32);
- info.dpb_size = pbi->used_buf_num;
+ 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_pic_infos(ctx, &info);
+ vdec_v4l_set_ps_infos(ctx, &ps);
}
}
@@ -9648,8 +9817,13 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (ctx->param_sets_from_ucode &&
!ctx->v4l_codec_ready &&
- pbi->v4l_params_parsed)
+ pbi->v4l_params_parsed) {
ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready) {
+ if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+ run_ready_min_buf_num)
+ ret = 0;
+ }
}
if (ret)
@@ -9695,6 +9869,7 @@ static void run_front(struct vdec_s *vdec)
vdec_schedule_work(&pbi->work);
return;
}
+
input_empty[pbi->index] = 0;
pbi->dec_result = DEC_RESULT_NONE;
pbi->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
@@ -9965,6 +10140,8 @@ static void init_frame_bufs(struct VP9Decoder_s *pbi)
frame_bufs[i].ref_count = 0;
frame_bufs[i].buf.vf_ref = 0;
frame_bufs[i].buf.decode_idx = 0;
+ frame_bufs[i].buf.cma_alloc_addr = 0;
+ frame_bufs[i].buf.index = i;
}
if (vdec->parallel_dec == 1) {
@@ -9981,7 +10158,6 @@ static void init_frame_bufs(struct VP9Decoder_s *pbi)
static void reset(struct vdec_s *vdec)
{
-
struct VP9Decoder_s *pbi =
(struct VP9Decoder_s *)vdec->private;
@@ -9997,7 +10173,6 @@ static void reset(struct vdec_s *vdec)
}
pbi->dec_result = DEC_RESULT_NONE;
reset_process_time(pbi);
- dealloc_mv_bufs(pbi);
vp9_local_uninit(pbi);
if (vvp9_local_init(pbi) < 0)
vp9_print(pbi, 0, "%s local_init failed \r\n", __func__);
@@ -10286,6 +10461,21 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->max_pic_h = vp9_buf_height;
vp9_print(pbi, 0, "use buf resolution\n");
}
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ pbi->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ pbi->dynamic_buf_num_margin = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_canvas_mem_mode",
+ &config_val) == 0)
+ pbi->mem_map_mode = config_val;
#endif
if (get_config_int(pdata->config, "HDRStaticInfo",
&vf_dp.present_flag) == 0
@@ -10333,6 +10523,11 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->vvp9_amstream_dec_info.rate = 30;*/
pbi->double_write_mode = double_write_mode;
}
+
+ if (!pbi->is_used_v4l) {
+ pbi->mem_map_mode = mem_map_mode;
+ }
+
if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) {
pr_err("over size: %dx%d, probe failed\n",
pbi->max_pic_w, pbi->max_pic_h);
@@ -10349,18 +10544,6 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->vvp9_amstream_dec_info.rate = 30;
}
pbi->low_latency_flag = 1;
- pbi->is_used_v4l = (((unsigned long)
- pbi->vvp9_amstream_dec_info.param & 0x80) >> 7);
- if (pbi->is_used_v4l) {
- pbi->mmu_enable = (((unsigned long)
- pbi->vvp9_amstream_dec_info.param & 0x100) >> 8);
- if (!pbi->mmu_enable)
- pbi->double_write_mode = 0x10;
-
- pbi->mmu_enable = 1;
- pbi->max_pic_w = 4096;
- pbi->max_pic_h = 2304;
- }
vp9_print(pbi, 0,
"no_head %d low_latency %d\n",
diff --git a/drivers/frame_sink/encoder/h264/encoder.c b/drivers/frame_sink/encoder/h264/encoder.c
index 7b83dd2..294c600 100644
--- a/drivers/frame_sink/encoder/h264/encoder.c
+++ b/drivers/frame_sink/encoder/h264/encoder.c
@@ -1067,6 +1067,8 @@ static int scale_frame(struct encode_wq_s *wq,
src_left = request->crop_left;
src_width = request->src_w - src_left - request->crop_right;
src_height = request->src_h - src_top - request->crop_bottom;
+ pr_err("request->fmt=%d, %d %d, canvas=%d\n", request->fmt, FMT_NV21, FMT_BGR888, canvas);
+
if (canvas) {
if ((request->fmt == FMT_NV21)
|| (request->fmt == FMT_NV12)) {
@@ -1075,6 +1077,9 @@ static int scale_frame(struct encode_wq_s *wq,
} else if (request->fmt == FMT_BGR888) {
src_canvas = src_addr & 0xffffff;
input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d
+ } else if (request->fmt == FMT_RGBA8888) {
+ src_canvas = src_addr & 0xffffff;
+ input_format = GE2D_FORMAT_S32_ABGR;
} else {
src_canvas = src_addr & 0xffffff;
input_format = GE2D_FORMAT_M24_YUV420;
@@ -1101,6 +1106,7 @@ static int scale_frame(struct encode_wq_s *wq,
} else if (request->fmt == FMT_BGR888) {
src_canvas_w =
((request->src_w + 31) >> 5) << 5;
+
canvas_config(ENC_CANVAS_OFFSET + 9,
src_addr,
src_canvas_w * 3, src_h,
@@ -1108,6 +1114,18 @@ static int scale_frame(struct encode_wq_s *wq,
CANVAS_BLKMODE_LINEAR);
src_canvas = ENC_CANVAS_OFFSET + 9;
input_format = GE2D_FORMAT_S24_RGB; //Opposite color after ge2d
+ } else if (request->fmt == FMT_RGBA8888) {
+ src_canvas_w =
+ ((request->src_w + 31) >> 5) << 5;
+ canvas_config(
+ ENC_CANVAS_OFFSET + 9,
+ src_addr,
+ src_canvas_w * 4,
+ src_h,
+ CANVAS_ADDR_NOWRAP,
+ CANVAS_BLKMODE_LINEAR);
+ src_canvas = ENC_CANVAS_OFFSET + 9;
+ input_format = GE2D_FORMAT_S32_ABGR; //Opposite color after ge2d
} else {
src_canvas_w =
((request->src_w + 63) >> 6) << 6;
@@ -1133,17 +1151,22 @@ static int scale_frame(struct encode_wq_s *wq,
input_format = GE2D_FORMAT_M24_YUV420;
}
}
+
dst_canvas_w = ((dst_w + 31) >> 5) << 5;
+
canvas_config(ENC_CANVAS_OFFSET + 6,
wq->mem.scaler_buff_start_addr,
dst_canvas_w, dst_h,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+
canvas_config(ENC_CANVAS_OFFSET + 7,
wq->mem.scaler_buff_start_addr + dst_canvas_w * dst_h,
dst_canvas_w, dst_h / 2,
CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+
dst_canvas = ((ENC_CANVAS_OFFSET + 7) << 8) |
(ENC_CANVAS_OFFSET + 6);
+
ge2d_config->alu_const_color = 0;
ge2d_config->bitmask_en = 0;
ge2d_config->src1_gb_alpha = 0;
@@ -1152,18 +1175,20 @@ static int scale_frame(struct encode_wq_s *wq,
canvas_read((src_canvas >> 8) & 0xff, &cs1);
canvas_read((src_canvas >> 16) & 0xff, &cs2);
ge2d_config->src_planes[0].addr = cs0.addr;
- ge2d_config->src_planes[0].w = cs0.width;
- ge2d_config->src_planes[0].h = cs0.height;
+ ge2d_config->src_planes[0].w = dst_w * 4;//cs0.width;
+ ge2d_config->src_planes[0].h = dst_h;//cs0.height;
ge2d_config->src_planes[1].addr = cs1.addr;
ge2d_config->src_planes[1].w = cs1.width;
ge2d_config->src_planes[1].h = cs1.height;
ge2d_config->src_planes[2].addr = cs2.addr;
ge2d_config->src_planes[2].w = cs2.width;
ge2d_config->src_planes[2].h = cs2.height;
+
canvas_read(dst_canvas & 0xff, &cd);
+
ge2d_config->dst_planes[0].addr = cd.addr;
- ge2d_config->dst_planes[0].w = cd.width;
- ge2d_config->dst_planes[0].h = cd.height;
+ ge2d_config->dst_planes[0].w = dst_w * 4;//cd.width;
+ ge2d_config->dst_planes[0].h = dst_h;//cd.height;
ge2d_config->src_key.key_enable = 0;
ge2d_config->src_key.key_mask = 0;
ge2d_config->src_key.key_mode = 0;
@@ -1177,13 +1202,18 @@ static int scale_frame(struct encode_wq_s *wq,
ge2d_config->src_para.color = 0xffffffff;
ge2d_config->src_para.top = 0;
ge2d_config->src_para.left = 0;
- ge2d_config->src_para.width = request->src_w;
- ge2d_config->src_para.height = request->src_h;
+ ge2d_config->src_para.width = dst_w;//request->src_w;
+ ge2d_config->src_para.height = dst_h;//request->src_h;
ge2d_config->src2_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.canvas_index = dst_canvas;
ge2d_config->dst_para.mem_type = CANVAS_TYPE_INVALID;
ge2d_config->dst_para.format =
GE2D_FORMAT_M24_NV21 | GE2D_LITTLE_ENDIAN;
+
+ if (wq->pic.encoder_width >= 1280 && wq->pic.encoder_height >= 720) {
+ ge2d_config->dst_para.format |= GE2D_FORMAT_BT_STANDARD;
+ }
+
ge2d_config->dst_para.fill_color_en = 0;
ge2d_config->dst_para.fill_mode = 0;
ge2d_config->dst_para.x_rev = 0;
@@ -1196,6 +1226,7 @@ static int scale_frame(struct encode_wq_s *wq,
ge2d_config->dst_para.x_rev = 0;
ge2d_config->dst_para.y_rev = 0;
+
if (ge2d_context_config_ex(context, ge2d_config) < 0) {
pr_err("++ge2d configing error.\n");
return -1;
@@ -1225,6 +1256,7 @@ static s32 set_input_format(struct encode_wq_s *wq,
picsize_x = ((wq->pic.encoder_width + 15) >> 4) << 4;
picsize_y = ((wq->pic.encoder_height + 15) >> 4) << 4;
oformat = 0;
+
if ((request->type == LOCAL_BUFF)
|| (request->type == PHYSICAL_BUFF)
|| (request->type == DMA_BUFF)) {
@@ -2670,6 +2702,19 @@ static s32 convert_request(struct encode_wq_s *wq, u32 *cmd_info)
wq->request.src_w = cmd_info[13];
wq->request.src_h = cmd_info[14];
wq->request.scale_enable = cmd_info[15];
+
+ enc_pr(LOG_INFO, "hwenc: wq->pic.encoder_width %d, ",
+ wq->pic.encoder_width);
+ enc_pr(LOG_INFO, "wq->pic.encoder_height:%d, request fmt=%d\n",
+ wq->pic.encoder_height, wq->request.fmt);
+
+ if (wq->pic.encoder_width >= 1280 && wq->pic.encoder_height >= 720 && wq->request.fmt == FMT_RGBA8888) {
+ wq->request.scale_enable = 1;
+ wq->request.src_w = wq->pic.encoder_width;
+ wq->request.src_h = wq->pic.encoder_height;
+ pr_err("hwenc: force wq->request.scale_enable=%d\n", wq->request.scale_enable);
+ }
+
wq->request.nr_mode =
(nr_mode > 0) ? nr_mode : cmd_info[16];
if (cmd == ENCODER_IDR)
@@ -3216,6 +3261,7 @@ static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg)
wq->mem.bufspec.max_height, (void *)wq);
return -1;
}
+ pr_err("hwenc: AMVENC_AVC_IOC_CONFIG_INIT: w:%d, h:%d\n", wq->pic.encoder_width, wq->pic.encoder_height);
wq->pic.encoder_width = addr_info[2];
wq->pic.encoder_height = addr_info[3];
if (wq->pic.encoder_width *
diff --git a/drivers/stream_input/parser/hw_demux/aml_dmx.c b/drivers/stream_input/parser/hw_demux/aml_dmx.c
index 286b922..52334da 100644
--- a/drivers/stream_input/parser/hw_demux/aml_dmx.c
+++ b/drivers/stream_input/parser/hw_demux/aml_dmx.c
@@ -129,6 +129,9 @@ module_param_array(debug_dmx##_dmx##_chanpids, short, &npids, 0444)
#define CIPLUS_OUTPUT_AUTO 8
static int ciplus_out_sel = CIPLUS_OUTPUT_AUTO;
static int ciplus_out_auto_mode = 1;
+static u32 ciplus = 0;
+#define CIPLUS_OUT_SEL 28
+#define CIPLUS_IN_SEL 26
MOD_PARAM_DECLARE_CHANPIDS(0);
MOD_PARAM_DECLARE_CHANPIDS(1);
@@ -1615,7 +1618,6 @@ static void stb_enable(struct aml_dvb *dvb)
dec_clk_en = 0;
break;
}
-
switch (dvb->tso_source) {
case AM_TS_SRC_DMX0:
tso_src = dvb->dmx[0].source;
@@ -1690,8 +1692,9 @@ static void stb_enable(struct aml_dvb *dvb)
(en_des << ENABLE_DES_PL) |
(dec_clk_en << ENABLE_DES_PL_CLK) |
(invert0 << INVERT_S2P0_FEC_CLK) |
- (fec_s0 << S2P0_FEC_SERIAL_SEL));
-
+ (fec_s0 << S2P0_FEC_SERIAL_SEL)|
+ (ciplus));
+ ciplus = 0;
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TL1) {
invert2 = dvb->s2p[2].invert;
@@ -1761,6 +1764,25 @@ int dsc_set_pid(struct aml_dsc_channel *ch, int pid)
return 0;
}
+int dsc_get_pid(struct aml_dsc_channel *ch, int *pid)
+{
+ struct aml_dsc *dsc = ch->dsc;
+ int is_dsc2 = (dsc->id == 1) ? 1 : 0;
+ u32 data;
+
+ WRITE_MPEG_REG(TS_PL_PID_INDEX,
+ ((ch->id & 0x0f) >> 1)+(is_dsc2 ? 4 : 0));
+ data = READ_MPEG_REG(TS_PL_PID_DATA);
+ if (ch->id & 1) {
+ *pid = data & 0x1fff;
+ } else {
+ *pid = (data >> 16) & 0x1fff;
+ }
+
+ /*pr_dbg("%s,get DSC %d ch %d PID %d\n", __FUNCTION__,dsc->id, ch->id, *pid);*/
+ return 0;
+}
+
int dsc_set_key(struct aml_dsc_channel *ch, int flags, enum ca_cw_type type,
u8 *key)
{
@@ -1931,8 +1953,6 @@ static int dsc_set_csa_key(struct aml_dsc_channel *ch, int flags,
#define ENABLE_DEC_PL 7
#define ENABLE_DES_PL_CLK 15
-#define CIPLUS_OUT_SEL 28
-#define CIPLUS_IN_SEL 26
#define KEY_WR_AES_IV_B 5
#define KEY_WR_AES_IV_A 4
@@ -3273,9 +3293,12 @@ static u32 dmx_get_chan_target(struct aml_dmx *dmx, int cid)
case DMX_PES_PCR:
type = SCR_ONLY_PACKET;
break;
- default:
+ case DMX_PES_AUDIO3:
type = OTHER_PES_PACKET;
break;
+ default:
+ type = BYPASS_PACKET;
+ break;
}
}
@@ -3726,8 +3749,22 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq)
if (reset_irq)
del_timer_sync(&dvb->watchdog_timer);
#endif
+ /*RESET_TOP will clear the dsc pid , save all dsc pid that setting in TA*/
+ for (id = 0; id < DSC_DEV_COUNT; id++) {
+ struct aml_dsc *dsc = &dvb->dsc[id];
+ int n;
- WRITE_MPEG_REG(RESET1_REGISTER, RESET_DEMUXSTB);
+ for (n = 0; n < DSC_COUNT; n++) {
+ struct aml_dsc_channel *ch = &dsc->channel[n];
+ /*if(ch->used)*/
+ {
+ ch->id = n;
+ dsc_get_pid(ch,&ch->pid);
+ }
+ }
+ }
+ /*WRITE_MPEG_REG(RESET1_REGISTER, RESET_DEMUXSTB);*/
+ WRITE_MPEG_REG(RESET3_REGISTER, RESET_DEMUX2|RESET_DEMUX1|RESET_DEMUX0|RESET_S2P1|RESET_S2P0|RESET_TOP);
for (id = 0; id < DMX_DEV_COUNT; id++) {
times = 0;
@@ -3736,6 +3773,11 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq)
break;
}
}
+ {
+ u32 data;
+ data = READ_MPEG_REG(STB_TOP_CONFIG);
+ ciplus = 0xF8000000 & data;
+ }
WRITE_MPEG_REG(STB_TOP_CONFIG, 0);
WRITE_MPEG_REG(STB_S2P2_CONFIG, 0);
@@ -3859,13 +3901,20 @@ void dmx_reset_hw_ex(struct aml_dvb *dvb, int reset_irq)
int n;
for (n = 0; n < DSC_COUNT; n++) {
+ int flag = 0;
struct aml_dsc_channel *ch = &dsc->channel[n];
- /*if(ch->used) */
+ /*if(ch->used)*/
{
- ch->id = n;
ch->work_mode = -1;
+ //if ta setting pid, used will 0
+ if (ch->pid != 0x1fff && !ch->used) {
+ flag = 1;
+ ch->used = 1;
+ }
dsc_set_pid(ch, ch->pid);
- dsc_set_keys(ch);
+ if (flag)
+ ch->used = 0;
+ //dsc_set_keys(ch);
}
}
}
@@ -3917,6 +3966,11 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx,
}
/*WRITE_MPEG_REG(STB_TOP_CONFIG, 0); */
+ {
+ u32 data;
+ data = READ_MPEG_REG(STB_TOP_CONFIG);
+ ciplus = 0xF8000000 & data;
+ }
{
u32 version, data;
@@ -4045,11 +4099,21 @@ void dmx_reset_dmx_hw_ex_unlock(struct aml_dvb *dvb, struct aml_dmx *dmx,
int n;
for (n = 0; n < DSC_COUNT; n++) {
+ int flag = 0;
struct aml_dsc_channel *ch = &dsc->channel[n];
- /*if(ch->used) */
+ /*if(ch->used)*/ {
+ ch->id = n;
ch->work_mode = -1;
+ dsc_get_pid(ch,&ch->pid);
+ if (ch->pid != 0x1fff && !ch->used) {
+ flag = 1;
+ ch->used = 1;
+ }
dsc_set_pid(ch, ch->pid);
- dsc_set_keys(ch);
+ if (flag)
+ ch->used = 0;
+ //dsc_set_keys(ch);
+ }
}
}
}
@@ -4152,6 +4216,7 @@ int dmx_alloc_chan(struct aml_dmx *dmx, int type, int pes_type, int pid)
id = 3;
break;
case DMX_PES_OTHER:
+ case DMX_PES_AUDIO3:
{
int i;
diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin
index 6ef6866..cf1c3b9 100644
--- a/firmware/video_ucode.bin
+++ b/firmware/video_ucode.bin
@@ -1,5 +1,5 @@
-*wSж!whs9+Π7"*.:k. -. ipj1 9No3y5DF_GOi8T }T{ȏ^"Ōҝ7#SKqSA<~u
-j T4sƨ({V08a>5kxtΛŸnŁأ~ۮ0_5`3@Ï04P"##LdWKCAP
+ejBe=4&8+ߘTtWGIߴ$Ym IoA1aŋEױv 
+5qa8џ3kY{s40-am2l@?BgX R,h=~H\&ɕ.Rc(vd-\\uq՟I`|TVwFAT!Hȷ୊~< W4+~JnKCAP
 @
I`
@@ -392,7 +392,7 @@ j
2  ! ,
x 3
-
+
 @
I`
=y `
@@ -845,7 +845,7 @@ j
2  ! ,
x 3
-
+
 @
I`
@@ -1237,7 +1237,7 @@ j
2  ! ,
x 3
-
+
 @
I`
@@ -1629,7 +1629,7 @@ j
2  ! ,
x 3
-
+
 @
I`
@@ -2016,7 +2016,7 @@ j
2  ! ,
x 3
-
+
 @
I`
@@ -2409,7 +2409,7 @@ j
2  ! ,
x 3
-
+

@x
Ȁ
@@ -2423,7 +2423,7 @@ H
H
@p
6 
-@
+@

%
x
@@ -2434,7 +2434,7 @@ H
H

x
-@
+@
 @
I`
x `
@@ -2923,7 +2923,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
 @
I`
x `
@@ -3411,7 +3411,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
 @
I`
x `
@@ -3899,7 +3899,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
 @
I`
x `
@@ -4387,7 +4387,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
 @
I`
x `
@@ -4875,7 +4875,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
I
v
G
@@ -4968,7 +4968,7 @@ U
T%H @ID
T%H @ID
T%H @ID
-U
+U
I@
v
G
@@ -5070,7 +5070,7 @@ U
T%H @ID
T%H @ID
T%H @ID
-U
+U
I
v
@@ -5165,7 +5165,7 @@ U
T%H @ID
T%H @ID
T%H @ID
-U
+U
I@
v
@@ -5269,14 +5269,14 @@ U
T%H @ID
T%H @ID
T%H @ID
-U
+U
-
+
x
B<
@@ -5833,7 +5833,7 @@ I
G @ @? # 
-G"@ ; # @=
+G"@ ; # @=
x
B<
@@ -6378,7 +6378,7 @@ I
G  @
-G"@ @< # =
+G"@ @< # =
x
B<
@@ -6936,7 +6936,7 @@ I
G @ @? # 
G"@ ; # @=
-gxm_h264_multi.bin
+gxm_h264_multi.bin
x
B<
@@ -7483,11 +7483,11 @@ I
G  @
-G"@ @< # =
+G"@ @< # =
-tl1_h264_multi.bin
+tl1_h264_multi.bin
x
B<
@@ -8034,7 +8034,7 @@ I
G  @
-G"@ @< # =
+G"@ @< # =
I !
`xI@ C
     @
@@ -8432,7 +8432,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 
I !
`xI@ C
     @
@@ -8830,7 +8830,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 
I !
`xI@ C
     @
@@ -9202,7 +9202,7 @@ EŇ@x
EG
ł
EŃ@
-`
+`
I !
`xI@ C
     @
@@ -9574,7 +9574,7 @@ EŇ@x
EG
ł
EŃ@
-`
+`
I !
`xI@ C
     @
@@ -9972,7 +9972,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 
I !
`iI@ C
     @
@@ -10344,7 +10344,7 @@ EŇ@x
EG
ł
EŃ@
-`
+`
I !
`xI@ C
     @
@@ -10716,7 +10716,7 @@ EŇ@x
EG
ł
EŃ@
-`
+`
I !
`iI@ C
     @
@@ -11114,7 +11114,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 
I !
`xI@ C
     @
@@ -11486,7 +11486,7 @@ EŇ@x
EG
ł
EŃ@
-`
+`
I !
`xI@ C
     @
@@ -11884,7 +11884,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 

@4x
@@ -12065,7 +12065,7 @@ n
J` 
-J` 
+J` 
@@ -12263,7 +12263,7 @@ n
J` 
-J` 
+J` 

@@ -12276,25 +12276,25 @@ n


-
+
y
o
c
HCc
-I
+I
x
*L6Lǁ Q ;LH2 
H
L `
-@@ I
+@@ I
x
 

@x  
-2
+2
( GGCG

@@ -12312,7 +12312,7 @@ x
`

X  ȃ 
-, 
+, 

q@BD HH@d
@@ -12331,13 +12331,13 @@ HA
@
" 
N" HD 2P @x ! x A! 
-
+@
` @
`
-
-
+
+
Hz o
N
@@ -12394,7 +12394,7 @@ G

GG
-B
+

@@ -12450,7 +12450,7 @@ J
x GGP ! @$ N
@
" 
-N" HD 2P @x ! x A! 
+N" HD 2P @x ! x A! 
GG
G
G`
@@ -12475,10 +12475,10 @@ I
"B @x @@ o

@
-ۆ[@ GL a~  ǀ
+ۆ[@ GL a~  ׀

-
-
+
+@e
(
! (@( hQ
@@ -12489,7 +12489,7 @@ kè
+B
*
-*
+*
! ( 銂( (
@@ -12546,11 +12546,11 @@ G

N N N

-  
-@
+  
+@
!
G
-
+
ߏN Lȃ JB
`
@@ -12559,7 +12559,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 

@@ -12572,25 +12572,25 @@ G


-
+
@y
o
c
HCc
-I
+I
x
*L6Lǁ Q ;LH2 
H
L `
-@@ I
+@@ I
x
 

@x  
-2
+2
( GGCG

@@ -12608,7 +12608,7 @@ x
`

X  ȃ 
-, 
+, 

q@BD HH@d
@@ -12627,13 +12627,13 @@ HA
@
" 
N" HD 2P @x ! x A! 
-
+@
` @
`
-
-
+
+
Hz o
N
@@ -12690,7 +12690,7 @@ G

GG
-B
+

@@ -12747,7 +12747,7 @@ J
x GGP ! @$ N
@
" 
-N" HD 2P @x ! x A! 
+N" HD 2P @x ! x A! 
GG
G
G`
@@ -12772,10 +12772,10 @@ I
"B @x @@ o

@
-ۆ[@ GL a~  ǀ
+ۆ[@ GL a~  ׀

-
-
+
+@e
(
! (@( hQ
@@ -12786,7 +12786,7 @@ kè
+B
*
-*
+*
! ( 銂( (
@@ -12843,11 +12843,11 @@ G

N N N

-  
-@
+  
+@
!
G
-
+
ߏN Lȃ JB
`
@@ -12856,7 +12856,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 

@@ -12869,25 +12869,25 @@ G


-
+
@y
o
c
HCc
-I
+I
x
*L6Lǁ Q ;LH2 
H
L `
-@@ I
+@@ I
x
 

@x  
-2
+2
( GGCG

@@ -12905,7 +12905,7 @@ x
`

X  ȃ 
-, 
+, 

q@BD HH@d
@@ -12924,13 +12924,13 @@ HA
@
" 
N" HD 2P @x ! x A! 
-
+@
` @
`
-
-
+
+
Hz o
N
@@ -12987,7 +12987,7 @@ G

GG
-B
+

@@ -13044,7 +13044,7 @@ J
x GGP ! @$ N
@
" 
-N" HD 2P @x ! x A! 
+N" HD 2P @x ! x A! 
GG
G
G`
@@ -13069,10 +13069,10 @@ I
"B @x @@ o

@
-ۆ[@ GL a~  ǀ
+ۆ[@ GL a~  ׀

-
-
+
+@e
(
! (@( hQ
@@ -13083,7 +13083,7 @@ kè
+B
*
-*
+*
! ( 銂( (
@@ -13140,11 +13140,11 @@ G

N N N

-  
-@
+  
+@
!
G
-
+
ߏN Lȃ JB
`
@@ -13153,7 +13153,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 

@@ -13166,25 +13166,25 @@ G


-
+
y
o
c
HCc
-I
+I
x
*L6Lǁ Q ;LH2 
H
L `
-@@ I
+@@ I
x
 

@x  
-2
+2
( GGCG

@@ -13202,7 +13202,7 @@ x
`

X  ȃ 
-, 
+, 

q@BD HH@d
@@ -13221,13 +13221,13 @@ HA
@
" 
N" HD 2P @x ! x A! 
-
+@
` @
`
-
-
+
+
Hz o
N
@@ -13284,7 +13284,7 @@ G

GG
-B
+

@@ -13340,7 +13340,7 @@ J
x GGP ! @$ N
@
" 
-N" HD 2P @x ! x A! 
+N" HD 2P @x ! x A! 
GG
G
G`
@@ -13365,10 +13365,10 @@ I
"B @x @@ o

@
-ۆ[@ GL a~  ǀ
+ۆ[@ GL a~  ׀

-
-
+
+@e
(
! (@( hQ
@@ -13379,7 +13379,7 @@ kè
+B
*
-*
+*
! ( 銂( (
@@ -13436,11 +13436,11 @@ G

N N N

-  
-@
+  
+@
!
G
-
+
ߏN Lȃ JB
`
@@ -13449,7 +13449,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 

@@ -13635,26 +13635,26 @@ D@ @
@x HR& b@I"@J@Hb
-
+

-
+
-
+
-:x
+:x
G @a
@x
-
+


, 

-
+

-@
+@

!
@@ -13667,46 +13667,46 @@ J 
G$
`
-
+

@I
-
+
o
-I@Ip v Gv v Gw  p v Gv v Gw  
+I@Ip v Gv v Gw  p v Gv v Gw  
-
+
-k@W @Z
-
+k@W @[
+

r
-H
-
+H
+
@I
 `

G `
-@x
+@x
 G`HR@
`"@
-
-
+
+
 b

2 x
-B 
+B 




-
+
A
@a

-
+

@@ -13716,7 +13716,7 @@ G `
@I ^ G \ G Z 
-I
+I
@@ -13729,40 +13729,41 @@ Q RIc P PCII G  B 

G LI B HbBx   a  t
-
+
-`
+a
GIǁ a
O
I@I

-
+
-@ x 
+@ x 
>
@x
- 
+ 
x QL FLBL
-@Lr@ǁ
+@Lr@ǁ
?I H
I HR
I  Ix  I  I  
L
H2X
-  IH
-
+  IH
+
+
-
+
@@ -13781,7 +13782,7 @@ H2X

I
A@_`
-T@ GL ~ 
+T@ GL ~ 
U
@@ -13822,7 +13823,7 @@ D@ @
@x HR& b@I"@J@Hb
-
+

@@ -14008,26 +14009,26 @@ D@ @
@x HR& b@I"@J@Hb
-
+

-
+
-
+
-:x
+:x
G @a
@x
-
+


, 

-
+

-@
+@

!
@@ -14040,46 +14041,46 @@ J 
G$
`
-
+

@I
-
+
o
-I@Ip v Gv v Gw  p v Gv v Gw  
+I@Ip v Gv v Gw  p v Gv v Gw  
-
+
-k@W @Z
-
+k@W @[
+

r
-H
-
+H
+
@I
 `

G `
-@x
+@x
 G`HR@
`"@
-
-
+
+
 b

2 x
-B 
+B 




-
+
A
@a

-
+

@@ -14089,7 +14090,7 @@ G `
@I ^ G \ G Z 
-I
+I
@@ -14102,40 +14103,41 @@ Q RIc P PCII G  B 

G LI B HbBx   a  t
-
+
-`
+a
GIǁ a
O
I@I

-
+
-@ x 
+@ x 
>
@x
- 
+ 
x QL FLBL
-@Lr@ǁ
+@Lr@ǁ
?I H
I HR
I  Ix  I  I  
L
H2X
-  IH
-
+  IH
+
+
-
+
@@ -14154,7 +14156,7 @@ H2X

I
A@_`
-T@ GL ~ 
+T@ GL ~ 
U
@@ -14195,7 +14197,8 @@ D@ @
@x HR& b@I"@J@Hb
-
+
+]I6d127c5
y
G@,
%
@@ -14513,7 +14516,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
G+
%
@@ -14805,7 +14808,7 @@ G
@
!
G
-
+
G+
%
@@ -15097,7 +15100,8 @@ G
@
!
G
-
+
+]I6d127c5
G+
%
@@ -15389,7 +15393,8 @@ G
@
!
G
-
+
+]I6d127c5
y
G@,
%
@@ -15707,7 +15712,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
y
G@,
%
@@ -16025,7 +16030,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
y
G@,
%
@@ -16343,7 +16348,8 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
+]I6d127c5
G+
%
@@ -16635,7 +16641,8 @@ G
@
!
G
-
+
+]I6d127c5
x
`
x
@@ -16850,7 +16857,8 @@ E 
-
+
+]I6d127c5
x
`
x
@@ -17065,7 +17073,8 @@ E 
-
+
+]I6d127c5
x
`
x
@@ -17287,7 +17296,8 @@ E 
-
+
+]I6d127c5
 @
I`
@x `
@@ -17666,7 +17676,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
 @
I`
@@ -18045,7 +18056,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
 @
I`
@x `
@@ -18424,7 +18436,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
 @
I`
@@ -18862,7 +18875,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
 @
I`
@x `
@@ -19235,7 +19249,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
 @
I`
@@ -19614,7 +19629,8 @@ H
*AL+CLh j@
j
-
+
+]I6d127c5
3
 
@@ -20444,7 +20460,8 @@ q 
@

i
-
+
+]I6d127c5
3
 
@@ -21275,7 +21292,7 @@ q 
@

i
-
+
@ `
@@ -21924,7 +21941,7 @@ J2 x 
0
`
-
+
@ `
@@ -22573,7 +22590,7 @@ J2 x 
0
`
-
+
@ `
@@ -23222,7 +23239,7 @@ J2 x 
0
`
-
+
@ `
@@ -23871,7 +23888,8 @@ J2 x 
0
`
-
+
+]I6d127c5
@x
@ `
@x
@@ -24518,7 +24536,7 @@ J2 x 
0
`
-
+

x
@x
@@ -25047,7 +25065,7 @@ H#`
&
-C
+C

x
x
@@ -25586,7 +25604,7 @@ H#`
&
-@
+@

@
x
@@ -26113,7 +26131,7 @@ H#`
&
-@
+@

x
x
@@ -26639,7 +26657,7 @@ H#`
&
-C
+C

x
@x
@@ -27168,7 +27186,7 @@ H#`
&
-C
+C

x
@x
@@ -27697,7 +27715,7 @@ H#`
&
-C
+C

x
@x
@@ -28226,7 +28244,7 @@ H#`
&
-C
+C
y

@@ -28841,7 +28859,7 @@ H
-
+
+@+@
@@ -29165,7 +29183,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -29487,7 +29505,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -29806,7 +29824,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -30125,7 +30143,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -30447,7 +30465,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -30772,7 +30790,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
+@+@
@@ -31091,7 +31109,7 @@ a . AB+@+@
-J`  JJ` 
+J`  JJ` 
FL  CL R@ 
I`
x `
@@ -31319,7 +31337,7 @@ E===  E DL>L
D@ @
-x HR& b@I"@J@Hb
+x HR& b@I"@J@Hb
FL  CL R@ 
I`
x `
@@ -31545,7 +31563,7 @@ E===  E DL>L
D@ @
-x HR& b@I"@J@Hb
+x HR& b@I"@J@Hb
FL  CL R@ 
I`
x `
@@ -31773,7 +31791,7 @@ E===  E DL>L
D@ @
-x HR& b@I"@J@Hb
+x HR& b@I"@J@Hb
FL  CL R@ 
I`
x `