tcm.h 10 KB

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