aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2008-04-28 05:14:49 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:35 -0400
commite4c690e061b909127ab0f12e929f82f3f39ec953 (patch)
treeb798bbda541f615cd4830cad96ed3f58db1fd19c
parent6b745b6fd02213f4b2fef2f2635985929fc5b8cc (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/Kconfig24
-rw-r--r--drivers/video/cfbcopyarea.c23
-rw-r--r--drivers/video/cfbfillrect.c48
-rw-r--r--drivers/video/cfbimgblt.c52
-rw-r--r--drivers/video/fb_draw.h31
-rw-r--r--drivers/video/fbmem.c30
-rw-r--r--drivers/video/syscopyarea.c20
-rw-r--r--drivers/video/sysfillrect.c49
-rw-r--r--drivers/video/sysimgblt.c47
-rw-r--r--include/linux/fb.h44
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
142menuconfig 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
151choice
152 prompt "Choice endianness support"
153 depends on FB_FOREIGN_ENDIAN
154
155config FB_BOTH_ENDIAN
156 bool "Support for Big- and Little-Endian framebuffers"
157
158config FB_BIG_ENDIAN
159 bool "Support for Big-Endian framebuffers only"
160
161config FB_LITTLE_ENDIAN
162 bool "Support for Little-Endian framebuffers only"
163
164endchoice
165
142config FB_SYS_FOPS 166config 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
46static void 46static void
47bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src, 47bitcpy(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
204static void 205static void
205bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src, 206bitcpy_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
38static void 38static void
39bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 39bitfill_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
95static void 95static void
96bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 96bitfill_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 */
149static void 149static void
150bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 150bitfill_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
219static void 220static void
220bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, 221bitfill_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
46static const u32 cfb_tab8[] = { 46static 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
53static 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
62static const u32 cfb_tab16[] = { 60static 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
64static 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
72static const u32 cfb_tab32[] = { 68static 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
97static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) 97static 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
117static inline unsigned long fb_shifted_pixels_mask_long(u32 index, u32 bswapmask) 118static 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
1353struct class *fb_class; 1353struct class *fb_class;
1354EXPORT_SYMBOL(fb_class); 1354EXPORT_SYMBOL(fb_class);
1355
1356static 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
28static void 28static void
29bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, 29bitcpy(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
169static void 169static void
170bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src, 170bitcpy_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
24static void 24static void
25bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat, 25bitfill_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
80static void 80static void
81bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat, 81bitfill_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 */
134static void 134static void
135bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, 135bitfill_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
190static void 190static void
191bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat, 191bitfill_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
26static const u32 cfb_tab8[] = { 26static 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
33static 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
42static const u32 cfb_tab16[] = { 40static 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
44static 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
52static const u32 cfb_tab32[] = { 48static 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
794struct fb_info { 805struct 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);
970extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, 977extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry,
971 int datasync); 978 int datasync);
972 979
980static 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 */
974extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); 1000extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
975extern void framebuffer_release(struct fb_info *info); 1001extern void framebuffer_release(struct fb_info *info);