| .. | .. |
|---|
| 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; |
|---|