diff mbox

[v5,08/11] media: vsp1: Add support for extended display list headers

Message ID 4c12a88003d585ecc36054a6492357fdd4565d40.1531857988.git-series.kieran.bingham+renesas@ideasonboard.com (mailing list archive)
State Not Applicable
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Kieran Bingham July 17, 2018, 8:35 p.m. UTC
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>

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

---

v2:
 - remove __packed attributes

v5:
 - Rename vsp1_dl_ext_header field names
 - Rename @extended -> @extension
 - Remove unnecessary VI6_DL_SWAP changes
 - Rename @cmd_opcode -> @opcode
 - Drop unused @data_size field
 - Move iteration of WPF's inside vsp1_dlm_setup
 - Rename vsp1_dl_ext_cmd_header -> vsp1_pre_ext_dl_body
 - Rename vsp1_pre_ext_dl_body->cmd to vsp1_pre_ext_dl_body->opcode
 - Rename vsp1_dl_ext_header->reserved0 to vsp1_dl_ext_header->padding
 - vsp1_pre_ext_dl_body: Rename 'data' to 'address_set'
 - vsp1_pre_ext_dl_body: Add struct documentation
 - Document ordering of 16bit accesses for flags in vsp1_dl_ext_header

 drivers/media/platform/vsp1/vsp1.h      |   1 +-
 drivers/media/platform/vsp1/vsp1_dl.c   | 104 ++++++++++++++++++++++++-
 drivers/media/platform/vsp1/vsp1_dl.h   |  25 ++++++-
 drivers/media/platform/vsp1/vsp1_drv.c  |   4 +-
 drivers/media/platform/vsp1/vsp1_regs.h |   2 +-
 5 files changed, 132 insertions(+), 4 deletions(-)

Comments

Laurent Pinchart Aug. 2, 2018, 2:39 p.m. UTC | #1
Hi Kieran,

Thank you for the patch.

On Tuesday, 17 July 2018 23:35:50 EEST Kieran Bingham wrote:
> From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> 
> 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+renesas@ideasonboard.com>
> 
> ---
> 
> v2:
>  - remove __packed attributes
> 
> v5:
>  - Rename vsp1_dl_ext_header field names
>  - Rename @extended -> @extension
>  - Remove unnecessary VI6_DL_SWAP changes
>  - Rename @cmd_opcode -> @opcode
>  - Drop unused @data_size field
>  - Move iteration of WPF's inside vsp1_dlm_setup
>  - Rename vsp1_dl_ext_cmd_header -> vsp1_pre_ext_dl_body
>  - Rename vsp1_pre_ext_dl_body->cmd to vsp1_pre_ext_dl_body->opcode
>  - Rename vsp1_dl_ext_header->reserved0 to vsp1_dl_ext_header->padding
>  - vsp1_pre_ext_dl_body: Rename 'data' to 'address_set'
>  - vsp1_pre_ext_dl_body: Add struct documentation
>  - Document ordering of 16bit accesses for flags in vsp1_dl_ext_header
> 
>  drivers/media/platform/vsp1/vsp1.h      |   1 +-
>  drivers/media/platform/vsp1/vsp1_dl.c   | 104 ++++++++++++++++++++++++-
>  drivers/media/platform/vsp1/vsp1_dl.h   |  25 ++++++-
>  drivers/media/platform/vsp1/vsp1_drv.c  |   4 +-
>  drivers/media/platform/vsp1/vsp1_regs.h |   2 +-
>  5 files changed, 132 insertions(+), 4 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 90e0a11c29b5..2fffe977aa35
> 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,12 +37,59 @@ struct vsp1_dl_header {
>  	u32 flags;
>  };
> 
> +/**
> + * struct vsp1_dl_ext_header - Extended display list header
> + * @padding: padding zero bytes for alignment
> + * @pre_ext_dl_num_cmd: number of pre-extended command bodies to parse
> + * @flags: enables or disables execution of the pre and post command
> + * @pre_ext_dl_plist: start address of pre-extended display list bodies
> + * @post_ext_dl_num_cmd: number of post-extended command bodies to parse
> + * @post_ext_dl_plist: start address of post-extended display list bodies
> + */
> +struct vsp1_dl_ext_header {
> +	u32 padding;
> +
> +	/*
> +	 * The datasheet represents flags as stored before pre_ext_dl_num_cmd,
> +	 * expecting 32-bit accesses. The flags are appropriate to the whole
> +	 * header, not just the pre_ext command, and thus warrant being
> +	 * separated out. Due to byte ordering, and representing as 16 bit
> +	 * values here, the flags must be positioned after the
> +	 * pre_ext_dl_num_cmd.
> +	 */
> +	u16 pre_ext_dl_num_cmd;
> +	u16 flags;
> +	u32 pre_ext_dl_plist;
> +
> +	u32 post_ext_dl_num_cmd;
> +	u32 post_ext_dl_plist;
> +};
> +
> +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_pre_ext_dl_body - Pre Extended Display List Body
> + * @opcode: Extended display list command operation code
> + * @flags: Pre-extended command flags. These are specific to each command
> + * @address_set: Source address set pointer. Must have 16 byte alignment

