0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #include <linux/module.h>
0033 #include <linux/string.h>
0034 #include <linux/fb.h>
0035 #include <asm/types.h>
0036 #include "fb_draw.h"
0037
0038 #define DEBUG
0039
0040 #ifdef DEBUG
0041 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
0042 #else
0043 #define DPRINTK(fmt, args...)
0044 #endif
0045
0046 static const u32 cfb_tab8_be[] = {
0047 0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0048 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0049 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0050 0xffff0000,0xffff00ff,0xffffff00,0xffffffff
0051 };
0052
0053 static const u32 cfb_tab8_le[] = {
0054 0x00000000,0xff000000,0x00ff0000,0xffff0000,
0055 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
0056 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
0057 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
0058 };
0059
0060 static const u32 cfb_tab16_be[] = {
0061 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
0062 };
0063
0064 static const u32 cfb_tab16_le[] = {
0065 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
0066 };
0067
0068 static const u32 cfb_tab32[] = {
0069 0x00000000, 0xffffffff
0070 };
0071
0072 #define FB_WRITEL fb_writel
0073 #define FB_READL fb_readl
0074
0075 static inline void color_imageblit(const struct fb_image *image,
0076 struct fb_info *p, u8 __iomem *dst1,
0077 u32 start_index,
0078 u32 pitch_index)
0079 {
0080
0081 u32 __iomem *dst, *dst2;
0082 u32 color = 0, val, shift;
0083 int i, n, bpp = p->var.bits_per_pixel;
0084 u32 null_bits = 32 - bpp;
0085 u32 *palette = (u32 *) p->pseudo_palette;
0086 const u8 *src = image->data;
0087 u32 bswapmask = fb_compute_bswapmask(p);
0088
0089 dst2 = (u32 __iomem *) dst1;
0090 for (i = image->height; i--; ) {
0091 n = image->width;
0092 dst = (u32 __iomem *) dst1;
0093 shift = 0;
0094 val = 0;
0095
0096 if (start_index) {
0097 u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
0098 start_index, bswapmask);
0099 val = FB_READL(dst) & start_mask;
0100 shift = start_index;
0101 }
0102 while (n--) {
0103 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
0104 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
0105 color = palette[*src];
0106 else
0107 color = *src;
0108 color <<= FB_LEFT_POS(p, bpp);
0109 val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
0110 if (shift >= null_bits) {
0111 FB_WRITEL(val, dst++);
0112
0113 val = (shift == null_bits) ? 0 :
0114 FB_SHIFT_LOW(p, color, 32 - shift);
0115 }
0116 shift += bpp;
0117 shift &= (32 - 1);
0118 src++;
0119 }
0120 if (shift) {
0121 u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
0122 bswapmask);
0123
0124 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
0125 }
0126 dst1 += p->fix.line_length;
0127 if (pitch_index) {
0128 dst2 += p->fix.line_length;
0129 dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
0130
0131 start_index += pitch_index;
0132 start_index &= 32 - 1;
0133 }
0134 }
0135 }
0136
0137 static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p,
0138 u8 __iomem *dst1, u32 fgcolor,
0139 u32 bgcolor,
0140 u32 start_index,
0141 u32 pitch_index)
0142 {
0143 u32 shift, color = 0, bpp = p->var.bits_per_pixel;
0144 u32 __iomem *dst, *dst2;
0145 u32 val, pitch = p->fix.line_length;
0146 u32 null_bits = 32 - bpp;
0147 u32 spitch = (image->width+7)/8;
0148 const u8 *src = image->data, *s;
0149 u32 i, j, l;
0150 u32 bswapmask = fb_compute_bswapmask(p);
0151
0152 dst2 = (u32 __iomem *) dst1;
0153 fgcolor <<= FB_LEFT_POS(p, bpp);
0154 bgcolor <<= FB_LEFT_POS(p, bpp);
0155
0156 for (i = image->height; i--; ) {
0157 shift = val = 0;
0158 l = 8;
0159 j = image->width;
0160 dst = (u32 __iomem *) dst1;
0161 s = src;
0162
0163
0164 if (start_index) {
0165 u32 start_mask = ~fb_shifted_pixels_mask_u32(p,
0166 start_index, bswapmask);
0167 val = FB_READL(dst) & start_mask;
0168 shift = start_index;
0169 }
0170
0171 while (j--) {
0172 l--;
0173 color = (*s & (1 << l)) ? fgcolor : bgcolor;
0174 val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask);
0175
0176
0177 if (shift >= null_bits) {
0178 FB_WRITEL(val, dst++);
0179 val = (shift == null_bits) ? 0 :
0180 FB_SHIFT_LOW(p, color, 32 - shift);
0181 }
0182 shift += bpp;
0183 shift &= (32 - 1);
0184 if (!l) { l = 8; s++; }
0185 }
0186
0187
0188 if (shift) {
0189 u32 end_mask = fb_shifted_pixels_mask_u32(p, shift,
0190 bswapmask);
0191
0192 FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
0193 }
0194
0195 dst1 += pitch;
0196 src += spitch;
0197 if (pitch_index) {
0198 dst2 += pitch;
0199 dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
0200 start_index += pitch_index;
0201 start_index &= 32 - 1;
0202 }
0203
0204 }
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p,
0216 u8 __iomem *dst1, u32 fgcolor,
0217 u32 bgcolor)
0218 {
0219 u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
0220 u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
0221 u32 bit_mask, eorx, shift;
0222 const char *s = image->data, *src;
0223 u32 __iomem *dst;
0224 const u32 *tab = NULL;
0225 size_t tablen;
0226 u32 colortab[16];
0227 int i, j, k;
0228
0229 switch (bpp) {
0230 case 8:
0231 tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
0232 tablen = 16;
0233 break;
0234 case 16:
0235 tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
0236 tablen = 4;
0237 break;
0238 case 32:
0239 tab = cfb_tab32;
0240 tablen = 2;
0241 break;
0242 default:
0243 return;
0244 }
0245
0246 for (i = ppw-1; i--; ) {
0247 fgx <<= bpp;
0248 bgx <<= bpp;
0249 fgx |= fgcolor;
0250 bgx |= bgcolor;
0251 }
0252
0253 bit_mask = (1 << ppw) - 1;
0254 eorx = fgx ^ bgx;
0255 k = image->width/ppw;
0256
0257 for (i = 0; i < tablen; ++i)
0258 colortab[i] = (tab[i] & eorx) ^ bgx;
0259
0260 for (i = image->height; i--; ) {
0261 dst = (u32 __iomem *)dst1;
0262 shift = 8;
0263 src = s;
0264
0265
0266
0267
0268
0269
0270 switch (ppw) {
0271 case 4:
0272 for (j = k; j >= 2; j -= 2, ++src) {
0273 FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
0274 FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
0275 }
0276 break;
0277 case 2:
0278 for (j = k; j >= 4; j -= 4, ++src) {
0279 FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
0280 FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
0281 FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
0282 FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
0283 }
0284 break;
0285 case 1:
0286 for (j = k; j >= 8; j -= 8, ++src) {
0287 FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++);
0288 FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++);
0289 FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++);
0290 FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++);
0291 FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++);
0292 FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++);
0293 FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++);
0294 FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++);
0295 }
0296 break;
0297 }
0298
0299
0300
0301
0302
0303
0304 for (; j--; ) {
0305 shift -= ppw;
0306 FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++);
0307 if (!shift) {
0308 shift = 8;
0309 ++src;
0310 }
0311 }
0312
0313 dst1 += p->fix.line_length;
0314 s += spitch;
0315 }
0316 }
0317
0318 void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
0319 {
0320 u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
0321 u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
0322 u32 width = image->width;
0323 u32 dx = image->dx, dy = image->dy;
0324 u8 __iomem *dst1;
0325
0326 if (p->state != FBINFO_STATE_RUNNING)
0327 return;
0328
0329 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
0330 start_index = bitstart & (32 - 1);
0331 pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
0332
0333 bitstart /= 8;
0334 bitstart &= ~(bpl - 1);
0335 dst1 = p->screen_base + bitstart;
0336
0337 if (p->fbops->fb_sync)
0338 p->fbops->fb_sync(p);
0339
0340 if (image->depth == 1) {
0341 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
0342 p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
0343 fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
0344 bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
0345 } else {
0346 fgcolor = image->fg_color;
0347 bgcolor = image->bg_color;
0348 }
0349
0350 if (32 % bpp == 0 && !start_index && !pitch_index &&
0351 ((width & (32/bpp-1)) == 0) &&
0352 bpp >= 8 && bpp <= 32)
0353 fast_imageblit(image, p, dst1, fgcolor, bgcolor);
0354 else
0355 slow_imageblit(image, p, dst1, fgcolor, bgcolor,
0356 start_index, pitch_index);
0357 } else
0358 color_imageblit(image, p, dst1, start_index, pitch_index);
0359 }
0360
0361 EXPORT_SYMBOL(cfb_imageblit);
0362
0363 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
0364 MODULE_DESCRIPTION("Generic software accelerated imaging drawing");
0365 MODULE_LICENSE("GPL");
0366