setup enviroment for compilation
[linux-2.4.21-pre4.git] / drivers / video / cgfourteenfb.c
1 /* $Id: cgfourteenfb.c,v 1.1.1.1 2005/04/11 02:50:41 jack Exp $
2  * cgfourteenfb.c: CGfourteen frame buffer driver
3  *
4  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
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 #include <asm/pgtable.h>
26 #include <asm/uaccess.h>
27
28 #include <video/fbcon-cfb8.h>
29
30 #define CG14_MCR_INTENABLE_SHIFT        7
31 #define CG14_MCR_INTENABLE_MASK         0x80
32 #define CG14_MCR_VIDENABLE_SHIFT        6
33 #define CG14_MCR_VIDENABLE_MASK         0x40
34 #define CG14_MCR_PIXMODE_SHIFT          4
35 #define CG14_MCR_PIXMODE_MASK           0x30
36 #define CG14_MCR_TMR_SHIFT              2
37 #define CG14_MCR_TMR_MASK               0x0c
38 #define CG14_MCR_TMENABLE_SHIFT         1
39 #define CG14_MCR_TMENABLE_MASK          0x02
40 #define CG14_MCR_RESET_SHIFT            0
41 #define CG14_MCR_RESET_MASK             0x01
42 #define CG14_REV_REVISION_SHIFT         4
43 #define CG14_REV_REVISION_MASK          0xf0
44 #define CG14_REV_IMPL_SHIFT             0
45 #define CG14_REV_IMPL_MASK              0x0f
46 #define CG14_VBR_FRAMEBASE_SHIFT        12
47 #define CG14_VBR_FRAMEBASE_MASK         0x00fff000
48 #define CG14_VMCR1_SETUP_SHIFT          0
49 #define CG14_VMCR1_SETUP_MASK           0x000001ff
50 #define CG14_VMCR1_VCONFIG_SHIFT        9
51 #define CG14_VMCR1_VCONFIG_MASK         0x00000e00
52 #define CG14_VMCR2_REFRESH_SHIFT        0
53 #define CG14_VMCR2_REFRESH_MASK         0x00000001
54 #define CG14_VMCR2_TESTROWCNT_SHIFT     1
55 #define CG14_VMCR2_TESTROWCNT_MASK      0x00000002
56 #define CG14_VMCR2_FBCONFIG_SHIFT       2
57 #define CG14_VMCR2_FBCONFIG_MASK        0x0000000c
58 #define CG14_VCR_REFRESHREQ_SHIFT       0
59 #define CG14_VCR_REFRESHREQ_MASK        0x000003ff
60 #define CG14_VCR1_REFRESHENA_SHIFT      10
61 #define CG14_VCR1_REFRESHENA_MASK       0x00000400
62 #define CG14_VCA_CAD_SHIFT              0
63 #define CG14_VCA_CAD_MASK               0x000003ff
64 #define CG14_VCA_VERS_SHIFT             10
65 #define CG14_VCA_VERS_MASK              0x00000c00
66 #define CG14_VCA_RAMSPEED_SHIFT         12
67 #define CG14_VCA_RAMSPEED_MASK          0x00001000
68 #define CG14_VCA_8MB_SHIFT              13
69 #define CG14_VCA_8MB_MASK               0x00002000
70
71 #define CG14_MCR_PIXMODE_8              0
72 #define CG14_MCR_PIXMODE_16             2
73 #define CG14_MCR_PIXMODE_32             3
74
75 MODULE_LICENSE("GPL");
76
77 struct cg14_regs{
78         volatile u8 mcr;        /* Master Control Reg */
79         volatile u8 ppr;        /* Packed Pixel Reg */
80         volatile u8 tms[2];     /* Test Mode Status Regs */
81         volatile u8 msr;        /* Master Status Reg */
82         volatile u8 fsr;        /* Fault Status Reg */
83         volatile u8 rev;        /* Revision & Impl */
84         volatile u8 ccr;        /* Clock Control Reg */
85         volatile u32 tmr;       /* Test Mode Read Back */
86         volatile u8 mod;        /* Monitor Operation Data Reg */
87         volatile u8 acr;        /* Aux Control */
88         u8 xxx0[6];
89         volatile u16 hct;       /* Hor Counter */
90         volatile u16 vct;       /* Vert Counter */
91         volatile u16 hbs;       /* Hor Blank Start */
92         volatile u16 hbc;       /* Hor Blank Clear */
93         volatile u16 hss;       /* Hor Sync Start */
94         volatile u16 hsc;       /* Hor Sync Clear */
95         volatile u16 csc;       /* Composite Sync Clear */
96         volatile u16 vbs;       /* Vert Blank Start */
97         volatile u16 vbc;       /* Vert Blank Clear */
98         volatile u16 vss;       /* Vert Sync Start */
99         volatile u16 vsc;       /* Vert Sync Clear */
100         volatile u16 xcs;
101         volatile u16 xcc;
102         volatile u16 fsa;       /* Fault Status Address */
103         volatile u16 adr;       /* Address Registers */
104         u8 xxx1[0xce];
105         volatile u8 pcg[0x100]; /* Pixel Clock Generator */
106         volatile u32 vbr;       /* Frame Base Row */
107         volatile u32 vmcr;      /* VBC Master Control */
108         volatile u32 vcr;       /* VBC refresh */
109         volatile u32 vca;       /* VBC Config */
110 };
111
112 #define CG14_CCR_ENABLE 0x04
113 #define CG14_CCR_SELECT 0x02    /* HW/Full screen */
114
115 struct cg14_cursor {
116         volatile u32 cpl0[32];  /* Enable plane 0 */
117         volatile u32 cpl1[32];  /* Color selection plane */
118         volatile u8 ccr;        /* Cursor Control Reg */
119         u8 xxx0[3];
120         volatile u16 cursx;     /* Cursor x,y position */
121         volatile u16 cursy;     /* Cursor x,y position */
122         volatile u32 color0;
123         volatile u32 color1;
124         u32 xxx1[0x1bc];
125         volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */
126         volatile u32 cpl1i[32]; /* Color selection autoinc */
127 };
128
129 struct cg14_dac {
130         volatile u8 addr;       /* Address Register */
131         u8 xxx0[255];
132         volatile u8 glut;       /* Gamma table */
133         u8 xxx1[255];
134         volatile u8 select;     /* Register Select */
135         u8 xxx2[255];
136         volatile u8 mode;       /* Mode Register */
137 };
138
139 struct cg14_xlut{
140         volatile u8 x_xlut [256];
141         volatile u8 x_xlutd [256];
142         u8 xxx0[0x600];
143         volatile u8 x_xlut_inc [256];
144         volatile u8 x_xlutd_inc [256];
145 };
146
147 /* Color look up table (clut) */
148 /* Each one of these arrays hold the color lookup table (for 256
149  * colors) for each MDI page (I assume then there should be 4 MDI
150  * pages, I still wonder what they are.  I have seen NeXTStep split
151  * the screen in four parts, while operating in 24 bits mode.  Each
152  * integer holds 4 values: alpha value (transparency channel, thanks
153  * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
154  *
155  * I currently use the clut instead of the Xlut
156  */
157 struct cg14_clut {
158         u32 c_clut [256];
159         u32 c_clutd [256];    /* i wonder what the 'd' is for */
160         u32 c_clut_inc [256];
161         u32 c_clutd_inc [256];
162 };
163
164 static struct sbus_mmap_map cg14_mmap_map[] __initdata = {
165         { CG14_REGS,            0x80000000,             0x1000              },
166         { CG14_XLUT,            0x80003000,             0x1000              },
167         { CG14_CLUT1,           0x80004000,             0x1000              },
168         { CG14_CLUT2,           0x80005000,             0x1000              },
169         { CG14_CLUT3,           0x80006000,             0x1000              },
170         { CG3_MMAP_OFFSET - 
171           0x7000,               0x80000000,             0x7000              },
172         { CG3_MMAP_OFFSET,      0x00000000,             SBUS_MMAP_FBSIZE(1) },
173         { MDI_CURSOR_MAP,       0x80001000,             0x1000              },
174         { MDI_CHUNKY_BGR_MAP,   0x01000000,             0x400000            },
175         { MDI_PLANAR_X16_MAP,   0x02000000,             0x200000            },
176         { MDI_PLANAR_C16_MAP,   0x02800000,             0x200000            },
177         { MDI_PLANAR_X32_MAP,   0x03000000,             0x100000            },
178         { MDI_PLANAR_B32_MAP,   0x03400000,             0x100000            },
179         { MDI_PLANAR_G32_MAP,   0x03800000,             0x100000            },
180         { MDI_PLANAR_R32_MAP,   0x03c00000,             0x100000            },
181         { 0,                    0,                      0                   }
182 };
183
184 static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p,
185                            int index, int count)
186 {
187         struct cg14_clut *clut = fb->s.cg14.clut;
188         unsigned long flags;
189                 
190         spin_lock_irqsave(&fb->lock, flags);
191         for (; count--; index++) {
192                 u32 val;
193
194                 val = ((fb->color_map CM(index,2) << 16) |
195                        (fb->color_map CM(index,1) << 8) |
196                        (fb->color_map CM(index,0)));
197                 sbus_writel(val, &clut->c_clut[index]);
198         }
199         spin_unlock_irqrestore(&fb->lock, flags);
200 }
201
202 static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p,
203                           int x_margin, int y_margin)
204 {
205         p->screen_base += (y_margin - fb->y_margin) *
206                 p->line_length + (x_margin - fb->x_margin);
207 }
208
209 static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
210 {
211         struct cg14_cursor *cur = fb->s.cg14.cursor;
212         unsigned long flags;
213         
214         spin_lock_irqsave(&fb->lock, flags);
215         sbus_writel(((red[0]) | (green[0] << 8) | (blue[0] << 16)), &cur->color0);
216         sbus_writel(((red[1]) | (green[1] << 8) | (blue[1] << 16)), &cur->color1);
217         spin_unlock_irqrestore(&fb->lock, flags);
218 }
219
220 /* Set cursor shape */
221 static void cg14_setcurshape (struct fb_info_sbusfb *fb)
222 {
223         struct cg14_cursor *cur = fb->s.cg14.cursor;
224         unsigned long flags;
225         int i;
226
227         spin_lock_irqsave(&fb->lock, flags);
228         for (i = 0; i < 32; i++){
229                 sbus_writel(fb->cursor.bits[0][i], &cur->cpl0[i]);
230                 sbus_writel(fb->cursor.bits[1][i], &cur->cpl1[i]);
231         }
232         spin_unlock_irqrestore(&fb->lock, flags);
233 }
234
235 /* Load cursor information */
236 static void cg14_setcursor (struct fb_info_sbusfb *fb)
237 {
238         struct cg_cursor *c = &fb->cursor;
239         struct cg14_cursor *cur = fb->s.cg14.cursor;
240         unsigned long flags;
241                 
242         spin_lock_irqsave(&fb->lock, flags);
243         if (c->enable) {
244                 u8 tmp = sbus_readb(&cur->ccr);
245
246                 tmp |= CG14_CCR_ENABLE;
247                 sbus_writeb(tmp, &cur->ccr);
248         } else {
249                 u8 tmp = sbus_readb(&cur->ccr);
250
251                 tmp &= ~CG14_CCR_ENABLE;
252                 sbus_writeb(tmp, &cur->ccr);
253         }
254         sbus_writew(((c->cpos.fbx - c->chot.fbx) & 0xfff), &cur->cursx);
255         sbus_writew(((c->cpos.fby - c->chot.fby) & 0xfff), &cur->cursy);
256         spin_unlock_irqrestore(&fb->lock, flags);
257 }
258
259 static void cg14_switch_from_graph (struct fb_info_sbusfb *fb)
260 {
261         unsigned long flags;
262
263         spin_lock_irqsave(&fb->lock, flags);
264
265         /* Set the 8-bpp mode */
266         if (fb->open && fb->mmaped){
267                 volatile char *mcr = &fb->s.cg14.regs->mcr;
268                 char tmp;
269                                         
270                 fb->s.cg14.mode = 8;
271                 tmp = sbus_readb(mcr);
272                 tmp &= ~(CG14_MCR_PIXMODE_MASK);
273                 sbus_writeb(tmp, mcr);
274         }
275         spin_unlock_irqrestore(&fb->lock, flags);
276 }
277
278 static void cg14_reset (struct fb_info_sbusfb *fb)
279 {
280         volatile char *mcr = &fb->s.cg14.regs->mcr;
281         unsigned long flags;
282         char tmp;
283                 
284         spin_lock_irqsave(&fb->lock, flags);
285         tmp = sbus_readb(mcr);
286         tmp &= ~(CG14_MCR_PIXMODE_MASK);
287         sbus_writeb(tmp, mcr);
288         spin_unlock_irqrestore(&fb->lock, flags);
289 }
290
291 static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg)
292 {
293         volatile char *mcr = &fb->s.cg14.regs->mcr;
294         struct mdi_cfginfo *mdii;
295         unsigned long flags;
296         int mode, ret = 0;
297         char tmp;
298                 
299         switch (cmd) {
300         case MDI_RESET:
301                 spin_lock_irqsave(&fb->lock, flags);
302                 tmp = sbus_readb(mcr);
303                 tmp &= ~CG14_MCR_PIXMODE_MASK;
304                 sbus_writeb(tmp, mcr);
305                 spin_unlock_irqrestore(&fb->lock, flags);
306                 break;
307         case MDI_GET_CFGINFO:
308                 mdii = (struct mdi_cfginfo *)arg;
309                 if (put_user(FBTYPE_MDICOLOR, &mdii->mdi_type) ||
310                     __put_user(fb->type.fb_height, &mdii->mdi_height) ||
311                     __put_user(fb->type.fb_width, &mdii->mdi_width) ||
312                     __put_user(fb->s.cg14.mode, &mdii->mdi_mode) ||
313                     __put_user(72, &mdii->mdi_pixfreq) || /* FIXME */
314                     __put_user(fb->s.cg14.ramsize, &mdii->mdi_size))
315                         return -EFAULT;
316                 break;
317         case MDI_SET_PIXELMODE:
318                 if (get_user(mode, (int *)arg))
319                         return -EFAULT;
320
321                 spin_lock_irqsave(&fb->lock, flags);
322                 tmp = sbus_readb(mcr);
323                 switch (mode){
324                 case MDI_32_PIX:
325                         tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) |
326                                 (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT);
327                         break;
328                 case MDI_16_PIX:
329                         tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | 0x20;
330                         break;
331                 case MDI_8_PIX:
332                         tmp = (tmp & ~CG14_MCR_PIXMODE_MASK);
333                         break;
334                 default:
335                         ret = -ENOSYS;
336                         break;
337                 };
338                 if (ret == 0) {
339                         sbus_writeb(tmp, mcr);
340                         fb->s.cg14.mode = mode;
341                 }
342                 spin_unlock_irqrestore(&fb->lock, flags);
343                 break;
344         default:
345                 ret = -EINVAL;
346         };
347
348         return ret;
349 }
350
351 static unsigned long __init get_phys(unsigned long addr)
352 {
353         return __get_phys(addr);
354 }
355
356 static int __init get_iospace(unsigned long addr)
357 {
358         return __get_iospace(addr);
359 }
360
361 static char idstring[60] __initdata = { 0 };
362
363 char __init *cgfourteenfb_init(struct fb_info_sbusfb *fb)
364 {
365         struct fb_fix_screeninfo *fix = &fb->fix;
366         struct display *disp = &fb->disp;
367         struct fbtype *type = &fb->type;
368         unsigned long rphys, phys;
369         u32 bases[6];
370         int is_8mb, i;
371
372 #ifndef FBCON_HAS_CFB8
373         return NULL;
374 #endif
375         prom_getproperty (fb->prom_node, "address", (char *) &bases[0], 8);
376         if (!bases[0]) {
377                 printk("cg14 not mmaped\n");
378                 return NULL;
379         }
380         if (get_iospace(bases[0]) != get_iospace(bases[1])) {
381                 printk("Ugh. cg14 iospaces don't match\n");
382                 return NULL;
383         }
384         fb->physbase = phys = get_phys(bases[1]);
385         rphys = get_phys(bases[0]);
386         fb->iospace = get_iospace(bases[0]);
387         fb->s.cg14.regs = (struct cg14_regs *)(unsigned long)bases[0];
388         fb->s.cg14.clut = (void *)((unsigned long)bases[0]+CG14_CLUT1);
389         fb->s.cg14.cursor = (void *)((unsigned long)bases[0]+CG14_CURSORREGS);
390         disp->screen_base = (char *)bases[1];
391         
392         /* CG14_VCA_8MB_MASK is not correctly set on the 501-2482
393          * VSIMM, so we read the memory size from the PROM
394          */
395         prom_getproperty(fb->prom_node, "reg", (char *) &bases[0], 24);
396         is_8mb = bases[5] == 0x800000;
397
398         fb->mmap_map = kmalloc(sizeof(cg14_mmap_map), GFP_KERNEL);
399         if (!fb->mmap_map)
400                 return NULL;
401
402         for (i = 0; ; i++) {
403                 fb->mmap_map[i].voff = cg14_mmap_map[i].voff;
404                 fb->mmap_map[i].poff = (cg14_mmap_map[i].poff & 0x80000000) ?
405                                        (cg14_mmap_map[i].poff & 0x7fffffff) + rphys - phys :
406                                        cg14_mmap_map[i].poff;
407                 fb->mmap_map[i].size = cg14_mmap_map[i].size;
408                 if (is_8mb && fb->mmap_map[i].size >= 0x100000 &&
409                     fb->mmap_map[i].size <= 0x400000)
410                         fb->mmap_map[i].size <<= 1;
411                 if (!cg14_mmap_map[i].size)
412                         break;
413         }
414
415         strcpy(fb->info.modename, "CGfourteen");
416         strcpy(fix->id, "CGfourteen");
417         fix->line_length = fb->var.xres_virtual;
418         fix->accel = FB_ACCEL_SUN_CG14;
419         
420         disp->scrollmode = SCROLL_YREDRAW;
421         disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
422         fb->dispsw = fbcon_cfb8;
423         
424         type->fb_depth = 24;
425         fb->emulations[1] = FBTYPE_SUN3COLOR;
426
427         fb->margins = cg14_margins;
428         fb->loadcmap = cg14_loadcmap;
429         fb->setcursor = cg14_setcursor;
430         fb->setcursormap = cg14_setcursormap;
431         fb->setcurshape = cg14_setcurshape;
432         fb->reset = cg14_reset;
433         fb->switch_from_graph = cg14_switch_from_graph;
434         fb->ioctl = cg14_ioctl;
435
436         fb->s.cg14.mode = 8;
437         fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000;
438         
439         cg14_reset(fb);
440         
441         sprintf(idstring, "cgfourteen at %x.%08lx, %dMB, rev=%d, impl=%d", fb->iospace, phys,
442                 is_8mb ? 8 : 4, fb->s.cg14.regs->rev >> 4, fb->s.cg14.regs->rev & 0xf);
443         
444         return idstring;
445 }