Skip to content

Commit e4c690e

Browse files
Anton Vorontsovtorvalds
Anton Vorontsov
authored andcommitted
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>
1 parent 6b745b6 commit e4c690e

File tree

10 files changed

+228
-140
lines changed

10 files changed

+228
-140
lines changed

drivers/video/Kconfig

+24
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,30 @@ config FB_SYS_IMAGEBLIT
139139
blitting. This is used by drivers that don't provide their own
140140
(accelerated) version and the framebuffer is in system RAM.
141141

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+
142166
config FB_SYS_FOPS
143167
tristate
144168
depends on FB

drivers/video/cfbcopyarea.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,16 @@
4444
*/
4545

4646
static void
47-
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
48-
int src_idx, int bits, unsigned n, u32 bswapmask)
47+
bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
48+
const unsigned long __iomem *src, int src_idx, int bits,
49+
unsigned n, u32 bswapmask)
4950
{
5051
unsigned long first, last;
5152
int const shift = dst_idx-src_idx;
5253
int left, right;
5354

54-
first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
55-
last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
55+
first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
56+
last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
5657

5758
if (!shift) {
5859
// Same alignment for source and dest
@@ -202,8 +203,9 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
202203
*/
203204

204205
static void
205-
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
206-
int src_idx, int bits, unsigned n, u32 bswapmask)
206+
bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
207+
const unsigned long __iomem *src, int src_idx, int bits,
208+
unsigned n, u32 bswapmask)
207209
{
208210
unsigned long first, last;
209211
int shift;
@@ -221,8 +223,9 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
221223

222224
shift = dst_idx-src_idx;
223225

224-
first = fb_shifted_pixels_mask_long(bits - 1 - dst_idx, bswapmask);
225-
last = ~fb_shifted_pixels_mask_long(bits - 1 - ((dst_idx-n) % bits), bswapmask);
226+
first = fb_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask);
227+
last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits),
228+
bswapmask);
226229

227230
if (!shift) {
228231
// Same alignment for source and dest
@@ -404,7 +407,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
404407
dst_idx &= (bytes - 1);
405408
src += src_idx >> (ffs(bits) - 1);
406409
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,
408411
width*p->var.bits_per_pixel, bswapmask);
409412
}
410413
} else {
@@ -413,7 +416,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
413416
dst_idx &= (bytes - 1);
414417
src += src_idx >> (ffs(bits) - 1);
415418
src_idx &= (bytes - 1);
416-
bitcpy(dst, dst_idx, src, src_idx, bits,
419+
bitcpy(p, dst, dst_idx, src, src_idx, bits,
417420
width*p->var.bits_per_pixel, bswapmask);
418421
dst_idx += bits_per_line;
419422
src_idx += bits_per_line;

drivers/video/cfbfillrect.c

+26-22
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@
3636
*/
3737

3838
static void
39-
bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
40-
unsigned n, int bits, u32 bswapmask)
39+
bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
40+
unsigned long pat, unsigned n, int bits, u32 bswapmask)
4141
{
4242
unsigned long first, last;
4343

4444
if (!n)
4545
return;
4646

47-
first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
48-
last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
47+
first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
48+
last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
4949

5050
if (dst_idx+n <= bits) {
5151
// Single word
@@ -93,16 +93,16 @@ bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
9393
*/
9494

9595
static void
96-
bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
97-
int left, int right, unsigned n, int bits)
96+
bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
97+
unsigned long pat, int left, int right, unsigned n, int bits)
9898
{
9999
unsigned long first, last;
100100

101101
if (!n)
102102
return;
103103

104-
first = FB_SHIFT_HIGH(~0UL, dst_idx);
105-
last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
104+
first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
105+
last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
106106

107107
if (dst_idx+n <= bits) {
108108
// Single word
@@ -147,17 +147,18 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
147147
* Aligned pattern invert using 32/64-bit memory accesses
148148
*/
149149
static void
150-
bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
151-
unsigned n, int bits, u32 bswapmask)
150+
bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
151+
int dst_idx, unsigned long pat, unsigned n, int bits,
152+
u32 bswapmask)
152153
{
153154
unsigned long val = pat, dat;
154155
unsigned long first, last;
155156

156157
if (!n)
157158
return;
158159

159-
first = fb_shifted_pixels_mask_long(dst_idx, bswapmask);
160-
last = ~fb_shifted_pixels_mask_long((dst_idx+n) % bits, bswapmask);
160+
first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
161+
last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
161162

162163
if (dst_idx+n <= bits) {
163164
// Single word
@@ -217,16 +218,17 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
217218
*/
218219

219220
static void
220-
bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
221-
int left, int right, unsigned n, int bits)
221+
bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
222+
int dst_idx, unsigned long pat, int left, int right,
223+
unsigned n, int bits)
222224
{
223225
unsigned long first, last, dat;
224226

225227
if (!n)
226228
return;
227229

228-
first = FB_SHIFT_HIGH(~0UL, dst_idx);
229-
last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
230+
first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
231+
last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
230232

231233
if (dst_idx+n <= bits) {
232234
// Single word
@@ -306,7 +308,8 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
306308
p->fbops->fb_sync(p);
307309
if (!left) {
308310
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,
310313
unsigned long pat, unsigned n, int bits,
311314
u32 bswapmask) = NULL;
312315

@@ -325,16 +328,17 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
325328
while (height--) {
326329
dst += dst_idx >> (ffs(bits) - 1);
327330
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);
329333
dst_idx += p->fix.line_length*8;
330334
}
331335
} else {
332336
int right;
333337
int r;
334338
int rot = (left-dst_idx) % bpp;
335-
void (*fill_op)(unsigned long __iomem *dst, int dst_idx,
336-
unsigned long pat, int left, int right,
337-
unsigned n, int bits) = NULL;
339+
void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
340+
int dst_idx, unsigned long pat, int left,
341+
int right, unsigned n, int bits) = NULL;
338342

