Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=15afdd433610c4ba0edf1f8a59915b3755af7365
Commit:     15afdd433610c4ba0edf1f8a59915b3755af7365
Parent:     c3ca34f90b44049dcde62a8f97554409112bf376
Author:     Pavel Pisa <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 01:29:55 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Oct 16 09:43:23 2007 -0700

    fbdev: copyarea function taught to fully support swapped pixel order in byte
    
    This correct case, when source and destination X coordinates difference is n
    multiple of pixels in byte.  This is probably rare case, but this case 
should
    supported for completeness.
    
    Reorganization of FB_READL and FB_WRITEL calls results in code size decrease
    for normal build without swapping support and size with support enabled is
    reasonable too.
    
    [adaplas]
    Add missing fb_rev_pixels_in_long() prototype.
    
    Signed-off-by: Pavel Pisa <[EMAIL PROTECTED]>
    Signed-off-by: Antonino Daplas <[EMAIL PROTECTED]>
    [EMAIL PROTECTED]: coding-style fixes]
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 drivers/video/cfbcopyarea.c |   86 ++++++++++++++++++++++++++++++------------
 drivers/video/fb_draw.h     |   26 +++++++++++++
 2 files changed, 87 insertions(+), 25 deletions(-)

diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 1c67885..b07e419 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -94,29 +94,34 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem *src
                                FB_WRITEL( comp( FB_READL(src), FB_READL(dst), 
last), dst);
                }
        } else {
+               /* Different alignment for source and dest */
                unsigned long d0, d1;
                int m;
-               // Different alignment for source and dest
 
                right = shift & (bits - 1);
                left = -shift & (bits - 1);
+               bswapmask &= shift;
 
                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
-                               FB_WRITEL( comp( FB_READL(src) >> right, 
FB_READL(dst), first), dst);
+                               d0 >>= right;
                        } 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
-                               d0 = FB_READL(src++);
-                               d1 = FB_READL(src);
-                               FB_WRITEL( comp(d0<<left | d1>>right, 
FB_READL(dst), first), dst);
+                               d1 = 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
@@ -125,25 +130,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++);
+                       d0 = fb_rev_pixels_in_long(d0, bswapmask);
                        // 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++);
-                               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;
                        }
+                       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;
-                       while (n >= 4) {
+                       while ((n >= 4) && !bswapmask) {
                                d1 = FB_READL(src++);
                                FB_WRITEL(d0 << left | d1 >> right, dst++);
                                d0 = d1;
@@ -160,7 +171,10 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem *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;
                        }
 
@@ -168,12 +182,16 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem *src
                        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);
-                                       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);
                        }
                }
        }
@@ -247,24 +265,32 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem
                }
        } 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);
+               bswapmask &= shift;
 
                if ((unsigned long)dst_idx+1 >= n) {
                        // Single destination word
                        if (last)
                                first &= last;
+                       d0 = FB_READL(src);
                        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
-                               FB_WRITEL( comp( FB_READL(src)>>right, 
FB_READL(dst), first), dst);
+                               d0 >>= right;
                        } 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
@@ -272,27 +298,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'. */
-                       unsigned long d0, d1;
-                       int m;
 
                        d0 = FB_READL(src--);
+                       d0 = fb_rev_pixels_in_long(d0, bswapmask);
                        // 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--);
-                               FB_WRITEL( comp( (d0>>right | d1<<left), 
FB_READL(dst), first), dst);
-                               d0 = d1;
+                               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);
+                       d0 = d1;
                        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;
@@ -309,7 +338,10 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem
                        }
                        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;
                        }
 
@@ -317,12 +349,16 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const 
unsigned long __iomem
                        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);
-                                       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);
                        }
                }
        }
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
index 816843f..cdafbe1 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fb_draw.h
@@ -72,6 +72,26 @@ pixel_to_pat( u32 bpp, u32 pixel)
 #endif
 
 #ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE
+#if BITS_PER_LONG == 64
+#define REV_PIXELS_MASK1 0x5555555555555555ul
+#define REV_PIXELS_MASK2 0x3333333333333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful
+#else
+#define REV_PIXELS_MASK1 0x55555555ul
+#define REV_PIXELS_MASK2 0x33333333ul
+#define REV_PIXELS_MASK4 0x0f0f0f0ful
+#endif
+
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+                                                 u32 bswapmask)
+{
+       if (bswapmask & 1)
+               val = comp(val >> 1, val << 1, REV_PIXELS_MASK1);
+       if (bswapmask & 2)
+               val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
+       if (bswapmask & 3)
+               val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
+}
 
 static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask)
 {
@@ -131,6 +151,12 @@ static inline u32 fb_compute_bswapmask(struct fb_info 
*info)
 
 #else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
 
+static inline unsigned long fb_rev_pixels_in_long(unsigned long val,
+                                                 u32 bswapmask)
+{
+       return val;
+}
+
 #define fb_shifted_pixels_mask_u32(i, b) FB_SHIFT_HIGH(~(u32)0, (i))
 #define fb_shifted_pixels_mask_long(i, b) FB_SHIFT_HIGH(~0UL, (i))
 #define fb_compute_bswapmask(...) 0
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to