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 * The code for depths like 24 that don't have integer number of pixels per
13 * long is broken and needs to be fixed. For now I turned these types of
16 * Also need to add code to deal with cards endians that are different than
17 * the native cpu endians. I also need to deal with MSB position in the word.
20 #include <linux/module.h>
21 #include <linux/string.h>
23 #include <asm/types.h>
26 #if BITS_PER_LONG == 32
27 # define FB_WRITEL fb_writel
28 # define FB_READL fb_readl
30 # define FB_WRITEL fb_writeq
31 # define FB_READL fb_readq
35 * Aligned pattern fill using 32/64-bit memory accesses
39 bitfill_aligned(struct fb_info
*p
, unsigned long __iomem
*dst
, int dst_idx
,
40 unsigned long pat
, unsigned n
, int bits
, u32 bswapmask
)
42 unsigned long first
, last
;
47 first
= fb_shifted_pixels_mask_long(p
, dst_idx
, bswapmask
);
48 last
= ~fb_shifted_pixels_mask_long(p
, (dst_idx
+n
) % bits
, bswapmask
);
50 if (dst_idx
+n
<= bits
) {
54 FB_WRITEL(comp(pat
, FB_READL(dst
), first
), dst
);
56 // Multiple destination words
60 FB_WRITEL(comp(pat
, FB_READL(dst
), first
), dst
);
68 FB_WRITEL(pat
, dst
++);
69 FB_WRITEL(pat
, dst
++);
70 FB_WRITEL(pat
, dst
++);
71 FB_WRITEL(pat
, dst
++);
72 FB_WRITEL(pat
, dst
++);
73 FB_WRITEL(pat
, dst
++);
74 FB_WRITEL(pat
, dst
++);
75 FB_WRITEL(pat
, dst
++);
79 FB_WRITEL(pat
, dst
++);
83 FB_WRITEL(comp(pat
, FB_READL(dst
), last
), dst
);
89 * Unaligned generic pattern fill using 32/64-bit memory accesses
90 * The pattern must have been expanded to a full 32/64-bit value
91 * Left/right are the appropriate shifts to convert to the pattern to be
92 * used for the next 32/64-bit word
96 bitfill_unaligned(struct fb_info
*p
, unsigned long __iomem
*dst
, int dst_idx
,
97 unsigned long pat
, int left
, int right
, unsigned n
, int bits
)
99 unsigned long first
, last
;
104 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
105 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
107 if (dst_idx
+n
<= bits
) {
111 FB_WRITEL(comp(pat
, FB_READL(dst
), first
), dst
);
113 // Multiple destination words
116 FB_WRITEL(comp(pat
, FB_READL(dst
), first
), dst
);
118 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
;
129 FB_WRITEL(pat
, dst
++);
130 pat
= pat
<< left
| pat
>> right
;
131 FB_WRITEL(pat
, dst
++);
132 pat
= pat
<< left
| pat
>> right
;
136 FB_WRITEL(pat
, dst
++);
137 pat
= pat
<< left
| pat
>> right
;
142 FB_WRITEL(comp(pat
, FB_READL(dst
), first
), dst
);
147 * Aligned pattern invert using 32/64-bit memory accesses
150 bitfill_aligned_rev(struct fb_info
*p
, unsigned long __iomem
*dst
,
151 int dst_idx
, unsigned long pat
, unsigned n
, int bits
,
154 unsigned long val
= pat
, dat
;
155 unsigned long first
, last
;
160 first
= fb_shifted_pixels_mask_long(p
, dst_idx
, bswapmask
);
161 last
= ~fb_shifted_pixels_mask_long(p
, (dst_idx
+n
) % bits
, bswapmask
);
163 if (dst_idx
+n
<= bits
) {
168 FB_WRITEL(comp(dat
^ val
, dat
, first
), dst
);
170 // Multiple destination words
174 FB_WRITEL(comp(dat
^ val
, dat
, first
), 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
);
194 FB_WRITEL(FB_READL(dst
) ^ val
, dst
);
196 FB_WRITEL(FB_READL(dst
) ^ val
, dst
);
201 FB_WRITEL(FB_READL(dst
) ^ val
, dst
);
207 FB_WRITEL(comp(dat
^ val
, dat
, last
), dst
);
214 * Unaligned generic pattern invert using 32/64-bit memory accesses
215 * The pattern must have been expanded to a full 32/64-bit value
216 * Left/right are the appropriate shifts to convert to the pattern to be
217 * used for the next 32/64-bit word
221 bitfill_unaligned_rev(struct fb_info
*p
, unsigned long __iomem
*dst
,
222 int dst_idx
, unsigned long pat
, int left
, int right
,
223 unsigned n
, int bits
)
225 unsigned long first
, last
, dat
;
230 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
231 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
233 if (dst_idx
+n
<= bits
) {
238 FB_WRITEL(comp(dat
^ pat
, dat
, first
), dst
);
240 // Multiple destination words
245 FB_WRITEL(comp(dat
^ pat
, dat
, first
), dst
);
247 pat
= pat
<< left
| pat
>> right
;
254 FB_WRITEL(FB_READL(dst
) ^ pat
, dst
);
256 pat
= pat
<< left
| pat
>> right
;
257 FB_WRITEL(FB_READL(dst
) ^ pat
, dst
);
259 pat
= pat
<< left
| pat
>> right
;
260 FB_WRITEL(FB_READL(dst
) ^ pat
, dst
);
262 pat
= pat
<< left
| pat
>> right
;
263 FB_WRITEL(FB_READL(dst
) ^ pat
, dst
);
265 pat
= pat
<< left
| pat
>> right
;
269 FB_WRITEL(FB_READL(dst
) ^ pat
, dst
);
271 pat
= pat
<< left
| pat
>> right
;
277 FB_WRITEL(comp(dat
^ pat
, dat
, last
), dst
);
282 void cfb_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
284 unsigned long pat
, fg
;
285 unsigned long width
= rect
->width
, height
= rect
->height
;
286 int bits
= BITS_PER_LONG
, bytes
= bits
>> 3;
287 u32 bpp
= p
->var
.bits_per_pixel
;
288 unsigned long __iomem
*dst
;
291 if (p
->state
!= FBINFO_STATE_RUNNING
)
294 if (p
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
295 p
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
296 fg
= ((u32
*) (p
->pseudo_palette
))[rect
->color
];
300 pat
= pixel_to_pat( bpp
, fg
);
302 dst
= (unsigned long __iomem
*)((unsigned long)p
->screen_base
& ~(bytes
-1));
303 dst_idx
= ((unsigned long)p
->screen_base
& (bytes
- 1))*8;
304 dst_idx
+= rect
->dy
*p
->fix
.line_length
*8+rect
->dx
*bpp
;
305 /* FIXME For now we support 1-32 bpp only */
307 if (p
->fbops
->fb_sync
)
308 p
->fbops
->fb_sync(p
);
310 u32 bswapmask
= fb_compute_bswapmask(p
);
311 void (*fill_op32
)(struct fb_info
*p
,
312 unsigned long __iomem
*dst
, int dst_idx
,
313 unsigned long pat
, unsigned n
, int bits
,
314 u32 bswapmask
) = NULL
;
318 fill_op32
= bitfill_aligned_rev
;
321 fill_op32
= bitfill_aligned
;
324 printk( KERN_ERR
"cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
325 fill_op32
= bitfill_aligned
;
329 dst
+= dst_idx
>> (ffs(bits
) - 1);
330 dst_idx
&= (bits
- 1);
331 fill_op32(p
, dst
, dst_idx
, pat
, width
*bpp
, bits
,
333 dst_idx
+= p
->fix
.line_length
*8;
338 int rot
= (left
-dst_idx
) % bpp
;
339 void (*fill_op
)(struct fb_info
*p
, unsigned long __iomem
*dst
,
340 int dst_idx
, unsigned long pat
, int left
,
341 int right
, unsigned n
, int bits
) = NULL
;
343 /* rotate pattern to correct start position */
344 pat
= pat
<< rot
| pat
>> (bpp
-rot
);
349 fill_op
= bitfill_unaligned_rev
;
352 fill_op
= bitfill_unaligned
;
355 printk( KERN_ERR
"cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
356 fill_op
= bitfill_unaligned
;
360 dst
+= dst_idx
>> (ffs(bits
) - 1);
361 dst_idx
&= (bits
- 1);
362 fill_op(p
, dst
, dst_idx
, pat
, left
, right
,
364 r
= (p
->fix
.line_length
*8) % bpp
;
365 pat
= pat
<< (bpp
-r
) | pat
>> r
;
366 dst_idx
+= p
->fix
.line_length
*8;
371 EXPORT_SYMBOL(cfb_fillrect
);
373 MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
374 MODULE_DESCRIPTION("Generic software accelerated fill rectangle");
375 MODULE_LICENSE("GPL");