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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [video/] [creatorfb.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: creatorfb.c,v 1.1.1.1 2004-04-15 02:23:25 phoenix Exp $
2
 * creatorfb.c: Creator/Creator3D frame buffer driver
3
 *
4
 * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
5
 */
6
 
7
#include <linux/module.h>
8
#include <linux/sched.h>
9
#include <linux/kernel.h>
10
#include <linux/errno.h>
11
#include <linux/string.h>
12
#include <linux/mm.h>
13
#include <linux/tty.h>
14
#include <linux/slab.h>
15
#include <linux/vmalloc.h>
16
#include <linux/delay.h>
17
#include <linux/interrupt.h>
18
#include <linux/fb.h>
19
#include <linux/init.h>
20
#include <linux/selection.h>
21
 
22
#include <video/sbusfb.h>
23
 
24
#include <asm/upa.h>
25
 
26
#define FFB_SFB8R_VOFF          0x00000000
27
#define FFB_SFB8G_VOFF          0x00400000
28
#define FFB_SFB8B_VOFF          0x00800000
29
#define FFB_SFB8X_VOFF          0x00c00000
30
#define FFB_SFB32_VOFF          0x01000000
31
#define FFB_SFB64_VOFF          0x02000000
32
#define FFB_FBC_REGS_VOFF       0x04000000
33
#define FFB_BM_FBC_REGS_VOFF    0x04002000
34
#define FFB_DFB8R_VOFF          0x04004000
35
#define FFB_DFB8G_VOFF          0x04404000
36
#define FFB_DFB8B_VOFF          0x04804000
37
#define FFB_DFB8X_VOFF          0x04c04000
38
#define FFB_DFB24_VOFF          0x05004000
39
#define FFB_DFB32_VOFF          0x06004000
40
#define FFB_DFB422A_VOFF        0x07004000      /* DFB 422 mode write to A */
41
#define FFB_DFB422AD_VOFF       0x07804000      /* DFB 422 mode with line doubling */
42
#define FFB_DFB24B_VOFF         0x08004000      /* DFB 24bit mode write to B */
43
#define FFB_DFB422B_VOFF        0x09004000      /* DFB 422 mode write to B */
44
#define FFB_DFB422BD_VOFF       0x09804000      /* DFB 422 mode with line doubling */
45
#define FFB_SFB16Z_VOFF         0x0a004000      /* 16bit mode Z planes */
46
#define FFB_SFB8Z_VOFF          0x0a404000      /* 8bit mode Z planes */
47
#define FFB_SFB422_VOFF         0x0ac04000      /* SFB 422 mode write to A/B */
48
#define FFB_SFB422D_VOFF        0x0b404000      /* SFB 422 mode with line doubling */
49
#define FFB_FBC_KREGS_VOFF      0x0bc04000
50
#define FFB_DAC_VOFF            0x0bc06000
51
#define FFB_PROM_VOFF           0x0bc08000
52
#define FFB_EXP_VOFF            0x0bc18000
53
 
54
#define FFB_SFB8R_POFF          0x04000000UL
55
#define FFB_SFB8G_POFF          0x04400000UL
56
#define FFB_SFB8B_POFF          0x04800000UL
57
#define FFB_SFB8X_POFF          0x04c00000UL
58
#define FFB_SFB32_POFF          0x05000000UL
59
#define FFB_SFB64_POFF          0x06000000UL
60
#define FFB_FBC_REGS_POFF       0x00600000UL
61
#define FFB_BM_FBC_REGS_POFF    0x00600000UL
62
#define FFB_DFB8R_POFF          0x01000000UL
63
#define FFB_DFB8G_POFF          0x01400000UL
64
#define FFB_DFB8B_POFF          0x01800000UL
65
#define FFB_DFB8X_POFF          0x01c00000UL
66
#define FFB_DFB24_POFF          0x02000000UL
67
#define FFB_DFB32_POFF          0x03000000UL
68
#define FFB_FBC_KREGS_POFF      0x00610000UL
69
#define FFB_DAC_POFF            0x00400000UL
70
#define FFB_PROM_POFF           0x00000000UL
71
#define FFB_EXP_POFF            0x00200000UL
72
#define FFB_DFB422A_POFF        0x09000000UL
73
#define FFB_DFB422AD_POFF       0x09800000UL
74
#define FFB_DFB24B_POFF         0x0a000000UL
75
#define FFB_DFB422B_POFF        0x0b000000UL
76
#define FFB_DFB422BD_POFF       0x0b800000UL
77
#define FFB_SFB16Z_POFF         0x0c800000UL
78
#define FFB_SFB8Z_POFF          0x0c000000UL
79
#define FFB_SFB422_POFF         0x0d000000UL
80
#define FFB_SFB422D_POFF        0x0d800000UL
81
 
82
/* Draw operations */
83
#define FFB_DRAWOP_DOT          0x00
84
#define FFB_DRAWOP_AADOT        0x01
85
#define FFB_DRAWOP_BRLINECAP    0x02
86
#define FFB_DRAWOP_BRLINEOPEN   0x03
87
#define FFB_DRAWOP_DDLINE       0x04
88
#define FFB_DRAWOP_AALINE       0x05
89
#define FFB_DRAWOP_TRIANGLE     0x06
90
#define FFB_DRAWOP_POLYGON      0x07
91
#define FFB_DRAWOP_RECTANGLE    0x08
92
#define FFB_DRAWOP_FASTFILL     0x09
93
#define FFB_DRAWOP_BCOPY        0x0a
94
#define FFB_DRAWOP_VSCROLL      0x0b
95
 
96
/* Pixel processor control */
97
/* Force WID */
98
#define FFB_PPC_FW_DISABLE      0x800000
99
#define FFB_PPC_FW_ENABLE       0xc00000
100
/* Auxiliary clip */
101
#define FFB_PPC_ACE_DISABLE     0x040000
102
#define FFB_PPC_ACE_AUX_SUB     0x080000
103
#define FFB_PPC_ACE_AUX_ADD     0x0c0000
104
/* Depth cue */
105
#define FFB_PPC_DCE_DISABLE     0x020000
106
#define FFB_PPC_DCE_ENABLE      0x030000
107
/* Alpha blend */
108
#define FFB_PPC_ABE_DISABLE     0x008000
109
#define FFB_PPC_ABE_ENABLE      0x00c000
110
/* View clip */
111
#define FFB_PPC_VCE_DISABLE     0x001000
112
#define FFB_PPC_VCE_2D          0x002000
113
#define FFB_PPC_VCE_3D          0x003000
114
/* Area pattern */
115
#define FFB_PPC_APE_DISABLE     0x000800
116
#define FFB_PPC_APE_ENABLE      0x000c00
117
/* Transparent background */
118
#define FFB_PPC_TBE_OPAQUE      0x000200
119
#define FFB_PPC_TBE_TRANSPARENT 0x000300
120
/* Z source */
121
#define FFB_PPC_ZS_VAR          0x000080
122
#define FFB_PPC_ZS_CONST        0x0000c0
123
/* Y source */
124
#define FFB_PPC_YS_VAR          0x000020
125
#define FFB_PPC_YS_CONST        0x000030
126
/* X source */
127
#define FFB_PPC_XS_WID          0x000004
128
#define FFB_PPC_XS_VAR          0x000008
129
#define FFB_PPC_XS_CONST        0x00000c
130
/* Color (BGR) source */
131
#define FFB_PPC_CS_VAR          0x000002
132
#define FFB_PPC_CS_CONST        0x000003
133
 
134
#define FFB_ROP_NEW                  0x83
135
 
136
#define FFB_UCSR_FIFO_MASK     0x00000fff
137
#define FFB_UCSR_FB_BUSY       0x01000000
138
#define FFB_UCSR_RP_BUSY       0x02000000
139
#define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
140
#define FFB_UCSR_READ_ERR      0x40000000
141
#define FFB_UCSR_FIFO_OVFL     0x80000000
142
#define FFB_UCSR_ALL_ERRORS    (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
143
 
144
struct ffb_fbc {
145
        /* Next vertex registers */
146
        u32             xxx1[3];
147
        volatile u32    alpha;
148
        volatile u32    red;
149
        volatile u32    green;
150
        volatile u32    blue;
151
        volatile u32    depth;
152
        volatile u32    y;
153
        volatile u32    x;
154
        u32             xxx2[2];
155
        volatile u32    ryf;
156
        volatile u32    rxf;
157
        u32             xxx3[2];
158
 
159
        volatile u32    dmyf;
160
        volatile u32    dmxf;
161
        u32             xxx4[2];
162
        volatile u32    ebyi;
163
        volatile u32    ebxi;
164
        u32             xxx5[2];
165
        volatile u32    by;
166
        volatile u32    bx;
167
        u32             dy;
168
        u32             dx;
169
        volatile u32    bh;
170
        volatile u32    bw;
171
        u32             xxx6[2];
172
 
173
        u32             xxx7[32];
174
 
175
        /* Setup unit vertex state register */
176
        volatile u32    suvtx;
177
        u32             xxx8[63];
178
 
179
        /* Control registers */
180
        volatile u32    ppc;
181
        volatile u32    wid;
182
        volatile u32    fg;
183
        volatile u32    bg;
184
        volatile u32    consty;
185
        volatile u32    constz;
186
        volatile u32    xclip;
187
        volatile u32    dcss;
188
        volatile u32    vclipmin;
189
        volatile u32    vclipmax;
190
        volatile u32    vclipzmin;
191
        volatile u32    vclipzmax;
192
        volatile u32    dcsf;
193
        volatile u32    dcsb;
194
        volatile u32    dczf;
195
        volatile u32    dczb;
196
 
197
        u32             xxx9;
198
        volatile u32    blendc;
199
        volatile u32    blendc1;
200
        volatile u32    blendc2;
201
        volatile u32    fbramitc;
202
        volatile u32    fbc;
203
        volatile u32    rop;
204
        volatile u32    cmp;
205
        volatile u32    matchab;
206
        volatile u32    matchc;
207
        volatile u32    magnab;
208
        volatile u32    magnc;
209
        volatile u32    fbcfg0;
210
        volatile u32    fbcfg1;
211
        volatile u32    fbcfg2;
212
        volatile u32    fbcfg3;
213
 
214
        u32             ppcfg;
215
        volatile u32    pick;
216
        volatile u32    fillmode;
217
        volatile u32    fbramwac;
218
        volatile u32    pmask;
219
        volatile u32    xpmask;
220
        volatile u32    ypmask;
221
        volatile u32    zpmask;
222
        volatile u32    clip0min;
223
        volatile u32    clip0max;
224
        volatile u32    clip1min;
225
        volatile u32    clip1max;
226
        volatile u32    clip2min;
227
        volatile u32    clip2max;
228
        volatile u32    clip3min;
229
        volatile u32    clip3max;
230
 
231
        /* New 3dRAM III support regs */
232
        volatile u32    rawblend2;
233
        volatile u32    rawpreblend;
234
        volatile u32    rawstencil;
235
        volatile u32    rawstencilctl;
236
        volatile u32    threedram1;
237
        volatile u32    threedram2;
238
        volatile u32    passin;
239
        volatile u32    rawclrdepth;
240
        volatile u32    rawpmask;
241
        volatile u32    rawcsrc;
242
        volatile u32    rawmatch;
243
        volatile u32    rawmagn;
244
        volatile u32    rawropblend;
245
        volatile u32    rawcmp;
246
        volatile u32    rawwac;
247
        volatile u32    fbramid;
248
 
249
        volatile u32    drawop;
250
        u32             xxx10[2];
251
        volatile u32    fontlpat;
252
        u32             xxx11;
253
        volatile u32    fontxy;
254
        volatile u32    fontw;
255
        volatile u32    fontinc;
256
        volatile u32    font;
257
        u32             xxx12[3];
258
        volatile u32    blend2;
259
        volatile u32    preblend;
260
        volatile u32    stencil;
261
        volatile u32    stencilctl;
262
 
263
        u32             xxx13[4];
264
        volatile u32    dcss1;
265
        volatile u32    dcss2;
266
        volatile u32    dcss3;
267
        volatile u32    widpmask;
268
        volatile u32    dcs2;
269
        volatile u32    dcs3;
270
        volatile u32    dcs4;
271
        u32             xxx14;
272
        volatile u32    dcd2;
273
        volatile u32    dcd3;
274
        volatile u32    dcd4;
275
        u32             xxx15;
276
 
277
        volatile u32    pattern[32];
278
 
279
        u32             xxx16[256];
280
 
281
        volatile u32    devid;
282
        u32             xxx17[63];
283
 
284
        volatile u32    ucsr;
285
        u32             xxx18[31];
286
 
287
        volatile u32    mer;
288
};
289
 
290
static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
291
{
292
        struct ffb_fbc *fbc;
293
        int cache = fb->s.ffb.fifo_cache;
294
 
295
        if (cache - n < 0) {
296
                fbc = fb->s.ffb.fbc;
297
                do {    cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
298
                } while (cache - n < 0);
299
        }
300
        fb->s.ffb.fifo_cache = cache - n;
301
}
302
 
303
static __inline__ void FFBWait(struct ffb_fbc *ffb)
304
{
305
        int limit = 10000;
306
 
307
        do {
308
                if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
309
                        break;
310
                if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
311
                        upa_writel(FFB_UCSR_ALL_ERRORS, &ffb->ucsr);
312
                }
313
        } while(--limit > 0);
314
}
315
 