s/byte/bytes/

> + * @reserved: Zero bits for alignment.
> + */
> +struct vsp1_pre_ext_dl_body {
> +	u32 opcode;
> +	u32 flags;
> +	u32 address_set;
> +	u32 reserved;
> +};
> +
> +/**
>   * struct vsp1_dl_body - Display list body
>   * @list: entry in the display list list of bodies
>   * @free: entry in the pool free body list
> @@ -95,9 +145,12 @@ struct vsp1_dl_body_pool {
>   * @list: entry in the display list manager lists
>   * @dlm: the display list manager
>   * @header: display list header
> + * @extension: extended display list header. NULL for normal lists
>   * @dma: DMA address for the header
>   * @body0: first display list body
>   * @bodies: list of extra display list bodies
> + * @pre_cmd: pre command to be issued through extended dl header
> + * @post_cmd: post command to be issued through extended dl header
>   * @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 +160,15 @@ struct vsp1_dl_list {
>  	struct vsp1_dl_manager *dlm;
> 
>  	struct vsp1_dl_header *header;
> +	struct vsp1_dl_ext_header *extension;
>  	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;
> 
> @@ -495,6 +552,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].opcode = cmd->opcode;
> +	cmd->cmds[0].flags = cmd->flags;
> +	cmd->cmds[0].address_set = 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;
> @@ -547,6 +612,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->extension)
> +		return;
> +
> +	dl->extension->flags = 0;
> +
> +	if (dl->pre_cmd) {
> +		dl->extension->pre_ext_dl_plist = dl->pre_cmd->cmd_dma;
> +		dl->extension->pre_ext_dl_num_cmd = dl->pre_cmd->num_cmds;
> +		dl->extension->flags |= VSP1_DLH_EXT_PRE_CMD_EXEC;
> +
> +		vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
> +	}
> +
> +	if (dl->post_cmd) {
> +		dl->extension->post_ext_dl_plist = dl->post_cmd->cmd_dma;
> +		dl->extension->post_ext_dl_num_cmd = dl->post_cmd->num_cmds;
> +		dl->extension->flags |= VSP1_DLH_EXT_POST_CMD_EXEC;
> +
> +		vsp1_dl_ext_cmd_fill_header(dl->post_cmd);
> +	}
>  }
> 
>  static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
> @@ -736,9 +822,16 @@ unsigned int vsp1_dlm_irq_frame_end(struct
> vsp1_dl_manager *dlm) /* Hardware Setup */
>  void vsp1_dlm_setup(struct vsp1_device *vsp1)
>  {
> +	unsigned int i;
>  	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;
> +	u32 ext_dl = (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT) |
> +		      VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT;

To match the style of the file, can you move the trailing | under the = ?

> +
> +	if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
> +		for (i = 0; i < vsp1->info->wpf_count; ++i)
> +			vsp1_write(vsp1, VI6_DL_EXT_CTRL(i), ext_dl);

And add {} to the if ?

With these small updates,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

If there's no other issue with v5 that would require a v6, I'll fix this when 
applying.

>  	vsp1_write(vsp1, VI6_DL_CTRL, ctrl);
>  	vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
> @@ -792,7 +885,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> vsp1_device *vsp1, * memory. An extra body is allocated on top of the
> prealloc to account * for the cached body used by the vsp1_pipeline object.
>  	 */
> -	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);
> 
>  	dlm->pool = vsp1_dl_body_pool_create(vsp1, prealloc + 1,
>  					     VSP1_DL_NUM_ENTRIES, header_size);
> @@ -808,6 +905,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
> vsp1_device *vsp1, return NULL;
>  		}
> 
> +		/* The extended header immediately follows the header. */
> +		if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
> +			dl->extension = (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 7dba0469c92e..afefd5bfa136
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_dl.h
> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
> @@ -20,6 +20,31 @@ struct vsp1_dl_manager;
>  #define VSP1_DL_FRAME_END_COMPLETED		BIT(0)
>  #define VSP1_DL_FRAME_END_INTERNAL		BIT(1)
> 
> +/**
> + * struct vsp1_dl_ext_cmd - Extended Display command
> + * @free: entry in the pool of free commands list
> + * @opcode: command type 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 body
> + * @data: memory allocation for command-specific data
> + * @data_dma: DMA address for command-specific data
> + */
> +struct vsp1_dl_ext_cmd {
> +	struct list_head free;
> +
> +	u8 opcode;
> +	u32 flags;
> +
> +	struct vsp1_pre_ext_dl_body *cmds;
> +	unsigned int num_cmds;
> +	dma_addr_t cmd_dma;
> +
> +	void *data;
> +	dma_addr_t data_dma;
> +};
> +
>  void vsp1_dlm_setup(struct vsp1_device *vsp1);
> 
>  struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c
> b/drivers/media/platform/vsp1/vsp1_drv.c index 3367c2ba990d..b6619c9c18bb
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_drv.c
> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
> @@ -754,7 +754,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 +774,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..5ea9f9070cf3
> 100644
> --- a/drivers/media/platform/vsp1/vsp1_regs.h
> +++ b/drivers/media/platform/vsp1/vsp1_regs.h
> @@ -72,7 +72,7 @@
>  #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
Kieran Bingham Aug. 3, 2018, 9:47 a.m. UTC | #2
Hi Laurent,

On 02/08/18 15:39, Laurent Pinchart wrote:
> Hi Kieran,
> 
> Thank you for the patch.

Thank you for (hopefully the last) review on this series :)



