summaryrefslogtreecommitdiff
path: root/drivers/media/platform/amphion/vdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/amphion/vdec.c')
-rw-r--r--drivers/media/platform/amphion/vdec.c350
1 files changed, 287 insertions, 63 deletions
diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c
index 3fa1a74a2e20..c0d2aabb9e0e 100644
--- a/drivers/media/platform/amphion/vdec.c
+++ b/drivers/media/platform/amphion/vdec.c
@@ -26,6 +26,7 @@
#include "vpu_cmds.h"
#include "vpu_rpc.h"
+#define VDEC_SLOT_CNT_DFT 32
#define VDEC_MIN_BUFFER_CAP 8
#define VDEC_MIN_BUFFER_OUT 8
@@ -41,6 +42,14 @@ struct vdec_fs_info {
u32 tag;
};
+struct vdec_frame_store_t {
+ struct vpu_vb2_buffer *curr;
+ struct vpu_vb2_buffer *pend;
+ dma_addr_t addr;
+ unsigned int state;
+ u32 tag;
+};
+
struct vdec_t {
u32 seq_hdr_found;
struct vpu_buffer udata;
@@ -48,7 +57,8 @@ struct vdec_t {
struct vpu_dec_codec_info codec_info;
enum vpu_codec_state state;
- struct vpu_vb2_buffer *slots[VB2_MAX_FRAME];
+ struct vdec_frame_store_t *slots;
+ u32 slot_count;
u32 req_frame_count;
struct vdec_fs_info mbi;
struct vdec_fs_info dcp;
@@ -195,7 +205,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
struct vdec_t *vdec = inst->priv;
int ret = 0;
- vpu_inst_lock(inst);
switch (ctrl->id) {
case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
vdec->params.display_delay_enable = ctrl->val;
@@ -207,7 +216,6 @@ static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
ret = -EINVAL;
break;
}
- vpu_inst_unlock(inst);
return ret;
}
@@ -234,6 +242,35 @@ static int vdec_ctrl_init(struct vpu_inst *inst)
V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
0, 1, 1, 0);
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, NULL,
+ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+ V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
+ ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED) |
+ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+ V4L2_MPEG_VIDEO_H264_PROFILE_MAIN);
+
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, NULL,
+ V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+ V4L2_MPEG_VIDEO_H264_LEVEL_6_2,
+ 0,
+ V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
+
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, NULL,
+ V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ ~((1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ (1 << V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10)),
+ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN);
+
+ v4l2_ctrl_new_std_menu(&inst->ctrl_handler, NULL,
+ V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+ V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
+ 0,
+ V4L2_MPEG_VIDEO_HEVC_LEVEL_4);
+
ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,
V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2);
if (ctrl)
@@ -260,6 +297,63 @@ static int vdec_ctrl_init(struct vpu_inst *inst)
return 0;
}
+static void vdec_attach_frame_store(struct vpu_inst *inst, struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf);
+ struct vdec_t *vdec = inst->priv;
+ struct vdec_frame_store_t *new_slots = NULL;
+ dma_addr_t addr;
+ int i;
+
+ addr = vpu_get_vb_phy_addr(vb, 0);
+ for (i = 0; i < vdec->slot_count; i++) {
+ if (addr == vdec->slots[i].addr) {
+ if (vdec->slots[i].curr && vdec->slots[i].curr != vpu_buf) {
+ vpu_set_buffer_state(vbuf, VPU_BUF_STATE_CHANGED);
+ vdec->slots[i].pend = vpu_buf;
+ } else {
+ vpu_set_buffer_state(vbuf, vdec->slots[i].state);
+ }
+ vpu_buf->fs_id = i;
+ return;
+ }
+ }
+
+ for (i = 0; i < vdec->slot_count; i++) {
+ if (!vdec->slots[i].addr) {
+ vdec->slots[i].addr = addr;
+ vpu_buf->fs_id = i;
+ return;
+ }
+ }
+
+ new_slots = krealloc_array(vdec->slots, vdec->slot_count * 2,
+ sizeof(*vdec->slots),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!new_slots) {
+ vpu_set_buffer_state(vbuf, VPU_BUF_STATE_ERROR);
+ return;
+ }
+
+ vdec->slots = new_slots;
+ vdec->slot_count *= 2;
+
+ vdec->slots[i].addr = addr;
+ vpu_buf->fs_id = i;
+}
+
+static void vdec_reset_frame_store(struct vpu_inst *inst)
+{
+ struct vdec_t *vdec = inst->priv;
+
+ if (!vdec->slots || !vdec->slot_count)
+ return;
+
+ vpu_trace(inst->dev, "inst[%d] reset slots\n", inst->id);
+ memset(vdec->slots, 0, sizeof(*vdec->slots) * vdec->slot_count);
+}
+
static void vdec_handle_resolution_change(struct vpu_inst *inst)
{
struct vdec_t *vdec = inst->priv;
@@ -279,6 +373,7 @@ static void vdec_handle_resolution_change(struct vpu_inst *inst)
vdec->source_change--;
vpu_notify_source_change(inst);
+ vpu_set_last_buffer_dequeued(inst, false);
}
static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force)
@@ -298,7 +393,8 @@ static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state,
vdec->state = VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE;
if (inst->state != pre_state)
- vpu_trace(inst->dev, "[%d] %d -> %d\n", inst->id, pre_state, inst->state);
+ vpu_trace(inst->dev, "[%d] %s -> %s\n", inst->id,
+ vpu_codec_state_name(pre_state), vpu_codec_state_name(inst->state));
if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)
vdec_handle_resolution_change(inst);
@@ -314,7 +410,7 @@ static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst)
return;
if (vdec->eos_received) {
- if (!vpu_set_last_buffer_dequeued(inst)) {
+ if (!vpu_set_last_buffer_dequeued(inst, true)) {
vdec->eos_received--;
vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0);
}
@@ -436,8 +532,6 @@ static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)
return -EINVAL;
q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);
- if (!q)
- return -EINVAL;
if (vb2_is_busy(q))
return -EBUSY;
@@ -569,7 +663,7 @@ static int vdec_drain(struct vpu_inst *inst)
return 0;
if (!vdec->params.frame_count) {
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
return 0;
}
@@ -608,7 +702,7 @@ static int vdec_cmd_stop(struct vpu_inst *inst)
vpu_trace(inst->dev, "[%d]\n", inst->id);
if (inst->state == VPU_CODEC_STATE_DEINIT) {
- vpu_set_last_buffer_dequeued(inst);
+ vpu_set_last_buffer_dequeued(inst, true);
} else {
vdec->drain = 1;
vdec_drain(inst);
@@ -714,11 +808,11 @@ static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
struct vb2_v4l2_buffer *src_buf;
int ret = 0;
- if (!info || info->id >= ARRAY_SIZE(vdec->slots))
+ if (!info || info->id >= vdec->slot_count)
return -EINVAL;
vpu_inst_lock(inst);
- vpu_buf = vdec->slots[info->id];
+ vpu_buf = vdec->slots[info->id].curr;
if (!vpu_buf) {
dev_err(inst->dev, "[%d] decoded invalid frame[%d]\n", inst->id, info->id);
ret = -EINVAL;
@@ -727,7 +821,7 @@ static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
vbuf = &vpu_buf->m2m_buf.vb;
src_buf = vdec_get_src_buffer(inst, info->consumed_count);
if (src_buf) {
- v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);
+ v4l2_m2m_buf_copy_metadata(src_buf, vbuf);
if (info->consumed_count) {
v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
@@ -739,7 +833,24 @@ static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)
if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED)
dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id);
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED);
+ vdec->slots[info->id].state = VPU_BUF_STATE_DECODED;
vdec->decoded_frame_count++;
+ if (vdec->params.display_delay_enable) {
+ struct vpu_format *cur_fmt;
+
+ cur_fmt = vpu_get_format(inst, inst->cap_format.type);
+ vdec->slots[info->id].state = VPU_BUF_STATE_READY;
+ vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);
+ for (int i = 0; i < vbuf->vb2_buf.num_planes; i++)
+ vb2_set_plane_payload(&vbuf->vb2_buf,
+ i, vpu_get_fmt_plane_size(cur_fmt, i));
+ vbuf->field = cur_fmt->field;
+ vbuf->sequence = vdec->sequence++;
+ dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
+
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+ vdec->display_frame_count++;
+ }
exit:
vpu_inst_unlock(inst);
@@ -751,11 +862,11 @@ static struct vpu_vb2_buffer *vdec_find_buffer(struct vpu_inst *inst, u32 luma)
struct vdec_t *vdec = inst->priv;
int i;
- for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {
- if (!vdec->slots[i])
+ for (i = 0; i < vdec->slot_count; i++) {
+ if (!vdec->slots[i].curr)
continue;
- if (luma == vdec->slots[i]->luma)
- return vdec->slots[i];
+ if (luma == vdec->slots[i].addr)
+ return vdec->slots[i].curr;
}
return NULL;
@@ -767,14 +878,14 @@ static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)
struct vpu_format *cur_fmt;
struct vpu_vb2_buffer *vpu_buf;
struct vb2_v4l2_buffer *vbuf;
- u32 sequence;
int i;
if (!frame)
return;
vpu_inst_lock(inst);
- sequence = vdec->sequence++;
+ if (!vdec->params.display_delay_enable)
+ vdec->sequence++;
vpu_buf = vdec_find_buffer(inst, frame->luma);
vpu_inst_unlock(inst);
if (!vpu_buf) {
@@ -789,23 +900,28 @@ static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)
cur_fmt = vpu_get_format(inst, inst->cap_format.type);
vbuf = &vpu_buf->m2m_buf.vb;
- if (vbuf->vb2_buf.index != frame->id)
- dev_err(inst->dev, "[%d] buffer id(%d, %d) dismatch\n",
- inst->id, vbuf->vb2_buf.index, frame->id);
+ if (vpu_buf->fs_id != frame->id)
+ dev_err(inst->dev, "[%d] buffer id(%d(%d), %d) mismatch\n",
+ inst->id, vpu_buf->fs_id, vbuf->vb2_buf.index, frame->id);
+
+ if (vdec->params.display_delay_enable)
+ return;
if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_DECODED)
dev_err(inst->dev, "[%d] buffer(%d) ready without decoded\n", inst->id, frame->id);
+
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);
for (i = 0; i < vbuf->vb2_buf.num_planes; i++)
vb2_set_plane_payload(&vbuf->vb2_buf, i, vpu_get_fmt_plane_size(cur_fmt, i));
vbuf->field = cur_fmt->field;
- vbuf->sequence = sequence;
+ vbuf->sequence = vdec->sequence;
dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);
- v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
vpu_inst_lock(inst);
+ vdec->slots[vpu_buf->fs_id].state = VPU_BUF_STATE_READY;
vdec->display_frame_count++;
vpu_inst_unlock(inst);
+ v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
dev_dbg(inst->dev, "[%d] decoded : %d, display : %d, sequence : %d\n",
inst->id, vdec->decoded_frame_count, vdec->display_frame_count, vdec->sequence);
}
@@ -998,6 +1114,7 @@ static int vdec_response_frame_abnormal(struct vpu_inst *inst)
{
struct vdec_t *vdec = inst->priv;
struct vpu_fs_info info;
+ int ret;
if (!vdec->req_frame_count)
return 0;
@@ -1005,7 +1122,9 @@ static int vdec_response_frame_abnormal(struct vpu_inst *inst)
memset(&info, 0, sizeof(info));
info.type = MEM_RES_FRAME;
info.tag = vdec->seq_tag + 0xf0;
- vpu_session_alloc_fs(inst, &info);
+ ret = vpu_session_alloc_fs(inst, &info);
+ if (ret)
+ return ret;
vdec->req_frame_count--;
return 0;
@@ -1030,18 +1149,30 @@ static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vb
if (!vbuf)
return -EINVAL;
- if (vdec->slots[vbuf->vb2_buf.index]) {
- dev_err(inst->dev, "[%d] repeat alloc fs %d\n",
- inst->id, vbuf->vb2_buf.index);
+ vpu_buf = to_vpu_vb2_buffer(vbuf);
+ if (vpu_buf->fs_id < 0 || vpu_buf->fs_id >= vdec->slot_count) {
+ dev_err(inst->dev, "invalid fs %d for v4l2 buffer %d\n",
+ vpu_buf->fs_id, vbuf->vb2_buf.index);
return -EINVAL;
}
- dev_dbg(inst->dev, "[%d] state = %d, alloc fs %d, tag = 0x%x\n",
- inst->id, inst->state, vbuf->vb2_buf.index, vdec->seq_tag);
- vpu_buf = to_vpu_vb2_buffer(vbuf);
+ if (vdec->slots[vpu_buf->fs_id].curr) {
+ if (vdec->slots[vpu_buf->fs_id].curr != vpu_buf) {
+ vpu_set_buffer_state(vbuf, VPU_BUF_STATE_CHANGED);
+ vdec->slots[vpu_buf->fs_id].pend = vpu_buf;
+ } else {
+ vpu_set_buffer_state(vbuf, vdec->slots[vpu_buf->fs_id].state);
+ }
+ dev_err(inst->dev, "[%d] repeat alloc fs %d (v4l2 index %d)\n",
+ inst->id, vpu_buf->fs_id, vbuf->vb2_buf.index);
+ return -EAGAIN;
+ }
+
+ dev_dbg(inst->dev, "[%d] state = %s, alloc fs %d, tag = 0x%x\n",
+ inst->id, vpu_codec_state_name(inst->state), vbuf->vb2_buf.index, vdec->seq_tag);
memset(&info, 0, sizeof(info));
- info.id = vbuf->vb2_buf.index;
+ info.id = vpu_buf->fs_id;
info.type = MEM_RES_FRAME;
info.tag = vdec->seq_tag;
info.luma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 0);
@@ -1056,12 +1187,13 @@ static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vb
if (ret)
return ret;
- vpu_buf->tag = info.tag;
vpu_buf->luma = info.luma_addr;
vpu_buf->chroma_u = info.chroma_addr;
vpu_buf->chroma_v = 0;
vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);
- vdec->slots[info.id] = vpu_buf;
+ vdec->slots[info.id].tag = info.tag;
+ vdec->slots[info.id].curr = vpu_buf;
+ vdec->slots[info.id].state = VPU_BUF_STATE_INUSE;
vdec->req_frame_count--;
return 0;
@@ -1122,25 +1254,76 @@ static void vdec_recycle_buffer(struct vpu_inst *inst, struct vb2_v4l2_buffer *v
v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf);
}
-static void vdec_clear_slots(struct vpu_inst *inst)
+static void vdec_release_curr_frame_store(struct vpu_inst *inst, u32 id)
{
struct vdec_t *vdec = inst->priv;
struct vpu_vb2_buffer *vpu_buf;
struct vb2_v4l2_buffer *vbuf;
+
+ if (id >= vdec->slot_count)
+ return;
+ if (!vdec->slots[id].curr)
+ return;
+
+ vpu_buf = vdec->slots[id].curr;
+ vbuf = &vpu_buf->m2m_buf.vb;
+
+ vdec_response_fs_release(inst, id, vdec->slots[id].tag);
+ if (vpu_buf->fs_id == id) {
+ if (vpu_buf->state != VPU_BUF_STATE_READY)
+ vdec_recycle_buffer(inst, vbuf);
+ vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
+ }
+
+ vdec->slots[id].curr = NULL;
+ vdec->slots[id].state = VPU_BUF_STATE_IDLE;
+
+ if (vdec->slots[id].pend) {
+ vpu_set_buffer_state(&vdec->slots[id].pend->m2m_buf.vb, VPU_BUF_STATE_IDLE);
+ vdec->slots[id].pend = NULL;
+ }
+}
+
+static void vdec_clear_slots(struct vpu_inst *inst)
+{
+ struct vdec_t *vdec = inst->priv;
int i;
- for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {
- if (!vdec->slots[i])
+ for (i = 0; i < vdec->slot_count; i++) {
+ if (!vdec->slots[i].curr)
continue;
- vpu_buf = vdec->slots[i];
- vbuf = &vpu_buf->m2m_buf.vb;
-
vpu_trace(inst->dev, "clear slot %d\n", i);
- vdec_response_fs_release(inst, i, vpu_buf->tag);
- vdec_recycle_buffer(inst, vbuf);
- vdec->slots[i]->state = VPU_BUF_STATE_IDLE;
- vdec->slots[i] = NULL;
+ vdec_release_curr_frame_store(inst, i);
+ }
+}
+
+static void vdec_update_v4l2_ctrl(struct vpu_inst *inst, u32 id, u32 val)
+{
+ struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&inst->ctrl_handler, id);
+
+ if (ctrl)
+ v4l2_ctrl_s_ctrl(ctrl, val);
+}
+
+static void vdec_update_v4l2_profile_level(struct vpu_inst *inst, struct vpu_dec_codec_info *hdr)
+{
+ switch (inst->out_format.pixfmt) {
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_H264_MVC:
+ vdec_update_v4l2_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+ vpu_get_h264_v4l2_profile(hdr));
+ vdec_update_v4l2_ctrl(inst, V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+ vpu_get_h264_v4l2_level(hdr));
+ break;
+ case V4L2_PIX_FMT_HEVC:
+ vdec_update_v4l2_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+ vpu_get_hevc_v4l2_profile(hdr));
+ vdec_update_v4l2_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+ vpu_get_hevc_v4l2_level(hdr));
+ break;
+ default:
+ return;
}
}
@@ -1167,6 +1350,7 @@ static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info
vdec_init_crop(inst);
vdec_init_mbi(inst);
vdec_init_dcp(inst);
+ vdec_update_v4l2_profile_level(inst, hdr);
if (!vdec->seq_hdr_found) {
vdec->seq_tag = vdec->codec_info.tag;
if (vdec->is_source_changed) {
@@ -1241,39 +1425,29 @@ static void vdec_event_req_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)
static void vdec_evnet_rel_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)
{
struct vdec_t *vdec = inst->priv;
- struct vpu_vb2_buffer *vpu_buf;
- struct vb2_v4l2_buffer *vbuf;
- if (!fs || fs->id >= ARRAY_SIZE(vdec->slots))
+ if (!fs || fs->id >= vdec->slot_count)
return;
if (fs->type != MEM_RES_FRAME)
return;
- if (fs->id >= vpu_get_num_buffers(inst, inst->cap_format.type)) {
+ if (fs->id >= vdec->slot_count) {
dev_err(inst->dev, "[%d] invalid fs(%d) to release\n", inst->id, fs->id);
return;
}
vpu_inst_lock(inst);
- vpu_buf = vdec->slots[fs->id];
- vdec->slots[fs->id] = NULL;
-
- if (!vpu_buf) {
+ if (!vdec->slots[fs->id].curr) {
dev_dbg(inst->dev, "[%d] fs[%d] has bee released\n", inst->id, fs->id);
goto exit;
}
- vbuf = &vpu_buf->m2m_buf.vb;
- if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) {
+ if (vdec->slots[fs->id].state == VPU_BUF_STATE_DECODED) {
dev_dbg(inst->dev, "[%d] frame skip\n", inst->id);
vdec->sequence++;
}
- vdec_response_fs_release(inst, fs->id, vpu_buf->tag);
- if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_READY)
- vdec_recycle_buffer(inst, vbuf);
-
- vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);
+ vdec_release_curr_frame_store(inst, fs->id);
vpu_process_capture_buffer(inst);
exit:
@@ -1399,7 +1573,7 @@ static void vdec_abort(struct vpu_inst *inst)
struct vpu_rpc_buffer_desc desc;
int ret;
- vpu_trace(inst->dev, "[%d] state = %d\n", inst->id, inst->state);
+ vpu_trace(inst->dev, "[%d] state = %s\n", inst->id, vpu_codec_state_name(inst->state));
vdec->aborting = true;
vpu_iface_add_scode(inst, SCODE_PADDING_ABORT);
@@ -1452,9 +1626,7 @@ static void vdec_release(struct vpu_inst *inst)
{
if (inst->id != VPU_INST_NULL_ID)
vpu_trace(inst->dev, "[%d]\n", inst->id);
- vpu_inst_lock(inst);
vdec_stop(inst, true);
- vpu_inst_unlock(inst);
}
static void vdec_cleanup(struct vpu_inst *inst)
@@ -1465,6 +1637,11 @@ static void vdec_cleanup(struct vpu_inst *inst)
return;
vdec = inst->priv;
+ if (vdec) {
+ kfree(vdec->slots);
+ vdec->slots = NULL;
+ vdec->slot_count = 0;
+ }
vfree(vdec);
inst->priv = NULL;
vfree(inst);
@@ -1573,9 +1750,11 @@ static int vdec_stop_session(struct vpu_inst *inst, u32 type)
if (V4L2_TYPE_IS_OUTPUT(type)) {
vdec_update_state(inst, VPU_CODEC_STATE_SEEK, 0);
vdec->drain = 0;
+ vdec_abort(inst);
} else {
if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) {
- vdec_abort(inst);
+ if (vb2_is_streaming(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx)))
+ vdec_abort(inst);
vdec->eos_received = 0;
}
vdec_clear_slots(inst);
@@ -1584,11 +1763,43 @@ static int vdec_stop_session(struct vpu_inst *inst, u32 type)
return 0;
}
-static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)
+static int vdec_get_slot_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)
{
struct vdec_t *vdec = inst->priv;
+ struct vpu_vb2_buffer *vpu_buf;
int num = -1;
+ vpu_inst_lock(inst);
+ if (i >= vdec->slot_count || !vdec->slots[i].addr)
+ goto exit;
+
+ vpu_buf = vdec->slots[i].curr;
+
+ num = scnprintf(str, size, "slot[%2d] :", i);
+ if (vpu_buf) {
+ num += scnprintf(str + num, size - num, " %2d",
+ vpu_buf->m2m_buf.vb.vb2_buf.index);
+ num += scnprintf(str + num, size - num, "; state = %d", vdec->slots[i].state);
+ } else {
+ num += scnprintf(str + num, size - num, " -1");
+ }
+
+ if (vdec->slots[i].pend)
+ num += scnprintf(str + num, size - num, "; %d",
+ vdec->slots[i].pend->m2m_buf.vb.vb2_buf.index);
+
+ num += scnprintf(str + num, size - num, "\n");
+exit:
+ vpu_inst_unlock(inst);
+
+ return num;
+}
+
+static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)
+{
+ struct vdec_t *vdec = inst->priv;
+ int num;
+
switch (i) {
case 0:
num = scnprintf(str, size,
@@ -1642,6 +1853,7 @@ static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i
vdec->codec_info.vui_present);
break;
default:
+ num = vdec_get_slot_debug_info(inst, str, size, i - 10);
break;
}
@@ -1665,6 +1877,8 @@ static struct vpu_inst_ops vdec_inst_ops = {
.get_debug_info = vdec_get_debug_info,
.wait_prepare = vpu_inst_unlock,
.wait_finish = vpu_inst_lock,
+ .attach_frame_store = vdec_attach_frame_store,
+ .reset_frame_store = vdec_reset_frame_store,
};
static void vdec_init(struct file *file)
@@ -1705,6 +1919,16 @@ static int vdec_open(struct file *file)
return -ENOMEM;
}
+ vdec->slots = kmalloc_array(VDEC_SLOT_CNT_DFT,
+ sizeof(*vdec->slots),
+ GFP_KERNEL | __GFP_ZERO);
+ if (!vdec->slots) {
+ vfree(vdec);
+ vfree(inst);
+ return -ENOMEM;
+ }
+ vdec->slot_count = VDEC_SLOT_CNT_DFT;
+
inst->ops = &vdec_inst_ops;
inst->formats = vdec_formats;
inst->type = VPU_CORE_TYPE_DEC;