316
struct ffb_dac {
317
        volatile u32    type;
318
        volatile u32    value;
319
        volatile u32    type2;
320
        volatile u32    value2;
321
};
322
 
323
static struct sbus_mmap_map ffb_mmap_map[] = {
324
        { FFB_SFB8R_VOFF,       FFB_SFB8R_POFF,         0x0400000 },
325
        { FFB_SFB8G_VOFF,       FFB_SFB8G_POFF,         0x0400000 },
326
        { FFB_SFB8B_VOFF,       FFB_SFB8B_POFF,         0x0400000 },
327
        { FFB_SFB8X_VOFF,       FFB_SFB8X_POFF,         0x0400000 },
328
        { FFB_SFB32_VOFF,       FFB_SFB32_POFF,         0x1000000 },
329
        { FFB_SFB64_VOFF,       FFB_SFB64_POFF,         0x2000000 },
330
        { FFB_FBC_REGS_VOFF,    FFB_FBC_REGS_POFF,      0x0002000 },
331
        { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF,   0x0002000 },
332
        { FFB_DFB8R_VOFF,       FFB_DFB8R_POFF,         0x0400000 },
333
        { FFB_DFB8G_VOFF,       FFB_DFB8G_POFF,         0x0400000 },
334
        { FFB_DFB8B_VOFF,       FFB_DFB8B_POFF,         0x0400000 },
335
        { FFB_DFB8X_VOFF,       FFB_DFB8X_POFF,         0x0400000 },
336
        { FFB_DFB24_VOFF,       FFB_DFB24_POFF,         0x1000000 },
337
        { FFB_DFB32_VOFF,       FFB_DFB32_POFF,         0x1000000 },
338
        { FFB_FBC_KREGS_VOFF,   FFB_FBC_KREGS_POFF,     0x0002000 },
339
        { FFB_DAC_VOFF,         FFB_DAC_POFF,           0x0002000 },
340
        { FFB_PROM_VOFF,        FFB_PROM_POFF,          0x0010000 },
341
        { FFB_EXP_VOFF,         FFB_EXP_POFF,           0x0002000 },
342
        { FFB_DFB422A_VOFF,     FFB_DFB422A_POFF,       0x0800000 },
343
        { FFB_DFB422AD_VOFF,    FFB_DFB422AD_POFF,      0x0800000 },
344
        { FFB_DFB24B_VOFF,      FFB_DFB24B_POFF,        0x1000000 },
345
        { FFB_DFB422B_VOFF,     FFB_DFB422B_POFF,       0x0800000 },
346
        { FFB_DFB422BD_VOFF,    FFB_DFB422BD_POFF,      0x0800000 },
347
        { FFB_SFB16Z_VOFF,      FFB_SFB16Z_POFF,        0x0800000 },
348
        { FFB_SFB8Z_VOFF,       FFB_SFB8Z_POFF,         0x0800000 },
349
        { FFB_SFB422_VOFF,      FFB_SFB422_POFF,        0x0800000 },
350
        { FFB_SFB422D_VOFF,     FFB_SFB422D_POFF,       0x0800000 },
351
        { 0,                     0,                       0          }
352
};
353
 
