projects
/
cascardo
/
linux.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[cascardo/linux.git]
/
drivers
/
video
/
cfbcopyarea.c
diff --git
a/drivers/video/cfbcopyarea.c
b/drivers/video/cfbcopyarea.c
index
6faea40
..
df03f37
100644
(file)
--- a/
drivers/video/cfbcopyarea.c
+++ b/
drivers/video/cfbcopyarea.c
@@
-22,8
+22,6
@@
* help moving some redundant computations and branches out of the loop, too.
*/
* help moving some redundant computations and branches out of the loop, too.
*/
-
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@
-31,6
+29,7
@@
#include <linux/slab.h>
#include <asm/types.h>
#include <asm/io.h>
#include <linux/slab.h>
#include <asm/types.h>
#include <asm/io.h>
+#include "fb_draw.h"
#if BITS_PER_LONG == 32
# define FB_WRITEL fb_writel
#if BITS_PER_LONG == 32
# define FB_WRITEL fb_writel
@@
-40,31
+39,21
@@
# define FB_READL fb_readq
#endif
# define FB_READL fb_readq
#endif
- /*
- * Compose two values, using a bitmask as decision value
- * This is equivalent to (a & mask) | (b & ~mask)
- */
-
-static inline unsigned long
-comp(unsigned long a, unsigned long b, unsigned long mask)
-{
- return ((a ^ b) & mask) ^ b;
-}
-
/*
* Generic bitwise copy algorithm
*/
static void
/*
* Generic bitwise copy algorithm
*/
static void
-bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
- int src_idx, int bits, unsigned n)
+bitcpy(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ const unsigned long __iomem *src, int src_idx, int bits,
+ unsigned n, u32 bswapmask)
{
unsigned long first, last;
int const shift = dst_idx-src_idx;
int left, right;
{
unsigned long first, last;
int const shift = dst_idx-src_idx;
int left, right;
- first =
FB_SHIFT_HIGH(~0UL, dst_idx
);
- last = ~
(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits)
);
+ first =
fb_shifted_pixels_mask_long(p, dst_idx, bswapmask
);
+ last = ~
fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask
);
if (!shift) {
// Same alignment for source and dest
if (!shift) {
// Same alignment for source and dest
@@
-106,29
+95,34
@@
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
+ /* Different alignment for source and dest */
unsigned long d0, d1;
int m;
unsigned long d0, d1;
int m;
- // Different alignment for source and dest
right = shift & (bits - 1);
left = -shift & (bits - 1);
right = shift & (bits - 1);
left = -shift & (bits - 1);
+ bswapmask &= shift;
if (dst_idx+n <= bits) {
// Single destination word
if (last)
first &= last;
if (dst_idx+n <= bits) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
if (shift > 0) {
// Single source word
if (shift > 0) {
// Single source word
-
FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst)
;
+
d0 >>= right
;
} else if (src_idx+n <= bits) {
// Single source word
} else if (src_idx+n <= bits) {
// Single source word
-
FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst)
;
+
d0 <<= left;
;
} else {
// 2 source words
} else {
// 2 source words
- d
0 = FB_READL(src++
);
- d1 =
FB_READL(src
);
-
FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst)
;
+ d
1 = FB_READL(src + 1
);
+ d1 =
fb_rev_pixels_in_long(d1, bswapmask
);
+
d0 = d0<<left | d1>>right
;
}
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@
-137,25
+131,31
@@
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
overlap with the current long from SRC. We store this value in
'd0'. */
d0 = FB_READL(src++);
overlap with the current long from SRC. We store this value in
'd0'. */
d0 = FB_READL(src++);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift > 0) {
// Single source word
// Leading bits
if (shift > 0) {
// Single source word
- FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 >>= right;
dst++;
n -= bits - dst_idx;
} else {
// 2 source words
d1 = FB_READL(src++);
dst++;
n -= bits - dst_idx;
} else {
// 2 source words
d1 = FB_READL(src++);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
- d0 = d1;
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+
+ d0 = d0<<left | d1>>right;
dst++;
n -= bits - dst_idx;
}
dst++;
n -= bits - dst_idx;
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
// Main chunk
m = n % bits;
n /= bits;
// Main chunk
m = n % bits;
n /= bits;
- while (
n >= 4
) {
+ while (
(n >= 4) && !bswapmask
) {
d1 = FB_READL(src++);
FB_WRITEL(d0 << left | d1 >> right, dst++);
d0 = d1;
d1 = FB_READL(src++);
FB_WRITEL(d0 << left | d1 >> right, dst++);
d0 = d1;
@@
-172,7
+172,10
@@
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
}
while (n--) {
d1 = FB_READL(src++);
}
while (n--) {
d1 = FB_READL(src++);
- FB_WRITEL(d0 << left | d1 >> right, dst++);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 << left | d1 >> right;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst++);
d0 = d1;
}
d0 = d1;
}
@@
-180,12
+183,16
@@
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
if (last) {
if (m <= right) {
// Single source word
if (last) {
if (m <= right) {
// Single source word
-
FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst)
;
+
d0 <<= left
;
} else {
// 2 source words
d1 = FB_READL(src);
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1,
+ bswapmask);
+ d0 = d0<<left | d1>>right;
}
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
}
}
}
}
}
}
@@
-196,8
+203,9
@@
bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
*/
static void
*/
static void
-bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
- int src_idx, int bits, unsigned n)
+bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
+ const unsigned long __iomem *src, int src_idx, int bits,
+ unsigned n, u32 bswapmask)
{
unsigned long first, last;
int shift;
{
unsigned long first, last;
int shift;
@@
-215,8
+223,9
@@
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
shift = dst_idx-src_idx;
shift = dst_idx-src_idx;
- first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
- last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
+ first = fb_shifted_pixels_mask_long(p, bits - 1 - dst_idx, bswapmask);
+ last = ~fb_shifted_pixels_mask_long(p, bits - 1 - ((dst_idx-n) % bits),
+ bswapmask);
if (!shift) {
// Same alignment for source and dest
if (!shift) {
// Same alignment for source and dest
@@
-259,24
+268,32
@@
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
}
} else {
// Different alignment for source and dest
}
} else {
// Different alignment for source and dest
+ unsigned long d0, d1;
+ int m;
int const left = -shift & (bits-1);
int const right = shift & (bits-1);
int const left = -shift & (bits-1);
int const right = shift & (bits-1);
+ bswapmask &= shift;
if ((unsigned long)dst_idx+1 >= n) {
// Single destination word
if (last)
first &= last;
if ((unsigned long)dst_idx+1 >= n) {
// Single destination word
if (last)
first &= last;
+ d0 = FB_READL(src);
if (shift < 0) {
// Single source word
if (shift < 0) {
// Single source word
-
FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst)
;
+
d0 <<= left
;
} else if (1+(unsigned long)src_idx >= n) {
// Single source word
} else if (1+(unsigned long)src_idx >= n) {
// Single source word
-
FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst)
;
+
d0 >>= right
;
} else {
// 2 source words
} else {
// 2 source words
- FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
+ d1 = FB_READL(src - 1);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0>>right | d1<<left;
}
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
} else {
// Multiple destination words
/** We must always remember the last value read, because in case
@@
-284,27
+301,30
@@
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
1bpp), we always collect one full long for DST and that might
overlap with the current long from SRC. We store this value in
'd0'. */
1bpp), we always collect one full long for DST and that might
overlap with the current long from SRC. We store this value in
'd0'. */
- unsigned long d0, d1;
- int m;
d0 = FB_READL(src--);
d0 = FB_READL(src--);
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
// Leading bits
if (shift < 0) {
// Single source word
// Leading bits
if (shift < 0) {
// Single source word
- FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
+ d1 = d0;
+ d0 <<= left;
} else {
// 2 source words
d1 = FB_READL(src--);
} else {
// 2 source words
d1 = FB_READL(src--);
-
FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst
);
- d0 = d
1
;
+
d1 = fb_rev_pixels_in_long(d1, bswapmask
);
+ d0 = d
0>>right | d1<<left
;
}
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), first), dst);
+ d0 = d1;
dst--;
n -= dst_idx+1;
// Main chunk
m = n % bits;
n /= bits;
dst--;
n -= dst_idx+1;
// Main chunk
m = n % bits;
n /= bits;
- while (
n >= 4
) {
+ while (
(n >= 4) && !bswapmask
) {
d1 = FB_READL(src--);
FB_WRITEL(d0 >> right | d1 << left, dst--);
d0 = d1;
d1 = FB_READL(src--);
FB_WRITEL(d0 >> right | d1 << left, dst--);
d0 = d1;
@@
-321,7
+341,10
@@
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
}
while (n--) {
d1 = FB_READL(src--);
}
while (n--) {
d1 = FB_READL(src--);
- FB_WRITEL(d0 >> right | d1 << left, dst--);
+ d1 = fb_rev_pixels_in_long(d1, bswapmask);
+ d0 = d0 >> right | d1 << left;
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(d0, dst--);
d0 = d1;
}
d0 = d1;
}
@@
-329,12
+352,16
@@
bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
if (last) {
if (m <= left) {
// Single source word
if (last) {
if (m <= left) {
// Single source word
-
FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst)
;
+
d0 >>= right
;
} else {
// 2 source words
d1 = FB_READL(src);
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
+ d1 = fb_rev_pixels_in_long(d1,
+ bswapmask);
+ d0 = d0>>right | d1<<left;
}
}
+ d0 = fb_rev_pixels_in_long(d0, bswapmask);
+ FB_WRITEL(comp(d0, FB_READL(dst), last), dst);
}
}
}
}
}
}
@@
-348,6
+375,7
@@
void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
unsigned long __iomem *dst = NULL, *src = NULL;
int bits = BITS_PER_LONG, bytes = bits >> 3;
int dst_idx = 0, src_idx = 0, rev_copy = 0;
unsigned long __iomem *dst = NULL, *src = NULL;
int bits = BITS_PER_LONG, bytes = bits >> 3;
int dst_idx = 0, src_idx = 0, rev_copy = 0;
+ u32 bswapmask = fb_compute_bswapmask(p);
if (p->state != FBINFO_STATE_RUNNING)
return;
if (p->state != FBINFO_STATE_RUNNING)
return;
@@
-379,8
+407,8
@@
void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
dst_idx &= (bytes - 1);
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
dst_idx &= (bytes - 1);
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
- bitcpy_rev(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ bitcpy_rev(
p,
dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel
, bswapmask
);
}
} else {
while (height--) {
}
} else {
while (height--) {
@@
-388,8
+416,8
@@
void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
dst_idx &= (bytes - 1);
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
dst_idx &= (bytes - 1);
src += src_idx >> (ffs(bits) - 1);
src_idx &= (bytes - 1);
- bitcpy(dst, dst_idx, src, src_idx, bits,
- width*p->var.bits_per_pixel);
+ bitcpy(
p,
dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel
, bswapmask
);
dst_idx += bits_per_line;
src_idx += bits_per_line;
}
dst_idx += bits_per_line;
src_idx += bits_per_line;
}