339343
/* rotate pattern to correct start position */
340344
pat = pat << rot | pat >> (bpp-rot);
@@ -355,7 +359,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
355359
while (height--) {
356360
dst += dst_idx >> (ffs(bits) - 1);
357361
dst_idx &= (bits - 1);
358-
fill_op(dst, dst_idx, pat, left, right,
362+
fill_op(p, dst, dst_idx, pat, left, right,
359363
width*bpp, bits);
360364
r = (p->fix.line_length*8) % bpp;
361365
pat = pat << (bpp-r) | pat >> r;

drivers/video/cfbimgblt.c

+26-26
Original file line numberDiff line numberDiff line change
@@ -43,30 +43,26 @@
4343
#define DPRINTK(fmt, args...)
4444
#endif
4545

46-
static const u32 cfb_tab8[] = {
47-
#if defined(__BIG_ENDIAN)
46+
static const u32 cfb_tab8_be[] = {
4847
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
4948
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
5049
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
5150
0xffff0000,0xffff00ff,0xffffff00,0xffffffff
52-
#elif defined(__LITTLE_ENDIAN)
51+
};
52+
53+
static const u32 cfb_tab8_le[] = {
5354
0x00000000,0xff000000,0x00ff0000,0xffff0000,
5455
0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
5556
0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
5657
0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
57-
#else
58-
#error FIXME: No endianness??
59-
#endif
6058
};
6159

62-
static const u32 cfb_tab16[] = {
63-
#if defined(__BIG_ENDIAN)
60+
static const u32 cfb_tab16_be[] = {
6461
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
65-
#elif defined(__LITTLE_ENDIAN)
62+
};
63+
64+
static const u32 cfb_tab16_le[] = {
6665
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
67-
#else
68-
#error FIXME: No endianness??
69-
#endif
7066
};
7167

7268
static const u32 cfb_tab32[] = {
@@ -98,7 +94,8 @@ static inline void color_imageblit(const struct fb_image *image,
9894
val = 0;
9995

10096
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);
10299
val = FB_READL(dst) & start_mask;
103100
shift = start_index;
104101
}
@@ -108,20 +105,21 @@ static inline void color_imageblit(const struct fb_image *image,
108105
color = palette[*src];
109106
else
110107
color = *src;
111-
color <<= FB_LEFT_POS(bpp);
112-
val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
108+
color <<= FB_LEFT_POS(p, bpp);
109+
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
113110
if (shift >= null_bits) {
114111
FB_WRITEL(val, dst++);
115112

116113
val = (shift == null_bits) ? 0 :
117-
FB_SHIFT_LOW(color, 32 - shift);
114+
FB_SHIFT_LOW(p, color, 32 - shift);
118115
}
119116
shift += bpp;
120117
shift &= (32 - 1);
121118
src++;
122119
}
123120
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);
125123

126124
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
127125
}
@@ -152,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
152150
u32 bswapmask = fb_compute_bswapmask(p);
153151

154152
dst2 = (u32 __iomem *) dst1;
155-
fgcolor <<= FB_LEFT_POS(bpp);
156-
bgcolor <<= FB_LEFT_POS(bpp);
153+
fgcolor <<= FB_LEFT_POS(p, bpp);
154+
bgcolor <<= FB_LEFT_POS(p, bpp);
157155

158156
for (i = image->height; i--; ) {
159157
shift = val = 0;
@@ -164,21 +162,22 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
164162

165163
/* write leading bits */
166164
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);
168167
val = FB_READL(dst) & start_mask;
169168
shift = start_index;
170169
}
171170

172171
while (j--) {
173172
l--;
174173
color = (*s & (1 << l)) ? fgcolor : bgcolor;
175-
val |= FB_SHIFT_HIGH(color, shift ^ bswapmask);
174+
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
176175

177176
/* Did the bitshift spill bits to the next long? */
178177
if (shift >= null_bits) {
179178
FB_WRITEL(val, dst++);
180179
val = (shift == null_bits) ? 0 :
181-
FB_SHIFT_LOW(color,32 - shift);
180+
FB_SHIFT_LOW(p, color, 32 - shift);
182181
}
183182
shift += bpp;
184183
shift &= (32 - 1);
@@ -187,7 +186,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
187186

188187
/* write trailing bits */
189188
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);
191191

192192
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
193193
}
@@ -223,13 +223,13 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
223223
u32 __iomem *dst;
224224
const u32 *tab = NULL;
225225
int i, j, k;
226-
226+
227227
switch (bpp) {
228228
case 8:
229-
tab = cfb_tab8;
229+
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
230230
break;
231231
case 16:
232-
tab = cfb_tab16;
232+
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
233233
break;
234234
case 32:
235235
default:

0 commit comments

Comments
 (0)