354
static void ffb_setup(struct display *p)
355
{
356
        p->next_line = 8192;
357
        p->next_plane = 0;
358
}
359
 
360
static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
361
                      int height, int width)
362
{
363
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
364
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
365
        unsigned long flags;
366
        u64 yx, hw;
367
        int fg;
368
 
369
        spin_lock_irqsave(&fb->lock, flags);
370
        fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
371
        if (fg != fb->s.ffb.fg_cache) {
372
                FFBFifo(fb, 5);
373
                upa_writel(fg, &fbc->fg);
374
                fb->s.ffb.fg_cache = fg;
375
        } else
376
                FFBFifo(fb, 4);
377
 
378
        if (fontheightlog(p)) {
379
                yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
380
        } else {
381
                yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
382
        }
383
        if (fontwidthlog(p)) {
384
                yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
385
        } else {
386
                yx += sx * fontwidth(p); hw += width * fontwidth(p);
387
        }
388
        upa_writeq(yx + fb->s.ffb.yx_margin, &fbc->by);
389
        upa_writeq(hw, &fbc->bh);
390
        spin_unlock_irqrestore(&fb->lock, flags);
391
}
392
 
393
static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
394
                     int count, unsigned short *boxes)
395
{
396
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
397
        unsigned long flags;
398
        int fg;
399
 
400
        spin_lock_irqsave(&fb->lock, flags);
401
        fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
402
        if (fg != fb->s.ffb.fg_cache) {
403
                FFBFifo(fb, 1);
404
                upa_writel(fg, &fbc->fg);
405
                fb->s.ffb.fg_cache = fg;
406
        }
407
        while (count-- > 0) {
408
                FFBFifo(fb, 4);
409
                upa_writel(boxes[1], &fbc->by);
410
                upa_writel(boxes[0], &fbc->bx);
411
                upa_writel(boxes[3] - boxes[1], &fbc->bh);
412
                upa_writel(boxes[2] - boxes[0], &fbc->bw);
413
                boxes += 4;
414
        }
415
        spin_unlock_irqrestore(&fb->lock, flags);
416
}
417
 
