Commit 7d630c49 authored by Kieran Bingham's avatar Kieran Bingham Committed by Mauro Carvalho Chehab

media: vsp1: Add support for extended display list headers

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: default avatarKieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 08e41f62
...@@ -53,6 +53,7 @@ struct vsp1_uif; ...@@ -53,6 +53,7 @@ struct vsp1_uif;
#define VSP1_HAS_HGO (1 << 7) #define VSP1_HAS_HGO (1 << 7)
#define VSP1_HAS_HGT (1 << 8) #define VSP1_HAS_HGT (1 << 8)
#define VSP1_HAS_BRS (1 << 9) #define VSP1_HAS_BRS (1 << 9)
#define VSP1_HAS_EXT_DL (1 << 10)
struct vsp1_device_info { struct vsp1_device_info {
u32 version; u32 version;
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#define VSP1_DLH_INT_ENABLE (1 << 1) #define VSP1_DLH_INT_ENABLE (1 << 1)
#define VSP1_DLH_AUTO_START (1 << 0) #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 { struct vsp1_dl_header_list {
u32 num_bytes; u32 num_bytes;
u32 addr; u32 addr;
...@@ -34,11 +37,58 @@ struct vsp1_dl_header { ...@@ -34,11 +37,58 @@ struct vsp1_dl_header {
u32 flags; u32 flags;
} __packed; } __packed;
/**
* 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;
} __packed;
struct vsp1_dl_header_extended {
struct vsp1_dl_header header;
struct vsp1_dl_ext_header ext;
} __packed;
struct vsp1_dl_entry { struct vsp1_dl_entry {
u32 addr; u32 addr;
u32 data; u32 data;
} __packed; } __packed;
/**
* 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;
} __packed;
/** /**
* struct vsp1_dl_body - Display list body * struct vsp1_dl_body - Display list body
* @list: entry in the display list list of bodies * @list: entry in the display list list of bodies
...@@ -96,9 +146,12 @@ struct vsp1_dl_body_pool { ...@@ -96,9 +146,12 @@ struct vsp1_dl_body_pool {
* @list: entry in the display list manager lists * @list: entry in the display list manager lists
* @dlm: the display list manager * @dlm: the display list manager
* @header: display list header * @header: display list header
* @extension: extended display list header. NULL for normal lists
* @dma: DMA address for the header * @dma: DMA address for the header
* @body0: first display list body * @body0: first display list body
* @bodies: list of extra display list bodies * @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 * @has_chain: if true, indicates that there's a partition chain
* @chain: entry in the display list partition chain * @chain: entry in the display list partition chain
* @internal: whether the display list is used for internal purpose * @internal: whether the display list is used for internal purpose
...@@ -108,11 +161,15 @@ struct vsp1_dl_list { ...@@ -108,11 +161,15 @@ struct vsp1_dl_list {
struct vsp1_dl_manager *dlm; struct vsp1_dl_manager *dlm;
struct vsp1_dl_header *header; struct vsp1_dl_header *header;
struct vsp1_dl_ext_header *extension;
dma_addr_t dma; dma_addr_t dma;
struct vsp1_dl_body *body0; struct vsp1_dl_body *body0;
struct list_head bodies; struct list_head bodies;
struct vsp1_dl_ext_cmd *pre_cmd;
struct vsp1_dl_ext_cmd *post_cmd;
bool has_chain; bool has_chain;
struct list_head chain; struct list_head chain;
...@@ -496,6 +553,14 @@ int vsp1_dl_list_add_chain(struct vsp1_dl_list *head, ...@@ -496,6 +553,14 @@ int vsp1_dl_list_add_chain(struct vsp1_dl_list *head,
return 0; 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) static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last)
{ {
struct vsp1_dl_manager *dlm = dl->dlm; struct vsp1_dl_manager *dlm = dl->dlm;
...@@ -548,6 +613,27 @@ static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last) ...@@ -548,6 +613,27 @@ static void vsp1_dl_list_fill_header(struct vsp1_dl_list *dl, bool is_last)
*/ */
dl->header->flags = VSP1_DLH_INT_ENABLE; 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) static bool vsp1_dl_list_hw_update_pending(struct vsp1_dl_manager *dlm)
...@@ -737,9 +823,17 @@ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) ...@@ -737,9 +823,17 @@ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
/* Hardware Setup */ /* Hardware Setup */
void vsp1_dlm_setup(struct vsp1_device *vsp1) void vsp1_dlm_setup(struct vsp1_device *vsp1)
{ {
unsigned int i;
u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT) u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT)
| VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0 | VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0
| VI6_DL_CTRL_DLE; | 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_CTRL, ctrl);
vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS); vsp1_write(vsp1, VI6_DL_SWAP, VI6_DL_SWAP_LWS);
...@@ -793,7 +887,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, ...@@ -793,7 +887,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 * memory. An extra body is allocated on top of the prealloc to account
* for the cached body used by the vsp1_pipeline object. * 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, dlm->pool = vsp1_dl_body_pool_create(vsp1, prealloc + 1,
VSP1_DL_NUM_ENTRIES, header_size); VSP1_DL_NUM_ENTRIES, header_size);
...@@ -809,6 +907,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, ...@@ -809,6 +907,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
return NULL; 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); list_add_tail(&dl->list, &dlm->free);
} }
......
...@@ -20,6 +20,31 @@ struct vsp1_dl_manager; ...@@ -20,6 +20,31 @@ struct vsp1_dl_manager;
#define VSP1_DL_FRAME_END_COMPLETED BIT(0) #define VSP1_DL_FRAME_END_COMPLETED BIT(0)
#define VSP1_DL_FRAME_END_INTERNAL BIT(1) #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); void vsp1_dlm_setup(struct vsp1_device *vsp1);
struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
......
...@@ -754,7 +754,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { ...@@ -754,7 +754,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPD_GEN3, .version = VI6_IP_VERSION_MODEL_VSPD_GEN3,
.model = "VSP2-D", .model = "VSP2-D",
.gen = 3, .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, .lif_count = 1,
.rpf_count = 5, .rpf_count = 5,
.uif_count = 1, .uif_count = 1,
...@@ -774,7 +774,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = { ...@@ -774,7 +774,7 @@ static const struct vsp1_device_info vsp1_device_infos[] = {
.version = VI6_IP_VERSION_MODEL_VSPDL_GEN3, .version = VI6_IP_VERSION_MODEL_VSPDL_GEN3,
.model = "VSP2-DL", .model = "VSP2-DL",
.gen = 3, .gen = 3,
.features = VSP1_HAS_BRS | VSP1_HAS_BRU, .features = VSP1_HAS_BRS | VSP1_HAS_BRU | VSP1_HAS_EXT_DL,
.lif_count = 2, .lif_count = 2,
.rpf_count = 5, .rpf_count = 5,
.uif_count = 2, .uif_count = 2,
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#define VI6_DL_SWAP_WDS (1 << 1) #define VI6_DL_SWAP_WDS (1 << 1)
#define VI6_DL_SWAP_BTS (1 << 0) #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_NWE (1 << 16)
#define VI6_DL_EXT_CTRL_POLINT_MASK (0x3f << 8) #define VI6_DL_EXT_CTRL_POLINT_MASK (0x3f << 8)
#define VI6_DL_EXT_CTRL_POLINT_SHIFT 8 #define VI6_DL_EXT_CTRL_POLINT_SHIFT 8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment