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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [video/] [leofb.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
/* $Id: leofb.c,v 1.1.1.1 2004-04-15 02:23:40 phoenix Exp $
2
 * leofb.c: Leo (ZX) 24/8bit frame buffer driver
3
 *
4
 * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
5
 * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
6
 */
7
 
8
#include <linux/module.h>
9
#include <linux/sched.h>
10
#include <linux/kernel.h>
11
#include <linux/errno.h>
12
#include <linux/string.h>
13
#include <linux/mm.h>
14
#include <linux/tty.h>
15
#include <linux/slab.h>
16
#include <linux/vmalloc.h>
17
#include <linux/delay.h>
18
#include <linux/interrupt.h>
19
#include <linux/fb.h>
20
#include <linux/init.h>
21
#include <linux/selection.h>
22
 
23
#include <video/sbusfb.h>
24
#include <asm/io.h>
25
 
26
#define LEO_OFF_LC_SS0_KRN      0x00200000UL
27
#define LEO_OFF_LC_SS0_USR      0x00201000UL
28
#define LEO_OFF_LC_SS1_KRN      0x01200000UL
29
#define LEO_OFF_LC_SS1_USR      0x01201000UL
30
#define LEO_OFF_LD_SS0          0x00400000UL
31
#define LEO_OFF_LD_SS1          0x01400000UL
32
#define LEO_OFF_LD_GBL          0x00401000UL
33
#define LEO_OFF_LX_KRN          0x00600000UL
34
#define LEO_OFF_LX_CURSOR       0x00601000UL
35
#define LEO_OFF_SS0             0x00800000UL
36
#define LEO_OFF_SS1             0x01800000UL
37
#define LEO_OFF_UNK             0x00602000UL
38
#define LEO_OFF_UNK2            0x00000000UL
39
 
40
#define LEO_CUR_ENABLE          0x00000080
41
#define LEO_CUR_UPDATE          0x00000030
42
#define LEO_CUR_PROGRESS        0x00000006
43
#define LEO_CUR_UPDATECMAP      0x00000003
44
 
45
#define LEO_CUR_TYPE_MASK       0x00000000
46
#define LEO_CUR_TYPE_IMAGE      0x00000020
47
#define LEO_CUR_TYPE_CMAP       0x00000050
48
 
49
struct leo_cursor {
50
        u8              xxx0[16];
51
        volatile u32    cur_type;
52
        volatile u32    cur_misc;
53
        volatile u32    cur_cursxy;
54
        volatile u32    cur_data;
55
};
56
 
57
#define LEO_KRN_TYPE_CLUT0      0x00001000
58
#define LEO_KRN_TYPE_CLUT1      0x00001001
59
#define LEO_KRN_TYPE_CLUT2      0x00001002
60
#define LEO_KRN_TYPE_WID        0x00001003
61
#define LEO_KRN_TYPE_UNK        0x00001006
62
#define LEO_KRN_TYPE_VIDEO      0x00002003
63
#define LEO_KRN_TYPE_CLUTDATA   0x00004000
64
#define LEO_KRN_CSR_ENABLE      0x00000008
65
#define LEO_KRN_CSR_PROGRESS    0x00000004
66
#define LEO_KRN_CSR_UNK         0x00000002
67
#define LEO_KRN_CSR_UNK2        0x00000001
68
 
69
struct leo_lx_krn {
70
        volatile u32    krn_type;
71
        volatile u32    krn_csr;
72
        volatile u32    krn_value;
73
};
74
 
75
struct leo_lc_ss0_krn {
76
        volatile u32    misc;
77
        u8              xxx0[0x800-4];
78
        volatile u32    rev;
79
};
80
 
81
struct leo_lc_ss0_usr {
82
        volatile u32    csr;
83
        volatile u32    addrspace;
84
        volatile u32    fontmsk;
85
        volatile u32    fontt;
86
        volatile u32    extent;
87
        volatile u32    src;
88
        u32             dst;
89
        volatile u32    copy;
90
        volatile u32    fill;
91
};
92
 
93
struct leo_lc_ss1_krn {
94
        u8      unknown;
95
};
96
 
97
struct leo_lc_ss1_usr {
98
        u8      unknown;
99
};
100
 
101
struct leo_ld {
102
        u8              xxx0[0xe00];
103
        volatile u32    csr;
104
        volatile u32    wid;
105
        volatile u32    wmask;
106
        volatile u32    widclip;
107
        volatile u32    vclipmin;
108
        volatile u32    vclipmax;
109
        volatile u32    pickmin;        /* SS1 only */
110
        volatile u32    pickmax;        /* SS1 only */
111
        volatile u32    fg;
112
        volatile u32    bg;
113
        volatile u32    src;            /* Copy/Scroll (SS0 only) */
114
        volatile u32    dst;            /* Copy/Scroll/Fill (SS0 only) */
115
        volatile u32    extent;         /* Copy/Scroll/Fill size (SS0 only) */
116
        u32             xxx1[3];
117
        volatile u32    setsem;         /* SS1 only */
118
        volatile u32    clrsem;         /* SS1 only */
119
        volatile u32    clrpick;        /* SS1 only */
120
        volatile u32    clrdat;         /* SS1 only */
121
        volatile u32    alpha;          /* SS1 only */
122
        u8              xxx2[0x2c];
123
        volatile u32    winbg;
124
        volatile u32    planemask;
125
        volatile u32    rop;
126
        volatile u32    z;
127
        volatile u32    dczf;           /* SS1 only */
128
        volatile u32    dczb;           /* SS1 only */
129
        volatile u32    dcs;            /* SS1 only */
130
        volatile u32    dczs;           /* SS1 only */
131
        volatile u32    pickfb;         /* SS1 only */
132
        volatile u32    pickbb;         /* SS1 only */
133
        volatile u32    dcfc;           /* SS1 only */
134
        volatile u32    forcecol;       /* SS1 only */
135
        volatile u32    door[8];        /* SS1 only */
136
        volatile u32    pick[5];        /* SS1 only */
137
};
138
 
139
#define LEO_SS1_MISC_ENABLE     0x00000001
140
#define LEO_SS1_MISC_STEREO     0x00000002
141
struct leo_ld_ss1 {
142
        u8              xxx0[0xef4];
143
        volatile u32    ss1_misc;
144
};
145
 
146
struct leo_ld_gbl {
147
        u8      unknown;
148
};
149
 
150
static struct sbus_mmap_map leo_mmap_map[] = {
151
        { LEO_SS0_MAP,          LEO_OFF_SS0,            0x800000        },
152
        { LEO_LC_SS0_USR_MAP,   LEO_OFF_LC_SS0_USR,     0x1000          },
153
        { LEO_LD_SS0_MAP,       LEO_OFF_LD_SS0,         0x1000          },
154
        { LEO_LX_CURSOR_MAP,    LEO_OFF_LX_CURSOR,      0x1000          },
155
        { LEO_SS1_MAP,          LEO_OFF_SS1,            0x800000        },
156
        { LEO_LC_SS1_USR_MAP,   LEO_OFF_LC_SS1_USR,     0x1000          },
157
        { LEO_LD_SS1_MAP,       LEO_OFF_LD_SS1,         0x1000          },
158
        { LEO_UNK_MAP,          LEO_OFF_UNK,            0x1000          },
159
        { LEO_LX_KRN_MAP,       LEO_OFF_LX_KRN,         0x1000          },
160
        { LEO_LC_SS0_KRN_MAP,   LEO_OFF_LC_SS0_KRN,     0x1000          },
161
        { LEO_LC_SS1_KRN_MAP,   LEO_OFF_LC_SS1_KRN,     0x1000          },
162
        { LEO_LD_GBL_MAP,       LEO_OFF_LD_GBL,         0x1000          },
163
        { LEO_UNK2_MAP,         LEO_OFF_UNK2,           0x100000        },
164
        { 0,                     0,                       0                }
165
};
166
 
167
static void leo_setup(struct display *p)
168
{
169
        p->next_line = 8192;
170
        p->next_plane = 0;
171
}
172
 
173
static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
174
                      int height, int width)
