On Wed Feb 11 10:57:11 2026 +0100, Jacopo Mondi wrote:
> Buffers are programmed into slots in queueing order.
>
> When returning pending buffers we can't simply start from the first slot
> but we should actually iterate slots starting from the one is use. The
> rzg3e_cru_irq() handler already uses 'active_slot', make rzg2l_cru_irq()
> use it as well to know where to start iterating from.
>
> As the pattern of iterating over slots in order will be used for slots
> programming in the next patches, provide an helper macro to do that.
>
> While at it, rename return_unused_buffers() to rzg2l_cru_return_buffers().
>
> Signed-off-by: Jacopo Mondi <[email protected]>
> Tested-by: Tommaso Merciai <[email protected]>
> Reviewed-by: Daniel Scally <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
.../media/platform/renesas/rzg2l-cru/rzg2l-video.c | 68 +++++++++++++++-------
1 file changed, 47 insertions(+), 21 deletions(-)
---
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
index b02940369a18..715628878b90 100644
--- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
+++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c
@@ -42,6 +42,24 @@ struct rzg2l_cru_buffer {
#define to_buf_list(vb2_buffer) \
(&container_of(vb2_buffer, struct rzg2l_cru_buffer, vb)->list)
+/*
+ * The CRU hardware cycles over its slots when transferring frames. All drivers
+ * structure that contains programming data for the slots, such as the memory
+ * destination addresses have to be iterated as they were circular buffers.
+ *
+ * Provide here utilities to iterate over slots and the associated data.
+ */
+static inline unsigned int rzg2l_cru_slot_next(struct rzg2l_cru_dev *cru,
+ unsigned int slot)
+{
+ return (slot + 1) % cru->num_buf;
+}
+
+/* Start cycling on cru slots from the one after 'start'. */
+#define for_each_cru_slot_from(cru, slot, start) \
+ for ((slot) = rzg2l_cru_slot_next((cru), (start));
\
+ (slot) != (start); (slot) = rzg2l_cru_slot_next((cru), (slot)))
+
/*
-----------------------------------------------------------------------------
* DMA operations
*/
@@ -105,28 +123,36 @@ __rzg2l_cru_read_constant(struct rzg2l_cru_dev *cru, u32
offset)
__rzg2l_cru_read_constant(cru, offset) : \
__rzg2l_cru_read(cru, offset))
-static void return_unused_buffers(struct rzg2l_cru_dev *cru,
- enum vb2_buffer_state state)
+static void rzg2l_cru_return_buffers(struct rzg2l_cru_dev *cru,
+ enum vb2_buffer_state state)
{
struct rzg2l_cru_buffer *buf, *node;
- unsigned int i;
scoped_guard(spinlock_irq, &cru->hw_lock) {
- for (i = 0; i < cru->num_buf; i++) {
- if (cru->queue_buf[i]) {
- vb2_buffer_done(&cru->queue_buf[i]->vb2_buf,
- state);
- cru->queue_buf[i] = NULL;
- }
+ /* Return the buffer in progress first, if not completed yet. */
+ unsigned int slot = cru->active_slot;
+
+ if (cru->queue_buf[slot]) {
+ vb2_buffer_done(&cru->queue_buf[slot]->vb2_buf, state);
+ cru->queue_buf[slot] = NULL;
}
- }
- scoped_guard(spinlock_irq, &cru->qlock) {
- list_for_each_entry_safe(buf, node, &cru->buf_list, list) {
- vb2_buffer_done(&buf->vb.vb2_buf, state);
- list_del(&buf->list);
+ /* Return all the pending buffers after the active one. */
+ for_each_cru_slot_from(cru, slot, cru->active_slot) {
+ if (!cru->queue_buf[slot])
+ continue;
+
+ vb2_buffer_done(&cru->queue_buf[slot]->vb2_buf, state);
+ cru->queue_buf[slot] = NULL;
}
}
+
+ guard(spinlock_irq)(&cru->qlock);
+
+ list_for_each_entry_safe(buf, node, &cru->buf_list, list) {
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
+ list_del(&buf->list);
+ }
}
static int rzg2l_cru_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
@@ -588,16 +614,16 @@ irqreturn_t rzg2l_cru_irq(int irq, void *data)
/* Prepare for capture and update state */
amnmbs = rzg2l_cru_read(cru, AMnMBS);
- slot = amnmbs & AMnMBS_MBSTS;
+ cru->active_slot = amnmbs & AMnMBS_MBSTS;
/*
* AMnMBS.MBSTS indicates the destination of Memory Bank (MB).
* Recalculate to get the current transfer complete MB.
*/
- if (slot == 0)
+ if (cru->active_slot == 0)
slot = cru->num_buf - 1;
else
- slot--;
+ slot = cru->active_slot - 1;
/*
* To hand buffers back in a known order to userspace start
@@ -666,7 +692,7 @@ irqreturn_t rzg3e_cru_irq(int irq, void *data)
}
slot = cru->active_slot;
- cru->active_slot = (cru->active_slot + 1) % cru->num_buf;
+ cru->active_slot = rzg2l_cru_slot_next(cru, cru->active_slot);
dev_dbg(cru->dev, "Current written slot: %d\n", slot);
cru->buf_addr[slot] = 0;
@@ -737,7 +763,7 @@ static int rzg2l_cru_start_streaming_vq(struct vb2_queue
*vq, unsigned int count
cru->scratch = dma_alloc_coherent(cru->dev, cru->format.sizeimage,
&cru->scratch_phys, GFP_KERNEL);
if (!cru->scratch) {
- return_unused_buffers(cru, VB2_BUF_STATE_QUEUED);
+ rzg2l_cru_return_buffers(cru, VB2_BUF_STATE_QUEUED);
dev_err(cru->dev, "Failed to allocate scratch buffer\n");
ret = -ENOMEM;
goto assert_presetn;
@@ -748,7 +774,7 @@ static int rzg2l_cru_start_streaming_vq(struct vb2_queue
*vq, unsigned int count
ret = rzg2l_cru_set_stream(cru, 1);
if (ret) {
- return_unused_buffers(cru, VB2_BUF_STATE_QUEUED);
+ rzg2l_cru_return_buffers(cru, VB2_BUF_STATE_QUEUED);
goto out;
}
@@ -785,7 +811,7 @@ static void rzg2l_cru_stop_streaming_vq(struct vb2_queue
*vq)
dma_free_coherent(cru->dev, cru->format.sizeimage,
cru->scratch, cru->scratch_phys);
- return_unused_buffers(cru, VB2_BUF_STATE_ERROR);
+ rzg2l_cru_return_buffers(cru, VB2_BUF_STATE_ERROR);
reset_control_assert(cru->presetn);
clk_disable_unprepare(cru->vclk);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]