Hi Kieran,

Thank you for the patch.

On Thursday, 3 May 2018 16:36:19 EEST Kieran Bingham wrote:
> Extended display list headers allow pre and post command lists to be
> executed by the VSP pipeline. This provides the base support for
> features such as AUTO_FLD (for interlaced support) and AUTO_DISP (for
> supporting continuous camera preview pipelines.
> 
> Signed-off-by: Kieran Bingham <kieran.bingham+rene...@ideasonboard.com>
> 
> ---
> 
> v2:
>  - remove __packed attributes
> ---
>  drivers/media/platform/vsp1/vsp1.h      |  1 +-
>  drivers/media/platform/vsp1/vsp1_dl.c   | 83 +++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_dl.h   | 29 ++++++++-
>  drivers/media/platform/vsp1/vsp1_drv.c  |  7 +-
>  drivers/media/platform/vsp1/vsp1_regs.h |  5 +-
>  5 files changed, 116 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/platform/vsp1/vsp1.h
> b/drivers/media/platform/vsp1/vsp1.h index f0d21cc8e9ab..56c62122a81a
> 100644
> --- a/drivers/media/platform/vsp1/vsp1.h
> +++ b/drivers/media/platform/vsp1/vsp1.h
> @@ -53,6 +53,7 @@ struct vsp1_uif;
>  #define VSP1_HAS_HGO         (1 << 7)
>  #define VSP1_HAS_HGT         (1 << 8)
>  #define VSP1_HAS_BRS         (1 << 9)
> +#define VSP1_HAS_EXT_DL              (1 << 10)
> 
>  struct vsp1_device_info {
>       u32 version;
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.c
> b/drivers/media/platform/vsp1/vsp1_dl.c index 56514cd51c51..b64d32535edc
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.c
> +++ b/drivers/media/platform/vsp1/vsp1_dl.c
> @@ -22,6 +22,9 @@
>  #define VSP1_DLH_INT_ENABLE          (1 << 1)
>  #define VSP1_DLH_AUTO_START          (1 << 0)
> 
> +#define VSP1_DLH_EXT_PRE_CMD_EXEC    (1 << 9)
> +#define VSP1_DLH_EXT_POST_CMD_EXEC   (1 << 8)
> +
>  struct vsp1_dl_header_list {
>       u32 num_bytes;
>       u32 addr;
> @@ -34,11 +37,34 @@ struct vsp1_dl_header {
>       u32 flags;
>  };
> 
> +struct vsp1_dl_ext_header {
> +     u32 reserved0;          /* alignment padding */
> +
> +     u16 pre_ext_cmd_qty;

Should this be called pre_ext_dl_num_cmd to match the datasheet ?

> +     u16 flags;

Aren't the flags supposed to come before the pre_ext_dl_num_cmd field ?

> +     u32 pre_ext_cmd_plist;

And pre_ext_dl_plist ?

> +
> +     u32 post_ext_cmd_qty;
> +     u32 post_ext_cmd_plist;

Similar comments for these variables.

> +};
> +
> +struct vsp1_dl_header_extended {
> +     struct vsp1_dl_header header;
> +     struct vsp1_dl_ext_header ext;
> +};
> +
>  struct vsp1_dl_entry {
>       u32 addr;
>       u32 data;
>  };
> 
> +struct vsp1_dl_ext_cmd_header {

Isn't this referred to in the datasheet as a body entry, not a header ? How 
about naming it vsp1_dl_ext_cmd_entry ? Or just vsp1_dl_ext_cmd (in which case 
the other structure that goes by the same name would need to be renamed) ?

> +     u32 cmd;
> +     u32 flags;
> +     u32 data;
> +     u32 reserved;

The datasheet documents this as two 64-bit fields, shouldn't we handle the 
structure the same way ?

> +};
> +
>  /**
>   * struct vsp1_dl_body - Display list body
>   * @list: entry in the display list list of bodies
> @@ -95,9 +121,12 @@ struct vsp1_dl_body_pool {
>   * @list: entry in the display list manager lists
>   * @dlm: the display list manager
>   * @header: display list header
> + * @extended: extended display list header. NULL for normal lists

Should we name this extension instead of extended ?

>   * @dma: DMA address for the header
>   * @body0: first display list body
>   * @bodies: list of extra display list bodies
> + * @pre_cmd: pre cmd to be issued through extended dl header
> + * @post_cmd: post cmd to be issued through extended dl header

I think you can spell command in full.

>   * @has_chain: if true, indicates that there's a partition chain
>   * @chain: entry in the display list partition chain
>   * @internal: whether the display list is used for internal purpose
> @@ -107,11 +136,15 @@ struct vsp1_dl_list {
>       struct vsp1_dl_manager *dlm;
> 
>       struct vsp1_dl_header *header;
> +     struct vsp1_dl_ext_header *extended;
>       dma_addr_t dma;
> 
>       struct vsp1_dl_body *body0;
>       struct list_head bodies;
> 
> +     struct vsp1_dl_ext_cmd *pre_cmd;
> +     struct vsp1_dl_ext_cmd *post_cmd;
> +
>       bool has_chain;
>       struct list_head chain;
> 
> @@ -496,6 +529,14 @@ int vsp1_dl_list_add_chain(struct vsp1_dl_list *head,
>       return 0;
>  }
> 
> +static void vsp1_dl_ext_cmd_fill_header(struct vsp1_dl_ext_cmd *cmd)

> +{
> +     cmd->cmds[0].cmd = cmd->cmd_opcode;
> +     cmd->cmds[0].flags = cmd->flags;
> +     cmd->cmds[0].data = cmd->data_dma;
> +     cmd->cmds[0].reserved = 0;
> +}
> +
>  static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last)
> {
>       struct vsp1_dl_manager *dlm = dl->dlm;
> @@ -548,6 +589,27 @@ static void vsp1_dl_list_fill_header(struct
> vsp1_dl_list *dl, bool is_last) */
>               dl->header->flags = VSP1_DLH_INT_ENABLE;
>       }
> +
> +     if (!dl->extended)
> +             return;
> +
> +     dl->extended->flags = 0;
> +
> +     if (dl->pre_cmd) {
> +             dl->extended->pre_ext_cmd_plist = dl->pre_cmd->cmd_dma;
> +             dl->extended->pre_ext_cmd_qty = dl->pre_cmd->num_cmds;
> +             dl->extended->flags |= VSP1_DLH_EXT_PRE_CMD_EXEC;
> +
> +             vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
> +     }
> +
> +     if (dl->post_cmd) {
> +             dl->extended->pre_ext_cmd_plist = dl->post_cmd->cmd_dma;
> +             dl->extended->pre_ext_cmd_qty = dl->post_cmd->num_cmds;
> +             dl->extended->flags |= VSP1_DLH_EXT_POST_CMD_EXEC;
> +
> +             vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
> +     }
>  }
> 
>  static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
> @@ -735,14 +797,20 @@ unsigned int vsp1_dlm_irq_frame_end(struct
> vsp1_dl_manager *dlm) }
> 
>  /* Hardware Setup */
> -void vsp1_dlm_setup(struct vsp1_device *vsp1)
> +void vsp1_dlm_setup(struct vsp1_device *vsp1, unsigned int index)
>  {
>       u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT)
> 
>                | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0
>                | VI6_DL_CTRL_DLE;
> 
> +     if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
> +             vsp1_write(vsp1, VI6_DL_EXT_CTRL(index),
> +                        (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT) |
> +                        VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT);
> +
>       vsp1_write(vsp1, VI6_DL_CTRL, ctrl);
> -     vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
> +     vsp1_write(vsp1, VI6_DL_SWAP(index), VI6_DL_SWAP_LWS |
> +                      ((index == 1) ? VI6_DL_SWAP_IND : 0));