418
static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
419
{
420
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
421
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
422
        unsigned long flags;
423
        int i, xy;
424
        u8 *fd;
425
        u64 fgbg;
426
 
427
        spin_lock_irqsave(&fb->lock, flags);
428
        if (fontheightlog(p)) {
429
                xy = (yy << (16 + fontheightlog(p)));
430
                i = ((c & p->charmask) << fontheightlog(p));
431
        } else {
432
                xy = ((yy * fontheight(p)) << 16);
433
                i = (c & p->charmask) * fontheight(p);
434
        }
435
        if (fontwidth(p) <= 8)
436
                fd = p->fontdata + i;
437
        else
438
                fd = p->fontdata + (i << 1);
439
        if (fontwidthlog(p))
440
                xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
441
        else
442
                xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
443
        fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
444
               ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
445
        if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
446
                FFBFifo(fb, 2);
447
                upa_writeq(fgbg, &fbc->fg);
448
                *(u64 *)&fb->s.ffb.fg_cache = fgbg;
449
        }
450
        FFBFifo(fb, 2 + fontheight(p));
451
        upa_writel(xy, &fbc->fontxy);
452
        upa_writel(fontwidth(p), &fbc->fontw);
453
        if (fontwidth(p) <= 8) {
454
                for (i = 0; i < fontheight(p); i++) {
455
                        u32 val = *fd++ << 24;
456
 
457
                        upa_writel(val, &fbc->font);
458
                }
459
        } else {
460
                for (i = 0; i < fontheight(p); i++) {
461
                        u32 val = *(u16 *)fd << 16;
462
 
463
                        upa_writel(val, &fbc->font);
464
                        fd += 2;
465
                }
466
        }
