.. | .. |
---|
178 | 178 | * @post_cmd: post command to be issued through extended dl header |
---|
179 | 179 | * @has_chain: if true, indicates that there's a partition chain |
---|
180 | 180 | * @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_* |
---|
182 | 182 | */ |
---|
183 | 183 | struct vsp1_dl_list { |
---|
184 | 184 | struct list_head list; |
---|
.. | .. |
---|
197 | 197 | bool has_chain; |
---|
198 | 198 | struct list_head chain; |
---|
199 | 199 | |
---|
200 | | - bool internal; |
---|
| 200 | + unsigned int flags; |
---|
201 | 201 | }; |
---|
202 | 202 | |
---|
203 | 203 | /** |
---|
.. | .. |
---|
703 | 703 | * which bodies are added. |
---|
704 | 704 | * |
---|
705 | 705 | * 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. |
---|
708 | 708 | * |
---|
709 | 709 | * The reference must be explicitly released by a call to vsp1_dl_body_put() |
---|
710 | 710 | * when the body isn't needed anymore. |
---|
.. | .. |
---|
774 | 774 | } |
---|
775 | 775 | |
---|
776 | 776 | dl->header->num_lists = num_lists; |
---|
| 777 | + dl->header->flags = 0; |
---|
777 | 778 | |
---|
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) { |
---|
779 | 799 | /* |
---|
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. |
---|
783 | 802 | */ |
---|
784 | 803 | struct vsp1_dl_list *next = list_next_entry(dl, chain); |
---|
785 | 804 | |
---|
786 | 805 | dl->header->next_header = next->dma; |
---|
787 | | - dl->header->flags = VSP1_DLH_AUTO_START; |
---|
788 | 806 | } else if (!dlm->singleshot) { |
---|
789 | 807 | /* |
---|
790 | 808 | * if the display list manager works in continuous mode, the VSP |
---|
.. | .. |
---|
792 | 810 | * instructed to do otherwise. |
---|
793 | 811 | */ |
---|
794 | 812 | 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; |
---|
802 | 813 | } |
---|
803 | 814 | |
---|
804 | 815 | if (!dl->extension) |
---|
.. | .. |
---|
865 | 876 | * |
---|
866 | 877 | * If a display list is already pending we simply drop it as the new |
---|
867 | 878 | * 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. |
---|
872 | 884 | */ |
---|
873 | 885 | 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)); |
---|
875 | 888 | __vsp1_dl_list_put(dlm->pending); |
---|
876 | 889 | dlm->pending = dl; |
---|
877 | 890 | return; |
---|
.. | .. |
---|
901 | 914 | dlm->active = dl; |
---|
902 | 915 | } |
---|
903 | 916 | |
---|
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) |
---|
905 | 918 | { |
---|
906 | 919 | struct vsp1_dl_manager *dlm = dl->dlm; |
---|
907 | 920 | struct vsp1_dl_list *dl_next; |
---|
.. | .. |
---|
916 | 929 | vsp1_dl_list_fill_header(dl_next, last); |
---|
917 | 930 | } |
---|
918 | 931 | |
---|
919 | | - dl->internal = internal; |
---|
| 932 | + dl->flags = dl_flags & ~VSP1_DL_FRAME_END_COMPLETED; |
---|
920 | 933 | |
---|
921 | 934 | spin_lock_irqsave(&dlm->lock, flags); |
---|
922 | 935 | |
---|
.. | .. |
---|
945 | 958 | * set in single-shot mode as display list processing is then not continuous and |
---|
946 | 959 | * races never occur. |
---|
947 | 960 | * |
---|
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. |
---|
951 | 968 | */ |
---|
952 | 969 | unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) |
---|
953 | 970 | { |
---|
.. | .. |
---|
986 | 1003 | goto done; |
---|
987 | 1004 | |
---|
988 | 1005 | /* |
---|
| 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 | + /* |
---|
989 | 1017 | * The device starts processing the queued display list right after the |
---|
990 | 1018 | * frame end interrupt. The display list thus becomes active. |
---|
991 | 1019 | */ |
---|
992 | 1020 | if (dlm->queued) { |
---|
993 | | - if (dlm->queued->internal) |
---|
| 1021 | + if (dlm->queued->flags & VSP1_DL_FRAME_END_INTERNAL) |
---|
994 | 1022 | flags |= VSP1_DL_FRAME_END_INTERNAL; |
---|
995 | | - dlm->queued->internal = false; |
---|
| 1023 | + dlm->queued->flags &= ~VSP1_DL_FRAME_END_INTERNAL; |
---|
996 | 1024 | |
---|
997 | 1025 | __vsp1_dl_list_put(dlm->active); |
---|
998 | 1026 | dlm->active = dlm->queued; |
---|