0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/string.h>
0013
0014 #include <asm/unaligned.h>
0015
0016 #include "c2p.h"
0017 #include "c2p_core.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 static void c2p_32x8(u32 d[8])
0028 {
0029 transp8(d, 16, 4);
0030 transp8(d, 8, 2);
0031 transp8(d, 4, 1);
0032 transp8(d, 2, 4);
0033 transp8(d, 1, 2);
0034 }
0035
0036
0037
0038
0039
0040
0041 static const int perm_c2p_32x8[8] = { 7, 5, 3, 1, 6, 4, 2, 0 };
0042
0043
0044
0045
0046
0047
0048 static inline void store_planar(void *dst, u32 dst_inc, u32 bpp, u32 d[8])
0049 {
0050 int i;
0051
0052 for (i = 0; i < bpp; i++, dst += dst_inc)
0053 put_unaligned_be32(d[perm_c2p_32x8[i]], dst);
0054 }
0055
0056
0057
0058
0059
0060
0061 static inline void store_planar_masked(void *dst, u32 dst_inc, u32 bpp,
0062 u32 d[8], u32 mask)
0063 {
0064 int i;
0065
0066 for (i = 0; i < bpp; i++, dst += dst_inc)
0067 put_unaligned_be32(comp(d[perm_c2p_32x8[i]],
0068 get_unaligned_be32(dst), mask),
0069 dst);
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width,
0087 u32 height, u32 dst_nextline, u32 dst_nextplane,
0088 u32 src_nextline, u32 bpp)
0089 {
0090 union {
0091 u8 pixels[32];
0092 u32 words[8];
0093 } d;
0094 u32 dst_idx, first, last, w;
0095 const u8 *c;
0096 void *p;
0097
0098 dst += dy*dst_nextline+(dx & ~31);
0099 dst_idx = dx % 32;
0100 first = 0xffffffffU >> dst_idx;
0101 last = ~(0xffffffffU >> ((dst_idx+width) % 32));
0102 while (height--) {
0103 c = src;
0104 p = dst;
0105 w = width;
0106 if (dst_idx+width <= 32) {
0107
0108 first &= last;
0109 memset(d.pixels, 0, sizeof(d));
0110 memcpy(d.pixels+dst_idx, c, width);
0111 c += width;
0112 c2p_32x8(d.words);
0113 store_planar_masked(p, dst_nextplane, bpp, d.words,
0114 first);
0115 p += 4;
0116 } else {
0117
0118 w = width;
0119
0120 if (dst_idx) {
0121 w = 32 - dst_idx;
0122 memset(d.pixels, 0, dst_idx);
0123 memcpy(d.pixels+dst_idx, c, w);
0124 c += w;
0125 c2p_32x8(d.words);
0126 store_planar_masked(p, dst_nextplane, bpp,
0127 d.words, first);
0128 p += 4;
0129 w = width-w;
0130 }
0131
0132 while (w >= 32) {
0133 memcpy(d.pixels, c, 32);
0134 c += 32;
0135 c2p_32x8(d.words);
0136 store_planar(p, dst_nextplane, bpp, d.words);
0137 p += 4;
0138 w -= 32;
0139 }
0140
0141 w %= 32;
0142 if (w > 0) {
0143 memcpy(d.pixels, c, w);
0144 memset(d.pixels+w, 0, 32-w);
0145 c2p_32x8(d.words);
0146 store_planar_masked(p, dst_nextplane, bpp,
0147 d.words, last);
0148 }
0149 }
0150 src += src_nextline;
0151 dst += dst_nextline;
0152 }
0153 }
0154 EXPORT_SYMBOL_GPL(c2p_planar);
0155
0156 MODULE_LICENSE("GPL");