2 * Generic fillrect for frame buffers in system RAM with packed pixels of
5 * Based almost entirely from cfbfillrect.c (which is based almost entirely
6 * on Geert Uytterhoeven's fillrect routine)
8 * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net>
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for
14 #include <linux/module.h>
15 #include <linux/string.h>
17 #include <asm/types.h>
21 * Aligned pattern fill using 32/64-bit memory accesses
25 bitfill_aligned(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
26 unsigned long pat
, unsigned n
, int bits
)
28 unsigned long first
, last
;
33 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
34 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
36 if (dst_idx
+n
<= bits
) {
40 *dst
= comp(pat
, *dst
, first
);
42 /* Multiple destination words */
46 *dst
= comp(pat
, *dst
, first
);
53 memset_l(dst
, pat
, n
);
58 *dst
= comp(pat
, *dst
, last
);
64 * Unaligned generic pattern fill using 32/64-bit memory accesses
65 * The pattern must have been expanded to a full 32/64-bit value
66 * Left/right are the appropriate shifts to convert to the pattern to be
67 * used for the next 32/64-bit word
71 bitfill_unaligned(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
72 unsigned long pat
, int left
, int right
, unsigned n
, int bits
)
74 unsigned long first
, last
;
79 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
80 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
82 if (dst_idx
+n
<= bits
) {
86 *dst
= comp(pat
, *dst
, first
);
88 /* Multiple destination words */
91 *dst
= comp(pat
, *dst
, first
);
93 pat
= pat
<< left
| pat
>> right
;
101 pat
= pat
<< left
| pat
>> right
;
103 pat
= pat
<< left
| pat
>> right
;
105 pat
= pat
<< left
| pat
>> right
;
107 pat
= pat
<< left
| pat
>> right
;
112 pat
= pat
<< left
| pat
>> right
;
117 *dst
= comp(pat
, *dst
, last
);
122 * Aligned pattern invert using 32/64-bit memory accesses
125 bitfill_aligned_rev(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
126 unsigned long pat
, unsigned n
, int bits
)
128 unsigned long val
= pat
;
129 unsigned long first
, last
;
134 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
135 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
137 if (dst_idx
+n
<= bits
) {
141 *dst
= comp(*dst
^ val
, *dst
, first
);
143 /* Multiple destination words */
146 *dst
= comp(*dst
^ val
, *dst
, first
);
168 *dst
= comp(*dst
^ val
, *dst
, last
);
174 * Unaligned generic pattern invert using 32/64-bit memory accesses
175 * The pattern must have been expanded to a full 32/64-bit value
176 * Left/right are the appropriate shifts to convert to the pattern to be
177 * used for the next 32/64-bit word
181 bitfill_unaligned_rev(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
182 unsigned long pat
, int left
, int right
, unsigned n
,
185 unsigned long first
, last
;
190 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
191 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
193 if (dst_idx
+n
<= bits
) {
197 *dst
= comp(*dst
^ pat
, *dst
, first
);
199 /* Multiple destination words */
203 *dst
= comp(*dst
^ pat
, *dst
, first
);
205 pat
= pat
<< left
| pat
>> right
;
213 pat
= pat
<< left
| pat
>> right
;
215 pat
= pat
<< left
| pat
>> right
;
217 pat
= pat
<< left
| pat
>> right
;
219 pat
= pat
<< left
| pat
>> right
;
224 pat
= pat
<< left
| pat
>> right
;
229 *dst
= comp(*dst
^ pat
, *dst
, last
);
233 void sys_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
235 unsigned long pat
, pat2
, fg
;
236 unsigned long width
= rect
->width
, height
= rect
->height
;
237 int bits
= BITS_PER_LONG
, bytes
= bits
>> 3;
238 u32 bpp
= p
->var
.bits_per_pixel
;
242 if (p
->state
!= FBINFO_STATE_RUNNING
)
245 if (!(p
->flags
& FBINFO_VIRTFB
))
246 fb_warn_once(p
, "Framebuffer is not in virtual address space.");
248 if (p
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
249 p
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
250 fg
= ((u32
*) (p
->pseudo_palette
))[rect
->color
];
254 pat
= pixel_to_pat( bpp
, fg
);
256 dst
= (unsigned long *)((unsigned long)p
->screen_base
& ~(bytes
-1));
257 dst_idx
= ((unsigned long)p
->screen_base
& (bytes
- 1))*8;
258 dst_idx
+= rect
->dy
*p
->fix
.line_length
*8+rect
->dx
*bpp
;
259 /* FIXME For now we support 1-32 bpp only */
261 if (p
->fbops
->fb_sync
)
262 p
->fbops
->fb_sync(p
);
264 void (*fill_op32
)(struct fb_info
*p
, unsigned long *dst
,
265 int dst_idx
, unsigned long pat
, unsigned n
,
270 fill_op32
= bitfill_aligned_rev
;
273 fill_op32
= bitfill_aligned
;
276 printk( KERN_ERR
"cfb_fillrect(): unknown rop, "
277 "defaulting to ROP_COPY\n");
278 fill_op32
= bitfill_aligned
;
282 dst
+= dst_idx
>> (ffs(bits
) - 1);
283 dst_idx
&= (bits
- 1);
284 fill_op32(p
, dst
, dst_idx
, pat
, width
*bpp
, bits
);
285 dst_idx
+= p
->fix
.line_length
*8;
289 void (*fill_op
)(struct fb_info
*p
, unsigned long *dst
,
290 int dst_idx
, unsigned long pat
, int left
,
291 int right
, unsigned n
, int bits
) = NULL
;
292 #ifdef __LITTLE_ENDIAN
300 fill_op
= bitfill_unaligned_rev
;
303 fill_op
= bitfill_unaligned
;
306 printk(KERN_ERR
"sys_fillrect(): unknown rop, "
307 "defaulting to ROP_COPY\n");
308 fill_op
= bitfill_unaligned
;
312 dst
+= dst_idx
/ bits
;
313 dst_idx
&= (bits
- 1);
315 /* rotate pattern to the correct start position */
316 pat2
= le_long_to_cpu(rolx(cpu_to_le_long(pat
), r
, bpp
));
317 fill_op(p
, dst
, dst_idx
, pat2
, left
, right
,
319 dst_idx
+= p
->fix
.line_length
*8;
324 EXPORT_SYMBOL(sys_fillrect
);
326 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
327 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
328 MODULE_LICENSE("GPL");