diff options
author | Lajos Molnar <molnar@ti.com> | 2010-06-29 05:41:37 -0400 |
---|---|---|
committer | Paolo Pisati <paolo.pisati@canonical.com> | 2012-08-17 04:18:57 -0400 |
commit | fe0ae617ff9b61bedc4f8a88289bf5b982aba2ef (patch) | |
tree | a6e7d5f1a97f0ba7341329973914634e30139f55 | |
parent | 0c5ba809d7e5be11eb04efc68067ab70d30c508e (diff) |
TILER: Update to v2.0 kernel API, remove d2cmap limitation
Changed tiler_alloc/x, tiler_map/x and tiler_free APIs to use
tiler_block_t structure.
Simplified tiler_mmap using information in this structure.
Now storing and able to reconstruct exact dimension of each
allocated tiler block.
Fixed issue with virtual stride of 1D buffers when using an
offset.
Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
-rw-r--r-- | arch/arm/mach-omap2/include/mach/tiler.h | 98 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler.c | 279 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler_def.h | 8 |
3 files changed, 240 insertions, 145 deletions
diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h index 9ce79734482..6f0757b9b24 100644 --- a/arch/arm/mach-omap2/include/mach/tiler.h +++ b/arch/arm/mach-omap2/include/mach/tiler.h | |||
@@ -47,6 +47,14 @@ enum tiler_fmt { | |||
47 | TILFMT_MAX = 3, | 47 | TILFMT_MAX = 3, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | struct tiler_block_t { | ||
51 | u32 phys; /* system space (L3) tiler addr */ | ||
52 | u32 width; /* width */ | ||
53 | u32 height; /* height */ | ||
54 | u32 key; /* secret key */ | ||
55 | u32 id; /* unique block ID */ | ||
56 | }; | ||
57 | |||
50 | struct area { | 58 | struct area { |
51 | u16 width; | 59 | u16 width; |
52 | u16 height; | 60 | u16 height; |
@@ -82,46 +90,39 @@ struct tiler_view_orient { | |||
82 | u8 y_invert; | 90 | u8 y_invert; |
83 | }; | 91 | }; |
84 | 92 | ||
85 | /* utility functions */ | ||
86 | static inline u32 tilfmt_bpp(enum tiler_fmt fmt) | ||
87 | { | ||
88 | return fmt == TILFMT_8BIT ? 1 : | ||
89 | fmt == TILFMT_16BIT ? 2 : | ||
90 | fmt == TILFMT_32BIT ? 4 : 0; | ||
91 | } | ||
92 | |||
93 | /** | 93 | /** |
94 | * Reserves a 1D or 2D TILER block area and memory for the | 94 | * Reserves a 1D or 2D TILER block area and memory for the |
95 | * current process with group ID 0. | 95 | * current process with group ID 0. |
96 | * | 96 | * |
97 | * @param fmt TILER bit mode | 97 | * @param blk pointer to tiler block data. This must be set up ('phys' member |
98 | * @param width block width | 98 | * must be 0) with the tiler block information. 'height' must be 1 |
99 | * @param height block height (must be 1 for 1D) | 99 | * for 1D block. |
100 | * @param sys_addr pointer where system space (L3) address | 100 | * @param fmt TILER block format |
101 | * will be stored. | 101 | * @param align block alignment (default: PAGE_SIZE) |
102 | * @param offs block offset | ||
102 | * | 103 | * |
103 | * @return error status | 104 | * @return error status |
104 | */ | 105 | */ |
105 | s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr); | 106 | s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, |
107 | u32 offs); | ||
106 | 108 | ||
107 | /** | 109 | /** |
108 | * Reserves a 1D or 2D TILER block area and memory with extended | 110 | * Reserves a 1D or 2D TILER block area and memory for a set process and group |
109 | * arguments. | 111 | * ID. |
110 | * | 112 | * |
111 | * @param fmt TILER bit mode | 113 | * @param blk pointer to tiler block data. This must be set up ('phys' member |
112 | * @param width block width | 114 | * must be 0) with the tiler block information. 'height' must be 1 |
113 | * @param height block height (must be 1 for 1D) | 115 | * for 1D block. |
114 | * @param align block alignment (default: PAGE_SIZE) | 116 | * @param fmt TILER bit mode |
115 | * @param offs block offset | 117 | * @param align block alignment (default: PAGE_SIZE) |
116 | * @param gid group ID | 118 | * @param offs block offset |
117 | * @param pid process ID | 119 | * @param gid group ID |
118 | * @param sys_addr pointer where system space (L3) address | 120 | * @param pid process ID |
119 | * will be stored. | ||
120 | * | 121 | * |
121 | * @return error status | 122 | * @return error status |
122 | */ | 123 | */ |
123 | s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height, | 124 | s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, |
124 | u32 align, u32 offs, u32 gid, pid_t pid, u32 *sys_addr); | 125 | u32 offs, u32 gid, pid_t pid); |
125 | 126 | ||
126 | /** | 127 | /** |
127 | * Maps an existing buffer to a 1D or 2D TILER area for the | 128 | * Maps an existing buffer to a 1D or 2D TILER area for the |
@@ -129,48 +130,53 @@ s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height, | |||
129 | * | 130 | * |
130 | * Currently, only 1D area mapping is supported. | 131 | * Currently, only 1D area mapping is supported. |
131 | * | 132 | * |
133 | * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped | ||
134 | * into tiler container. | ||
135 | * | ||
136 | * @param blk pointer to tiler block data. This must be set up | ||
137 | * ('phys' member must be 0) with the tiler block information. | ||
138 | * 'height' must be 1 for 1D block. | ||
132 | * @param fmt TILER bit mode | 139 | * @param fmt TILER bit mode |
133 | * @param width block width | ||
134 | * @param height block height (must be 1 for 1D) | ||
135 | * @param sys_addr pointer where system space (L3) address | ||
136 | * will be stored. | ||
137 | * @param usr_addr user space address of existing buffer. | 140 | * @param usr_addr user space address of existing buffer. |
138 | * | 141 | * |
139 | * @return error status | 142 | * @return error status |
140 | */ | 143 | */ |
141 | s32 tiler_map(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr, | 144 | s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr); |
142 | u32 usr_addr); | ||
143 | 145 | ||
144 | /** | 146 | /** |
145 | * Maps an existing buffer to a 1D or 2D TILER area with | 147 | * Maps an existing buffer to a 1D or 2D TILER area for a set process and group |
146 | * extended arguments. | 148 | * ID. |
147 | * | 149 | * |
148 | * Currently, only 1D area mapping is supported. | 150 | * Currently, only 1D area mapping is supported. |
149 | * | 151 | * |
150 | * NOTE: alignment is always PAGE_SIZE and offset is 0 | 152 | * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped |
153 | * into tiler container. | ||
151 | * | 154 | * |
155 | * @param blk pointer to tiler block data. This must be set up | ||
156 | * ('phys' member must be 0) with the tiler block information. | ||
157 | * 'height' must be 1 for 1D block. | ||
152 | * @param fmt TILER bit mode | 158 | * @param fmt TILER bit mode |
153 | * @param width block width | ||
154 | * @param height block height (must be 1 for 1D) | ||
155 | * @param gid group ID | 159 | * @param gid group ID |
156 | * @param pid process ID | 160 | * @param pid process ID |
157 | * @param sys_addr pointer where system space (L3) address | ||
158 | * will be stored. | ||
159 | * @param usr_addr user space address of existing buffer. | 161 | * @param usr_addr user space address of existing buffer. |
160 | * | 162 | * |
161 | * @return error status | 163 | * @return error status |
162 | */ | 164 | */ |
163 | s32 tiler_mapx(enum tiler_fmt fmt, u32 width, u32 height, | 165 | s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, |
164 | u32 gid, pid_t pid, u32 *sys_addr, u32 usr_addr); | 166 | u32 gid, pid_t pid, u32 usr_addr); |
165 | 167 | ||
166 | /** | 168 | /** |
167 | * Free TILER memory. | 169 | * Frees TILER memory. Since there may be multiple references for the same area |
170 | * if duplicated by tiler_dup, the area is only actually freed if all references | ||
171 | * have been freed. | ||
168 | * | 172 | * |
169 | * @param sys_addr system space (L3) address. | 173 | * @param blk pointer to a tiler block data as filled by tiler_alloc, |
174 | * tiler_map or tiler_dup. 'phys' member will be set to 0 on | ||
175 | * success. | ||
170 | * | 176 | * |
171 | * @return an error status. | 177 | * @return an error status. |
172 | */ | 178 | */ |
173 | s32 tiler_free(u32 sys_addr); | 179 | s32 tiler_free(struct tiler_block_t *blk); |
174 | 180 | ||
175 | /** | 181 | /** |
176 | * Reserves tiler area for n identical set of blocks (buffer) | 182 | * Reserves tiler area for n identical set of blocks (buffer) |
diff --git a/drivers/media/video/tiler/tiler.c b/drivers/media/video/tiler/tiler.c index ed0baa63468..0d3aa51efa8 100644 --- a/drivers/media/video/tiler/tiler.c +++ b/drivers/media/video/tiler/tiler.c | |||
@@ -92,13 +92,13 @@ struct area_info { | |||
92 | 92 | ||
93 | struct mem_info { | 93 | struct mem_info { |
94 | struct list_head global; /* reserved / global blocks */ | 94 | struct list_head global; /* reserved / global blocks */ |
95 | u32 sys_addr; /* system space (L3) tiler addr */ | 95 | struct tiler_block_t blk; /* block info */ |
96 | u32 num_pg; /* number of pages in page-list */ | 96 | u32 num_pg; /* number of pages in page-list */ |
97 | u32 usr; /* user space address */ | 97 | u32 usr; /* user space address */ |
98 | u32 *pg_ptr; /* list of mapped struct page pointers */ | 98 | u32 *pg_ptr; /* list of mapped struct page ptrs */ |
99 | struct tcm_area area; | 99 | struct tcm_area area; |
100 | u32 *mem; /* list of alloced phys addresses */ | 100 | u32 *mem; /* list of alloced phys addresses */ |
101 | u32 refs; /* number of times referenced */ | 101 | u32 refs; /* number of times referenced */ |
102 | bool alloced; /* still alloced */ | 102 | bool alloced; /* still alloced */ |
103 | 103 | ||
104 | struct list_head by_area; /* blocks in the same area / 1D */ | 104 | struct list_head by_area; /* blocks in the same area / 1D */ |
@@ -129,6 +129,48 @@ static struct tmm *tmm[TILER_FORMATS]; | |||
129 | #define TMM_SS(ssptr) TMM(TILER_GET_ACC_MODE(ssptr)) | 129 | #define TMM_SS(ssptr) TMM(TILER_GET_ACC_MODE(ssptr)) |
130 | #define TMM_SET(fmt, i) tmm[(fmt) - TILFMT_8BIT] = i | 130 | #define TMM_SET(fmt, i) tmm[(fmt) - TILFMT_8BIT] = i |
131 | 131 | ||
132 | static const u32 tiler_bpps[4] = { 1, 2, 4, 1 }; | ||
133 | static const u32 tiler_strides[4] = { 16384, 32768, 32768, 0 }; | ||
134 | |||
135 | static u32 is_tiler_addr(u32 addr) | ||
136 | { | ||
137 | return addr >= TILVIEW_8BIT && addr < TILVIEW_END; | ||
138 | } | ||
139 | |||
140 | /* get tiler format */ | ||
141 | static inline u32 tiler_fmt(const struct tiler_block_t *b) | ||
142 | { | ||
143 | if (!is_tiler_addr(b->phys)) | ||
144 | BUG(); | ||
145 | /* return TILER_GET_ACC_MODE(b->phys); */ | ||
146 | return TILFMT_8BIT + (((b->phys - TILVIEW_8BIT) >> 27) & 3); | ||
147 | } | ||
148 | |||
149 | /* get tiler block bpp */ | ||
150 | static inline u32 tiler_bpp(const struct tiler_block_t *b) | ||
151 | { | ||
152 | return tiler_bpps[tiler_fmt(b) - TILFMT_8BIT]; | ||
153 | } | ||
154 | |||
155 | /* get tiler block virtual stride */ | ||
156 | static inline u32 tiler_vstride(const struct tiler_block_t *b) | ||
157 | { | ||
158 | return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width); | ||
159 | } | ||
160 | |||
161 | /* get tiler block physical stride */ | ||
162 | static inline u32 tiler_pstride(const struct tiler_block_t *b) | ||
163 | { | ||
164 | return tiler_strides[tiler_fmt(b) - TILFMT_8BIT] ? : tiler_vstride(b); | ||
165 | } | ||
166 | |||
167 | /* returns the virtual size of the block (for mmap) */ | ||
168 | static inline u32 tiler_size(const struct tiler_block_t *b) | ||
169 | { | ||
170 | return b->height * tiler_vstride(b); | ||
171 | } | ||
172 | |||
173 | |||
132 | /* get process info, and increment refs for device tracking */ | 174 | /* get process info, and increment refs for device tracking */ |
133 | static struct process_info *__get_pi(pid_t pid, bool kernel) | 175 | static struct process_info *__get_pi(pid_t pid, bool kernel) |
134 | { | 176 | { |
@@ -237,7 +279,7 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
237 | } | 279 | } |
238 | 280 | ||
239 | /* get the # of bytes per row in 1 slot */ | 281 | /* get the # of bytes per row in 1 slot */ |
240 | bpp = tilfmt_bpp(fmt); | 282 | bpp = tiler_bpps[fmt - TILFMT_8BIT]; |
241 | slot_row = slot_w * bpp; | 283 | slot_row = slot_w * bpp; |
242 | 284 | ||
243 | /* how many slots are can be accessed via one physical page */ | 285 | /* how many slots are can be accessed via one physical page */ |
@@ -443,8 +485,8 @@ static s32 _m_free(struct mem_info *mi) | |||
443 | } | 485 | } |
444 | kfree(mi->pg_ptr); | 486 | kfree(mi->pg_ptr); |
445 | } else if (mi->mem) { | 487 | } else if (mi->mem) { |
446 | tmm_free(TMM_SS(mi->sys_addr), mi->mem); | 488 | tmm_free(TMM_SS(mi->blk.phys), mi->mem); |
447 | clear_pat(TMM_SS(mi->sys_addr), &mi->area); | 489 | clear_pat(TMM_SS(mi->blk.phys), &mi->area); |
448 | } | 490 | } |
449 | 491 | ||
450 | /* safe deletion as list may not have been assigned */ | 492 | /* safe deletion as list may not have been assigned */ |
@@ -530,7 +572,7 @@ static s32 register_buf(struct __buf_info *_b, struct process_info *pi) | |||
530 | /* find each block */ | 572 | /* find each block */ |
531 | list_for_each_entry(mi, &blocks, global) { | 573 | list_for_each_entry(mi, &blocks, global) { |
532 | for (i = 0; i < num; i++) { | 574 | for (i = 0; i < num; i++) { |
533 | if (!_b->mi[i] && mi->sys_addr == b->blocks[i].ssptr) { | 575 | if (!_b->mi[i] && mi->blk.phys == b->blocks[i].ssptr) { |
534 | _b->mi[i] = mi; | 576 | _b->mi[i] = mi; |
535 | 577 | ||
536 | /* quit if found all*/ | 578 | /* quit if found all*/ |
@@ -774,7 +816,7 @@ static struct mem_info *__get_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
774 | gi->refs--; | 816 | gi->refs--; |
775 | mutex_unlock(&mtx); | 817 | mutex_unlock(&mtx); |
776 | 818 | ||
777 | mi->sys_addr = __get_alias_addr(fmt, mi->area.p0.x, mi->area.p0.y) | 819 | mi->blk.phys = __get_alias_addr(fmt, mi->area.p0.x, mi->area.p0.y) |
778 | + in_offs; | 820 | + in_offs; |
779 | return mi; | 821 | return mi; |
780 | } | 822 | } |
@@ -783,7 +825,7 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) | |||
783 | { | 825 | { |
784 | struct __buf_info *_b = NULL; | 826 | struct __buf_info *_b = NULL; |
785 | struct tiler_buf_info *b = NULL; | 827 | struct tiler_buf_info *b = NULL; |
786 | s32 i = 0, j = 0, k = 0, m = 0, p = 0, bpp = 1; | 828 | s32 i = 0, j = 0, k = 0, m = 0, p = 0; |
787 | struct list_head *pos = NULL; | 829 | struct list_head *pos = NULL; |
788 | struct process_info *pi = filp->private_data; | 830 | struct process_info *pi = filp->private_data; |
789 | 831 | ||
@@ -805,36 +847,15 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) | |||
805 | b = &_b->buf_info; | 847 | b = &_b->buf_info; |
806 | 848 | ||
807 | for (i = 0; i < b->num_blocks; i++) { | 849 | for (i = 0; i < b->num_blocks; i++) { |
808 | if (b->blocks[i].fmt >= TILFMT_8BIT && | 850 | p = tiler_vstride(&_b->mi[i]->blk); |
809 | b->blocks[i].fmt <= TILFMT_32BIT) { | 851 | for (m = j = 0; j < _b->mi[i]->blk.height; j++) { |
810 | /* get line width */ | 852 | /* map each page of the line */ |
811 | bpp = (b->blocks[i].fmt == TILFMT_8BIT ? 1 : | 853 | vma->vm_pgoff = (b->blocks[i].ssptr + m) >> PAGE_SHIFT; |
812 | b->blocks[i].fmt == TILFMT_16BIT ? 2 : 4); | ||
813 | p = PAGE_ALIGN(b->blocks[i].dim.area.width * bpp); | ||
814 | |||
815 | for (j = 0; j < b->blocks[i].dim.area.height; j++) { | ||
816 | /* map each page of the line */ | ||
817 | vma->vm_pgoff = | ||
818 | (b->blocks[i].ssptr + m) >> PAGE_SHIFT; | ||
819 | if (remap_pfn_range(vma, vma->vm_start + k, | ||
820 | (b->blocks[i].ssptr + m) >> PAGE_SHIFT, | ||
821 | p, vma->vm_page_prot)) | ||
822 | return -EAGAIN; | ||
823 | k += p; | ||
824 | if (b->blocks[i].fmt == TILFMT_8BIT) | ||
825 | m += 64*TILER_WIDTH; | ||
826 | else | ||
827 | m += 2*64*TILER_WIDTH; | ||
828 | } | ||
829 | m = 0; | ||
830 | } else if (b->blocks[i].fmt == TILFMT_PAGE) { | ||
831 | vma->vm_pgoff = (b->blocks[i].ssptr) >> PAGE_SHIFT; | ||
832 | p = PAGE_ALIGN(b->blocks[i].dim.len); | ||
833 | if (remap_pfn_range(vma, vma->vm_start + k, | 854 | if (remap_pfn_range(vma, vma->vm_start + k, |
834 | (b->blocks[i].ssptr) >> PAGE_SHIFT, p, | 855 | vma->vm_pgoff, p, vma->vm_page_prot)) |
835 | vma->vm_page_prot)) | 856 | return -EAGAIN; |
836 | return -EAGAIN;; | ||
837 | k += p; | 857 | k += p; |
858 | m += tiler_pstride(&_b->mi[i]->blk); | ||
838 | } | 859 | } |
839 | } | 860 | } |
840 | return 0; | 861 | return 0; |
@@ -874,8 +895,9 @@ static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr) | |||
874 | return res; | 895 | return res; |
875 | } | 896 | } |
876 | 897 | ||
877 | static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, | 898 | static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, |
878 | struct process_info *pi, u32 *sys_addr, u32 usr_addr) | 899 | u32 key, u32 gid, struct process_info *pi, |
900 | struct mem_info **info, u32 usr_addr) | ||
879 | { | 901 | { |
880 | u32 i = 0, tmp = -1, *mem = NULL; | 902 | u32 i = 0, tmp = -1, *mem = NULL; |
881 | u8 write = 0; | 903 | u8 write = 0; |
@@ -887,6 +909,8 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, | |||
887 | struct vm_area_struct *vma = NULL; | 909 | struct vm_area_struct *vma = NULL; |
888 | struct gid_info *gi = NULL; | 910 | struct gid_info *gi = NULL; |
889 | 911 | ||
912 | *info = NULL; | ||
913 | |||
890 | /* we only support mapping a user buffer in page mode */ | 914 | /* we only support mapping a user buffer in page mode */ |
891 | if (fmt != TILFMT_PAGE) | 915 | if (fmt != TILFMT_PAGE) |
892 | return -EPERM; | 916 | return -EPERM; |
@@ -913,7 +937,8 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, | |||
913 | return -ENOMEM; | 937 | return -ENOMEM; |
914 | } | 938 | } |
915 | 939 | ||
916 | *sys_addr = mi->sys_addr; | 940 | mi->blk.width = width; |
941 | mi->blk.height = height; | ||
917 | mi->usr = usr_addr; | 942 | mi->usr = usr_addr; |
918 | 943 | ||
919 | /* allocate pages */ | 944 | /* allocate pages */ |
@@ -979,6 +1004,7 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, | |||
979 | goto fault; | 1004 | goto fault; |
980 | 1005 | ||
981 | res = 0; | 1006 | res = 0; |
1007 | *info = mi; | ||
982 | goto done; | 1008 | goto done; |
983 | fault: | 1009 | fault: |
984 | up_read(&mm->mmap_sem); | 1010 | up_read(&mm->mmap_sem); |
@@ -992,19 +1018,32 @@ done: | |||
992 | return res; | 1018 | return res; |
993 | } | 1019 | } |
994 | 1020 | ||
995 | s32 tiler_mapx(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, | 1021 | s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 gid, |
996 | pid_t pid, u32 *sys_addr, u32 usr_addr) | 1022 | pid_t pid, u32 usr_addr) |
997 | { | 1023 | { |
998 | return map_block(fmt, width, height, gid, __get_pi(pid, true), | 1024 | struct mem_info *mi; |
999 | sys_addr, usr_addr); | 1025 | struct process_info *pi; |
1026 | s32 res; | ||
1027 | |||
1028 | if (!blk || blk->phys) | ||
1029 | BUG(); | ||
1030 | |||
1031 | pi = __get_pi(pid, true); | ||
1032 | if (!pi) | ||
1033 | return -ENOMEM; | ||
1034 | |||
1035 | res = map_block(fmt, blk->width, blk->height, blk->key, gid, pi, &mi, | ||
1036 | usr_addr); | ||
1037 | if (mi) | ||
1038 | blk->phys = mi->blk.phys; | ||
1039 | return res; | ||
1040 | |||
1000 | } | 1041 | } |
1001 | EXPORT_SYMBOL(tiler_mapx); | 1042 | EXPORT_SYMBOL(tiler_mapx); |
1002 | 1043 | ||
1003 | s32 tiler_map(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr, | 1044 | s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr) |
1004 | u32 usr_addr) | ||
1005 | { | 1045 | { |
1006 | return tiler_mapx(fmt, width, height, 0, current->tgid, sys_addr, | 1046 | return tiler_mapx(blk, fmt, 0, current->tgid, usr_addr); |
1007 | usr_addr); | ||
1008 | } | 1047 | } |
1009 | EXPORT_SYMBOL(tiler_map); | 1048 | EXPORT_SYMBOL(tiler_map); |
1010 | 1049 | ||
@@ -1022,7 +1061,7 @@ s32 free_block(u32 sys_addr, struct process_info *pi) | |||
1022 | /* currently we know if block is 1D or 2D by the address */ | 1061 | /* currently we know if block is 1D or 2D by the address */ |
1023 | if (TILER_GET_ACC_MODE(sys_addr) == TILFMT_PAGE) { | 1062 | if (TILER_GET_ACC_MODE(sys_addr) == TILFMT_PAGE) { |
1024 | list_for_each_entry(mi, &gi->onedim, by_area) { | 1063 | list_for_each_entry(mi, &gi->onedim, by_area) { |
1025 | if (mi->sys_addr == sys_addr) { | 1064 | if (mi->blk.phys == sys_addr) { |
1026 | _m_try_free(mi); | 1065 | _m_try_free(mi); |
1027 | res = 0; | 1066 | res = 0; |
1028 | goto done; | 1067 | goto done; |
@@ -1031,7 +1070,7 @@ s32 free_block(u32 sys_addr, struct process_info *pi) | |||
1031 | } else { | 1070 | } else { |
1032 | list_for_each_entry(ai, &gi->areas, by_gid) { | 1071 | list_for_each_entry(ai, &gi->areas, by_gid) { |
1033 | list_for_each_entry(mi, &ai->blocks, by_area) { | 1072 | list_for_each_entry(mi, &ai->blocks, by_area) { |
1034 | if (mi->sys_addr == sys_addr) { | 1073 | if (mi->blk.phys == sys_addr) { |
1035 | _m_try_free(mi); | 1074 | _m_try_free(mi); |
1036 | res = 0; | 1075 | res = 0; |
1037 | goto done; | 1076 | goto done; |
@@ -1048,7 +1087,28 @@ done: | |||
1048 | return res; | 1087 | return res; |
1049 | } | 1088 | } |
1050 | 1089 | ||
1051 | s32 tiler_free(u32 sys_addr) | 1090 | s32 free_block_global(u32 ssptr) |
1091 | { | ||
1092 | struct mem_info *mi; | ||
1093 | s32 res = -ENOENT; | ||
1094 | |||
1095 | mutex_lock(&mtx); | ||
1096 | |||
1097 | /* find block in global list and free it */ | ||
1098 | list_for_each_entry(mi, &blocks, global) { | ||
1099 | if (mi->blk.phys == ssptr) { | ||
1100 | _m_try_free(mi); | ||
1101 | res = 0; | ||
1102 | break; | ||
1103 | } | ||
1104 | } | ||
1105 | mutex_unlock(&mtx); | ||
1106 | |||
1107 | /* for debugging, we can set the PAT entries to DMM_LISA_MAP__0 */ | ||
1108 | return res; | ||
1109 | } | ||
1110 | |||
1111 | s32 tiler_free(struct tiler_block_t *blk) | ||
1052 | { | 1112 | { |
1053 | struct mem_info *mi; | 1113 | struct mem_info *mi; |
1054 | s32 res = -ENOENT; | 1114 | s32 res = -ENOENT; |
@@ -1057,7 +1117,7 @@ s32 tiler_free(u32 sys_addr) | |||
1057 | 1117 | ||
1058 | /* find block in global list and free it */ | 1118 | /* find block in global list and free it */ |
1059 | list_for_each_entry(mi, &blocks, global) { | 1119 | list_for_each_entry(mi, &blocks, global) { |
1060 | if (mi->sys_addr == sys_addr) { | 1120 | if (mi->blk.phys == blk->phys) { |
1061 | _m_try_free(mi); | 1121 | _m_try_free(mi); |
1062 | res = 0; | 1122 | res = 0; |
1063 | break; | 1123 | break; |
@@ -1070,54 +1130,47 @@ s32 tiler_free(u32 sys_addr) | |||
1070 | } | 1130 | } |
1071 | EXPORT_SYMBOL(tiler_free); | 1131 | EXPORT_SYMBOL(tiler_free); |
1072 | 1132 | ||
1073 | /* :TODO: Currently we do not track enough information from alloc to get back | ||
1074 | the actual width and height of the container, so we must make a guess. We | ||
1075 | do not even have enough information to get the virtual stride of the buffer, | ||
1076 | which is the real reason for this ioctl */ | ||
1077 | s32 find_block(u32 sys_addr, struct tiler_block_info *blk) | 1133 | s32 find_block(u32 sys_addr, struct tiler_block_info *blk) |
1078 | { | 1134 | { |
1079 | struct mem_info *i; | 1135 | struct mem_info *i; |
1080 | struct tcm_pt pt; | 1136 | struct tcm_pt pt; |
1081 | 1137 | ||
1138 | if (!is_tiler_addr(sys_addr)) | ||
1139 | return -EFAULT; | ||
1140 | |||
1082 | if (get_area(sys_addr, &pt)) | 1141 | if (get_area(sys_addr, &pt)) |
1083 | return -EFAULT; | 1142 | return -EFAULT; |
1084 | 1143 | ||
1085 | list_for_each_entry(i, &blocks, global) { | 1144 | list_for_each_entry(i, &blocks, global) { |
1086 | if (tcm_is_in(pt, i->area)) | 1145 | if (tiler_fmt(&i->blk) == TILER_GET_ACC_MODE(sys_addr) && |
1146 | tcm_is_in(pt, i->area)) | ||
1087 | goto found; | 1147 | goto found; |
1088 | } | 1148 | } |
1089 | |||
1090 | blk->fmt = TILFMT_INVALID; | ||
1091 | blk->dim.len = blk->stride = blk->ssptr = 0; | ||
1092 | return -EFAULT; | 1149 | return -EFAULT; |
1093 | 1150 | ||
1094 | found: | 1151 | found: |
1095 | blk->ptr = NULL; | 1152 | blk->ptr = NULL; |
1096 | blk->fmt = TILER_GET_ACC_MODE(sys_addr); | 1153 | blk->fmt = TILER_GET_ACC_MODE(i->blk.phys); |
1097 | blk->ssptr = __get_alias_addr(blk->fmt, i->area.p0.x, i->area.p0.y); | 1154 | blk->ssptr = i->blk.phys; |
1098 | 1155 | ||
1099 | if (blk->fmt == TILFMT_PAGE) { | 1156 | if (blk->fmt == TILFMT_PAGE) { |
1100 | blk->dim.len = tcm_sizeof(i->area) * TILER_PAGE; | 1157 | blk->dim.len = i->blk.width; |
1101 | blk->stride = 0; | 1158 | blk->stride = 0; |
1159 | blk->group_id = ((struct gid_info *) i->parent)->gid; | ||
1102 | } else { | 1160 | } else { |
1103 | blk->stride = blk->dim.area.width = | 1161 | blk->stride = tiler_vstride(&i->blk); |
1104 | tcm_awidth(i->area) * TILER_BLOCK_WIDTH; | 1162 | blk->dim.area.width = i->blk.width; |
1105 | blk->dim.area.height = tcm_aheight(i->area) | 1163 | blk->dim.area.height = i->blk.height; |
1106 | * TILER_BLOCK_HEIGHT; | 1164 | blk->group_id = ((struct area_info *) i->parent)->gi->gid; |
1107 | if (blk->fmt != TILFMT_8BIT) { | ||
1108 | blk->stride <<= 1; | ||
1109 | blk->dim.area.height >>= 1; | ||
1110 | if (blk->fmt == TILFMT_32BIT) | ||
1111 | blk->dim.area.width >>= 1; | ||
1112 | } | ||
1113 | blk->stride = PAGE_ALIGN(blk->stride); | ||
1114 | } | 1165 | } |
1166 | blk->offs = i->blk.phys & ~PAGE_MASK; | ||
1167 | blk->align = 0; | ||
1115 | return 0; | 1168 | return 0; |
1116 | } | 1169 | } |
1117 | 1170 | ||
1118 | static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, | 1171 | static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, |
1119 | u32 align, u32 offs, u32 gid, struct process_info *pi, | 1172 | u32 align, u32 offs, u32 key, u32 gid, struct process_info *pi, |
1120 | u32 *sys_addr); | 1173 | struct mem_info **info); |
1121 | 1174 | ||
1122 | static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | 1175 | static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, |
1123 | unsigned long arg) | 1176 | unsigned long arg) |
@@ -1126,12 +1179,12 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1126 | pmd_t *pmd = NULL; | 1179 | pmd_t *pmd = NULL; |
1127 | pte_t *ptep = NULL, pte = 0x0; | 1180 | pte_t *ptep = NULL, pte = 0x0; |
1128 | s32 r = -1; | 1181 | s32 r = -1; |
1129 | u32 til_addr = 0x0; | ||
1130 | struct process_info *pi = filp->private_data; | 1182 | struct process_info *pi = filp->private_data; |
1131 | 1183 | ||
1132 | struct __buf_info *_b = NULL; | 1184 | struct __buf_info *_b = NULL; |
1133 | struct tiler_buf_info buf_info = {0}; | 1185 | struct tiler_buf_info buf_info = {0}; |
1134 | struct tiler_block_info block_info = {0}; | 1186 | struct tiler_block_info block_info = {0}; |
1187 | struct mem_info *mi; | ||
1135 | 1188 | ||
1136 | switch (cmd) { | 1189 | switch (cmd) { |
1137 | case TILIOC_GBLK: | 1190 | case TILIOC_GBLK: |
@@ -1142,7 +1195,9 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1142 | switch (block_info.fmt) { | 1195 | switch (block_info.fmt) { |
1143 | case TILFMT_PAGE: | 1196 | case TILFMT_PAGE: |
1144 | r = alloc_block(block_info.fmt, block_info.dim.len, 1, | 1197 | r = alloc_block(block_info.fmt, block_info.dim.len, 1, |
1145 | 0, 0, 0, pi, &til_addr); | 1198 | block_info.align, block_info.offs, |
1199 | block_info.key, block_info.group_id, | ||
1200 | pi, &mi); | ||
1146 | if (r) | 1201 | if (r) |
1147 | return r; | 1202 | return r; |
1148 | break; | 1203 | break; |
@@ -1152,7 +1207,9 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1152 | r = alloc_block(block_info.fmt, | 1207 | r = alloc_block(block_info.fmt, |
1153 | block_info.dim.area.width, | 1208 | block_info.dim.area.width, |
1154 | block_info.dim.area.height, | 1209 | block_info.dim.area.height, |
1155 | 0, 0, 0, pi, &til_addr); | 1210 | block_info.align, block_info.offs, |
1211 | block_info.key, block_info.group_id, | ||
1212 | pi, &mi); | ||
1156 | if (r) | 1213 | if (r) |
1157 | return r; | 1214 | return r; |
1158 | break; | 1215 | break; |
@@ -1160,7 +1217,10 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1160 | return -EINVAL; | 1217 | return -EINVAL; |
1161 | } | 1218 | } |
1162 | 1219 | ||
1163 | block_info.ssptr = til_addr; | 1220 | if (mi) { |
1221 | block_info.stride = tiler_vstride(&mi->blk); | ||
1222 | block_info.ssptr = mi->blk.phys; | ||
1223 | } | ||
1164 | if (copy_to_user((void __user *)arg, &block_info, | 1224 | if (copy_to_user((void __user *)arg, &block_info, |
1165 | sizeof(block_info))) | 1225 | sizeof(block_info))) |
1166 | return -EFAULT; | 1226 | return -EFAULT; |
@@ -1173,7 +1233,7 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1173 | 1233 | ||
1174 | /* search current process first, then all processes */ | 1234 | /* search current process first, then all processes */ |
1175 | free_block(block_info.ssptr, pi) ? | 1235 | free_block(block_info.ssptr, pi) ? |
1176 | tiler_free(block_info.ssptr) : 0; | 1236 | free_block_global(block_info.ssptr) : 0; |
1177 | 1237 | ||
1178 | /* free always succeeds */ | 1238 | /* free always succeeds */ |
1179 | break; | 1239 | break; |
@@ -1203,10 +1263,16 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1203 | if (!block_info.ptr) | 1263 | if (!block_info.ptr) |
1204 | return -EFAULT; | 1264 | return -EFAULT; |
1205 | 1265 | ||
1206 | if (map_block(block_info.fmt, block_info.dim.len, 1, 0, pi, | 1266 | r = map_block(block_info.fmt, block_info.dim.len, 1, |
1207 | &block_info.ssptr, (u32)block_info.ptr)) | 1267 | block_info.key, block_info.group_id, pi, |
1208 | return -ENOMEM; | 1268 | &mi, (u32)block_info.ptr); |
1269 | if (r) | ||
1270 | return r; | ||
1209 | 1271 | ||
1272 | if (mi) { | ||
1273 | block_info.stride = tiler_vstride(&mi->blk); | ||
1274 | block_info.ssptr = mi->blk.phys; | ||
1275 | } | ||
1210 | if (copy_to_user((void __user *)arg, &block_info, | 1276 | if (copy_to_user((void __user *)arg, &block_info, |
1211 | sizeof(block_info))) | 1277 | sizeof(block_info))) |
1212 | return -EFAULT; | 1278 | return -EFAULT; |
@@ -1292,12 +1358,14 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
1292 | } | 1358 | } |
1293 | 1359 | ||
1294 | s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, | 1360 | s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, |
1295 | u32 align, u32 offs, u32 gid, struct process_info *pi, | 1361 | u32 align, u32 offs, u32 key, u32 gid, struct process_info *pi, |
1296 | u32 *sys_addr) | 1362 | struct mem_info **info) |
1297 | { | 1363 | { |
1298 | struct mem_info *mi = NULL; | 1364 | struct mem_info *mi = NULL; |
1299 | struct gid_info *gi = NULL; | 1365 | struct gid_info *gi = NULL; |
1300 | 1366 | ||
1367 | *info = NULL; | ||
1368 | |||
1301 | /* only support up to page alignment */ | 1369 | /* only support up to page alignment */ |
1302 | if (align > PAGE_SIZE || offs > align || !pi) | 1370 | if (align > PAGE_SIZE || offs > align || !pi) |
1303 | return -EINVAL; | 1371 | return -EINVAL; |
@@ -1320,7 +1388,8 @@ s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, | |||
1320 | return -ENOMEM; | 1388 | return -ENOMEM; |
1321 | } | 1389 | } |
1322 | 1390 | ||
1323 | *sys_addr = mi->sys_addr; | 1391 | mi->blk.width = width; |
1392 | mi->blk.height = height; | ||
1324 | 1393 | ||
1325 | /* allocate and map if mapping is supported */ | 1394 | /* allocate and map if mapping is supported */ |
1326 | if (tmm_can_map(TMM(fmt))) { | 1395 | if (tmm_can_map(TMM(fmt))) { |
@@ -1334,6 +1403,7 @@ s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, | |||
1334 | if (refill_pat(TMM(fmt), &mi->area, mi->mem)) | 1403 | if (refill_pat(TMM(fmt), &mi->area, mi->mem)) |
1335 | goto cleanup; | 1404 | goto cleanup; |
1336 | } | 1405 | } |
1406 | *info = mi; | ||
1337 | return 0; | 1407 | return 0; |
1338 | 1408 | ||
1339 | cleanup: | 1409 | cleanup: |
@@ -1344,22 +1414,35 @@ cleanup: | |||
1344 | 1414 | ||
1345 | } | 1415 | } |
1346 | 1416 | ||
1347 | s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height, | 1417 | s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, |
1348 | u32 align, u32 offs, u32 gid, pid_t pid, u32 *sys_addr) | 1418 | u32 align, u32 offs, u32 gid, pid_t pid) |
1349 | { | 1419 | { |
1350 | return alloc_block(fmt, width, height, align, offs, gid, | 1420 | struct mem_info *mi; |
1351 | __get_pi(pid, true), sys_addr); | 1421 | struct process_info *pi; |
1422 | s32 res; | ||
1423 | |||
1424 | if (!blk || blk->phys) | ||
1425 | BUG(); | ||
1426 | |||
1427 | pi = __get_pi(pid, true); | ||
1428 | if (!pi) | ||
1429 | return -ENOMEM; | ||
1430 | |||
1431 | res = alloc_block(fmt, blk->width, blk->height, align, offs, blk->key, | ||
1432 | gid, pi, &mi); | ||
1433 | if (mi) | ||
1434 | blk->phys = mi->blk.phys; | ||
1435 | return res; | ||
1352 | } | 1436 | } |
1353 | EXPORT_SYMBOL(tiler_allocx); | 1437 | EXPORT_SYMBOL(tiler_allocx); |
1354 | 1438 | ||
1355 | s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr) | 1439 | s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, |
1440 | u32 align, u32 offs) | ||
1356 | { | 1441 | { |
1357 | return tiler_allocx(fmt, width, height, 0, 0, | 1442 | return tiler_allocx(blk, fmt, align, offs, 0, current->tgid); |
1358 | 0, current->tgid, sys_addr); | ||
1359 | } | 1443 | } |
1360 | EXPORT_SYMBOL(tiler_alloc); | 1444 | EXPORT_SYMBOL(tiler_alloc); |
1361 | 1445 | ||
1362 | |||
1363 | static void reserve_nv12_blocks(u32 n, u32 width, u32 height, | 1446 | static void reserve_nv12_blocks(u32 n, u32 width, u32 height, |
1364 | u32 align, u32 offs, u32 gid, pid_t pid) | 1447 | u32 align, u32 offs, u32 gid, pid_t pid) |
1365 | { | 1448 | { |
diff --git a/drivers/media/video/tiler/tiler_def.h b/drivers/media/video/tiler/tiler_def.h index 61212295ebb..d931e18de15 100644 --- a/drivers/media/video/tiler/tiler_def.h +++ b/drivers/media/video/tiler/tiler_def.h | |||
@@ -28,7 +28,13 @@ | |||
28 | #define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) (TILFMT_8BIT + \ | 28 | #define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) (TILFMT_8BIT + \ |
29 | (((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT))) | 29 | (((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT))) |
30 | 30 | ||
31 | #define TILER_ALIAS_BASE (0x60000000) | 31 | #define TILER_ALIAS_BASE 0x60000000u |
32 | #define TILVIEW_8BIT TILER_ALIAS_BASE | ||
33 | #define TILVIEW_16BIT (TILVIEW_8BIT + 0x08000000u) | ||
34 | #define TILVIEW_32BIT (TILVIEW_16BIT + 0x08000000u) | ||
35 | #define TILVIEW_PAGE (TILVIEW_32BIT + 0x08000000u) | ||
36 | #define TILVIEW_END (TILVIEW_PAGE + 0x08000000u) | ||
37 | |||
32 | #define TILER_ACC_MODE_SHIFT (27) | 38 | #define TILER_ACC_MODE_SHIFT (27) |
33 | #define DMM_ACC_MODE_SHIFT (27) | 39 | #define DMM_ACC_MODE_SHIFT (27) |
34 | 40 | ||