467
        spin_unlock_irqrestore(&fb->lock, flags);
468
}
469
 
470
static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
471
                      int count, int yy, int xx)
472
{
473
        struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
474
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
475
        unsigned long flags;
476
        int i, xy;
477
        u8 *fd1, *fd2, *fd3, *fd4;
478
        u16 c;
479
        u64 fgbg;
480
 
481
        spin_lock_irqsave(&fb->lock, flags);
482
        c = scr_readw(s);
483
        fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p, c)])) << 32) |
484
               ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
485
        if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
486
                FFBFifo(fb, 2);
487
                upa_writeq(fgbg, &fbc->fg);
488
                *(u64 *)&fb->s.ffb.fg_cache = fgbg;
489
        }
490
        xy = fb->s.ffb.xy_margin;
491
        if (fontwidthlog(p))
492
                xy += (xx << fontwidthlog(p));
493
        else
494
                xy += xx * fontwidth(p);
495
        if (fontheightlog(p))
496
                xy += (yy << (16 + fontheightlog(p)));
497
        else
498
                xy += ((yy * fontheight(p)) << 16);
499
        if (fontwidth(p) <= 8) {
500
                while (count >= 4) {
501
                        count -= 4;
502
                        FFBFifo(fb, 2 + fontheight(p));
503
                        upa_writel(4 * fontwidth(p), &fbc->fontw);
504
                        upa_writel(xy, &fbc->fontxy);
505
                        if (fontheightlog(p)) {
506
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
507
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
508
                                fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
509
                                fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
510
                        } else {
511
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
512
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
513
                                fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
514
                                fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
515
                        }
516
                        if (fontwidth(p) == 8) {
517
                                for (i = 0; i < fontheight(p); i++) {
518
                                        u32 val;
519
 
520
                                        val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
521
                                                << 8)) << 8)) << 8);
522
                                        upa_writel(val, &fbc->font);
523
                                }
524
                                xy += 32;
525
                        } else {
526
                                for (i = 0; i < fontheight(p); i++) {
527
                                        u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
528
                                                << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
529
                                        upa_writel(val, &fbc->font);
530
                                }
531
                                xy += 4 * fontwidth(p);
532
                        }
533
                }
534
        } else {
535
                while (count >= 2) {
536
                        count -= 2;
537
                        FFBFifo(fb, 2 + fontheight(p));
538
                        upa_writel(2 * fontwidth(p), &fbc->fontw);
539
                        upa_writel(xy, &fbc->fontxy);
540
                        if (fontheightlog(p)) {
541
                                fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
542
                                fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
543
                        } else {
544
                                fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
545
                                fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
546
                        }
547
                        for (i = 0; i < fontheight(p); i++) {
548
                                u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
549
 
550
                                upa_writel(val, &fbc->font);
551
                                fd1 += 2; fd2 += 2;
552
                        }
553
                        xy += 2 * fontwidth(p);
554
                }
555
        }
