22
22
#define VSP1_DLH_INT_ENABLE (1 << 1)
23
23
#define VSP1_DLH_AUTO_START (1 << 0)
24
24
25
+ #define VSP1_DLH_EXT_PRE_CMD_EXEC (1 << 9)
26
+ #define VSP1_DLH_EXT_POST_CMD_EXEC (1 << 8)
27
+
25
28
struct vsp1_dl_header_list {
26
29
u32 num_bytes ;
27
30
u32 addr ;
@@ -34,11 +37,58 @@ struct vsp1_dl_header {
34
37
u32 flags ;
35
38
} __packed ;
36
39
40
+ /**
41
+ * struct vsp1_dl_ext_header - Extended display list header
42
+ * @padding: padding zero bytes for alignment
43
+ * @pre_ext_dl_num_cmd: number of pre-extended command bodies to parse
44
+ * @flags: enables or disables execution of the pre and post command
45
+ * @pre_ext_dl_plist: start address of pre-extended display list bodies
46
+ * @post_ext_dl_num_cmd: number of post-extended command bodies to parse
47
+ * @post_ext_dl_plist: start address of post-extended display list bodies
48
+ */
49
+ struct vsp1_dl_ext_header {
50
+ u32 padding ;
51
+
52
+ /*
53
+ * The datasheet represents flags as stored before pre_ext_dl_num_cmd,
54
+ * expecting 32-bit accesses. The flags are appropriate to the whole
55
+ * header, not just the pre_ext command, and thus warrant being
56
+ * separated out. Due to byte ordering, and representing as 16 bit
57
+ * values here, the flags must be positioned after the
58
+ * pre_ext_dl_num_cmd.
59
+ */
60
+ u16 pre_ext_dl_num_cmd ;
61
+ u16 flags ;
62
+ u32 pre_ext_dl_plist ;
63
+
64
+ u32 post_ext_dl_num_cmd ;
65
+ u32 post_ext_dl_plist ;
66
+ } __packed ;
67
+
68
+ struct vsp1_dl_header_extended {
69
+ struct vsp1_dl_header header ;
70
+ struct vsp1_dl_ext_header ext ;
71
+ } __packed ;
72
+
37
73
struct vsp1_dl_entry {
38
74
u32 addr ;
39
75
u32 data ;
40
76
} __packed ;
41
77
78
+ /**
79
+ * struct vsp1_pre_ext_dl_body - Pre Extended Display List Body
80
+ * @opcode: Extended display list command operation code
81
+ * @flags: Pre-extended command flags. These are specific to each command
82
+ * @address_set: Source address set pointer. Must have 16-byte alignment
83
+ * @reserved: Zero bits for alignment.
84
+ */
85
+ struct vsp1_pre_ext_dl_body {
86
+ u32 opcode ;
87
+ u32 flags ;
88
+ u32 address_set ;
89
+ u32 reserved ;
90
+ } __packed ;
91
+
42
92
/**
43
93
* struct vsp1_dl_body - Display list body
44
94
* @list: entry in the display list list of bodies
@@ -96,9 +146,12 @@ struct vsp1_dl_body_pool {
96
146
* @list: entry in the display list manager lists
97
147
* @dlm: the display list manager
98
148
* @header: display list header
149
+ * @extension: extended display list header. NULL for normal lists
99
150
* @dma: DMA address for the header
100
151
* @body0: first display list body
101
152
* @bodies: list of extra display list bodies
153
+ * @pre_cmd: pre command to be issued through extended dl header
154
+ * @post_cmd: post command to be issued through extended dl header
102
155
* @has_chain: if true, indicates that there's a partition chain
103
156
* @chain: entry in the display list partition chain
104
157
* @internal: whether the display list is used for internal purpose
@@ -108,11 +161,15 @@ struct vsp1_dl_list {
108
161
struct vsp1_dl_manager * dlm ;
109
162
110
163
struct vsp1_dl_header * header ;
164
+ struct vsp1_dl_ext_header * extension ;
111
165
dma_addr_t dma ;
112
166
113
167
struct vsp1_dl_body * body0 ;
114
168
struct list_head bodies ;
115
169
170
+ struct vsp1_dl_ext_cmd * pre_cmd ;
171
+ struct vsp1_dl_ext_cmd * post_cmd ;
172
+
116
173
bool has_chain ;
117
174
struct list_head chain ;
118
175
@@ -496,6 +553,14 @@ int vsp1_dl_list_add_chain(struct vsp1_dl_list *head,
496
553
return 0 ;
497
554
}
498
555
556
+ static void vsp1_dl_ext_cmd_fill_header (struct vsp1_dl_ext_cmd * cmd )
557
+ {
558
+ cmd -> cmds [0 ].opcode = cmd -> opcode ;
559
+ cmd -> cmds [0 ].flags = cmd -> flags ;
560
+ cmd -> cmds [0 ].address_set = cmd -> data_dma ;
561
+ cmd -> cmds [0 ].reserved = 0 ;
562
+ }
563
+
499
564
static void vsp1_dl_list_fill_header (struct vsp1_dl_list * dl , bool is_last )
500
565
{
501
566
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
613
*/
549
614
dl -> header -> flags = VSP1_DLH_INT_ENABLE ;
550
615
}
616
+
617
+ if (!dl -> extension )
618
+ return ;
619
+
620
+ dl -> extension -> flags = 0 ;
621
+
622
+ if (dl -> pre_cmd ) {
623
+ dl -> extension -> pre_ext_dl_plist = dl -> pre_cmd -> cmd_dma ;
624
+ dl -> extension -> pre_ext_dl_num_cmd = dl -> pre_cmd -> num_cmds ;
625
+ dl -> extension -> flags |= VSP1_DLH_EXT_PRE_CMD_EXEC ;
626
+
627
+ vsp1_dl_ext_cmd_fill_header (dl -> pre_cmd );
628
+ }
629
+
630
+ if (dl -> post_cmd ) {
631
+ dl -> extension -> post_ext_dl_plist = dl -> post_cmd -> cmd_dma ;
632
+ dl -> extension -> post_ext_dl_num_cmd = dl -> post_cmd -> num_cmds ;
633
+ dl -> extension -> flags |= VSP1_DLH_EXT_POST_CMD_EXEC ;
634
+
635
+ vsp1_dl_ext_cmd_fill_header (dl -> post_cmd );
636
+ }
551
637
}
552
638
553
639
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
823
/* Hardware Setup */
738
824
void vsp1_dlm_setup (struct vsp1_device * vsp1 )
739
825
{
826
+ unsigned int i ;
740
827
u32 ctrl = (256 << VI6_DL_CTRL_AR_WAIT_SHIFT )
741
828
| VI6_DL_CTRL_DC2 | VI6_DL_CTRL_DC1 | VI6_DL_CTRL_DC0
742
829
| VI6_DL_CTRL_DLE ;
830
+ u32 ext_dl = (0x02 << VI6_DL_EXT_CTRL_POLINT_SHIFT )
831
+ | VI6_DL_EXT_CTRL_DLPRI | VI6_DL_EXT_CTRL_EXT ;
832
+
833
+ if (vsp1_feature (vsp1 , VSP1_HAS_EXT_DL )) {
834
+ for (i = 0 ; i < vsp1 -> info -> wpf_count ; ++ i )
835
+ vsp1_write (vsp1 , VI6_DL_EXT_CTRL (i ), ext_dl );
836
+ }
743
837
744
838
vsp1_write (vsp1 , VI6_DL_CTRL , ctrl );
745
839
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
887
* memory. An extra body is allocated on top of the prealloc to account
794
888
* for the cached body used by the vsp1_pipeline object.
795
889
*/
796
- header_size = ALIGN (sizeof (struct vsp1_dl_header ), 8 );
890
+ header_size = vsp1_feature (vsp1 , VSP1_HAS_EXT_DL ) ?
891
+ sizeof (struct vsp1_dl_header_extended ) :
892
+ sizeof (struct vsp1_dl_header );
893
+
894
+ header_size = ALIGN (header_size , 8 );
797
895
798
896
dlm -> pool = vsp1_dl_body_pool_create (vsp1 , prealloc + 1 ,
799
897
VSP1_DL_NUM_ENTRIES , header_size );
@@ -809,6 +907,11 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1,
809
907
return NULL ;
810
908
}
811
909
910
+ /* The extended header immediately follows the header. */
911
+ if (vsp1_feature (vsp1 , VSP1_HAS_EXT_DL ))
912
+ dl -> extension = (void * )dl -> header
913
+ + sizeof (* dl -> header );
914
+
812
915
list_add_tail (& dl -> list , & dlm -> free );
813
916
}
814
917
0 commit comments