On Fri Jan 9 11:15:20 2026 -0500, Detlev Casanova wrote:
> In an effort to merge the rkvdec2 driver [1] with this one, switch from
> writel() calls to using structs to represent the register mappings.
>
> This is done in order to have all supported decoders use the same format
> in the future and ease reading of the code.
>
> Using structs also improves stability as the hardware is tested and
> validated downstream using a similar method.
> It was noticed, on decoders, that:
> - Some registers require to be writen in increasing order [2]
> - Some registers, even if unrelated, need to be written to their reset
> values (it was the case here for axi_ddr_[rw]data).
>
> Using structs can also help improving performance later when, e.g.
> multicore support is added on RK3588.
>
> Performance seems to be slightly improved, but at least, not made worse.
> Running fluster's JVT-AVC_V1 test suite with GStreamer on the Radxa ROCK
> PI 4 SE gives the following times:
>
> Before this patch:
>
> - --jobs 1: Ran 129/135 tests successfully in 77.167 secs
> - --jobs 6: Ran 129/135 tests successfully in 23.046 secs
>
> With this patch:
> - --jobs 1: Ran 129/135 tests successfully in 70.698 secs
> - --jobs 6: Ran 129/135 tests successfully in 22.917 secs
>
> This also shows that the fluster score hasn't changed.
>
> [1]:
> https://lore.kernel.org/all/[email protected]/
> [2]:
> https://lore.kernel.org/all/[email protected]/
>
> Tested-by: Diederik de Haas <[email protected]> # Rock 5B
> Reviewed-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Detlev Casanova <[email protected]>
> Signed-off-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
.../media/platform/rockchip/rkvdec/rkvdec-h264.c | 166 +++---
.../media/platform/rockchip/rkvdec/rkvdec-hevc.c | 64 +--
.../media/platform/rockchip/rkvdec/rkvdec-regs.h | 586 ++++++++++++++-------
.../media/platform/rockchip/rkvdec/rkvdec-vp9.c | 232 ++++----
drivers/media/platform/rockchip/rkvdec/rkvdec.c | 10 +-
drivers/media/platform/rockchip/rkvdec/rkvdec.h | 1 +
6 files changed, 604 insertions(+), 455 deletions(-)
---
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c
b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c
index d14b4d173448..68e20cb81a88 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-h264.c
@@ -115,6 +115,7 @@ struct rkvdec_h264_run {
struct rkvdec_h264_ctx {
struct rkvdec_aux_buf priv_tbl;
struct rkvdec_h264_reflists reflists;
+ struct rkvdec_regs regs;
};
#define CABAC_ENTRY(ctxidx, idc0_m, idc0_n, idc1_m, idc1_n, \
@@ -841,45 +842,41 @@ static void assemble_hw_scaling_list(struct rkvdec_ctx
*ctx,
}
/*
- * dpb poc related registers table
+ * Set the ref POC in the correct register.
+ *
+ * The 32 registers are spread across 3 regions, each alternating top and
bottom ref POCs:
+ * - 1: ref 0 to 14 contain top 0 to 7 and bottoms 0 to 6
+ * - 2: ref 15 to 29 contain top 8 to 14 and bottoms 7 to 14
+ * - 3: ref 30 and 31 which correspond to top 15 and bottom 15 respectively.
*/
-static const u32 poc_reg_tbl_top_field[16] = {
- RKVDEC_REG_H264_POC_REFER0(0),
- RKVDEC_REG_H264_POC_REFER0(2),
- RKVDEC_REG_H264_POC_REFER0(4),
- RKVDEC_REG_H264_POC_REFER0(6),
- RKVDEC_REG_H264_POC_REFER0(8),
- RKVDEC_REG_H264_POC_REFER0(10),
- RKVDEC_REG_H264_POC_REFER0(12),
- RKVDEC_REG_H264_POC_REFER0(14),
- RKVDEC_REG_H264_POC_REFER1(1),
- RKVDEC_REG_H264_POC_REFER1(3),
- RKVDEC_REG_H264_POC_REFER1(5),
- RKVDEC_REG_H264_POC_REFER1(7),
- RKVDEC_REG_H264_POC_REFER1(9),
- RKVDEC_REG_H264_POC_REFER1(11),
- RKVDEC_REG_H264_POC_REFER1(13),
- RKVDEC_REG_H264_POC_REFER2(0)
-};
-
-static const u32 poc_reg_tbl_bottom_field[16] = {
- RKVDEC_REG_H264_POC_REFER0(1),
- RKVDEC_REG_H264_POC_REFER0(3),
- RKVDEC_REG_H264_POC_REFER0(5),
- RKVDEC_REG_H264_POC_REFER0(7),
- RKVDEC_REG_H264_POC_REFER0(9),
- RKVDEC_REG_H264_POC_REFER0(11),
- RKVDEC_REG_H264_POC_REFER0(13),
- RKVDEC_REG_H264_POC_REFER1(0),
- RKVDEC_REG_H264_POC_REFER1(2),
- RKVDEC_REG_H264_POC_REFER1(4),
- RKVDEC_REG_H264_POC_REFER1(6),
- RKVDEC_REG_H264_POC_REFER1(8),
- RKVDEC_REG_H264_POC_REFER1(10),
- RKVDEC_REG_H264_POC_REFER1(12),
- RKVDEC_REG_H264_POC_REFER1(14),
- RKVDEC_REG_H264_POC_REFER2(1)
-};
+static void set_poc_reg(struct rkvdec_regs *regs, uint32_t poc, int id, bool
bottom)
+{
+ if (!bottom) {
+ switch (id) {
+ case 0 ... 7:
+ regs->h26x.ref0_14_poc[id * 2] = poc;
+ break;
+ case 8 ... 14:
+ regs->h26x.ref15_29_poc[(id - 8) * 2 + 1] = poc;
+ break;
+ case 15:
+ regs->h26x.ref30_poc = poc;
+ break;
+ }
+ } else {
+ switch (id) {
+ case 0 ... 6:
+ regs->h26x.ref0_14_poc[id * 2 + 1] = poc;
+ break;
+ case 7 ... 14:
+ regs->h26x.ref15_29_poc[(id - 7) * 2] = poc;
+ break;
+ case 15:
+ regs->h26x.ref31_poc = poc;
+ break;
+ }
+ }
+}
static void config_registers(struct rkvdec_ctx *ctx,
struct rkvdec_h264_run *run)
@@ -894,6 +891,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
struct vb2_v4l2_buffer *src_buf = run->base.bufs.src;
struct vb2_v4l2_buffer *dst_buf = run->base.bufs.dst;
const struct v4l2_format *f;
+ struct rkvdec_regs *regs = &h264_ctx->regs;
dma_addr_t rlc_addr;
dma_addr_t refer_addr;
u32 rlc_len;
@@ -903,10 +901,11 @@ static void config_registers(struct rkvdec_ctx *ctx,
u32 yuv_virstride = 0;
u32 offset;
dma_addr_t dst_addr;
- u32 reg, i;
+ u32 i;
- reg = RKVDEC_MODE(RKVDEC_MODE_H264);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL);
+ memset(regs, 0, sizeof(*regs));
+
+ regs->common.reg02.dec_mode = RKVDEC_MODE_H264;
f = &ctx->decoded_fmt;
dst_fmt = &f->fmt.pix_mp;
@@ -921,39 +920,35 @@ static void config_registers(struct rkvdec_ctx *ctx,
else if (sps->chroma_format_idc == 2)
yuv_virstride = 2 * y_virstride;
- reg = RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) |
- RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) |
- RKVDEC_SLICE_NUM_HIGHBIT |
- RKVDEC_SLICE_NUM_LOWBITS(0x7ff);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR);
+ regs->common.reg03.uv_hor_virstride = hor_virstride / 16;
+ regs->common.reg03.y_hor_virstride = hor_virstride / 16;
+ regs->common.reg03.slice_num_highbit = 1;
+ regs->common.reg03.slice_num_lowbits = 0x7ff;
/* config rlc base address */
rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
- writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
- writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_RLCWRITE_BASE);
+ regs->common.strm_rlc_base = rlc_addr;
+ regs->h26x.rlcwrite_base = rlc_addr;
rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
- reg = RKVDEC_STRM_LEN(rlc_len);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN);
+ regs->common.stream_len = rlc_len;
/* config cabac table */
offset = offsetof(struct rkvdec_h264_priv_tbl, cabac_table);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
+ regs->common.cabactbl_base = priv_start_addr + offset;
/* config output base address */
dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
- writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
+ regs->common.decout_base = dst_addr;
- reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
+ regs->common.reg08.y_virstride = y_virstride / 16;
- reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
+ regs->common.reg09.yuv_virstride = yuv_virstride / 16;
/* config ref pic address & poc */
for (i = 0; i < ARRAY_SIZE(dec_params->dpb); i++) {
struct vb2_buffer *vb_buf = run->ref_buf[i];
+ struct ref_base *base;
/*
* If a DPB entry is unused or invalid, address of current
destination
@@ -963,54 +958,37 @@ static void config_registers(struct rkvdec_ctx *ctx,
vb_buf = &dst_buf->vb2_buf;
refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0);
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
- refer_addr |= RKVDEC_COLMV_USED_FLAG_REF;
- if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD)
- refer_addr |= RKVDEC_FIELD_REF;
-
- if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
- refer_addr |= RKVDEC_TOPFIELD_USED_REF;
- if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
- refer_addr |= RKVDEC_BOTFIELD_USED_REF;
-
- writel_relaxed(dpb[i].top_field_order_cnt,
- rkvdec->regs + poc_reg_tbl_top_field[i]);
- writel_relaxed(dpb[i].bottom_field_order_cnt,
- rkvdec->regs + poc_reg_tbl_bottom_field[i]);
-
if (i < V4L2_H264_NUM_DPB_ENTRIES - 1)
- writel_relaxed(refer_addr,
- rkvdec->regs +
RKVDEC_REG_H264_BASE_REFER(i));
+ base = ®s->h26x.ref0_14_base[i];
else
- writel_relaxed(refer_addr,
- rkvdec->regs +
RKVDEC_REG_H264_BASE_REFER15);
- }
+ base = ®s->h26x.ref15_base;
- reg = RKVDEC_CUR_POC(dec_params->top_field_order_cnt);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0);
+ base->base_addr = refer_addr >> 4;
+ base->field_ref = !!(dpb[i].flags &
V4L2_H264_DPB_ENTRY_FLAG_FIELD);
+ base->colmv_use_flag_ref = !!(dpb[i].flags &
V4L2_H264_DPB_ENTRY_FLAG_ACTIVE);
+ base->topfield_used_ref = !!(dpb[i].fields &
V4L2_H264_TOP_FIELD_REF);
+ base->botfield_used_ref = !!(dpb[i].fields &
V4L2_H264_BOTTOM_FIELD_REF);
- reg = RKVDEC_CUR_POC(dec_params->bottom_field_order_cnt);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC1);
+ set_poc_reg(regs, dpb[i].top_field_order_cnt, i, false);
+ set_poc_reg(regs, dpb[i].bottom_field_order_cnt, i, true);
+ }
+
+ regs->h26x.cur_poc = dec_params->top_field_order_cnt;
+ regs->h26x.cur_poc1 = dec_params->bottom_field_order_cnt;
/* config hw pps address */
offset = offsetof(struct rkvdec_h264_priv_tbl, param_set);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_PPS_BASE);
+ regs->h26x.pps_base = priv_start_addr + offset;
/* config hw rps address */
offset = offsetof(struct rkvdec_h264_priv_tbl, rps);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_RPS_BASE);
-
- reg = RKVDEC_AXI_DDR_RDATA(0);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA);
-
- reg = RKVDEC_AXI_DDR_WDATA(0);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA);
+ regs->h26x.rps_base = priv_start_addr + offset;
offset = offsetof(struct rkvdec_h264_priv_tbl, err_info);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_H264_ERRINFO_BASE);
+ regs->h26x.errorinfo_base = priv_start_addr + offset;
+
+ rkvdec_memcpy_toio(rkvdec->regs, regs,
+ MIN(sizeof(*regs), sizeof(u32) *
rkvdec->variant->num_regs));
}
#define RKVDEC_H264_MAX_DEPTH_IN_BYTES 2
@@ -1181,8 +1159,6 @@ static int rkvdec_h264_run(struct rkvdec_ctx *ctx)
schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000));
- writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
- writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E);
writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
index fc7e6a260b0a..2d9e0e947a6d 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-hevc.c
@@ -129,6 +129,7 @@ struct rkvdec_hevc_run {
struct rkvdec_hevc_ctx {
struct rkvdec_aux_buf priv_tbl;
struct v4l2_ctrl_hevc_scaling_matrix scaling_matrix_cache;
+ struct rkvdec_regs regs;
};
struct scaling_factor {
@@ -548,6 +549,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
const struct v4l2_ctrl_hevc_slice_params *sl_params =
&run->slices_params[0];
const struct v4l2_hevc_dpb_entry *dpb = decode_params->dpb;
struct rkvdec_hevc_ctx *hevc_ctx = ctx->priv;
+ struct rkvdec_regs *regs = &hevc_ctx->regs;
dma_addr_t priv_start_addr = hevc_ctx->priv_tbl.dma;
const struct v4l2_pix_format_mplane *dst_fmt;
struct vb2_v4l2_buffer *src_buf = run->base.bufs.src;
@@ -564,8 +566,9 @@ static void config_registers(struct rkvdec_ctx *ctx,
dma_addr_t dst_addr;
u32 reg, i;
- reg = RKVDEC_MODE(RKVDEC_MODE_HEVC);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_SYSCTRL);
+ memset(regs, 0, sizeof(*regs));
+
+ regs->common.reg02.dec_mode = RKVDEC_MODE_HEVC;
f = &ctx->decoded_fmt;
dst_fmt = &f->fmt.pix_mp;
@@ -580,33 +583,27 @@ static void config_registers(struct rkvdec_ctx *ctx,
else if (sps->chroma_format_idc == 2)
yuv_virstride = 2 * y_virstride;
- reg = RKVDEC_Y_HOR_VIRSTRIDE(hor_virstride / 16) |
- RKVDEC_UV_HOR_VIRSTRIDE(hor_virstride / 16) |
- RKVDEC_SLICE_NUM_LOWBITS(run->num_slices);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_PICPAR);
+ regs->common.reg03.slice_num_lowbits = run->num_slices;
+ regs->common.reg03.uv_hor_virstride = hor_virstride / 16;
+ regs->common.reg03.y_hor_virstride = hor_virstride / 16;
/* config rlc base address */
rlc_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
- writel_relaxed(rlc_addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
+ regs->common.strm_rlc_base = rlc_addr;
rlc_len = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
- reg = RKVDEC_STRM_LEN(round_up(rlc_len, 16) + 64);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_STRM_LEN);
+ regs->common.stream_len = round_up(rlc_len, 16) + 64;
/* config cabac table */
offset = offsetof(struct rkvdec_hevc_priv_tbl, cabac_table);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
+ regs->common.cabactbl_base = priv_start_addr + offset;
/* config output base address */
dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
- writel_relaxed(dst_addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
-
- reg = RKVDEC_Y_VIRSTRIDE(y_virstride / 16);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
+ regs->common.decout_base = dst_addr;
- reg = RKVDEC_YUV_VIRSTRIDE(yuv_virstride / 16);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
+ regs->common.reg08.y_virstride = y_virstride / 16;
+ regs->common.reg09.yuv_virstride = yuv_virstride / 16;
/* config ref pic address */
for (i = 0; i < 15; i++) {
@@ -620,33 +617,30 @@ static void config_registers(struct rkvdec_ctx *ctx,
}
refer_addr = vb2_dma_contig_plane_dma_addr(vb_buf, 0);
- writel_relaxed(refer_addr | reg,
- rkvdec->regs + RKVDEC_REG_H264_BASE_REFER(i));
- reg = RKVDEC_POC_REFER(i <
decode_params->num_active_dpb_entries ?
- dpb[i].pic_order_cnt_val : 0);
- writel_relaxed(reg,
- rkvdec->regs + RKVDEC_REG_H264_POC_REFER0(i));
+ regs->h26x.ref0_14_base[i].base_addr = refer_addr >> 4;
+ regs->h26x.ref0_14_base[i].field_ref = !!(reg & 1);
+ regs->h26x.ref0_14_base[i].topfield_used_ref = !!(reg & 2);
+ regs->h26x.ref0_14_base[i].botfield_used_ref = !!(reg & 4);
+ regs->h26x.ref0_14_base[i].colmv_use_flag_ref = !!(reg & 8);
+
+ regs->h26x.ref0_14_poc[i] = i <
decode_params->num_active_dpb_entries
+ ? dpb[i].pic_order_cnt_val
+ : 0;
}
- reg = RKVDEC_CUR_POC(sl_params->slice_pic_order_cnt);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_CUR_POC0);
+ regs->h26x.cur_poc = sl_params->slice_pic_order_cnt;
/* config hw pps address */
offset = offsetof(struct rkvdec_hevc_priv_tbl, param_set);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_PPS_BASE);
+ regs->h26x.pps_base = priv_start_addr + offset;
/* config hw rps address */
offset = offsetof(struct rkvdec_hevc_priv_tbl, rps);
- writel_relaxed(priv_start_addr + offset,
- rkvdec->regs + RKVDEC_REG_RPS_BASE);
-
- reg = RKVDEC_AXI_DDR_RDATA(0);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_RDATA);
+ regs->h26x.rps_base = priv_start_addr + offset;
- reg = RKVDEC_AXI_DDR_WDATA(0);
- writel_relaxed(reg, rkvdec->regs + RKVDEC_REG_AXI_DDR_WDATA);
+ rkvdec_memcpy_toio(rkvdec->regs, regs,
+ MIN(sizeof(*regs), sizeof(u32) *
rkvdec->variant->num_regs));
}
#define RKVDEC_HEVC_MAX_DEPTH_IN_BYTES 2
@@ -784,8 +778,6 @@ static int rkvdec_hevc_run(struct rkvdec_ctx *ctx)
schedule_delayed_work(&rkvdec->watchdog_work, msecs_to_jiffies(2000));
- writel(0, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
- writel(0, rkvdec->regs + RKVDEC_REG_H264_ERR_E);
writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
b/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
index c627b6b6f53a..1af66c5f1c9b 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-regs.h
@@ -3,7 +3,12 @@
#ifndef RKVDEC_REGS_H_
#define RKVDEC_REGS_H_
-/* rkvcodec registers */
+#include <linux/types.h>
+
+/*
+ * REG_INTERRUPT is accessed via writel to enable the decoder after
+ * configuring it and clear interrupt strmd_error_status
+ */
#define RKVDEC_REG_INTERRUPT 0x004
#define RKVDEC_INTERRUPT_DEC_E BIT(0)
#define RKVDEC_CONFIG_DEC_CLK_GATE_E BIT(1)
@@ -30,198 +35,399 @@
#define RKVDEC_SOFTRESET_RDY BIT(22)
#define RKVDEC_WR_DDR_ALIGN_EN BIT(23)
-#define RKVDEC_REG_SYSCTRL 0x008
-#define RKVDEC_IN_ENDIAN BIT(0)
-#define RKVDEC_IN_SWAP32_E BIT(1)
-#define RKVDEC_IN_SWAP64_E BIT(2)
-#define RKVDEC_STR_ENDIAN BIT(3)
-#define RKVDEC_STR_SWAP32_E BIT(4)
-#define RKVDEC_STR_SWAP64_E BIT(5)
-#define RKVDEC_OUT_ENDIAN BIT(6)
-#define RKVDEC_OUT_SWAP32_E BIT(7)
-#define RKVDEC_OUT_CBCR_SWAP BIT(8)
-#define RKVDEC_RLC_MODE_DIRECT_WRITE BIT(10)
-#define RKVDEC_RLC_MODE BIT(11)
-#define RKVDEC_STRM_START_BIT(x) (((x) & 0x7f) << 12)
-#define RKVDEC_MODE(x) (((x) & 0x03) << 20)
-#define RKVDEC_MODE_HEVC 0
-#define RKVDEC_MODE_H264 1
-#define RKVDEC_MODE_VP9 2
-#define RKVDEC_RPS_MODE BIT(24)
-#define RKVDEC_STRM_MODE BIT(25)
-#define RKVDEC_H264_STRM_LASTPKT BIT(26)
-#define RKVDEC_H264_FIRSTSLICE_FLAG BIT(27)
-#define RKVDEC_H264_FRAME_ORSLICE BIT(28)
-#define RKVDEC_BUSPR_SLOT_DIS BIT(29)
-
-#define RKVDEC_REG_PICPAR 0x00C
-#define RKVDEC_Y_HOR_VIRSTRIDE(x) ((x) & 0x1ff)
-#define RKVDEC_SLICE_NUM_HIGHBIT BIT(11)
-#define RKVDEC_UV_HOR_VIRSTRIDE(x) (((x) & 0x1ff) << 12)
-#define RKVDEC_SLICE_NUM_LOWBITS(x) (((x) & 0x7ff) << 21)
-
-#define RKVDEC_REG_STRM_RLC_BASE 0x010
-
-#define RKVDEC_REG_STRM_LEN 0x014
-#define RKVDEC_STRM_LEN(x) ((x) & 0x7ffffff)
-
-#define RKVDEC_REG_CABACTBL_PROB_BASE 0x018
-#define RKVDEC_REG_DECOUT_BASE 0x01C
-
-#define RKVDEC_REG_Y_VIRSTRIDE 0x020
-#define RKVDEC_Y_VIRSTRIDE(x) ((x) & 0xfffff)
-
-#define RKVDEC_REG_YUV_VIRSTRIDE 0x024
-#define RKVDEC_YUV_VIRSTRIDE(x) ((x) & 0x1fffff)
-#define RKVDEC_REG_H264_BASE_REFER(i) (((i) * 0x04) + 0x028)
-
-#define RKVDEC_REG_H264_BASE_REFER15 0x0C0
-#define RKVDEC_FIELD_REF BIT(0)
-#define RKVDEC_TOPFIELD_USED_REF BIT(1)
-#define RKVDEC_BOTFIELD_USED_REF BIT(2)
-#define RKVDEC_COLMV_USED_FLAG_REF BIT(3)
-
-#define RKVDEC_REG_VP9_LAST_FRAME_BASE 0x02c
-#define RKVDEC_REG_VP9_GOLDEN_FRAME_BASE 0x030
-#define RKVDEC_REG_VP9_ALTREF_FRAME_BASE 0x034
-
-#define RKVDEC_REG_VP9_CPRHEADER_OFFSET 0x028
-#define RKVDEC_VP9_CPRHEADER_OFFSET(x) ((x) & 0xffff)
-
-#define RKVDEC_REG_VP9_REFERLAST_BASE 0x02C
-#define RKVDEC_REG_VP9_REFERGOLDEN_BASE 0x030
-#define RKVDEC_REG_VP9_REFERALFTER_BASE 0x034
-
-#define RKVDEC_REG_VP9COUNT_BASE 0x038
-#define RKVDEC_VP9COUNT_UPDATE_EN BIT(0)
-
-#define RKVDEC_REG_VP9_SEGIDLAST_BASE 0x03C
-#define RKVDEC_REG_VP9_SEGIDCUR_BASE 0x040
-#define RKVDEC_REG_VP9_FRAME_SIZE(i) ((i) * 0x04 + 0x044)
-#define RKVDEC_VP9_FRAMEWIDTH(x) (((x) & 0xffff) << 0)
-#define RKVDEC_VP9_FRAMEHEIGHT(x) (((x) & 0xffff) << 16)
-
-#define RKVDEC_VP9_SEGID_GRP(i) ((i) * 0x04 +
0x050)
-#define RKVDEC_SEGID_ABS_DELTA(x) ((x) & 0x1)
-#define RKVDEC_SEGID_FRAME_QP_DELTA_EN(x) (((x) & 0x1) << 1)
-#define RKVDEC_SEGID_FRAME_QP_DELTA(x) (((x) & 0x1ff) << 2)
-#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(x) (((x) & 0x1) << 11)
-#define RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(x) (((x) & 0x7f) << 12)
-#define RKVDEC_SEGID_REFERINFO_EN(x) (((x) & 0x1) << 19)
-#define RKVDEC_SEGID_REFERINFO(x) (((x) & 0x03) << 20)
-#define RKVDEC_SEGID_FRAME_SKIP_EN(x) (((x) & 0x1) << 22)
-
-#define RKVDEC_VP9_CPRHEADER_CONFIG 0x070
-#define RKVDEC_VP9_TX_MODE(x) ((x) & 0x07)
-#define RKVDEC_VP9_FRAME_REF_MODE(x) (((x) & 0x03) << 3)
-
-#define RKVDEC_VP9_REF_SCALE(i) ((i) * 0x04 +
0x074)
-#define RKVDEC_VP9_REF_HOR_SCALE(x) ((x) & 0xffff)
-#define RKVDEC_VP9_REF_VER_SCALE(x) (((x) & 0xffff) << 16)
-
-#define RKVDEC_VP9_REF_DELTAS_LASTFRAME 0x080
-#define RKVDEC_REF_DELTAS_LASTFRAME(pos, val) (((val) & 0x7f) <<
((pos) * 7))
-
-#define RKVDEC_VP9_INFO_LASTFRAME 0x084
-#define RKVDEC_MODE_DELTAS_LASTFRAME(pos, val) (((val) & 0x7f) <<
((pos) * 7))
-#define RKVDEC_SEG_EN_LASTFRAME BIT(16)
-#define RKVDEC_LAST_SHOW_FRAME BIT(17)
-#define RKVDEC_LAST_INTRA_ONLY BIT(18)
-#define RKVDEC_LAST_WIDHHEIGHT_EQCUR BIT(19)
-#define RKVDEC_COLOR_SPACE_LASTKEYFRAME(x) (((x) & 0x07) << 20)
-
-#define RKVDEC_VP9_INTERCMD_BASE 0x088
-
-#define RKVDEC_VP9_INTERCMD_NUM 0x08C
-#define RKVDEC_INTERCMD_NUM(x) ((x) & 0xffffff)
-
-#define RKVDEC_VP9_LASTTILE_SIZE 0x090
-#define RKVDEC_LASTTILE_SIZE(x) ((x) & 0xffffff)
-
-#define RKVDEC_VP9_HOR_VIRSTRIDE(i) ((i) * 0x04 + 0x094)
-#define RKVDEC_HOR_Y_VIRSTRIDE(x) ((x) & 0x1ff)
-#define RKVDEC_HOR_UV_VIRSTRIDE(x) (((x) & 0x1ff) << 16)
-
-#define RKVDEC_REG_H264_POC_REFER0(i) (((i) * 0x04) + 0x064)
-#define RKVDEC_REG_H264_POC_REFER1(i) (((i) * 0x04) + 0x0C4)
-#define RKVDEC_REG_H264_POC_REFER2(i) (((i) * 0x04) + 0x120)
-#define RKVDEC_POC_REFER(x) ((x) & 0xffffffff)
-
-#define RKVDEC_REG_CUR_POC0 0x0A0
-#define RKVDEC_REG_CUR_POC1 0x128
-#define RKVDEC_CUR_POC(x) ((x) & 0xffffffff)
-
-#define RKVDEC_REG_RLCWRITE_BASE 0x0A4
-#define RKVDEC_REG_PPS_BASE 0x0A8
-#define RKVDEC_REG_RPS_BASE 0x0AC
-
-#define RKVDEC_REG_STRMD_ERR_EN 0x0B0
-#define RKVDEC_STRMD_ERR_EN(x) ((x) & 0xffffffff)
-
-#define RKVDEC_REG_STRMD_ERR_STA 0x0B4
-#define RKVDEC_STRMD_ERR_STA(x) ((x) &
0xfffffff)
-#define RKVDEC_COLMV_ERR_REF_PICIDX(x) (((x) & 0x0f) << 28)
-
-#define RKVDEC_REG_STRMD_ERR_CTU 0x0B8
-#define RKVDEC_STRMD_ERR_CTU(x) ((x) & 0xff)
-#define RKVDEC_STRMD_ERR_CTU_YOFFSET(x) (((x) & 0xff)
<< 8)
-#define RKVDEC_STRMFIFO_SPACE2FULL(x) (((x) & 0x7f) << 16)
-#define RKVDEC_VP9_ERR_EN_CTU0 BIT(24)
-
-#define RKVDEC_REG_SAO_CTU_POS 0x0BC
-#define RKVDEC_SAOWR_XOFFSET(x) ((x) & 0x1ff)
-#define RKVDEC_SAOWR_YOFFSET(x) (((x) & 0x3ff)
<< 16)
-
-#define RKVDEC_VP9_LAST_FRAME_YSTRIDE 0x0C0
-#define RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE 0x0C4
-#define RKVDEC_VP9_ALTREF_FRAME_YSTRIDE 0x0C8
-#define RKVDEC_VP9_REF_YSTRIDE(x) (((x) & 0xfffff) << 0)
-
-#define RKVDEC_VP9_LAST_FRAME_YUVSTRIDE 0x0CC
-#define RKVDEC_VP9_REF_YUVSTRIDE(x) (((x) & 0x1fffff) << 0)
-
-#define RKVDEC_VP9_REF_COLMV_BASE 0x0D0
-
-#define RKVDEC_REG_PERFORMANCE_CYCLE 0x100
-#define RKVDEC_PERFORMANCE_CYCLE(x) ((x) & 0xffffffff)
-
-#define RKVDEC_REG_AXI_DDR_RDATA 0x104
-#define RKVDEC_AXI_DDR_RDATA(x) ((x) &
0xffffffff)
-
-#define RKVDEC_REG_AXI_DDR_WDATA 0x108
-#define RKVDEC_AXI_DDR_WDATA(x) ((x) &
0xffffffff)
-
-#define RKVDEC_REG_FPGADEBUG_RESET 0x10C
-#define RKVDEC_BUSIFD_RESETN BIT(0)
-#define RKVDEC_CABAC_RESETN BIT(1)
-#define RKVDEC_DEC_CTRL_RESETN BIT(2)
-#define RKVDEC_TRANSD_RESETN BIT(3)
-#define RKVDEC_INTRA_RESETN BIT(4)
-#define RKVDEC_INTER_RESETN BIT(5)
-#define RKVDEC_RECON_RESETN BIT(6)
-#define RKVDEC_FILER_RESETN BIT(7)
-
-#define RKVDEC_REG_PERFORMANCE_SEL 0x110
-#define RKVDEC_PERF_SEL_CNT0(x) ((x) & 0x3f)
-#define RKVDEC_PERF_SEL_CNT1(x) (((x) & 0x3f)
<< 8)
-#define RKVDEC_PERF_SEL_CNT2(x) (((x) & 0x3f)
<< 16)
-
-#define RKVDEC_REG_PERFORMANCE_CNT(i) ((i) * 0x04 + 0x114)
-#define RKVDEC_PERF_CNT(x) ((x) & 0xffffffff)
-
-#define RKVDEC_REG_H264_ERRINFO_BASE 0x12C
-
-#define RKVDEC_REG_H264_ERRINFO_NUM 0x130
-#define RKVDEC_SLICEDEC_NUM(x) ((x) & 0x3fff)
-#define RKVDEC_STRMD_DECT_ERR_FLAG BIT(15)
-#define RKVDEC_ERR_PKT_NUM(x) (((x) & 0x3fff) << 16)
-
-#define RKVDEC_REG_H264_ERR_E 0x134
-#define RKVDEC_H264_ERR_EN_HIGHBITS(x) ((x) & 0x3fffffff)
-
#define RKVDEC_REG_QOS_CTRL 0x18C
+/*
+ * Cache configuration is not covered in the range of the register struct
+ */
#define RKVDEC_REG_PREF_LUMA_CACHE_COMMAND 0x410
#define RKVDEC_REG_PREF_CHR_CACHE_COMMAND 0x450
+/*
+ * Define the mode values
+ */
+#define RKVDEC_MODE_HEVC 0
+#define RKVDEC_MODE_H264 1
+#define RKVDEC_MODE_VP9 2
+
+/* rkvcodec registers */
+struct rkvdec_common_regs {
+ struct rkvdec_id {
+ u32 minor_ver : 8;
+ u32 level : 1;
+ u32 dec_support : 3;
+ u32 profile : 1;
+ u32 reserved0 : 1;
+ u32 codec_flag : 1;
+ u32 reserved1 : 1;
+ u32 prod_num : 16;
+ } reg00;
+
+ struct rkvdec_int {
+ u32 dec_e : 1;
+ u32 dec_clkgate_e : 1;
+ u32 dec_e_strmd_clkgate_dis : 1;
+ u32 timeout_mode : 1;
+ u32 dec_irq_dis : 1;
+ u32 dec_timeout_e : 1;
+ u32 buf_empty_en : 1;
+ u32 stmerror_waitdecfifo_empty : 1;
+ u32 dec_irq : 1;
+ u32 dec_irq_raw : 1;
+ u32 reserved2 : 2;
+ u32 dec_rdy_sta : 1;
+ u32 dec_bus_sta : 1;
+ u32 dec_error_sta : 1;
+ u32 dec_timeout_sta : 1;
+ u32 dec_empty_sta : 1;
+ u32 colmv_ref_error_sta : 1;
+ u32 cabu_end_sta : 1;
+ u32 h264orvp9_error_mode : 1;
+ u32 softrst_en_p : 1;
+ u32 force_softreset_valid : 1;
+ u32 softreset_rdy : 1;
+ u32 wr_ddr_align_en : 1;
+ u32 scl_down_en : 1;
+ u32 allow_not_wr_unref_bframe : 1;
+ u32 reserved1 : 6;
+ } reg01;
+
+ struct rkvdec_sysctrl {
+ u32 in_endian : 1;
+ u32 in_swap32_e : 1;
+ u32 in_swap64_e : 1;
+ u32 str_endian : 1;
+ u32 str_swap32_e : 1;
+ u32 str_swap64_e : 1;
+ u32 out_endian : 1;
+ u32 out_swap32_e : 1;
+ u32 out_cbcr_swap : 1;
+ u32 reserved0 : 1;
+ u32 rlc_mode_direct_write : 1;
+ u32 rlc_mode : 1;
+ u32 strm_start_bit : 7;
+ u32 reserved1 : 1;
+ u32 dec_mode : 2;
+ u32 reserved2 : 2;
+ u32 rps_mode : 1;
+ u32 stream_mode : 1;
+ u32 stream_lastpacket : 1;
+ u32 firstslice_flag : 1;
+ u32 frame_orslice : 1;
+ u32 buspr_slot_disable : 1;
+ u32 colmv_mode : 1;
+ u32 ycacherd_prior : 1;
+ } reg02;
+
+ struct rkvdec_picpar {
+ u32 y_hor_virstride : 9;
+ u32 reserved : 2;
+ u32 slice_num_highbit : 1;
+ u32 uv_hor_virstride : 9;
+ u32 slice_num_lowbits : 11;
+ } reg03;
+
+ u32 strm_rlc_base;
+ u32 stream_len;
+ u32 cabactbl_base;
+ u32 decout_base;
+
+ struct rkvdec_y_virstride {
+ u32 y_virstride : 20;
+ u32 reserved0 : 12;
+ } reg08;
+
+ struct rkvdec_yuv_virstride {
+ u32 yuv_virstride : 21;
+ u32 reserved0 : 11;
+ } reg09;
+} __packed;
+
+struct ref_base {
+ u32 field_ref : 1;
+ u32 topfield_used_ref : 1;
+ u32 botfield_used_ref : 1;
+ u32 colmv_use_flag_ref : 1;
+ u32 base_addr : 28;
+};
+
+struct rkvdec_h26x_regs {
+ struct ref_base ref0_14_base[15];
+ u32 ref0_14_poc[15];
+
+ u32 cur_poc;
+ u32 rlcwrite_base;
+ u32 pps_base;
+ u32 rps_base;
+
+ u32 strmd_error_e;
+
+ struct {
+ u32 strmd_error_status : 28;
+ u32 colmv_error_ref_picidx : 4;
+ } reg45;
+
+ struct {
+ u32 strmd_error_ctu_xoffset : 8;
+ u32 strmd_error_ctu_yoffset : 8;
+ u32 streamfifo_space2full : 7;
+ u32 reserved0 : 1;
+ u32 vp9_error_ctu0_en : 1;
+ u32 reserved1 : 7;
+ } reg46;
+
+ struct {
+ u32 saowr_xoffet : 9;
+ u32 reserved0 : 7;
+ u32 saowr_yoffset : 10;
+ u32 reserved1 : 6;
+ } reg47;
+
+ struct ref_base ref15_base;
+
+ u32 ref15_29_poc[15];
+
+ u32 performance_cycle;
+ u32 axi_ddr_rdata;
+ u32 axi_ddr_wdata;
+
+ struct {
+ u32 busifd_resetn : 1;
+ u32 cabac_resetn : 1;
+ u32 dec_ctrl_resetn : 1;
+ u32 transd_resetn : 1;
+ u32 intra_resetn : 1;
+ u32 inter_resetn : 1;
+ u32 recon_resetn : 1;
+ u32 filer_resetn : 1;
+ u32 reserved0 : 24;
+ } reg67;
+
+ struct {
+ u32 perf_cnt0_sel : 6;
+ u32 reserved0 : 2;
+ u32 perf_cnt1_sel : 6;
+ u32 reserved1 : 2;
+ u32 perf_cnt2_sel : 6;
+ u32 reserved2 : 10;
+ } reg68;
+
+ u32 perf_cnt0;
+ u32 perf_cnt1;
+ u32 perf_cnt2;
+ u32 ref30_poc;
+ u32 ref31_poc;
+ u32 cur_poc1;
+ u32 errorinfo_base;
+
+ struct {
+ u32 slicedec_num : 14;
+ u32 reserved0 : 1;
+ u32 strmd_detect_error_flag : 1;
+ u32 error_packet_num : 14;
+ u32 reserved1 : 2;
+ } reg76;
+
+ struct {
+ u32 error_en_highbits : 30;
+ u32 strmd_error_slice_en : 1;
+ u32 strmd_error_frame_en : 1;
+ } reg77;
+
+ u32 colmv_cur_base;
+ u32 colmv_ref_base[16];
+ u32 scanlist_addr;
+ u32 reg96_sd_decout_base;
+ u32 sd_y_virstride;
+ u32 sd_hor_stride;
+ u32 qos_ctrl;
+ u32 perf[8];
+ u32 qos1;
+} __packed;
+
+struct rkvdec_vp9_regs {
+ struct cprheader_offset {
+ u32 cprheader_offset : 16;
+ u32 reserved : 16;
+ } reg10;
+
+ u32 refer_bases[3];
+ u32 count_base;
+ u32 segidlast_base;
+ u32 segidcur_base;
+
+ struct frame_sizes {
+ u32 framewidth : 16;
+ u32 frameheight : 16;
+ } reg17_19[3];
+
+ struct segid_grp {
+ u32 segid_abs_delta : 1;
+ u32 segid_frame_qp_delta_en : 1;
+ u32 segid_frame_qp_delta : 9;
+ u32 segid_frame_loopfilter_value_en : 1;
+ u32 segid_frame_loopfilter_value : 7;
+ u32 segid_referinfo_en : 1;
+ u32 segid_referinfo : 2;
+ u32 segid_frame_skip_en : 1;
+ u32 reserved : 9;
+ } reg20_27[8];
+
+ struct cprheader_config {
+ u32 tx_mode : 3;
+ u32 frame_reference_mode : 2;
+ u32 reserved : 27;
+ } reg28;
+
+ struct ref_scale {
+ u32 ref_hor_scale : 16;
+ u32 ref_ver_scale : 16;
+ } reg29_31[3];
+
+ struct ref_deltas_lastframe {
+ u32 ref_deltas_lastframe0 : 7;
+ u32 ref_deltas_lastframe1 : 7;
+ u32 ref_deltas_lastframe2 : 7;
+ u32 ref_deltas_lastframe3 : 7;
+ u32 reserved : 4;
+ } reg32;
+
+ struct info_lastframe {
+ u32 mode_deltas_lastframe0 : 7;
+ u32 mode_deltas_lastframe1 : 7;
+ u32 reserved0 : 2;
+ u32 segmentation_enable_lstframe : 1;
+ u32 last_show_frame : 1;
+ u32 last_intra_only : 1;
+ u32 last_widthheight_eqcur : 1;
+ u32 color_space_lastkeyframe : 3;
+ u32 reserved1 : 9;
+ } reg33;
+
+ u32 intercmd_base;
+
+ struct intercmd_num {
+ u32 intercmd_num : 24;
+ u32 reserved : 8;
+ } reg35;
+
+ struct lasttile_size {
+ u32 lasttile_size : 24;
+ u32 reserved : 8;
+ } reg36;
+
+ struct hor_virstride {
+ u32 y_hor_virstride : 9;
+ u32 reserved0 : 7;
+ u32 uv_hor_virstride : 9;
+ u32 reserved1 : 7;
+ } reg37_39[3];
+
+ u32 cur_poc;
+
+ struct rlcwrite_base {
+ u32 reserved : 3;
+ u32 rlcwrite_base : 29;
+ } reg41;
+
+ struct pps_base {
+ u32 reserved : 4;
+ u32 pps_base : 28;
+ } reg42;
+
+ struct rps_base {
+ u32 reserved : 4;
+ u32 rps_base : 28;
+ } reg43;
+
+ struct strmd_error_en {
+ u32 strmd_error_e : 28;
+ u32 reserved : 4;
+ } reg44;
+
+ u32 vp9_error_info0;
+
+ struct strmd_error_ctu {
+ u32 strmd_error_ctu_xoffset : 8;
+ u32 strmd_error_ctu_yoffset : 8;
+ u32 streamfifo_space2full : 7;
+ u32 reserved0 : 1;
+ u32 error_ctu0_en : 1;
+ u32 reserved1 : 7;
+ } reg46;
+
+ struct sao_ctu_position {
+ u32 saowr_xoffet : 9;
+ u32 reserved0 : 7;
+ u32 saowr_yoffset : 10;
+ u32 reserved1 : 6;
+ } reg47;
+
+ struct ystride {
+ u32 virstride : 20;
+ u32 reserved : 12;
+ } reg48_50[3];
+
+ struct lastref_yuvstride {
+ u32 lastref_yuv_virstride : 21;
+ u32 reserved : 11;
+ } reg51;
+
+ u32 refcolmv_base;
+
+ u32 reserved0[11];
+
+ u32 performance_cycle;
+ u32 axi_ddr_rdata;
+ u32 axi_ddr_wdata;
+
+ struct fpgadebug_reset {
+ u32 busifd_resetn : 1;
+ u32 cabac_resetn : 1;
+ u32 dec_ctrl_resetn : 1;
+ u32 transd_resetn : 1;
+ u32 intra_resetn : 1;
+ u32 inter_resetn : 1;
+ u32 recon_resetn : 1;
+ u32 filer_resetn : 1;
+ u32 reserved : 24;
+ } reg67;
+
+ struct performance_sel {
+ u32 perf_cnt0_sel : 6;
+ u32 reserved0 : 2;
+ u32 perf_cnt1_sel : 6;
+ u32 reserved1 : 2;
+ u32 perf_cnt2_sel : 6;
+ u32 reserved : 10;
+ } reg68;
+
+ u32 perf_cnt0;
+ u32 perf_cnt1;
+ u32 perf_cnt2;
+
+ u32 reserved1[3];
+
+ u32 vp9_error_info1;
+
+ struct error_ctu1 {
+ u32 vp9_error_ctu1_x : 6;
+ u32 reserved0 : 2;
+ u32 vp9_error_ctu1_y : 6;
+ u32 reserved1 : 1;
+ u32 vp9_error_ctu1_en : 1;
+ u32 reserved2 : 16;
+ } reg76;
+
+ u32 reserved2;
+} __packed;
+
+struct rkvdec_regs {
+ struct rkvdec_common_regs common;
+ union {
+ struct rkvdec_h26x_regs h26x;
+ struct rkvdec_vp9_regs vp9;
+ };
+} __packed;
+
#endif /* RKVDEC_REGS_H_ */
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
index b4bf01e839ef..ba51a7c2fe55 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
@@ -163,6 +163,7 @@ struct rkvdec_vp9_ctx {
struct v4l2_vp9_frame_context frame_context[4];
struct rkvdec_vp9_frame_info cur;
struct rkvdec_vp9_frame_info last;
+ struct rkvdec_regs regs;
};
static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
@@ -347,38 +348,6 @@ static void init_probs(struct rkvdec_ctx *ctx,
init_inter_probs(ctx, run);
}
-struct rkvdec_vp9_ref_reg {
- u32 reg_frm_size;
- u32 reg_hor_stride;
- u32 reg_y_stride;
- u32 reg_yuv_stride;
- u32 reg_ref_base;
-};
-
-static struct rkvdec_vp9_ref_reg ref_regs[] = {
- {
- .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(0),
- .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(0),
- .reg_y_stride = RKVDEC_VP9_LAST_FRAME_YSTRIDE,
- .reg_yuv_stride = RKVDEC_VP9_LAST_FRAME_YUVSTRIDE,
- .reg_ref_base = RKVDEC_REG_VP9_LAST_FRAME_BASE,
- },
- {
- .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(1),
- .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(1),
- .reg_y_stride = RKVDEC_VP9_GOLDEN_FRAME_YSTRIDE,
- .reg_yuv_stride = 0,
- .reg_ref_base = RKVDEC_REG_VP9_GOLDEN_FRAME_BASE,
- },
- {
- .reg_frm_size = RKVDEC_REG_VP9_FRAME_SIZE(2),
- .reg_hor_stride = RKVDEC_VP9_HOR_VIRSTRIDE(2),
- .reg_y_stride = RKVDEC_VP9_ALTREF_FRAME_YSTRIDE,
- .reg_yuv_stride = 0,
- .reg_ref_base = RKVDEC_REG_VP9_ALTREF_FRAME_BASE,
- }
-};
-
static struct rkvdec_decoded_buffer *
get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
{
@@ -412,18 +381,17 @@ static dma_addr_t get_mv_base_addr(struct
rkvdec_decoded_buffer *buf)
static void config_ref_registers(struct rkvdec_ctx *ctx,
const struct rkvdec_vp9_run *run,
struct rkvdec_decoded_buffer *ref_buf,
- struct rkvdec_vp9_ref_reg *ref_reg)
+ int i)
{
unsigned int aligned_pitch, aligned_height, y_len, yuv_len;
- struct rkvdec_dev *rkvdec = ctx->dev;
+ struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+ struct rkvdec_regs *regs = &vp9_ctx->regs;
aligned_height = round_up(ref_buf->vp9.height, 64);
- writel_relaxed(RKVDEC_VP9_FRAMEWIDTH(ref_buf->vp9.width) |
- RKVDEC_VP9_FRAMEHEIGHT(ref_buf->vp9.height),
- rkvdec->regs + ref_reg->reg_frm_size);
+ regs->vp9.reg17_19[i].frameheight = ref_buf->vp9.height;
+ regs->vp9.reg17_19[i].framewidth = ref_buf->vp9.width;
- writel_relaxed(vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf,
0),
- rkvdec->regs + ref_reg->reg_ref_base);
+ regs->vp9.refer_bases[i] =
vb2_dma_contig_plane_dma_addr(&ref_buf->base.vb.vb2_buf, 0);
if (&ref_buf->base.vb == run->base.bufs.dst)
return;
@@ -432,59 +400,50 @@ static void config_ref_registers(struct rkvdec_ctx *ctx,
y_len = aligned_height * aligned_pitch;
yuv_len = (y_len * 3) / 2;
- writel_relaxed(RKVDEC_HOR_Y_VIRSTRIDE(aligned_pitch / 16) |
- RKVDEC_HOR_UV_VIRSTRIDE(aligned_pitch / 16),
- rkvdec->regs + ref_reg->reg_hor_stride);
- writel_relaxed(RKVDEC_VP9_REF_YSTRIDE(y_len / 16),
- rkvdec->regs + ref_reg->reg_y_stride);
-
- if (!ref_reg->reg_yuv_stride)
- return;
+ regs->vp9.reg37_39[i].y_hor_virstride = aligned_pitch / 16;
+ regs->vp9.reg37_39[i].uv_hor_virstride = aligned_pitch / 16;
+ regs->vp9.reg48_50[i].virstride = y_len / 16;
- writel_relaxed(RKVDEC_VP9_REF_YUVSTRIDE(yuv_len / 16),
- rkvdec->regs + ref_reg->reg_yuv_stride);
+ if (!i)
+ regs->vp9.reg51.lastref_yuv_virstride = yuv_len / 16;
}
static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
{
struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
+ struct rkvdec_regs *regs = &vp9_ctx->regs;
const struct v4l2_vp9_segmentation *seg;
- struct rkvdec_dev *rkvdec = ctx->dev;
s16 feature_val;
int feature_id;
- u32 val = 0;
seg = vp9_ctx->last.valid ? &vp9_ctx->last.seg : &vp9_ctx->cur.seg;
feature_id = V4L2_VP9_SEG_LVL_ALT_Q;
if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
{
feature_val = seg->feature_data[segid][feature_id];
- val |= RKVDEC_SEGID_FRAME_QP_DELTA_EN(1) |
- RKVDEC_SEGID_FRAME_QP_DELTA(feature_val);
+ regs->vp9.reg20_27[segid].segid_frame_qp_delta_en = 1;
+ regs->vp9.reg20_27[segid].segid_frame_qp_delta = feature_val;
}
feature_id = V4L2_VP9_SEG_LVL_ALT_L;
if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
{
feature_val = seg->feature_data[segid][feature_id];
- val |= RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE_EN(1) |
- RKVDEC_SEGID_FRAME_LOOPFILTER_VALUE(feature_val);
+ regs->vp9.reg20_27[segid].segid_frame_loopfilter_value_en = 1;
+ regs->vp9.reg20_27[segid].segid_frame_loopfilter_value =
feature_val;
}
feature_id = V4L2_VP9_SEG_LVL_REF_FRAME;
if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
{
feature_val = seg->feature_data[segid][feature_id];
- val |= RKVDEC_SEGID_REFERINFO_EN(1) |
- RKVDEC_SEGID_REFERINFO(feature_val);
+ regs->vp9.reg20_27[segid].segid_referinfo_en = 1;
+ regs->vp9.reg20_27[segid].segid_referinfo = feature_val;
}
feature_id = V4L2_VP9_SEG_LVL_SKIP;
- if (v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id, segid))
- val |= RKVDEC_SEGID_FRAME_SKIP_EN(1);
-
- if (!segid &&
- (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE))
- val |= RKVDEC_SEGID_ABS_DELTA(1);
+ regs->vp9.reg20_27[segid].segid_frame_skip_en =
+ v4l2_vp9_seg_feat_enabled(seg->feature_enabled, feature_id,
segid);
- writel_relaxed(val, rkvdec->regs + RKVDEC_VP9_SEGID_GRP(segid));
+ regs->vp9.reg20_27[segid].segid_abs_delta = !segid &&
+ (seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
}
static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
@@ -521,7 +480,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
struct rkvdec_decoded_buffer *ref_bufs[3];
struct rkvdec_decoded_buffer *dst, *last, *mv_ref;
struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
- u32 val, last_frame_info = 0;
+ struct rkvdec_regs *regs = &vp9_ctx->regs;
const struct v4l2_vp9_segmentation *seg;
struct rkvdec_dev *rkvdec = ctx->dev;
dma_addr_t addr;
@@ -547,8 +506,7 @@ static void config_registers(struct rkvdec_ctx *ctx,
(V4L2_VP9_FRAME_FLAG_KEY_FRAME |
V4L2_VP9_FRAME_FLAG_INTRA_ONLY));
- writel_relaxed(RKVDEC_MODE(RKVDEC_MODE_VP9),
- rkvdec->regs + RKVDEC_REG_SYSCTRL);
+ regs->common.reg02.dec_mode = RKVDEC_MODE_VP9;
bit_depth = dec_params->bit_depth;
aligned_height = round_up(ctx->decoded_fmt.fmt.pix_mp.height, 64);
@@ -560,17 +518,14 @@ static void config_registers(struct rkvdec_ctx *ctx,
uv_len = y_len / 2;
yuv_len = y_len + uv_len;
- writel_relaxed(RKVDEC_Y_HOR_VIRSTRIDE(aligned_pitch / 16) |
- RKVDEC_UV_HOR_VIRSTRIDE(aligned_pitch / 16),
- rkvdec->regs + RKVDEC_REG_PICPAR);
- writel_relaxed(RKVDEC_Y_VIRSTRIDE(y_len / 16),
- rkvdec->regs + RKVDEC_REG_Y_VIRSTRIDE);
- writel_relaxed(RKVDEC_YUV_VIRSTRIDE(yuv_len / 16),
- rkvdec->regs + RKVDEC_REG_YUV_VIRSTRIDE);
+ regs->common.reg03.y_hor_virstride = aligned_pitch / 16;
+ regs->common.reg03.uv_hor_virstride = aligned_pitch / 16;
+ regs->common.reg08.y_virstride = y_len / 16;
+ regs->common.reg09.yuv_virstride = yuv_len / 16;
stream_len = vb2_get_plane_payload(&run->base.bufs.src->vb2_buf, 0);
- writel_relaxed(RKVDEC_STRM_LEN(stream_len),
- rkvdec->regs + RKVDEC_REG_STRM_LEN);
+
+ regs->common.stream_len = stream_len;
/*
* Reset count buffer, because decoder only output intra related syntax
@@ -588,14 +543,13 @@ static void config_registers(struct rkvdec_ctx *ctx,
vp9_ctx->cur.segmapid++;
for (i = 0; i < ARRAY_SIZE(ref_bufs); i++)
- config_ref_registers(ctx, run, ref_bufs[i], &ref_regs[i]);
+ config_ref_registers(ctx, run, ref_bufs[i], i);
for (i = 0; i < 8; i++)
config_seg_registers(ctx, i);
- writel_relaxed(RKVDEC_VP9_TX_MODE(vp9_ctx->cur.tx_mode) |
- RKVDEC_VP9_FRAME_REF_MODE(dec_params->reference_mode),
- rkvdec->regs + RKVDEC_VP9_CPRHEADER_CONFIG);
+ regs->vp9.reg28.tx_mode = vp9_ctx->cur.tx_mode;
+ regs->vp9.reg28.frame_reference_mode = dec_params->reference_mode;
if (!intra_only) {
const struct v4l2_vp9_loop_filter *lf;
@@ -606,46 +560,58 @@ static void config_registers(struct rkvdec_ctx *ctx,
else
lf = &vp9_ctx->cur.lf;
- val = 0;
for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) {
delta = lf->ref_deltas[i];
- val |= RKVDEC_REF_DELTAS_LASTFRAME(i, delta);
+ switch (i) {
+ case 0:
+ regs->vp9.reg32.ref_deltas_lastframe0 = delta;
+ break;
+ case 1:
+ regs->vp9.reg32.ref_deltas_lastframe1 = delta;
+ break;
+ case 2:
+ regs->vp9.reg32.ref_deltas_lastframe2 = delta;
+ break;
+ case 3:
+ regs->vp9.reg32.ref_deltas_lastframe3 = delta;
+ break;
+ }
}
- writel_relaxed(val,
- rkvdec->regs + RKVDEC_VP9_REF_DELTAS_LASTFRAME);
-
for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) {
delta = lf->mode_deltas[i];
- last_frame_info |= RKVDEC_MODE_DELTAS_LASTFRAME(i,
- delta);
+ switch (i) {
+ case 0:
+ regs->vp9.reg33.mode_deltas_lastframe0 = delta;
+ break;
+ case 1:
+ regs->vp9.reg33.mode_deltas_lastframe1 = delta;
+ break;
+ }
}
}
- if (vp9_ctx->last.valid && !intra_only &&
- vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED)
- last_frame_info |= RKVDEC_SEG_EN_LASTFRAME;
+ regs->vp9.reg33.segmentation_enable_lstframe =
+ vp9_ctx->last.valid && !intra_only &&
+ vp9_ctx->last.seg.flags & V4L2_VP9_SEGMENTATION_FLAG_ENABLED;
- if (vp9_ctx->last.valid &&
- vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME)
- last_frame_info |= RKVDEC_LAST_SHOW_FRAME;
+ regs->vp9.reg33.last_show_frame =
+ vp9_ctx->last.valid &&
+ vp9_ctx->last.flags & V4L2_VP9_FRAME_FLAG_SHOW_FRAME;
- if (vp9_ctx->last.valid &&
- vp9_ctx->last.flags &
- (V4L2_VP9_FRAME_FLAG_KEY_FRAME | V4L2_VP9_FRAME_FLAG_INTRA_ONLY))
- last_frame_info |= RKVDEC_LAST_INTRA_ONLY;
+ regs->vp9.reg33.last_intra_only =
+ vp9_ctx->last.valid &&
+ vp9_ctx->last.flags &
+ (V4L2_VP9_FRAME_FLAG_KEY_FRAME |
V4L2_VP9_FRAME_FLAG_INTRA_ONLY);
- if (vp9_ctx->last.valid &&
- last->vp9.width == dst->vp9.width &&
- last->vp9.height == dst->vp9.height)
- last_frame_info |= RKVDEC_LAST_WIDHHEIGHT_EQCUR;
+ regs->vp9.reg33.last_widthheight_eqcur =
+ vp9_ctx->last.valid &&
+ last->vp9.width == dst->vp9.width &&
+ last->vp9.height == dst->vp9.height;
- writel_relaxed(last_frame_info,
- rkvdec->regs + RKVDEC_VP9_INFO_LASTFRAME);
-
- writel_relaxed(stream_len - dec_params->compressed_header_size -
- dec_params->uncompressed_header_size,
- rkvdec->regs + RKVDEC_VP9_LASTTILE_SIZE);
+ regs->vp9.reg36.lasttile_size =
+ stream_len - dec_params->compressed_header_size -
+ dec_params->uncompressed_header_size;
for (i = 0; !intra_only && i < ARRAY_SIZE(ref_bufs); i++) {
unsigned int refw = ref_bufs[i]->vp9.width;
@@ -654,29 +620,28 @@ static void config_registers(struct rkvdec_ctx *ctx,
hscale = (refw << 14) / dst->vp9.width;
vscale = (refh << 14) / dst->vp9.height;
- writel_relaxed(RKVDEC_VP9_REF_HOR_SCALE(hscale) |
- RKVDEC_VP9_REF_VER_SCALE(vscale),
- rkvdec->regs + RKVDEC_VP9_REF_SCALE(i));
+
+ regs->vp9.reg29_31[i].ref_hor_scale = hscale;
+ regs->vp9.reg29_31[i].ref_ver_scale = vscale;
}
addr = vb2_dma_contig_plane_dma_addr(&dst->base.vb.vb2_buf, 0);
- writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_DECOUT_BASE);
+ regs->common.decout_base = addr;
addr = vb2_dma_contig_plane_dma_addr(&run->base.bufs.src->vb2_buf, 0);
- writel_relaxed(addr, rkvdec->regs + RKVDEC_REG_STRM_RLC_BASE);
- writel_relaxed(vp9_ctx->priv_tbl.dma +
- offsetof(struct rkvdec_vp9_priv_tbl, probs),
- rkvdec->regs + RKVDEC_REG_CABACTBL_PROB_BASE);
- writel_relaxed(vp9_ctx->count_tbl.dma,
- rkvdec->regs + RKVDEC_REG_VP9COUNT_BASE);
-
- writel_relaxed(vp9_ctx->priv_tbl.dma +
- offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
- (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid),
- rkvdec->regs + RKVDEC_REG_VP9_SEGIDCUR_BASE);
- writel_relaxed(vp9_ctx->priv_tbl.dma +
- offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
- (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid)),
- rkvdec->regs + RKVDEC_REG_VP9_SEGIDLAST_BASE);
+ regs->common.strm_rlc_base = addr;
+
+ regs->common.cabactbl_base = vp9_ctx->priv_tbl.dma +
+ offsetof(struct rkvdec_vp9_priv_tbl, probs);
+
+ regs->vp9.count_base = vp9_ctx->count_tbl.dma;
+
+ regs->vp9.segidlast_base = vp9_ctx->priv_tbl.dma +
+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * (!vp9_ctx->cur.segmapid));
+
+ regs->vp9.segidcur_base = vp9_ctx->priv_tbl.dma +
+ offsetof(struct rkvdec_vp9_priv_tbl, segmap) +
+ (RKVDEC_VP9_MAX_SEGMAP_SIZE * vp9_ctx->cur.segmapid);
if (!intra_only &&
!(dec_params->flags & V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT) &&
@@ -685,12 +650,15 @@ static void config_registers(struct rkvdec_ctx *ctx,
else
mv_ref = dst;
- writel_relaxed(get_mv_base_addr(mv_ref),
- rkvdec->regs + RKVDEC_VP9_REF_COLMV_BASE);
+ regs->vp9.refcolmv_base = get_mv_base_addr(mv_ref);
- writel_relaxed(ctx->decoded_fmt.fmt.pix_mp.width |
- (ctx->decoded_fmt.fmt.pix_mp.height << 16),
- rkvdec->regs + RKVDEC_REG_PERFORMANCE_CYCLE);
+ regs->vp9.performance_cycle = ctx->decoded_fmt.fmt.pix_mp.width |
+ (ctx->decoded_fmt.fmt.pix_mp.height << 16);
+
+ regs->vp9.reg44.strmd_error_e = 0xe;
+
+ rkvdec_memcpy_toio(rkvdec->regs, regs,
+ MIN(sizeof(*regs), sizeof(u32) *
rkvdec->variant->num_regs));
}
static int validate_dec_params(struct rkvdec_ctx *ctx,
@@ -823,8 +791,6 @@ static int rkvdec_vp9_run(struct rkvdec_ctx *ctx)
writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND);
writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND);
- writel(0xe, rkvdec->regs + RKVDEC_REG_STRMD_ERR_EN);
-
if (rkvdec->variant->quirks & RKVDEC_QUIRK_DISABLE_QOS)
rkvdec_quirks_disable_qos(ctx);
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
index 5af9aa5ab353..776149f871b0 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.c
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.c
@@ -914,6 +914,15 @@ void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx)
writel(reg, rkvdec->regs + RKVDEC_REG_QOS_CTRL);
}
+void rkvdec_memcpy_toio(void __iomem *dst, void *src, size_t len)
+{
+#ifdef CONFIG_ARM64
+ __iowrite32_copy(dst, src, len / 4);
+#else
+ memcpy_toio(dst, src, len);
+#endif
+}
+
static void rkvdec_device_run(void *priv)
{
struct rkvdec_ctx *ctx = priv;
@@ -1227,7 +1236,6 @@ static void rkvdec_watchdog_func(struct work_struct *work)
if (ctx) {
dev_err(rkvdec->dev, "Frame processing timed out!\n");
writel(RKVDEC_IRQ_DIS, rkvdec->regs + RKVDEC_REG_INTERRUPT);
- writel(0, rkvdec->regs + RKVDEC_REG_SYSCTRL);
rkvdec_job_finish(ctx, VB2_BUF_STATE_ERROR);
}
}
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec.h
b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
index 566e06fa2b1e..f35f6e80ea2e 100644
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec.h
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec.h
@@ -151,6 +151,7 @@ struct rkvdec_aux_buf {
void rkvdec_run_preamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
void rkvdec_run_postamble(struct rkvdec_ctx *ctx, struct rkvdec_run *run);
+void rkvdec_memcpy_toio(void __iomem *dst, void *src, size_t len);
void rkvdec_quirks_disable_qos(struct rkvdec_ctx *ctx);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]