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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [video/] [fbcon-iplan2p4.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/video/fbcon-iplan2p4.c -- Low level frame buffer operations
3
 *                                 for interleaved bitplanes à la Atari (4
4
 *                                 planes, 2 bytes interleave)
5
 *
6
 *      Created 5 Apr 1997 by Geert Uytterhoeven
7
 *
8
 *  This file is subject to the terms and conditions of the GNU General Public
9
 *  License.  See the file COPYING in the main directory of this archive for
10
 *  more details.
11
 */
12
 
13
#include <linux/module.h>
14
#include <linux/tty.h>
15
#include <linux/console.h>
16
#include <linux/string.h>
17
#include <linux/fb.h>
18
 
19
#include <asm/byteorder.h>
20
 
21
#ifdef __mc68000__
22
#include <asm/setup.h>
23
#endif
24
 
25
#include <video/fbcon.h>
26
#include <video/fbcon-iplan2p4.h>
27
 
28
 
29
    /*
30
     *  Interleaved bitplanes à la Atari (4 planes, 2 bytes interleave)
31
     */
32
 
33
/* Increment/decrement 4 plane addresses */
34
 
35
#define INC_4P(p)       do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
36
#define DEC_4P(p)       do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
37
 
38
/* Perform the m68k movepl operation.  */
39
static inline void movepl(u8 *d, u32 val)
40
{
41
#if defined __mc68000__ && !defined CPU_M68060_ONLY
42
    asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val));
43
#else
44
    d[0] = (val >> 24) & 0xff;
45
    d[2] = (val >> 16) & 0xff;
46
    d[4] = (val >> 8) & 0xff;
47
    d[6] = val & 0xff;
48
#endif
49
}
50
 
51
/* Sets the bytes in the visible column at d, height h, to the value
52
 * val for a 4 plane screen. The bits of the color in 'color' are
53
 * moved (8 times) to the respective bytes. This means:
54
 *
55
 * for(h times; d += bpr)
56
 *   *d     = (color & 1) ? 0xff : 0;
57
 *   *(d+2) = (color & 2) ? 0xff : 0;
58
 *   *(d+4) = (color & 4) ? 0xff : 0;
59
 *   *(d+6) = (color & 8) ? 0xff : 0;
60
 */
61
 
62
static __inline__ void memclear_4p_col(void *d, size_t h, u32 val, int bpr)
63
{
64
    u8 *dd = d;
65
    do {
66
        movepl(dd, val);
67
        dd += bpr;
68
    } while (--h);
69
}
70
 
71
/* Sets a 4 plane region from 'd', length 'count' bytes, to the color
72
 * in val1/val2. 'd' has to be an even address and count must be divisible
73
 * by 8, because only whole words and all planes are accessed. I.e.:
74
 *
75
 * for(count/8 times)
76
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
77
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
78
 *   *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
79
 *   *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
80
 */
81
 
82
static __inline__ void memset_even_4p(void *d, size_t count, u32 val1,
83
                                      u32 val2)
84
{
85
    u32 *dd = d;
86
 
87
    count /= 8;
88
    while (count--) {
89
        *dd++ = val1;
90
        *dd++ = val2;
91
    }
92
}
93
 
94
/* Copies a 4 plane column from 's', height 'h', to 'd'. */
95
 
96
static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr)
97
{
98
    u8 *dd = d, *ss = s;
99
 
100
    while (h--) {
101
        dd[0] = ss[0];
102
        dd[2] = ss[2];
103
        dd[4] = ss[4];
104
        dd[6] = ss[6];
105
        dd += bpr;
106
        ss += bpr;
107
    }
108
}
109
 
110
 
111
/* This expands a 4 bit color into a long for movepl (4 plane) operations. */
112
 
113
static const u32 four2byte[] = {
114
    0x00000000, 0xff000000, 0x00ff0000, 0xffff0000,
115
    0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
116
    0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff,
117
    0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff
118
};
119
 
120
static __inline__ u32 expand4l(u8 c)
121
{
122
    return four2byte[c];
123
}
124
 
125
 
126
/* This expands a 4 bit color into two longs for two movel operations
127
 * (4 planes).
128
 */