Is this change needed ? If VI6_DL_SWAP_IND is not set in VI6_DL_SWAP(1), 
display list swap for WPF1 is supposed to be controlled by VI6_DL_SWAP(0) 
according to the datasheet.

If that's not the case and this change is needed, I would split support for 
VI6_DL_SWAP(n) to a separate patch, and moved it before 07/11.

>  }
> 
>  void vsp1_dlm_reset(struct vsp1_dl_manager *dlm)
> @@ -787,7 +855,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> vsp1_device *vsp1,
>        * fragmentation, with the header located right after the body in
>        * memory.
>        */
> -     header_size = ALIGN(sizeof(struct vsp1_dl_header), 8);
> +     header_size = vsp1_feature(vsp1, VSP1_HAS_EXT_DL) ?
> +                     sizeof(struct vsp1_dl_header_extended) :
> +                     sizeof(struct vsp1_dl_header);
> +
> +     header_size = ALIGN(header_size, 8);

We will have to improve header handling at some point. Not all headers require 
extensions.

>       dlm->pool = vsp1_dl_body_pool_create(vsp1, prealloc,
>                                            VSP1_DL_NUM_ENTRIES, header_size);
> @@ -803,6 +875,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> vsp1_device *vsp1, return NULL;
>               }
> 
> +             /* The extended header immediately follows the header */

s/ \*/. */