175
{
176
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
177
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
178
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
179
        unsigned long flags;
180
        int x, y, w, h;
181
        int i;
182
 
183
        spin_lock_irqsave(&fb->lock, flags);
184
        do {
185
                i = sbus_readl(&us->csr);
186
        } while (i & 0x20000000);
187
        sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
188
        if (fontheightlog(p)) {
189
                y = sy << fontheightlog(p); h = height << fontheightlog(p);
190
        } else {
191
                y = sy * fontheight(p); h = height * fontheight(p);
192
        }
193
        if (fontwidthlog(p)) {
194
                x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
195
        } else {
196
                x = sx * fontwidth(p); w = width * fontwidth(p);
197
        }
198
        sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
199
        sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
200
                    &us->fill);
201
        spin_unlock_irqrestore(&fb->lock, flags);
202
}
203
 
204
static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
205
                     int count, unsigned short *boxes)
206
{
207
        int i;
208
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
209
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
210
        unsigned long flags;
211
 
212
        spin_lock_irqsave(&fb->lock, flags);
213
        sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
214
        while (count-- > 0) {
215
                do {
216
                        i = sbus_readl(&us->csr);
217
                } while (i & 0x20000000);
218
                sbus_writel((boxes[2] - boxes[0] - 1) |
219
                            ((boxes[3] - boxes[1] - 1) << 11),
220
                            &us->extent);
221
                sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
222
                            &us->fill);
223
                boxes += 4;
224
        }