129
 
130
static const u32 two2word[] = {
131
#ifndef __LITTLE_ENDIAN
132
    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff,
133
#else
134
    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff,
135
#endif
136
};
137
 
138
static __inline__ void expand4dl(u8 c, u32 *ret1, u32 *ret2)
139
{
140
    *ret1 = two2word[c & 3];
141
    *ret2 = two2word[c >> 2];
142
}
143
 
144
 
145
/* This duplicates a byte 4 times into a long. */
146
 
147
static __inline__ u32 dup4l(u8 c)
148
{
149
    u32 rv;
150
 
151
    rv = c;
152
    rv |= rv << 8;
153
    rv |= rv << 16;
154
    return rv;
155
}
156
 
157
 
158
void fbcon_iplan2p4_setup(struct display *p)
159
{
160
    p->next_line = p->var.xres_virtual>>1;
161
    p->next_plane = 2;
162
}
163
 
164
void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, int dx,
165
                          int height, int width)
166
{
167
    /*  bmove() has to distinguish two major cases: If both, source and
168
     *  destination, start at even addresses or both are at odd
169
     *  addresses, just the first odd and last even column (if present)
170
     *  require special treatment (memmove_col()). The rest between
171
     *  then can be copied by normal operations, because all adjacent
172
     *  bytes are affected and are to be stored in the same order.
173
     *    The pathological case is when the move should go from an odd
174
     *  address to an even or vice versa. Since the bytes in the plane
175
     *  words must be assembled in new order, it seems wisest to make
176
     *  all movements by memmove_col().
177
     */
178
 
179
    if (sx == 0 && dx == 0 && width * 4 == p->next_line) {
180
        /*  Special (but often used) case: Moving whole lines can be
181
         *done with memmove()
182
         */
183
        fb_memmove(p->screen_base + dy * p->next_line * fontheight(p),
184
                  p->screen_base + sy * p->next_line * fontheight(p),
185
                  p->next_line * height * fontheight(p));
186
    } else {
187
        int rows, cols;
188
        u8 *src;
189
        u8 *dst;
190
        int bytes = p->next_line;
191
        int linesize;
192
        u_int colsize;
193
        u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
194
 
195
        if (fontheightlog(p)) {
196
            linesize = bytes << fontheightlog(p);
197
            colsize = height << fontheightlog(p);
198
        } else {
199
            linesize = bytes * fontheight(p);
200
            colsize = height * fontheight(p);
201
        }
202
        if ((sx & 1) == (dx & 1)) {
203
            /* odd->odd or even->even */
204
 
205
            if (upwards) {
206
                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
207
                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
208
                if (sx & 1) {
209
                    memmove_4p_col(dst, src, colsize, bytes);
210
                    src += 7;
211
                    dst += 7;
212
                    --width;
213
                }
214
                if (width > 1) {
215
                    for(rows = colsize; rows > 0; --rows) {
216
                        fb_memmove(dst, src, (width>>1)*8);
217
                        src += bytes;
218
                        dst += bytes;
219
                    }
220
                }
221
                if (width & 1) {
222
                    src -= colsize * bytes;
223
                    dst -= colsize * bytes;
224
                    memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8,
225
                    colsize, bytes);
226
                }
227
            } else {
228
                if (!((sx+width-1) & 1)) {
229
                    src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*8;
230
                    dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*8;
231
                    memmove_4p_col(dst, src, colsize, bytes);
232
                    --width;
233
                }
234
                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
235
                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
236
                if (width > 1) {
237
                    src += colsize * bytes + (sx & 1)*7;
238
                    dst += colsize * bytes + (sx & 1)*7;
239
                    for(rows = colsize; rows > 0; --rows) {
240
                        src -= bytes;
241
                        dst -= bytes;
242
                        fb_memmove(dst, src, (width>>1)*8);
243
                    }
244
                }
245
                if (width & 1) {
246
                memmove_4p_col(dst-7, src-7, colsize, bytes);
247
                }
248
            }
249
        } else {
250
        /* odd->even or even->odd */
251
 
252
            if (upwards) {
253
                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
254
                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
255
                for(cols = width; cols > 0; --cols) {
256
                    memmove_4p_col(dst, src, colsize, bytes);
257
                    INC_4P(src);
258
                    INC_4P(dst);
259
                }
260
            } else {
261
                sx += width-1;
262
                dx += width-1;
263
                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
264
                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
265
                for(cols = width; cols > 0; --cols) {
266
                    memmove_4p_col(dst, src, colsize, bytes);
267
                    DEC_4P(src);
268
                    DEC_4P(dst);
269
                }
270
            }
271
        }
272
    }
