root/drivers/gpu/drm/omapdrm/tcm.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. tcm_deinit
  2. tcm_reserve_2d
  3. tcm_reserve_1d
  4. tcm_free
  5. tcm_slice
  6. tcm_area_is_valid
  7. __tcm_is_in
  8. __tcm_area_width
  9. __tcm_area_height
  10. __tcm_sizeof
  11. tcm_1d_limit

   1 /*
   2  * TILER container manager specification and support functions for TI
   3  * TILER driver.
   4  *
   5  * Author: Lajos Molnar <molnar@ti.com>
   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 
  37 #ifndef TCM_H
  38 #define TCM_H
  39 
  40 struct tcm;
  41 
  42 /* point */
  43 struct tcm_pt {
  44         u16 x;
  45         u16 y;
  46 };
  47 
  48 /* 1d or 2d area */
  49 struct tcm_area {
  50         bool is2d;              /* whether area is 1d or 2d */
  51         struct tcm    *tcm;     /* parent */
  52         struct tcm_pt  p0;
  53         struct tcm_pt  p1;
  54 };
  55 
  56 struct tcm {
  57         u16 width, height;      /* container dimensions */
  58         int lut_id;             /* Lookup table identifier */
  59 
  60         unsigned int y_offset;  /* offset to use for y coordinates */
  61 
  62         spinlock_t lock;
  63         unsigned long *bitmap;
  64         size_t map_size;
  65 
  66         /* function table */
  67         s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u16 align,
  68                           s16 offset, u16 slot_bytes,
  69                           struct tcm_area *area);
  70         s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area);
  71         s32 (*free)(struct tcm *tcm, struct tcm_area *area);
  72         void (*deinit)(struct tcm *tcm);
  73 };
  74 
  75 /*=============================================================================
  76     BASIC TILER CONTAINER MANAGER INTERFACE
  77 =============================================================================*/
  78 
  79 /*
  80  * NOTE:
  81  *
  82  * Since some basic parameter checking is done outside the TCM algorithms,
  83  * TCM implementation do NOT have to check the following:
  84  *
  85  *   area pointer is NULL
  86  *   width and height fits within container
  87  *   number of pages is more than the size of the container
  88  *
  89  */
  90 
  91 struct tcm *sita_init(u16 width, u16 height);
  92 
  93 
  94 /**
  95  * Deinitialize tiler container manager.
  96  *
  97  * @param tcm   Pointer to container manager.
  98  *
  99  * @return 0 on success, non-0 error value on error.  The call
 100  *         should free as much memory as possible and meaningful
 101  *         even on failure.  Some error codes: -ENODEV: invalid
 102  *         manager.
 103  */
 104 static inline void tcm_deinit(struct tcm *tcm)
 105 {
 106         if (tcm)
 107                 tcm->deinit(tcm);
 108 }
 109 
 110 /**
 111  * Reserves a 2D area in the container.
 112  *
 113  * @param tcm           Pointer to container manager.
 114  * @param height        Height(in pages) of area to be reserved.
 115  * @param width         Width(in pages) of area to be reserved.
 116  * @param align         Alignment requirement for top-left corner of area. Not
 117  *                      all values may be supported by the container manager,
 118  *                      but it must support 0 (1), 32 and 64.
 119  *                      0 value is equivalent to 1.
 120  * @param offset        Offset requirement, in bytes.  This is the offset
 121  *                      from a 4KiB aligned virtual address.
 122  * @param slot_bytes    Width of slot in bytes
 123  * @param area          Pointer to where the reserved area should be stored.
 124  *
 125  * @return 0 on success.  Non-0 error code on failure.  Also,
 126  *         the tcm field of the area will be set to NULL on
 127  *         failure.  Some error codes: -ENODEV: invalid manager,
 128  *         -EINVAL: invalid area, -ENOMEM: not enough space for
 129  *          allocation.
 130  */
 131 static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
 132                                 u16 align, s16 offset, u16 slot_bytes,
 133                                 struct tcm_area *area)
 134 {
 135         /* perform rudimentary error checking */
 136         s32 res = tcm  == NULL ? -ENODEV :
 137                 (area == NULL || width == 0 || height == 0 ||
 138                  /* align must be a 2 power */
 139                  (align & (align - 1))) ? -EINVAL :
 140                 (height > tcm->height || width > tcm->width) ? -ENOMEM : 0;
 141 
 142         if (!res) {
 143                 area->is2d = true;
 144                 res = tcm->reserve_2d(tcm, height, width, align, offset,
 145                                         slot_bytes, area);
 146                 area->tcm = res ? NULL : tcm;
 147         }
 148 
 149         return res;
 150 }
 151 
 152 /**
 153  * Reserves a 1D area in the container.
 154  *
 155  * @param tcm           Pointer to container manager.
 156  * @param slots         Number of (contiguous) slots to reserve.
 157  * @param area          Pointer to where the reserved area should be stored.
 158  *
 159  * @return 0 on success.  Non-0 error code on failure.  Also,
 160  *         the tcm field of the area will be set to NULL on
 161  *         failure.  Some error codes: -ENODEV: invalid manager,
 162  *         -EINVAL: invalid area, -ENOMEM: not enough space for
 163  *          allocation.
 164  */
 165 static inline s32 tcm_reserve_1d(struct tcm *tcm, u32 slots,
 166                                  struct tcm_area *area)
 167 {
 168         /* perform rudimentary error checking */
 169         s32 res = tcm  == NULL ? -ENODEV :
 170                 (area == NULL || slots == 0) ? -EINVAL :
 171                 slots > (tcm->width * (u32) tcm->height) ? -ENOMEM : 0;
 172 
 173         if (!res) {
 174                 area->is2d = false;
 175                 res = tcm->reserve_1d(tcm, slots, area);
 176                 area->tcm = res ? NULL : tcm;
 177         }
 178 
 179         return res;
 180 }
 181 
 182 /**
 183  * Free a previously reserved area from the container.
 184  *
 185  * @param area  Pointer to area reserved by a prior call to
 186  *              tcm_reserve_1d or tcm_reserve_2d call, whether
 187  *              it was successful or not. (Note: all fields of
 188  *              the structure must match.)
 189  *
 190  * @return 0 on success.  Non-0 error code on failure.  Also, the tcm
 191  *         field of the area is set to NULL on success to avoid subsequent
 192  *         freeing.  This call will succeed even if supplying
 193  *         the area from a failed reserved call.
 194  */
 195 static inline s32 tcm_free(struct tcm_area *area)
 196 {
 197         s32 res = 0; /* free succeeds by default */
 198 
 199         if (area && area->tcm) {
 200                 res = area->tcm->free(area->tcm, area);
 201                 if (res == 0)
 202                         area->tcm = NULL;
 203         }
 204 
 205         return res;
 206 }
 207 
 208 /*=============================================================================
 209     HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
 210 =============================================================================*/
 211 
 212 /**
 213  * This method slices off the topmost 2D slice from the parent area, and stores
 214  * it in the 'slice' parameter.  The 'parent' parameter will get modified to
 215  * contain the remaining portion of the area.  If the whole parent area can
 216  * fit in a 2D slice, its tcm pointer is set to NULL to mark that it is no
 217  * longer a valid area.
 218  *
 219  * @param parent        Pointer to a VALID parent area that will get modified
 220  * @param slice         Pointer to the slice area that will get modified
 221  */
 222 static inline void tcm_slice(struct tcm_area *parent, struct tcm_area *slice)
 223 {
 224         *slice = *parent;
 225 
 226         /* check if we need to slice */
 227         if (slice->tcm && !slice->is2d &&
 228                 slice->p0.y != slice->p1.y &&
 229                 (slice->p0.x || (slice->p1.x != slice->tcm->width - 1))) {
 230                 /* set end point of slice (start always remains) */
 231                 slice->p1.x = slice->tcm->width - 1;
 232                 slice->p1.y = (slice->p0.x) ? slice->p0.y : slice->p1.y - 1;
 233                 /* adjust remaining area */
 234                 parent->p0.x = 0;
 235                 parent->p0.y = slice->p1.y + 1;
 236         } else {
 237                 /* mark this as the last slice */
 238                 parent->tcm = NULL;
 239         }
 240 }
 241 
 242 /* Verify if a tcm area is logically valid */
 243 static inline bool tcm_area_is_valid(struct tcm_area *area)
 244 {
 245         return area && area->tcm &&
 246                 /* coordinate bounds */
 247                 area->p1.x < area->tcm->width &&
 248                 area->p1.y < area->tcm->height &&
 249                 area->p0.y <= area->p1.y &&
 250                 /* 1D coordinate relationship + p0.x check */
 251                 ((!area->is2d &&
 252                   area->p0.x < area->tcm->width &&
 253                   area->p0.x + area->p0.y * area->tcm->width <=
 254                   area->p1.x + area->p1.y * area->tcm->width) ||
 255                  /* 2D coordinate relationship */
 256                  (area->is2d &&
 257                   area->p0.x <= area->p1.x));
 258 }
 259 
 260 /* see if a coordinate is within an area */
 261 static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
 262 {
 263         u16 i;
 264 
 265         if (a->is2d) {
 266                 return p->x >= a->p0.x && p->x <= a->p1.x &&
 267                        p->y >= a->p0.y && p->y <= a->p1.y;
 268         } else {
 269                 i = p->x + p->y * a->tcm->width;
 270                 return i >= a->p0.x + a->p0.y * a->tcm->width &&
 271                        i <= a->p1.x + a->p1.y * a->tcm->width;
 272         }
 273 }
 274 
 275 /* calculate area width */
 276 static inline u16 __tcm_area_width(struct tcm_area *area)
 277 {
 278         return area->p1.x - area->p0.x + 1;
 279 }
 280 
 281 /* calculate area height */
 282 static inline u16 __tcm_area_height(struct tcm_area *area)
 283 {
 284         return area->p1.y - area->p0.y + 1;
 285 }
 286 
 287 /* calculate number of slots in an area */
 288 static inline u16 __tcm_sizeof(struct tcm_area *area)
 289 {
 290         return area->is2d ?
 291                 __tcm_area_width(area) * __tcm_area_height(area) :
 292                 (area->p1.x - area->p0.x + 1) + (area->p1.y - area->p0.y) *
 293                                                         area->tcm->width;
 294 }
 295 #define tcm_sizeof(area) __tcm_sizeof(&(area))
 296 #define tcm_awidth(area) __tcm_area_width(&(area))
 297 #define tcm_aheight(area) __tcm_area_height(&(area))
 298 #define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
 299 
 300 /* limit a 1D area to the first N pages */
 301 static inline s32 tcm_1d_limit(struct tcm_area *a, u32 num_pg)
 302 {
 303         if (__tcm_sizeof(a) < num_pg)
 304                 return -ENOMEM;
 305         if (!num_pg)
 306                 return -EINVAL;
 307 
 308         a->p1.x = (a->p0.x + num_pg - 1) % a->tcm->width;
 309         a->p1.y = a->p0.y + ((a->p0.x + num_pg - 1) / a->tcm->width);
 310         return 0;
 311 }
 312 
 313 /**
 314  * Iterate through 2D slices of a valid area. Behaves
 315  * syntactically as a for(;;) statement.
 316  *
 317  * @param var           Name of a local variable of type 'struct
 318  *                      tcm_area *' that will get modified to
 319  *                      contain each slice.
 320  * @param area          Pointer to the VALID parent area. This
 321  *                      structure will not get modified
 322  *                      throughout the loop.
 323  *
 324  */
 325 #define tcm_for_each_slice(var, area, safe) \
 326         for (safe = area, \
 327              tcm_slice(&safe, &var); \
 328              var.tcm; tcm_slice(&safe, &var))
 329 
 330 #endif

/* [<][>][^][v][top][bottom][index][help] */