OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [video/] [syscopyarea.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  Generic Bit Block Transfer for frame buffers located in system RAM with
3
 *  packed pixels of any depth.
4
 *
5
 *  Based almost entirely from cfbcopyarea.c (which is based almost entirely
6
 *  on Geert Uytterhoeven's copyarea 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
 */
15
#include <linux/module.h>
16
#include <linux/kernel.h>
17
#include <linux/string.h>
18
#include <linux/fb.h>
19
#include <linux/slab.h>
20
#include <asm/types.h>
21
#include <asm/io.h>
22
#include "fb_draw.h"
23
 
24
    /*
25
     *  Generic bitwise copy algorithm
26
     */
27
 
28
static void
29
bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
30
        int src_idx, int bits, unsigned n)
31
{
32
        unsigned long first, last;
33
        int const shift = dst_idx-src_idx;
34
        int left, right;
35
 
36
        first = FB_SHIFT_HIGH(~0UL, dst_idx);
37
        last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
38
 
39
        if (!shift) {
40
                /* Same alignment for source and dest */
41
                if (dst_idx+n <= bits) {
42
                        /* Single word */
43
                        if (last)
44
                                first &= last;
45
                        *dst = comp(*src, *dst, first);
46
                } else {
47
                        /* Multiple destination words */
48
                        /* Leading bits */
49
                        if (first != ~0UL) {
50
                                *dst = comp(*src, *dst, first);
51
                                dst++;
52
                                src++;
53
                                n -= bits - dst_idx;
54
                        }
55
 
56
                        /* Main chunk */
57
                        n /= bits;
58
                        while (n >= 8) {
59
                                *dst++ = *src++;
60
                                *dst++ = *src++;
61
                                *dst++ = *src++;
62
                                *dst++ = *src++;
63
                                *dst++ = *src++;
64
                                *dst++ = *src++;
65
                                *dst++ = *src++;
66
                                *dst++ = *src++;
67
                                n -= 8;
68
                        }
69
                        while (n--)
70
                                *dst++ = *src++;
71
 
72
                        /* Trailing bits */
73
                        if (last)
74
                                *dst = comp(*src, *dst, last);
75
                }
76
        } else {
77
                unsigned long d0, d1;
78
                int m;
79
 
80
                /* Different alignment for source and dest */
81
                right = shift & (bits - 1);
82
                left = -shift & (bits - 1);
83
 
84
                if (dst_idx+n <= bits) {
85
                        /* Single destination word */
86
                        if (last)
87
                                first &= last;
88
                        if (shift > 0) {
89
                                /* Single source word */
90
                                *dst = comp(*src >> right, *dst, first);
91
                        } else if (src_idx+n <= bits) {
92
                                /* Single source word */
93
                                *dst = comp(*src << left, *dst, first);
94
                        } else {
95
                                /* 2 source words */
96
                                d0 = *src++;
97
                                d1 = *src;
98
                                *dst = comp(d0 << left | d1 >> right, *dst,
99
                                            first);
100
                        }
101
                } else {
102
                        /* Multiple destination words */
103
                        /** We must always remember the last value read,
104
                            because in case SRC and DST overlap bitwise (e.g.
105
                            when moving just one pixel in 1bpp), we always
106
                            collect one full long for DST and that might
107
                            overlap with the current long from SRC. We store
108
                            this value in 'd0'. */
109
                        d0 = *src++;
110
                        /* Leading bits */
111
                        if (shift > 0) {
112
                                /* Single source word */
113
                                *dst = comp(d0 >> right, *dst, first);
114
                                dst++;
115
                                n -= bits - dst_idx;
116
                        } else {
117
                                /* 2 source words */
118
                                d1 = *src++;
119
                                *dst = comp(d0 << left | *dst >> right, *dst, first);
120
                                d0 = d1;
121
                                dst++;
122
                                n -= bits - dst_idx;
123
                        }
124
 
125
                        /* Main chunk */
126
                        m = n % bits;
127
                        n /= bits;
128
                        while (n >= 4) {
129
                                d1 = *src++;
130
                                *dst++ = d0 << left | d1 >> right;
131
                                d0 = d1;
132
                                d1 = *src++;
133
                                *dst++ = d0 << left | d1 >> right;
134
                                d0 = d1;
135
                                d1 = *src++;
136
                                *dst++ = d0 << left | d1 >> right;
137
                                d0 = d1;
138
                                d1 = *src++;
139
                                *dst++ = d0 << left | d1 >> right;
140
                                d0 = d1;
141
                                n -= 4;
142
                        }
143
                        while (n--) {
144
                                d1 = *src++;
145
                                *dst++ = d0 << left | d1 >> right;
146
                                d0 = d1;
147
                        }
148
 
149
                        /* Trailing bits */
150
                        if (last) {
151
                                if (m <= right) {
152
                                        /* Single source word */
153
                                        *dst = comp(d0 << left, *dst, last);
154
                                } else {
155
                                        /* 2 source words */
156
                                        d1 = *src;
157
                                        *dst = comp(d0 << left | d1 >> right,
158
                                                    *dst, last);
159
                                }
160
                        }
161
                }
162
        }
163
}
164
 
165
    /*
166
     *  Generic bitwise copy algorithm, operating backward
167
     */
168
 
169
static void
170
bitcpy_rev(unsigned long *dst, int dst_idx, const unsigned long *src,
171
           int src_idx, int bits, unsigned n)
172
{
173
        unsigned long first, last;
174
        int shift;
175
 
176
        dst += (n-1)/bits;
177
        src += (n-1)/bits;
178
        if ((n-1) % bits) {
179
                dst_idx += (n-1) % bits;
180
                dst += dst_idx >> (ffs(bits) - 1);
181
                dst_idx &= bits - 1;
182
                src_idx += (n-1) % bits;
183
                src += src_idx >> (ffs(bits) - 1);
184
                src_idx &= bits - 1;
185
        }
186
 
187
        shift = dst_idx-src_idx;
188
 
189
        first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
190
        last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
191
 
192
        if (!shift) {
193
                /* Same alignment for source and dest */
194
                if ((unsigned long)dst_idx+1 >= n) {
195
                        /* Single word */
196
                        if (last)
197
                                first &= last;
198
                        *dst = comp(*src, *dst, first);
199
                } else {
200
                        /* Multiple destination words */
201
 
202
                        /* Leading bits */
203
                        if (first != ~0UL) {
204
                                *dst = comp(*src, *dst, first);
205
                                dst--;
206
                                src--;
207
                                n -= dst_idx+1;
208
                        }
209
 
210
                        /* Main chunk */
211
                        n /= bits;
212
                        while (n >= 8) {
213
                                *dst-- = *src--;
214
                                *dst-- = *src--;
215
                                *dst-- = *src--;
216
                                *dst-- = *src--;
217
                                *dst-- = *src--;
218
                                *dst-- = *src--;
219
                                *dst-- = *src--;
220
                                *dst-- = *src--;
221
                                n -= 8;
222
                        }
223
                        while (n--)
224
                                *dst-- = *src--;
225
                        /* Trailing bits */
226
                        if (last)
227
                                *dst = comp(*src, *dst, last);
228
                }
229
        } else {
230
                /* Different alignment for source and dest */
231
 
232
                int const left = -shift & (bits-1);
233
                int const right = shift & (bits-1);
234
 
235
                if ((unsigned long)dst_idx+1 >= n) {
236
                        /* Single destination word */
237
                        if (last)
238
                                first &= last;
239
                        if (shift < 0) {
240
                                /* Single source word */
241
                                *dst = comp(*src << left, *dst, first);
242
                        } else if (1+(unsigned long)src_idx >= n) {
243
                                /* Single source word */
244
                                *dst = comp(*src >> right, *dst, first);
245
                        } else {
246
                                /* 2 source words */
247
                                *dst = comp(*src >> right | *(src-1) << left,
248
                                            *dst, first);
249
                        }
250
                } else {
251
                        /* Multiple destination words */
252
                        /** We must always remember the last value read,
253
                            because in case SRC and DST overlap bitwise (e.g.
254
                            when moving just one pixel in 1bpp), we always
255
                            collect one full long for DST and that might
256
                            overlap with the current long from SRC. We store
257
                            this value in 'd0'. */
258
                        unsigned long d0, d1;
259
                        int m;
260
 
261
                        d0 = *src--;
262
                        /* Leading bits */
263
                        if (shift < 0) {
264
                                /* Single source word */
265
                                *dst = comp(d0 << left, *dst, first);
266
                        } else {
267
                                /* 2 source words */
268
                                d1 = *src--;
269
                                *dst = comp(d0 >> right | d1 << left, *dst,
270
                                            first);
271
                                d0 = d1;
272
                        }
273
                        dst--;
274
                        n -= dst_idx+1;
275
 
276
                        /* Main chunk */
277
                        m = n % bits;
278
                        n /= bits;
279
                        while (n >= 4) {
280
                                d1 = *src--;
281
                                *dst-- = d0 >> right | d1 << left;
282
                                d0 = d1;
283
                                d1 = *src--;
284
                                *dst-- = d0 >> right | d1 << left;
285
                                d0 = d1;
286
                                d1 = *src--;
287
                                *dst-- = d0 >> right | d1 << left;
288
                                d0 = d1;
289
                                d1 = *src--;
290
                                *dst-- = d0 >> right | d1 << left;
291
                                d0 = d1;
292
                                n -= 4;
293
                        }
294
                        while (n--) {
295
                                d1 = *src--;
296
                                *dst-- = d0 >> right | d1 << left;
297
                                d0 = d1;
298
                        }
299
 
300
                        /* Trailing bits */
301
                        if (last) {
302
                                if (m <= left) {
303
                                        /* Single source word */
304
                                        *dst = comp(d0 >> right, *dst, last);
305
                                } else {
306
                                        /* 2 source words */
307
                                        d1 = *src;
308
                                        *dst = comp(d0 >> right | d1 << left,
309
                                                    *dst, last);
310
                                }
311
                        }
312
                }
313
        }
314
}
315
 
316
void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area)
317
{
318
        u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
319
        u32 height = area->height, width = area->width;
320
        unsigned long const bits_per_line = p->fix.line_length*8u;
321
        unsigned long *dst = NULL, *src = NULL;
322
        int bits = BITS_PER_LONG, bytes = bits >> 3;
323
        int dst_idx = 0, src_idx = 0, rev_copy = 0;
324
 
325
        if (p->state != FBINFO_STATE_RUNNING)
326
                return;
327
 
328
        /* if the beginning of the target area might overlap with the end of
329
        the source area, be have to copy the area reverse. */
330
        if ((dy == sy && dx > sx) || (dy > sy)) {
331
                dy += height;
332
                sy += height;
333
                rev_copy = 1;
334
        }
335
 
336
        /* split the base of the framebuffer into a long-aligned address and
337
           the index of the first bit */
338
        dst = src = (unsigned long *)((unsigned long)p->screen_base &
339
                                      ~(bytes-1));
340
        dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
341
        /* add offset of source and target area */
342
        dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
343
        src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
344
 
345
        if (p->fbops->fb_sync)
346
                p->fbops->fb_sync(p);
347
 
348
        if (rev_copy) {
349
                while (height--) {
350
                        dst_idx -= bits_per_line;
351
                        src_idx -= bits_per_line;
352
                        dst += dst_idx >> (ffs(bits) - 1);
353
                        dst_idx &= (bytes - 1);
354
                        src += src_idx >> (ffs(bits) - 1);
355
                        src_idx &= (bytes - 1);
356
                        bitcpy_rev(dst, dst_idx, src, src_idx, bits,
357
                                width*p->var.bits_per_pixel);
358
                }
359
        } else {
360
                while (height--) {
361
                        dst += dst_idx >> (ffs(bits) - 1);
362
                        dst_idx &= (bytes - 1);
363
                        src += src_idx >> (ffs(bits) - 1);
364
                        src_idx &= (bytes - 1);
365
                        bitcpy(dst, dst_idx, src, src_idx, bits,
366
                                width*p->var.bits_per_pixel);
367
                        dst_idx += bits_per_line;
368
                        src_idx += bits_per_line;
369
                }
370
        }
371
}
372
 
373
EXPORT_SYMBOL(sys_copyarea);
374
 
375
MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
376
MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)");
377
MODULE_LICENSE("GPL");
378
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.