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)  *  Fast C2P (Chunky-to-Planar) Conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Copyright (C) 2003-2008 Geert Uytterhoeven
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "c2p.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "c2p_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)      *  Perform a full C2P step on 32 8-bit pixels, stored in 8 32-bit words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)      *  containing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)      *    - 32 8-bit chunky pixels on input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)      *    - permutated planar data (1 plane per 32-bit word) on output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static void c2p_32x8(u32 d[8])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	transp8(d, 16, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	transp8(d, 8, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	transp8(d, 4, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	transp8(d, 2, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	transp8(d, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^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)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)      *  Array containing the permutation indices of the planar data after c2p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)      *  Store a full block of planar data after c2p conversion
^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) static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	for (i = 0; i < bpp; i++, dst += dst_inc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)      *  Store a partial block of planar data after c2p conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 				       u32 d[8], u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	for (i = 0; i < bpp; i++, dst += dst_inc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 					get_unaligned_be32(dst), mask),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				   dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)      *  c2p_planar - Copy 8-bit chunky image data to a planar frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)      *  @dst: Starting address of the planar frame buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)      *  @dx: Horizontal destination offset (in pixels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)      *  @dy: Vertical destination offset (in pixels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)      *  @width: Image width (in pixels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)      *  @height: Image height (in pixels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)      *  @dst_nextline: Frame buffer offset to the next line (in bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)      *  @dst_nextplane: Frame buffer offset to the next plane (in bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)      *  @src_nextline: Image offset to the next line (in bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)      *  @bpp: Bits per pixel of the planar frame buffer (1-8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		u32 height, u32 dst_nextline, u32 dst_nextplane,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		u32 src_nextline, u32 bpp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		u8 pixels[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		u32 words[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	} d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	u32 dst_idx, first, last, w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	const u8 *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	void *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	dst += dy*dst_nextline+(dx & ~31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	dst_idx = dx % 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	first = 0xffffffffU >> dst_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	last = ~(0xffffffffU >> ((dst_idx+width) % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	while (height--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		c = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		p = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		w = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		if (dst_idx+width <= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			/* Single destination word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			first &= last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			memset(d.pixels, 0, sizeof(d));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			memcpy(d.pixels+dst_idx, c, width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			c += width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			c2p_32x8(d.words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			store_planar_masked(p, dst_nextplane, bpp, d.words,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 					    first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			/* Multiple destination words */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			w = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			/* Leading bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			if (dst_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				w = 32 - dst_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 				memset(d.pixels, 0, dst_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 				memcpy(d.pixels+dst_idx, c, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				c += w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 				c2p_32x8(d.words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 				store_planar_masked(p, dst_nextplane, bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 						    d.words, first);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 				p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 				w = width-w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			/* Main chunk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			while (w >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 				memcpy(d.pixels, c, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 				c += 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				c2p_32x8(d.words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 				store_planar(p, dst_nextplane, bpp, d.words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 				p += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 				w -= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			/* Trailing bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			w %= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			if (w > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 				memcpy(d.pixels, c, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 				memset(d.pixels+w, 0, 32-w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 				c2p_32x8(d.words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 				store_planar_masked(p, dst_nextplane, bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 						    d.words, last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		src += src_nextline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		dst += dst_nextline;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) EXPORT_SYMBOL_GPL(c2p_planar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) MODULE_LICENSE("GPL");