aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2007-10-16 04:29:55 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:23 -0400
commit15afdd433610c4ba0edf1f8a59915b3755af7365 (patch)
tree0e59d4eeb2e66af72a4b1a1fead29fa362826792
parentc3ca34f90b44049dcde62a8f97554409112bf376 (diff)
fbdev: copyarea function taught to fully support swapped pixel order in byte
This correct case, when source and destination X coordinates difference is n multiple of pixels in byte. This is probably rare case, but this case should supported for completeness. Reorganization of FB_READL and FB_WRITEL calls results in code size decrease for normal build without swapping support and size with support enabled is reasonable too. [adaplas] Add missing fb_rev_pixels_in_long() prototype. Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz> Signed-off-by: Antonino Daplas <adaplas@gmail.com> [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/cfbcopyarea.c86
-rw-r--r--drivers/video/fb_draw.h26
2 files changed, 87 insertions, 25 deletions
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 1c67885a1f4f..b07e419b12d2 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -94,29 +94,34 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
94 FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); 94 FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
95 } 95 }
96 } else { 96 } else {
97 /* Different alignment for source and dest */
97 unsigned long d0, d1; 98 unsigned long d0, d1;
98 int m; 99 int m;
99 // Different alignment for source and dest
100 100
101 right = shift & (bits - 1); 101 right = shift & (bits - 1);
102 left = -shift & (bits - 1); 102 left = -shift & (bits - 1);
103 bswapmask &= shift;
103 104
104 if (dst_idx+n <= bits) { 105 if (dst_idx+n <= bits) {
105 // Single destination word 106 // Single destination word
106 if (last) 107 if (last)
107 first &= last; 108 first &= last;
109 d0 = FB_READL(src);
110 d0 = fb_rev_pixels_in_long(d0, bswapmask);
108 if (shift > 0) { 111 if (shift > 0) {
109 // Single source word 112 // Single source word
110 FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst); 113 d0 >>= right;
111 } else if (src_idx+n <= bits) { 114 } else if (src_idx+n <= bits) {
112 // Single source word 115 // Single source word
113 FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst); 116 d0 <<= left;;
114 } else { 117 } else {
115 // 2 source words 118 // 2 source words
116 d0 = FB_READL(src++); 119 d1 = FB_READL(src + 1);
117 d1 = FB_READL(src); 120 d1 = fb_rev_pixels_in_long(d1, bswapmask);
118 FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst); 121 d0 = d0<<left | d1>>right;
119 } 122 }
123 d0 = fb_rev_pixels_in_long(d0, bswapmask);
124 FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
120 } else { 125 } else {
121 // Multiple destination words 126 // Multiple destination words
122 /** We must always remember the last value read, because in case 127 /** We must always remember the last value read, because in case
@@ -125,25 +130,31 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
125 overlap with the current long from SRC. We store this value in 130 overlap with the current long from SRC. We store this value in
126 'd0'. */ 131 'd0'. */
127 d0 = FB_READL(src++); 132 d0 = FB_READL(src++);
133 d0 = fb_rev_pixels_in_long(d0, bswapmask);
128 // Leading bits 134 // Leading bits
129 if (shift > 0) { 135 if (shift > 0) {
130 // Single source word 136 // Single source word
131 FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst); 137 d1 = d0;
138 d0 >>= right;
132 dst++; 139 dst++;
133 n -= bits - dst_idx; 140 n -= bits - dst_idx;
134 } else { 141 } else {
135 // 2 source words 142 // 2 source words
136 d1 = FB_READL(src++); 143 d1 = FB_READL(src++);
137 FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst); 144 d1 = fb_rev_pixels_in_long(d1, bswapmask);
138 d0 = d1; 145
146 d0 = d0<<left | d1>>right;
139 dst++; 147 dst++;
140 n -= bits - dst_idx; 148 n -= bits - dst_idx;
141 } 149 }
150 d0 = fb_rev_pixels_in_long(d0, bswapmask);
151 FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
152 d0 = d1;
142 153
143 // Main chunk 154 // Main chunk
144 m = n % bits; 155 m = n % bits;
145 n /= bits; 156 n /= bits;
146 while (n >= 4) { 157 while ((n >= 4) && !bswapmask) {
147 d1 = FB_READL(src++); 158 d1 = FB_READL(src++);
148 FB_WRITEL(d0 << left | d1 >> right, dst++); 159 FB_WRITEL(d0 << left | d1 >> right, dst++);
149 d0 = d1; 160 d0 = d1;
@@ -160,7 +171,10 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
160 } 171 }
161 while (n--) { 172 while (n--) {
162 d1 = FB_READL(src++); 173 d1 = FB_READL(src++);
163 FB_WRITEL(d0 << left | d1 >> right, dst++); 174 d1 = fb_rev_pixels_in_long(d1, bswapmask);
175 d0 = d0 << left | d1 >> right;
176 d0 = fb_rev_pixels_in_long(d0, bswapmask);
177 FB_WRITEL(d0, dst++);
164 d0 = d1; 178 d0 = d1;
165 } 179 }
166 180
@@ -168,12 +182,16 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
168 if (last) { 182 if (last) {
169 if (m <= right) { 183 if (m <= right) {
170 // Single source word 184 // Single source word
171 FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst); 185 d0 <<= left;
172 } else { 186 } else {
173 // 2 source words 187 // 2 source words
174 d1 = FB_READL(src); 188 d1 = FB_READL(src);
175 FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst); 189 d1 = fb_rev_pixels_in_long(d1,
190 bswapmask);
191 d0 = d0<<left | d1>>right;
176 } 192 }
193 d0 = fb_rev_pixels_in_long(d0, bswapmask);
194 FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
177 } 195 }
178 } 196 }
179 } 197 }
@@ -247,24 +265,32 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
247 } 265 }
248 } else { 266 } else {
249 // Different alignment for source and dest 267 // Different alignment for source and dest
268 unsigned long d0, d1;
269 int m;
250 270
251 int const left = -shift & (bits-1); 271 int const left = -shift & (bits-1);
252 int const right = shift & (bits-1); 272 int const right = shift & (bits-1);
273 bswapmask &= shift;
253 274
254 if ((unsigned long)dst_idx+1 >= n) { 275 if ((unsigned long)dst_idx+1 >= n) {
255 // Single destination word 276 // Single destination word
256 if (last) 277 if (last)
257 first &= last; 278 first &= last;
279 d0 = FB_READL(src);
258 if (shift < 0) { 280 if (shift < 0) {
259 // Single source word 281 // Single source word
260 FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst); 282 d0 <<= left;
261 } else if (1+(unsigned long)src_idx >= n) { 283 } else if (1+(unsigned long)src_idx >= n) {
262 // Single source word 284 // Single source word
263 FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst); 285 d0 >>= right;
264 } else { 286 } else {
265 // 2 source words 287 // 2 source words
266 FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst); 288 d1 = FB_READL(src - 1);
289 d1 = fb_rev_pixels_in_long(d1, bswapmask);
290 d0 = d0>>right | d1<<left;
267 } 291 }
292 d0 = fb_rev_pixels_in_long(d0, bswapmask);
293 FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
268 } else { 294 } else {
269 // Multiple destination words 295 // Multiple destination words
270 /** We must always remember the last value read, because in case 296 /** We must always remember the last value read, because in case
@@ -272,27 +298,30 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
272 1bpp), we always collect one full long for DST and that might 298 1bpp), we always collect one full long for DST and that might
273 overlap with the current long from SRC. We store this value in 299 overlap with the current long from SRC. We store this value in
274 'd0'. */ 300 'd0'. */
275 unsigned long d0, d1;
276 int m;
277 301
278 d0 = FB_READL(src--); 302 d0 = FB_READL(src--);
303 d0 = fb_rev_pixels_in_long(d0, bswapmask);
279 // Leading bits 304 // Leading bits
280 if (shift < 0) { 305 if (shift < 0) {
281 // Single source word 306 // Single source word
282 FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst); 307 d1 = d0;
308 d0 <<= left;
283 } else { 309 } else {
284 // 2 source words 310 // 2 source words
285 d1 = FB_READL(src--); 311 d1 = FB_READL(src--);
286 FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst); 312 d1 = fb_rev_pixels_in_long(d1, bswapmask);
287 d0 = d1; 313 d0 = d0>>right | d1<<left;
288 } 314 }
315 d0 = fb_rev_pixels_in_long(d0, bswapmask);
316 FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
317 d0 = d1;
289 dst--; 318 dst--;
290 n -= dst_idx+1; 319 n -= dst_idx+1;
291 320
292 // Main chunk 321 // Main chunk
293 m = n % bits; 322 m = n % bits;
294 n /= bits; 323 n /= bits;
295 while (n >= 4) { 324 while ((n >= 4) && !bswapmask) {
296 d1 = FB_READL(src--); 325 d1 = FB_READL(src--);
297 FB_WRITEL(d0 >> right | d1 << left, dst--); 326 FB_WRITEL(d0 >> right | d1 << left, dst--);
298 d0 = d1; 327 d0 = d1;
@@ -309,7 +338,10 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
309 } 338 }
310 while (n--) { 339 while (n--) {
311 d1 = FB_READL(src--); 340 d1 = FB_READL(src--);
312 FB_WRITEL(d0 >> right | d1 << left, dst--); 341 d1 = fb_rev_pixels_in_long(d1, bswapmask);
342 d0 = d0 >> right | d1 << left;
343 d0 = fb_rev_pixels_in_long(d0, bswapmask);
344 FB_WRITEL(d0, dst--);
313 d0 = d1; 345 d0 = d1;
314 } 346 }
315 347
@@ -317,12 +349,16 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
317 if (last) { 349 if (last) {
318 if (m <= left) { 350 if (m <= left) {
319 // Single source word 351 // Single source word
320 FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst); 352 d0 >>= right;
321 } else { 353 } else {
322 // 2 source words 354 // 2 source words
323 d1 = FB_READL(src); 355 d1 = FB_READL(src);
324 FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst); 356 d1 = fb_rev_pixels_in_long(d1,
357 bswapmask);
358 d0 = d0>>right | d1<<left;
325 } 359 }
360 d0 = fb_rev_pixels_in_long(d0, bswapmask);
361 FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
326 } 362 }
327 } 363 }
328 } 364 }
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
index 816843f06bb7..cdafbe14ef1f 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fb_draw.h
@@ -72,6 +72,26 @@ pixel_to_pat( u32 bpp, u32 pixel)
72#endif 72#endif
73 73
74#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE 74#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE
75#if BITS_PER_LONG == 64
76#define REV_PIXELS_MASK1 0x5555555555555555ul
77#define REV_PIXELS_MASK2 0x3333333333333333ul
78#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful
79#else
80#define REV_PIXELS_MASK1 0x55555555ul
81#define REV_PIXELS_MASK2 0x33333333ul
82#define REV_PIXELS_MASK4 0x0f0f0f0ful
83#endif
84
85static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
86 u32 bswapmask)
87{
88 if (bswapmask & 1)
89 val = comp(val >> 1, val << 1, REV_PIXELS_MASK1);
90 if (bswapmask & 2)
91 val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
92 if (bswapmask & 3)
93 val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
94}
75 95
76static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) 96static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask)
77{ 97{
@@ -131,6 +151,12 @@ static inline u32 fb_compute_bswapmask(struct fb_info *info)
131 151
132#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ 152#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
133 153
154static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
155 u32 bswapmask)
156{
157 return val;
158}
159
134#define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i)) 160#define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i))
135#define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i)) 161#define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i))
136#define fb_compute_bswapmask(...) 0 162#define fb_compute_bswapmask(...) 0