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
);
68 *dst
= comp(pat
, *dst
, last
);
74 * Unaligned generic pattern fill using 32/64-bit memory accesses
75 * The pattern must have been expanded to a full 32/64-bit value
76 * Left/right are the appropriate shifts to convert to the pattern to be
77 * used for the next 32/64-bit word
81 bitfill_unaligned(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
82 unsigned long pat
, int left
, int right
, unsigned n
, int bits
)
84 unsigned long first
, last
;
89 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
90 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
92 if (dst_idx
+n
<= bits
) {
96 *dst
= comp(pat
, *dst
, first
);
98 /* Multiple destination words */
101 *dst
= comp(pat
, *dst
, first
);
103 pat
= pat
<< left
| pat
>> right
;
111 pat
= pat
<< left
| pat
>> right
;
113 pat
= pat
<< left
| pat
>> right
;
115 pat
= pat
<< left
| pat
>> right
;
117 pat
= pat
<< left
| pat
>> right
;
122 pat
= pat
<< left
| pat
>> right
;
127 *dst
= comp(pat
, *dst
, last
);
132 * Aligned pattern invert using 32/64-bit memory accesses
135 bitfill_aligned_rev(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
136 unsigned long pat
, unsigned n
, int bits
)
138 unsigned long val
= pat
;
139 unsigned long first
, last
;
144 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
145 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
147 if (dst_idx
+n
<= bits
) {
151 *dst
= comp(*dst
^ val
, *dst
, first
);
153 /* Multiple destination words */
156 *dst
= comp(*dst
^ val
, *dst
, first
);
178 *dst
= comp(*dst
^ val
, *dst
, last
);
184 * Unaligned generic pattern invert using 32/64-bit memory accesses
185 * The pattern must have been expanded to a full 32/64-bit value
186 * Left/right are the appropriate shifts to convert to the pattern to be
187 * used for the next 32/64-bit word
191 bitfill_unaligned_rev(struct fb_info
*p
, unsigned long *dst
, int dst_idx
,
192 unsigned long pat
, int left
, int right
, unsigned n
,
195 unsigned long first
, last
;
200 first
= FB_SHIFT_HIGH(p
, ~0UL, dst_idx
);
201 last
= ~(FB_SHIFT_HIGH(p
, ~0UL, (dst_idx
+n
) % bits
));
203 if (dst_idx
+n
<= bits
) {
207 *dst
= comp(*dst
^ pat
, *dst
, first
);
209 /* Multiple destination words */
213 *dst
= comp(*dst
^ pat
, *dst
, first
);
215 pat
= pat
<< left
| pat
>> right
;
223 pat
= pat
<< left
| pat
>> right
;
225 pat
= pat
<< left
| pat
>> right
;
227 pat
= pat
<< left
| pat
>> right
;
229 pat
= pat
<< left
| pat
>> right
;
234 pat
= pat
<< left
| pat
>> right
;
239 *dst
= comp(*dst
^ pat
, *dst
, last
);
243 void sys_fillrect(struct fb_info
*p
, const struct fb_fillrect
*rect
)
245 unsigned long pat
, pat2
, fg
;
246 unsigned long width
= rect
->width
, height
= rect
->height
;
247 int bits
= BITS_PER_LONG
, bytes
= bits
>> 3;
248 u32 bpp
= p
->var
.bits_per_pixel
;
252 if (p
->state
!= FBINFO_STATE_RUNNING
)
255 if (p
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
256 p
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
257 fg
= ((u32
*) (p
->pseudo_palette
))[rect
->color
];
261 pat
= pixel_to_pat( bpp
, fg
);
263 dst
= (unsigned long *)((unsigned long)p
->screen_base
& ~(bytes
-1));
264 dst_idx
= ((unsigned long)p
->screen_base
& (bytes
- 1))*8;
265 dst_idx
+= rect
->dy
*p
->fix
.line_length
*8+rect
->dx
*bpp
;
267 if (p
->fbops
->fb_sync
)
268 p
->fbops
->fb_sync(p
);
270 void (*fill_op32
)(struct fb_info
*p
, unsigned long *dst
,
271 int dst_idx
, unsigned long pat
, unsigned n
,
276 fill_op32
= bitfill_aligned_rev
;
279 fill_op32
= bitfill_aligned
;
282 printk( KERN_ERR
"cfb_fillrect(): unknown rop, "
283 "defaulting to ROP_COPY\n");
284 fill_op32
= bitfill_aligned
;
288 dst
+= dst_idx
>> (ffs(bits
) - 1);
289 dst_idx
&= (bits
- 1);
290 fill_op32(p
, dst
, dst_idx
, pat
, width
*bpp
, bits
);
291 dst_idx
+= p
->fix
.line_length
*8;
295 void (*fill_op
)(struct fb_info
*p
, unsigned long *dst
,
296 int dst_idx
, unsigned long pat
, int left
,
297 int right
, unsigned n
, int bits
) = NULL
;
298 #ifdef __LITTLE_ENDIAN
306 fill_op
= bitfill_unaligned_rev
;
309 fill_op
= bitfill_unaligned
;
312 printk(KERN_ERR
"sys_fillrect(): unknown rop, "
313 "defaulting to ROP_COPY\n");
314 fill_op
= bitfill_unaligned
;
318 dst
+= dst_idx
/ bits
;
319 dst_idx
&= (bits
- 1);
321 /* rotate pattern to the correct start position */
322 pat2
= le_long_to_cpu(rolx(cpu_to_le_long(pat
), r
, bpp
));
323 fill_op(p
, dst
, dst_idx
, pat2
, left
, right
,
325 dst_idx
+= p
->fix
.line_length
*8;
330 EXPORT_SYMBOL(sys_fillrect
);
332 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
333 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
334 MODULE_LICENSE("GPL");