[PATCH v5 07/19] media: vsp1: dl: Support one-shot entries in the display list
Kieran Bingham
kieran.bingham at ideasonboard.com
Thu Feb 21 13:16:47 UTC 2019
Hi Laurent,
On 21/02/2019 10:32, Laurent Pinchart wrote:
> One-shot entries are used as an alternative to committing a complete new
> display list when a couple of registers need to be written for one frame
> and then reset to another value for all subsequent frames. This will be
> used to implement writeback support that will need to enable writeback
> for the duration of a single frame.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas at ideasonboard.com>
Thanks for adding the documentation, and the new name _oneshot() sounds
fine to me.
Reviewed-by: Kieran Bingham <kieran.bingham+renesas at ideasonboard.com>
> ---
> drivers/media/platform/vsp1/vsp1_dl.c | 78 +++++++++++++++++++++++++++
> drivers/media/platform/vsp1/vsp1_dl.h | 3 ++
> 2 files changed, 81 insertions(+)
>
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c
> index 886b3a69d329..7b4d252bfde7 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.c
> +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> @@ -115,6 +115,12 @@ struct vsp1_dl_body {
>
> unsigned int num_entries;
> unsigned int max_entries;
> +
> + unsigned int num_patches;
> + struct {
> + struct vsp1_dl_entry *entry;
> + u32 data;
> + } patches[2];
> };
>
> /**
> @@ -361,6 +367,7 @@ void vsp1_dl_body_put(struct vsp1_dl_body *dlb)
> return;
>
> dlb->num_entries = 0;
> + dlb->num_patches = 0;
>
> spin_lock_irqsave(&dlb->pool->lock, flags);
> list_add_tail(&dlb->free, &dlb->pool->free);
> @@ -388,6 +395,47 @@ void vsp1_dl_body_write(struct vsp1_dl_body *dlb, u32 reg, u32 data)
> dlb->num_entries++;
> }
>
> +/**
> + * vsp1_dl_body_write_oneshot - Write a register to a display list body for a
> + * single frame
> + * @dlb: The body
> + * @reg: The register address
> + * @value: The register value
> + * @reset_value: The value to reset the register to at the next vblank
> + *
> + * Display lists in continuous mode are re-used by the hardware for successive
> + * frames until a new display list is committed. Changing the VSP configuration
> + * normally requires creating and committing a new display list. This function
> + * offers an alternative race-free way by writing a @value to the @register in
> + * the display list body for a single frame, specifying in @reset_value the
> + * value to reset the register to one vblank after the display list is
> + * committed.
> + *
> + * The maximum number of one-shot entries is limited to 2 per display list body,
> + * and one-shot entries are counted in the total number of entries specified
> + * when the body is allocated by vsp1_dl_body_alloc().
> + */
> +void vsp1_dl_body_write_oneshot(struct vsp1_dl_body *dlb, u32 reg, u32 value,
> + u32 reset_value)
> +{
> + if (WARN_ONCE(dlb->num_entries >= dlb->max_entries,
> + "DLB size exceeded (max %u)", dlb->max_entries))
> + return;
> +
> + if (WARN_ONCE(dlb->num_patches >= ARRAY_SIZE(dlb->patches),
> + "DLB patches size exceeded (max %zu)",
> + ARRAY_SIZE(dlb->patches)))
> + return;
> +
> + dlb->patches[dlb->num_patches].entry = &dlb->entries[dlb->num_entries];
> + dlb->patches[dlb->num_patches].data = reset_value;
> + dlb->num_patches++;
> +
> + dlb->entries[dlb->num_entries].addr = reg;
> + dlb->entries[dlb->num_entries].data = value;
> + dlb->num_entries++;
> +}
> +
> /* -----------------------------------------------------------------------------
> * Display List Extended Command Management
> */
> @@ -652,6 +700,7 @@ static void __vsp1_dl_list_put(struct vsp1_dl_list *dl)
> * has at least one body, thus we reinitialise the entries list.
> */
> dl->body0->num_entries = 0;
> + dl->body0->num_patches = 0;
>
> list_add_tail(&dl->list, &dl->dlm->free);
> }
> @@ -930,6 +979,35 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags)
> * Display List Manager
> */
>
> +/**
> + * vsp1_dlm_irq_display_start - Display list handler for the display start
> + * interrupt
> + * @dlm: the display list manager
> + *
> + * Apply all one-shot patches registered for the active display list.
> + */
> +void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm)
> +{
> + struct vsp1_dl_body *dlb;
> + struct vsp1_dl_list *dl;
> + unsigned int i;
> +
> + spin_lock(&dlm->lock);
> +
> + dl = dlm->active;
> + if (!dl)
> + goto done;
> +
> + list_for_each_entry(dlb, &dl->bodies, list) {
> + for (i = 0; i < dlb->num_patches; ++i)
> + dlb->patches[i].entry->data = dlb->patches[i].data;
> + dlb->num_patches = 0;
> + }
> +
> +done:
> + spin_unlock(&dlm->lock);
> +}
> +
> /**
> * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt
> * @dlm: the display list manager
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h
> index e0fdb145e6ed..f845607abc4c 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.h
> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> @@ -54,6 +54,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
> unsigned int prealloc);
> void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm);
> void vsp1_dlm_reset(struct vsp1_dl_manager *dlm);
> +void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm);
> unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm);
> struct vsp1_dl_body *vsp1_dlm_dl_body_get(struct vsp1_dl_manager *dlm);
>
> @@ -71,6 +72,8 @@ struct vsp1_dl_body *vsp1_dl_body_get(struct vsp1_dl_body_pool *pool);
> void vsp1_dl_body_put(struct vsp1_dl_body *dlb);
>
> void vsp1_dl_body_write(struct vsp1_dl_body *dlb, u32 reg, u32 data);
> +void vsp1_dl_body_write_oneshot(struct vsp1_dl_body *dlb, u32 reg, u32 value,
> + u32 reset_value);
> int vsp1_dl_list_add_body(struct vsp1_dl_list *dl, struct vsp1_dl_body *dlb);
> int vsp1_dl_list_add_chain(struct vsp1_dl_list *head, struct vsp1_dl_list *dl);
>
>
--
Regards
--
Kieran
More information about the dri-devel
mailing list