> On Tuesday, 17 July 2018 23:35:50 EEST Kieran Bingham wrote:
>> From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>>
>> 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+renesas@ideasonboard.com>
>>
>> ---
>>
>> v2:
>>  - remove __packed attributes
>>
>> v5:
>>  - Rename vsp1_dl_ext_header field names
>>  - Rename @extended -> @extension
>>  - Remove unnecessary VI6_DL_SWAP changes
>>  - Rename @cmd_opcode -> @opcode
>>  - Drop unused @data_size field
>>  - Move iteration of WPF's inside vsp1_dlm_setup
>>  - Rename vsp1_dl_ext_cmd_header -> vsp1_pre_ext_dl_body
>>  - Rename vsp1_pre_ext_dl_body->cmd to vsp1_pre_ext_dl_body->opcode
>>  - Rename vsp1_dl_ext_header->reserved0 to vsp1_dl_ext_header->padding
>>  - vsp1_pre_ext_dl_body: Rename 'data' to 'address_set'
>>  - vsp1_pre_ext_dl_body: Add struct documentation
>>  - Document ordering of 16bit accesses for flags in vsp1_dl_ext_header
>>
>>  drivers/media/platform/vsp1/vsp1.h      |   1 +-
>>  drivers/media/platform/vsp1/vsp1_dl.c   | 104 ++++++++++++++++++++++++-
>>  drivers/media/platform/vsp1/vsp1_dl.h   |  25 ++++++-
>>  drivers/media/platform/vsp1/vsp1_drv.c  |   4 +-
>>  drivers/media/platform/vsp1/vsp1_regs.h |   2 +-
>>  5 files changed, 132 insertions(+), 4 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 90e0a11c29b5..2fffe977aa35
>> 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,12 +37,59 @@ struct vsp1_dl_header {
>>  	u32 flags;
>>  };
>>
>> +/**
>> + * struct vsp1_dl_ext_header - Extended display list header
>> + * @padding: padding zero bytes for alignment
>> + * @pre_ext_dl_num_cmd: number of pre-extended command bodies to parse
>> + * @flags: enables or disables execution of the pre and post command
>> + * @pre_ext_dl_plist: start address of pre-extended display list bodies
>> + * @post_ext_dl_num_cmd: number of post-extended command bodies to parse
>> + * @post_ext_dl_plist: start address of post-extended display list bodies
>> + */
>> +struct vsp1_dl_ext_header {
>> +	u32 padding;
>> +
>> +	/*
>> +	 * The datasheet represents flags as stored before pre_ext_dl_num_cmd,
>> +	 * expecting 32-bit accesses. The flags are appropriate to the whole
>> +	 * header, not just the pre_ext command, and thus warrant being
>> +	 * separated out. Due to byte ordering, and representing as 16 bit
>> +	 * values here, the flags must be positioned after the
>> +	 * pre_ext_dl_num_cmd.
>> +	 */
>> +	u16 pre_ext_dl_num_cmd;
>> +	u16 flags;
>> +	u32 pre_ext_dl_plist;
>> +
>> +	u32 post_ext_dl_num_cmd;
>> +	u32 post_ext_dl_plist;
>> +};
>> +
>> +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_pre_ext_dl_body - Pre Extended Display List Body
>> + * @opcode: Extended display list command operation code
>> + * @flags: Pre-extended command flags. These are specific to each command
>> + * @address_set: Source address set pointer. Must have 16 byte alignment
> 
> s/byte/bytes/