556
        while (count) {
557
                count--;
558
                FFBFifo(fb, 2 + fontheight(p));
559
                upa_writel(fontwidth(p), &fbc->fontw);
560
                upa_writel(xy, &fbc->fontxy);
561
                if (fontheightlog(p))
562
                        i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
563
                else
564
                        i = ((scr_readw(s++) & p->charmask) * fontheight(p));
565
                if (fontwidth(p) <= 8) {
566
                        fd1 = p->fontdata + i;
567
                        for (i = 0; i < fontheight(p); i++) {
568
                                u32 val = *fd1++ << 24;
569
 
570
                                upa_writel(val, &fbc->font);
571
                        }
572
                } else {
573
                        fd1 = p->fontdata + (i << 1);
574
                        for (i = 0; i < fontheight(p); i++) {
575
                                u32 val = *(u16 *)fd1 << 16;
576
 
577
                                upa_writel(val, &fbc->font);
578
                                fd1 += 2;
579
                        }
580
                }
581
                xy += fontwidth(p);
582
        }
583
        spin_unlock_irqrestore(&fb->lock, flags);
584
}
585
 
586
static void ffb_revc(struct display *p, int xx, int yy)
587
{
588
        /* Not used if hw cursor */
589
}
590
 
591
#if 0
592
static void ffb_blank(struct fb_info_sbusfb *fb)
593
{
594
        struct ffb_dac *dac = fb->s.ffb.dac;
595
        unsigned long flags;
596
        u32 tmp;
597
 
598
        spin_lock_irqsave(&fb->lock, flags);
599
        upa_writel(0x6000, &dac->type);
600
        tmp = (upa_readl(&dac->value) & ~0x1);
601
        upa_writel(0x6000, &dac->type);
602
        upa_writel(tmp, &dac->value);
603
        spin_unlock_irqrestore(&fb->lock, flags);
604
}
605
#endif
606
 
607
static void ffb_unblank(struct fb_info_sbusfb *fb)
608
{
609
        struct ffb_dac *dac = fb->s.ffb.dac;
610
        unsigned long flags;
611
        u32 tmp;
612
 
613
        spin_lock_irqsave(&fb->lock, flags);
614
        upa_writel(0x6000, &dac->type);
615
        tmp = (upa_readl(&dac->value) | 0x1);
616
        upa_writel(0x6000, &dac->type);
617
        upa_writel(tmp, &dac->value);
618
        spin_unlock_irqrestore(&fb->lock, flags);
619
}
620
 
621
static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
622
{
623
        struct ffb_dac *dac = fb->s.ffb.dac;
624
        unsigned long flags;
625
        int i, j = count;
626
 
627
        spin_lock_irqsave(&fb->lock, flags);
628
        upa_writel(0x2000 | index, &dac->type);
629
        for (i = index; j--; i++) {
630
                u32 val;
631
 
632
                /* Feed the colors in :)) */
633
                val = ((fb->color_map CM(i,0))) |
634
                        ((fb->color_map CM(i,1)) << 8) |
635
                        ((fb->color_map CM(i,2)) << 16);
636
                upa_writel(val, &dac->value);
637
        }
638
        if (!p)
639
                goto out;
640
        for (i = index, j = count; i < 16 && j--; i++)
641
                ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
642
                                             ((fb->color_map CM(i,1)) << 8) |
643
                                             ((fb->color_map CM(i,2)) << 16);
644
out:
645
        spin_unlock_irqrestore(&fb->lock, flags);
646
}
647
 
648
static struct display_switch ffb_dispsw __initdata = {
649
        setup:          ffb_setup,
650
        bmove:          fbcon_redraw_bmove,
651
        clear:          ffb_clear,
652
        putc:           ffb_putc,
653
        putcs:          ffb_putcs,
654
        revc:           ffb_revc,
655
        fontwidthmask:  FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
656
};
657
 
658
static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
659
{
660
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
661
        unsigned long flags;
662
 
663
        spin_lock_irqsave(&fb->lock, flags);
664
        fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
665
        fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
666
        p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
667
        FFBWait(fbc);
668
        spin_unlock_irqrestore(&fb->lock, flags);
669
}
670
 
