diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2008-04-28 05:14:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:35 -0400 |
commit | e4c690e061b909127ab0f12e929f82f3f39ec953 (patch) | |
tree | b798bbda541f615cd4830cad96ed3f58db1fd19c | |
parent | 6b745b6fd02213f4b2fef2f2635985929fc5b8cc (diff) |
fb: add support for foreign endianness
Add support for the framebuffers with non-native endianness. This is done via
FBINFO_FOREIGN_ENDIAN flag that will be used by the drivers. Depending on the
host endianness this flag will be overwritten by FBINFO_BE_MATH internal flag,
or cleared.
Tested to work on MPC8360E-RDK (BE) + Fujitsu MINT framebuffer (LE).
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: <Valdis.Kletnieks@vt.edu>
Cc: Clemens Koller <clemens.koller@anagramm.de>
Cc: Krzysztof Helt <krzysztof.h1@poczta.fm>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/video/Kconfig | 24 | ||||
-rw-r--r-- | drivers/video/cfbcopyarea.c | 23 | ||||
-rw-r--r-- | drivers/video/cfbfillrect.c | 48 | ||||
-rw-r--r-- | drivers/video/cfbimgblt.c | 52 | ||||
-rw-r--r-- | drivers/video/fb_draw.h | 31 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 30 | ||||
-rw-r--r-- | drivers/video/syscopyarea.c | 20 | ||||
-rw-r--r-- | drivers/video/sysfillrect.c | 49 | ||||
-rw-r--r-- | drivers/video/sysimgblt.c | 47 | ||||
-rw-r--r-- | include/linux/fb.h | 44 |
10 files changed, 228 insertions, 140 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index e3dc8f8d0c3e..da7b9705ca81 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -139,6 +139,30 @@ config FB_SYS_IMAGEBLIT | |||
139 | blitting. This is used by drivers that don't provide their own | 139 | blitting. This is used by drivers that don't provide their own |
140 | (accelerated) version and the framebuffer is in system RAM. | 140 | (accelerated) version and the framebuffer is in system RAM. |
141 | 141 | ||
142 | menuconfig FB_FOREIGN_ENDIAN | ||
143 | bool "Framebuffer foreign endianness support" | ||
144 | depends on FB | ||
145 | ---help--- | ||
146 | This menu will let you enable support for the framebuffers with | ||
147 | non-native endianness (e.g. Little-Endian framebuffer on a | ||
148 | Big-Endian machine). Most probably you don't have such hardware, | ||
149 | so it's safe to say "n" here. | ||
150 | |||
151 | choice | ||
152 | prompt "Choice endianness support" | ||
153 | depends on FB_FOREIGN_ENDIAN | ||
154 | |||
155 | config FB_BOTH_ENDIAN | ||
156 | bool "Support for Big- and Little-Endian framebuffers" | ||
157 | |||
158 | config FB_BIG_ENDIAN | ||
159 | bool "Support for Big-Endian framebuffers only" | ||
160 | |||
161 | config FB_LITTLE_ENDIAN | ||
162 | bool "Support for Little-Endian framebuffers only" | ||
163 | |||
164 | endchoice | ||
165 | |||
142 | config FB_SYS_FOPS | 166 | config FB_SYS_FOPS |
143 | tristate | 167 | tristate |
144 | depends on FB | 168 | depends on FB |
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index b07e419b12d2..df03f3776dcc 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c | |||
@@ -44,15 +44,16 @@ | |||
44 | */ | 44 | */ |
45 | 45 | ||
46 | static void | 46 | static void |
47 | bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src, | 47 | bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, |
48 | int src_idx, int bits, unsigned n, u32 bswapmask) | 48 | const unsigned long __iomem *src, int src_idx, int bits, |
49 | unsigned n, u32 bswapmask) | ||
49 | { | 50 | { |
50 | unsigned long first, last; | 51 | unsigned long first, last; |
51 | int const shift = dst_idx-src_idx; | 52 | int const shift = dst_idx-src_idx; |
52 | int left, right; | 53 | int left, right; |
53 | 54 | ||
54 | first = fb_shifted_pixels_mask_long(dst_idx, bswapmask); | 55 | first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); |
55 | last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask); | 56 | last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); |
56 | 57 | ||
57 | if (!shift) { | 58 | if (!shift) { |
58 | // Same alignment for source and dest | 59 | // Same alignment for source and dest |
@@ -202,8 +203,9 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src | |||
202 | */ | 203 | */ |
203 | 204 | ||
204 | static void | 205 | static void |
205 | bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src, | 206 | bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, |
206 | int src_idx, int bits, unsigned n, u32 bswapmask) | 207 | const unsigned long __iomem *src, int src_idx, int bits, |
208 | unsigned n, u32 bswapmask) | ||
207 | { | 209 | { |
208 | unsigned long first, last; | 210 | unsigned long first, last; |
209 | int shift; | 211 | int shift; |
@@ -221,8 +223,9 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem | |||
221 | 223 | ||
222 | shift = dst_idx-src_idx; | 224 | shift = dst_idx-src_idx; |
223 | 225 | ||
224 | first = fb_shifted_pixels_mask_long(bits - 1 - dst_idx, bswapmask); | 226 | first = fb_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask); |
225 | last = ~fb_shifted_pixels_mask_long(bits - 1 - ((dst_idx-n) % bits), bswapmask); | 227 | last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits), |
228 | bswapmask); | ||
226 | 229 | ||
227 | if (!shift) { | 230 | if (!shift) { |
228 | // Same alignment for source and dest | 231 | // Same alignment for source and dest |
@@ -404,7 +407,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) | |||
404 | dst_idx &= (bytes - 1); | 407 | dst_idx &= (bytes - 1); |
405 | src += src_idx >> (ffs(bits) - 1); | 408 | src += src_idx >> (ffs(bits) - 1); |
406 | src_idx &= (bytes - 1); | 409 | src_idx &= (bytes - 1); |
407 | bitcpy_rev(dst, dst_idx, src, src_idx, bits, | 410 | bitcpy_rev(p, dst, dst_idx, src, src_idx, bits, |
408 | width*p->var.bits_per_pixel, bswapmask); | 411 | width*p->var.bits_per_pixel, bswapmask); |
409 | } | 412 | } |
410 | } else { | 413 | } else { |
@@ -413,7 +416,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) | |||
413 | dst_idx &= (bytes - 1); | 416 | dst_idx &= (bytes - 1); |
414 | src += src_idx >> (ffs(bits) - 1); | 417 | src += src_idx >> (ffs(bits) - 1); |
415 | src_idx &= (bytes - 1); | 418 | src_idx &= (bytes - 1); |
416 | bitcpy(dst, dst_idx, src, src_idx, bits, | 419 | bitcpy(p, dst, dst_idx, src, src_idx, bits, |
417 | width*p->var.bits_per_pixel, bswapmask); | 420 | width*p->var.bits_per_pixel, bswapmask); |
418 | dst_idx += bits_per_line; | 421 | dst_idx += bits_per_line; |
419 | src_idx += bits_per_line; | 422 | src_idx += bits_per_line; |
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index 23d70a12e4da..64b35766b2a2 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c | |||
@@ -36,16 +36,16 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | static void | 38 | static void |
39 | bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | 39 | bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, |
40 | unsigned n, int bits, u32 bswapmask) | 40 | unsigned long pat, unsigned n, int bits, u32 bswapmask) |
41 | { | 41 | { |
42 | unsigned long first, last; | 42 | unsigned long first, last; |
43 | 43 | ||
44 | if (!n) | 44 | if (!n) |
45 | return; | 45 | return; |
46 | 46 | ||
47 | first = fb_shifted_pixels_mask_long(dst_idx, bswapmask); | 47 | first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); |
48 | last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask); | 48 | last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); |
49 | 49 | ||
50 | if (dst_idx+n <= bits) { | 50 | if (dst_idx+n <= bits) { |
51 | // Single word | 51 | // Single word |
@@ -93,16 +93,16 @@ bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
93 | */ | 93 | */ |
94 | 94 | ||
95 | static void | 95 | static void |
96 | bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | 96 | bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, |
97 | int left, int right, unsigned n, int bits) | 97 | unsigned long pat, int left, int right, unsigned n, int bits) |
98 | { | 98 | { |
99 | unsigned long first, last; | 99 | unsigned long first, last; |
100 | 100 | ||
101 | if (!n) | 101 | if (!n) |
102 | return; | 102 | return; |
103 | 103 | ||
104 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 104 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
105 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 105 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
106 | 106 | ||
107 | if (dst_idx+n <= bits) { | 107 | if (dst_idx+n <= bits) { |
108 | // Single word | 108 | // Single word |
@@ -147,8 +147,9 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
147 | * Aligned pattern invert using 32/64-bit memory accesses | 147 | * Aligned pattern invert using 32/64-bit memory accesses |
148 | */ | 148 | */ |
149 | static void | 149 | static void |
150 | bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | 150 | bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, |
151 | unsigned n, int bits, u32 bswapmask) | 151 | int dst_idx, unsigned long pat, unsigned n, int bits, |
152 | u32 bswapmask) | ||
152 | { | 153 | { |
153 | unsigned long val = pat, dat; | 154 | unsigned long val = pat, dat; |
154 | unsigned long first, last; | 155 | unsigned long first, last; |
@@ -156,8 +157,8 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
156 | if (!n) | 157 | if (!n) |
157 | return; | 158 | return; |
158 | 159 | ||
159 | first = fb_shifted_pixels_mask_long(dst_idx, bswapmask); | 160 | first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); |
160 | last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask); | 161 | last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); |
161 | 162 | ||
162 | if (dst_idx+n <= bits) { | 163 | if (dst_idx+n <= bits) { |
163 | // Single word | 164 | // Single word |
@@ -217,16 +218,17 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | |||
217 | */ | 218 | */ |
218 | 219 | ||
219 | static void | 220 | static void |
220 | bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, | 221 | bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, |
221 | int left, int right, unsigned n, int bits) | 222 | int dst_idx, unsigned long pat, int left, int right, |
223 | unsigned n, int bits) | ||
222 | { | 224 | { |
223 | unsigned long first, last, dat; | 225 | unsigned long first, last, dat; |
224 | 226 | ||
225 | if (!n) | 227 | if (!n) |
226 | return; | 228 | return; |
227 | 229 | ||
228 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 230 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
229 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 231 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
230 | 232 | ||
231 | if (dst_idx+n <= bits) { | 233 | if (dst_idx+n <= bits) { |
232 | // Single word | 234 | // Single word |
@@ -306,7 +308,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
306 | p->fbops->fb_sync(p); | 308 | p->fbops->fb_sync(p); |
307 | if (!left) { | 309 | if (!left) { |
308 | u32 bswapmask = fb_compute_bswapmask(p); | 310 | u32 bswapmask = fb_compute_bswapmask(p); |
309 | void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, | 311 | void (*fill_op32)(struct fb_info *p, |
312 | unsigned long __iomem *dst, int dst_idx, | ||
310 | unsigned long pat, unsigned n, int bits, | 313 | unsigned long pat, unsigned n, int bits, |
311 | u32 bswapmask) = NULL; | 314 | u32 bswapmask) = NULL; |
312 | 315 | ||
@@ -325,16 +328,17 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
325 | while (height--) { | 328 | while (height--) { |
326 | dst += dst_idx >> (ffs(bits) - 1); | 329 | dst += dst_idx >> (ffs(bits) - 1); |
327 | dst_idx &= (bits - 1); | 330 | dst_idx &= (bits - 1); |
328 | fill_op32(dst, dst_idx, pat, width*bpp, bits, bswapmask); | 331 | fill_op32(p, dst, dst_idx, pat, width*bpp, bits, |
332 | bswapmask); | ||
329 | dst_idx += p->fix.line_length*8; | 333 | dst_idx += p->fix.line_length*8; |
330 | } | 334 | } |
331 | } else { | 335 | } else { |
332 | int right; | 336 | int right; |
333 | int r; | 337 | int r; |
334 | int rot = (left-dst_idx) % bpp; | 338 | int rot = (left-dst_idx) % bpp; |
335 | void (*fill_op)(unsigned long __iomem *dst, int dst_idx, | 339 | void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, |
336 | unsigned long pat, int left, int right, | 340 | int dst_idx, unsigned long pat, int left, |
337 | unsigned n, int bits) = NULL; | 341 | int right, unsigned n, int bits) = NULL; |
338 | 342 | ||
339 | /* rotate pattern to correct start position */ | 343 | /* rotate pattern to correct start position */ |
340 | pat = pat << rot | pat >> (bpp-rot); | 344 | pat = pat << rot | pat >> (bpp-rot); |
@@ -355,7 +359,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
355 | while (height--) { | 359 | while (height--) { |
356 | dst += dst_idx >> (ffs(bits) - 1); | 360 | dst += dst_idx >> (ffs(bits) - 1); |
357 | dst_idx &= (bits - 1); | 361 | dst_idx &= (bits - 1); |
358 | fill_op(dst, dst_idx, pat, left, right, | 362 | fill_op(p, dst, dst_idx, pat, left, right, |
359 | width*bpp, bits); | 363 | width*bpp, bits); |
360 | r = (p->fix.line_length*8) % bpp; | 364 | r = (p->fix.line_length*8) % bpp; |
361 | pat = pat << (bpp-r) | pat >> r; | 365 | pat = pat << (bpp-r) | pat >> r; |
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index f598907b42ad..ff3136bd464b 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c | |||
@@ -43,30 +43,26 @@ | |||
43 | #define DPRINTK(fmt, args...) | 43 | #define DPRINTK(fmt, args...) |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | static const u32 cfb_tab8[] = { | 46 | static const u32 cfb_tab8_be[] = { |
47 | #if defined(__BIG_ENDIAN) | ||
48 | 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, | 47 | 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, |
49 | 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, | 48 | 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, |
50 | 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, | 49 | 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, |
51 | 0xffff0000,0xffff00ff,0xffffff00,0xffffffff | 50 | 0xffff0000,0xffff00ff,0xffffff00,0xffffffff |
52 | #elif defined(__LITTLE_ENDIAN) | 51 | }; |
52 | |||
53 | static const u32 cfb_tab8_le[] = { | ||
53 | 0x00000000,0xff000000,0x00ff0000,0xffff0000, | 54 | 0x00000000,0xff000000,0x00ff0000,0xffff0000, |
54 | 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, | 55 | 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, |
55 | 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, | 56 | 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, |
56 | 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff | 57 | 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff |
57 | #else | ||
58 | #error FIXME: No endianness?? | ||
59 | #endif | ||
60 | }; | 58 | }; |
61 | 59 | ||
62 | static const u32 cfb_tab16[] = { | 60 | static const u32 cfb_tab16_be[] = { |
63 | #if defined(__BIG_ENDIAN) | ||
64 | 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff | 61 | 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff |
65 | #elif defined(__LITTLE_ENDIAN) | 62 | }; |
63 | |||
64 | static const u32 cfb_tab16_le[] = { | ||
66 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff | 65 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff |
67 | #else | ||
68 | #error FIXME: No endianness?? | ||
69 | #endif | ||
70 | }; | 66 | }; |
71 | 67 | ||
72 | static const u32 cfb_tab32[] = { | 68 | static const u32 cfb_tab32[] = { |
@@ -98,7 +94,8 @@ static inline void color_imageblit(const struct fb_image *image, | |||
98 | val = 0; | 94 | val = 0; |
99 | 95 | ||
100 | if (start_index) { | 96 | if (start_index) { |
101 | u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask); | 97 | u32 start_mask = ~fb_shifted_pixels_mask_u32(p, |
98 | start_index, bswapmask); | ||
102 | val = FB_READL(dst) & start_mask; | 99 | val = FB_READL(dst) & start_mask; |
103 | shift = start_index; | 100 | shift = start_index; |
104 | } | 101 | } |
@@ -108,20 +105,21 @@ static inline void color_imageblit(const struct fb_image *image, | |||
108 | color = palette[*src]; | 105 | color = palette[*src]; |
109 | else | 106 | else |
110 | color = *src; | 107 | color = *src; |
111 | color <<= FB_LEFT_POS(bpp); | 108 | color <<= FB_LEFT_POS(p, bpp); |
112 | val |= FB_SHIFT_HIGH(color, shift ^ bswapmask); | 109 | val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); |
113 | if (shift >= null_bits) { | 110 | if (shift >= null_bits) { |
114 | FB_WRITEL(val, dst++); | 111 | FB_WRITEL(val, dst++); |
115 | 112 | ||
116 | val = (shift == null_bits) ? 0 : | 113 | val = (shift == null_bits) ? 0 : |
117 | FB_SHIFT_LOW(color, 32 - shift); | 114 | FB_SHIFT_LOW(p, color, 32 - shift); |
118 | } | 115 | } |
119 | shift += bpp; | 116 | shift += bpp; |
120 | shift &= (32 - 1); | 117 | shift &= (32 - 1); |
121 | src++; | 118 | src++; |
122 | } | 119 | } |
123 | if (shift) { | 120 | if (shift) { |
124 | u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask); | 121 | u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, |
122 | bswapmask); | ||
125 | 123 | ||
126 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 124 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
127 | } | 125 | } |
@@ -152,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
152 | u32 bswapmask = fb_compute_bswapmask(p); | 150 | u32 bswapmask = fb_compute_bswapmask(p); |
153 | 151 | ||
154 | dst2 = (u32 __iomem *) dst1; | 152 | dst2 = (u32 __iomem *) dst1; |
155 | fgcolor <<= FB_LEFT_POS(bpp); | 153 | fgcolor <<= FB_LEFT_POS(p, bpp); |
156 | bgcolor <<= FB_LEFT_POS(bpp); | 154 | bgcolor <<= FB_LEFT_POS(p, bpp); |
157 | 155 | ||
158 | for (i = image->height; i--; ) { | 156 | for (i = image->height; i--; ) { |
159 | shift = val = 0; | 157 | shift = val = 0; |
@@ -164,7 +162,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
164 | 162 | ||
165 | /* write leading bits */ | 163 | /* write leading bits */ |
166 | if (start_index) { | 164 | if (start_index) { |
167 | u32 start_mask = ~fb_shifted_pixels_mask_u32(start_index, bswapmask); | 165 | u32 start_mask = ~fb_shifted_pixels_mask_u32(p, |
166 | start_index, bswapmask); | ||
168 | val = FB_READL(dst) & start_mask; | 167 | val = FB_READL(dst) & start_mask; |
169 | shift = start_index; | 168 | shift = start_index; |
170 | } | 169 | } |
@@ -172,13 +171,13 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
172 | while (j--) { | 171 | while (j--) { |
173 | l--; | 172 | l--; |
174 | color = (*s & (1 << l)) ? fgcolor : bgcolor; | 173 | color = (*s & (1 << l)) ? fgcolor : bgcolor; |
175 | val |= FB_SHIFT_HIGH(color, shift ^ bswapmask); | 174 | val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); |
176 | 175 | ||
177 | /* Did the bitshift spill bits to the next long? */ | 176 | /* Did the bitshift spill bits to the next long? */ |
178 | if (shift >= null_bits) { | 177 | if (shift >= null_bits) { |
179 | FB_WRITEL(val, dst++); | 178 | FB_WRITEL(val, dst++); |
180 | val = (shift == null_bits) ? 0 : | 179 | val = (shift == null_bits) ? 0 : |
181 | FB_SHIFT_LOW(color,32 - shift); | 180 | FB_SHIFT_LOW(p, color, 32 - shift); |
182 | } | 181 | } |
183 | shift += bpp; | 182 | shift += bpp; |
184 | shift &= (32 - 1); | 183 | shift &= (32 - 1); |
@@ -187,7 +186,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * | |||
187 | 186 | ||
188 | /* write trailing bits */ | 187 | /* write trailing bits */ |
189 | if (shift) { | 188 | if (shift) { |
190 | u32 end_mask = fb_shifted_pixels_mask_u32(shift, bswapmask); | 189 | u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, |
190 | bswapmask); | ||
191 | 191 | ||
192 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); | 192 | FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
193 | } | 193 | } |
@@ -223,13 +223,13 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * | |||
223 | u32 __iomem *dst; | 223 | u32 __iomem *dst; |
224 | const u32 *tab = NULL; | 224 | const u32 *tab = NULL; |
225 | int i, j, k; | 225 | int i, j, k; |
226 | 226 | ||
227 | switch (bpp) { | 227 | switch (bpp) { |
228 | case 8: | 228 | case 8: |
229 | tab = cfb_tab8; | 229 | tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; |
230 | break; | 230 | break; |
231 | case 16: | 231 | case 16: |
232 | tab = cfb_tab16; | 232 | tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; |
233 | break; | 233 | break; |
234 | case 32: | 234 | case 32: |
235 | default: | 235 | default: |
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h index a2a0618d86a5..1db622192bde 100644 --- a/drivers/video/fb_draw.h +++ b/drivers/video/fb_draw.h | |||
@@ -94,41 +94,44 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, | |||
94 | return val; | 94 | return val; |
95 | } | 95 | } |
96 | 96 | ||
97 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) | 97 | static inline u32 fb_shifted_pixels_mask_u32(struct fb_info *p, u32 index, |
98 | u32 bswapmask) | ||
98 | { | 99 | { |
99 | u32 mask; | 100 | u32 mask; |
100 | 101 | ||
101 | if (!bswapmask) { | 102 | if (!bswapmask) { |
102 | mask = FB_SHIFT_HIGH(~(u32)0, index); | 103 | mask = FB_SHIFT_HIGH(p, ~(u32)0, index); |
103 | } else { | 104 | } else { |
104 | mask = 0xff << FB_LEFT_POS(8); | 105 | mask = 0xff << FB_LEFT_POS(p, 8); |
105 | mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask; | 106 | mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask; |
106 | mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask)); | 107 | mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask)); |
107 | #if defined(__i386__) || defined(__x86_64__) | 108 | #if defined(__i386__) || defined(__x86_64__) |
108 | /* Shift argument is limited to 0 - 31 on x86 based CPU's */ | 109 | /* Shift argument is limited to 0 - 31 on x86 based CPU's */ |
109 | if(index + bswapmask < 32) | 110 | if(index + bswapmask < 32) |
110 | #endif | 111 | #endif |
111 | mask |= FB_SHIFT_HIGH(~(u32)0, | 112 | mask |= FB_SHIFT_HIGH(p, ~(u32)0, |
112 | (index + bswapmask) & ~(bswapmask)); | 113 | (index + bswapmask) & ~(bswapmask)); |
113 | } | 114 | } |
114 | return mask; | 115 | return mask; |
115 | } | 116 | } |
116 | 117 | ||
117 | static inline unsigned long fb_shifted_pixels_mask_long(u32 index, u32 bswapmask) | 118 | static inline unsigned long fb_shifted_pixels_mask_long(struct fb_info *p, |
119 | u32 index, | ||
120 | u32 bswapmask) | ||
118 | { | 121 | { |
119 | unsigned long mask; | 122 | unsigned long mask; |
120 | 123 | ||
121 | if (!bswapmask) { | 124 | if (!bswapmask) { |
122 | mask = FB_SHIFT_HIGH(~0UL, index); | 125 | mask = FB_SHIFT_HIGH(p, ~0UL, index); |
123 | } else { | 126 | } else { |
124 | mask = 0xff << FB_LEFT_POS(8); | 127 | mask = 0xff << FB_LEFT_POS(p, 8); |
125 | mask = FB_SHIFT_LOW(mask, index & (bswapmask)) & mask; | 128 | mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask; |
126 | mask = FB_SHIFT_HIGH(mask, index & ~(bswapmask)); | 129 | mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask)); |
127 | #if defined(__i386__) || defined(__x86_64__) | 130 | #if defined(__i386__) || defined(__x86_64__) |
128 | /* Shift argument is limited to 0 - 31 on x86 based CPU's */ | 131 | /* Shift argument is limited to 0 - 31 on x86 based CPU's */ |
129 | if(index + bswapmask < BITS_PER_LONG) | 132 | if(index + bswapmask < BITS_PER_LONG) |
130 | #endif | 133 | #endif |
131 | mask |= FB_SHIFT_HIGH(~0UL, | 134 | mask |= FB_SHIFT_HIGH(p, ~0UL, |
132 | (index + bswapmask) & ~(bswapmask)); | 135 | (index + bswapmask) & ~(bswapmask)); |
133 | } | 136 | } |
134 | return mask; | 137 | return mask; |
@@ -158,8 +161,8 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, | |||
158 | return val; | 161 | return val; |
159 | } | 162 | } |
160 | 163 | ||
161 | #define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i)) | 164 | #define fb_shifted_pixels_mask_u32(p, i, b) FB_SHIFT_HIGH((p), ~(u32)0, (i)) |
162 | #define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i)) | 165 | #define fb_shifted_pixels_mask_long(p, i, b) FB_SHIFT_HIGH((p), ~0UL, (i)) |
163 | #define fb_compute_bswapmask(...) 0 | 166 | #define fb_compute_bswapmask(...) 0 |
164 | 167 | ||
165 | #endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ | 168 | #endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 01072f4b3e8f..279c2dbef8f8 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1352,6 +1352,32 @@ static const struct file_operations fb_fops = { | |||
1352 | 1352 | ||
1353 | struct class *fb_class; | 1353 | struct class *fb_class; |
1354 | EXPORT_SYMBOL(fb_class); | 1354 | EXPORT_SYMBOL(fb_class); |
1355 | |||
1356 | static int fb_check_foreignness(struct fb_info *fi) | ||
1357 | { | ||
1358 | const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN; | ||
1359 | |||
1360 | fi->flags &= ~FBINFO_FOREIGN_ENDIAN; | ||
1361 | |||
1362 | #ifdef __BIG_ENDIAN | ||
1363 | fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH; | ||
1364 | #else | ||
1365 | fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0; | ||
1366 | #endif /* __BIG_ENDIAN */ | ||
1367 | |||
1368 | if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) { | ||
1369 | pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to " | ||
1370 | "support this framebuffer\n", fi->fix.id); | ||
1371 | return -ENOSYS; | ||
1372 | } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) { | ||
1373 | pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to " | ||
1374 | "support this framebuffer\n", fi->fix.id); | ||
1375 | return -ENOSYS; | ||
1376 | } | ||
1377 | |||
1378 | return 0; | ||
1379 | } | ||
1380 | |||
1355 | /** | 1381 | /** |
1356 | * register_framebuffer - registers a frame buffer device | 1382 | * register_framebuffer - registers a frame buffer device |
1357 | * @fb_info: frame buffer info structure | 1383 | * @fb_info: frame buffer info structure |
@@ -1371,6 +1397,10 @@ register_framebuffer(struct fb_info *fb_info) | |||
1371 | 1397 | ||
1372 | if (num_registered_fb == FB_MAX) | 1398 | if (num_registered_fb == FB_MAX) |
1373 | return -ENXIO; | 1399 | return -ENXIO; |
1400 | |||
1401 | if (fb_check_foreignness(fb_info)) | ||
1402 | return -ENOSYS; | ||
1403 | |||
1374 | num_registered_fb++; | 1404 | num_registered_fb++; |
1375 | for (i = 0 ; i < FB_MAX; i++) | 1405 | for (i = 0 ; i < FB_MAX; i++) |
1376 | if (!registered_fb[i]) | 1406 | if (!registered_fb[i]) |
diff --git a/drivers/video/syscopyarea.c b/drivers/video/syscopyarea.c index 37af10ab8f52..a352d5f46bbf 100644 --- a/drivers/video/syscopyarea.c +++ b/drivers/video/syscopyarea.c | |||
@@ -26,15 +26,15 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | static void | 28 | static void |
29 | bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, | 29 | bitcpy(struct fb_info *p, unsigned long *dst, int dst_idx, |
30 | int src_idx, int bits, unsigned n) | 30 | const unsigned long *src, int src_idx, int bits, unsigned n) |
31 | { | 31 | { |
32 | unsigned long first, last; | 32 | unsigned long first, last; |
33 | int const shift = dst_idx-src_idx; | 33 | int const shift = dst_idx-src_idx; |
34 | int left, right; | 34 | int left, right; |
35 | 35 | ||
36 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 36 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
37 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 37 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
38 | 38 | ||
39 | if (!shift) { | 39 | if (!shift) { |
40 | /* Same alignment for source and dest */ | 40 | /* Same alignment for source and dest */ |
@@ -167,8 +167,8 @@ bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, | |||
167 | */ | 167 | */ |
168 | 168 | ||
169 | static void | 169 | static void |
170 | bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src, | 170 | bitcpy_rev(struct fb_info *p, unsigned long *dst, int dst_idx, |
171 | int src_idx, int bits, unsigned n) | 171 | const unsigned long *src, int src_idx, int bits, unsigned n) |
172 | { | 172 | { |
173 | unsigned long first, last; | 173 | unsigned long first, last; |
174 | int shift; | 174 | int shift; |
@@ -186,8 +186,8 @@ bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src, | |||
186 | 186 | ||
187 | shift = dst_idx-src_idx; | 187 | shift = dst_idx-src_idx; |
188 | 188 | ||
189 | first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx); | 189 | first = FB_SHIFT_LOW(p, ~0UL, bits - 1 - dst_idx); |
190 | last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits))); | 190 | last = ~(FB_SHIFT_LOW(p, ~0UL, bits - 1 - ((dst_idx-n) % bits))); |
191 | 191 | ||
192 | if (!shift) { | 192 | if (!shift) { |
193 | /* Same alignment for source and dest */ | 193 | /* Same alignment for source and dest */ |
@@ -353,7 +353,7 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) | |||
353 | dst_idx &= (bytes - 1); | 353 | dst_idx &= (bytes - 1); |
354 | src += src_idx >> (ffs(bits) - 1); | 354 | src += src_idx >> (ffs(bits) - 1); |
355 | src_idx &= (bytes - 1); | 355 | src_idx &= (bytes - 1); |
356 | bitcpy_rev(dst, dst_idx, src, src_idx, bits, | 356 | bitcpy_rev(p, dst, dst_idx, src, src_idx, bits, |
357 | width*p->var.bits_per_pixel); | 357 | width*p->var.bits_per_pixel); |
358 | } | 358 | } |
359 | } else { | 359 | } else { |
@@ -362,7 +362,7 @@ void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) | |||
362 | dst_idx &= (bytes - 1); | 362 | dst_idx &= (bytes - 1); |
363 | src += src_idx >> (ffs(bits) - 1); | 363 | src += src_idx >> (ffs(bits) - 1); |
364 | src_idx &= (bytes - 1); | 364 | src_idx &= (bytes - 1); |
365 | bitcpy(dst, dst_idx, src, src_idx, bits, | 365 | bitcpy(p, dst, dst_idx, src, src_idx, bits, |
366 | width*p->var.bits_per_pixel); | 366 | width*p->var.bits_per_pixel); |
367 | dst_idx += bits_per_line; | 367 | dst_idx += bits_per_line; |
368 | src_idx += bits_per_line; | 368 | src_idx += bits_per_line; |
diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c index a261e9e6a675..f94d6b6e29ee 100644 --- a/drivers/video/sysfillrect.c +++ b/drivers/video/sysfillrect.c | |||
@@ -22,16 +22,16 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | static void | 24 | static void |
25 | bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat, | 25 | bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx, |
26 | unsigned n, int bits) | 26 | unsigned long pat, unsigned n, int bits) |
27 | { | 27 | { |
28 | unsigned long first, last; | 28 | unsigned long first, last; |
29 | 29 | ||
30 | if (!n) | 30 | if (!n) |
31 | return; | 31 | return; |
32 | 32 | ||
33 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 33 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
34 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 34 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
35 | 35 | ||
36 | if (dst_idx+n <= bits) { | 36 | if (dst_idx+n <= bits) { |
37 | /* Single word */ | 37 | /* Single word */ |
@@ -78,16 +78,16 @@ bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat, | |||
78 | */ | 78 | */ |
79 | 79 | ||
80 | static void | 80 | static void |
81 | bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat, | 81 | bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx, |
82 | int left, int right, unsigned n, int bits) | 82 | unsigned long pat, int left, int right, unsigned n, int bits) |
83 | { | 83 | { |
84 | unsigned long first, last; | 84 | unsigned long first, last; |
85 | 85 | ||
86 | if (!n) | 86 | if (!n) |
87 | return; | 87 | return; |
88 | 88 | ||
89 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 89 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
90 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 90 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
91 | 91 | ||
92 | if (dst_idx+n <= bits) { | 92 | if (dst_idx+n <= bits) { |
93 | /* Single word */ | 93 | /* Single word */ |
@@ -132,8 +132,8 @@ bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat, | |||
132 | * Aligned pattern invert using 32/64-bit memory accesses | 132 | * Aligned pattern invert using 32/64-bit memory accesses |
133 | */ | 133 | */ |
134 | static void | 134 | static void |
135 | bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, | 135 | bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, |
136 | unsigned n, int bits) | 136 | unsigned long pat, unsigned n, int bits) |
137 | { | 137 | { |
138 | unsigned long val = pat; | 138 | unsigned long val = pat; |
139 | unsigned long first, last; | 139 | unsigned long first, last; |
@@ -141,8 +141,8 @@ bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, | |||
141 | if (!n) | 141 | if (!n) |
142 | return; | 142 | return; |
143 | 143 | ||
144 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 144 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
145 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 145 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
146 | 146 | ||
147 | if (dst_idx+n <= bits) { | 147 | if (dst_idx+n <= bits) { |
148 | /* Single word */ | 148 | /* Single word */ |
@@ -188,16 +188,17 @@ bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, | |||
188 | */ | 188 | */ |
189 | 189 | ||
190 | static void | 190 | static void |
191 | bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, | 191 | bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, |
192 | int left, int right, unsigned n, int bits) | 192 | unsigned long pat, int left, int right, unsigned n, |
193 | int bits) | ||
193 | { | 194 | { |
194 | unsigned long first, last; | 195 | unsigned long first, last; |
195 | 196 | ||
196 | if (!n) | 197 | if (!n) |
197 | return; | 198 | return; |
198 | 199 | ||
199 | first = FB_SHIFT_HIGH(~0UL, dst_idx); | 200 | first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); |
200 | last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)); | 201 | last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); |
201 | 202 | ||
202 | if (dst_idx+n <= bits) { | 203 | if (dst_idx+n <= bits) { |
203 | /* Single word */ | 204 | /* Single word */ |
@@ -267,9 +268,9 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
267 | if (p->fbops->fb_sync) | 268 | if (p->fbops->fb_sync) |
268 | p->fbops->fb_sync(p); | 269 | p->fbops->fb_sync(p); |
269 | if (!left) { | 270 | if (!left) { |
270 | void (*fill_op32)(unsigned long *dst, int dst_idx, | 271 | void (*fill_op32)(struct fb_info *p, unsigned long *dst, |
271 | unsigned long pat, unsigned n, int bits) = | 272 | int dst_idx, unsigned long pat, unsigned n, |
272 | NULL; | 273 | int bits) = NULL; |
273 | 274 | ||
274 | switch (rect->rop) { | 275 | switch (rect->rop) { |
275 | case ROP_XOR: | 276 | case ROP_XOR: |
@@ -287,16 +288,16 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
287 | while (height--) { | 288 | while (height--) { |
288 | dst += dst_idx >> (ffs(bits) - 1); | 289 | dst += dst_idx >> (ffs(bits) - 1); |
289 | dst_idx &= (bits - 1); | 290 | dst_idx &= (bits - 1); |
290 | fill_op32(dst, dst_idx, pat, width*bpp, bits); | 291 | fill_op32(p, dst, dst_idx, pat, width*bpp, bits); |
291 | dst_idx += p->fix.line_length*8; | 292 | dst_idx += p->fix.line_length*8; |
292 | } | 293 | } |
293 | } else { | 294 | } else { |
294 | int right; | 295 | int right; |
295 | int r; | 296 | int r; |
296 | int rot = (left-dst_idx) % bpp; | 297 | int rot = (left-dst_idx) % bpp; |
297 | void (*fill_op)(unsigned long *dst, int dst_idx, | 298 | void (*fill_op)(struct fb_info *p, unsigned long *dst, |
298 | unsigned long pat, int left, int right, | 299 | int dst_idx, unsigned long pat, int left, |
299 | unsigned n, int bits) = NULL; | 300 | int right, unsigned n, int bits) = NULL; |
300 | 301 | ||
301 | /* rotate pattern to correct start position */ | 302 | /* rotate pattern to correct start position */ |
302 | pat = pat << rot | pat >> (bpp-rot); | 303 | pat = pat << rot | pat >> (bpp-rot); |
@@ -318,7 +319,7 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) | |||
318 | while (height--) { | 319 | while (height--) { |
319 | dst += dst_idx >> (ffs(bits) - 1); | 320 | dst += dst_idx >> (ffs(bits) - 1); |
320 | dst_idx &= (bits - 1); | 321 | dst_idx &= (bits - 1); |
321 | fill_op(dst, dst_idx, pat, left, right, | 322 | fill_op(p, dst, dst_idx, pat, left, right, |
322 | width*bpp, bits); | 323 | width*bpp, bits); |
323 | r = (p->fix.line_length*8) % bpp; | 324 | r = (p->fix.line_length*8) % bpp; |
324 | pat = pat << (bpp-r) | pat >> r; | 325 | pat = pat << (bpp-r) | pat >> r; |
diff --git a/drivers/video/sysimgblt.c b/drivers/video/sysimgblt.c index bd7e7e9d155f..88daa9b6f69a 100644 --- a/drivers/video/sysimgblt.c +++ b/drivers/video/sysimgblt.c | |||
@@ -23,30 +23,26 @@ | |||
23 | #define DPRINTK(fmt, args...) | 23 | #define DPRINTK(fmt, args...) |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | static const u32 cfb_tab8[] = { | 26 | static const u32 cfb_tab8_be[] = { |
27 | #if defined(__BIG_ENDIAN) | ||
28 | 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, | 27 | 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, |
29 | 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, | 28 | 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, |
30 | 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, | 29 | 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, |
31 | 0xffff0000,0xffff00ff,0xffffff00,0xffffffff | 30 | 0xffff0000,0xffff00ff,0xffffff00,0xffffffff |
32 | #elif defined(__LITTLE_ENDIAN) | 31 | }; |
32 | |||
33 | static const u32 cfb_tab8_le[] = { | ||
33 | 0x00000000,0xff000000,0x00ff0000,0xffff0000, | 34 | 0x00000000,0xff000000,0x00ff0000,0xffff0000, |
34 | 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, | 35 | 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, |
35 | 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, | 36 | 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, |
36 | 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff | 37 | 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff |
37 | #else | ||
38 | #error FIXME: No endianness?? | ||
39 | #endif | ||
40 | }; | 38 | }; |
41 | 39 | ||
42 | static const u32 cfb_tab16[] = { | 40 | static const u32 cfb_tab16_be[] = { |
43 | #if defined(__BIG_ENDIAN) | ||
44 | 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff | 41 | 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff |
45 | #elif defined(__LITTLE_ENDIAN) | 42 | }; |
43 | |||
44 | static const u32 cfb_tab16_le[] = { | ||
46 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff | 45 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff |
47 | #else | ||
48 | #error FIXME: No endianness?? | ||
49 | #endif | ||
50 | }; | 46 | }; |
51 | 47 | ||
52 | static const u32 cfb_tab32[] = { | 48 | static const u32 cfb_tab32[] = { |
@@ -72,7 +68,7 @@ static void color_imageblit(const struct fb_image *image, struct fb_info *p, | |||
72 | val = 0; | 68 | val = 0; |
73 | 69 | ||
74 | if (start_index) { | 70 | if (start_index) { |
75 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, | 71 | u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, |
76 | start_index)); | 72 | start_index)); |
77 | val = *dst & start_mask; | 73 | val = *dst & start_mask; |
78 | shift = start_index; | 74 | shift = start_index; |
@@ -83,20 +79,20 @@ static void color_imageblit(const struct fb_image *image, struct fb_info *p, | |||
83 | color = palette[*src]; | 79 | color = palette[*src]; |
84 | else | 80 | else |
85 | color = *src; | 81 | color = *src; |
86 | color <<= FB_LEFT_POS(bpp); | 82 | color <<= FB_LEFT_POS(p, bpp); |
87 | val |= FB_SHIFT_HIGH(color, shift); | 83 | val |= FB_SHIFT_HIGH(p, color, shift); |
88 | if (shift >= null_bits) { | 84 | if (shift >= null_bits) { |
89 | *dst++ = val; | 85 | *dst++ = val; |
90 | 86 | ||
91 | val = (shift == null_bits) ? 0 : | 87 | val = (shift == null_bits) ? 0 : |
92 | FB_SHIFT_LOW(color, 32 - shift); | 88 | FB_SHIFT_LOW(p, color, 32 - shift); |
93 | } | 89 | } |
94 | shift += bpp; | 90 | shift += bpp; |
95 | shift &= (32 - 1); | 91 | shift &= (32 - 1); |
96 | src++; | 92 | src++; |
97 | } | 93 | } |
98 | if (shift) { | 94 | if (shift) { |
99 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); | 95 | u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); |
100 | 96 | ||
101 | *dst &= end_mask; | 97 | *dst &= end_mask; |
102 | *dst |= val; | 98 | *dst |= val; |
@@ -125,8 +121,8 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p, | |||
125 | u32 i, j, l; | 121 | u32 i, j, l; |
126 | 122 | ||
127 | dst2 = dst1; | 123 | dst2 = dst1; |
128 | fgcolor <<= FB_LEFT_POS(bpp); | 124 | fgcolor <<= FB_LEFT_POS(p, bpp); |
129 | bgcolor <<= FB_LEFT_POS(bpp); | 125 | bgcolor <<= FB_LEFT_POS(p, bpp); |
130 | 126 | ||
131 | for (i = image->height; i--; ) { | 127 | for (i = image->height; i--; ) { |
132 | shift = val = 0; | 128 | shift = val = 0; |
@@ -137,7 +133,8 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p, | |||
137 | 133 | ||
138 | /* write leading bits */ | 134 | /* write leading bits */ |
139 | if (start_index) { | 135 | if (start_index) { |
140 | u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index)); | 136 | u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, |
137 | start_index)); | ||
141 | val = *dst & start_mask; | 138 | val = *dst & start_mask; |
142 | shift = start_index; | 139 | shift = start_index; |
143 | } | 140 | } |
@@ -145,13 +142,13 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p, | |||
145 | while (j--) { | 142 | while (j--) { |
146 | l--; | 143 | l--; |
147 | color = (*s & (1 << l)) ? fgcolor : bgcolor; | 144 | color = (*s & (1 << l)) ? fgcolor : bgcolor; |
148 | val |= FB_SHIFT_HIGH(color, shift); | 145 | val |= FB_SHIFT_HIGH(p, color, shift); |
149 | 146 | ||
150 | /* Did the bitshift spill bits to the next long? */ | 147 | /* Did the bitshift spill bits to the next long? */ |
151 | if (shift >= null_bits) { | 148 | if (shift >= null_bits) { |
152 | *dst++ = val; | 149 | *dst++ = val; |
153 | val = (shift == null_bits) ? 0 : | 150 | val = (shift == null_bits) ? 0 : |
154 | FB_SHIFT_LOW(color,32 - shift); | 151 | FB_SHIFT_LOW(p, color, 32 - shift); |
155 | } | 152 | } |
156 | shift += bpp; | 153 | shift += bpp; |
157 | shift &= (32 - 1); | 154 | shift &= (32 - 1); |
@@ -160,7 +157,7 @@ static void slow_imageblit(const struct fb_image *image, struct fb_info *p, | |||
160 | 157 | ||
161 | /* write trailing bits */ | 158 | /* write trailing bits */ |
162 | if (shift) { | 159 | if (shift) { |
163 | u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift); | 160 | u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); |
164 | 161 | ||
165 | *dst &= end_mask; | 162 | *dst &= end_mask; |
166 | *dst |= val; | 163 | *dst |= val; |
@@ -199,10 +196,10 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, | |||
199 | 196 | ||
200 | switch (bpp) { | 197 | switch (bpp) { |
201 | case 8: | 198 | case 8: |
202 | tab = cfb_tab8; | 199 | tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; |
203 | break; | 200 | break; |
204 | case 16: | 201 | case 16: |
205 | tab = cfb_tab16; | 202 | tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; |
206 | break; | 203 | break; |
207 | case 32: | 204 | case 32: |
208 | default: | 205 | default: |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 58c57a33e5dd..72295b099228 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -791,6 +791,17 @@ struct fb_tile_ops { | |||
791 | */ | 791 | */ |
792 | #define FBINFO_MISC_ALWAYS_SETPAR 0x40000 | 792 | #define FBINFO_MISC_ALWAYS_SETPAR 0x40000 |
793 | 793 | ||
794 | /* | ||
795 | * Host and GPU endianness differ. | ||
796 | */ | ||
797 | #define FBINFO_FOREIGN_ENDIAN 0x100000 | ||
798 | /* | ||
799 | * Big endian math. This is the same flags as above, but with different | ||
800 | * meaning, it is set by the fb subsystem depending FOREIGN_ENDIAN flag | ||
801 | * and host endianness. Drivers should not use this flag. | ||
802 | */ | ||
803 | #define FBINFO_BE_MATH 0x100000 | ||
804 | |||
794 | struct fb_info { | 805 | struct fb_info { |
795 | int node; | 806 | int node; |
796 | int flags; | 807 | int flags; |
@@ -899,15 +910,11 @@ struct fb_info { | |||
899 | 910 | ||
900 | #endif | 911 | #endif |
901 | 912 | ||
902 | #if defined (__BIG_ENDIAN) | 913 | #define FB_LEFT_POS(p, bpp) (fb_be_math(p) ? (32 - (bpp)) : 0) |
903 | #define FB_LEFT_POS(bpp) (32 - bpp) | 914 | #define FB_SHIFT_HIGH(p, val, bits) (fb_be_math(p) ? (val) >> (bits) : \ |
904 | #define FB_SHIFT_HIGH(val, bits) ((val) >> (bits)) | 915 | (val) << (bits)) |
905 | #define FB_SHIFT_LOW(val, bits) ((val) << (bits)) | 916 | #define FB_SHIFT_LOW(p, val, bits) (fb_be_math(p) ? (val) << (bits) : \ |
906 | #else | 917 | (val) >> (bits)) |
907 | #define FB_LEFT_POS(bpp) (0) | ||
908 | #define FB_SHIFT_HIGH(val, bits) ((val) << (bits)) | ||
909 | #define FB_SHIFT_LOW(val, bits) ((val) >> (bits)) | ||
910 | #endif | ||
911 | 918 | ||
912 | /* | 919 | /* |
913 | * `Generic' versions of the frame buffer device operations | 920 | * `Generic' versions of the frame buffer device operations |
@@ -970,6 +977,25 @@ extern void fb_deferred_io_cleanup(struct fb_info *info); | |||
970 | extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, | 977 | extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, |
971 | int datasync); | 978 | int datasync); |
972 | 979 | ||
980 | static inline bool fb_be_math(struct fb_info *info) | ||
981 | { | ||
982 | #ifdef CONFIG_FB_FOREIGN_ENDIAN | ||
983 | #if defined(CONFIG_FB_BOTH_ENDIAN) | ||
984 | return info->flags & FBINFO_BE_MATH; | ||
985 | #elif defined(CONFIG_FB_BIG_ENDIAN) | ||
986 | return true; | ||
987 | #elif defined(CONFIG_FB_LITTLE_ENDIAN) | ||
988 | return false; | ||
989 | #endif /* CONFIG_FB_BOTH_ENDIAN */ | ||
990 | #else | ||
991 | #ifdef __BIG_ENDIAN | ||
992 | return true; | ||
993 | #else | ||
994 | return false; | ||
995 | #endif /* __BIG_ENDIAN */ | ||
996 | #endif /* CONFIG_FB_FOREIGN_ENDIAN */ | ||
997 | } | ||
998 | |||
973 | /* drivers/video/fbsysfs.c */ | 999 | /* drivers/video/fbsysfs.c */ |
974 | extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); | 1000 | extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); |
975 | extern void framebuffer_release(struct fb_info *info); | 1001 | extern void framebuffer_release(struct fb_info *info); |