I've made this "16-byte alignment" - I don't think you can align to a
plural, or at least it doesn't sound right in my head.

It's an interesting grammatical question that I couldn't find the answer
to, so I've asked online @ ell.stackexchange.com [0]


[0]
https://ell.stackexchange.com/questions/175063/what-is-the-correct-use-of-a-plural-term-and-alignment


> 
>> + * @reserved: Zero bits for alignment.
>> + */
>> +struct vsp1_pre_ext_dl_body {
>> +	u32 opcode;
>> +	u32 flags;
>> +	u32 address_set;
>> +	u32 reserved;
>> +};
>> +
>> +/**
>>   * struct vsp1_dl_body - Display list body
>>   * @list: entry in the display list list of bodies
>>   * @free: entry in the pool free body list
>> @@ -95,9 +145,12 @@ struct vsp1_dl_body_pool {
>>   * @list: entry in the display list manager lists
>>   * @dlm: the display list manager
>>   * @header: display list header
>> + * @extension: extended display list header. NULL for normal lists
>>   * @dma: DMA address for the header
>>   * @body0: first display list body
>>   * @bodies: list of extra display list bodies
>> + * @pre_cmd: pre command to be issued through extended dl header
>> + * @post_cmd: post command to be issued through extended dl header
>>   * @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 +160,15 @@ struct vsp1_dl_list {
>>  	struct vsp1_dl_manager *dlm;
>>
>>  	struct vsp1_dl_header *header;
>> +	struct vsp1_dl_ext_header *extension;
>>  	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;
>>
>> @@ -495,6 +552,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].opcode = cmd->opcode;
>> +	cmd->cmds[0].flags = cmd->flags;
>> +	cmd->cmds[0].address_set = 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;
>> @@ -547,6 +612,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->extension)
>> +		return;
>> +
>> +	dl->extension->flags = 0;
>> +
>> +	if (dl->pre_cmd) {
>> +		dl->extension->pre_ext_dl_plist = dl->pre_cmd->cmd_dma;
>> +		dl->extension->pre_ext_dl_num_cmd = dl->pre_cmd->num_cmds;
>> +		dl->extension->flags |= VSP1_DLH_EXT_PRE_CMD_EXEC;
>> +
>> +		vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
>> +	}
>> +
>> +	if (dl->post_cmd) {
>> +		dl->extension->post_ext_dl_plist = dl->post_cmd->cmd_dma;
>> +		dl->extension->post_ext_dl_num_cmd = dl->post_cmd->num_cmds;
>> +		dl->extension->flags |= VSP1_DLH_EXT_POST_CMD_EXEC;
>> +
>> +		vsp1_dl_ext_cmd_fill_header(dl->post_cmd);
>> +	}
>>  }
>>
>>  static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
>> @@ -736,9 +822,16 @@ unsigned int vsp1_dlm_irq_frame_end(struct
>> vsp1_dl_manager *dlm) /* Hardware Setup */
>>  void vsp1_dlm_setup(struct vsp1_device *vsp1)
>>  {
>> +	unsigned int i;
>>  	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;
>> +	u32 ext_dl = (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT) |
>> +		      VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT;
> 
> To match the style of the file, can you move the trailing | under the = ?

Done.


> 
>> +
>> +	if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
>> +		for (i = 0; i < vsp1->info->wpf_count; ++i)
>> +			vsp1_write(vsp1, VI6_DL_EXT_CTRL(i), ext_dl);
> 
> And add {} to the if ?

Added.


> With these small updates,
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Collected.

> 
> If there's no other issue with v5 that would require a v6, I'll fix this when 
> applying.
> 
>>  	vsp1_write(vsp1, VI6_DL_CTRL, ctrl);
>>  	vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
>> @@ -792,7 +885,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
>> vsp1_device *vsp1, * memory. An extra body is allocated on top of the
>> prealloc to account * for the cached body used by the vsp1_pipeline object.
>>  	 */
>> -	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);
>>
>>  	dlm->pool = vsp1_dl_body_pool_create(vsp1, prealloc + 1,
>>  					     VSP1_DL_NUM_ENTRIES, header_size);
>> @@ -808,6 +905,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct
>> vsp1_device *vsp1, return NULL;
>>  		}
>>
>> +		/* The extended header immediately follows the header. */
>> +		if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
>> +			dl->extension = (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 7dba0469c92e..afefd5bfa136
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_dl.h
>> +++ b/drivers/media/platform/vsp1/vsp1_dl.h
>> @@ -20,6 +20,31 @@ struct vsp1_dl_manager;
>>  #define VSP1_DL_FRAME_END_COMPLETED		BIT(0)
>>  #define VSP1_DL_FRAME_END_INTERNAL		BIT(1)
>>
>> +/**
>> + * struct vsp1_dl_ext_cmd - Extended Display command
>> + * @free: entry in the pool of free commands list
>> + * @opcode: command type 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 body
>> + * @data: memory allocation for command-specific data
>> + * @data_dma: DMA address for command-specific data
>> + */
>> +struct vsp1_dl_ext_cmd {
>> +	struct list_head free;
>> +
>> +	u8 opcode;
>> +	u32 flags;
>> +
>> +	struct vsp1_pre_ext_dl_body *cmds;
>> +	unsigned int num_cmds;
>> +	dma_addr_t cmd_dma;
>> +
>> +	void *data;
>> +	dma_addr_t data_dma;
>> +};
>> +
>>  void vsp1_dlm_setup(struct vsp1_device *vsp1);
>>
>>  struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
>> diff --git a/drivers/media/platform/vsp1/vsp1_drv.c
>> b/drivers/media/platform/vsp1/vsp1_drv.c index 3367c2ba990d..b6619c9c18bb
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_drv.c
>> +++ b/drivers/media/platform/vsp1/vsp1_drv.c
>> @@ -754,7 +754,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 +774,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..5ea9f9070cf3
>> 100644
>> --- a/drivers/media/platform/vsp1/vsp1_regs.h
>> +++ b/drivers/media/platform/vsp1/vsp1_regs.h
>> @@ -72,7 +72,7 @@
>>  #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
> 
>
diff mbox

Patch

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 90e0a11c29b5..2fffe977aa35 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,12 +37,59 @@  struct vsp1_dl_header {
 	u32 flags;
 };
 
+/**
+ * struct vsp1_dl_ext_header - Extended display list header
+ * @padding: padding zero bytes for alignment
+ * @pre_ext_dl_num_cmd: number of pre-extended command bodies to parse
+ * @flags: enables or disables execution of the pre and post command
+ * @pre_ext_dl_plist: start address of pre-extended display list bodies
+ * @post_ext_dl_num_cmd: number of post-extended command bodies to parse
+ * @post_ext_dl_plist: start address of post-extended display list bodies
+ */
+struct vsp1_dl_ext_header {
+	u32 padding;
+
+	/*
+	 * The datasheet represents flags as stored before pre_ext_dl_num_cmd,
+	 * expecting 32-bit accesses. The flags are appropriate to the whole
+	 * header, not just the pre_ext command, and thus warrant being
+	 * separated out. Due to byte ordering, and representing as 16 bit
+	 * values here, the flags must be positioned after the
+	 * pre_ext_dl_num_cmd.
+	 */
+	u16 pre_ext_dl_num_cmd;
+	u16 flags;
+	u32 pre_ext_dl_plist;
+
+	u32 post_ext_dl_num_cmd;
+	u32 post_ext_dl_plist;
+};
+
+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_pre_ext_dl_body - Pre Extended Display List Body
+ * @opcode: Extended display list command operation code
+ * @flags: Pre-extended command flags. These are specific to each command
+ * @address_set: Source address set pointer. Must have 16 byte alignment
+ * @reserved: Zero bits for alignment.
+ */
+struct vsp1_pre_ext_dl_body {
+	u32 opcode;
+	u32 flags;
+	u32 address_set;
+	u32 reserved;
+};
+
+/**
  * struct vsp1_dl_body - Display list body
  * @list: entry in the display list list of bodies
  * @free: entry in the pool free body list
@@ -95,9 +145,12 @@  struct vsp1_dl_body_pool {
  * @list: entry in the display list manager lists
  * @dlm: the display list manager
  * @header: display list header
+ * @extension: extended display list header. NULL for normal lists
  * @dma: DMA address for the header
  * @body0: first display list body
  * @bodies: list of extra display list bodies
+ * @pre_cmd: pre command to be issued through extended dl header
+ * @post_cmd: post command to be issued through extended dl header
  * @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 +160,15 @@  struct vsp1_dl_list {
 	struct vsp1_dl_manager *dlm;
 
 	struct vsp1_dl_header *header;
+	struct vsp1_dl_ext_header *extension;
 	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;
 
@@ -495,6 +552,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].opcode = cmd->opcode;
+	cmd->cmds[0].flags = cmd->flags;
+	cmd->cmds[0].address_set = 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;
@@ -547,6 +612,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->extension)
+		return;
+
+	dl->extension->flags = 0;
+
+	if (dl->pre_cmd) {
+		dl->extension->pre_ext_dl_plist = dl->pre_cmd->cmd_dma;
+		dl->extension->pre_ext_dl_num_cmd = dl->pre_cmd->num_cmds;
+		dl->extension->flags |= VSP1_DLH_EXT_PRE_CMD_EXEC;
+
+		vsp1_dl_ext_cmd_fill_header(dl->pre_cmd);
+	}
+
+	if (dl->post_cmd) {
+		dl->extension->post_ext_dl_plist = dl->post_cmd->cmd_dma;
+		dl->extension->post_ext_dl_num_cmd = dl->post_cmd->num_cmds;
+		dl->extension->flags |= VSP1_DLH_EXT_POST_CMD_EXEC;
+
+		vsp1_dl_ext_cmd_fill_header(dl->post_cmd);
+	}
 }
 
 static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
@@ -736,9 +822,16 @@  unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
 /* Hardware Setup */
 void vsp1_dlm_setup(struct vsp1_device *vsp1)
 {
+	unsigned int i;
 	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;
+	u32 ext_dl = (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT) |
+		      VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT;
+
+	if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
+		for (i = 0; i < vsp1->info->wpf_count; ++i)
+			vsp1_write(vsp1, VI6_DL_EXT_CTRL(i), ext_dl);
 
 	vsp1_write(vsp1, VI6_DL_CTRL, ctrl);
 	vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
@@ -792,7 +885,11 @@  struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 	 * memory. An extra body is allocated on top of the prealloc to account
 	 * for the cached body used by the vsp1_pipeline object.
 	 */
-	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);
 
 	dlm->pool = vsp1_dl_body_pool_create(vsp1, prealloc + 1,
 					     VSP1_DL_NUM_ENTRIES, header_size);
@@ -808,6 +905,11 @@  struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
 			return NULL;
 		}
 