671
static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
672
{
673
        struct ffb_dac *dac = fb->s.ffb.dac;
674
        u32 val;
675
 
676
        upa_writel(0x100, &dac->type2);
677
        if (fb->s.ffb.dac_rev <= 2) {
678
                val = enable ? 3 : 0;
679
        } else {
680
                val = enable ? 0 : 3;
681
        }
682
        upa_writel(val, &dac->value2);
683
}
684
 
685
static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
686
{
687
        struct ffb_dac *dac = fb->s.ffb.dac;
688
        unsigned long flags;
689
 
690
        spin_lock_irqsave(&fb->lock, flags);
691
        __ffb_curs_enable (fb, 0);
692
        upa_writel(0x102, &dac->type2);
693
        upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2);
694
        upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2);
695
        spin_unlock_irqrestore(&fb->lock, flags);
696
}
697
 
698
/* Set cursor shape */
699
static void ffb_setcurshape (struct fb_info_sbusfb *fb)
700
{
701
        struct ffb_dac *dac = fb->s.ffb.dac;
702
        unsigned long flags;
703
        int i, j;
704
 
705
        spin_lock_irqsave(&fb->lock, flags);
706
        __ffb_curs_enable (fb, 0);
707
        for (j = 0; j < 2; j++) {
708
                u32 val = j ? 0 : 0x80;
709
 
710
                upa_writel(val, &dac->type2);
711
                for (i = 0; i < 0x40; i++) {
712
                        if (fb->cursor.size.fbx <= 32) {
713
                                upa_writel(fb->cursor.bits [j][i], &dac->value2);
714
                                upa_writel(0, &dac->value2);
715
                        } else {
716
                                upa_writel(fb->cursor.bits [j][2*i], &dac->value2);
717
                                upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2);
718
                        }
719
                }
720
        }
721
        spin_unlock_irqrestore(&fb->lock, flags);
722
}
723
 
724
/* Load cursor information */
725
static void ffb_setcursor (struct fb_info_sbusfb *fb)
726
{
727
        struct ffb_dac *dac = fb->s.ffb.dac;
728
        struct cg_cursor *c = &fb->cursor;
729
        unsigned long flags;
730
        u32 val;
731
 
732
        spin_lock_irqsave(&fb->lock, flags);
733
        upa_writel(0x104, &dac->type2);
734
        /* Should this be just 0x7ff??
735
           Should I do some margin handling and setcurshape in that case? */
736
        val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
737
                |((c->cpos.fbx - c->chot.fbx) & 0xffff);
738
        upa_writel(val, &dac->value2);
739
        __ffb_curs_enable (fb, fb->cursor.enable);
740
        spin_unlock_irqrestore(&fb->lock, flags);
741
}
742
 
743
static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
744
{
745
        register struct ffb_fbc *fbc = fb->s.ffb.fbc;
746
        unsigned long flags;
747
 
748
        spin_lock_irqsave(&fb->lock, flags);
749
        FFBWait(fbc);
750
        fb->s.ffb.fifo_cache = 0;
751
        FFBFifo(fb, 8);
752
        upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
753
                   FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
754
                   &fbc->ppc);
755
        upa_writel(0x2000707f, &fbc->fbc);
756
        upa_writel(FFB_ROP_NEW, &fbc->rop);
757
        upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
758
        upa_writel(0xffffffff, &fbc->pmask);
759
        upa_writel(0x10000, &fbc->fontinc);
760
        upa_writel(fb->s.ffb.fg_cache, &fbc->fg);
761
        upa_writel(fb->s.ffb.bg_cache, &fbc->bg);
762
        FFBWait(fbc);
763
        spin_unlock_irqrestore(&fb->lock, flags);
764
}
765
 
766
static int __init ffb_rasterimg (struct fb_info *info, int start)
767
{
768
        ffb_switch_from_graph (sbusfbinfo(info));
769
        return 0;
770
}
771
 
772
static char idstring[60] __initdata = { 0 };
773
 
774
static int __init creator_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs)
775
{
776
        struct linux_prom64_ranges ranges[PROMREG_MAX];
777
        char name[128];
778
        int len, i;
779
 
780
        prom_getproperty(parent, "name", name, sizeof(name));
781
        if (strcmp(name, "upa") != 0)
782
                return 0;
783
 
784
        len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));
785
        if (len <= 0)
786
                return 1;
787
 
788
        len /= sizeof(struct linux_prom64_ranges);
789
        for (i = 0; i < len; i++) {
790
                struct linux_prom64_ranges *rng = &ranges[i];
791
                u64 phys_addr = regs->phys_addr;
792
 
793
                if (phys_addr >= rng->ot_child_base &&
794
                    phys_addr < (rng->ot_child_base + rng->or_size)) {
795
                        regs->phys_addr -= rng->ot_child_base;
796
                        regs->phys_addr += rng->ot_parent_base;
797
                        return 0;
798
                }
799
        }
