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