+		/* The extended header immediately follows the header. */
+		if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL))
+			dl->extension = (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 7dba0469c92e..afefd5bfa136 100644
--- a/drivers/media/platform/vsp1/vsp1_dl.h
+++ b/drivers/media/platform/vsp1/vsp1_dl.h
@@ -20,6 +20,31 @@  struct vsp1_dl_manager;
 #define VSP1_DL_FRAME_END_COMPLETED		BIT(0)
 #define VSP1_DL_FRAME_END_INTERNAL		BIT(1)
 
+/**
+ * struct vsp1_dl_ext_cmd - Extended Display command
+ * @free: entry in the pool of free commands list
+ * @opcode: command type 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 body
+ * @data: memory allocation for command-specific data
+ * @data_dma: DMA address for command-specific data
+ */
+struct vsp1_dl_ext_cmd {
+	struct list_head free;
+
+	u8 opcode;
+	u32 flags;
+
+	struct vsp1_pre_ext_dl_body *cmds;
+	unsigned int num_cmds;
+	dma_addr_t cmd_dma;
+
+	void *data;
+	dma_addr_t data_dma;
+};
+
 void vsp1_dlm_setup(struct vsp1_device *vsp1);
 
 struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 3367c2ba990d..b6619c9c18bb 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -754,7 +754,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 +774,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..5ea9f9070cf3 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -72,7 +72,7 @@ 
 #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