From 9756f0b7bd84f021be0d0cdafa771dac694694c9 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sat, 23 May 2020 14:42:27 +0000 Subject: [PATCH] WIP: media: rkvdec: h264: add field decoding support Signed-off-by: Jonas Karlman --- drivers/staging/media/rkvdec/rkvdec-h264.c | 79 ++++++++++++++++++---- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/drivers/staging/media/rkvdec/rkvdec-h264.c b/drivers/staging/media/rkvdec/rkvdec-h264.c index 1c68ebdd8d08e8..68090c4c2cfa3e 100644 --- a/drivers/staging/media/rkvdec/rkvdec-h264.c +++ b/drivers/staging/media/rkvdec/rkvdec-h264.c @@ -737,7 +737,7 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, u8 *reflists[3] = { h264_ctx->reflists.p, h264_ctx->reflists.b0, h264_ctx->reflists.b1 }; u32 *hw_rps = priv_tbl->rps; - u32 i, j; + u32 i, j, k; u16 *p = (u16 *)hw_rps; memset(hw_rps, 0, sizeof(priv_tbl->rps)); @@ -764,18 +764,71 @@ static void assemble_hw_rps(struct rkvdec_ctx *ctx, p[i] = dpb[i].frame_num - max_frame_num; } - for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { - for (i = 0; i < h264_ctx->reflists.num_valid; i++) { - u8 dpb_valid = 0; - u8 idx = reflists[j][i]; + if (!(dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) { + for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { + for (i = 0; i < h264_ctx->reflists.num_valid; i++) { + u8 dpb_valid = 0; + u8 idx = reflists[j][i]; - if (idx >= ARRAY_SIZE(dec_params->dpb)) - continue; - dpb_valid = !!(dpb[idx].flags & - V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); + if (idx >= ARRAY_SIZE(dec_params->dpb)) + continue; + dpb_valid = !!(dpb[idx].flags & + V4L2_H264_DPB_ENTRY_FLAG_ACTIVE); - set_ps_field(hw_rps, DPB_INFO(i, j), - idx | dpb_valid << 4); + set_ps_field(hw_rps, DPB_INFO(i, j), + idx | dpb_valid << 4); + } + } + return; + } + + for (j = 0; j < RKVDEC_NUM_REFLIST; j++) { + enum v4l2_h264_dpb_reference a_parity = + (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + ? V4L2_H264_DPB_BOTTOM_REF : V4L2_H264_DPB_TOP_REF; + enum v4l2_h264_dpb_reference b_parity = + (dec_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + ? V4L2_H264_DPB_TOP_REF : V4L2_H264_DPB_BOTTOM_REF; + u32 flags = V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM; + i = 0; + + for (k = 0; k < 2; k++) { + u8 a = 0; + u8 b = 0; + u32 long_term = k ? V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM : 0; + + while (a < h264_ctx->reflists.num_valid || b < h264_ctx->reflists.num_valid) { + for (; a < h264_ctx->reflists.num_valid; a++) { + u8 idx = reflists[j][a]; + if (idx >= ARRAY_SIZE(dec_params->dpb)) + continue; + if ((dpb[idx].reference & a_parity) == a_parity && + (dpb[idx].flags & flags) == long_term) { + set_ps_field(hw_rps, DPB_INFO(i, j), + idx | (1 << 4)); + set_ps_field(hw_rps, BOTTOM_FLAG(i, j), + a_parity == V4L2_H264_DPB_BOTTOM_REF); + i++; + a++; + break; + } + } + for (; b < h264_ctx->reflists.num_valid; b++) { + u8 idx = reflists[j][b]; + if (idx >= ARRAY_SIZE(dec_params->dpb)) + continue; + if ((dpb[idx].reference & b_parity) == b_parity && + (dpb[idx].flags & flags) == long_term) { + set_ps_field(hw_rps, DPB_INFO(i, j), + idx | (1 << 4)); + set_ps_field(hw_rps, BOTTOM_FLAG(i, j), + b_parity == V4L2_H264_DPB_BOTTOM_REF); + i++; + b++; + break; + } + } + } } } } @@ -964,10 +1017,6 @@ static void config_registers(struct rkvdec_ctx *ctx, rkvdec->regs + RKVDEC_REG_H264_BASE_REFER15); } - /* - * Since support frame mode only - * top_field_order_cnt is the same as bottom_field_order_cnt - */ reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt); writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0);