1*19757fc8STomi Valkeinen /*
2*19757fc8STomi Valkeinen  *  Generic fillrect for frame buffers with packed pixels of any depth.
3*19757fc8STomi Valkeinen  *
4*19757fc8STomi Valkeinen  *      Copyright (C)  2000 James Simmons ([email protected])
5*19757fc8STomi Valkeinen  *
6*19757fc8STomi Valkeinen  *  This file is subject to the terms and conditions of the GNU General Public
7*19757fc8STomi Valkeinen  *  License.  See the file COPYING in the main directory of this archive for
8*19757fc8STomi Valkeinen  *  more details.
9*19757fc8STomi Valkeinen  *
10*19757fc8STomi Valkeinen  * NOTES:
11*19757fc8STomi Valkeinen  *
12*19757fc8STomi Valkeinen  *  Also need to add code to deal with cards endians that are different than
13*19757fc8STomi Valkeinen  *  the native cpu endians. I also need to deal with MSB position in the word.
14*19757fc8STomi Valkeinen  *
15*19757fc8STomi Valkeinen  */
16*19757fc8STomi Valkeinen #include <linux/module.h>
17*19757fc8STomi Valkeinen #include <linux/string.h>
18*19757fc8STomi Valkeinen #include <linux/fb.h>
19*19757fc8STomi Valkeinen #include <asm/types.h>
20*19757fc8STomi Valkeinen #include "fb_draw.h"
21*19757fc8STomi Valkeinen 
22*19757fc8STomi Valkeinen #if BITS_PER_LONG == 32
23*19757fc8STomi Valkeinen #  define FB_WRITEL fb_writel
24*19757fc8STomi Valkeinen #  define FB_READL  fb_readl
25*19757fc8STomi Valkeinen #else
26*19757fc8STomi Valkeinen #  define FB_WRITEL fb_writeq
27*19757fc8STomi Valkeinen #  define FB_READL  fb_readq
28*19757fc8STomi Valkeinen #endif
29*19757fc8STomi Valkeinen 
30*19757fc8STomi Valkeinen     /*
31*19757fc8STomi Valkeinen      *  Aligned pattern fill using 32/64-bit memory accesses
32*19757fc8STomi Valkeinen      */
33*19757fc8STomi Valkeinen 
34*19757fc8STomi Valkeinen static void
35*19757fc8STomi Valkeinen bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
36*19757fc8STomi Valkeinen 		unsigned long pat, unsigned n, int bits, u32 bswapmask)
37*19757fc8STomi Valkeinen {
38*19757fc8STomi Valkeinen 	unsigned long first, last;
39*19757fc8STomi Valkeinen 
40*19757fc8STomi Valkeinen 	if (!n)
41*19757fc8STomi Valkeinen 		return;
42*19757fc8STomi Valkeinen 
43*19757fc8STomi Valkeinen 	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
44*19757fc8STomi Valkeinen 	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
45*19757fc8STomi Valkeinen 
46*19757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
47*19757fc8STomi Valkeinen 		// Single word
48*19757fc8STomi Valkeinen 		if (last)
49*19757fc8STomi Valkeinen 			first &= last;
50*19757fc8STomi Valkeinen 		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
51*19757fc8STomi Valkeinen 	} else {
52*19757fc8STomi Valkeinen 		// Multiple destination words
53*19757fc8STomi Valkeinen 
54*19757fc8STomi Valkeinen 		// Leading bits
55*19757fc8STomi Valkeinen 		if (first!= ~0UL) {
56*19757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
57*19757fc8STomi Valkeinen 			dst++;
58*19757fc8STomi Valkeinen 			n -= bits - dst_idx;
59*19757fc8STomi Valkeinen 		}
60*19757fc8STomi Valkeinen 
61*19757fc8STomi Valkeinen 		// Main chunk
62*19757fc8STomi Valkeinen 		n /= bits;
63*19757fc8STomi Valkeinen 		while (n >= 8) {
64*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
65*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
66*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
67*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
68*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
69*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
70*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
71*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
72*19757fc8STomi Valkeinen 			n -= 8;
73*19757fc8STomi Valkeinen 		}
74*19757fc8STomi Valkeinen 		while (n--)
75*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
76*19757fc8STomi Valkeinen 
77*19757fc8STomi Valkeinen 		// Trailing bits
78*19757fc8STomi Valkeinen 		if (last)
79*19757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
80*19757fc8STomi Valkeinen 	}
81*19757fc8STomi Valkeinen }
82*19757fc8STomi Valkeinen 
83*19757fc8STomi Valkeinen 
84*19757fc8STomi Valkeinen     /*
85*19757fc8STomi Valkeinen      *  Unaligned generic pattern fill using 32/64-bit memory accesses
86*19757fc8STomi Valkeinen      *  The pattern must have been expanded to a full 32/64-bit value
87*19757fc8STomi Valkeinen      *  Left/right are the appropriate shifts to convert to the pattern to be
88*19757fc8STomi Valkeinen      *  used for the next 32/64-bit word
89*19757fc8STomi Valkeinen      */
90*19757fc8STomi Valkeinen 
91*19757fc8STomi Valkeinen static void
92*19757fc8STomi Valkeinen bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx,
93*19757fc8STomi Valkeinen 		  unsigned long pat, int left, int right, unsigned n, int bits)
94*19757fc8STomi Valkeinen {
95*19757fc8STomi Valkeinen 	unsigned long first, last;
96*19757fc8STomi Valkeinen 
97*19757fc8STomi Valkeinen 	if (!n)
98*19757fc8STomi Valkeinen 		return;
99*19757fc8STomi Valkeinen 
100*19757fc8STomi Valkeinen 	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
101*19757fc8STomi Valkeinen 	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
102*19757fc8STomi Valkeinen 
103*19757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
104*19757fc8STomi Valkeinen 		// Single word
105*19757fc8STomi Valkeinen 		if (last)
106*19757fc8STomi Valkeinen 			first &= last;
107*19757fc8STomi Valkeinen 		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
108*19757fc8STomi Valkeinen 	} else {
109*19757fc8STomi Valkeinen 		// Multiple destination words
110*19757fc8STomi Valkeinen 		// Leading bits
111*19757fc8STomi Valkeinen 		if (first) {
112*19757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
113*19757fc8STomi Valkeinen 			dst++;
114*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
115*19757fc8STomi Valkeinen 			n -= bits - dst_idx;
116*19757fc8STomi Valkeinen 		}
117*19757fc8STomi Valkeinen 
118*19757fc8STomi Valkeinen 		// Main chunk
119*19757fc8STomi Valkeinen 		n /= bits;
120*19757fc8STomi Valkeinen 		while (n >= 4) {
121*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
122*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
123*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
124*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
125*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
126*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
127*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
128*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
129*19757fc8STomi Valkeinen 			n -= 4;
130*19757fc8STomi Valkeinen 		}
131*19757fc8STomi Valkeinen 		while (n--) {
132*19757fc8STomi Valkeinen 			FB_WRITEL(pat, dst++);
133*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
134*19757fc8STomi Valkeinen 		}
135*19757fc8STomi Valkeinen 
136*19757fc8STomi Valkeinen 		// Trailing bits
137*19757fc8STomi Valkeinen 		if (last)
138*19757fc8STomi Valkeinen 			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
139*19757fc8STomi Valkeinen 	}
140*19757fc8STomi Valkeinen }
141*19757fc8STomi Valkeinen 
142*19757fc8STomi Valkeinen     /*
143*19757fc8STomi Valkeinen      *  Aligned pattern invert using 32/64-bit memory accesses
144*19757fc8STomi Valkeinen      */
145*19757fc8STomi Valkeinen static void
146*19757fc8STomi Valkeinen bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst,
147*19757fc8STomi Valkeinen 		    int dst_idx, unsigned long pat, unsigned n, int bits,
148*19757fc8STomi Valkeinen 		    u32 bswapmask)
149*19757fc8STomi Valkeinen {
150*19757fc8STomi Valkeinen 	unsigned long val = pat, dat;
151*19757fc8STomi Valkeinen 	unsigned long first, last;
152*19757fc8STomi Valkeinen 
153*19757fc8STomi Valkeinen 	if (!n)
154*19757fc8STomi Valkeinen 		return;
155*19757fc8STomi Valkeinen 
156*19757fc8STomi Valkeinen 	first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask);
157*19757fc8STomi Valkeinen 	last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask);
158*19757fc8STomi Valkeinen 
159*19757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
160*19757fc8STomi Valkeinen 		// Single word
161*19757fc8STomi Valkeinen 		if (last)
162*19757fc8STomi Valkeinen 			first &= last;
163*19757fc8STomi Valkeinen 		dat = FB_READL(dst);
164*19757fc8STomi Valkeinen 		FB_WRITEL(comp(dat ^ val, dat, first), dst);
165*19757fc8STomi Valkeinen 	} else {
166*19757fc8STomi Valkeinen 		// Multiple destination words
167*19757fc8STomi Valkeinen 		// Leading bits
168*19757fc8STomi Valkeinen 		if (first!=0UL) {
169*19757fc8STomi Valkeinen 			dat = FB_READL(dst);
170*19757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ val, dat, first), dst);
171*19757fc8STomi Valkeinen 			dst++;
172*19757fc8STomi Valkeinen 			n -= bits - dst_idx;
173*19757fc8STomi Valkeinen 		}
174*19757fc8STomi Valkeinen 
175*19757fc8STomi Valkeinen 		// Main chunk
176*19757fc8STomi Valkeinen 		n /= bits;
177*19757fc8STomi Valkeinen 		while (n >= 8) {
178*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
179*19757fc8STomi Valkeinen 			dst++;
180*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
181*19757fc8STomi Valkeinen 			dst++;
182*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
183*19757fc8STomi Valkeinen 			dst++;
184*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
185*19757fc8STomi Valkeinen 			dst++;
186*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
187*19757fc8STomi Valkeinen 			dst++;
188*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
189*19757fc8STomi Valkeinen 			dst++;
190*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
191*19757fc8STomi Valkeinen 			dst++;
192*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
193*19757fc8STomi Valkeinen 			dst++;
194*19757fc8STomi Valkeinen 			n -= 8;
195*19757fc8STomi Valkeinen 		}
196*19757fc8STomi Valkeinen 		while (n--) {
197*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ val, dst);
198*19757fc8STomi Valkeinen 			dst++;
199*19757fc8STomi Valkeinen 		}
200*19757fc8STomi Valkeinen 		// Trailing bits
201*19757fc8STomi Valkeinen 		if (last) {
202*19757fc8STomi Valkeinen 			dat = FB_READL(dst);
203*19757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ val, dat, last), dst);
204*19757fc8STomi Valkeinen 		}
205*19757fc8STomi Valkeinen 	}
206*19757fc8STomi Valkeinen }
207*19757fc8STomi Valkeinen 
208*19757fc8STomi Valkeinen 
209*19757fc8STomi Valkeinen     /*
210*19757fc8STomi Valkeinen      *  Unaligned generic pattern invert using 32/64-bit memory accesses
211*19757fc8STomi Valkeinen      *  The pattern must have been expanded to a full 32/64-bit value
212*19757fc8STomi Valkeinen      *  Left/right are the appropriate shifts to convert to the pattern to be
213*19757fc8STomi Valkeinen      *  used for the next 32/64-bit word
214*19757fc8STomi Valkeinen      */
215*19757fc8STomi Valkeinen 
216*19757fc8STomi Valkeinen static void
217*19757fc8STomi Valkeinen bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst,
218*19757fc8STomi Valkeinen 		      int dst_idx, unsigned long pat, int left, int right,
219*19757fc8STomi Valkeinen 		      unsigned n, int bits)
220*19757fc8STomi Valkeinen {
221*19757fc8STomi Valkeinen 	unsigned long first, last, dat;
222*19757fc8STomi Valkeinen 
223*19757fc8STomi Valkeinen 	if (!n)
224*19757fc8STomi Valkeinen 		return;
225*19757fc8STomi Valkeinen 
226*19757fc8STomi Valkeinen 	first = FB_SHIFT_HIGH(p, ~0UL, dst_idx);
227*19757fc8STomi Valkeinen 	last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits));
228*19757fc8STomi Valkeinen 
229*19757fc8STomi Valkeinen 	if (dst_idx+n <= bits) {
230*19757fc8STomi Valkeinen 		// Single word
231*19757fc8STomi Valkeinen 		if (last)
232*19757fc8STomi Valkeinen 			first &= last;
233*19757fc8STomi Valkeinen 		dat = FB_READL(dst);
234*19757fc8STomi Valkeinen 		FB_WRITEL(comp(dat ^ pat, dat, first), dst);
235*19757fc8STomi Valkeinen 	} else {
236*19757fc8STomi Valkeinen 		// Multiple destination words
237*19757fc8STomi Valkeinen 
238*19757fc8STomi Valkeinen 		// Leading bits
239*19757fc8STomi Valkeinen 		if (first != 0UL) {
240*19757fc8STomi Valkeinen 			dat = FB_READL(dst);
241*19757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
242*19757fc8STomi Valkeinen 			dst++;
243*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
244*19757fc8STomi Valkeinen 			n -= bits - dst_idx;
245*19757fc8STomi Valkeinen 		}
246*19757fc8STomi Valkeinen 
247*19757fc8STomi Valkeinen 		// Main chunk
248*19757fc8STomi Valkeinen 		n /= bits;
249*19757fc8STomi Valkeinen 		while (n >= 4) {
250*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
251*19757fc8STomi Valkeinen 			dst++;
252*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
253*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
254*19757fc8STomi Valkeinen 			dst++;
255*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
256*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
257*19757fc8STomi Valkeinen 			dst++;
258*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
259*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
260*19757fc8STomi Valkeinen 			dst++;
261*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
262*19757fc8STomi Valkeinen 			n -= 4;
263*19757fc8STomi Valkeinen 		}
264*19757fc8STomi Valkeinen 		while (n--) {
265*19757fc8STomi Valkeinen 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
266*19757fc8STomi Valkeinen 			dst++;
267*19757fc8STomi Valkeinen 			pat = pat << left | pat >> right;
268*19757fc8STomi Valkeinen 		}
269*19757fc8STomi Valkeinen 
270*19757fc8STomi Valkeinen 		// Trailing bits
271*19757fc8STomi Valkeinen 		if (last) {
272*19757fc8STomi Valkeinen 			dat = FB_READL(dst);
273*19757fc8STomi Valkeinen 			FB_WRITEL(comp(dat ^ pat, dat, last), dst);
274*19757fc8STomi Valkeinen 		}
275*19757fc8STomi Valkeinen 	}
276*19757fc8STomi Valkeinen }
277*19757fc8STomi Valkeinen 
278*19757fc8STomi Valkeinen void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
279*19757fc8STomi Valkeinen {
280*19757fc8STomi Valkeinen 	unsigned long pat, pat2, fg;
281*19757fc8STomi Valkeinen 	unsigned long width = rect->width, height = rect->height;
282*19757fc8STomi Valkeinen 	int bits = BITS_PER_LONG, bytes = bits >> 3;
283*19757fc8STomi Valkeinen 	u32 bpp = p->var.bits_per_pixel;
284*19757fc8STomi Valkeinen 	unsigned long __iomem *dst;
285*19757fc8STomi Valkeinen 	int dst_idx, left;
286*19757fc8STomi Valkeinen 
287*19757fc8STomi Valkeinen 	if (p->state != FBINFO_STATE_RUNNING)
288*19757fc8STomi Valkeinen 		return;
289*19757fc8STomi Valkeinen 
290*19757fc8STomi Valkeinen 	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
291*19757fc8STomi Valkeinen 	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
292*19757fc8STomi Valkeinen 		fg = ((u32 *) (p->pseudo_palette))[rect->color];
293*19757fc8STomi Valkeinen 	else
294*19757fc8STomi Valkeinen 		fg = rect->color;
295*19757fc8STomi Valkeinen 
296*19757fc8STomi Valkeinen 	pat = pixel_to_pat(bpp, fg);
297*19757fc8STomi Valkeinen 
298*19757fc8STomi Valkeinen 	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
299*19757fc8STomi Valkeinen 	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
300*19757fc8STomi Valkeinen 	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
301*19757fc8STomi Valkeinen 	/* FIXME For now we support 1-32 bpp only */
302*19757fc8STomi Valkeinen 	left = bits % bpp;
303*19757fc8STomi Valkeinen 	if (p->fbops->fb_sync)
304*19757fc8STomi Valkeinen 		p->fbops->fb_sync(p);
305*19757fc8STomi Valkeinen 	if (!left) {
306*19757fc8STomi Valkeinen 		u32 bswapmask = fb_compute_bswapmask(p);
307*19757fc8STomi Valkeinen 		void (*fill_op32)(struct fb_info *p,
308*19757fc8STomi Valkeinen 				  unsigned long __iomem *dst, int dst_idx,
309*19757fc8STomi Valkeinen 		                  unsigned long pat, unsigned n, int bits,
310*19757fc8STomi Valkeinen 				  u32 bswapmask) = NULL;
311*19757fc8STomi Valkeinen 
312*19757fc8STomi Valkeinen 		switch (rect->rop) {
313*19757fc8STomi Valkeinen 		case ROP_XOR:
314*19757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned_rev;
315*19757fc8STomi Valkeinen 			break;
316*19757fc8STomi Valkeinen 		case ROP_COPY:
317*19757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned;
318*19757fc8STomi Valkeinen 			break;
319*19757fc8STomi Valkeinen 		default:
320*19757fc8STomi Valkeinen 			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
321*19757fc8STomi Valkeinen 			fill_op32 = bitfill_aligned;
322*19757fc8STomi Valkeinen 			break;
323*19757fc8STomi Valkeinen 		}
324*19757fc8STomi Valkeinen 		while (height--) {
325*19757fc8STomi Valkeinen 			dst += dst_idx >> (ffs(bits) - 1);
326*19757fc8STomi Valkeinen 			dst_idx &= (bits - 1);
327*19757fc8STomi Valkeinen 			fill_op32(p, dst, dst_idx, pat, width*bpp, bits,
328*19757fc8STomi Valkeinen 				  bswapmask);
329*19757fc8STomi Valkeinen 			dst_idx += p->fix.line_length*8;
330*19757fc8STomi Valkeinen 		}
331*19757fc8STomi Valkeinen 	} else {
332*19757fc8STomi Valkeinen 		int right, r;
333*19757fc8STomi Valkeinen 		void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
334*19757fc8STomi Valkeinen 				int dst_idx, unsigned long pat, int left,
335*19757fc8STomi Valkeinen 				int right, unsigned n, int bits) = NULL;
336*19757fc8STomi Valkeinen #ifdef __LITTLE_ENDIAN
337*19757fc8STomi Valkeinen 		right = left;
338*19757fc8STomi Valkeinen 		left = bpp - right;
339*19757fc8STomi Valkeinen #else
340*19757fc8STomi Valkeinen 		right = bpp - left;
341*19757fc8STomi Valkeinen #endif
342*19757fc8STomi Valkeinen 		switch (rect->rop) {
343*19757fc8STomi Valkeinen 		case ROP_XOR:
344*19757fc8STomi Valkeinen 			fill_op = bitfill_unaligned_rev;
345*19757fc8STomi Valkeinen 			break;
346*19757fc8STomi Valkeinen 		case ROP_COPY:
347*19757fc8STomi Valkeinen 			fill_op = bitfill_unaligned;
348*19757fc8STomi Valkeinen 			break;
349*19757fc8STomi Valkeinen 		default:
350*19757fc8STomi Valkeinen 			printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
351*19757fc8STomi Valkeinen 			fill_op = bitfill_unaligned;
352*19757fc8STomi Valkeinen 			break;
353*19757fc8STomi Valkeinen 		}
354*19757fc8STomi Valkeinen 		while (height--) {
355*19757fc8STomi Valkeinen 			dst += dst_idx / bits;
356*19757fc8STomi Valkeinen 			dst_idx &= (bits - 1);
357*19757fc8STomi Valkeinen 			r = dst_idx % bpp;
358*19757fc8STomi Valkeinen 			/* rotate pattern to the correct start position */
359*19757fc8STomi Valkeinen 			pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
360*19757fc8STomi Valkeinen 			fill_op(p, dst, dst_idx, pat2, left, right,
361*19757fc8STomi Valkeinen 				width*bpp, bits);
362*19757fc8STomi Valkeinen 			dst_idx += p->fix.line_length*8;
363*19757fc8STomi Valkeinen 		}
364*19757fc8STomi Valkeinen 	}
365*19757fc8STomi Valkeinen }
366*19757fc8STomi Valkeinen 
367*19757fc8STomi Valkeinen EXPORT_SYMBOL(cfb_fillrect);
368*19757fc8STomi Valkeinen 
369*19757fc8STomi Valkeinen MODULE_AUTHOR("James Simmons <[email protected]>");
370*19757fc8STomi Valkeinen MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
371*19757fc8STomi Valkeinen MODULE_LICENSE("GPL");
372