273
}
274
 
275
void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy,
276
                          int sx, int height, int width)
277
{
278
    u32 offset;
279
    u8 *start;
280
    int rows;
281
    int bytes = p->next_line;
282
    int lines;
283
    u32 size;
284
    u32 cval1, cval2, pcval;
285
 
286
    expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
287
 
288
    if (fontheightlog(p))
289
        lines = height << fontheightlog(p);
290
    else
291
        lines = height * fontheight(p);
292
 
293
    if (sx == 0 && width * 4 == bytes) {
294
        if (fontheightlog(p))
295
            offset = (sy * bytes) << fontheightlog(p);
296
        else
297
            offset = sy * bytes * fontheight(p);
298
        size = lines * bytes;
299
        memset_even_4p(p->screen_base+offset, size, cval1, cval2);
300
    } else {
301
        if (fontheightlog(p))
302
            offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
303
        else
304
            offset = sy * bytes * fontheight(p) + (sx>>1)*8 + (sx & 1);
305
        start = p->screen_base + offset;
306
        pcval = expand4l(attr_bgcol_ec(p,conp));
307
 
308
        /*  Clears are split if the region starts at an odd column or
309
         *  end at an even column. These extra columns are spread
310
         *  across the interleaved planes. All in between can be
311
         *  cleared by normal fb_memclear_small(), because both bytes of
312
         *  the single plane words are affected.
313
         */
314
 
315
        if (sx & 1) {
316
            memclear_4p_col(start, lines, pcval, bytes);
317
            start += 7;
318
            width--;
319
        }
320
        if (width & 1) {
321
            memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes);
322
            width--;
323
        }
324
        if (width) {
325
            for(rows = lines; rows-- ; start += bytes)
326
                memset_even_4p(start, width*4, cval1, cval2);
327
        }
328
    }
329
}
330
 
331
void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
332
                         int yy, int xx)
333
{
334
    u8 *dest;
335
    u8 *cdat;
336
    int rows;
337
    int bytes = p->next_line;
338
    u32 eorx, fgx, bgx, fdx;
339
 
340
    if (fontheightlog(p)) {
341
        dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
342
                (xx>>1)*8 + (xx & 1));
343
        cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
344
    } else {
345
        dest = (p->screen_base + yy * bytes * fontheight(p) +
346
                (xx>>1)*8 + (xx & 1));
347
        cdat = p->fontdata + (c & p->charmask) * fontheight(p);
348
    }
349
 
350
    fgx = expand4l(attr_fgcol(p,c));
351
    bgx = expand4l(attr_bgcol(p,c));
352
    eorx = fgx ^ bgx;
353
 
354
    for(rows = fontheight(p) ; rows-- ; dest += bytes) {
355
        fdx = dup4l(*cdat++);
356
        movepl(dest, (fdx & eorx) ^ bgx);
357
    }
358
}
359
 
360
void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
361
                          const unsigned short *s, int count, int yy, int xx)
362
{
363
    u8 *dest, *dest0;
364
    u8 *cdat;
365
    u16 c;
366
    int rows;
367
    int bytes;
368
    u32 eorx, fgx, bgx, fdx;
369
 
370
    bytes = p->next_line;
371
    if (fontheightlog(p))
372
        dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
373
                 (xx>>1)*8 + (xx & 1));
374
    else
375
        dest0 = (p->screen_base + yy * bytes * fontheight(p) +
376
                 (xx>>1)*8 + (xx & 1));
377
    c = scr_readw(s);
378
    fgx = expand4l(attr_fgcol(p, c));
379
    bgx = expand4l(attr_bgcol(p, c));
