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