225
        spin_unlock_irqrestore(&fb->lock, flags);
226
}
227
 
228
static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
229
{
230
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
231
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
232
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
233
        unsigned long flags;
234
        int i, x, y;
235
        u8 *fd;
236
        u32 *u;
237
 
238
        spin_lock_irqsave(&fb->lock, flags);
239
        if (fontheightlog(p)) {
240
                y = yy << (fontheightlog(p) + 11);
241
                i = (c & p->charmask) << fontheightlog(p);
242
        } else {
243
                y = (yy * fontheight(p)) << 11;
244
                i = (c & p->charmask) * fontheight(p);
245
        }
246
        if (fontwidth(p) <= 8)
247
                fd = p->fontdata + i;
248
        else
249
                fd = p->fontdata + (i << 1);
250
        if (fontwidthlog(p))
251
                x = xx << fontwidthlog(p);
252
        else
253
                x = xx * fontwidth(p);
254
        do {
255
                i = sbus_readl(&us->csr);
256
        } while (i & 0x20000000);
257
        sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
258
        sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
259
        sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
260
                    &us->fontmsk);
261
        u = ((u32 *)p->screen_base) + y + x;
262
        if (fontwidth(p) <= 8) {
263
                for (i = 0; i < fontheight(p); i++, u += 2048) {
264
                        u32 val = *fd++ << 24;
265
 
266
                        sbus_writel(val, u);
267
                }
268
        } else {
269
                for (i = 0; i < fontheight(p); i++, u += 2048) {
270
                        u32 val = *(u16 *)fd << 16;
271
 
272
                        sbus_writel(val, u);
273
                        fd += 2;
274
                }
275
        }
276
        spin_unlock_irqrestore(&fb->lock, flags);
277
}
278
 
279
static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
280
                      int count, int yy, int xx)
