On Thu May 21 00:44:21 2026 +0200, Sven Püschel wrote:
> 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 <[email protected]>
> Reviewed-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Nicolas Dufresne <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/platform/rockchip/rga/rga-hw.c | 13 +++++++++----
 drivers/media/platform/rockchip/rga/rga.c    | 11 +++++++++--
 drivers/media/platform/rockchip/rga/rga.h    |  2 ++
 3 files changed, 20 insertions(+), 6 deletions(-)

---

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);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to