Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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