aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/core/cfbimgblt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/core/cfbimgblt.c')
-rw-r--r--drivers/video/fbdev/core/cfbimgblt.c107
1 files changed, 70 insertions, 37 deletions
diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c
index a2bb276a8b24..7361cfabdd85 100644
--- a/drivers/video/fbdev/core/cfbimgblt.c
+++ b/drivers/video/fbdev/core/cfbimgblt.c
@@ -16,15 +16,15 @@
* must be laid out exactly in the same format as the framebuffer. Yes I know
* their are cards with hardware that coverts images of various depths to the
* framebuffer depth. But not every card has this. All images must be rounded
- * up to the nearest byte. For example a bitmap 12 bits wide must be two
- * bytes width.
+ * up to the nearest byte. For example a bitmap 12 bits wide must be two
+ * bytes width.
*
- * Tony:
- * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
+ * Tony:
+ * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly.
- *
+ *
* Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
- * still processed a bit at a time.
+ * still processed a bit at a time.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
@@ -72,8 +72,8 @@ static const u32 cfb_tab32[] = {
#define FB_WRITEL fb_writel
#define FB_READL fb_readl
-static inline void color_imageblit(const struct fb_image *image,
- struct fb_info *p, u8 __iomem *dst1,
+static inline void color_imageblit(const struct fb_image *image,
+ struct fb_info *p, u8 __iomem *dst1,
u32 start_index,
u32 pitch_index)
{
@@ -92,7 +92,7 @@ static inline void color_imageblit(const struct fb_image *image,
dst = (u32 __iomem *) dst1;
shift = 0;
val = 0;
-
+
if (start_index) {
u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
start_index, bswapmask);
@@ -109,8 +109,8 @@ static inline void color_imageblit(const struct fb_image *image,
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
-
- val = (shift == null_bits) ? 0 :
+
+ val = (shift == null_bits) ? 0 :
FB_SHIFT_LOW(p, color, 32 - shift);
}
shift += bpp;
@@ -134,9 +134,9 @@ static inline void color_imageblit(const struct fb_image *image,
}
}
-static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
+static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
u8 __iomem *dst1, u32 fgcolor,
- u32 bgcolor,
+ u32 bgcolor,
u32 start_index,
u32 pitch_index)
{
@@ -172,7 +172,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
l--;
color = (*s & (1 << l)) ? fgcolor : bgcolor;
val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
-
+
/* Did the bitshift spill bits to the next long? */
if (shift >= null_bits) {
FB_WRITEL(val, dst++);
@@ -191,16 +191,16 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
-
+
dst1 += pitch;
- src += spitch;
+ src += spitch;
if (pitch_index) {
dst2 += pitch;
dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
start_index += pitch_index;
start_index &= 32 - 1;
}
-
+
}
}
@@ -212,29 +212,35 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
* fix->line_legth is divisible by 4;
* beginning and end of a scanline is dword aligned
*/
-static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
- u8 __iomem *dst1, u32 fgcolor,
- u32 bgcolor)
+static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
+ u8 __iomem *dst1, u32 fgcolor,
+ u32 bgcolor)
{
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
- u32 bit_mask, end_mask, eorx, shift;
+ u32 bit_mask, eorx;
const char *s = image->data, *src;
u32 __iomem *dst;
const u32 *tab = NULL;
+ size_t tablen;
+ u32 colortab[16];
int i, j, k;
switch (bpp) {
case 8:
tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
+ tablen = 16;
break;
case 16:
tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
+ tablen = 4;
break;
case 32:
- default:
tab = cfb_tab32;
+ tablen = 2;
break;
+ default:
+ return;
}
for (i = ppw-1; i--; ) {
@@ -243,25 +249,52 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
fgx |= fgcolor;
bgx |= bgcolor;
}
-
+
bit_mask = (1 << ppw) - 1;
eorx = fgx ^ bgx;
k = image->width/ppw;
+ for (i = 0; i < tablen; ++i)
+ colortab[i] = (tab[i] & eorx) ^ bgx;
+
for (i = image->height; i--; ) {
- dst = (u32 __iomem *) dst1, shift = 8; src = s;
-
- for (j = k; j--; ) {
- shift -= ppw;
- end_mask = tab[(*src >> shift) & bit_mask];
- FB_WRITEL((end_mask & eorx)^bgx, dst++);
- if (!shift) { shift = 8; src++; }
+ dst = (u32 __iomem *)dst1;
+ src = s;
+
+ switch (ppw) {
+ case 4: /* 8 bpp */
+ for (j = k; j; j -= 2, ++src) {
+ FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
+ }
+ break;
+ case 2: /* 16 bpp */
+ for (j = k; j; j -= 4, ++src) {
+ FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
+ }
+ break;
+ case 1: /* 32 bpp */
+ for (j = k; j; j -= 8, ++src) {
+ FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++);
+ FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
+ }
+ break;
}
+
dst1 += p->fix.line_length;
s += spitch;
}
-}
-
+}
+
void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
@@ -292,13 +325,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
} else {
fgcolor = image->fg_color;
bgcolor = image->bg_color;
- }
-
- if (32 % bpp == 0 && !start_index && !pitch_index &&
+ }
+
+ if (32 % bpp == 0 && !start_index && !pitch_index &&
((width & (32/bpp-1)) == 0) &&
- bpp >= 8 && bpp <= 32)
+ bpp >= 8 && bpp <= 32)
fast_imageblit(image, p, dst1, fgcolor, bgcolor);
- else
+ else
slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index);
} else