Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  Generic fillrect for frame buffers in system RAM with packed pixels of
  3  *  any depth.
  4  *
  5  *  Based almost entirely from cfbfillrect.c (which is based almost entirely
  6  *  on Geert Uytterhoeven's fillrect routine)
  7  *
  8  *      Copyright (C)  2007 Antonino Daplas <adaplas@pol.net>
  9  *
 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
 12  *  more details.
 13  */
 14 #include <linux/module.h>
 15 #include <linux/string.h>
 16 #include <linux/fb.h>
 17 #include <asm/types.h>
 18 #include "fb_draw.h"
 19 
 20     /*
 21      *  Aligned pattern fill using 32/64-bit memory accesses
 22      */
 23 
 24 static void
 25 bitfill_aligned(unsigned long *dst, int dst_idx, unsigned long pat,
 26                 unsigned n, int bits)
 27 {
 28         unsigned long first, last;
 29 
 30         if (!n)
 31                 return;
 32 
 33         first = FB_SHIFT_HIGH(~0UL, dst_idx);
 34         last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 35 
 36         if (dst_idx+n <= bits) {
 37                 /* Single word */
 38                 if (last)
 39                         first &= last;
 40                 *dst = comp(pat, *dst, first);
 41         } else {
 42                 /* Multiple destination words */
 43 
 44                 /* Leading bits */
 45                 if (first!= ~0UL) {
 46                         *dst = comp(pat, *dst, first);
 47                         dst++;
 48                         n -= bits - dst_idx;
 49                 }
 50 
 51                 /* Main chunk */
 52                 n /= bits;
 53                 while (n >= 8) {
 54                         *dst++ = pat;
 55                         *dst++ = pat;
 56                         *dst++ = pat;
 57                         *dst++ = pat;
 58                         *dst++ = pat;
 59                         *dst++ = pat;
 60                         *dst++ = pat;
 61                         *dst++ = pat;
 62                         n -= 8;
 63                 }
 64                 while (n--)
 65                         *dst++ = pat;
 66                 /* Trailing bits */
 67                 if (last)
 68                         *dst = comp(pat, *dst, last);
 69         }
 70 }
 71 
 72 
 73     /*
 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
 78      */
 79 
 80 static void
 81 bitfill_unaligned(unsigned long *dst, int dst_idx, unsigned long pat,
 82                   int left, int right, unsigned n, int bits)
 83 {
 84         unsigned long first, last;
 85 
 86         if (!n)
 87                 return;
 88 
 89         first = FB_SHIFT_HIGH(~0UL, dst_idx);
 90         last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 91 
 92         if (dst_idx+n <= bits) {
 93                 /* Single word */
 94                 if (last)
 95                         first &= last;
 96                 *dst = comp(pat, *dst, first);
 97         } else {
 98                 /* Multiple destination words */
 99                 /* Leading bits */
100                 if (first) {
101                         *dst = comp(pat, *dst, first);
102                         dst++;
103                         pat = pat << left | pat >> right;
104                         n -= bits - dst_idx;
105                 }
106 
107                 /* Main chunk */
108                 n /= bits;
109                 while (n >= 4) {
110                         *dst++ = pat;
111                         pat = pat << left | pat >> right;
112                         *dst++ = pat;
113                         pat = pat << left | pat >> right;
114                         *dst++ = pat;
115                         pat = pat << left | pat >> right;
116                         *dst++ = pat;
117                         pat = pat << left | pat >> right;
118                         n -= 4;
119                 }
120                 while (n--) {
121                         *dst++ = pat;
122                         pat = pat << left | pat >> right;
123                 }
124 
125                 /* Trailing bits */
126                 if (last)
127                         *dst = comp(pat, *dst, first);
128         }
129 }
130 
131     /*
132      *  Aligned pattern invert using 32/64-bit memory accesses
133      */
134 static void
135 bitfill_aligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
136                     unsigned n, int bits)
137 {
138         unsigned long val = pat;
139         unsigned long first, last;
140 
141         if (!n)
142                 return;
143 
144         first = FB_SHIFT_HIGH(~0UL, dst_idx);
145         last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
146 
147         if (dst_idx+n <= bits) {
148                 /* Single word */
149                 if (last)
150                         first &= last;
151                 *dst = comp(*dst ^ val, *dst, first);
152         } else {
153                 /* Multiple destination words */
154                 /* Leading bits */
155                 if (first!=0UL) {
156                         *dst = comp(*dst ^ val, *dst, first);
157                         dst++;
158                         n -= bits - dst_idx;
159                 }
160 
161                 /* Main chunk */
162                 n /= bits;
163                 while (n >= 8) {
164                         *dst++ ^= val;
165                         *dst++ ^= val;
166                         *dst++ ^= val;
167                         *dst++ ^= val;
168                         *dst++ ^= val;
169                         *dst++ ^= val;
170                         *dst++ ^= val;
171                         *dst++ ^= val;
172                         n -= 8;
173                 }
174                 while (n--)
175                         *dst++ ^= val;
176                 /* Trailing bits */
177                 if (last)
178                         *dst = comp(*dst ^ val, *dst, last);
179         }
180 }
181 
182 
183     /*
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
188      */
189 
190 static void
191 bitfill_unaligned_rev(unsigned long *dst, int dst_idx, unsigned long pat,
192                         int left, int right, unsigned n, int bits)
193 {
194         unsigned long first, last;
195 
196         if (!n)
197                 return;
198 
199         first = FB_SHIFT_HIGH(~0UL, dst_idx);
200         last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
201 
202         if (dst_idx+n <= bits) {
203                 /* Single word */
204                 if (last)
205                         first &= last;
206                 *dst = comp(*dst ^ pat, *dst, first);
207         } else {
208                 /* Multiple destination words */
209 
210                 /* Leading bits */
211                 if (first != 0UL) {
212                         *dst = comp(*dst ^ pat, *dst, first);
213                         dst++;
214                         pat = pat << left | pat >> right;
215                         n -= bits - dst_idx;
216                 }
217 
218                 /* Main chunk */
219                 n /= bits;
220                 while (n >= 4) {
221                         *dst++ ^= pat;
222                         pat = pat << left | pat >> right;
223                         *dst++ ^= pat;
224                         pat = pat << left | pat >> right;
225                         *dst++ ^= pat;
226                         pat = pat << left | pat >> right;
227                         *dst++ ^= pat;
228                         pat = pat << left | pat >> right;
229                         n -= 4;
230                 }
231                 while (n--) {
232                         *dst ^= pat;
233                         pat = pat << left | pat >> right;
234                 }
235 
236                 /* Trailing bits */
237                 if (last)
238                         *dst = comp(*dst ^ pat, *dst, last);
239         }
240 }
241 
242 void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
243 {
244         unsigned long pat, fg;
245         unsigned long width = rect->width, height = rect->height;
246         int bits = BITS_PER_LONG, bytes = bits >> 3;
247         u32 bpp = p->var.bits_per_pixel;
248         unsigned long *dst;
249         int dst_idx, left;
250 
251         if (p->state != FBINFO_STATE_RUNNING)
252                 return;
253 
254         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
255             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
256                 fg = ((u32 *) (p->pseudo_palette))[rect->color];
257         else
258                 fg = rect->color;
259 
260         pat = pixel_to_pat( bpp, fg);
261 
262         dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1));
263         dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
264         dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
265         /* FIXME For now we support 1-32 bpp only */
266         left = bits % bpp;
267         if (p->fbops->fb_sync)
268                 p->fbops->fb_sync(p);
269         if (!left) {
270                 void (*fill_op32)(unsigned long *dst, int dst_idx,
271                                   unsigned long pat, unsigned n, int bits) =
272                         NULL;
273 
274                 switch (rect->rop) {
275                 case ROP_XOR:
276                         fill_op32 = bitfill_aligned_rev;
277                         break;
278                 case ROP_COPY:
279                         fill_op32 = bitfill_aligned;
280                         break;
281                 default:
282                         printk( KERN_ERR "cfb_fillrect(): unknown rop, "
283                                 "defaulting to ROP_COPY\n");
284                         fill_op32 = bitfill_aligned;
285                         break;
286                 }
287                 while (height--) {
288                         dst += dst_idx >> (ffs(bits) - 1);
289                         dst_idx &= (bits - 1);
290                         fill_op32(dst, dst_idx, pat, width*bpp, bits);
291                         dst_idx += p->fix.line_length*8;
292                 }
293         } else {
294                 int right;
295                 int r;
296                 int rot = (left-dst_idx) % bpp;
297                 void (*fill_op)(unsigned long *dst, int dst_idx,
298                                 unsigned long pat, int left, int right,
299                                 unsigned n, int bits) = NULL;
300 
301                 /* rotate pattern to correct start position */
302                 pat = pat << rot | pat >> (bpp-rot);
303 
304                 right = bpp-left;
305                 switch (rect->rop) {
306                 case ROP_XOR:
307                         fill_op = bitfill_unaligned_rev;
308                         break;
309                 case ROP_COPY:
310                         fill_op = bitfill_unaligned;
311                         break;
312                 default:
313                         printk(KERN_ERR "cfb_fillrect(): unknown rop, "
314                                 "defaulting to ROP_COPY\n");
315                         fill_op = bitfill_unaligned;
316                         break;
317                 }
318                 while (height--) {
319                         dst += dst_idx >> (ffs(bits) - 1);
320                         dst_idx &= (bits - 1);
321                         fill_op(dst, dst_idx, pat, left, right,
322                                 width*bpp, bits);
323                         r = (p->fix.line_length*8) % bpp;
324                         pat = pat << (bpp-r) | pat >> r;
325                         dst_idx += p->fix.line_length*8;
326                 }
327         }
328 }
329 
330 EXPORT_SYMBOL(sys_fillrect);
331 
332 MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
333 MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)");
334 MODULE_LICENSE("GPL");
335 
  This page was automatically generated by the LXR engine.