X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fvideo%2Fcfbcopyarea.c;h=df03f3776dcc3b41503018c0cc7d8045bbe67d88;hb=f7160c7573615ec82c691e294cf80d920b5d588d;hp=032210f45be37a539831030b63d64c1a5d3df61a;hpb=02a93208edec0d655c9f18613d830dc6afeda7d4;p=linux-2.6-omap-h63xx.git diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c index 032210f45be..df03f3776dc 100644 --- a/drivers/video/cfbcopyarea.c +++ b/drivers/video/cfbcopyarea.c @@ -44,15 +44,16 @@ */ 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; - 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 @@ -94,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 { + /* 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<>right, FB_READL(dst), first), dst); + d1 = FB_READL(src + 1); + d1 = fb_rev_pixels_in_long(d1, bswapmask); + d0 = d0<>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 +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++); + 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<>right, FB_READL(dst), first), dst); - d0 = d1; + d1 = fb_rev_pixels_in_long(d1, bswapmask); + + d0 = d0<>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 +172,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 +183,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<>right, FB_READL(dst), last), dst); + d1 = fb_rev_pixels_in_long(d1, + bswapmask); + d0 = d0<>right; } + d0 = fb_rev_pixels_in_long(d0, bswapmask); + FB_WRITEL(comp(d0, FB_READL(dst), last), dst); } } } @@ -184,8 +203,9 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src */ 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; @@ -203,8 +223,9 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem 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 @@ -247,24 +268,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)<= 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)<>right | d1<>right | d1<>right | d1<= 4) { + while ((n >= 4) && !bswapmask) { d1 = FB_READL(src--); FB_WRITEL(d0 >> right | d1 << left, dst--); d0 = d1; @@ -309,7 +341,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 +352,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<>right | d1<> 3; int dst_idx = 0, src_idx = 0, rev_copy = 0; + u32 bswapmask = fb_compute_bswapmask(p); if (p->state != FBINFO_STATE_RUNNING) return; @@ -367,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); - 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--) { @@ -376,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); - 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; }