281
{
282
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
283
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
284
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
285
        unsigned long flags;
286
        int i, x, y;
287
        u8 *fd1, *fd2, *fd3, *fd4;
288
        u16 c;
289
        u32 *u;
290
 
291
        spin_lock_irqsave(&fb->lock, flags);
292
        do {
293
                i = sbus_readl(&us->csr);
294
        } while (i & 0x20000000);
295
        c = scr_readw(s);
296
        sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
297
        sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
298
        sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
299
        if (fontwidthlog(p))
300
                x = (xx << fontwidthlog(p));
301
        else
302
                x = xx * fontwidth(p);
303
        if (fontheightlog(p))
304
                y = yy << (fontheightlog(p) + 11);
305
        else
306
                y = (yy * fontheight(p)) << 11;
307
        u = ((u32 *)p->screen_base) + y + x;
308
        if (fontwidth(p) <= 8) {
309
                sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
310
                x = 4*fontwidth(p) - fontheight(p)*2048;
311
                while (count >= 4) {
312
                        count -= 4;
313
                        if (fontheightlog(p)) {
314
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
315
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
316
                                fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
317
                                fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
318
                        } else {
319
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
320
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
321
                                fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
322
                                fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
323
                        }
324
                        if (fontwidth(p) == 8) {
325
                                for (i = 0; i < fontheight(p); i++, u += 2048) {
326
                                        u32 val;
327
 
328
                                        val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
329
                                                << 8)) << 8)) << 8);
330
                                        sbus_writel(val, u);
331
                                }
332
                                u += x;
333
                        } else {
334
                                for (i = 0; i < fontheight(p); i++, u += 2048) {
335
                                        u32 val;
336
 
337
                                        val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
338
                                                << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
339
                                        sbus_writel(val, u);
340
                                }
341
                                u += x;
342
                        }
343
                }
344
        } else {
345
                sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
346
                x = 2*fontwidth(p) - fontheight(p)*2048;
347
                while (count >= 2) {
348
                        count -= 2;
349
                        if (fontheightlog(p)) {
350
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
351
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
352
                        } else {
353
                                fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
354
                                fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
355
                        }
356
                        for (i = 0; i < fontheight(p); i++, u += 2048) {
357
                                u32 val;
358
 
359
                                val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
360
                                sbus_writel(val, u);
361
                                fd1 += 2; fd2 += 2;
362
                        }
363
                        u += x;
364
                }
365
        }
366
        sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
367
        x = fontwidth(p) - fontheight(p)*2048;
368
        while (count) {
369
                count--;
370
                if (fontheightlog(p))
371
                        i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
372
                else
373
                        i = ((scr_readw(s++) & p->charmask) * fontheight(p));
374
                if (fontwidth(p) <= 8) {
375
                        fd1 = p->fontdata + i;
376
                        for (i = 0; i < fontheight(p); i++, u += 2048) {
377
                                u32 val = *fd1++ << 24;
378
 
379
                                sbus_writel(val, u);
380
                        }
381
                } else {
382
                        fd1 = p->fontdata + (i << 1);
383
                        for (i = 0; i < fontheight(p); i++, u += 2048) {
384
                                u32 val = *(u16 *)fd1 << 16;
385
 
386
                                sbus_writel(val, u);
387
                                fd1 += 2;
388
                        }
389
                }
390
                u += x;
391
        }
392
        spin_unlock_irqrestore(&fb->lock, flags);
393
}
394
 
395
static void leo_revc(struct display *p, int xx, int yy)
396
{
397
        /* Not used if hw cursor */
398
}
399
 
400
static int leo_wait (struct leo_lx_krn *lx_krn)
401
{
402
        int i;
403
 
404
        for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
405
                udelay (1); /* Busy wait at most 0.3 sec */
406
        if (i == 300000)
407
                return -EFAULT; /* Timed out - should we print some message? */
408
        return 0;
409
}
410
 
411
static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
412
{
413
        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
414
        unsigned long flags;
415
        u32 tmp;
416
        int i;
417
 
418
        spin_lock_irqsave(&fb->lock, flags);
419
        sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
420
        i = leo_wait (lx_krn);
421
        if (i)
422
                goto out;
423
        sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
424
        for (i = 0; i < 256; i++) {
425
                u32 val;
426
 
427
                val = fb->color_map CM(i,0) |
428
                        (fb->color_map CM(i,1) << 8) |
429
                        (fb->color_map CM(i,2) << 16);
430
 
431
                sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
432
        }
433
        sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
434
        tmp = sbus_readl(&lx_krn->krn_csr);
435
        tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
436
        sbus_writel(tmp, &lx_krn->krn_csr);
437
out:
438
        spin_unlock_irqrestore(&fb->lock, flags);
439
}
440
 