380
    eorx = fgx ^ bgx;
381
 
382
    while (count--) {
383
        /* I think, unrolling the loops like in the 1 plane case isn't
384
        * practicable here, because the body is much longer for 4
385
        * planes (mostly the dup4l()). I guess, unrolling this would
386
        * need more than 256 bytes and so exceed the instruction
387
        * cache :-(
388
        */
389
 
390
        c = scr_readw(s++) & p->charmask;
391
        if (fontheightlog(p))
392
            cdat = p->fontdata + (c << fontheightlog(p));
393
        else
394
            cdat = p->fontdata + c * fontheight(p);
395
 
396
        for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
397
            fdx = dup4l(*cdat++);
398
            movepl(dest, (fdx & eorx) ^ bgx);
399
        }
400
        INC_4P(dest0);
401
    }
402
}
403
 
404
void fbcon_iplan2p4_revc(struct display *p, int xx, int yy)
405
{
406
    u8 *dest;
407
    int j;
408
    int bytes;
409
 
410
    if (fontheightlog(p))
411
        dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
412
                (xx>>1)*8 + (xx & 1));
413
    else
414
        dest = (p->screen_base + yy * p->next_line * fontheight(p) +
415
                (xx>>1)*8 + (xx & 1));
416
    j = fontheight(p);
417
    bytes = p->next_line;
418
 
419
    while (j--) {
420
        /*  This should really obey the individual character's
421
         *  background and foreground colors instead of simply
422
         *  inverting.
423
         */
424
        dest[0] = ~dest[0];
425
        dest[2] = ~dest[2];
426
        dest[4] = ~dest[4];
427
        dest[6] = ~dest[6];
428
        dest += bytes;
429
    }
430
}
431
 
432
void fbcon_iplan2p4_clear_margins(struct vc_data *conp, struct display *p,
433
                                  int bottom_only)
434
{
435
    u32 offset;
436
    int bytes;
437
    int lines;
438
    u32 cval1, cval2;
439
 
440
/* No need to handle right margin, cannot occur with fontwidth == 8 */
441
 
442
    bytes = p->next_line;
443
    if (fontheightlog(p)) {
444
        lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
445
        offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
446
    } else {
447
        lines = p->var.yres - conp->vc_rows * fontheight(p);
448
        offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
449
    }
450
    if (lines) {
451
        expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
452
        memset_even_4p(p->screen_base+offset, lines * bytes, cval1, cval2);
453
    }
454
}
455
 
456
 
457
    /*
458
     *  `switch' for the low level operations
459
     */
460
 
461
struct display_switch fbcon_iplan2p4 = {
462
    setup:              fbcon_iplan2p4_setup,
463
    bmove:              fbcon_iplan2p4_bmove,
464
    clear:              fbcon_iplan2p4_clear,
465
    putc:               fbcon_iplan2p4_putc,
466
    putcs:              fbcon_iplan2p4_putcs,
467
    revc:               fbcon_iplan2p4_revc,
468
    clear_margins:      fbcon_iplan2p4_clear_margins,
469
    fontwidthmask:      FONTWIDTH(8)
470
};
471
 
472
 
473
#ifdef MODULE
474
MODULE_LICENSE("GPL");
475
 
476
int init_module(void)
477
{
478
    return 0;
479
}
480
 
481
void cleanup_module(void)
482
{}
483
#endif /* MODULE */
484
 
485
 
486
    /*
487
     *  Visible symbols for modules
488
     */
489
 
490
EXPORT_SYMBOL(fbcon_iplan2p4);
491
EXPORT_SYMBOL(fbcon_iplan2p4_setup);
492
EXPORT_SYMBOL(fbcon_iplan2p4_bmove);
493
EXPORT_SYMBOL(fbcon_iplan2p4_clear);
494
EXPORT_SYMBOL(fbcon_iplan2p4_putc);
495
EXPORT_SYMBOL(fbcon_iplan2p4_putcs);
496
EXPORT_SYMBOL(fbcon_iplan2p4_revc);
497
EXPORT_SYMBOL(fbcon_iplan2p4_clear_margins);

powered by: WebSVN 2.1.0

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