[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