441
static void leo_restore_palette (struct fb_info_sbusfb *fb)
442
{
443
        u32 tmp;
444
        unsigned long flags;
445
 
446
        spin_lock_irqsave(&fb->lock, flags);
447
        tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
448
        tmp &= ~(LEO_SS1_MISC_ENABLE);
449
        sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
450
        spin_unlock_irqrestore(&fb->lock, flags);
451
}
452
 
453
static struct display_switch leo_dispsw __initdata = {
454
        setup:          leo_setup,
455
        bmove:          fbcon_redraw_bmove,
456
        clear:          leo_clear,
457
        putc:           leo_putc,
458
        putcs:          leo_putcs,
459
        revc:           leo_revc,
460
        fontwidthmask:  FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
461
};
462
 
463
static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
464
{
465
        struct leo_cursor *l = fb->s.leo.cursor;
466
        unsigned long flags;
467
        int i;
468
 
469
        spin_lock_irqsave(&fb->lock, flags);
470
        for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
471
                udelay (1); /* Busy wait at most 0.3 sec */
472
        if (i == 300000)
473
                goto out; /* Timed out - should we print some message? */
474
        sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
475
        sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
476
        sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
477
        sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
478
out:
479
        spin_unlock_irqrestore(&fb->lock, flags);
480
}
481
 
482
/* Set cursor shape */
483
static void leo_setcurshape (struct fb_info_sbusfb *fb)
484
{
485
        int i, j, k;
486
        u32 m, n, mask;
487
        struct leo_cursor *l = fb->s.leo.cursor;
488
        u32 tmp;
489
        unsigned long flags;
490
 
491
        spin_lock_irqsave(&fb->lock, flags);
492
        tmp = sbus_readl(&l->cur_misc);
493
        tmp &= ~LEO_CUR_ENABLE;
494
        sbus_writel(tmp, &l->cur_misc);
495
        for (k = 0; k < 2; k ++) {
496
                sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
497
                for (i = 0; i < 32; i++) {
498
                        mask = 0;
499
                        m = fb->cursor.bits[k][i];
500
                        /* mask = m with reversed bit order */
501
                        for (j = 0, n = 1; j < 32; j++, n <<= 1)
502
                                if (m & n)
503
                                        mask |= (0x80000000 >> j);
504
                        sbus_writel(mask, &l->cur_data);
505
                }
506
        }
507
        tmp = sbus_readl(&l->cur_misc);
508
        tmp |= LEO_CUR_ENABLE;
509
        sbus_writel(tmp, &l->cur_misc);
510
        spin_unlock_irqrestore(&fb->lock, flags);
511
}
512
 
513
/* Load cursor information */
514
static void leo_setcursor (struct fb_info_sbusfb *fb)
515
{
516
        struct cg_cursor *c = &fb->cursor;
517
        struct leo_cursor *l = fb->s.leo.cursor;
518
        unsigned long flags;
519
        u32 tmp;
520
 
521
        spin_lock_irqsave(&fb->lock, flags);
522
        tmp = sbus_readl(&l->cur_misc);
523
        tmp &= ~LEO_CUR_ENABLE;
524
        sbus_writel(tmp, &l->cur_misc);
525
 
526
        sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
527
                    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
528
                    &l->cur_cursxy);
529
 
530
        tmp = sbus_readl(&l->cur_misc);
531
        tmp |= LEO_CUR_UPDATE;
532
        if (c->enable)
533
                tmp |= LEO_CUR_ENABLE;
534
        sbus_writel(tmp, &l->cur_misc);
535
        spin_unlock_irqrestore(&fb->lock, flags);
536
}
537
 
