0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/module.h>
0017 #include <linux/string.h>
0018 #include <linux/fb.h>
0019 #include <asm/types.h>
0020 #include "fb_draw.h"
0021
0022 #if BITS_PER_LONG == 32
0023 # define FB_WRITEL fb_writel
0024 # define FB_READL fb_readl
0025 #else
0026 # define FB_WRITEL fb_writeq
0027 # define FB_READL fb_readq
0028 #endif
0029
0030
0031
0032
0033
0034 static void
0035 bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
0036 unsigned long pat, unsigned n, int bits, u32 bswapmask)
0037 {
0038 unsigned long first, last;
0039
0040 if (!n)
0041 return;
0042
0043 first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
0044 last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
0045
0046 if (dst_idx+n <= bits) {
0047
0048 if (last)
0049 first &= last;
0050 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
0051 } else {
0052
0053
0054
0055 if (first!= ~0UL) {
0056 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
0057 dst++;
0058 n -= bits - dst_idx;
0059 }
0060
0061
0062 n /= bits;
0063 while (n >= 8) {
0064 FB_WRITEL(pat, dst++);
0065 FB_WRITEL(pat, dst++);
0066 FB_WRITEL(pat, dst++);
0067 FB_WRITEL(pat, dst++);
0068 FB_WRITEL(pat, dst++);
0069 FB_WRITEL(pat, dst++);
0070 FB_WRITEL(pat, dst++);
0071 FB_WRITEL(pat, dst++);
0072 n -= 8;
0073 }
0074 while (n--)
0075 FB_WRITEL(pat, dst++);
0076
0077
0078 if (last)
0079 FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
0080 }
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static void
0092 bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
0093 unsigned long pat, int left, int right, unsigned n, int bits)
0094 {
0095 unsigned long first, last;
0096
0097 if (!n)
0098 return;
0099
0100 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0101 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0102
0103 if (dst_idx+n <= bits) {
0104
0105 if (last)
0106 first &= last;
0107 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
0108 } else {
0109
0110
0111 if (first) {
0112 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
0113 dst++;
0114 pat = pat << left | pat >> right;
0115 n -= bits - dst_idx;
0116 }
0117
0118
0119 n /= bits;
0120 while (n >= 4) {
0121 FB_WRITEL(pat, dst++);
0122 pat = pat << left | pat >> right;
0123 FB_WRITEL(pat, dst++);
0124 pat = pat << left | pat >> right;
0125 FB_WRITEL(pat, dst++);
0126 pat = pat << left | pat >> right;
0127 FB_WRITEL(pat, dst++);
0128 pat = pat << left | pat >> right;
0129 n -= 4;
0130 }
0131 while (n--) {
0132 FB_WRITEL(pat, dst++);
0133 pat = pat << left | pat >> right;
0134 }
0135
0136
0137 if (last)
0138 FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
0139 }
0140 }
0141
0142
0143
0144
0145 static void
0146 bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
0147 int dst_idx, unsigned long pat, unsigned n, int bits,
0148 u32 bswapmask)
0149 {
0150 unsigned long val = pat, dat;
0151 unsigned long first, last;
0152
0153 if (!n)
0154 return;
0155
0156 first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
0157 last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
0158
0159 if (dst_idx+n <= bits) {
0160
0161 if (last)
0162 first &= last;
0163 dat = FB_READL(dst);
0164 FB_WRITEL(comp(dat ^ val, dat, first), dst);
0165 } else {
0166
0167
0168 if (first!=0UL) {
0169 dat = FB_READL(dst);
0170 FB_WRITEL(comp(dat ^ val, dat, first), dst);
0171 dst++;
0172 n -= bits - dst_idx;
0173 }
0174
0175
0176 n /= bits;
0177 while (n >= 8) {
0178 FB_WRITEL(FB_READL(dst) ^ val, dst);
0179 dst++;
0180 FB_WRITEL(FB_READL(dst) ^ val, dst);
0181 dst++;
0182 FB_WRITEL(FB_READL(dst) ^ val, dst);
0183 dst++;
0184 FB_WRITEL(FB_READL(dst) ^ val, dst);
0185 dst++;
0186 FB_WRITEL(FB_READL(dst) ^ val, dst);
0187 dst++;
0188 FB_WRITEL(FB_READL(dst) ^ val, dst);
0189 dst++;
0190 FB_WRITEL(FB_READL(dst) ^ val, dst);
0191 dst++;
0192 FB_WRITEL(FB_READL(dst) ^ val, dst);
0193 dst++;
0194 n -= 8;
0195 }
0196 while (n--) {
0197 FB_WRITEL(FB_READL(dst) ^ val, dst);
0198 dst++;
0199 }
0200
0201 if (last) {
0202 dat = FB_READL(dst);
0203 FB_WRITEL(comp(dat ^ val, dat, last), dst);
0204 }
0205 }
0206 }
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 static void
0217 bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
0218 int dst_idx, unsigned long pat, int left, int right,
0219 unsigned n, int bits)
0220 {
0221 unsigned long first, last, dat;
0222
0223 if (!n)
0224 return;
0225
0226 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
0227 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
0228
0229 if (dst_idx+n <= bits) {
0230
0231 if (last)
0232 first &= last;
0233 dat = FB_READL(dst);
0234 FB_WRITEL(comp(dat ^ pat, dat, first), dst);
0235 } else {
0236
0237
0238
0239 if (first != 0UL) {
0240 dat = FB_READL(dst);
0241 FB_WRITEL(comp(dat ^ pat, dat, first), dst);
0242 dst++;
0243 pat = pat << left | pat >> right;
0244 n -= bits - dst_idx;
0245 }
0246
0247
0248 n /= bits;
0249 while (n >= 4) {
0250 FB_WRITEL(FB_READL(dst) ^ pat, dst);
0251 dst++;
0252 pat = pat << left | pat >> right;
0253 FB_WRITEL(FB_READL(dst) ^ pat, dst);
0254 dst++;
0255 pat = pat << left | pat >> right;
0256 FB_WRITEL(FB_READL(dst) ^ pat, dst);
0257 dst++;
0258 pat = pat << left | pat >> right;
0259 FB_WRITEL(FB_READL(dst) ^ pat, dst);
0260 dst++;
0261 pat = pat << left | pat >> right;
0262 n -= 4;
0263 }
0264 while (n--) {
0265 FB_WRITEL(FB_READL(dst) ^ pat, dst);
0266 dst++;
0267 pat = pat << left | pat >> right;
0268 }
0269
0270
0271 if (last) {
0272 dat = FB_READL(dst);
0273 FB_WRITEL(comp(dat ^ pat, dat, last), dst);
0274 }
0275 }
0276 }
0277
0278 void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
0279 {
0280 unsigned long pat, pat2, fg;
0281 unsigned long width = rect->width, height = rect->height;
0282 int bits = BITS_PER_LONG, bytes = bits >> 3;
0283 u32 bpp = p->var.bits_per_pixel;
0284 unsigned long __iomem *dst;
0285 int dst_idx, left;
0286
0287 if (p->state != FBINFO_STATE_RUNNING)
0288 return;
0289
0290 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
0291 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
0292 fg = ((u32 *) (p->pseudo_palette))[rect->color];
0293 else
0294 fg = rect->color;
0295
0296 pat = pixel_to_pat(bpp, fg);
0297
0298 dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
0299 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
0300 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
0301
0302 left = bits % bpp;
0303 if (p->fbops->fb_sync)
0304 p->fbops->fb_sync(p);
0305 if (!left) {
0306 u32 bswapmask = fb_compute_bswapmask(p);
0307 void (*fill_op32)(struct fb_info *p,
0308 unsigned long __iomem *dst, int dst_idx,
0309 unsigned long pat, unsigned n, int bits,
0310 u32 bswapmask) = NULL;
0311
0312 switch (rect->rop) {
0313 case ROP_XOR:
0314 fill_op32 = bitfill_aligned_rev;
0315 break;
0316 case ROP_COPY:
0317 fill_op32 = bitfill_aligned;
0318 break;
0319 default:
0320 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
0321 fill_op32 = bitfill_aligned;
0322 break;
0323 }
0324 while (height--) {
0325 dst += dst_idx >> (ffs(bits) - 1);
0326 dst_idx &= (bits - 1);
0327 fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
0328 bswapmask);
0329 dst_idx += p->fix.line_length*8;
0330 }
0331 } else {
0332 int right, r;
0333 void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
0334 int dst_idx, unsigned long pat, int left,
0335 int right, unsigned n, int bits) = NULL;
0336 #ifdef __LITTLE_ENDIAN
0337 right = left;
0338 left = bpp - right;
0339 #else
0340 right = bpp - left;
0341 #endif
0342 switch (rect->rop) {
0343 case ROP_XOR:
0344 fill_op = bitfill_unaligned_rev;
0345 break;
0346 case ROP_COPY:
0347 fill_op = bitfill_unaligned;
0348 break;
0349 default:
0350 printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
0351 fill_op = bitfill_unaligned;
0352 break;
0353 }
0354 while (height--) {
0355 dst += dst_idx / bits;
0356 dst_idx &= (bits - 1);
0357 r = dst_idx % bpp;
0358
0359 pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
0360 fill_op(p, dst, dst_idx, pat2, left, right,
0361 width*bpp, bits);
0362 dst_idx += p->fix.line_length*8;
0363 }
0364 }
0365 }
0366
0367 EXPORT_SYMBOL(cfb_fillrect);
0368
0369 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
0370 MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
0371 MODULE_LICENSE("GPL");