ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / video / sgivwfb.c
1 /*
2  *  linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
3  *
4  *      Copyright (C) 1999 Silicon Graphics, Inc.
5  *      Jeffrey Newquist, newquist@engr.sgi.som
6  *
7  *  This file is subject to the terms and conditions of the GNU General Public
8  *  License. See the file COPYING in the main directory of this archive for
9  *  more details.
10  */
11
12 #include <linux/config.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/errno.h>
17 #include <linux/delay.h>
18 #include <linux/fb.h>
19 #include <linux/init.h>
20 #include <linux/ioport.h>
21 #include <asm/io.h>
22 #include <asm/mtrr.h>
23
24 #define INCLUDE_TIMING_TABLE_DATA
25 #define DBE_REG_BASE default_par.regs
26 #include <video/sgivw.h>
27
28 struct sgivw_par {
29         struct asregs *regs;
30         u32 cmap_fifo;
31         u_long timing_num;
32 };
33
34 #define FLATPANEL_SGI_1600SW    5
35
36 /*
37  *  RAM we reserve for the frame buffer. This defines the maximum screen
38  *  size
39  *
40  *  The default can be overridden if the driver is compiled as a module
41  */
42
43 /* set by arch/i386/kernel/setup.c */
44 extern unsigned long sgivwfb_mem_phys;
45 extern unsigned long sgivwfb_mem_size;
46
47 static struct sgivw_par default_par;
48 static u32 pseudo_palette[17];
49 static struct fb_info fb_info;
50 static int ypan = 0;
51 static int ywrap = 0;
52
53 static int flatpanel_id = -1;
54
55 static struct fb_fix_screeninfo sgivwfb_fix __initdata = {
56         .id             = "SGI Vis WS FB",
57         .type           = FB_TYPE_PACKED_PIXELS,
58         .visual         = FB_VISUAL_PSEUDOCOLOR,
59         .mmio_start     = DBE_REG_PHYS,
60         .mmio_len       = DBE_REG_SIZE,
61         .accel          = FB_ACCEL_NONE,
62         .line_length    = 640,
63 };
64
65 static struct fb_var_screeninfo sgivwfb_var __initdata = {
66         /* 640x480, 8 bpp */
67         .xres           = 640,
68         .yres           = 480,
69         .xres_virtual   = 640,
70         .yres_virtual   = 480,
71         .bits_per_pixel = 8,
72         .red            = { 0, 8, 0 },
73         .green          = { 0, 8, 0 },
74         .blue           = { 0, 8, 0 },
75         .height         = -1,
76         .width          = -1,
77         .pixclock       = 20000,
78         .left_margin    = 64,
79         .right_margin   = 64,
80         .upper_margin   = 32,
81         .lower_margin   = 32,
82         .hsync_len      = 64,
83         .vsync_len      = 2,
84         .vmode          = FB_VMODE_NONINTERLACED
85 };
86
87 static struct fb_var_screeninfo sgivwfb_var1600sw __initdata = {
88         /* 1600x1024, 8 bpp */
89         .xres           = 1600,
90         .yres           = 1024,
91         .xres_virtual   = 1600,
92         .yres_virtual   = 1024,
93         .bits_per_pixel = 8,
94         .red            = { 0, 8, 0 },
95         .green          = { 0, 8, 0 },
96         .blue           = { 0, 8, 0 },
97         .height         = -1,
98         .width          = -1,
99         .pixclock       = 9353,
100         .left_margin    = 20,
101         .right_margin   = 30,
102         .upper_margin   = 37,
103         .lower_margin   = 3,
104         .hsync_len      = 20,
105         .vsync_len      = 3,
106         .vmode          = FB_VMODE_NONINTERLACED
107 };
108
109 /*
110  *  Interface used by the world
111  */
112 int sgivwfb_init(void);
113
114 static int sgivwfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
115 static int sgivwfb_set_par(struct fb_info *info);
116 static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
117                              u_int blue, u_int transp,
118                              struct fb_info *info);
119 static int sgivwfb_mmap(struct fb_info *info, struct file *file,
120                         struct vm_area_struct *vma);
121
122 static struct fb_ops sgivwfb_ops = {
123         .owner          = THIS_MODULE,
124         .fb_check_var   = sgivwfb_check_var,
125         .fb_set_par     = sgivwfb_set_par,
126         .fb_setcolreg   = sgivwfb_setcolreg,
127         .fb_fillrect    = cfb_fillrect,
128         .fb_copyarea    = cfb_copyarea,
129         .fb_imageblit   = cfb_imageblit,
130         .fb_cursor      = soft_cursor,
131         .fb_mmap        = sgivwfb_mmap,
132 };
133
134 /*
135  *  Internal routines
136  */
137 static unsigned long bytes_per_pixel(int bpp)
138 {
139         switch (bpp) {
140                 case 8:
141                         return 1;
142                 case 16:
143                         return 2;
144                 case 32:
145                         return 4;
146                 default:
147                         printk(KERN_INFO "sgivwfb: unsupported bpp %d\n", bpp);
148                         return 0;
149         }
150 }
151
152 static unsigned long get_line_length(int xres_virtual, int bpp)
153 {
154         return (xres_virtual * bytes_per_pixel(bpp));
155 }
156
157 /*
158  * Function:    dbe_TurnOffDma
159  * Parameters:  (None)
160  * Description: This should turn off the monitor and dbe.  This is used
161  *              when switching between the serial console and the graphics
162  *              console.
163  */
164
165 static void dbe_TurnOffDma(void)
166 {
167         unsigned int readVal;
168         int i;
169
170         // Check to see if things are already turned off:
171         // 1) Check to see if dbe is not using the internal dotclock.
172         // 2) Check to see if the xy counter in dbe is already off.
173
174         DBE_GETREG(ctrlstat, readVal);
175         if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
176                 return;
177
178         DBE_GETREG(vt_xy, readVal);
179         if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
180                 return;
181
182         // Otherwise, turn off dbe
183
184         DBE_GETREG(ovr_control, readVal);
185         SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
186         DBE_SETREG(ovr_control, readVal);
187         udelay(1000);
188         DBE_GETREG(frm_control, readVal);
189         SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
190         DBE_SETREG(frm_control, readVal);
191         udelay(1000);
192         DBE_GETREG(did_control, readVal);
193         SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
194         DBE_SETREG(did_control, readVal);
195         udelay(1000);
196
197         // XXX HACK:
198         //
199         //    This was necessary for GBE--we had to wait through two
200         //    vertical retrace periods before the pixel DMA was
201         //    turned off for sure.  I've left this in for now, in
202         //    case dbe needs it.
203
204         for (i = 0; i < 10000; i++) {
205                 DBE_GETREG(frm_inhwctrl, readVal);
206                 if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) ==
207                     0)
208                         udelay(10);
209                 else {
210                         DBE_GETREG(ovr_inhwctrl, readVal);
211                         if (GET_DBE_FIELD
212                             (OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
213                                 udelay(10);
214                         else {
215                                 DBE_GETREG(did_inhwctrl, readVal);
216                                 if (GET_DBE_FIELD
217                                     (DID_INHWCTRL, DID_DMA_ENABLE,
218                                      readVal) == 0)
219                                         udelay(10);
220                                 else
221                                         break;
222                         }
223                 }
224         }
225 }
226
227 /*
228  *  Set the User Defined Part of the Display. Again if par use it to get
229  *  real video mode.
230  */
231 static int sgivwfb_check_var(struct fb_var_screeninfo *var, 
232                              struct fb_info *info)
233 {
234         struct sgivw_par *par = (struct sgivw_par *)info->par;
235         struct dbe_timing_info *timing;
236         u_long line_length;
237         u_long min_mode;
238         int req_dot;
239         int test_mode;
240
241         /*
242          *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
243          *  as FB_VMODE_SMOOTH_XPAN is only used internally
244          */
245
246         if (var->vmode & FB_VMODE_CONUPDATE) {
247                 var->vmode |= FB_VMODE_YWRAP;
248                 var->xoffset = info->var.xoffset;
249                 var->yoffset = info->var.yoffset;
250         }
251
252         /* XXX FIXME - forcing var's */
253         var->xoffset = 0;
254         var->yoffset = 0;
255
256         /* Limit bpp to 8, 16, and 32 */
257         if (var->bits_per_pixel <= 8)
258                 var->bits_per_pixel = 8;
259         else if (var->bits_per_pixel <= 16)
260                 var->bits_per_pixel = 16;
261         else if (var->bits_per_pixel <= 32)
262                 var->bits_per_pixel = 32;
263         else
264                 return -EINVAL;
265
266         var->grayscale = 0;     /* No grayscale for now */
267
268         /* determine valid resolution and timing */
269         for (min_mode = 0; min_mode < DBE_VT_SIZE; min_mode++) {
270                 if (dbeVTimings[min_mode].width >= var->xres &&
271                     dbeVTimings[min_mode].height >= var->yres)
272                         break;
273         }
274
275         if (min_mode == DBE_VT_SIZE)
276                 return -EINVAL; /* Resolution to high */
277
278         /* XXX FIXME - should try to pick best refresh rate */
279         /* for now, pick closest dot-clock within 3MHz */
280         req_dot = PICOS2KHZ(var->pixclock);
281         printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n",
282                var->pixclock, req_dot);
283         test_mode = min_mode;
284         while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
285                 if (dbeVTimings[test_mode].cfreq + 3000 > req_dot)
286                         break;
287                 test_mode++;
288         }
289         if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
290                 test_mode--;
291         min_mode = test_mode;
292         timing = &dbeVTimings[min_mode];
293         printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
294
295         /* Adjust virtual resolution, if necessary */
296         if (var->xres > var->xres_virtual || (!ywrap && !ypan))
297                 var->xres_virtual = var->xres;
298         if (var->yres > var->yres_virtual || (!ywrap && !ypan))
299                 var->yres_virtual = var->yres;
300
301         /*
302          *  Memory limit
303          */
304         line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
305         if (line_length * var->yres_virtual > sgivwfb_mem_size)
306                 return -ENOMEM; /* Virtual resolution to high */
307
308         info->fix.line_length = line_length;
309
310         switch (var->bits_per_pixel) {
311         case 8:
312                 var->red.offset = 0;
313                 var->red.length = 8;
314                 var->green.offset = 0;
315                 var->green.length = 8;
316                 var->blue.offset = 0;
317                 var->blue.length = 8;
318                 var->transp.offset = 0;
319                 var->transp.length = 0;
320                 break;
321         case 16:                /* RGBA 5551 */
322                 var->red.offset = 11;
323                 var->red.length = 5;
324                 var->green.offset = 6;
325                 var->green.length = 5;
326                 var->blue.offset = 1;
327                 var->blue.length = 5;
328                 var->transp.offset = 0;
329                 var->transp.length = 0;
330                 break;
331         case 32:                /* RGB 8888 */
332                 var->red.offset = 0;
333                 var->red.length = 8;
334                 var->green.offset = 8;
335                 var->green.length = 8;
336                 var->blue.offset = 16;
337                 var->blue.length = 8;
338                 var->transp.offset = 24;
339                 var->transp.length = 8;
340                 break;
341         }
342         var->red.msb_right = 0;
343         var->green.msb_right = 0;
344         var->blue.msb_right = 0;
345         var->transp.msb_right = 0;
346
347         /* set video timing information */
348         var->pixclock = KHZ2PICOS(timing->cfreq);
349         var->left_margin = timing->htotal - timing->hsync_end;
350         var->right_margin = timing->hsync_start - timing->width;
351         var->upper_margin = timing->vtotal - timing->vsync_end;
352         var->lower_margin = timing->vsync_start - timing->height;
353         var->hsync_len = timing->hsync_end - timing->hsync_start;
354         var->vsync_len = timing->vsync_end - timing->vsync_start;
355
356         /* Ouch. This breaks the rules but timing_num is only important if you
357         * change a video mode */
358         par->timing_num = min_mode;
359
360         printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
361                 var->xres, var->yres, var->bits_per_pixel);
362         printk(KERN_INFO "         vxres=%d vyres=%d\n", var->xres_virtual,
363                 var->yres_virtual);
364         return 0;
365 }
366
367 /*
368  *  Setup flatpanel related registers.
369  */
370 static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
371 {
372         int fp_wid, fp_hgt, fp_vbs, fp_vbe;
373         u32 outputVal = 0;
374
375         SET_DBE_FIELD(VT_FLAGS, HDRV_INVERT, outputVal, 
376                 (currentTiming->flags & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1);
377         SET_DBE_FIELD(VT_FLAGS, VDRV_INVERT, outputVal, 
378                 (currentTiming->flags & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1);
379         DBE_SETREG(vt_flags, outputVal);
380
381         /* Turn on the flat panel */
382         switch (flatpanel_id) {
383                 case FLATPANEL_SGI_1600SW:
384                         fp_wid = 1600;
385                         fp_hgt = 1024;
386                         fp_vbs = 0;
387                         fp_vbe = 1600;
388                         currentTiming->pll_m = 4;
389                         currentTiming->pll_n = 1;
390                         currentTiming->pll_p = 0;
391                         break;
392                 default:
393                         fp_wid = fp_hgt = fp_vbs = fp_vbe = 0xfff;
394         }
395
396         outputVal = 0;
397         SET_DBE_FIELD(FP_DE, FP_DE_ON, outputVal, fp_vbs);
398         SET_DBE_FIELD(FP_DE, FP_DE_OFF, outputVal, fp_vbe);
399         DBE_SETREG(fp_de, outputVal);
400         outputVal = 0;
401         SET_DBE_FIELD(FP_HDRV, FP_HDRV_OFF, outputVal, fp_wid);
402         DBE_SETREG(fp_hdrv, outputVal);
403         outputVal = 0;
404         SET_DBE_FIELD(FP_VDRV, FP_VDRV_ON, outputVal, 1);
405         SET_DBE_FIELD(FP_VDRV, FP_VDRV_OFF, outputVal, fp_hgt + 1);
406         DBE_SETREG(fp_vdrv, outputVal);
407 }
408
409 /*
410  *  Set the hardware according to 'par'.
411  */
412 static int sgivwfb_set_par(struct fb_info *info)
413 {
414         struct sgivw_par *par = info->par;
415         int i, j, htmp, temp;
416         u32 readVal, outputVal;
417         int wholeTilesX, maxPixelsPerTileX;
418         int frmWrite1, frmWrite2, frmWrite3b;
419         struct dbe_timing_info *currentTiming; /* Current Video Timing */
420         int xpmax, ypmax;       // Monitor resolution
421         int bytesPerPixel;      // Bytes per pixel
422
423         currentTiming = &dbeVTimings[par->timing_num];
424         bytesPerPixel = bytes_per_pixel(info->var.bits_per_pixel);
425         xpmax = currentTiming->width;
426         ypmax = currentTiming->height;
427
428         /* dbe_InitGraphicsBase(); */
429         /* Turn on dotclock PLL */
430         DBE_SETREG(ctrlstat, 0x20000000);
431
432         dbe_TurnOffDma();
433
434         /* dbe_CalculateScreenParams(); */
435         maxPixelsPerTileX = 512 / bytesPerPixel;
436         wholeTilesX = xpmax / maxPixelsPerTileX;
437         if (wholeTilesX * maxPixelsPerTileX < xpmax)
438                 wholeTilesX++;
439
440         printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
441                maxPixelsPerTileX, wholeTilesX);
442
443         /* dbe_InitGammaMap(); */
444         udelay(10);
445
446         for (i = 0; i < 256; i++) {
447                 DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
448         }
449
450         /* dbe_TurnOn(); */
451         DBE_GETREG(vt_xy, readVal);
452         if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) {
453                 DBE_SETREG(vt_xy, 0x00000000);
454                 udelay(1);
455         } else
456                 dbe_TurnOffDma();
457
458         /* dbe_Initdbe(); */
459         for (i = 0; i < 256; i++) {
460                 for (j = 0; j < 100; j++) {
461                         DBE_GETREG(cm_fifo, readVal);
462                         if (readVal != 0x00000000)
463                                 break;
464                         else
465                                 udelay(10);
466                 }
467
468                 // DBE_ISETREG(cmap, i, 0x00000000);
469                 DBE_ISETREG(cmap, i, (i << 8) | (i << 16) | (i << 24));
470         }
471
472         /* dbe_InitFramebuffer(); */
473         frmWrite1 = 0;
474         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1,
475                       wholeTilesX);
476         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
477
478         switch (bytesPerPixel) {
479         case 1:
480                 SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
481                               DBE_FRM_DEPTH_8);
482                 break;
483         case 2:
484                 SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
485                               DBE_FRM_DEPTH_16);
486                 break;
487         case 4:
488                 SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1,
489                               DBE_FRM_DEPTH_32);
490                 break;
491         }
492
493         frmWrite2 = 0;
494         SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
495
496         // Tell dbe about the framebuffer location and type
497         // XXX What format is the FRM_TILE_PTR??  64K aligned address?
498         frmWrite3b = 0;
499         SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b,
500                       sgivwfb_mem_phys >> 9);
501         SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
502         SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
503
504         /* Initialize DIDs */
505
506         outputVal = 0;
507         switch (bytesPerPixel) {
508         case 1:
509                 SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
510                 break;
511         case 2:
512                 SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
513                 break;
514         case 4:
515                 SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
516                 break;
517         }
518         SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
519
520         for (i = 0; i < 32; i++) {
521                 DBE_ISETREG(mode_regs, i, outputVal);
522         }
523
524         /* dbe_InitTiming(); */
525         DBE_SETREG(vt_intr01, 0xffffffff);
526         DBE_SETREG(vt_intr23, 0xffffffff);
527
528         DBE_GETREG(dotclock, readVal);
529         DBE_SETREG(dotclock, readVal & 0xffff);
530
531         DBE_SETREG(vt_xymax, 0x00000000);
532         outputVal = 0;
533         SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal,
534                       currentTiming->vsync_start);
535         SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal,
536                       currentTiming->vsync_end);
537         DBE_SETREG(vt_vsync, outputVal);
538         outputVal = 0;
539         SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal,
540                       currentTiming->hsync_start);
541         SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal,
542                       currentTiming->hsync_end);
543         DBE_SETREG(vt_hsync, outputVal);
544         outputVal = 0;
545         SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal,
546                       currentTiming->vblank_start);
547         SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal,
548                       currentTiming->vblank_end);
549         DBE_SETREG(vt_vblank, outputVal);
550         outputVal = 0;
551         SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal,
552                       currentTiming->hblank_start);
553         SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal,
554                       currentTiming->hblank_end - 3);
555         DBE_SETREG(vt_hblank, outputVal);
556         outputVal = 0;
557         SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal,
558                       currentTiming->vblank_start);
559         SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal,
560                       currentTiming->vblank_end);
561         DBE_SETREG(vt_vcmap, outputVal);
562         outputVal = 0;
563         SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal,
564                       currentTiming->hblank_start);
565         SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal,
566                       currentTiming->hblank_end - 3);
567         DBE_SETREG(vt_hcmap, outputVal);
568
569         if (flatpanel_id != -1)
570                 sgivwfb_setup_flatpanel(currentTiming);
571
572         outputVal = 0;
573         temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
574         if (temp > 0)
575                 temp = -temp;
576
577         SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32) temp);
578         if (currentTiming->hblank_end >= 20)
579                 SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
580                               currentTiming->hblank_end - 20);
581         else
582                 SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
583                               currentTiming->htotal - (20 -
584                                                        currentTiming->
585                                                        hblank_end));
586         DBE_SETREG(did_start_xy, outputVal);
587
588         outputVal = 0;
589         SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal,
590                       (u32) (temp + 1));
591         if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
592                 SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
593                               currentTiming->hblank_end - DBE_CRS_MAGIC);
594         else
595                 SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
596                               currentTiming->htotal - (DBE_CRS_MAGIC -
597                                                        currentTiming->
598                                                        hblank_end));
599         DBE_SETREG(crs_start_xy, outputVal);
600
601         outputVal = 0;
602         SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32) temp);
603         SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
604                       currentTiming->hblank_end - 4);
605         DBE_SETREG(vc_start_xy, outputVal);
606
607         DBE_SETREG(frm_size_tile, frmWrite1);
608         DBE_SETREG(frm_size_pixel, frmWrite2);
609
610         outputVal = 0;
611         SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m - 1);
612         SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n - 1);
613         SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
614         SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
615         DBE_SETREG(dotclock, outputVal);
616
617         udelay(11 * 1000);
618
619         DBE_SETREG(vt_vpixen, 0xffffff);
620         DBE_SETREG(vt_hpixen, 0xffffff);
621
622         outputVal = 0;
623         SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
624         SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
625         DBE_SETREG(vt_xymax, outputVal);
626
627         outputVal = frmWrite1;
628         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
629         DBE_SETREG(frm_size_tile, outputVal);
630         DBE_SETREG(frm_size_tile, frmWrite1);
631
632         outputVal = 0;
633         SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
634         DBE_SETREG(ovr_width_tile, outputVal);
635         DBE_SETREG(ovr_width_tile, 0);
636
637         DBE_SETREG(frm_control, frmWrite3b);
638         DBE_SETREG(did_control, 0);
639
640         // Wait for dbe to take frame settings
641         for (i = 0; i < 100000; i++) {
642                 DBE_GETREG(frm_inhwctrl, readVal);
643                 if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) !=
644                     0)
645                         break;
646                 else
647                         udelay(1);
648         }
649
650         if (i == 100000)
651                 printk(KERN_INFO
652                        "sgivwfb: timeout waiting for frame DMA enable.\n");
653
654         outputVal = 0;
655         htmp = currentTiming->hblank_end - 19;
656         if (htmp < 0)
657                 htmp += currentTiming->htotal;  /* allow blank to wrap around */
658         SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
659         SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
660                       ((htmp + currentTiming->width -
661                         2) % currentTiming->htotal));
662         DBE_SETREG(vt_hpixen, outputVal);
663
664         outputVal = 0;
665         SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
666                       currentTiming->vblank_start);
667         SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
668                       currentTiming->vblank_end);
669         DBE_SETREG(vt_vpixen, outputVal);
670
671         // Turn off mouse cursor
672         par->regs->crs_ctl = 0;
673
674         // XXX What's this section for??
675         DBE_GETREG(ctrlstat, readVal);
676         readVal &= 0x02000000;
677
678         if (readVal != 0) {
679                 DBE_SETREG(ctrlstat, 0x30000000);
680         }
681         return 0;
682 }
683
684 /*
685  *  Set a single color register. The values supplied are already
686  *  rounded down to the hardware's capabilities (according to the
687  *  entries in the var structure). Return != 0 for invalid regno.
688  */
689
690 static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
691                              u_int blue, u_int transp,
692                              struct fb_info *info)
693 {
694         struct sgivw_par *par = (struct sgivw_par *) info->par;
695
696         if (regno > 255)
697                 return 1;
698         red >>= 8;
699         green >>= 8;
700         blue >>= 8;
701
702         /* wait for the color map FIFO to have a free entry */
703         while (par->cmap_fifo == 0)
704                 par->cmap_fifo = par->regs->cm_fifo;
705
706         par->regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
707         par->cmap_fifo--;       /* assume FIFO is filling up */
708         return 0;
709 }
710
711 static int sgivwfb_mmap(struct fb_info *info, struct file *file,
712                         struct vm_area_struct *vma)
713 {
714         unsigned long size = vma->vm_end - vma->vm_start;
715         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
716
717         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
718                 return -EINVAL;
719         if (offset + size > sgivwfb_mem_size)
720                 return -EINVAL;
721         offset += sgivwfb_mem_phys;
722         pgprot_val(vma->vm_page_prot) =
723             pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
724         vma->vm_flags |= VM_IO;
725         if (remap_page_range
726             (vma, vma->vm_start, offset, size, vma->vm_page_prot))
727                 return -EAGAIN;
728         vma->vm_file = file;
729         printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
730                offset, vma->vm_start);
731         return 0;
732 }
733
734 int __init sgivwfb_setup(char *options)
735 {
736         char *this_opt;
737
738         if (!options || !*options)
739                 return 0;
740
741         while ((this_opt = strsep(&options, ",")) != NULL) {
742                 if (!strncmp(this_opt, "monitor:", 8)) {
743                         if (!strncmp(this_opt + 8, "crt", 3))
744                                 flatpanel_id = -1;
745                         else if (!strncmp(this_opt + 8, "1600sw", 6))
746                                 flatpanel_id = FLATPANEL_SGI_1600SW;
747                 }
748         }
749         return 0;
750 }
751
752 /*
753  *  Initialisation
754  */
755 int __init sgivwfb_init(void)
756 {
757         char *monitor;
758
759         if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
760                 printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
761                 return -EBUSY;
762         }
763         default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
764         if (!default_par.regs) {
765                 printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
766                 goto fail_ioremap_regs;
767         }
768
769         mtrr_add(sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
770
771         sgivwfb_fix.smem_start = sgivwfb_mem_phys;
772         sgivwfb_fix.smem_len = sgivwfb_mem_size;
773         sgivwfb_fix.ywrapstep = ywrap;
774         sgivwfb_fix.ypanstep = ypan;
775
776         fb_info.fix = sgivwfb_fix;
777
778         switch (flatpanel_id) {
779                 case FLATPANEL_SGI_1600SW:
780                         fb_info.var = sgivwfb_var1600sw;
781                         monitor = "SGI 1600SW flatpanel";
782                         break;
783                 default:
784                         fb_info.var = sgivwfb_var;
785                         monitor = "CRT";
786         }
787
788         printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
789
790         fb_info.fbops = &sgivwfb_ops;
791         fb_info.pseudo_palette = pseudo_palette;
792         fb_info.par = &default_par;
793         fb_info.flags = FBINFO_FLAG_DEFAULT;
794
795         fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
796         if (!fb_info.screen_base) {
797                 printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
798                 goto fail_ioremap_fbmem;
799         }
800
801         fb_alloc_cmap(&fb_info.cmap, 256, 0);
802
803         if (register_framebuffer(&fb_info) < 0) {
804                 printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
805                 goto fail_register_framebuffer;
806         }
807
808         printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",      
809                 fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
810         return 0;
811
812 fail_register_framebuffer:
813         iounmap((char *) fb_info.screen_base);
814 fail_ioremap_fbmem:
815         iounmap(default_par.regs);
816 fail_ioremap_regs:
817         release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
818         return -ENXIO;
819 }
820
821 #ifdef MODULE
822 MODULE_LICENSE("GPL");
823
824 int init_module(void)
825 {
826         return sgivwfb_init();
827 }
828
829 void cleanup_module(void)
830 {
831         unregister_framebuffer(&fb_info);
832         dbe_TurnOffDma();
833         iounmap(regs);
834         iounmap(&fb_info.screen_base);
835         release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
836 }
837
838 #endif                          /* MODULE */