119757fc8STomi Valkeinen /*
219757fc8STomi Valkeinen  *  Generic fillrect for frame buffers with packed pixels of any depth.
319757fc8STomi Valkeinen  *
419757fc8STomi Valkeinen  *      Copyright (C)  2000 James Simmons ([email protected])
519757fc8STomi Valkeinen  *
619757fc8STomi Valkeinen  *  This file is subject to the terms and conditions of the GNU General Public
719757fc8STomi Valkeinen  *  License.  See the file COPYING in the main directory of this archive for
819757fc8STomi Valkeinen  *  more details.
919757fc8STomi Valkeinen  *
1019757fc8STomi Valkeinen  * NOTES:
1119757fc8STomi Valkeinen  *
1219757fc8STomi Valkeinen  *  Also need to add code to deal with cards endians that are different than
1319757fc8STomi Valkeinen  *  the native cpu endians. I also need to deal with MSB position in the word.
1419757fc8STomi Valkeinen  *
1519757fc8STomi Valkeinen  */
1619757fc8STomi Valkeinen #include <linux/module.h>
1719757fc8STomi Valkeinen #include <linux/string.h>
1819757fc8STomi Valkeinen #include <linux/fb.h>
1919757fc8STomi Valkeinen #include <asm/types.h>
2019757fc8STomi Valkeinen #include "fb_draw.h"
2119757fc8STomi Valkeinen 
2219757fc8STomi Valkeinen #if BITS_PER_LONG == 32
2319757fc8STomi Valkeinen #  define FB_WRITEL fb_writel
2419757fc8STomi Valkeinen #  define FB_READL  fb_readl
2519757fc8STomi Valkeinen #else
2619757fc8STomi Valkeinen #  define FB_WRITEL fb_writeq
2719757fc8STomi Valkeinen #  define FB_READL  fb_readq
2819757fc8STomi Valkeinen #endif
2919757fc8STomi Valkeinen 
3019757fc8STomi Valkeinen     /*
3119757fc8STomi Valkeinen      *  Aligned pattern fill using 32/64-bit memory accesses
3219757fc8STomi Valkeinen      */
3319757fc8STomi Valkeinen 
3419757fc8STomi Valkeinen static void
3519757fc8STomi Valkeinen bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
3619757fc8STomi Valkeinen 		unsigned long pat, unsigned n, int bits, u32 bswapmask)
3719757fc8STomi Valkeinen {
3819757fc8STomi Valkeinen 	unsigned long first, last;
3919757fc8STomi Valkeinen 
4019757fc8STomi Valkeinen 	if (!n)
4119757fc8STomi Valkeinen 		return;
4219757fc8STomi Valkeinen 
4319757fc8STomi Valkeinen 	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
4419757fc8STomi Valkeinen 	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
4519757fc8STomi Valkeinen 
4619757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
4719757fc8STomi Valkeinen 		// Single word
4819757fc8STomi Valkeinen 		if (last)
4919757fc8STomi Valkeinen 			first &= last;
5019757fc8STomi Valkeinen 		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
5119757fc8STomi Valkeinen 	} else {
5219757fc8STomi Valkeinen 		// Multiple destination words
5319757fc8STomi Valkeinen 
5419757fc8STomi Valkeinen 		// Leading bits
5519757fc8STomi Valkeinen 		if (first!= ~0UL) {
5619757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
5719757fc8STomi Valkeinen 			dst++;
5819757fc8STomi Valkeinen 			n -= bits - dst_idx;
5919757fc8STomi Valkeinen 		}
6019757fc8STomi Valkeinen 
6119757fc8STomi Valkeinen 		// Main chunk
6219757fc8STomi Valkeinen 		n /= bits;
6319757fc8STomi Valkeinen 		while (n >= 8) {
6419757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
6519757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
6619757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
6719757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
6819757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
6919757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
7019757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
7119757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
7219757fc8STomi Valkeinen 			n -= 8;
7319757fc8STomi Valkeinen 		}
7419757fc8STomi Valkeinen 		while (n--)
7519757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
7619757fc8STomi Valkeinen 
7719757fc8STomi Valkeinen 		// Trailing bits
7819757fc8STomi Valkeinen 		if (last)
7919757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
8019757fc8STomi Valkeinen 	}
8119757fc8STomi Valkeinen }
8219757fc8STomi Valkeinen 
8319757fc8STomi Valkeinen 
8419757fc8STomi Valkeinen     /*
8519757fc8STomi Valkeinen      *  Unaligned generic pattern fill using 32/64-bit memory accesses
8619757fc8STomi Valkeinen      *  The pattern must have been expanded to a full 32/64-bit value
8719757fc8STomi Valkeinen      *  Left/right are the appropriate shifts to convert to the pattern to be
8819757fc8STomi Valkeinen      *  used for the next 32/64-bit word
8919757fc8STomi Valkeinen      */
9019757fc8STomi Valkeinen 
9119757fc8STomi Valkeinen static void
9219757fc8STomi Valkeinen bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
9319757fc8STomi Valkeinen 		  unsigned long pat, int left, int right, unsigned n, int bits)
9419757fc8STomi Valkeinen {
9519757fc8STomi Valkeinen 	unsigned long first, last;
9619757fc8STomi Valkeinen 
9719757fc8STomi Valkeinen 	if (!n)
9819757fc8STomi Valkeinen 		return;
9919757fc8STomi Valkeinen 
10019757fc8STomi Valkeinen 	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
10119757fc8STomi Valkeinen 	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
10219757fc8STomi Valkeinen 
10319757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
10419757fc8STomi Valkeinen 		// Single word
10519757fc8STomi Valkeinen 		if (last)
10619757fc8STomi Valkeinen 			first &= last;
10719757fc8STomi Valkeinen 		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
10819757fc8STomi Valkeinen 	} else {
10919757fc8STomi Valkeinen 		// Multiple destination words
11019757fc8STomi Valkeinen 		// Leading bits
11119757fc8STomi Valkeinen 		if (first) {
11219757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
11319757fc8STomi Valkeinen 			dst++;
11419757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
11519757fc8STomi Valkeinen 			n -= bits - dst_idx;
11619757fc8STomi Valkeinen 		}
11719757fc8STomi Valkeinen 
11819757fc8STomi Valkeinen 		// Main chunk
11919757fc8STomi Valkeinen 		n /= bits;
12019757fc8STomi Valkeinen 		while (n >= 4) {
12119757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
12219757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
12319757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
12419757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
12519757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
12619757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
12719757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
12819757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
12919757fc8STomi Valkeinen 			n -= 4;
13019757fc8STomi Valkeinen 		}
13119757fc8STomi Valkeinen 		while (n--) {
13219757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
13319757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
13419757fc8STomi Valkeinen 		}
13519757fc8STomi Valkeinen 
13619757fc8STomi Valkeinen 		// Trailing bits
13719757fc8STomi Valkeinen 		if (last)
13819757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
13919757fc8STomi Valkeinen 	}
14019757fc8STomi Valkeinen }
14119757fc8STomi Valkeinen 
14219757fc8STomi Valkeinen     /*
14319757fc8STomi Valkeinen      *  Aligned pattern invert using 32/64-bit memory accesses
14419757fc8STomi Valkeinen      */
14519757fc8STomi Valkeinen static void
14619757fc8STomi Valkeinen bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
14719757fc8STomi Valkeinen 		    int dst_idx, unsigned long pat, unsigned n, int bits,
14819757fc8STomi Valkeinen 		    u32 bswapmask)
14919757fc8STomi Valkeinen {
15019757fc8STomi Valkeinen 	unsigned long val = pat, dat;
15119757fc8STomi Valkeinen 	unsigned long first, last;
15219757fc8STomi Valkeinen 
15319757fc8STomi Valkeinen 	if (!n)
15419757fc8STomi Valkeinen 		return;
15519757fc8STomi Valkeinen 
15619757fc8STomi Valkeinen 	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
15719757fc8STomi Valkeinen 	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
15819757fc8STomi Valkeinen 
15919757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
16019757fc8STomi Valkeinen 		// Single word
16119757fc8STomi Valkeinen 		if (last)
16219757fc8STomi Valkeinen 			first &= last;
16319757fc8STomi Valkeinen 		dat = FB_READL(dst);
16419757fc8STomi Valkeinen 		FB_WRITEL(comp(dat ^ val, dat, first), dst);
16519757fc8STomi Valkeinen 	} else {
16619757fc8STomi Valkeinen 		// Multiple destination words
16719757fc8STomi Valkeinen 		// Leading bits
16819757fc8STomi Valkeinen 		if (first!=0UL) {
16919757fc8STomi Valkeinen 			dat = FB_READL(dst);
17019757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ val, dat, first), dst);
17119757fc8STomi Valkeinen 			dst++;
17219757fc8STomi Valkeinen 			n -= bits - dst_idx;
17319757fc8STomi Valkeinen 		}
17419757fc8STomi Valkeinen 
17519757fc8STomi Valkeinen 		// Main chunk
17619757fc8STomi Valkeinen 		n /= bits;
17719757fc8STomi Valkeinen 		while (n >= 8) {
17819757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
17919757fc8STomi Valkeinen 			dst++;
18019757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
18119757fc8STomi Valkeinen 			dst++;
18219757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
18319757fc8STomi Valkeinen 			dst++;
18419757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
18519757fc8STomi Valkeinen 			dst++;
18619757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
18719757fc8STomi Valkeinen 			dst++;
18819757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
18919757fc8STomi Valkeinen 			dst++;
19019757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
19119757fc8STomi Valkeinen 			dst++;
19219757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
19319757fc8STomi Valkeinen 			dst++;
19419757fc8STomi Valkeinen 			n -= 8;
19519757fc8STomi Valkeinen 		}
19619757fc8STomi Valkeinen 		while (n--) {
19719757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
19819757fc8STomi Valkeinen 			dst++;
19919757fc8STomi Valkeinen 		}
20019757fc8STomi Valkeinen 		// Trailing bits
20119757fc8STomi Valkeinen 		if (last) {
20219757fc8STomi Valkeinen 			dat = FB_READL(dst);
20319757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ val, dat, last), dst);
20419757fc8STomi Valkeinen 		}
20519757fc8STomi Valkeinen 	}
20619757fc8STomi Valkeinen }
20719757fc8STomi Valkeinen 
20819757fc8STomi Valkeinen 
20919757fc8STomi Valkeinen     /*
21019757fc8STomi Valkeinen      *  Unaligned generic pattern invert using 32/64-bit memory accesses
21119757fc8STomi Valkeinen      *  The pattern must have been expanded to a full 32/64-bit value
21219757fc8STomi Valkeinen      *  Left/right are the appropriate shifts to convert to the pattern to be
21319757fc8STomi Valkeinen      *  used for the next 32/64-bit word
21419757fc8STomi Valkeinen      */
21519757fc8STomi Valkeinen 
21619757fc8STomi Valkeinen static void
21719757fc8STomi Valkeinen bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
21819757fc8STomi Valkeinen 		      int dst_idx, unsigned long pat, int left, int right,
21919757fc8STomi Valkeinen 		      unsigned n, int bits)
22019757fc8STomi Valkeinen {
22119757fc8STomi Valkeinen 	unsigned long first, last, dat;
22219757fc8STomi Valkeinen 
22319757fc8STomi Valkeinen 	if (!n)
22419757fc8STomi Valkeinen 		return;
22519757fc8STomi Valkeinen 
22619757fc8STomi Valkeinen 	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
22719757fc8STomi Valkeinen 	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
22819757fc8STomi Valkeinen 
22919757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
23019757fc8STomi Valkeinen 		// Single word
23119757fc8STomi Valkeinen 		if (last)
23219757fc8STomi Valkeinen 			first &= last;
23319757fc8STomi Valkeinen 		dat = FB_READL(dst);
23419757fc8STomi Valkeinen 		FB_WRITEL(comp(dat ^ pat, dat, first), dst);
23519757fc8STomi Valkeinen 	} else {
23619757fc8STomi Valkeinen 		// Multiple destination words
23719757fc8STomi Valkeinen 
23819757fc8STomi Valkeinen 		// Leading bits
23919757fc8STomi Valkeinen 		if (first != 0UL) {
24019757fc8STomi Valkeinen 			dat = FB_READL(dst);
24119757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
24219757fc8STomi Valkeinen 			dst++;
24319757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
24419757fc8STomi Valkeinen 			n -= bits - dst_idx;
24519757fc8STomi Valkeinen 		}
24619757fc8STomi Valkeinen 
24719757fc8STomi Valkeinen 		// Main chunk
24819757fc8STomi Valkeinen 		n /= bits;
24919757fc8STomi Valkeinen 		while (n >= 4) {
25019757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
25119757fc8STomi Valkeinen 			dst++;
25219757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
25319757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
25419757fc8STomi Valkeinen 			dst++;
25519757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
25619757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
25719757fc8STomi Valkeinen 			dst++;
25819757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
25919757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
26019757fc8STomi Valkeinen 			dst++;
26119757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
26219757fc8STomi Valkeinen 			n -= 4;
26319757fc8STomi Valkeinen 		}
26419757fc8STomi Valkeinen 		while (n--) {
26519757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
26619757fc8STomi Valkeinen 			dst++;
26719757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
26819757fc8STomi Valkeinen 		}
26919757fc8STomi Valkeinen 
27019757fc8STomi Valkeinen 		// Trailing bits
27119757fc8STomi Valkeinen 		if (last) {
27219757fc8STomi Valkeinen 			dat = FB_READL(dst);
27319757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ pat, dat, last), dst);
27419757fc8STomi Valkeinen 		}
27519757fc8STomi Valkeinen 	}
27619757fc8STomi Valkeinen }
27719757fc8STomi Valkeinen 
27819757fc8STomi Valkeinen void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
27919757fc8STomi Valkeinen {
28019757fc8STomi Valkeinen 	unsigned long pat, pat2, fg;
28119757fc8STomi Valkeinen 	unsigned long width = rect->width, height = rect->height;
28219757fc8STomi Valkeinen 	int bits = BITS_PER_LONG, bytes = bits >> 3;
28319757fc8STomi Valkeinen 	u32 bpp = p->var.bits_per_pixel;
28419757fc8STomi Valkeinen 	unsigned long __iomem *dst;
28519757fc8STomi Valkeinen 	int dst_idx, left;
28619757fc8STomi Valkeinen 
28719757fc8STomi Valkeinen 	if (p->state != FBINFO_STATE_RUNNING)
28819757fc8STomi Valkeinen 		return;
28919757fc8STomi Valkeinen 
290*b3e88137SThomas Zimmermann 	if (p->flags & FBINFO_VIRTFB)
291*b3e88137SThomas Zimmermann 		fb_warn_once(p, "Framebuffer is not in I/O address space.");
292*b3e88137SThomas Zimmermann 
29319757fc8STomi Valkeinen 	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
29419757fc8STomi Valkeinen 	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
29519757fc8STomi Valkeinen 		fg = ((u32 *) (p->pseudo_palette))[rect->color];
29619757fc8STomi Valkeinen 	else
29719757fc8STomi Valkeinen 		fg = rect->color;
29819757fc8STomi Valkeinen 
29919757fc8STomi Valkeinen 	pat = pixel_to_pat(bpp, fg);
30019757fc8STomi Valkeinen 
30119757fc8STomi Valkeinen 	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
30219757fc8STomi Valkeinen 	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
30319757fc8STomi Valkeinen 	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
30419757fc8STomi Valkeinen 	/* FIXME For now we support 1-32 bpp only */
30519757fc8STomi Valkeinen 	left = bits % bpp;
30619757fc8STomi Valkeinen 	if (p->fbops->fb_sync)
30719757fc8STomi Valkeinen 		p->fbops->fb_sync(p);
30819757fc8STomi Valkeinen 	if (!left) {
30919757fc8STomi Valkeinen 		u32 bswapmask = fb_compute_bswapmask(p);
31019757fc8STomi Valkeinen 		void (*fill_op32)(struct fb_info *p,
31119757fc8STomi Valkeinen 				  unsigned long __iomem *dst, int dst_idx,
31219757fc8STomi Valkeinen 		                  unsigned long pat, unsigned n, int bits,
31319757fc8STomi Valkeinen 				  u32 bswapmask) = NULL;
31419757fc8STomi Valkeinen 
31519757fc8STomi Valkeinen 		switch (rect->rop) {
31619757fc8STomi Valkeinen 		case ROP_XOR:
31719757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned_rev;
31819757fc8STomi Valkeinen 			break;
31919757fc8STomi Valkeinen 		case ROP_COPY:
32019757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned;
32119757fc8STomi Valkeinen 			break;
32219757fc8STomi Valkeinen 		default:
32319757fc8STomi Valkeinen 			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
32419757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned;
32519757fc8STomi Valkeinen 			break;
32619757fc8STomi Valkeinen 		}
32719757fc8STomi Valkeinen 		while (height--) {
32819757fc8STomi Valkeinen 			dst += dst_idx >> (ffs(bits) - 1);
32919757fc8STomi Valkeinen 			dst_idx &= (bits - 1);
33019757fc8STomi Valkeinen 			fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
33119757fc8STomi Valkeinen 				  bswapmask);
33219757fc8STomi Valkeinen 			dst_idx += p->fix.line_length*8;
33319757fc8STomi Valkeinen 		}
33419757fc8STomi Valkeinen 	} else {
33519757fc8STomi Valkeinen 		int right, r;
33619757fc8STomi Valkeinen 		void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
33719757fc8STomi Valkeinen 				int dst_idx, unsigned long pat, int left,
33819757fc8STomi Valkeinen 				int right, unsigned n, int bits) = NULL;
33919757fc8STomi Valkeinen #ifdef __LITTLE_ENDIAN
34019757fc8STomi Valkeinen 		right = left;
34119757fc8STomi Valkeinen 		left = bpp - right;
34219757fc8STomi Valkeinen #else
34319757fc8STomi Valkeinen 		right = bpp - left;
34419757fc8STomi Valkeinen #endif
34519757fc8STomi Valkeinen 		switch (rect->rop) {
34619757fc8STomi Valkeinen 		case ROP_XOR:
34719757fc8STomi Valkeinen 			fill_op = bitfill_unaligned_rev;
34819757fc8STomi Valkeinen 			break;
34919757fc8STomi Valkeinen 		case ROP_COPY:
35019757fc8STomi Valkeinen 			fill_op = bitfill_unaligned;
35119757fc8STomi Valkeinen 			break;
35219757fc8STomi Valkeinen 		default:
35319757fc8STomi Valkeinen 			printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
35419757fc8STomi Valkeinen 			fill_op = bitfill_unaligned;
35519757fc8STomi Valkeinen 			break;
35619757fc8STomi Valkeinen 		}
35719757fc8STomi Valkeinen 		while (height--) {
35819757fc8STomi Valkeinen 			dst += dst_idx / bits;
35919757fc8STomi Valkeinen 			dst_idx &= (bits - 1);
36019757fc8STomi Valkeinen 			r = dst_idx % bpp;
36119757fc8STomi Valkeinen 			/* rotate pattern to the correct start position */
36219757fc8STomi Valkeinen 			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
36319757fc8STomi Valkeinen 			fill_op(p, dst, dst_idx, pat2, left, right,
36419757fc8STomi Valkeinen 				width*bpp, bits);
36519757fc8STomi Valkeinen 			dst_idx += p->fix.line_length*8;
36619757fc8STomi Valkeinen 		}
36719757fc8STomi Valkeinen 	}
36819757fc8STomi Valkeinen }
36919757fc8STomi Valkeinen 
37019757fc8STomi Valkeinen EXPORT_SYMBOL(cfb_fillrect);
37119757fc8STomi Valkeinen 
37219757fc8STomi Valkeinen MODULE_AUTHOR("James Simmons <[email protected]>");
37319757fc8STomi Valkeinen MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
37419757fc8STomi Valkeinen MODULE_LICENSE("GPL");
375