538
static void leo_blank (struct fb_info_sbusfb *fb)
539
{
540
        unsigned long flags;
541
        u32 tmp;
542
 
543
        spin_lock_irqsave(&fb->lock, flags);
544
        sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
545
 
546
        tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
547
        tmp &= ~LEO_KRN_CSR_ENABLE;
548
        sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
549
        spin_unlock_irqrestore(&fb->lock, flags);
550
}
551
 
552
static void leo_unblank (struct fb_info_sbusfb *fb)
553
{
554
        unsigned long flags;
555
        u32 tmp;
556
 
557
        spin_lock_irqsave(&fb->lock, flags);
558
        sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
559
 
560
        tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
561
        if (!(tmp & LEO_KRN_CSR_ENABLE)) {
562
                tmp |= LEO_KRN_CSR_ENABLE;
563
                sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
564
        }
565
        spin_unlock_irqrestore(&fb->lock, flags);
566
}
567
 
568
static int __init
569
leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
570
{
571
        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
572
        struct fb_wid_item *wi;
573
        int i, j;
574
 
575
        sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
576
        i = leo_wait (lx_krn);
577
        if (i)
578
                return i;
579
        for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
580
                switch (wi->wi_type) {
581
                case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
582
                case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
583
                default: return -EINVAL;
584
                }
585
                sbus_writel(0x5800 + j, &lx_krn->krn_type);
586
                sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
587
        }
588
        sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
589
        sbus_writel(3, &lx_krn->krn_csr);
590
        return 0;
591
}
592
 
593
static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
594
{
595
        p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
596
}
597
 
598
static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
599
{
600
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
601
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
602
        unsigned long flags;
603
 
604
        spin_lock_irqsave(&fb->lock, flags);
605
        sbus_writel(0xffffffff, &ss->wid);
606
        sbus_writel(0xffff, &ss->wmask);
607
        sbus_writel(0, &ss->vclipmin);
608
        sbus_writel(fb->s.leo.extent, &ss->vclipmax);
609
        sbus_writel(0xff000000, &ss->planemask);
610
        sbus_writel(0x310850, &ss->rop);
611
        sbus_writel(0, &ss->widclip);
612
        sbus_writel(4, &us->addrspace);
613
        sbus_writel(0, &us->fontt);
614
        spin_unlock_irqrestore(&fb->lock, flags);
615
}
616
 
617
static int __init leo_rasterimg (struct fb_info *info, int start)
618
{
619
        struct fb_info_sbusfb *fb = sbusfbinfo(info);
620
        register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
621
        register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
622
 
623
        if (start) {
624
                sbus_writel(1, &ss->wid);
625
                sbus_writel(0xffffff, &ss->planemask);
626
                sbus_writel(0x310b90, &ss->rop);
627
                sbus_writel(0, &us->addrspace);
628
        } else {
629
                sbus_writel(0xffffffff, &ss->wid);
630
                sbus_writel(0xff000000, &ss->planemask);
631
                sbus_writel(0x310850, &ss->rop);
632
                sbus_writel(4, &us->addrspace);
633
        }
634
        return 0;
635
}
636
 
637
static char idstring[40] __initdata = { 0 };
638
 
639
char * __init leofb_init(struct fb_info_sbusfb *fb)
640
{
641
        struct fb_fix_screeninfo *fix = &fb->fix;
642
        struct fb_var_screeninfo *var = &fb->var;
643
        struct display *disp = &fb->disp;
644
        struct fbtype *type = &fb->type;
645
        struct sbus_dev *sdev = fb->sbdp;
646
        unsigned long phys = sdev->reg_addrs[0].phys_addr;
647
        struct fb_wid_item wi;
648
        struct fb_wid_list wl;
649
        int i;
650
        register struct leo_lc_ss0_usr *us;
651
        register struct leo_ld *ss;
652
        struct fb_ops *fbops;
653
        u32 tmp;
654
 
655
        strcpy(fb->info.modename, "Leo");
656
 
657
        strcpy(fix->id, "Leo");
658
        fix->visual = FB_VISUAL_TRUECOLOR;
659
        fix->line_length = 8192;
660
        fix->accel = FB_ACCEL_SUN_LEO;
661
 
662
        var->bits_per_pixel = 32;
663
        var->green.offset = 8;
664
        var->blue.offset = 16;
665
        var->accel_flags = FB_ACCELF_TEXT;
666
 
667
        fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
668
        if (fbops == NULL)
669
                return NULL;
670
 
671
        *fbops = *fb->info.fbops;
672
        fbops->fb_rasterimg = leo_rasterimg;
673
        fb->info.fbops = fbops;
674
 
675
        disp->scrollmode = SCROLL_YREDRAW;
676
        if (!disp->screen_base) {
677
                disp->screen_base = (char *)
678
                        sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
679
                                     0x800000, "leo ram");
680
        }