800
 
801
        return 1;
802
}
803
 
804
char __init *creatorfb_init(struct fb_info_sbusfb *fb)
805
{
806
        struct fb_fix_screeninfo *fix = &fb->fix;
807
        struct fb_var_screeninfo *var = &fb->var;
808
        struct display *disp = &fb->disp;
809
        struct fbtype *type = &fb->type;
810
        struct linux_prom64_registers regs[2*PROMREG_MAX];
811
        int i, afb = 0;
812
        unsigned int btype;
813
        char name[64];
814
        struct fb_ops *fbops;
815
 
816
        if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
817
                return NULL;
818
 
819
        if (creator_apply_upa_parent_ranges(fb->prom_parent, &regs[0]))
820
                return NULL;
821
 
822
        disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
823
        if (disp->dispsw_data == NULL)
824
                return NULL;
825
        memset(disp->dispsw_data, 0, 16 * sizeof(u32));
826
 
827
        fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
828
        if (fbops == NULL) {
829
                kfree(disp->dispsw_data);
830
                return NULL;
831
        }
832
 
833
        *fbops = *fb->info.fbops;
834
        fbops->fb_rasterimg = ffb_rasterimg;
835
        fb->info.fbops = fbops;
836
 
837
        prom_getstring(fb->prom_node, "name", name, sizeof(name));
838
        if (!strcmp(name, "SUNW,afb"))
839
                afb = 1;
840
 
841
        btype = prom_getintdefault(fb->prom_node, "board_type", 0);
842
 
843
        strcpy(fb->info.modename, "Creator");
844
        if (!afb) {
845
                if ((btype & 7) == 3)
846
                    strcpy(fix->id, "Creator 3D");
847
                else
848
                    strcpy(fix->id, "Creator");
849
        } else
850
                strcpy(fix->id, "Elite 3D");
851
 
852
        fix->visual = FB_VISUAL_TRUECOLOR;
853
        fix->line_length = 8192;
854
        fix->accel = FB_ACCEL_SUN_CREATOR;
855
 
856
        var->bits_per_pixel = 32;
857
        var->green.offset = 8;
858
        var->blue.offset = 16;
859
        var->accel_flags = FB_ACCELF_TEXT;
860
 
861
        disp->scrollmode = SCROLL_YREDRAW;
862
        disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
863
        fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
864
        fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
865
        fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
866
        fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
867
        fb->dispsw = ffb_dispsw;
868
 
869
        fb->margins = ffb_margins;
870
        fb->loadcmap = ffb_loadcmap;
871
        fb->setcursor = ffb_setcursor;
872
        fb->setcursormap = ffb_setcursormap;
873
        fb->setcurshape = ffb_setcurshape;
874
        fb->switch_from_graph = ffb_switch_from_graph;
875
        fb->fill = ffb_fill;
876
#if 0
877
        /* XXX Can't enable this for now, I've seen cases
878
         * XXX where the VC was blanked, and Xsun24 was started
879
         * XXX via a remote login, the sunfb code did not
880
         * XXX unblank creator when it was mmap'd for some
881
         * XXX reason, investigate later... -DaveM
882
         */
883
        fb->blank = ffb_blank;
884
        fb->unblank = ffb_unblank;
885
#endif
886
 
887
        /* If there are any read errors or fifo overflow conditions,
888
         * clear them now.
889
         */
890
        if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
891
                upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr);
892
 
893
        ffb_switch_from_graph(fb);
894
 
895
        fb->physbase = regs[0].phys_addr;
896
        fb->mmap_map = ffb_mmap_map;
897
 
898
        fb->cursor.hwsize.fbx = 64;
899
        fb->cursor.hwsize.fby = 64;
900
 
901
        type->fb_depth = 24;
902
 
903
        upa_writel(0x8000, &fb->s.ffb.dac->type);
904
        fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c);
905
 
906
        i = prom_getintdefault (fb->prom_node, "board_type", 8);
907
 
908
        sprintf(idstring, "%s at %016lx type %d DAC %d",
909
                fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
910
 
911
        /* Elite3D has different DAC revision numbering, and no DAC revisions
912
           have the reversed meaning of cursor enable */
913
        if (afb)
914
                fb->s.ffb.dac_rev = 10;
915
 
916
        /* Unblank it just to be sure.  When there are multiple
917
         * FFB/AFB cards in the system, or it is not the OBP
918
         * chosen console, it will have video outputs off in
919
         * the DAC.
920
         */
921
        ffb_unblank(fb);
922
 
923
        return idstring;
924
}
925
 
926
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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