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+rene...@ideasonboard.com>

Thanks for adding the documentation, and the new name _oneshot() sounds
fine to me.


Reviewed-by: Kieran Bingham <kieran.bingham+rene...@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
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to