tcm.h 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * TILER container manager specification and support functions for TI
  3. * TILER driver.
  4. *
  5. * Author: Lajos Molnar <[email protected]>
  6. *
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * * Neither the name of Texas Instruments Incorporated nor the names of
  21. * its contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  26. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  27. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  28. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  29. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  30. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  31. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  32. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  33. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  34. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. #ifndef TCM_H
  37. #define TCM_H
  38. struct tcm;
  39. /* point */
  40. struct tcm_pt {
  41. u16 x;
  42. u16 y;
  43. };
  44. /* 1d or 2d area */
  45. struct tcm_area {
  46. bool is2d; /* whether area is 1d or 2d */
  47. struct tcm *tcm; /* parent */
  48. struct tcm_pt p0;
  49. struct tcm_pt p1;
  50. };
  51. struct tcm {
  52. u16 width, height; /* container dimensions */
  53. int lut_id; /* Lookup table identifier */
  54. unsigned int y_offset; /* offset to use for y coordinates */
  55. spinlock_t lock;
  56. unsigned long *bitmap;
  57. size_t map_size;
  58. /* function table */
  59. s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u16 align,
  60. s16 offset, u16 slot_bytes,
  61. struct tcm_area *area);
  62. s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area);
  63. s32 (*free)(struct tcm *tcm, struct tcm_area *area);
  64. void (*deinit)(struct tcm *tcm);
  65. };
  66. /*=============================================================================
  67. BASIC TILER CONTAINER MANAGER INTERFACE
  68. =============================================================================*/
  69. /*
  70. * NOTE:
  71. *
  72. * Since some basic parameter checking is done outside the TCM algorithms,
  73. * TCM implementation do NOT have to check the following:
  74. *
  75. * area pointer is NULL
  76. * width and height fits within container
  77. * number of pages is more than the size of the container
  78. *
  79. */
  80. struct tcm *sita_init(u16 width, u16 height);
  81. /**
  82. * Deinitialize tiler container manager.
  83. *
  84. * @param tcm Pointer to container manager.
  85. *
  86. * @return 0 on success, non-0 error value on error. The call
  87. * should free as much memory as possible and meaningful
  88. * even on failure. Some error codes: -ENODEV: invalid
  89. * manager.
  90. */
  91. static inline void tcm_deinit(struct tcm *tcm)
  92. {
  93. if (tcm)
  94. tcm->deinit(tcm);
  95. }
  96. /**
  97. * Reserves a 2D area in the container.
  98. *
  99. * @param tcm Pointer to container manager.
  100. * @param height Height(in pages) of area to be reserved.
  101. * @param width Width(in pages) of area to be reserved.
  102. * @param align Alignment requirement for top-left corner of area. Not
  103. * all values may be supported by the container manager,
  104. * but it must support 0 (1), 32 and 64.
  105. * 0 value is equivalent to 1.
  106. * @param offset Offset requirement, in bytes. This is the offset
  107. * from a 4KiB aligned virtual address.
  108. * @param slot_bytes Width of slot in bytes
  109. * @param area Pointer to where the reserved area should be stored.
  110. *
  111. * @return 0 on success. Non-0 error code on failure. Also,
  112. * the tcm field of the area will be set to NULL on
  113. * failure. Some error codes: -ENODEV: invalid manager,
  114. * -EINVAL: invalid area, -ENOMEM: not enough space for
  115. * allocation.
  116. */
  117. static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
  118. u16 align, s16 offset, u16 slot_bytes,
  119. struct tcm_area *area)
  120. {
  121. /* perform rudimentary error checking */
  122. s32 res = tcm == NULL ? -ENODEV :
  123. (area == NULL || width == 0 || height == 0 ||
  124. /* align must be a 2 power */
  125. (align & (align - 1))) ? -EINVAL :
  126. (height > tcm->height || width > tcm->width) ? -ENOMEM : 0;
  127. if (!res) {
  128. area->is2d = true;
  129. res = tcm->reserve_2d(tcm, height, width, align, offset,
  130. slot_bytes, area);
  131. area->tcm = res ? NULL : tcm;
  132. }
  133. return res;
  134. }
  135. /**
  136. * Reserves a 1D area in the container.
  137. *
  138. * @param tcm Pointer to container manager.
  139. * @param slots Number of (contiguous) slots to reserve.
  140. * @param area Pointer to where the reserved area should be stored.
  141. *
  142. * @return 0 on success. Non-0 error code on failure. Also,
  143. * the tcm field of the area will be set to NULL on
  144. * failure. Some error codes: -ENODEV: invalid manager,
  145. * -EINVAL: invalid area, -ENOMEM: not enough space for
  146. * allocation.
  147. */
  148. static inline s32 tcm_reserve_1d(struct tcm *tcm, u32 slots,
  149. struct tcm_area *area)
  150. {
  151. /* perform rudimentary error checking */
  152. s32 res = tcm == NULL ? -ENODEV :
  153. (area == NULL || slots == 0) ? -EINVAL :
  154. slots > (tcm->width * (u32) tcm->height) ? -ENOMEM : 0;
  155. if (!res) {
  156. area->is2d = false;
  157. res = tcm->reserve_1d(tcm, slots, area);
  158. area->tcm = res ? NULL : tcm;
  159. }
  160. return res;
  161. }
  162. /**
  163. * Free a previously reserved area from the container.
  164. *
  165. * @param area Pointer to area reserved by a prior call to
  166. * tcm_reserve_1d or tcm_reserve_2d call, whether
  167. * it was successful or not. (Note: all fields of
  168. * the structure must match.)
  169. *
  170. * @return 0 on success. Non-0 error code on failure. Also, the tcm
  171. * field of the area is set to NULL on success to avoid subsequent
  172. * freeing. This call will succeed even if supplying
  173. * the area from a failed reserved call.
  174. */
  175. static inline s32 tcm_free(struct tcm_area *area)
  176. {
  177. s32 res = 0; /* free succeeds by default */
  178. if (area && area->tcm) {
  179. res = area->tcm->free(area->tcm, area);
  180. if (res == 0)
  181. area->tcm = NULL;
  182. }
  183. return res;
  184. }
  185. /*=============================================================================
  186. HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
  187. =============================================================================*/
  188. /**
  189. * This method slices off the topmost 2D slice from the parent area, and stores
  190. * it in the 'slice' parameter. The 'parent' parameter will get modified to
  191. * contain the remaining portion of the area. If the whole parent area can
  192. * fit in a 2D slice, its tcm pointer is set to NULL to mark that it is no
  193. * longer a valid area.
  194. *
  195. * @param parent Pointer to a VALID parent area that will get modified
  196. * @param slice Pointer to the slice area that will get modified
  197. */
  198. static inline void tcm_slice(struct tcm_area *parent, struct tcm_area *slice)
  199. {
  200. *slice = *parent;
  201. /* check if we need to slice */
  202. if (slice->tcm && !slice->is2d &&
  203. slice->p0.y != slice->p1.y &&
  204. (slice->p0.x || (slice->p1.x != slice->tcm->width - 1))) {
  205. /* set end point of slice (start always remains) */
  206. slice->p1.x = slice->tcm->width - 1;
  207. slice->p1.y = (slice->p0.x) ? slice->p0.y : slice->p1.y - 1;
  208. /* adjust remaining area */
  209. parent->p0.x = 0;
  210. parent->p0.y = slice->p1.y + 1;
  211. } else {
  212. /* mark this as the last slice */
  213. parent->tcm = NULL;
  214. }
  215. }
  216. /* Verify if a tcm area is logically valid */
  217. static inline bool tcm_area_is_valid(struct tcm_area *area)
  218. {
  219. return area && area->tcm &&
  220. /* coordinate bounds */
  221. area->p1.x < area->tcm->width &&
  222. area->p1.y < area->tcm->height &&
  223. area->p0.y <= area->p1.y &&
  224. /* 1D coordinate relationship + p0.x check */
  225. ((!area->is2d &&
  226. area->p0.x < area->tcm->width &&
  227. area->p0.x + area->p0.y * area->tcm->width <=
  228. area->p1.x + area->p1.y * area->tcm->width) ||
  229. /* 2D coordinate relationship */
  230. (area->is2d &&
  231. area->p0.x <= area->p1.x));
  232. }
  233. /* see if a coordinate is within an area */
  234. static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
  235. {
  236. u16 i;
  237. if (a->is2d) {
  238. return p->x >= a->p0.x && p->x <= a->p1.x &&
  239. p->y >= a->p0.y && p->y <= a->p1.y;
  240. } else {
  241. i = p->x + p->y * a->tcm->width;
  242. return i >= a->p0.x + a->p0.y * a->tcm->width &&
  243. i <= a->p1.x + a->p1.y * a->tcm->width;
  244. }
  245. }
  246. /* calculate area width */
  247. static inline u16 __tcm_area_width(struct tcm_area *area)
  248. {
  249. return area->p1.x - area->p0.x + 1;
  250. }
  251. /* calculate area height */
  252. static inline u16 __tcm_area_height(struct tcm_area *area)
  253. {
  254. return area->p1.y - area->p0.y + 1;
  255. }
  256. /* calculate number of slots in an area */
  257. static inline u16 __tcm_sizeof(struct tcm_area *area)
  258. {
  259. return area->is2d ?
  260. __tcm_area_width(area) * __tcm_area_height(area) :
  261. (area->p1.x - area->p0.x + 1) + (area->p1.y - area->p0.y) *
  262. area->tcm->width;
  263. }
  264. #define tcm_sizeof(area) __tcm_sizeof(&(area))
  265. #define tcm_awidth(area) __tcm_area_width(&(area))
  266. #define tcm_aheight(area) __tcm_area_height(&(area))
  267. #define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
  268. /* limit a 1D area to the first N pages */
  269. static inline s32 tcm_1d_limit(struct tcm_area *a, u32 num_pg)
  270. {
  271. if (__tcm_sizeof(a) < num_pg)
  272. return -ENOMEM;
  273. if (!num_pg)
  274. return -EINVAL;
  275. a->p1.x = (a->p0.x + num_pg - 1) % a->tcm->width;
  276. a->p1.y = a->p0.y + ((a->p0.x + num_pg - 1) / a->tcm->width);
  277. return 0;
  278. }
  279. /**
  280. * Iterate through 2D slices of a valid area. Behaves
  281. * syntactically as a for(;;) statement.
  282. *
  283. * @param var Name of a local variable of type 'struct
  284. * tcm_area *' that will get modified to
  285. * contain each slice.
  286. * @param area Pointer to the VALID parent area. This
  287. * structure will not get modified
  288. * throughout the loop.
  289. *
  290. */
  291. #define tcm_for_each_slice(var, area, safe) \
  292. for (safe = area, \
  293. tcm_slice(&safe, &var); \
  294. var.tcm; tcm_slice(&safe, &var))
  295. #endif