hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/platform/vsp1/vsp1_dl.c
....@@ -178,7 +178,7 @@
178178 * @post_cmd: post command to be issued through extended dl header
179179 * @has_chain: if true, indicates that there's a partition chain
180180 * @chain: entry in the display list partition chain
181
- * @internal: whether the display list is used for internal purpose
181
+ * @flags: display list flags, a combination of VSP1_DL_FRAME_END_*
182182 */
183183 struct vsp1_dl_list {
184184 struct list_head list;
....@@ -197,7 +197,7 @@
197197 bool has_chain;
198198 struct list_head chain;
199199
200
- bool internal;
200
+ unsigned int flags;
201201 };
202202
203203 /**
....@@ -703,8 +703,8 @@
703703 * which bodies are added.
704704 *
705705 * Adding a body to a display list passes ownership of the body to the list. The
706
- * caller retains its reference to the fragment when adding it to the display
707
- * list, but is not allowed to add new entries to the body.
706
+ * caller retains its reference to the body when adding it to the display list,
707
+ * but is not allowed to add new entries to the body.
708708 *
709709 * The reference must be explicitly released by a call to vsp1_dl_body_put()
710710 * when the body isn't needed anymore.
....@@ -774,17 +774,35 @@
774774 }
775775
776776 dl->header->num_lists = num_lists;
777
+ dl->header->flags = 0;
777778
778
- if (!list_empty(&dl->chain) && !is_last) {
779
+ /*
780
+ * Enable the interrupt for the end of each frame. In continuous mode
781
+ * chained lists are used with one list per frame, so enable the
782
+ * interrupt for each list. In singleshot mode chained lists are used
783
+ * to partition a single frame, so enable the interrupt for the last
784
+ * list only.
785
+ */
786
+ if (!dlm->singleshot || is_last)
787
+ dl->header->flags |= VSP1_DLH_INT_ENABLE;
788
+
789
+ /*
790
+ * In continuous mode enable auto-start for all lists, as the VSP must
791
+ * loop on the same list until a new one is queued. In singleshot mode
792
+ * enable auto-start for all lists but the last to chain processing of
793
+ * partitions without software intervention.
794
+ */
795
+ if (!dlm->singleshot || !is_last)
796
+ dl->header->flags |= VSP1_DLH_AUTO_START;
797
+
798
+ if (!is_last) {
779799 /*
780
- * If this display list's chain is not empty, we are on a list,
781
- * and the next item is the display list that we must queue for
782
- * automatic processing by the hardware.
800
+ * If this is not the last display list in the chain, queue the
801
+ * next item for automatic processing by the hardware.
783802 */
784803 struct vsp1_dl_list *next = list_next_entry(dl, chain);
785804
786805 dl->header->next_header = next->dma;
787
- dl->header->flags = VSP1_DLH_AUTO_START;
788806 } else if (!dlm->singleshot) {
789807 /*
790808 * if the display list manager works in continuous mode, the VSP
....@@ -792,13 +810,6 @@
792810 * instructed to do otherwise.
793811 */
794812 dl->header->next_header = dl->dma;
795
- dl->header->flags = VSP1_DLH_INT_ENABLE | VSP1_DLH_AUTO_START;
796
- } else {
797
- /*
798
- * Otherwise, in mem-to-mem mode, we work in single-shot mode
799
- * and the next display list must not be started automatically.
800
- */
801
- dl->header->flags = VSP1_DLH_INT_ENABLE;
802813 }
803814
804815 if (!dl->extension)
....@@ -865,13 +876,15 @@
865876 *
866877 * If a display list is already pending we simply drop it as the new
867878 * display list is assumed to contain a more recent configuration. It is
868
- * an error if the already pending list has the internal flag set, as
869
- * there is then a process waiting for that list to complete. This
870
- * shouldn't happen as the waiting process should perform proper
871
- * locking, but warn just in case.
879
+ * an error if the already pending list has the
880
+ * VSP1_DL_FRAME_END_INTERNAL flag set, as there is then a process
881
+ * waiting for that list to complete. This shouldn't happen as the
882
+ * waiting process should perform proper locking, but warn just in
883
+ * case.
872884 */
873885 if (vsp1_dl_list_hw_update_pending(dlm)) {
874
- WARN_ON(dlm->pending && dlm->pending->internal);
886
+ WARN_ON(dlm->pending &&
887
+ (dlm->pending->flags & VSP1_DL_FRAME_END_INTERNAL));
875888 __vsp1_dl_list_put(dlm->pending);
876889 dlm->pending = dl;
877890 return;
....@@ -901,7 +914,7 @@
901914 dlm->active = dl;
902915 }
903916
904
-void vsp1_dl_list_commit(struct vsp1_dl_list *dl, bool internal)
917
+void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags)
905918 {
906919 struct vsp1_dl_manager *dlm = dl->dlm;
907920 struct vsp1_dl_list *dl_next;
....@@ -916,7 +929,7 @@
916929 vsp1_dl_list_fill_header(dl_next, last);
917930 }
918931
919
- dl->internal = internal;
932
+ dl->flags = dl_flags & ~VSP1_DL_FRAME_END_COMPLETED;
920933
921934 spin_lock_irqsave(&dlm->lock, flags);
922935
....@@ -945,9 +958,13 @@
945958 * set in single-shot mode as display list processing is then not continuous and
946959 * races never occur.
947960 *
948
- * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the previous display list
949
- * has completed and had been queued with the internal notification flag.
950
- * Internal notification is only supported for continuous mode.
961
+ * The following flags are only supported for continuous mode.
962
+ *
963
+ * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the display list that just
964
+ * became active had been queued with the internal notification flag.
965
+ *
966
+ * The VSP1_DL_FRAME_END_WRITEBACK flag indicates that the previously active
967
+ * display list had been queued with the writeback flag.
951968 */
952969 unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm)
953970 {
....@@ -986,13 +1003,24 @@
9861003 goto done;
9871004
9881005 /*
1006
+ * If the active display list has the writeback flag set, the frame
1007
+ * completion marks the end of the writeback capture. Return the
1008
+ * VSP1_DL_FRAME_END_WRITEBACK flag and reset the display list's
1009
+ * writeback flag.
1010
+ */
1011
+ if (dlm->active && (dlm->active->flags & VSP1_DL_FRAME_END_WRITEBACK)) {
1012
+ flags |= VSP1_DL_FRAME_END_WRITEBACK;
1013
+ dlm->active->flags &= ~VSP1_DL_FRAME_END_WRITEBACK;
1014
+ }
1015
+
1016
+ /*
9891017 * The device starts processing the queued display list right after the
9901018 * frame end interrupt. The display list thus becomes active.
9911019 */
9921020 if (dlm->queued) {
993
- if (dlm->queued->internal)
1021
+ if (dlm->queued->flags & VSP1_DL_FRAME_END_INTERNAL)
9941022 flags |= VSP1_DL_FRAME_END_INTERNAL;
995
- dlm->queued->internal = false;
1023
+ dlm->queued->flags &= ~VSP1_DL_FRAME_END_INTERNAL;
9961024
9971025 __vsp1_dl_list_put(dlm->active);
9981026 dlm->active = dlm->queued;