2 * Generic fillrect for frame buffers with packed pixels of any depth.
4 * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org)
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
12 * Also need to add code to deal with cards endians that are different than
13 * the native cpu endians. I also need to deal with MSB position in the word.
16 #include <linux/module.h>
17 #include <linux/string.h>
19 #include <asm/types.h>
22 #if BITS_PER_LONG == 32
23 # define FB_WRITEL fb_writel
24 # define FB_READL fb_readl
26 # define FB_WRITEL fb_writeq
27 # define FB_READL fb_readq
31 * Aligned pattern fill using 32/64-bit memory accesses
35 bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
36 unsigned long pat, unsigned n, int bits, u32 bswapmask)
38 unsigned long first, last;
43 first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
44 last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
46 if (dst_idx+n <= bits) {
50 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
52 // Multiple destination words
56 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
64 FB_WRITEL(pat, dst++);
65 FB_WRITEL(pat, dst++);
66 FB_WRITEL(pat, dst++);
67 FB_WRITEL(pat, dst++);
68 FB_WRITEL(pat, dst++);
69 FB_WRITEL(pat, dst++);
70 FB_WRITEL(pat, dst++);
71 FB_WRITEL(pat, dst++);
75 FB_WRITEL(pat, dst++);
79 FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
85 * Unaligned generic pattern fill using 32/64-bit memory accesses
86 * The pattern must have been expanded to a full 32/64-bit value
87 * Left/right are the appropriate shifts to convert to the pattern to be
88 * used for the next 32/64-bit word
92 bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
93 unsigned long pat, int left, int right, unsigned n, int bits)
95 unsigned long first, last;
100 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
101 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
103 if (dst_idx+n <= bits) {
107 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
109 // Multiple destination words
112 FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
114 pat = pat << left | pat >> right;
121 FB_WRITEL(pat, dst++);
122 pat = pat << left | pat >> right;
123 FB_WRITEL(pat, dst++);
124 pat = pat << left | pat >> right;
125 FB_WRITEL(pat, dst++);
126 pat = pat << left | pat >> right;
127 FB_WRITEL(pat, dst++);
128 pat = pat << left | pat >> right;
132 FB_WRITEL(pat, dst++);
133 pat = pat << left | pat >> right;
138 FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
143 * Aligned pattern invert using 32/64-bit memory accesses
146 bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
147 int dst_idx, unsigned long pat, unsigned n, int bits,
150 unsigned long val = pat, dat;
151 unsigned long first, last;
156 first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
157 last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
159 if (dst_idx+n <= bits) {
164 FB_WRITEL(comp(dat ^ val, dat, first), dst);
166 // Multiple destination words
170 FB_WRITEL(comp(dat ^ val, dat, first), dst);
178 FB_WRITEL(FB_READL(dst) ^ val, dst);
180 FB_WRITEL(FB_READL(dst) ^ val, dst);
182 FB_WRITEL(FB_READL(dst) ^ val, dst);
184 FB_WRITEL(FB_READL(dst) ^ val, dst);
186 FB_WRITEL(FB_READL(dst) ^ val, dst);
188 FB_WRITEL(FB_READL(dst) ^ val, dst);
190 FB_WRITEL(FB_READL(dst) ^ val, dst);
192 FB_WRITEL(FB_READL(dst) ^ val, dst);
197 FB_WRITEL(FB_READL(dst) ^ val, dst);
203 FB_WRITEL(comp(dat ^ val, dat, last), dst);
210 * Unaligned generic pattern invert using 32/64-bit memory accesses
211 * The pattern must have been expanded to a full 32/64-bit value
212 * Left/right are the appropriate shifts to convert to the pattern to be
213 * used for the next 32/64-bit word
217 bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
218 int dst_idx, unsigned long pat, int left, int right,
219 unsigned n, int bits)
221 unsigned long first, last, dat;
226 first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
227 last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
229 if (dst_idx+n <= bits) {
234 FB_WRITEL(comp(dat ^ pat, dat, first), dst);
236 // Multiple destination words
241 FB_WRITEL(comp(dat ^ pat, dat, first), dst);
243 pat = pat << left | pat >> right;
250 FB_WRITEL(FB_READL(dst) ^ pat, dst);
252 pat = pat << left | pat >> right;
253 FB_WRITEL(FB_READL(dst) ^ pat, dst);
255 pat = pat << left | pat >> right;
256 FB_WRITEL(FB_READL(dst) ^ pat, dst);
258 pat = pat << left | pat >> right;
259 FB_WRITEL(FB_READL(dst) ^ pat, dst);
261 pat = pat << left | pat >> right;
265 FB_WRITEL(FB_READL(dst) ^ pat, dst);
267 pat = pat << left | pat >> right;
273 FB_WRITEL(comp(dat ^ pat, dat, last), dst);
278 void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
280 unsigned long pat, pat2, fg;
281 unsigned long width = rect->width, height = rect->height;
282 int bits = BITS_PER_LONG, bytes = bits >> 3;
283 u32 bpp = p->var.bits_per_pixel;
284 unsigned long __iomem *dst;
287 if (p->state != FBINFO_STATE_RUNNING)
290 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
291 p->fix.visual == FB_VISUAL_DIRECTCOLOR )
292 fg = ((u32 *) (p->pseudo_palette))[rect->color];
296 pat = pixel_to_pat(bpp, fg);
298 dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
299 dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
300 dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
301 /* FIXME For now we support 1-32 bpp only */
303 if (p->fbops->fb_sync)
304 p->fbops->fb_sync(p);
306 u32 bswapmask = fb_compute_bswapmask(p);
307 void (*fill_op32)(struct fb_info *p,
308 unsigned long __iomem *dst, int dst_idx,
309 unsigned long pat, unsigned n, int bits,
310 u32 bswapmask) = NULL;
314 fill_op32 = bitfill_aligned_rev;
317 fill_op32 = bitfill_aligned;
320 printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
321 fill_op32 = bitfill_aligned;
325 dst += dst_idx >> (ffs(bits) - 1);
326 dst_idx &= (bits - 1);
327 fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
329 dst_idx += p->fix.line_length*8;
333 void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
334 int dst_idx, unsigned long pat, int left,
335 int right, unsigned n, int bits) = NULL;
336 #ifdef __LITTLE_ENDIAN
344 fill_op = bitfill_unaligned_rev;
347 fill_op = bitfill_unaligned;
350 printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
351 fill_op = bitfill_unaligned;
355 dst += dst_idx / bits;
356 dst_idx &= (bits - 1);
358 /* rotate pattern to the correct start position */
359 pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
360 fill_op(p, dst, dst_idx, pat2, left, right,
362 dst_idx += p->fix.line_length*8;
367 EXPORT_SYMBOL(cfb_fillrect);
369 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
370 MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
371 MODULE_LICENSE("GPL");