1/* 2 * Fast C2P (Chunky-to-Planar) Conversion 3 * 4 * NOTES: 5 * - This code was inspired by Scout's C2P tutorial 6 * - It assumes to run on a big endian system 7 * 8 * Copyright © 2003-2008 Geert Uytterhoeven 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the "Software"), 12 * to deal in the Software without restriction, including without limitation 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 * and/or sell copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice (including the next 18 * paragraph) shall be included in all copies or substantial portions of the 19 * Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 * DEALINGS IN THE SOFTWARE. 28 */ 29 30 31 /* 32 * Basic transpose step 33 */ 34 35static inline void _transp(CARD32 d[], unsigned int i1, unsigned int i2, 36 unsigned int shift, CARD32 mask) 37{ 38 CARD32 t = (d[i1] ^ (d[i2] >> shift)) & mask; 39 40 d[i1] ^= t; 41 d[i2] ^= t << shift; 42} 43 44 45static inline void c2p_unsupported(void) { 46 BUG_WARN(1); 47} 48 49static inline CARD32 get_mask(unsigned int n) 50{ 51 switch (n) { 52 case 1: 53 return 0x55555555; 54 55 case 2: 56 return 0x33333333; 57 58 case 4: 59 return 0x0f0f0f0f; 60 61 case 8: 62 return 0x00ff00ff; 63 64 case 16: 65 return 0x0000ffff; 66 } 67 68 c2p_unsupported(); 69 return 0; 70} 71 72 73 /* 74 * Transpose operations on 8 32-bit words 75 */ 76 77static inline void transp8(CARD32 d[], unsigned int n, unsigned int m) 78{ 79 CARD32 mask = get_mask(n); 80 81 switch (m) { 82 case 1: 83 /* First n x 1 block */ 84 _transp(d, 0, 1, n, mask); 85 /* Second n x 1 block */ 86 _transp(d, 2, 3, n, mask); 87 /* Third n x 1 block */ 88 _transp(d, 4, 5, n, mask); 89 /* Fourth n x 1 block */ 90 _transp(d, 6, 7, n, mask); 91 return; 92 93 case 2: 94 /* First n x 2 block */ 95 _transp(d, 0, 2, n, mask); 96 _transp(d, 1, 3, n, mask); 97 /* Second n x 2 block */ 98 _transp(d, 4, 6, n, mask); 99 _transp(d, 5, 7, n, mask); 100 return; 101 102 case 4: 103 /* Single n x 4 block */ 104 _transp(d, 0, 4, n, mask); 105 _transp(d, 1, 5, n, mask); 106 _transp(d, 2, 6, n, mask); 107 _transp(d, 3, 7, n, mask); 108 return; 109 } 110 111 c2p_unsupported(); 112} 113 114 115 /* 116 * Transpose operations on 4 32-bit words 117 */ 118 119static inline void transp4(CARD32 d[], unsigned int n, unsigned int m) 120{ 121 CARD32 mask = get_mask(n); 122 123 switch (m) { 124 case 1: 125 /* First n x 1 block */ 126 _transp(d, 0, 1, n, mask); 127 /* Second n x 1 block */ 128 _transp(d, 2, 3, n, mask); 129 return; 130 131 case 2: 132 /* Single n x 2 block */ 133 _transp(d, 0, 2, n, mask); 134 _transp(d, 1, 3, n, mask); 135 return; 136 } 137 138 c2p_unsupported(); 139} 140 141 142 /* 143 * Transpose operations on 4 32-bit words (reverse order) 144 */ 145 146static inline void transp4x(CARD32 d[], unsigned int n, unsigned int m) 147{ 148 CARD32 mask = get_mask(n); 149 150 switch (m) { 151 case 2: 152 /* Single n x 2 block */ 153 _transp(d, 2, 0, n, mask); 154 _transp(d, 3, 1, n, mask); 155 return; 156 } 157 158 c2p_unsupported(); 159} 160 161 162 /* 163 * Transpose operations on 2 32-bit words 164 */ 165 166static inline void transp2(CARD32 d[], unsigned int n) 167{ 168 CARD32 mask = get_mask(n); 169 170 /* Single n x 1 block */ 171 _transp(d, 0, 1, n, mask); 172 return; 173} 174 175 176 /* 177 * Transpose operations on 2 32-bit words (reverse order) 178 */ 179 180static inline void transp2x(CARD32 d[], unsigned int n) 181{ 182 CARD32 mask = get_mask(n); 183 184 /* Single n x 1 block */ 185 _transp(d, 1, 0, n, mask); 186 return; 187} 188