> +             if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
> +                     dl->extended = (void *)dl->header
> +                                  + sizeof(*dl->header);
> +
>               list_add_tail(&dl->list, &dlm->free);
>       }
> 
> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h
> b/drivers/media/platform/vsp1/vsp1_dl.h index 216bd23029dd..aa5f4adc6617
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.h
> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> @@ -20,7 +20,34 @@ struct vsp1_dl_manager;
>  #define VSP1_DL_FRAME_END_COMPLETED          BIT(0)
>  #define VSP1_DL_FRAME_END_INTERNAL           BIT(1)
> 
> -void vsp1_dlm_setup(struct vsp1_device *vsp1);
> +/**
> + * struct vsp1_dl_ext_cmd - Extended Display command
> + * @free: entry in the pool of free commands list
> + * @cmd_opcode: command type opcode

Maybe just opcode ?

> + * @flags: flags used by the command
> + * @cmds: array of command bodies for this extended cmd
> + * @num_cmds: quantity of commands in @cmds array
> + * @cmd_dma: DMA address of the command bodies

s/command bodies/commands body/ ?

> + * @data: memory allocation for command specific data
> + * @data_dma: DMA address for command specific data

s/command specific/command-specific/

> + * @data_size: size of the @data_dma memory in bytes

data_size is set but otherwise never used. Should we drop the field, or make 
use of it ?

> + */
> +struct vsp1_dl_ext_cmd {
> +     struct list_head free;
> +
> +     u8 cmd_opcode;
> +     u32 flags;
> +
> +     struct vsp1_dl_ext_cmd_header *cmds;
> +     unsigned int num_cmds;
> +     dma_addr_t cmd_dma;
> +
> +     void *data;
> +     dma_addr_t data_dma;
> +     size_t data_size;
> +};
> +
> +void vsp1_dlm_setup(struct vsp1_device *vsp1, unsigned int index);
> 
>  struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
>                                       unsigned int index,
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c
> b/drivers/media/platform/vsp1/vsp1_drv.c index 0fc388bf5a33..26a7b4d32e6c
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -545,7 +545,8 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
>       vsp1_write(vsp1, VI6_DPR_HGT_SMPPT, (7 << VI6_DPR_SMPPT_TGW_SHIFT) |
>                  (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT));
> 
> -     vsp1_dlm_setup(vsp1);
> +     for (i = 0; i < vsp1->info->wpf_count; ++i)
> +             vsp1_dlm_setup(vsp1, i);
> 
>       return 0;
>  }
> @@ -754,7 +755,7 @@ static const struct vsp1_device_info vsp1_device_infos[]
> = { .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
>               .model = "VSP2-D",
>               .gen = 3,
> -             .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP,
> +             .features = VSP1_HAS_BRU | VSP1_HAS_WPF_VFLIP | VSP1_HAS_EXT_DL,
>               .lif_count = 1,
>               .rpf_count = 5,
>               .uif_count = 1,
> @@ -774,7 +775,7 @@ static const struct vsp1_device_info vsp1_device_infos[]
> = { .version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
>               .model = "VSP2-DL",
>               .gen = 3,
> -             .features = VSP1_HAS_BRS | VSP1_HAS_BRU,
> +             .features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
>               .lif_count = 2,
>               .rpf_count = 5,
>               .uif_count = 2,
> diff --git a/drivers/media/platform/vsp1/vsp1_regs.h
> b/drivers/media/platform/vsp1/vsp1_regs.h index 0d249ff9f564..d054767570c1
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_regs.h
> +++ b/drivers/media/platform/vsp1/vsp1_regs.h
> @@ -67,12 +67,13 @@
> 
>  #define VI6_DL_HDR_ADDR(n)           (0x0104 + (n) * 4)
> 
> -#define VI6_DL_SWAP                  0x0114
> +#define VI6_DL_SWAP(n)                       (0x0114 + (n) * 56)
> +#define VI6_DL_SWAP_IND                      (1 << 31)
>  #define VI6_DL_SWAP_LWS                      (1 << 2)
>  #define VI6_DL_SWAP_WDS                      (1 << 1)
>  #define VI6_DL_SWAP_BTS                      (1 << 0)
> 
> -#define VI6_DL_EXT_CTRL                      0x011c
> +#define VI6_DL_EXT_CTRL(n)           (0x011c + (n) * 36)
>  #define VI6_DL_EXT_CTRL_NWE          (1 << 16)
>  #define VI6_DL_EXT_CTRL_POLINT_MASK  (0x3f << 8)
>  #define VI6_DL_EXT_CTRL_POLINT_SHIFT 8

-- 
Regards,

Laurent Pinchart



Reply via email to