diff options
author | Lajos Molnar <molnar@ti.com> | 2010-07-17 00:39:41 -0400 |
---|---|---|
committer | Paolo Pisati <paolo.pisati@canonical.com> | 2012-08-17 04:19:02 -0400 |
commit | b13a8b20c3607a331f5d55b110d6a3dbbe676c03 (patch) | |
tree | e601090aa253680ba8408cf73e0b79518a0be684 | |
parent | a5491c9d0de5f33056b336c788d54e864e150c4d (diff) |
TILER: Cleaned up tiler-iface.c and tiler.h, _tiler.h
Updated comments.
Simplified common expression when copying ioctl data.
Simplified block_info filling.
Removed unused variables, initializers, macros.
Fixed issue with registering buffer with no blocks.
Signed-off-by: Lajos Molnar <molnar@ti.com>
Signed-off-by: David Sin <davidsin@ti.com>
TILER: Minor comment & code cleanup
Updated header comments.
Removed extranous headers.
Made ssptr_id flag read-only, as it should not be changed once tiler
is being used.
__analize_area now returns error values.
1D stride is explicitly set to 0 by describe.
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/dmm.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/include/mach/tiler.h | 142 | ||||
-rw-r--r-- | drivers/media/video/tiler/_tiler.h | 21 | ||||
-rw-r--r-- | drivers/media/video/tiler/dmm.c | 1 | ||||
-rw-r--r-- | drivers/media/video/tiler/tcm.h | 2 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler-iface.c | 284 | ||||
-rw-r--r-- | drivers/media/video/tiler/tiler-main.c | 77 | ||||
-rw-r--r-- | drivers/media/video/tiler/tmm-pat.c | 2 | ||||
-rw-r--r-- | drivers/media/video/tiler/tmm.h | 2 |
9 files changed, 274 insertions, 259 deletions
diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-omap2/include/mach/dmm.h index 77f824d2a8c..68b798a22c4 100644 --- a/arch/arm/mach-omap2/include/mach/dmm.h +++ b/arch/arm/mach-omap2/include/mach/dmm.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * dmm.h | 2 | * dmm.h |
3 | * | 3 | * |
4 | * DMM driver support functions for TI OMAP processors. | 4 | * DMM driver support functions for TI DMM-TILER hardware block. |
5 | * | 5 | * |
6 | * Author: David Sin <davidsin@ti.com> | 6 | * Author: David Sin <davidsin@ti.com> |
7 | * | 7 | * |
diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h index a598fe51ffd..84452bc8944 100644 --- a/arch/arm/mach-omap2/include/mach/tiler.h +++ b/arch/arm/mach-omap2/include/mach/tiler.h | |||
@@ -1,7 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * tiler.h | 2 | * tiler.h |
3 | * | 3 | * |
4 | * TILER driver support functions for TI OMAP processors. | 4 | * TILER driver support functions for TI TILER hardware block. |
5 | * | ||
6 | * Authors: Lajos Molnar <molnar@ti.com> | ||
7 | * David Sin <davidsin@ti.com> | ||
5 | * | 8 | * |
6 | * Copyright (C) 2009-2010 Texas Instruments, Inc. | 9 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
7 | * | 10 | * |
@@ -17,8 +20,6 @@ | |||
17 | #ifndef TILER_H | 20 | #ifndef TILER_H |
18 | #define TILER_H | 21 | #define TILER_H |
19 | 22 | ||
20 | #define TILER_MAX_NUM_BLOCKS 16 | ||
21 | |||
22 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
23 | 24 | ||
24 | /* | 25 | /* |
@@ -40,27 +41,29 @@ enum tiler_fmt { | |||
40 | TILFMT_8AND16 = 4, /* used to mark NV12 reserve block */ | 41 | TILFMT_8AND16 = 4, /* used to mark NV12 reserve block */ |
41 | }; | 42 | }; |
42 | 43 | ||
44 | /* tiler block info */ | ||
43 | struct tiler_block_t { | 45 | struct tiler_block_t { |
44 | u32 phys; /* system space (L3) tiler addr */ | 46 | u32 phys; /* system space (L3) tiler addr */ |
45 | u32 width; /* width */ | 47 | u32 width; /* width */ |
46 | u32 height; /* height */ | 48 | u32 height; /* height */ |
47 | u32 key; /* secret key */ | 49 | u32 key; /* secret key */ |
48 | u32 id; /* unique block ID */ | 50 | u32 id; /* unique block ID */ |
49 | }; | 51 | }; |
50 | 52 | ||
53 | /* tiler (image/video frame) view */ | ||
51 | struct tiler_view_t { | 54 | struct tiler_view_t { |
52 | u32 tsptr; /* tiler space addr */ | 55 | u32 tsptr; /* tiler space addr */ |
53 | u32 width; /* width */ | 56 | u32 width; /* width */ |
54 | u32 height; /* height */ | 57 | u32 height; /* height */ |
55 | u32 bpp; /* bytes per pixel */ | 58 | u32 bpp; /* bytes per pixel */ |
56 | s32 h_inc; /* horizontal increment */ | 59 | s32 h_inc; /* horizontal increment */ |
57 | s32 v_inc; /* vertical increment */ | 60 | s32 v_inc; /* vertical increment */ |
58 | }; | 61 | }; |
59 | 62 | ||
60 | /* get tiler format for a physical address */ | 63 | /* get the tiler format for a physical address or TILFMT_INVALID */ |
61 | enum tiler_fmt tiler_fmt(u32 phys); | 64 | enum tiler_fmt tiler_fmt(u32 phys); |
62 | 65 | ||
63 | /* get tiler block bytes-per-pixel */ | 66 | /* get the modified (1 for page mode) bytes-per-pixel for a tiler block */ |
64 | u32 tiler_bpp(const struct tiler_block_t *b); | 67 | u32 tiler_bpp(const struct tiler_block_t *b); |
65 | 68 | ||
66 | /* get tiler block physical stride */ | 69 | /* get tiler block physical stride */ |
@@ -86,7 +89,7 @@ static inline u32 tiler_size(const struct tiler_block_t *b) | |||
86 | * must be 0) with the tiler block information. 'height' must be 1 | 89 | * must be 0) with the tiler block information. 'height' must be 1 |
87 | * for 1D block. | 90 | * for 1D block. |
88 | * @param fmt TILER block format | 91 | * @param fmt TILER block format |
89 | * @param align block alignment (default: PAGE_SIZE) | 92 | * @param align block alignment (default: normally PAGE_SIZE) |
90 | * @param offs block offset | 93 | * @param offs block offset |
91 | * | 94 | * |
92 | * @return error status | 95 | * @return error status |
@@ -101,8 +104,8 @@ s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, | |||
101 | * @param blk pointer to tiler block data. This must be set up ('phys' member | 104 | * @param blk pointer to tiler block data. This must be set up ('phys' member |
102 | * must be 0) with the tiler block information. 'height' must be 1 | 105 | * must be 0) with the tiler block information. 'height' must be 1 |
103 | * for 1D block. | 106 | * for 1D block. |
104 | * @param fmt TILER bit mode | 107 | * @param fmt TILER block format |
105 | * @param align block alignment (default: PAGE_SIZE) | 108 | * @param align block alignment (default: normally PAGE_SIZE) |
106 | * @param offs block offset | 109 | * @param offs block offset |
107 | * @param gid group ID | 110 | * @param gid group ID |
108 | * @param pid process ID | 111 | * @param pid process ID |
@@ -110,7 +113,7 @@ s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, | |||
110 | * @return error status | 113 | * @return error status |
111 | */ | 114 | */ |
112 | s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, | 115 | s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, |
113 | u32 offs, u32 gid, pid_t pid); | 116 | u32 offs, u32 gid, pid_t pid); |
114 | 117 | ||
115 | /** | 118 | /** |
116 | * Mmaps a portion of a tiler block to a virtual address. Use this method in | 119 | * Mmaps a portion of a tiler block to a virtual address. Use this method in |
@@ -120,7 +123,9 @@ s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align, | |||
120 | * @param blk pointer to tiler block data | 123 | * @param blk pointer to tiler block data |
121 | * @param offs offset from where to map (must be page aligned) | 124 | * @param offs offset from where to map (must be page aligned) |
122 | * @param size size of area to map (must be page aligned) | 125 | * @param size size of area to map (must be page aligned) |
123 | * @param addr virtual address | 126 | * @param vma VMM memory area to map to |
127 | * @param voffs offset (from vm_start) in the VMM memory area to start | ||
128 | * mapping at | ||
124 | * | 129 | * |
125 | * @return error status | 130 | * @return error status |
126 | */ | 131 | */ |
@@ -136,11 +141,12 @@ s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size, | |||
136 | * @param offs offset from where to map (must be page aligned) | 141 | * @param offs offset from where to map (must be page aligned) |
137 | * @param size size of area to map (must be page aligned) | 142 | * @param size size of area to map (must be page aligned) |
138 | * @param addr virtual address | 143 | * @param addr virtual address |
144 | * @param mtype ioremap memory type (e.g. MT_DEVICE) | ||
139 | * | 145 | * |
140 | * @return error status | 146 | * @return error status |
141 | */ | 147 | */ |
142 | s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr, | 148 | s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr, |
143 | u32 mtype); | 149 | u32 mtype); |
144 | 150 | ||
145 | /** | 151 | /** |
146 | * Maps an existing buffer to a 1D or 2D TILER area for the | 152 | * Maps an existing buffer to a 1D or 2D TILER area for the |
@@ -152,9 +158,9 @@ s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, u32 addr, | |||
152 | * into tiler container. | 158 | * into tiler container. |
153 | * | 159 | * |
154 | * @param blk pointer to tiler block data. This must be set up | 160 | * @param blk pointer to tiler block data. This must be set up |
155 | * ('phys' member must be 0) with the tiler block information. | 161 | * ('phys' member must be 0) with the tiler block |
156 | * 'height' must be 1 for 1D block. | 162 | * information. 'height' must be 1 for 1D block. |
157 | * @param fmt TILER bit mode | 163 | * @param fmt TILER format |
158 | * @param usr_addr user space address of existing buffer. | 164 | * @param usr_addr user space address of existing buffer. |
159 | * | 165 | * |
160 | * @return error status | 166 | * @return error status |
@@ -171,9 +177,9 @@ s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr); | |||
171 | * into tiler container. | 177 | * into tiler container. |
172 | * | 178 | * |
173 | * @param blk pointer to tiler block data. This must be set up | 179 | * @param blk pointer to tiler block data. This must be set up |
174 | * ('phys' member must be 0) with the tiler block information. | 180 | * ('phys' member must be 0) with the tiler block |
175 | * 'height' must be 1 for 1D block. | 181 | * information. 'height' must be 1 for 1D block. |
176 | * @param fmt TILER bit mode | 182 | * @param fmt TILER format |
177 | * @param gid group ID | 183 | * @param gid group ID |
178 | * @param pid process ID | 184 | * @param pid process ID |
179 | * @param usr_addr user space address of existing buffer. | 185 | * @param usr_addr user space address of existing buffer. |
@@ -181,7 +187,7 @@ s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr); | |||
181 | * @return error status | 187 | * @return error status |
182 | */ | 188 | */ |
183 | s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, | 189 | s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, |
184 | u32 gid, pid_t pid, u32 usr_addr); | 190 | u32 gid, pid_t pid, u32 usr_addr); |
185 | 191 | ||
186 | /** | 192 | /** |
187 | * Frees TILER memory. Since there may be multiple references for the same area | 193 | * Frees TILER memory. Since there may be multiple references for the same area |
@@ -189,34 +195,30 @@ s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, | |||
189 | * have been freed. | 195 | * have been freed. |
190 | * | 196 | * |
191 | * @param blk pointer to a tiler block data as filled by tiler_alloc, | 197 | * @param blk pointer to a tiler block data as filled by tiler_alloc, |
192 | * tiler_map or tiler_dup. 'phys' member will be set to 0 on | 198 | * tiler_map or tiler_dup. 'phys' and 'id' members will be set to |
193 | * success. | 199 | * 0 on success. |
194 | */ | 200 | */ |
195 | void tiler_free(struct tiler_block_t *blk); | 201 | void tiler_free(struct tiler_block_t *blk); |
196 | 202 | ||
197 | /** | 203 | /** |
198 | * Reserves tiler area for n identical blocks for the current | 204 | * Reserves tiler area for n identical blocks for the current process. Use this |
199 | * process. Use this method to get optimal placement of | 205 | * method to get optimal placement of multiple identical tiler blocks; however, |
200 | * multiple identical tiler blocks; however, it may not reserve | 206 | * it may not reserve area if tiler_alloc is equally efficient. |
201 | * area if tiler_alloc is equally efficient. | ||
202 | * | 207 | * |
203 | * @param n number of identical set of blocks | 208 | * @param n number of identical set of blocks |
204 | * @param fmt TILER bit mode | 209 | * @param fmt TILER format |
205 | * @param width block width | 210 | * @param width block width |
206 | * @param height block height (must be 1 for 1D) | 211 | * @param height block height (must be 1 for 1D) |
207 | * @param align block alignment (default: PAGE_SIZE) | 212 | * @param align block alignment (default: PAGE_SIZE) |
208 | * @param offs block offset | 213 | * @param offs block offset |
209 | * | ||
210 | * @return error status | ||
211 | */ | 214 | */ |
212 | s32 tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height, | 215 | void tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height, u32 align, |
213 | u32 align, u32 offs); | 216 | u32 offs); |
214 | 217 | ||
215 | /** | 218 | /** |
216 | * Reserves tiler area for n identical blocks. Use this method | 219 | * Reserves tiler area for n identical blocks. Use this method to get optimal |
217 | * to get optimal placement of multiple identical tiler blocks; | 220 | * placement of multiple identical tiler blocks; however, it may not reserve |
218 | * however, it may not reserve area if tiler_alloc is equally | 221 | * area if tiler_alloc is equally efficient. |
219 | * efficient. | ||
220 | * | 222 | * |
221 | * @param n number of identical set of blocks | 223 | * @param n number of identical set of blocks |
222 | * @param fmt TILER bit mode | 224 | * @param fmt TILER bit mode |
@@ -226,33 +228,27 @@ s32 tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height, | |||
226 | * @param offs block offset | 228 | * @param offs block offset |
227 | * @param gid group ID | 229 | * @param gid group ID |
228 | * @param pid process ID | 230 | * @param pid process ID |
229 | * | ||
230 | * @return error status | ||
231 | */ | 231 | */ |
232 | s32 tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height, | 232 | void tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height, |
233 | u32 align, u32 offs, u32 gid, pid_t pid); | 233 | u32 align, u32 offs, u32 gid, pid_t pid); |
234 | 234 | ||
235 | /** | 235 | /** |
236 | * Reserves tiler area for n identical NV12 blocks for the | 236 | * Reserves tiler area for n identical NV12 blocks for the current process. Use |
237 | * current process. Use this method to get optimal placement of | 237 | * this method to get optimal placement of multiple identical NV12 tiler blocks; |
238 | * multiple identical NV12 tiler blocks; however, it may not | 238 | * however, it may not reserve area if tiler_alloc is equally efficient. |
239 | * reserve area if tiler_alloc is equally efficient. | ||
240 | * | 239 | * |
241 | * @param n number of identical set of blocks | 240 | * @param n number of identical set of blocks |
242 | * @param width block width (Y) | 241 | * @param width block width (Y) |
243 | * @param height block height (Y) | 242 | * @param height block height (Y) |
244 | * @param align block alignment (default: PAGE_SIZE) | 243 | * @param align block alignment (default: PAGE_SIZE) |
245 | * @param offs block offset | 244 | * @param offs block offset |
246 | * | ||
247 | * @return error status | ||
248 | */ | 245 | */ |
249 | s32 tiler_reserve_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs); | 246 | void tiler_reserve_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs); |
250 | 247 | ||
251 | /** | 248 | /** |
252 | * Reserves tiler area for n identical NV12 blocks. Use this | 249 | * Reserves tiler area for n identical NV12 blocks. Use this method to get |
253 | * method to get optimal placement of multiple identical NV12 | 250 | * optimal placement of multiple identical NV12 tiler blocks; however, it may |
254 | * tiler blocks; however, it may not reserve area if tiler_alloc | 251 | * not reserve area if tiler_alloc is equally efficient. |
255 | * is equally efficient. | ||
256 | * | 252 | * |
257 | * @param n number of identical set of blocks | 253 | * @param n number of identical set of blocks |
258 | * @param width block width (Y) | 254 | * @param width block width (Y) |
@@ -261,18 +257,16 @@ s32 tiler_reserve_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs); | |||
261 | * @param offs block offset | 257 | * @param offs block offset |
262 | * @param gid group ID | 258 | * @param gid group ID |
263 | * @param pid process ID | 259 | * @param pid process ID |
264 | * | ||
265 | * @return error status | ||
266 | */ | 260 | */ |
267 | s32 tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs, | 261 | void tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs, |
268 | u32 gid, pid_t pid); | 262 | u32 gid, pid_t pid); |
269 | 263 | ||
270 | /** | 264 | /** |
271 | * Create a view based on a tiler address and width and height | 265 | * Create a view based on a tiler address and width and height |
272 | * | 266 | * |
273 | * This method should only be used as a last resort, if tilview object cannot | 267 | * This method should only be used as a last resort, e.g. if tilview object |
274 | * be passed because of incoherence with other view 2D objects that must be | 268 | * cannot be passed because of incoherence with other view 2D objects that must |
275 | * supported. | 269 | * be supported. |
276 | * | 270 | * |
277 | * @param view Pointer to a view where the information will be stored | 271 | * @param view Pointer to a view where the information will be stored |
278 | * @param ssptr MUST BE a tiler address | 272 | * @param ssptr MUST BE a tiler address |
@@ -333,6 +327,7 @@ s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y); | |||
333 | * ---------------------------- IOCTL Definitions ---------------------------- | 327 | * ---------------------------- IOCTL Definitions ---------------------------- |
334 | */ | 328 | */ |
335 | 329 | ||
330 | /* ioctls */ | ||
336 | #define TILIOC_GBLK _IOWR('z', 100, struct tiler_block_info) | 331 | #define TILIOC_GBLK _IOWR('z', 100, struct tiler_block_info) |
337 | #define TILIOC_FBLK _IOW('z', 101, struct tiler_block_info) | 332 | #define TILIOC_FBLK _IOW('z', 101, struct tiler_block_info) |
338 | #define TILIOC_GSSP _IOWR('z', 102, u32) | 333 | #define TILIOC_GSSP _IOWR('z', 102, u32) |
@@ -350,23 +345,26 @@ struct area { | |||
350 | u16 height; | 345 | u16 height; |
351 | }; | 346 | }; |
352 | 347 | ||
348 | /* userspace tiler block info */ | ||
353 | struct tiler_block_info { | 349 | struct tiler_block_info { |
354 | enum tiler_fmt fmt; | 350 | enum tiler_fmt fmt; |
355 | union { | 351 | union { |
356 | struct area area; | 352 | struct area area; |
357 | u32 len; | 353 | u32 len; |
358 | } dim; | 354 | } dim; |
359 | u32 stride; | 355 | u32 stride; /* stride is not maintained for 1D blocks */ |
360 | void *ptr; | 356 | void *ptr; /* userspace address for mapping existing buffer */ |
361 | u32 id; | 357 | u32 id; |
362 | u32 key; | 358 | u32 key; |
363 | u32 group_id; | 359 | u32 group_id; |
364 | /* alignment requirements for ssptr: ssptr & (align - 1) == offs */ | 360 | u32 align; /* alignment requirements for ssptr */ |
365 | u32 align; | 361 | u32 offs; /* offset (ssptr & (align - 1) will equal offs) */ |
366 | u32 offs; | 362 | u32 ssptr; /* physical address, may not exposed by default */ |
367 | u32 ssptr; | ||
368 | }; | 363 | }; |
369 | 364 | ||
365 | #define TILER_MAX_NUM_BLOCKS 16 | ||
366 | |||
367 | /* userspace tiler buffer info */ | ||
370 | struct tiler_buf_info { | 368 | struct tiler_buf_info { |
371 | u32 num_blocks; | 369 | u32 num_blocks; |
372 | struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS]; | 370 | struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS]; |
@@ -374,6 +372,4 @@ struct tiler_buf_info { | |||
374 | u32 length; /* also used as number of buffers for reservation */ | 372 | u32 length; /* also used as number of buffers for reservation */ |
375 | }; | 373 | }; |
376 | 374 | ||
377 | |||
378 | #endif | 375 | #endif |
379 | |||
diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h index 24031348bf6..aeec9f6de6e 100644 --- a/drivers/media/video/tiler/_tiler.h +++ b/drivers/media/video/tiler/_tiler.h | |||
@@ -1,7 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * _tiler.h | 2 | * _tiler.h |
3 | * | 3 | * |
4 | * TILER driver internal shared definitions for TI OMAP processors. | 4 | * TI TILER driver internal shared definitions. |
5 | * | ||
6 | * Author: Lajos Molnar <molnar@ti.com> | ||
5 | * | 7 | * |
6 | * Copyright (C) 2009-2010 Texas Instruments, Inc. | 8 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
7 | * | 9 | * |
@@ -21,9 +23,6 @@ | |||
21 | #include <mach/tiler.h> | 23 | #include <mach/tiler.h> |
22 | #include "tcm.h" | 24 | #include "tcm.h" |
23 | 25 | ||
24 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
25 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
26 | |||
27 | #define TILER_FORMATS (TILFMT_MAX - TILFMT_MIN + 1) | 26 | #define TILER_FORMATS (TILFMT_MAX - TILFMT_MIN + 1) |
28 | 27 | ||
29 | /* per process (thread group) info */ | 28 | /* per process (thread group) info */ |
@@ -48,6 +47,7 @@ struct gid_info { | |||
48 | struct process_info *pi; /* parent */ | 47 | struct process_info *pi; /* parent */ |
49 | }; | 48 | }; |
50 | 49 | ||
50 | /* info for an area reserved from a container */ | ||
51 | struct area_info { | 51 | struct area_info { |
52 | struct list_head by_gid; /* areas in this pid/gid */ | 52 | struct list_head by_gid; /* areas in this pid/gid */ |
53 | struct list_head blocks; /* blocks in this area */ | 53 | struct list_head blocks; /* blocks in this area */ |
@@ -57,6 +57,7 @@ struct area_info { | |||
57 | struct gid_info *gi; /* link to parent, if still alive */ | 57 | struct gid_info *gi; /* link to parent, if still alive */ |
58 | }; | 58 | }; |
59 | 59 | ||
60 | /* info for a block */ | ||
60 | struct mem_info { | 61 | struct mem_info { |
61 | struct list_head global; /* reserved / global blocks */ | 62 | struct list_head global; /* reserved / global blocks */ |
62 | struct tiler_block_t blk; /* block info */ | 63 | struct tiler_block_t blk; /* block info */ |
@@ -72,6 +73,7 @@ struct mem_info { | |||
72 | void *parent; /* area info for 2D, else group info */ | 73 | void *parent; /* area info for 2D, else group info */ |
73 | }; | 74 | }; |
74 | 75 | ||
76 | /* tiler geometry information */ | ||
75 | struct tiler_geom { | 77 | struct tiler_geom { |
76 | u32 x_shft; /* unused X-bits (as part of bpp) */ | 78 | u32 x_shft; /* unused X-bits (as part of bpp) */ |
77 | u32 y_shft; /* unused Y-bits (as part of bpp) */ | 79 | u32 y_shft; /* unused Y-bits (as part of bpp) */ |
@@ -81,6 +83,7 @@ struct tiler_geom { | |||
81 | u32 bpp_m; /* modified bytes per pixel (=1 for page mode) */ | 83 | u32 bpp_m; /* modified bytes per pixel (=1 for page mode) */ |
82 | }; | 84 | }; |
83 | 85 | ||
86 | /* methods and variables shared between source files */ | ||
84 | struct tiler_ops { | 87 | struct tiler_ops { |
85 | /* block operations */ | 88 | /* block operations */ |
86 | s32 (*alloc) (enum tiler_fmt fmt, u32 width, u32 height, | 89 | s32 (*alloc) (enum tiler_fmt fmt, u32 width, u32 height, |
@@ -93,7 +96,7 @@ struct tiler_ops { | |||
93 | void (*reserve_nv12) (u32 n, u32 width, u32 height, u32 align, u32 offs, | 96 | void (*reserve_nv12) (u32 n, u32 width, u32 height, u32 align, u32 offs, |
94 | u32 gid, struct process_info *pi); | 97 | u32 gid, struct process_info *pi); |
95 | void (*reserve) (u32 n, enum tiler_fmt fmt, u32 width, u32 height, | 98 | void (*reserve) (u32 n, enum tiler_fmt fmt, u32 width, u32 height, |
96 | u32 align, u32 offs, u32 gid, struct process_info *pi); | 99 | u32 align, u32 offs, u32 gid, struct process_info *pi); |
97 | void (*unreserve) (u32 gid, struct process_info *pi); | 100 | void (*unreserve) (u32 gid, struct process_info *pi); |
98 | 101 | ||
99 | /* block access operations */ | 102 | /* block access operations */ |
@@ -103,8 +106,8 @@ struct tiler_ops { | |||
103 | void (*unlock_free) (struct mem_info *mi, bool free); | 106 | void (*unlock_free) (struct mem_info *mi, bool free); |
104 | 107 | ||
105 | s32 (*lay_2d) (enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band, | 108 | s32 (*lay_2d) (enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band, |
106 | u16 align, u16 offs, struct gid_info *gi, | 109 | u16 align, u16 offs, struct gid_info *gi, |
107 | struct list_head *pos); | 110 | struct list_head *pos); |
108 | s32 (*lay_nv12) (int n, u16 w, u16 w1, u16 h, struct gid_info *gi, | 111 | s32 (*lay_nv12) (int n, u16 w, u16 w1, u16 h, struct gid_info *gi, |
109 | u8 *p); | 112 | u8 *p); |
110 | /* group operations */ | 113 | /* group operations */ |
@@ -118,8 +121,8 @@ struct tiler_ops { | |||
118 | 121 | ||
119 | /* area operations */ | 122 | /* area operations */ |
120 | s32 (*analize) (enum tiler_fmt fmt, u32 width, u32 height, | 123 | s32 (*analize) (enum tiler_fmt fmt, u32 width, u32 height, |
121 | u16 *x_area, u16 *y_area, u16 *band, | 124 | u16 *x_area, u16 *y_area, u16 *band, |
122 | u16 *align, u16 *offs, u16 *in_offs); | 125 | u16 *align, u16 *offs, u16 *in_offs); |
123 | 126 | ||
124 | /* process operations */ | 127 | /* process operations */ |
125 | void (*cleanup) (void); | 128 | void (*cleanup) (void); |
diff --git a/drivers/media/video/tiler/dmm.c b/drivers/media/video/tiler/dmm.c index 685a1935a7f..5ca5e7d5fa3 100644 --- a/drivers/media/video/tiler/dmm.c +++ b/drivers/media/video/tiler/dmm.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/platform_device.h> /* platform_device() */ | 22 | #include <linux/platform_device.h> /* platform_device() */ |
23 | #include <linux/err.h> /* IS_ERR() */ | ||
24 | #include <linux/io.h> /* ioremap() */ | 23 | #include <linux/io.h> /* ioremap() */ |
25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
diff --git a/drivers/media/video/tiler/tcm.h b/drivers/media/video/tiler/tcm.h index abeb99b6697..68b0d684dd5 100644 --- a/drivers/media/video/tiler/tcm.h +++ b/drivers/media/video/tiler/tcm.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * tcm.h | 2 | * tcm.h |
3 | * | 3 | * |
4 | * TILER container manager specification and support functions for TI | 4 | * TILER container manager specification and support functions for TI |
5 | * processors. | 5 | * TILER driver. |
6 | * | 6 | * |
7 | * Author: Lajos Molnar <molnar@ti.com> | 7 | * Author: Lajos Molnar <molnar@ti.com> |
8 | * | 8 | * |
diff --git a/drivers/media/video/tiler/tiler-iface.c b/drivers/media/video/tiler/tiler-iface.c index 688af6c8f71..a93cd486e09 100644 --- a/drivers/media/video/tiler/tiler-iface.c +++ b/drivers/media/video/tiler/tiler-iface.c | |||
@@ -1,7 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * tiler-iface.c | 2 | * tiler-iface.c |
3 | * | 3 | * |
4 | * TILER driver interace functions for TI OMAP processors. | 4 | * TILER driver interace functions for TI TILER hardware block. |
5 | * | ||
6 | * Authors: Lajos Molnar <molnar@ti.com> | ||
7 | * David Sin <davidsin@ti.com> | ||
5 | * | 8 | * |
6 | * Copyright (C) 2009-2010 Texas Instruments, Inc. | 9 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
7 | * | 10 | * |
@@ -22,7 +25,7 @@ | |||
22 | #include <linux/sched.h> /* current */ | 25 | #include <linux/sched.h> /* current */ |
23 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
24 | #include <linux/mm_types.h> | 27 | #include <linux/mm_types.h> |
25 | #include <asm/mach/map.h> /* for ioremap_page */ | 28 | #include <asm/mach/map.h> /* for ioremap_page */ |
26 | 29 | ||
27 | #include "_tiler.h" | 30 | #include "_tiler.h" |
28 | 31 | ||
@@ -41,8 +44,8 @@ MODULE_PARM_DESC(offset_lookup, | |||
41 | "Allow looking up a buffer by offset - This is a security risk"); | 44 | "Allow looking up a buffer by offset - This is a security risk"); |
42 | 45 | ||
43 | static struct mutex mtx; | 46 | static struct mutex mtx; |
44 | static struct list_head procs; | 47 | static struct list_head procs; /* list of process info structs */ |
45 | static struct tiler_ops *ops; | 48 | static struct tiler_ops *ops; /* shared methods and variables */ |
46 | 49 | ||
47 | /* | 50 | /* |
48 | * Buffer handling methods | 51 | * Buffer handling methods |
@@ -56,11 +59,10 @@ struct __buf_info { | |||
56 | }; | 59 | }; |
57 | 60 | ||
58 | /* check if an offset is used */ | 61 | /* check if an offset is used */ |
59 | /* must have mutex */ | ||
60 | /*** register_buf */ | ||
61 | static bool _m_offs_in_use(u32 offs, u32 length, struct process_info *pi) | 62 | static bool _m_offs_in_use(u32 offs, u32 length, struct process_info *pi) |
62 | { | 63 | { |
63 | struct __buf_info *_b; | 64 | struct __buf_info *_b; |
65 | /* have mutex */ | ||
64 | list_for_each_entry(_b, &pi->bufs, by_pid) | 66 | list_for_each_entry(_b, &pi->bufs, by_pid) |
65 | if (_b->buf_info.offset < offs + length && | 67 | if (_b->buf_info.offset < offs + length && |
66 | _b->buf_info.offset + _b->buf_info.length > offs) | 68 | _b->buf_info.offset + _b->buf_info.length > offs) |
@@ -69,8 +71,6 @@ static bool _m_offs_in_use(u32 offs, u32 length, struct process_info *pi) | |||
69 | } | 71 | } |
70 | 72 | ||
71 | /* get an offset */ | 73 | /* get an offset */ |
72 | /* must have mutex */ | ||
73 | /*** register_buf */ | ||
74 | static u32 _m_get_offs(struct process_info *pi, u32 length) | 74 | static u32 _m_get_offs(struct process_info *pi, u32 length) |
75 | { | 75 | { |
76 | static u32 offs = 0xda7a; | 76 | static u32 offs = 0xda7a; |
@@ -78,6 +78,8 @@ static u32 _m_get_offs(struct process_info *pi, u32 length) | |||
78 | /* ensure no-one is using this offset */ | 78 | /* ensure no-one is using this offset */ |
79 | while ((offs << PAGE_SHIFT) + length < length || | 79 | while ((offs << PAGE_SHIFT) + length < length || |
80 | _m_offs_in_use(offs << PAGE_SHIFT, length, pi)) { | 80 | _m_offs_in_use(offs << PAGE_SHIFT, length, pi)) { |
81 | /* use a pseudo-random generator to get a new offset to try */ | ||
82 | |||
81 | /* Galois LSF: 20, 17 */ | 83 | /* Galois LSF: 20, 17 */ |
82 | offs = (offs >> 1) ^ (u32)((0 - (offs & 1u)) & 0x90000); | 84 | offs = (offs >> 1) ^ (u32)((0 - (offs & 1u)) & 0x90000); |
83 | } | 85 | } |
@@ -86,14 +88,15 @@ static u32 _m_get_offs(struct process_info *pi, u32 length) | |||
86 | } | 88 | } |
87 | 89 | ||
88 | /* find and lock a block. process_info is optional */ | 90 | /* find and lock a block. process_info is optional */ |
89 | /* must have mutex */ | ||
90 | static struct mem_info * | 91 | static struct mem_info * |
91 | _m_lock_block(u32 key, u32 id, struct process_info *pi) { | 92 | _m_lock_block(u32 key, u32 id, struct process_info *pi) { |
92 | struct gid_info *gi = NULL; | 93 | struct gid_info *gi; |
93 | struct mem_info *mi = NULL; | 94 | struct mem_info *mi; |
94 | 95 | ||
95 | /* if process_info is given, look there first */ | 96 | /* if process_info is given, look there first */ |
96 | if (pi) { | 97 | if (pi) { |
98 | /* have mutex */ | ||
99 | |||
97 | /* find block in process list and free it */ | 100 | /* find block in process list and free it */ |
98 | list_for_each_entry(gi, &pi->groups, by_pid) { | 101 | list_for_each_entry(gi, &pi->groups, by_pid) { |
99 | mi = ops->lock(key, id, gi); | 102 | mi = ops->lock(key, id, gi); |
@@ -107,15 +110,14 @@ _m_lock_block(u32 key, u32 id, struct process_info *pi) { | |||
107 | } | 110 | } |
108 | 111 | ||
109 | /* register a buffer */ | 112 | /* register a buffer */ |
110 | /* must have mutex */ | ||
111 | static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi) | 113 | static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi) |
112 | { | 114 | { |
113 | struct mem_info *mi = NULL; | 115 | struct mem_info *mi; |
114 | struct tiler_buf_info *b = &_b->buf_info; | 116 | struct tiler_buf_info *b = &_b->buf_info; |
115 | u32 i, num = b->num_blocks, offs; | 117 | u32 i, num = b->num_blocks, offs; |
116 | 118 | ||
117 | /* check validity */ | 119 | /* check validity */ |
118 | if (num > TILER_MAX_NUM_BLOCKS) | 120 | if (num > TILER_MAX_NUM_BLOCKS || num == 0) |
119 | return -EINVAL; | 121 | return -EINVAL; |
120 | 122 | ||
121 | /* find each block */ | 123 | /* find each block */ |
@@ -129,6 +131,11 @@ static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi) | |||
129 | return -EACCES; | 131 | return -EACCES; |
130 | } | 132 | } |
131 | _b->mi[i] = mi; | 133 | _b->mi[i] = mi; |
134 | |||
135 | /* we don't keep track of ptr and 1D stride so clear them */ | ||
136 | b->blocks[i].ptr = NULL; | ||
137 | b->blocks[i].stride = 0; | ||
138 | |||
132 | ops->describe(mi, b->blocks + i); | 139 | ops->describe(mi, b->blocks + i); |
133 | b->length += tiler_size(&mi->blk); | 140 | b->length += tiler_size(&mi->blk); |
134 | } | 141 | } |
@@ -138,13 +145,13 @@ static s32 _m_register_buf(struct __buf_info *_b, struct process_info *pi) | |||
138 | b->offset = _m_get_offs(pi, b->length) + offs; | 145 | b->offset = _m_get_offs(pi, b->length) + offs; |
139 | b->length -= offs; | 146 | b->length -= offs; |
140 | 147 | ||
148 | /* have mutex */ | ||
141 | list_add(&_b->by_pid, &pi->bufs); | 149 | list_add(&_b->by_pid, &pi->bufs); |
142 | 150 | ||
143 | return 0; | 151 | return 0; |
144 | } | 152 | } |
145 | 153 | ||
146 | /* unregister a buffer */ | 154 | /* unregister a buffer */ |
147 | /* must have mutex */ | ||
148 | static void _m_unregister_buf(struct __buf_info *_b) | 155 | static void _m_unregister_buf(struct __buf_info *_b) |
149 | { | 156 | { |
150 | u32 i; | 157 | u32 i; |
@@ -164,15 +171,16 @@ static void _m_unregister_buf(struct __buf_info *_b) | |||
164 | * ========================================================================== | 171 | * ========================================================================== |
165 | */ | 172 | */ |
166 | 173 | ||
167 | |||
168 | /* get process info, and increment refs for device tracking */ | 174 | /* get process info, and increment refs for device tracking */ |
169 | static struct process_info *__get_pi(pid_t pid, bool kernel) | 175 | static struct process_info *__get_pi(pid_t pid, bool kernel) |
170 | { | 176 | { |
171 | struct process_info *pi; | 177 | struct process_info *pi; |
172 | 178 | ||
173 | /* treat all processes as the same, kernel processes are still treated | 179 | /* |
174 | differently so not to free kernel allocated areas when a user process | 180 | * treat all processes as the same, kernel processes are still treated |
175 | closes the tiler driver */ | 181 | * differently so not to free kernel allocated areas when a user process |
182 | * closes the tiler driver | ||
183 | */ | ||
176 | if (!security) | 184 | if (!security) |
177 | pid = 0; | 185 | pid = 0; |
178 | 186 | ||
@@ -187,14 +195,15 @@ static struct process_info *__get_pi(pid_t pid, bool kernel) | |||
187 | pi = kmalloc(sizeof(*pi), GFP_KERNEL); | 195 | pi = kmalloc(sizeof(*pi), GFP_KERNEL); |
188 | if (!pi) | 196 | if (!pi) |
189 | goto done; | 197 | goto done; |
190 | |||
191 | memset(pi, 0, sizeof(*pi)); | 198 | memset(pi, 0, sizeof(*pi)); |
199 | |||
192 | pi->pid = pid; | 200 | pi->pid = pid; |
193 | pi->kernel = kernel; | 201 | pi->kernel = kernel; |
194 | INIT_LIST_HEAD(&pi->groups); | 202 | INIT_LIST_HEAD(&pi->groups); |
195 | INIT_LIST_HEAD(&pi->bufs); | 203 | INIT_LIST_HEAD(&pi->bufs); |
196 | list_add(&pi->list, &procs); | 204 | list_add(&pi->list, &procs); |
197 | done: | 205 | done: |
206 | /* increment reference count */ | ||
198 | if (pi && !kernel) | 207 | if (pi && !kernel) |
199 | pi->refs++; | 208 | pi->refs++; |
200 | mutex_unlock(&mtx); | 209 | mutex_unlock(&mtx); |
@@ -202,20 +211,17 @@ done: | |||
202 | } | 211 | } |
203 | 212 | ||
204 | /** | 213 | /** |
205 | * Free all info kept by a process: | 214 | * Free all info kept by a process: all registered buffers, allocated blocks, |
206 | * | 215 | * and unreferenced blocks. Any blocks/areas still referenced will move to the |
207 | * all registered buffers, allocated blocks, and unreferenced | 216 | * orphaned lists to avoid issues if a new process is created with the same pid. |
208 | * blocks. Any blocks/areas still referenced will move to the | ||
209 | * orphaned lists to avoid issues if a new process is created | ||
210 | * with the same pid. | ||
211 | * | ||
212 | * (must have mutex) | ||
213 | */ | 217 | */ |
214 | void _m_free_process_info(struct process_info *pi) | 218 | static void _m_free_process_info(struct process_info *pi) |
215 | { | 219 | { |
216 | struct gid_info *gi, *gi_; | 220 | struct gid_info *gi, *gi_; |
217 | struct __buf_info *_b = NULL, *_b_ = NULL; | 221 | struct __buf_info *_b = NULL, *_b_ = NULL; |
218 | 222 | ||
223 | /* have mutex */ | ||
224 | |||
219 | /* unregister all buffers */ | 225 | /* unregister all buffers */ |
220 | list_for_each_entry_safe(_b, _b_, &pi->bufs, by_pid) | 226 | list_for_each_entry_safe(_b, _b_, &pi->bufs, by_pid) |
221 | _m_unregister_buf(_b); | 227 | _m_unregister_buf(_b); |
@@ -223,15 +229,15 @@ void _m_free_process_info(struct process_info *pi) | |||
223 | BUG_ON(!list_empty(&pi->bufs)); | 229 | BUG_ON(!list_empty(&pi->bufs)); |
224 | 230 | ||
225 | /* free all allocated blocks, and remove unreferenced ones */ | 231 | /* free all allocated blocks, and remove unreferenced ones */ |
226 | list_for_each_entry_safe(gi, gi_, &pi->groups, by_pid) { | 232 | list_for_each_entry_safe(gi, gi_, &pi->groups, by_pid) |
227 | ops->destroy_group(gi); | 233 | ops->destroy_group(gi); |
228 | } | ||
229 | 234 | ||
230 | BUG_ON(!list_empty(&pi->groups)); | 235 | BUG_ON(!list_empty(&pi->groups)); |
231 | list_del(&pi->list); | 236 | list_del(&pi->list); |
232 | kfree(pi); | 237 | kfree(pi); |
233 | } | 238 | } |
234 | 239 | ||
240 | /* Free all info kept by all processes. Called on cleanup. */ | ||
235 | static void destroy_processes(void) | 241 | static void destroy_processes(void) |
236 | { | 242 | { |
237 | struct process_info *pi, *pi_; | 243 | struct process_info *pi, *pi_; |
@@ -250,9 +256,10 @@ static void destroy_processes(void) | |||
250 | * ========================================================================== | 256 | * ========================================================================== |
251 | */ | 257 | */ |
252 | 258 | ||
259 | /* mmap tiler buffer into user's virtual space */ | ||
253 | static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) | 260 | static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) |
254 | { | 261 | { |
255 | struct __buf_info *_b = NULL; | 262 | struct __buf_info *_b; |
256 | struct tiler_buf_info *b = NULL; | 263 | struct tiler_buf_info *b = NULL; |
257 | u32 i, map_offs, map_size, blk_offs, blk_size, mapped_size; | 264 | u32 i, map_offs, map_size, blk_offs, blk_size, mapped_size; |
258 | struct process_info *pi = filp->private_data; | 265 | struct process_info *pi = filp->private_data; |
@@ -261,8 +268,10 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) | |||
261 | 268 | ||
262 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 269 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
263 | 270 | ||
271 | /* find tiler buffer to mmap */ | ||
264 | mutex_lock(&mtx); | 272 | mutex_lock(&mtx); |
265 | list_for_each_entry(_b, &pi->bufs, by_pid) { | 273 | list_for_each_entry(_b, &pi->bufs, by_pid) { |
274 | /* we support partial mmaping of a whole tiler buffer */ | ||
266 | if (offs >= (_b->buf_info.offset & PAGE_MASK) && | 275 | if (offs >= (_b->buf_info.offset & PAGE_MASK) && |
267 | offs + size <= PAGE_ALIGN(_b->buf_info.offset + | 276 | offs + size <= PAGE_ALIGN(_b->buf_info.offset + |
268 | _b->buf_info.length)) { | 277 | _b->buf_info.length)) { |
@@ -271,44 +280,55 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma) | |||
271 | } | 280 | } |
272 | } | 281 | } |
273 | mutex_unlock(&mtx); | 282 | mutex_unlock(&mtx); |
283 | |||
284 | /* we use b to detect if we found the bufffer */ | ||
274 | if (!b) | 285 | if (!b) |
275 | return -ENXIO; | 286 | return -ENXIO; |
276 | 287 | ||
277 | /* mmap relevant blocks */ | 288 | /* mmap relevant blocks */ |
278 | blk_offs = _b->buf_info.offset; | 289 | blk_offs = _b->buf_info.offset; |
290 | |||
291 | /* start at the beginning of the region */ | ||
279 | mapped_size = 0; | 292 | mapped_size = 0; |
280 | for (i = 0; i < b->num_blocks; i++, blk_offs += blk_size) { | 293 | for (i = 0; i < b->num_blocks; i++, blk_offs += blk_size) { |
281 | blk_size = tiler_size(&_b->mi[i]->blk); | 294 | blk_size = tiler_size(&_b->mi[i]->blk); |
295 | /* see if tiler block is inside the requested region */ | ||
282 | if (offs >= blk_offs + blk_size || offs + size < blk_offs) | 296 | if (offs >= blk_offs + blk_size || offs + size < blk_offs) |
283 | continue; | 297 | continue; |
298 | /* get the offset and map size for this particular block */ | ||
284 | map_offs = max(offs, blk_offs) - blk_offs; | 299 | map_offs = max(offs, blk_offs) - blk_offs; |
285 | map_size = min(size - mapped_size, blk_size); | 300 | map_size = min(size - mapped_size, blk_size); |
301 | |||
302 | /* mmap block */ | ||
286 | if (tiler_mmap_blk(&_b->mi[i]->blk, map_offs, map_size, vma, | 303 | if (tiler_mmap_blk(&_b->mi[i]->blk, map_offs, map_size, vma, |
287 | mapped_size)) | 304 | mapped_size)) |
288 | return -EAGAIN; | 305 | return -EAGAIN; |
306 | |||
307 | /* update mmap region pointer */ | ||
289 | mapped_size += map_size; | 308 | mapped_size += map_size; |
290 | } | 309 | } |
291 | return 0; | 310 | return 0; |
292 | } | 311 | } |
293 | 312 | ||
313 | /* ioctl handler */ | ||
294 | static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | 314 | static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, |
295 | unsigned long arg) | 315 | unsigned long arg) |
296 | { | 316 | { |
297 | pgd_t *pgd = NULL; | 317 | pgd_t *pgd; |
298 | pmd_t *pmd = NULL; | 318 | pmd_t *pmd; |
299 | pte_t *ptep = NULL, pte = 0x0; | 319 | pte_t *ptep, pte; |
300 | s32 r = -1; | 320 | s32 r; |
321 | void __user *data = (void __user *)arg; | ||
301 | struct process_info *pi = filp->private_data; | 322 | struct process_info *pi = filp->private_data; |
302 | 323 | struct __buf_info *_b; | |
303 | struct __buf_info *_b = NULL; | ||
304 | struct tiler_buf_info buf_info = {0}; | 324 | struct tiler_buf_info buf_info = {0}; |
305 | struct tiler_block_info block_info = {0}; | 325 | struct tiler_block_info block_info = {0}; |
306 | struct mem_info *mi = NULL; | 326 | struct mem_info *mi; |
307 | 327 | ||
308 | switch (cmd) { | 328 | switch (cmd) { |
329 | /* allocate block */ | ||
309 | case TILIOC_GBLK: | 330 | case TILIOC_GBLK: |
310 | if (copy_from_user(&block_info, (void __user *)arg, | 331 | if (copy_from_user(&block_info, data, sizeof(block_info))) |
311 | sizeof(block_info))) | ||
312 | return -EFAULT; | 332 | return -EFAULT; |
313 | 333 | ||
314 | switch (block_info.fmt) { | 334 | switch (block_info.fmt) { |
@@ -317,8 +337,6 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
317 | block_info.align, block_info.offs, | 337 | block_info.align, block_info.offs, |
318 | block_info.key, block_info.group_id, | 338 | block_info.key, block_info.group_id, |
319 | pi, &mi); | 339 | pi, &mi); |
320 | if (r) | ||
321 | return r; | ||
322 | break; | 340 | break; |
323 | case TILFMT_8BIT: | 341 | case TILFMT_8BIT: |
324 | case TILFMT_16BIT: | 342 | case TILFMT_16BIT: |
@@ -329,45 +347,38 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
329 | block_info.align, block_info.offs, | 347 | block_info.align, block_info.offs, |
330 | block_info.key, block_info.group_id, | 348 | block_info.key, block_info.group_id, |
331 | pi, &mi); | 349 | pi, &mi); |
332 | if (r) | ||
333 | return r; | ||
334 | break; | 350 | break; |
335 | default: | 351 | default: |
336 | return -EINVAL; | 352 | return -EINVAL; |
337 | } | 353 | } |
354 | if (r) | ||
355 | return r; | ||
338 | 356 | ||
357 | /* fill out block info */ | ||
339 | if (mi) { | 358 | if (mi) { |
340 | block_info.id = mi->blk.id; | 359 | block_info.ptr = NULL; |
341 | block_info.stride = tiler_vstride(&mi->blk); | 360 | ops->describe(mi, &block_info); |
342 | block_info.offs = mi->blk.phys & ~PAGE_MASK; | ||
343 | block_info.align = PAGE_SIZE; | ||
344 | #ifdef CONFIG_TILER_EXPOSE_SSPTR | ||
345 | block_info.ssptr = mi->blk.phys; | ||
346 | #endif | ||
347 | } | 361 | } |
348 | if (copy_to_user((void __user *)arg, &block_info, | 362 | |
349 | sizeof(block_info))) | 363 | if (copy_to_user(data, &block_info, sizeof(block_info))) |
350 | return -EFAULT; | 364 | return -EFAULT; |
351 | break; | 365 | break; |
366 | /* free/unmap block */ | ||
352 | case TILIOC_FBLK: | 367 | case TILIOC_FBLK: |
353 | case TILIOC_UMBLK: | 368 | case TILIOC_UMBLK: |
354 | if (copy_from_user(&block_info, (void __user *)arg, | 369 | if (copy_from_user(&block_info, data, sizeof(block_info))) |
355 | sizeof(block_info))) | ||
356 | return -EFAULT; | 370 | return -EFAULT; |
357 | 371 | ||
358 | /* search current process first, then all processes */ | 372 | /* search current process first, then all processes */ |
359 | mutex_lock(&mtx); | 373 | mutex_lock(&mtx); |
360 | mi = _m_lock_block(block_info.key, block_info.id, pi); | 374 | mi = _m_lock_block(block_info.key, block_info.id, pi); |
361 | mutex_unlock(&mtx); | 375 | mutex_unlock(&mtx); |
362 | if (mi) { | 376 | if (mi) |
363 | ops->unlock_free(mi, true); | 377 | ops->unlock_free(mi, true); |
364 | r = 0; | ||
365 | } | ||
366 | r = -EACCES; | ||
367 | 378 | ||
368 | /* free always succeeds */ | 379 | /* free always succeeds */ |
369 | break; | 380 | break; |
370 | 381 | /* get physical address */ | |
371 | case TILIOC_GSSP: | 382 | case TILIOC_GSSP: |
372 | pgd = pgd_offset(current->mm, arg); | 383 | pgd = pgd_offset(current->mm, arg); |
373 | if (!(pgd_none(*pgd) || pgd_bad(*pgd))) { | 384 | if (!(pgd_none(*pgd) || pgd_bad(*pgd))) { |
@@ -382,12 +393,12 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
382 | } | 393 | } |
383 | } | 394 | } |
384 | } | 395 | } |
385 | /* va not in page table */ | 396 | /* va not in page table, return NULL */ |
386 | return 0x0; | 397 | return (s32) NULL; |
387 | break; | 398 | break; |
399 | /* map block */ | ||
388 | case TILIOC_MBLK: | 400 | case TILIOC_MBLK: |
389 | if (copy_from_user(&block_info, (void __user *)arg, | 401 | if (copy_from_user(&block_info, data, sizeof(block_info))) |
390 | sizeof(block_info))) | ||
391 | return -EFAULT; | 402 | return -EFAULT; |
392 | 403 | ||
393 | if (!block_info.ptr) | 404 | if (!block_info.ptr) |
@@ -399,30 +410,26 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
399 | if (r) | 410 | if (r) |
400 | return r; | 411 | return r; |
401 | 412 | ||
402 | if (mi) { | 413 | /* fill out block info */ |
403 | block_info.id = mi->blk.id; | 414 | if (mi) |
404 | block_info.stride = tiler_vstride(&mi->blk); | 415 | ops->describe(mi, &block_info); |
405 | block_info.offs = mi->blk.phys & ~PAGE_MASK; | 416 | |
406 | block_info.align = PAGE_SIZE; | 417 | if (copy_to_user(data, &block_info, sizeof(block_info))) |
407 | #ifdef CONFIG_TILER_EXPOSE_SSPTR | ||
408 | block_info.ssptr = mi->blk.phys; | ||
409 | #endif | ||
410 | } | ||
411 | if (copy_to_user((void __user *)arg, &block_info, | ||
412 | sizeof(block_info))) | ||
413 | return -EFAULT; | 418 | return -EFAULT; |
414 | break; | 419 | break; |
415 | #ifndef CONFIG_TILER_SECURE | 420 | #ifndef CONFIG_TILER_SECURE |
421 | /* query buffer information by offset */ | ||
416 | case TILIOC_QBUF: | 422 | case TILIOC_QBUF: |
417 | if (!offset_lookup) | 423 | if (!offset_lookup) |
418 | return -EPERM; | 424 | return -EPERM; |
419 | 425 | ||
420 | if (copy_from_user(&buf_info, (void __user *)arg, | 426 | if (copy_from_user(&buf_info, data, sizeof(buf_info))) |
421 | sizeof(buf_info))) | ||
422 | return -EFAULT; | 427 | return -EFAULT; |
423 | 428 | ||
429 | /* find buffer */ | ||
424 | mutex_lock(&mtx); | 430 | mutex_lock(&mtx); |
425 | r = -ENOENT; | 431 | r = -ENOENT; |
432 | /* buffer registration is per process */ | ||
426 | list_for_each_entry(_b, &pi->bufs, by_pid) { | 433 | list_for_each_entry(_b, &pi->bufs, by_pid) { |
427 | if (buf_info.offset == _b->buf_info.offset) { | 434 | if (buf_info.offset == _b->buf_info.offset) { |
428 | memcpy(&buf_info, &_b->buf_info, | 435 | memcpy(&buf_info, &_b->buf_info, |
@@ -436,21 +443,21 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
436 | if (r) | 443 | if (r) |
437 | return r; | 444 | return r; |
438 | 445 | ||
439 | if (copy_to_user((void __user *)arg, &_b->buf_info, | 446 | if (copy_to_user(data, &_b->buf_info, sizeof(_b->buf_info))) |
440 | sizeof(_b->buf_info))) | ||
441 | return -EFAULT; | 447 | return -EFAULT; |
442 | break; | 448 | break; |
443 | #endif | 449 | #endif |
450 | /* register buffer */ | ||
444 | case TILIOC_RBUF: | 451 | case TILIOC_RBUF: |
452 | /* save buffer information */ | ||
445 | _b = kmalloc(sizeof(*_b), GFP_KERNEL); | 453 | _b = kmalloc(sizeof(*_b), GFP_KERNEL); |
446 | if (!_b) | 454 | if (!_b) |
447 | return -ENOMEM; | 455 | return -ENOMEM; |
456 | memset(_b, 0, sizeof(*_b)); | ||
448 | 457 | ||
449 | memset(_b, 0x0, sizeof(*_b)); | 458 | if (copy_from_user(&_b->buf_info, data, sizeof(_b->buf_info))) { |
450 | 459 | kfree(_b); | |
451 | if (copy_from_user(&_b->buf_info, (void __user *)arg, | 460 | return -EFAULT; |
452 | sizeof(_b->buf_info))) { | ||
453 | kfree(_b); return -EFAULT; | ||
454 | } | 461 | } |
455 | 462 | ||
456 | mutex_lock(&mtx); | 463 | mutex_lock(&mtx); |
@@ -458,28 +465,31 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
458 | mutex_unlock(&mtx); | 465 | mutex_unlock(&mtx); |
459 | 466 | ||
460 | if (r) { | 467 | if (r) { |
461 | kfree(_b); return -EACCES; | 468 | kfree(_b); |
469 | return -EACCES; | ||
462 | } | 470 | } |
463 | 471 | ||
464 | if (copy_to_user((void __user *)arg, &_b->buf_info, | 472 | /* undu registration on failure */ |
465 | sizeof(_b->buf_info))) { | 473 | if (copy_to_user(data, &_b->buf_info, sizeof(_b->buf_info))) { |
466 | mutex_lock(&mtx); | 474 | mutex_lock(&mtx); |
467 | _m_unregister_buf(_b); | 475 | _m_unregister_buf(_b); |
468 | mutex_unlock(&mtx); | 476 | mutex_unlock(&mtx); |
469 | return -EFAULT; | 477 | return -EFAULT; |
470 | } | 478 | } |
471 | break; | 479 | break; |
480 | /* unregister a buffer */ | ||
472 | case TILIOC_URBUF: | 481 | case TILIOC_URBUF: |
473 | if (copy_from_user(&buf_info, (void __user *)arg, | 482 | if (copy_from_user(&buf_info, data, sizeof(buf_info))) |
474 | sizeof(buf_info))) | ||
475 | return -EFAULT; | 483 | return -EFAULT; |
476 | 484 | ||
485 | /* find buffer */ | ||
477 | r = -EFAULT; | 486 | r = -EFAULT; |
478 | mutex_lock(&mtx); | 487 | mutex_lock(&mtx); |
479 | /* buffer registration is per process */ | 488 | /* buffer registration is per process */ |
480 | list_for_each_entry(_b, &pi->bufs, by_pid) { | 489 | list_for_each_entry(_b, &pi->bufs, by_pid) { |
481 | if (buf_info.offset == _b->buf_info.offset) { | 490 | if (buf_info.offset == _b->buf_info.offset) { |
482 | _m_unregister_buf(_b); | 491 | _m_unregister_buf(_b); |
492 | /* only retrieve buffer length */ | ||
483 | buf_info.length = _b->buf_info.length; | 493 | buf_info.length = _b->buf_info.length; |
484 | r = 0; | 494 | r = 0; |
485 | break; | 495 | break; |
@@ -487,25 +497,25 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
487 | } | 497 | } |
488 | mutex_unlock(&mtx); | 498 | mutex_unlock(&mtx); |
489 | 499 | ||
490 | if (copy_to_user((void __user *)arg, &buf_info, | 500 | if (r) |
491 | sizeof(_b->buf_info))) | 501 | return r; |
492 | return -EFAULT; | ||
493 | 502 | ||
494 | return r; | 503 | if (copy_to_user(data, &buf_info, sizeof(_b->buf_info))) |
504 | return -EFAULT; | ||
495 | break; | 505 | break; |
506 | /* prereserv blocks */ | ||
496 | case TILIOC_PRBLK: | 507 | case TILIOC_PRBLK: |
497 | if (copy_from_user(&block_info, (void __user *)arg, | 508 | if (copy_from_user(&block_info, data, sizeof(block_info))) |
498 | sizeof(block_info))) | ||
499 | return -EFAULT; | 509 | return -EFAULT; |
500 | 510 | ||
501 | if (block_info.fmt == TILFMT_8AND16) { | 511 | if (block_info.fmt == TILFMT_8AND16) |
502 | ops->reserve_nv12(block_info.key, | 512 | ops->reserve_nv12(block_info.key, |
503 | block_info.dim.area.width, | 513 | block_info.dim.area.width, |
504 | block_info.dim.area.height, | 514 | block_info.dim.area.height, |
505 | block_info.align, | 515 | block_info.align, |
506 | block_info.offs, | 516 | block_info.offs, |
507 | block_info.group_id, pi); | 517 | block_info.group_id, pi); |
508 | } else { | 518 | else |
509 | ops->reserve(block_info.key, | 519 | ops->reserve(block_info.key, |
510 | block_info.fmt, | 520 | block_info.fmt, |
511 | block_info.dim.area.width, | 521 | block_info.dim.area.width, |
@@ -513,14 +523,14 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
513 | block_info.align, | 523 | block_info.align, |
514 | block_info.offs, | 524 | block_info.offs, |
515 | block_info.group_id, pi); | 525 | block_info.group_id, pi); |
516 | } | ||
517 | break; | 526 | break; |
527 | /* unreserve blocks */ | ||
518 | case TILIOC_URBLK: | 528 | case TILIOC_URBLK: |
519 | ops->unreserve(arg, pi); | 529 | ops->unreserve(arg, pi); |
520 | break; | 530 | break; |
531 | /* query a tiler block */ | ||
521 | case TILIOC_QBLK: | 532 | case TILIOC_QBLK: |
522 | if (copy_from_user(&block_info, (void __user *)arg, | 533 | if (copy_from_user(&block_info, data, sizeof(block_info))) |
523 | sizeof(block_info))) | ||
524 | return -EFAULT; | 534 | return -EFAULT; |
525 | 535 | ||
526 | if (block_info.id) { | 536 | if (block_info.id) { |
@@ -537,24 +547,26 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, | |||
537 | #endif | 547 | #endif |
538 | return -EPERM; | 548 | return -EPERM; |
539 | 549 | ||
540 | if (mi) { | ||
541 | ops->describe(mi, &block_info); | ||
542 | ops->unlock_free(mi, false); | ||
543 | } | ||
544 | |||
545 | if (!mi) | 550 | if (!mi) |
546 | return -EFAULT; | 551 | return -EFAULT; |
547 | 552 | ||
548 | if (copy_to_user((void __user *)arg, &block_info, | 553 | /* we don't keep track of ptr and 1D stride so clear them */ |
549 | sizeof(block_info))) | 554 | block_info.ptr = NULL; |
555 | block_info.stride = 0; | ||
556 | |||
557 | ops->describe(mi, &block_info); | ||
558 | ops->unlock_free(mi, false); | ||
559 | |||
560 | if (copy_to_user(data, &block_info, sizeof(block_info))) | ||
550 | return -EFAULT; | 561 | return -EFAULT; |
551 | break; | 562 | break; |
552 | default: | 563 | default: |
553 | return -EINVAL; | 564 | return -EINVAL; |
554 | } | 565 | } |
555 | return 0x0; | 566 | return 0; |
556 | } | 567 | } |
557 | 568 | ||
569 | /* open tiler driver */ | ||
558 | static s32 tiler_open(struct inode *ip, struct file *filp) | 570 | static s32 tiler_open(struct inode *ip, struct file *filp) |
559 | { | 571 | { |
560 | struct process_info *pi = __get_pi(current->tgid, false); | 572 | struct process_info *pi = __get_pi(current->tgid, false); |
@@ -562,9 +574,10 @@ static s32 tiler_open(struct inode *ip, struct file *filp) | |||
562 | return -ENOMEM; | 574 | return -ENOMEM; |
563 | 575 | ||
564 | filp->private_data = pi; | 576 | filp->private_data = pi; |
565 | return 0x0; | 577 | return 0; |
566 | } | 578 | } |
567 | 579 | ||
580 | /* close tiler driver */ | ||
568 | static s32 tiler_release(struct inode *ip, struct file *filp) | 581 | static s32 tiler_release(struct inode *ip, struct file *filp) |
569 | { | 582 | { |
570 | struct process_info *pi = filp->private_data; | 583 | struct process_info *pi = filp->private_data; |
@@ -576,16 +589,18 @@ static s32 tiler_release(struct inode *ip, struct file *filp) | |||
576 | 589 | ||
577 | mutex_unlock(&mtx); | 590 | mutex_unlock(&mtx); |
578 | 591 | ||
579 | return 0x0; | 592 | return 0; |
580 | } | 593 | } |
581 | 594 | ||
582 | const struct file_operations tiler_fops = { | 595 | /* tiler driver file operations */ |
596 | static const struct file_operations tiler_fops = { | ||
583 | .open = tiler_open, | 597 | .open = tiler_open, |
584 | .ioctl = tiler_ioctl, | 598 | .ioctl = tiler_ioctl, |
585 | .release = tiler_release, | 599 | .release = tiler_release, |
586 | .mmap = tiler_mmap, | 600 | .mmap = tiler_mmap, |
587 | }; | 601 | }; |
588 | 602 | ||
603 | /* initialize tiler interface */ | ||
589 | void tiler_iface_init(struct tiler_ops *tiler) | 604 | void tiler_iface_init(struct tiler_ops *tiler) |
590 | { | 605 | { |
591 | ops = tiler; | 606 | ops = tiler; |
@@ -606,41 +621,36 @@ void tiler_iface_init(struct tiler_ops *tiler) | |||
606 | * ========================================================================== | 621 | * ========================================================================== |
607 | */ | 622 | */ |
608 | 623 | ||
609 | s32 tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height, | 624 | void tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height, |
610 | u32 align, u32 offs, u32 gid, pid_t pid) | 625 | u32 align, u32 offs, u32 gid, pid_t pid) |
611 | { | 626 | { |
612 | struct process_info *pi = __get_pi(pid, true); | 627 | struct process_info *pi = __get_pi(pid, true); |
613 | 628 | ||
614 | if (pi) | 629 | if (pi) |
615 | ops->reserve(n, fmt, width, height, align, offs, gid, pi); | 630 | ops->reserve(n, fmt, width, height, align, offs, gid, pi); |
616 | return 0; | ||
617 | } | 631 | } |
618 | EXPORT_SYMBOL(tiler_reservex); | 632 | EXPORT_SYMBOL(tiler_reservex); |
619 | 633 | ||
620 | s32 tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height, | 634 | void tiler_reserve(u32 n, enum tiler_fmt fmt, u32 width, u32 height, |
621 | u32 align, u32 offs) | 635 | u32 align, u32 offs) |
622 | { | 636 | { |
623 | return tiler_reservex(n, fmt, width, height, align, offs, | 637 | tiler_reservex(n, fmt, width, height, align, offs, 0, current->tgid); |
624 | 0, current->tgid); | ||
625 | } | 638 | } |
626 | EXPORT_SYMBOL(tiler_reserve); | 639 | EXPORT_SYMBOL(tiler_reserve); |
627 | 640 | ||
628 | /* reserve area for n identical buffers */ | 641 | void tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs, |
629 | s32 tiler_reservex_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs, | ||
630 | u32 gid, pid_t pid) | 642 | u32 gid, pid_t pid) |
631 | { | 643 | { |
632 | struct process_info *pi = __get_pi(pid, true); | 644 | struct process_info *pi = __get_pi(pid, true); |
633 | 645 | ||
634 | if (pi) | 646 | if (pi) |
635 | ops->reserve_nv12(n, width, height, align, offs, gid, pi); | 647 | ops->reserve_nv12(n, width, height, align, offs, gid, pi); |
636 | return 0; | ||
637 | } | 648 | } |
638 | EXPORT_SYMBOL(tiler_reservex_nv12); | 649 | EXPORT_SYMBOL(tiler_reservex_nv12); |
639 | 650 | ||
640 | s32 tiler_reserve_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs) | 651 | void tiler_reserve_nv12(u32 n, u32 width, u32 height, u32 align, u32 offs) |
641 | { | 652 | { |
642 | return tiler_reservex_nv12(n, width, height, align, offs, | 653 | tiler_reservex_nv12(n, width, height, align, offs, 0, current->tgid); |
643 | 0, current->tgid); | ||
644 | } | 654 | } |
645 | EXPORT_SYMBOL(tiler_reserve_nv12); | 655 | EXPORT_SYMBOL(tiler_reserve_nv12); |
646 | 656 | ||
@@ -651,8 +661,7 @@ s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, | |||
651 | struct process_info *pi; | 661 | struct process_info *pi; |
652 | s32 res; | 662 | s32 res; |
653 | 663 | ||
654 | if (!blk || blk->phys) | 664 | BUG_ON(!blk || blk->phys); |
655 | BUG(); | ||
656 | 665 | ||
657 | pi = __get_pi(pid, true); | 666 | pi = __get_pi(pid, true); |
658 | if (!pi) | 667 | if (!pi) |
@@ -682,8 +691,7 @@ s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 gid, | |||
682 | struct process_info *pi; | 691 | struct process_info *pi; |
683 | s32 res; | 692 | s32 res; |
684 | 693 | ||
685 | if (!blk || blk->phys) | 694 | BUG_ON(!blk || blk->phys); |
686 | BUG(); | ||
687 | 695 | ||
688 | pi = __get_pi(pid, true); | 696 | pi = __get_pi(pid, true); |
689 | if (!pi) | 697 | if (!pi) |
@@ -709,22 +717,18 @@ EXPORT_SYMBOL(tiler_map); | |||
709 | s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size, | 717 | s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size, |
710 | struct vm_area_struct *vma, u32 voffs) | 718 | struct vm_area_struct *vma, u32 voffs) |
711 | { | 719 | { |
712 | u32 v, p; | 720 | u32 v, p, len; |
713 | u32 len; /* area to map */ | ||
714 | 721 | ||
715 | /* don't allow mremap */ | 722 | /* don't allow mremap */ |
716 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | 723 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; |
717 | 724 | ||
718 | /* mapping must fit into vma */ | 725 | /* mapping must fit into vma */ |
719 | if (vma->vm_start > vma->vm_start + voffs || | 726 | BUG_ON(vma->vm_start > vma->vm_start + voffs || |
720 | vma->vm_start + voffs > vma->vm_start + voffs + size || | 727 | vma->vm_start + voffs > vma->vm_start + voffs + size || |
721 | vma->vm_start + voffs + size > vma->vm_end) | 728 | vma->vm_start + voffs + size > vma->vm_end); |
722 | BUG(); | ||
723 | 729 | ||
724 | /* mapping must fit into block */ | 730 | /* mapping must fit into block */ |
725 | if (offs > offs + size || | 731 | BUG_ON(offs > offs + size || offs + size > tiler_size(blk)); |
726 | offs + size > tiler_size(blk)) | ||
727 | BUG(); | ||
728 | 732 | ||
729 | v = tiler_vstride(blk); | 733 | v = tiler_vstride(blk); |
730 | p = tiler_pstride(blk); | 734 | p = tiler_pstride(blk); |
@@ -732,6 +736,7 @@ s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size, | |||
732 | /* remap block portion */ | 736 | /* remap block portion */ |
733 | len = v - (offs % v); /* initial area to map */ | 737 | len = v - (offs % v); /* initial area to map */ |
734 | while (size) { | 738 | while (size) { |
739 | /* restrict to size still needs mapping */ | ||
735 | if (len > size) | 740 | if (len > size) |
736 | len = size; | 741 | len = size; |
737 | 742 | ||
@@ -756,13 +761,10 @@ s32 tiler_ioremap_blk(struct tiler_block_t *blk, u32 offs, u32 size, | |||
756 | const struct mem_type *type = get_mem_type(mtype); | 761 | const struct mem_type *type = get_mem_type(mtype); |
757 | 762 | ||
758 | /* mapping must fit into address space */ | 763 | /* mapping must fit into address space */ |
759 | if (addr > addr + size) | 764 | BUG_ON(addr > addr + size); |
760 | BUG(); | ||
761 | 765 | ||
762 | /* mapping must fit into block */ | 766 | /* mapping must fit into block */ |
763 | if (offs > offs + size || | 767 | BUG_ON(offs > offs + size || offs + size > tiler_size(blk)); |
764 | offs + size > tiler_size(blk)) | ||
765 | BUG(); | ||
766 | 768 | ||
767 | v = tiler_vstride(blk); | 769 | v = tiler_vstride(blk); |
768 | p = tiler_pstride(blk); | 770 | p = tiler_pstride(blk); |
diff --git a/drivers/media/video/tiler/tiler-main.c b/drivers/media/video/tiler/tiler-main.c index c755567edd5..19e838f9ec3 100644 --- a/drivers/media/video/tiler/tiler-main.c +++ b/drivers/media/video/tiler/tiler-main.c | |||
@@ -1,7 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * tiler-main.c | 2 | * tiler-main.c |
3 | * | 3 | * |
4 | * TILER driver support functions for TI OMAP processors. | 4 | * TILER driver main support functions for TI TILER hardware block. |
5 | * | ||
6 | * Authors: Lajos Molnar <molnar@ti.com> | ||
7 | * David Sin <davidsin@ti.com> | ||
5 | * | 8 | * |
6 | * Copyright (C) 2009-2010 Texas Instruments, Inc. | 9 | * Copyright (C) 2009-2010 Texas Instruments, Inc. |
7 | * | 10 | * |
@@ -16,39 +19,39 @@ | |||
16 | 19 | ||
17 | #include <linux/init.h> | 20 | #include <linux/init.h> |
18 | #include <linux/module.h> | 21 | #include <linux/module.h> |
19 | #include <linux/cdev.h> /* struct cdev */ | 22 | #include <linux/cdev.h> /* struct cdev */ |
20 | #include <linux/kdev_t.h> /* MKDEV() */ | 23 | #include <linux/kdev_t.h> /* MKDEV() */ |
21 | #include <linux/fs.h> /* register_chrdev_region() */ | 24 | #include <linux/fs.h> /* register_chrdev_region() */ |
22 | #include <linux/device.h> /* struct class */ | 25 | #include <linux/device.h> /* struct class */ |
23 | #include <linux/platform_device.h> /* platform_device() */ | 26 | #include <linux/platform_device.h> /* platform_device() */ |
24 | #include <linux/err.h> /* IS_ERR() */ | 27 | #include <linux/err.h> /* IS_ERR() */ |
25 | /* #include <linux/sched.h> */ | ||
26 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
27 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
28 | #include <linux/dma-mapping.h> | 30 | #include <linux/dma-mapping.h> /* dma_alloc_coherent */ |
29 | #include <linux/pagemap.h> /* page_cache_release() */ | 31 | #include <linux/pagemap.h> /* page_cache_release() */ |
30 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
31 | 33 | ||
32 | #include <mach/dmm.h> | 34 | #include <mach/dmm.h> |
33 | #include "tmm.h" | 35 | #include "tmm.h" |
34 | #include "_tiler.h" | 36 | #include "_tiler.h" |
35 | #include "tcm/tcm-sita.h" /* Algo Specific header */ | 37 | #include "tcm/tcm-sita.h" /* TCM algorithm */ |
36 | |||
37 | #include <linux/syscalls.h> | ||
38 | 38 | ||
39 | static bool ssptr_id = CONFIG_TILER_SSPTR_ID; | 39 | static bool ssptr_id = CONFIG_TILER_SSPTR_ID; |
40 | static uint default_align = CONFIG_TILER_ALIGNMENT; | 40 | static uint default_align = CONFIG_TILER_ALIGNMENT; |
41 | static uint granularity = CONFIG_TILER_GRANULARITY; | 41 | static uint granularity = CONFIG_TILER_GRANULARITY; |
42 | 42 | ||
43 | module_param(ssptr_id, bool, 0644); | 43 | /* |
44 | * We can only change ssptr_id if there are no blocks allocated, so that | ||
45 | * pseudo-random ids and ssptrs do not potentially clash. For now make it | ||
46 | * read-only. | ||
47 | */ | ||
48 | module_param(ssptr_id, bool, 0444); | ||
44 | MODULE_PARM_DESC(ssptr_id, "Use ssptr as block ID"); | 49 | MODULE_PARM_DESC(ssptr_id, "Use ssptr as block ID"); |
45 | module_param_named(align, default_align, uint, 0644); | 50 | module_param_named(align, default_align, uint, 0644); |
46 | MODULE_PARM_DESC(align, "Default block ssptr alignment"); | 51 | MODULE_PARM_DESC(align, "Default block ssptr alignment"); |
47 | module_param_named(grain, granularity, uint, 0644); | 52 | module_param_named(grain, granularity, uint, 0644); |
48 | MODULE_PARM_DESC(grain, "Granularity (bytes)"); | 53 | MODULE_PARM_DESC(grain, "Granularity (bytes)"); |
49 | 54 | ||
50 | struct tiler_ops tiler; | ||
51 | |||
52 | struct tiler_dev { | 55 | struct tiler_dev { |
53 | struct cdev cdev; | 56 | struct cdev cdev; |
54 | }; | 57 | }; |
@@ -63,9 +66,11 @@ struct platform_driver tiler_driver_ldm = { | |||
63 | .remove = NULL, | 66 | .remove = NULL, |
64 | }; | 67 | }; |
65 | 68 | ||
66 | static struct list_head blocks; | 69 | static struct tiler_ops tiler; /* shared methods and variables */ |
67 | static struct list_head orphan_areas; | 70 | |
68 | static struct list_head orphan_onedim; | 71 | static struct list_head blocks; /* all tiler blocks */ |
72 | static struct list_head orphan_areas; /* orphaned 2D areas */ | ||
73 | static struct list_head orphan_onedim; /* orphaned 1D areas */ | ||
69 | 74 | ||
70 | static s32 tiler_major; | 75 | static s32 tiler_major; |
71 | static s32 tiler_minor; | 76 | static s32 tiler_minor; |
@@ -81,6 +86,7 @@ static dma_addr_t dmac_pa; | |||
81 | * TMM connectors | 86 | * TMM connectors |
82 | * ========================================================================== | 87 | * ========================================================================== |
83 | */ | 88 | */ |
89 | /* wrapper around tmm_map */ | ||
84 | static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr) | 90 | static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr) |
85 | { | 91 | { |
86 | s32 res = 0; | 92 | s32 res = 0; |
@@ -105,6 +111,7 @@ static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr) | |||
105 | return res; | 111 | return res; |
106 | } | 112 | } |
107 | 113 | ||
114 | /* wrapper around tmm_clear */ | ||
108 | static void clear_pat(struct tmm *tmm, struct tcm_area *area) | 115 | static void clear_pat(struct tmm *tmm, struct tcm_area *area) |
109 | { | 116 | { |
110 | struct pat_area p_area = {0}; | 117 | struct pat_area p_area = {0}; |
@@ -142,6 +149,8 @@ static u32 _m_get_id(void) | |||
142 | 149 | ||
143 | /* ensure noone is using this id */ | 150 | /* ensure noone is using this id */ |
144 | while (_m_id_in_use(id)) { | 151 | while (_m_id_in_use(id)) { |
152 | /* generate a new pseudo-random ID */ | ||
153 | |||
145 | /* Galois LSFR: 32, 22, 2, 1 */ | 154 | /* Galois LSFR: 32, 22, 2, 1 */ |
146 | id = (id >> 1) ^ (u32)((0 - (id & 1u)) & 0x80200003u); | 155 | id = (id >> 1) ^ (u32)((0 - (id & 1u)) & 0x80200003u); |
147 | } | 156 | } |
@@ -154,11 +163,13 @@ static u32 _m_get_id(void) | |||
154 | * ========================================================================== | 163 | * ========================================================================== |
155 | */ | 164 | */ |
156 | 165 | ||
157 | /* must have mutex */ | 166 | /* get or create new gid_info object */ |
158 | static struct gid_info *_m_get_gi(struct process_info *pi, u32 gid) | 167 | static struct gid_info *_m_get_gi(struct process_info *pi, u32 gid) |
159 | { | 168 | { |
160 | struct gid_info *gi; | 169 | struct gid_info *gi; |
161 | 170 | ||
171 | /* have mutex */ | ||
172 | |||
162 | /* see if group already exist */ | 173 | /* see if group already exist */ |
163 | list_for_each_entry(gi, &pi->groups, by_pid) { | 174 | list_for_each_entry(gi, &pi->groups, by_pid) { |
164 | if (gi->gid == gid) | 175 | if (gi->gid == gid) |
@@ -186,9 +197,10 @@ done: | |||
186 | return gi; | 197 | return gi; |
187 | } | 198 | } |
188 | 199 | ||
189 | /* (must have mutex) */ | 200 | /* free gid_info object if empty */ |
190 | static void _m_try_free_group(struct gid_info *gi) | 201 | static void _m_try_free_group(struct gid_info *gi) |
191 | { | 202 | { |
203 | /* have mutex */ | ||
192 | if (gi && list_empty(&gi->areas) && list_empty(&gi->onedim) && | 204 | if (gi && list_empty(&gi->areas) && list_empty(&gi->onedim) && |
193 | /* also ensure noone is still using this group */ | 205 | /* also ensure noone is still using this group */ |
194 | !gi->refs) { | 206 | !gi->refs) { |
@@ -277,11 +289,11 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
277 | 289 | ||
278 | /* width and height must be positive */ | 290 | /* width and height must be positive */ |
279 | if (!width || !height) | 291 | if (!width || !height) |
280 | return -1; | 292 | return -EINVAL; |
281 | 293 | ||
282 | /* align must be 2 power */ | 294 | /* align must be 2 power */ |
283 | if (*align & (*align - 1)) | 295 | if (*align & (*align - 1)) |
284 | return -1; | 296 | return -EINVAL; |
285 | 297 | ||
286 | if (fmt == TILFMT_PAGE) { | 298 | if (fmt == TILFMT_PAGE) { |
287 | /* adjust size to accomodate offset, only do page alignment */ | 299 | /* adjust size to accomodate offset, only do page alignment */ |
@@ -294,7 +306,7 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
294 | *y_area = *band = 1; | 306 | *y_area = *band = 1; |
295 | 307 | ||
296 | if (*x_area * *y_area > tiler.width * tiler.height) | 308 | if (*x_area * *y_area > tiler.width * tiler.height) |
297 | return -1; | 309 | return -ENOMEM; |
298 | return 0; | 310 | return 0; |
299 | } | 311 | } |
300 | 312 | ||
@@ -310,9 +322,13 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
310 | *band = PAGE_SIZE / slot_row; | 322 | *band = PAGE_SIZE / slot_row; |
311 | 323 | ||
312 | /* minimum alignment is at least 1 slot. Use default if needed */ | 324 | /* minimum alignment is at least 1 slot. Use default if needed */ |
313 | min_align = MAX(slot_row, granularity); | 325 | min_align = max(slot_row, granularity); |
314 | *align = ALIGN(*align ? : default_align, min_align); | 326 | *align = ALIGN(*align ? : default_align, min_align); |
315 | 327 | ||
328 | /* align must still be 2 power (in case default_align is wrong) */ | ||
329 | if (*align & (*align - 1)) | ||
330 | return -EAGAIN; | ||
331 | |||
316 | /* offset must be multiple of bpp */ | 332 | /* offset must be multiple of bpp */ |
317 | if (*offs & (g->bpp - 1) || *offs >= *align) | 333 | if (*offs & (g->bpp - 1) || *offs >= *align) |
318 | return -EINVAL; | 334 | return -EINVAL; |
@@ -334,8 +350,8 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height, | |||
334 | *offs /= slot_row; | 350 | *offs /= slot_row; |
335 | 351 | ||
336 | if (*x_area > tiler.width || *y_area > tiler.height) | 352 | if (*x_area > tiler.width || *y_area > tiler.height) |
337 | return -1; | 353 | return -ENOMEM; |
338 | return 0x0; | 354 | return 0; |
339 | } | 355 | } |
340 | 356 | ||
341 | /** | 357 | /** |
@@ -811,13 +827,12 @@ found: | |||
811 | /* find a block by ssptr */ | 827 | /* find a block by ssptr */ |
812 | static void fill_block_info(struct mem_info *i, struct tiler_block_info *blk) | 828 | static void fill_block_info(struct mem_info *i, struct tiler_block_info *blk) |
813 | { | 829 | { |
814 | blk->ptr = NULL; | ||
815 | blk->fmt = tiler_fmt(i->blk.phys); | 830 | blk->fmt = tiler_fmt(i->blk.phys); |
831 | #ifdef CONFIG_TILER_EXPOSE_SSPTR | ||
816 | blk->ssptr = i->blk.phys; | 832 | blk->ssptr = i->blk.phys; |
817 | 833 | #endif | |
818 | if (blk->fmt == TILFMT_PAGE) { | 834 | if (blk->fmt == TILFMT_PAGE) { |
819 | blk->dim.len = i->blk.width; | 835 | blk->dim.len = i->blk.width; |
820 | blk->stride = 0; | ||
821 | blk->group_id = ((struct gid_info *) i->parent)->gid; | 836 | blk->group_id = ((struct gid_info *) i->parent)->gid; |
822 | } else { | 837 | } else { |
823 | blk->stride = tiler_vstride(&i->blk); | 838 | blk->stride = tiler_vstride(&i->blk); |
@@ -1248,7 +1263,7 @@ static void __exit tiler_exit(void) | |||
1248 | } | 1263 | } |
1249 | 1264 | ||
1250 | MODULE_LICENSE("GPL v2"); | 1265 | MODULE_LICENSE("GPL v2"); |
1251 | MODULE_AUTHOR("David Sin <davidsin@ti.com>"); | ||
1252 | MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>"); | 1266 | MODULE_AUTHOR("Lajos Molnar <molnar@ti.com>"); |
1267 | MODULE_AUTHOR("David Sin <davidsin@ti.com>"); | ||
1253 | module_init(tiler_init); | 1268 | module_init(tiler_init); |
1254 | module_exit(tiler_exit); | 1269 | module_exit(tiler_exit); |
diff --git a/drivers/media/video/tiler/tmm-pat.c b/drivers/media/video/tiler/tmm-pat.c index bfef67cbe39..d33866b125e 100644 --- a/drivers/media/video/tiler/tmm-pat.c +++ b/drivers/media/video/tiler/tmm-pat.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * tmm-pat.c | 2 | * tmm-pat.c |
3 | * | 3 | * |
4 | * DMM driver support functions for TI OMAP processors. | 4 | * DMM driver support functions for TI TILER hardware block. |
5 | * | 5 | * |
6 | * Author: Lajos Molnar <molnar@ti.com>, David Sin <dsin@ti.com> | 6 | * Author: Lajos Molnar <molnar@ti.com>, David Sin <dsin@ti.com> |
7 | * | 7 | * |
diff --git a/drivers/media/video/tiler/tmm.h b/drivers/media/video/tiler/tmm.h index 31470b3e44d..fbdc1e23d0e 100644 --- a/drivers/media/video/tiler/tmm.h +++ b/drivers/media/video/tiler/tmm.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * tmm.h | 2 | * tmm.h |
3 | * | 3 | * |
4 | * TMM interface definition for TI TILER. | 4 | * TMM interface definition for TI TILER driver. |
5 | * | 5 | * |
6 | * Author: Lajos Molnar <molnar@ti.com> | 6 | * Author: Lajos Molnar <molnar@ti.com> |
7 | * | 7 | * |