681
        disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
682
        us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
683
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
684
                             0x1000, "leolc ss0usr");
685
        fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
686
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
687
                             0x1000, "leold ss0");
688
        ss = (struct leo_ld *) fb->s.leo.ld_ss0;
689
        fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
690
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
691
                             0x1000, "leold ss1");
692
        fb->s.leo.lx_krn = (struct leo_lx_krn *)
693
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
694
                             0x1000, "leolx krn");
695
        fb->s.leo.cursor = (struct leo_cursor *)
696
                sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
697
                             sizeof(struct leo_cursor), "leolx cursor");
698
        fb->dispsw = leo_dispsw;
699
 
700
        fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
701
 
702
        wl.wl_count = 1;
703
        wl.wl_list = &wi;
704
        wi.wi_type = FB_WID_DBL_8;
705
        wi.wi_index = 0;
706
        wi.wi_values [0] = 0x2c0;
707
        leo_wid_put (fb, &wl);
708
        wi.wi_index = 1;
709
        wi.wi_values [0] = 0x30;
710
        leo_wid_put (fb, &wl);
711
        wi.wi_index = 2;
712
        wi.wi_values [0] = 0x20;
713
        leo_wid_put (fb, &wl);
714
        wi.wi_type = FB_WID_DBL_24;
715
        wi.wi_index = 1;
716
        wi.wi_values [0] = 0x30;
717
        leo_wid_put (fb, &wl);
718
 
719
        tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
720
        tmp |= LEO_SS1_MISC_ENABLE;
721
        sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
722
 
723
        sbus_writel(0xffffffff, &ss->wid);
724
        sbus_writel(0xffff, &ss->wmask);
725
        sbus_writel(0, &ss->vclipmin);
726
        sbus_writel(fb->s.leo.extent, &ss->vclipmax);
727
        sbus_writel(0, &ss->fg);
728
        sbus_writel(0xff000000, &ss->planemask);
729
        sbus_writel(0x310850, &ss->rop);
730
        sbus_writel(0, &ss->widclip);
731
        sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
732
        sbus_writel(4, &us->addrspace);
733
        sbus_writel(0x80000000, &us->fill);
734
        sbus_writel(0, &us->fontt);
735
        do {
736
                i = sbus_readl(&us->csr);
737
        } while (i & 0x20000000);
738
 
739
        fb->margins = leo_margins;
740
        fb->loadcmap = leo_loadcmap;
741
        fb->setcursor = leo_setcursor;
742
        fb->setcursormap = leo_setcursormap;
743
        fb->setcurshape = leo_setcurshape;
744
        fb->restore_palette = leo_restore_palette;
745
        fb->switch_from_graph = leo_switch_from_graph;
746
        fb->fill = leo_fill;
747
        fb->blank = leo_blank;
748
        fb->unblank = leo_unblank;
749
 
750
        fb->physbase = phys;
751
        fb->mmap_map = leo_mmap_map;
752
 
753
#ifdef __sparc_v9__
754
        sprintf(idstring, "leo at %016lx", phys);
755
#else   
756
        sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
757
#endif
758
 
759
        return idstring;
760
}
761
 
762
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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