From: Sven Püschel Date: Wed, 20 May 2026 22:44:21 +0000 (+0200) Subject: media: rockchip: rga: reuse cmdbuf contents X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10e2141179fe480763d10b604d7e4f9c62e8ba76;p=thirdparty%2Fkernel%2Flinux.git media: rockchip: rga: reuse cmdbuf contents Reuse the command buffer contents instead of completely writing it for every frame. Therefore we only need to replace the source and destination addresses for each frame. This reduces the amount of CPU and memory operations done in each frame. A new cmdbuf_dirty flag notes if the cmdbuf has to be rewritten on the next frame. The initial idea of initializing the cmdbuf on streamon broke the ability to update controls while streaming (e.g. mirroring). Signed-off-by: Sven Püschel Reviewed-by: Nicolas Dufresne Signed-off-by: Nicolas Dufresne Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c index dac3cb6aa17d..567d39e58d33 100644 --- a/drivers/media/platform/rockchip/rga/rga-hw.c +++ b/drivers/media/platform/rockchip/rga/rga-hw.c @@ -417,8 +417,6 @@ static void rga_cmd_set(struct rga_ctx *ctx, { struct rockchip_rga *rga = ctx->rga; - memset(ctx->cmdbuf_virt, 0, RGA_CMDBUF_SIZE); - rga_cmd_set_src_addr(ctx, src->dma_desc_pa); /* * Due to hardware bug, @@ -427,11 +425,9 @@ static void rga_cmd_set(struct rga_ctx *ctx, rga_cmd_set_src1_addr(ctx, dst->dma_desc_pa); rga_cmd_set_dst_addr(ctx, dst->dma_desc_pa); - rga_cmd_set_mode(ctx); rga_cmd_set_src_info(ctx, &src->offset); rga_cmd_set_dst_info(ctx, &dst->offset); - rga_cmd_set_trans_info(ctx); rga_write(rga, RGA_CMD_BASE, ctx->cmdbuf_phy); @@ -440,6 +436,14 @@ static void rga_cmd_set(struct rga_ctx *ctx, PAGE_SIZE, DMA_BIDIRECTIONAL); } +static void rga_hw_setup_cmdbuf(struct rga_ctx *ctx) +{ + memset(ctx->cmdbuf_virt, 0, RGA_CMDBUF_SIZE); + + rga_cmd_set_mode(ctx); + rga_cmd_set_trans_info(ctx); +} + static void rga_hw_start(struct rockchip_rga *rga, struct rga_vb_buffer *src, struct rga_vb_buffer *dst) { @@ -582,6 +586,7 @@ const struct rga_hw rga2_hw = { .max_height = MAX_HEIGHT, .stride_alignment = 4, + .setup_cmdbuf = rga_hw_setup_cmdbuf, .start = rga_hw_start, .handle_irq = rga_handle_irq, .get_version = rga_get_version, diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index d080cb672740..394b14b9469d 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -38,6 +38,11 @@ static void device_run(void *prv) unsigned long flags; spin_lock_irqsave(&rga->ctrl_lock, flags); + if (ctx->cmdbuf_dirty) { + ctx->cmdbuf_dirty = false; + rga->hw->setup_cmdbuf(ctx); + } + spin_unlock_irqrestore(&rga->ctrl_lock, flags); rga->curr = ctx; @@ -47,8 +52,6 @@ static void device_run(void *prv) dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); rga->hw->start(rga, vb_to_rga(src), vb_to_rga(dst)); - - spin_unlock_irqrestore(&rga->ctrl_lock, flags); } static irqreturn_t rga_isr(int irq, void *prv) @@ -141,6 +144,7 @@ static int rga_s_ctrl(struct v4l2_ctrl *ctrl) ctx->fill_color = ctrl->val; break; } + ctx->cmdbuf_dirty = true; spin_unlock_irqrestore(&ctx->rga->ctrl_lock, flags); return 0; } @@ -228,6 +232,7 @@ static int rga_open(struct file *file) ret = -ENOMEM; goto rel_ctx; } + ctx->cmdbuf_dirty = true; ctx->rga = rga; /* Set default formats */ @@ -448,6 +453,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) frm->crop.height = pix_fmt->height; frm->pix = *pix_fmt; + ctx->cmdbuf_dirty = true; v4l2_dbg(debug, 1, &rga->v4l2_dev, "[%s] fmt - %p4cc %dx%d (stride %d, sizeimage %d)\n", @@ -564,6 +570,7 @@ static int vidioc_s_selection(struct file *file, void *priv, } f->crop = s->r; + ctx->cmdbuf_dirty = true; return ret; } diff --git a/drivers/media/platform/rockchip/rga/rga.h b/drivers/media/platform/rockchip/rga/rga.h index 38518146910a..5360f092fecf 100644 --- a/drivers/media/platform/rockchip/rga/rga.h +++ b/drivers/media/platform/rockchip/rga/rga.h @@ -55,6 +55,7 @@ struct rga_ctx { void *cmdbuf_virt; dma_addr_t cmdbuf_phy; + bool cmdbuf_dirty; int osequence; int csequence; @@ -152,6 +153,7 @@ struct rga_hw { u32 max_width, max_height; u8 stride_alignment; + void (*setup_cmdbuf)(struct rga_ctx *ctx); void (*start)(struct rockchip_rga *rga, struct rga_vb_buffer *src, struct rga_vb_buffer *dst); bool (*handle_irq)(struct rockchip_rga *rga);