[PATCH] Add ethtool -g support to Spidernet network driver
[linux-2.6] / drivers / video / neofb.c
1 /*
2  * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
3  *
4  * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
5  *
6  *
7  * Card specific code is based on XFree86's neomagic driver.
8  * Framebuffer framework code is based on code of cyber2000fb.
9  *
10  * This file is subject to the terms and conditions of the GNU General
11  * Public License.  See the file COPYING in the main directory of this
12  * archive for more details.
13  *
14  *
15  * 0.4.1
16  *  - Cosmetic changes (dok)
17  *
18  * 0.4
19  *  - Toshiba Libretto support, allow modes larger than LCD size if
20  *    LCD is disabled, keep BIOS settings if internal/external display
21  *    haven't been enabled explicitly
22  *                          (Thomas J. Moore <dark@mama.indstate.edu>)
23  *
24  * 0.3.3
25  *  - Porting over to new fbdev api. (jsimmons)
26  *  
27  * 0.3.2
28  *  - got rid of all floating point (dok) 
29  *
30  * 0.3.1
31  *  - added module license (dok)
32  *
33  * 0.3
34  *  - hardware accelerated clear and move for 2200 and above (dok)
35  *  - maximum allowed dotclock is handled now (dok)
36  *
37  * 0.2.1
38  *  - correct panning after X usage (dok)
39  *  - added module and kernel parameters (dok)
40  *  - no stretching if external display is enabled (dok)
41  *
42  * 0.2
43  *  - initial version (dok)
44  *
45  *
46  * TODO
47  * - ioctl for internal/external switching
48  * - blanking
49  * - 32bit depth support, maybe impossible
50  * - disable pan-on-sync, need specs
51  *
52  * BUGS
53  * - white margin on bootup like with tdfxfb (colormap problem?)
54  *
55  */
56
57 #include <linux/module.h>
58 #include <linux/kernel.h>
59 #include <linux/errno.h>
60 #include <linux/string.h>
61 #include <linux/mm.h>
62 #include <linux/slab.h>
63 #include <linux/delay.h>
64 #include <linux/fb.h>
65 #include <linux/pci.h>
66 #include <linux/init.h>
67 #ifdef CONFIG_TOSHIBA
68 #include <linux/toshiba.h>
69 extern int tosh_smm(SMMRegisters *regs);
70 #endif
71
72 #include <asm/io.h>
73 #include <asm/irq.h>
74 #include <asm/pgtable.h>
75 #include <asm/system.h>
76 #include <asm/uaccess.h>
77
78 #ifdef CONFIG_MTRR
79 #include <asm/mtrr.h>
80 #endif
81
82 #include <video/vga.h>
83 #include <video/neomagic.h>
84
85 #define NEOFB_VERSION "0.4.2"
86
87 /* --------------------------------------------------------------------- */
88
89 static int internal;
90 static int external;
91 static int libretto;
92 static int nostretch;
93 static int nopciburst;
94 static char *mode_option __devinitdata = NULL;
95
96 #ifdef MODULE
97
98 MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");
99 MODULE_LICENSE("GPL");
100 MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
101 module_param(internal, bool, 0);
102 MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
103 module_param(external, bool, 0);
104 MODULE_PARM_DESC(external, "Enable output on external CRT.");
105 module_param(libretto, bool, 0);
106 MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
107 module_param(nostretch, bool, 0);
108 MODULE_PARM_DESC(nostretch,
109                  "Disable stretching of modes smaller than LCD.");
110 module_param(nopciburst, bool, 0);
111 MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
112 module_param(mode_option, charp, 0);
113 MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
114
115 #endif
116
117
118 /* --------------------------------------------------------------------- */
119
120 static biosMode bios8[] = {
121         {320, 240, 0x40},
122         {300, 400, 0x42},
123         {640, 400, 0x20},
124         {640, 480, 0x21},
125         {800, 600, 0x23},
126         {1024, 768, 0x25},
127 };
128
129 static biosMode bios16[] = {
130         {320, 200, 0x2e},
131         {320, 240, 0x41},
132         {300, 400, 0x43},
133         {640, 480, 0x31},
134         {800, 600, 0x34},
135         {1024, 768, 0x37},
136 };
137
138 static biosMode bios24[] = {
139         {640, 480, 0x32},
140         {800, 600, 0x35},
141         {1024, 768, 0x38}
142 };
143
144 #ifdef NO_32BIT_SUPPORT_YET
145 /* FIXME: guessed values, wrong */
146 static biosMode bios32[] = {
147         {640, 480, 0x33},
148         {800, 600, 0x36},
149         {1024, 768, 0x39}
150 };
151 #endif
152
153 static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
154 {
155         writel(val, par->neo2200 + par->cursorOff + regindex);
156 }
157
158 static int neoFindMode(int xres, int yres, int depth)
159 {
160         int xres_s;
161         int i, size;
162         biosMode *mode;
163
164         switch (depth) {
165         case 8:
166                 size = ARRAY_SIZE(bios8);
167                 mode = bios8;
168                 break;
169         case 16:
170                 size = ARRAY_SIZE(bios16);
171                 mode = bios16;
172                 break;
173         case 24:
174                 size = ARRAY_SIZE(bios24);
175                 mode = bios24;
176                 break;
177 #ifdef NO_32BIT_SUPPORT_YET
178         case 32:
179                 size = ARRAY_SIZE(bios32);
180                 mode = bios32;
181                 break;
182 #endif
183         default:
184                 return 0;
185         }
186
187         for (i = 0; i < size; i++) {
188                 if (xres <= mode[i].x_res) {
189                         xres_s = mode[i].x_res;
190                         for (; i < size; i++) {
191                                 if (mode[i].x_res != xres_s)
192                                         return mode[i - 1].mode;
193                                 if (yres <= mode[i].y_res)
194                                         return mode[i].mode;
195                         }
196                 }
197         }
198         return mode[size - 1].mode;
199 }
200
201 /*
202  * neoCalcVCLK --
203  *
204  * Determine the closest clock frequency to the one requested.
205  */
206 #define REF_FREQ 0xe517         /* 14.31818 in 20.12 fixed point */
207 #define MAX_N 127
208 #define MAX_D 31
209 #define MAX_F 1
210
211 static void neoCalcVCLK(const struct fb_info *info,
212                         struct neofb_par *par, long freq)
213 {
214         int n, d, f;
215         int n_best = 0, d_best = 0, f_best = 0;
216         long f_best_diff = (0x7ffff << 12);     /* 20.12 */
217         long f_target = (freq << 12) / 1000;    /* 20.12 */
218
219         for (f = 0; f <= MAX_F; f++)
220                 for (n = 0; n <= MAX_N; n++)
221                         for (d = 0; d <= MAX_D; d++) {
222                                 long f_out;     /* 20.12 */
223                                 long f_diff;    /* 20.12 */
224
225                                 f_out =
226                                     ((((n + 1) << 12) / ((d +
227                                                           1) *
228                                                          (1 << f))) >> 12)
229                                     * REF_FREQ;
230                                 f_diff = abs(f_out - f_target);
231                                 if (f_diff < f_best_diff) {
232                                         f_best_diff = f_diff;
233                                         n_best = n;
234                                         d_best = d;
235                                         f_best = f;
236                                 }
237                         }
238
239         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
240             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
241             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
242             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
243                 /* NOT_DONE:  We are trying the full range of the 2200 clock.
244                    We should be able to try n up to 2047 */
245                 par->VCLK3NumeratorLow = n_best;
246                 par->VCLK3NumeratorHigh = (f_best << 7);
247         } else
248                 par->VCLK3NumeratorLow = n_best | (f_best << 7);
249
250         par->VCLK3Denominator = d_best;
251
252 #ifdef NEOFB_DEBUG
253         printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
254                f_target >> 12,
255                par->VCLK3NumeratorLow,
256                par->VCLK3NumeratorHigh,
257                par->VCLK3Denominator, f_best_diff >> 12);
258 #endif
259 }
260
261 /*
262  * vgaHWInit --
263  *      Handle the initialization, etc. of a screen.
264  *      Return FALSE on failure.
265  */
266
267 static int vgaHWInit(const struct fb_var_screeninfo *var,
268                      const struct fb_info *info,
269                      struct neofb_par *par, struct xtimings *timings)
270 {
271         par->MiscOutReg = 0x23;
272
273         if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
274                 par->MiscOutReg |= 0x40;
275
276         if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
277                 par->MiscOutReg |= 0x80;
278
279         /*
280          * Time Sequencer
281          */
282         par->Sequencer[0] = 0x00;
283         par->Sequencer[1] = 0x01;
284         par->Sequencer[2] = 0x0F;
285         par->Sequencer[3] = 0x00;       /* Font select */
286         par->Sequencer[4] = 0x0E;       /* Misc */
287
288         /*
289          * CRTC Controller
290          */
291         par->CRTC[0] = (timings->HTotal >> 3) - 5;
292         par->CRTC[1] = (timings->HDisplay >> 3) - 1;
293         par->CRTC[2] = (timings->HDisplay >> 3) - 1;
294         par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
295         par->CRTC[4] = (timings->HSyncStart >> 3);
296         par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
297             | (((timings->HSyncEnd >> 3)) & 0x1F);
298         par->CRTC[6] = (timings->VTotal - 2) & 0xFF;
299         par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8)
300             | (((timings->VDisplay - 1) & 0x100) >> 7)
301             | ((timings->VSyncStart & 0x100) >> 6)
302             | (((timings->VDisplay - 1) & 0x100) >> 5)
303             | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4)
304             | (((timings->VDisplay - 1) & 0x200) >> 3)
305             | ((timings->VSyncStart & 0x200) >> 2);
306         par->CRTC[8] = 0x00;
307         par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
308
309         if (timings->dblscan)
310                 par->CRTC[9] |= 0x80;
311
312         par->CRTC[10] = 0x00;
313         par->CRTC[11] = 0x00;
314         par->CRTC[12] = 0x00;
315         par->CRTC[13] = 0x00;
316         par->CRTC[14] = 0x00;
317         par->CRTC[15] = 0x00;
318         par->CRTC[16] = timings->VSyncStart & 0xFF;
319         par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
320         par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
321         par->CRTC[19] = var->xres_virtual >> 4;
322         par->CRTC[20] = 0x00;
323         par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;
324         par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
325         par->CRTC[23] = 0xC3;
326         par->CRTC[24] = 0xFF;
327
328         /*
329          * are these unnecessary?
330          * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
331          * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
332          */
333
334         /*
335          * Graphics Display Controller
336          */
337         par->Graphics[0] = 0x00;
338         par->Graphics[1] = 0x00;
339         par->Graphics[2] = 0x00;
340         par->Graphics[3] = 0x00;
341         par->Graphics[4] = 0x00;
342         par->Graphics[5] = 0x40;
343         par->Graphics[6] = 0x05;        /* only map 64k VGA memory !!!! */
344         par->Graphics[7] = 0x0F;
345         par->Graphics[8] = 0xFF;
346
347
348         par->Attribute[0] = 0x00;       /* standard colormap translation */
349         par->Attribute[1] = 0x01;
350         par->Attribute[2] = 0x02;
351         par->Attribute[3] = 0x03;
352         par->Attribute[4] = 0x04;
353         par->Attribute[5] = 0x05;
354         par->Attribute[6] = 0x06;
355         par->Attribute[7] = 0x07;
356         par->Attribute[8] = 0x08;
357         par->Attribute[9] = 0x09;
358         par->Attribute[10] = 0x0A;
359         par->Attribute[11] = 0x0B;
360         par->Attribute[12] = 0x0C;
361         par->Attribute[13] = 0x0D;
362         par->Attribute[14] = 0x0E;
363         par->Attribute[15] = 0x0F;
364         par->Attribute[16] = 0x41;
365         par->Attribute[17] = 0xFF;
366         par->Attribute[18] = 0x0F;
367         par->Attribute[19] = 0x00;
368         par->Attribute[20] = 0x00;
369         return 0;
370 }
371
372 static void vgaHWLock(struct vgastate *state)
373 {
374         /* Protect CRTC[0-7] */
375         vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
376 }
377
378 static void vgaHWUnlock(void)
379 {
380         /* Unprotect CRTC[0-7] */
381         vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
382 }
383
384 static void neoLock(struct vgastate *state)
385 {
386         vga_wgfx(state->vgabase, 0x09, 0x00);
387         vgaHWLock(state);
388 }
389
390 static void neoUnlock(void)
391 {
392         vgaHWUnlock();
393         vga_wgfx(NULL, 0x09, 0x26);
394 }
395
396 /*
397  * VGA Palette management
398  */
399 static int paletteEnabled = 0;
400
401 static inline void VGAenablePalette(void)
402 {
403         vga_r(NULL, VGA_IS1_RC);
404         vga_w(NULL, VGA_ATT_W, 0x00);
405         paletteEnabled = 1;
406 }
407
408 static inline void VGAdisablePalette(void)
409 {
410         vga_r(NULL, VGA_IS1_RC);
411         vga_w(NULL, VGA_ATT_W, 0x20);
412         paletteEnabled = 0;
413 }
414
415 static inline void VGAwATTR(u8 index, u8 value)
416 {
417         if (paletteEnabled)
418                 index &= ~0x20;
419         else
420                 index |= 0x20;
421
422         vga_r(NULL, VGA_IS1_RC);
423         vga_wattr(NULL, index, value);
424 }
425
426 static void vgaHWProtect(int on)
427 {
428         unsigned char tmp;
429
430         if (on) {
431                 /*
432                  * Turn off screen and disable sequencer.
433                  */
434                 tmp = vga_rseq(NULL, 0x01);
435                 vga_wseq(NULL, 0x00, 0x01);             /* Synchronous Reset */
436                 vga_wseq(NULL, 0x01, tmp | 0x20);       /* disable the display */
437
438                 VGAenablePalette();
439         } else {
440                 /*
441                  * Reenable sequencer, then turn on screen.
442                  */
443                 tmp = vga_rseq(NULL, 0x01);
444                 vga_wseq(NULL, 0x01, tmp & ~0x20);      /* reenable display */
445                 vga_wseq(NULL, 0x00, 0x03);             /* clear synchronousreset */
446
447                 VGAdisablePalette();
448         }
449 }
450
451 static void vgaHWRestore(const struct fb_info *info,
452                          const struct neofb_par *par)
453 {
454         int i;
455
456         vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
457
458         for (i = 1; i < 5; i++)
459                 vga_wseq(NULL, i, par->Sequencer[i]);
460
461         /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
462         vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
463
464         for (i = 0; i < 25; i++)
465                 vga_wcrt(NULL, i, par->CRTC[i]);
466
467         for (i = 0; i < 9; i++)
468                 vga_wgfx(NULL, i, par->Graphics[i]);
469
470         VGAenablePalette();
471
472         for (i = 0; i < 21; i++)
473                 VGAwATTR(i, par->Attribute[i]);
474
475         VGAdisablePalette();
476 }
477
478
479 /* -------------------- Hardware specific routines ------------------------- */
480
481 /*
482  * Hardware Acceleration for Neo2200+
483  */
484 static inline int neo2200_sync(struct fb_info *info)
485 {
486         struct neofb_par *par = info->par;
487
488         while (readl(&par->neo2200->bltStat) & 1);
489         return 0;
490 }
491
492 static inline void neo2200_wait_fifo(struct fb_info *info,
493                                      int requested_fifo_space)
494 {
495         //  ndev->neo.waitfifo_calls++;
496         //  ndev->neo.waitfifo_sum += requested_fifo_space;
497
498         /* FIXME: does not work
499            if (neo_fifo_space < requested_fifo_space)
500            {
501            neo_fifo_waitcycles++;
502
503            while (1)
504            {
505            neo_fifo_space = (neo2200->bltStat >> 8);
506            if (neo_fifo_space >= requested_fifo_space)
507            break;
508            }
509            }
510            else
511            {
512            neo_fifo_cache_hits++;
513            }
514
515            neo_fifo_space -= requested_fifo_space;
516          */
517
518         neo2200_sync(info);
519 }
520
521 static inline void neo2200_accel_init(struct fb_info *info,
522                                       struct fb_var_screeninfo *var)
523 {
524         struct neofb_par *par = info->par;
525         Neo2200 __iomem *neo2200 = par->neo2200;
526         u32 bltMod, pitch;
527
528         neo2200_sync(info);
529
530         switch (var->bits_per_pixel) {
531         case 8:
532                 bltMod = NEO_MODE1_DEPTH8;
533                 pitch = var->xres_virtual;
534                 break;
535         case 15:
536         case 16:
537                 bltMod = NEO_MODE1_DEPTH16;
538                 pitch = var->xres_virtual * 2;
539                 break;
540         case 24:
541                 bltMod = NEO_MODE1_DEPTH24;
542                 pitch = var->xres_virtual * 3;
543                 break;
544         default:
545                 printk(KERN_ERR
546                        "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
547                 return;
548         }
549
550         writel(bltMod << 16, &neo2200->bltStat);
551         writel((pitch << 16) | pitch, &neo2200->pitch);
552 }
553
554 /* --------------------------------------------------------------------- */
555
556 static int
557 neofb_open(struct fb_info *info, int user)
558 {
559         struct neofb_par *par = info->par;
560         int cnt = atomic_read(&par->ref_count);
561
562         if (!cnt) {
563                 memset(&par->state, 0, sizeof(struct vgastate));
564                 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
565                 save_vga(&par->state);
566         }
567         atomic_inc(&par->ref_count);
568         return 0;
569 }
570
571 static int
572 neofb_release(struct fb_info *info, int user)
573 {
574         struct neofb_par *par = info->par;
575         int cnt = atomic_read(&par->ref_count);
576
577         if (!cnt)
578                 return -EINVAL;
579         if (cnt == 1) {
580                 restore_vga(&par->state);
581         }
582         atomic_dec(&par->ref_count);
583         return 0;
584 }
585
586 static int
587 neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
588 {
589         struct neofb_par *par = info->par;
590         unsigned int pixclock = var->pixclock;
591         struct xtimings timings;
592         int memlen, vramlen;
593         int mode_ok = 0;
594
595         DBG("neofb_check_var");
596
597         if (!pixclock)
598                 pixclock = 10000;       /* 10ns = 100MHz */
599         timings.pixclock = 1000000000 / pixclock;
600         if (timings.pixclock < 1)
601                 timings.pixclock = 1;
602
603         if (timings.pixclock > par->maxClock)
604                 return -EINVAL;
605
606         timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
607         timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
608         timings.HDisplay = var->xres;
609         timings.HSyncStart = timings.HDisplay + var->right_margin;
610         timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
611         timings.HTotal = timings.HSyncEnd + var->left_margin;
612         timings.VDisplay = var->yres;
613         timings.VSyncStart = timings.VDisplay + var->lower_margin;
614         timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
615         timings.VTotal = timings.VSyncEnd + var->upper_margin;
616         timings.sync = var->sync;
617
618         /* Is the mode larger than the LCD panel? */
619         if (par->internal_display &&
620             ((var->xres > par->NeoPanelWidth) ||
621              (var->yres > par->NeoPanelHeight))) {
622                 printk(KERN_INFO
623                        "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
624                        var->xres, var->yres, par->NeoPanelWidth,
625                        par->NeoPanelHeight);
626                 return -EINVAL;
627         }
628
629         /* Is the mode one of the acceptable sizes? */
630         if (!par->internal_display)
631                 mode_ok = 1;
632         else {
633                 switch (var->xres) {
634                 case 1280:
635                         if (var->yres == 1024)
636                                 mode_ok = 1;
637                         break;
638                 case 1024:
639                         if (var->yres == 768)
640                                 mode_ok = 1;
641                         break;
642                 case 800:
643                         if (var->yres == (par->libretto ? 480 : 600))
644                                 mode_ok = 1;
645                         break;
646                 case 640:
647                         if (var->yres == 480)
648                                 mode_ok = 1;
649                         break;
650                 }
651         }
652
653         if (!mode_ok) {
654                 printk(KERN_INFO
655                        "Mode (%dx%d) won't display properly on LCD\n",
656                        var->xres, var->yres);
657                 return -EINVAL;
658         }
659
660         var->red.msb_right = 0;
661         var->green.msb_right = 0;
662         var->blue.msb_right = 0;
663
664         switch (var->bits_per_pixel) {
665         case 8:         /* PSEUDOCOLOUR, 256 */
666                 var->transp.offset = 0;
667                 var->transp.length = 0;
668                 var->red.offset = 0;
669                 var->red.length = 8;
670                 var->green.offset = 0;
671                 var->green.length = 8;
672                 var->blue.offset = 0;
673                 var->blue.length = 8;
674                 break;
675
676         case 16:                /* DIRECTCOLOUR, 64k */
677                 var->transp.offset = 0;
678                 var->transp.length = 0;
679                 var->red.offset = 11;
680                 var->red.length = 5;
681                 var->green.offset = 5;
682                 var->green.length = 6;
683                 var->blue.offset = 0;
684                 var->blue.length = 5;
685                 break;
686
687         case 24:                /* TRUECOLOUR, 16m */
688                 var->transp.offset = 0;
689                 var->transp.length = 0;
690                 var->red.offset = 16;
691                 var->red.length = 8;
692                 var->green.offset = 8;
693                 var->green.length = 8;
694                 var->blue.offset = 0;
695                 var->blue.length = 8;
696                 break;
697
698 #ifdef NO_32BIT_SUPPORT_YET
699         case 32:                /* TRUECOLOUR, 16m */
700                 var->transp.offset = 24;
701                 var->transp.length = 8;
702                 var->red.offset = 16;
703                 var->red.length = 8;
704                 var->green.offset = 8;
705                 var->green.length = 8;
706                 var->blue.offset = 0;
707                 var->blue.length = 8;
708                 break;
709 #endif
710         default:
711                 printk(KERN_WARNING "neofb: no support for %dbpp\n",
712                        var->bits_per_pixel);
713                 return -EINVAL;
714         }
715
716         vramlen = info->fix.smem_len;
717         if (vramlen > 4 * 1024 * 1024)
718                 vramlen = 4 * 1024 * 1024;
719
720         if (var->yres_virtual < var->yres)
721                 var->yres_virtual = var->yres;
722         if (var->xres_virtual < var->xres)
723                 var->xres_virtual = var->xres;
724
725         memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
726
727         if (memlen > vramlen) {
728                 var->yres_virtual =  vramlen * 8 / (var->xres_virtual *
729                                         var->bits_per_pixel);
730                 memlen = var->xres_virtual * var->bits_per_pixel *
731                                 var->yres_virtual / 8;
732         }
733
734         /* we must round yres/xres down, we already rounded y/xres_virtual up
735            if it was possible. We should return -EINVAL, but I disagree */
736         if (var->yres_virtual < var->yres)
737                 var->yres = var->yres_virtual;
738         if (var->xres_virtual < var->xres)
739                 var->xres = var->xres_virtual;
740         if (var->xoffset + var->xres > var->xres_virtual)
741                 var->xoffset = var->xres_virtual - var->xres;
742         if (var->yoffset + var->yres > var->yres_virtual)
743                 var->yoffset = var->yres_virtual - var->yres;
744
745         var->nonstd = 0;
746         var->height = -1;
747         var->width = -1;
748
749         if (var->bits_per_pixel >= 24 || !par->neo2200)
750                 var->accel_flags &= ~FB_ACCELF_TEXT;
751         return 0;
752 }
753
754 static int neofb_set_par(struct fb_info *info)
755 {
756         struct neofb_par *par = info->par;
757         struct xtimings timings;
758         unsigned char temp;
759         int i, clock_hi = 0;
760         int lcd_stretch;
761         int hoffset, voffset;
762
763         DBG("neofb_set_par");
764
765         neoUnlock();
766
767         vgaHWProtect(1);        /* Blank the screen */
768
769         timings.dblscan = info->var.vmode & FB_VMODE_DOUBLE;
770         timings.interlaced = info->var.vmode & FB_VMODE_INTERLACED;
771         timings.HDisplay = info->var.xres;
772         timings.HSyncStart = timings.HDisplay + info->var.right_margin;
773         timings.HSyncEnd = timings.HSyncStart + info->var.hsync_len;
774         timings.HTotal = timings.HSyncEnd + info->var.left_margin;
775         timings.VDisplay = info->var.yres;
776         timings.VSyncStart = timings.VDisplay + info->var.lower_margin;
777         timings.VSyncEnd = timings.VSyncStart + info->var.vsync_len;
778         timings.VTotal = timings.VSyncEnd + info->var.upper_margin;
779         timings.sync = info->var.sync;
780         timings.pixclock = PICOS2KHZ(info->var.pixclock);
781
782         if (timings.pixclock < 1)
783                 timings.pixclock = 1;
784
785         /*
786          * This will allocate the datastructure and initialize all of the
787          * generic VGA registers.
788          */
789
790         if (vgaHWInit(&info->var, info, par, &timings))
791                 return -EINVAL;
792
793         /*
794          * The default value assigned by vgaHW.c is 0x41, but this does
795          * not work for NeoMagic.
796          */
797         par->Attribute[16] = 0x01;
798
799         switch (info->var.bits_per_pixel) {
800         case 8:
801                 par->CRTC[0x13] = info->var.xres_virtual >> 3;
802                 par->ExtCRTOffset = info->var.xres_virtual >> 11;
803                 par->ExtColorModeSelect = 0x11;
804                 break;
805         case 16:
806                 par->CRTC[0x13] = info->var.xres_virtual >> 2;
807                 par->ExtCRTOffset = info->var.xres_virtual >> 10;
808                 par->ExtColorModeSelect = 0x13;
809                 break;
810         case 24:
811                 par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
812                 par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
813                 par->ExtColorModeSelect = 0x14;
814                 break;
815 #ifdef NO_32BIT_SUPPORT_YET
816         case 32:                /* FIXME: guessed values */
817                 par->CRTC[0x13] = info->var.xres_virtual >> 1;
818                 par->ExtCRTOffset = info->var.xres_virtual >> 9;
819                 par->ExtColorModeSelect = 0x15;
820                 break;
821 #endif
822         default:
823                 break;
824         }
825
826         par->ExtCRTDispAddr = 0x10;
827
828         /* Vertical Extension */
829         par->VerticalExt = (((timings.VTotal - 2) & 0x400) >> 10)
830             | (((timings.VDisplay - 1) & 0x400) >> 9)
831             | (((timings.VSyncStart) & 0x400) >> 8)
832             | (((timings.VSyncStart) & 0x400) >> 7);
833
834         /* Fast write bursts on unless disabled. */
835         if (par->pci_burst)
836                 par->SysIfaceCntl1 = 0x30;
837         else
838                 par->SysIfaceCntl1 = 0x00;
839
840         par->SysIfaceCntl2 = 0xc0;      /* VESA Bios sets this to 0x80! */
841
842         /* Initialize: by default, we want display config register to be read */
843         par->PanelDispCntlRegRead = 1;
844
845         /* Enable any user specified display devices. */
846         par->PanelDispCntlReg1 = 0x00;
847         if (par->internal_display)
848                 par->PanelDispCntlReg1 |= 0x02;
849         if (par->external_display)
850                 par->PanelDispCntlReg1 |= 0x01;
851
852         /* If the user did not specify any display devices, then... */
853         if (par->PanelDispCntlReg1 == 0x00) {
854                 /* Default to internal (i.e., LCD) only. */
855                 par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
856         }
857
858         /* If we are using a fixed mode, then tell the chip we are. */
859         switch (info->var.xres) {
860         case 1280:
861                 par->PanelDispCntlReg1 |= 0x60;
862                 break;
863         case 1024:
864                 par->PanelDispCntlReg1 |= 0x40;
865                 break;
866         case 800:
867                 par->PanelDispCntlReg1 |= 0x20;
868                 break;
869         case 640:
870         default:
871                 break;
872         }
873
874         /* Setup shadow register locking. */
875         switch (par->PanelDispCntlReg1 & 0x03) {
876         case 0x01:              /* External CRT only mode: */
877                 par->GeneralLockReg = 0x00;
878                 /* We need to program the VCLK for external display only mode. */
879                 par->ProgramVCLK = 1;
880                 break;
881         case 0x02:              /* Internal LCD only mode: */
882         case 0x03:              /* Simultaneous internal/external (LCD/CRT) mode: */
883                 par->GeneralLockReg = 0x01;
884                 /* Don't program the VCLK when using the LCD. */
885                 par->ProgramVCLK = 0;
886                 break;
887         }
888
889         /*
890          * If the screen is to be stretched, turn on stretching for the
891          * various modes.
892          *
893          * OPTION_LCD_STRETCH means stretching should be turned off!
894          */
895         par->PanelDispCntlReg2 = 0x00;
896         par->PanelDispCntlReg3 = 0x00;
897
898         if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&     /* LCD only */
899             (info->var.xres != par->NeoPanelWidth)) {
900                 switch (info->var.xres) {
901                 case 320:       /* Needs testing.  KEM -- 24 May 98 */
902                 case 400:       /* Needs testing.  KEM -- 24 May 98 */
903                 case 640:
904                 case 800:
905                 case 1024:
906                         lcd_stretch = 1;
907                         par->PanelDispCntlReg2 |= 0xC6;
908                         break;
909                 default:
910                         lcd_stretch = 0;
911                         /* No stretching in these modes. */
912                 }
913         } else
914                 lcd_stretch = 0;
915
916         /*
917          * If the screen is to be centerd, turn on the centering for the
918          * various modes.
919          */
920         par->PanelVertCenterReg1 = 0x00;
921         par->PanelVertCenterReg2 = 0x00;
922         par->PanelVertCenterReg3 = 0x00;
923         par->PanelVertCenterReg4 = 0x00;
924         par->PanelVertCenterReg5 = 0x00;
925         par->PanelHorizCenterReg1 = 0x00;
926         par->PanelHorizCenterReg2 = 0x00;
927         par->PanelHorizCenterReg3 = 0x00;
928         par->PanelHorizCenterReg4 = 0x00;
929         par->PanelHorizCenterReg5 = 0x00;
930
931
932         if (par->PanelDispCntlReg1 & 0x02) {
933                 if (info->var.xres == par->NeoPanelWidth) {
934                         /*
935                          * No centering required when the requested display width
936                          * equals the panel width.
937                          */
938                 } else {
939                         par->PanelDispCntlReg2 |= 0x01;
940                         par->PanelDispCntlReg3 |= 0x10;
941
942                         /* Calculate the horizontal and vertical offsets. */
943                         if (!lcd_stretch) {
944                                 hoffset =
945                                     ((par->NeoPanelWidth -
946                                       info->var.xres) >> 4) - 1;
947                                 voffset =
948                                     ((par->NeoPanelHeight -
949                                       info->var.yres) >> 1) - 2;
950                         } else {
951                                 /* Stretched modes cannot be centered. */
952                                 hoffset = 0;
953                                 voffset = 0;
954                         }
955
956                         switch (info->var.xres) {
957                         case 320:       /* Needs testing.  KEM -- 24 May 98 */
958                                 par->PanelHorizCenterReg3 = hoffset;
959                                 par->PanelVertCenterReg2 = voffset;
960                                 break;
961                         case 400:       /* Needs testing.  KEM -- 24 May 98 */
962                                 par->PanelHorizCenterReg4 = hoffset;
963                                 par->PanelVertCenterReg1 = voffset;
964                                 break;
965                         case 640:
966                                 par->PanelHorizCenterReg1 = hoffset;
967                                 par->PanelVertCenterReg3 = voffset;
968                                 break;
969                         case 800:
970                                 par->PanelHorizCenterReg2 = hoffset;
971                                 par->PanelVertCenterReg4 = voffset;
972                                 break;
973                         case 1024:
974                                 par->PanelHorizCenterReg5 = hoffset;
975                                 par->PanelVertCenterReg5 = voffset;
976                                 break;
977                         case 1280:
978                         default:
979                                 /* No centering in these modes. */
980                                 break;
981                         }
982                 }
983         }
984
985         par->biosMode =
986             neoFindMode(info->var.xres, info->var.yres,
987                         info->var.bits_per_pixel);
988
989         /*
990          * Calculate the VCLK that most closely matches the requested dot
991          * clock.
992          */
993         neoCalcVCLK(info, par, timings.pixclock);
994
995         /* Since we program the clocks ourselves, always use VCLK3. */
996         par->MiscOutReg |= 0x0C;
997
998         /* alread unlocked above */
999         /* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */
1000
1001         /* don't know what this is, but it's 0 from bootup anyway */
1002         vga_wgfx(NULL, 0x15, 0x00);
1003
1004         /* was set to 0x01 by my bios in text and vesa modes */
1005         vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
1006
1007         /*
1008          * The color mode needs to be set before calling vgaHWRestore
1009          * to ensure the DAC is initialized properly.
1010          *
1011          * NOTE: Make sure we don't change bits make sure we don't change
1012          * any reserved bits.
1013          */
1014         temp = vga_rgfx(NULL, 0x90);
1015         switch (info->fix.accel) {
1016         case FB_ACCEL_NEOMAGIC_NM2070:
1017                 temp &= 0xF0;   /* Save bits 7:4 */
1018                 temp |= (par->ExtColorModeSelect & ~0xF0);
1019                 break;
1020         case FB_ACCEL_NEOMAGIC_NM2090:
1021         case FB_ACCEL_NEOMAGIC_NM2093:
1022         case FB_ACCEL_NEOMAGIC_NM2097:
1023         case FB_ACCEL_NEOMAGIC_NM2160:
1024         case FB_ACCEL_NEOMAGIC_NM2200:
1025         case FB_ACCEL_NEOMAGIC_NM2230:
1026         case FB_ACCEL_NEOMAGIC_NM2360:
1027         case FB_ACCEL_NEOMAGIC_NM2380:
1028                 temp &= 0x70;   /* Save bits 6:4 */
1029                 temp |= (par->ExtColorModeSelect & ~0x70);
1030                 break;
1031         }
1032
1033         vga_wgfx(NULL, 0x90, temp);
1034
1035         /*
1036          * In some rare cases a lockup might occur if we don't delay
1037          * here. (Reported by Miles Lane)
1038          */
1039         //mdelay(200);
1040
1041         /*
1042          * Disable horizontal and vertical graphics and text expansions so
1043          * that vgaHWRestore works properly.
1044          */
1045         temp = vga_rgfx(NULL, 0x25);
1046         temp &= 0x39;
1047         vga_wgfx(NULL, 0x25, temp);
1048
1049         /*
1050          * Sleep for 200ms to make sure that the two operations above have
1051          * had time to take effect.
1052          */
1053         mdelay(200);
1054
1055         /*
1056          * This function handles restoring the generic VGA registers.  */
1057         vgaHWRestore(info, par);
1058
1059         /* linear colormap for non palettized modes */
1060         switch (info->var.bits_per_pixel) {
1061         case 8:
1062                 /* PseudoColor, 256 */
1063                 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1064                 break;
1065         case 16:
1066                 /* TrueColor, 64k */
1067                 info->fix.visual = FB_VISUAL_TRUECOLOR;
1068
1069                 for (i = 0; i < 64; i++) {
1070                         outb(i, 0x3c8);
1071
1072                         outb(i << 1, 0x3c9);
1073                         outb(i, 0x3c9);
1074                         outb(i << 1, 0x3c9);
1075                 }
1076                 break;
1077         case 24:
1078 #ifdef NO_32BIT_SUPPORT_YET
1079         case 32:
1080 #endif
1081                 /* TrueColor, 16m */
1082                 info->fix.visual = FB_VISUAL_TRUECOLOR;
1083
1084                 for (i = 0; i < 256; i++) {
1085                         outb(i, 0x3c8);
1086
1087                         outb(i, 0x3c9);
1088                         outb(i, 0x3c9);
1089                         outb(i, 0x3c9);
1090                 }
1091                 break;
1092         }
1093
1094         vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
1095         vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
1096         temp = vga_rgfx(NULL, 0x10);
1097         temp &= 0x0F;           /* Save bits 3:0 */
1098         temp |= (par->SysIfaceCntl1 & ~0x0F);   /* VESA Bios sets bit 1! */
1099         vga_wgfx(NULL, 0x10, temp);
1100
1101         vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
1102         vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );
1103         vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );
1104
1105         temp = vga_rgfx(NULL, 0x20);
1106         switch (info->fix.accel) {
1107         case FB_ACCEL_NEOMAGIC_NM2070:
1108                 temp &= 0xFC;   /* Save bits 7:2 */
1109                 temp |= (par->PanelDispCntlReg1 & ~0xFC);
1110                 break;
1111         case FB_ACCEL_NEOMAGIC_NM2090:
1112         case FB_ACCEL_NEOMAGIC_NM2093:
1113         case FB_ACCEL_NEOMAGIC_NM2097:
1114         case FB_ACCEL_NEOMAGIC_NM2160:
1115                 temp &= 0xDC;   /* Save bits 7:6,4:2 */
1116                 temp |= (par->PanelDispCntlReg1 & ~0xDC);
1117                 break;
1118         case FB_ACCEL_NEOMAGIC_NM2200:
1119         case FB_ACCEL_NEOMAGIC_NM2230:
1120         case FB_ACCEL_NEOMAGIC_NM2360:
1121         case FB_ACCEL_NEOMAGIC_NM2380:
1122                 temp &= 0x98;   /* Save bits 7,4:3 */
1123                 temp |= (par->PanelDispCntlReg1 & ~0x98);
1124                 break;
1125         }
1126         vga_wgfx(NULL, 0x20, temp);
1127
1128         temp = vga_rgfx(NULL, 0x25);
1129         temp &= 0x38;           /* Save bits 5:3 */
1130         temp |= (par->PanelDispCntlReg2 & ~0x38);
1131         vga_wgfx(NULL, 0x25, temp);
1132
1133         if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1134                 temp = vga_rgfx(NULL, 0x30);
1135                 temp &= 0xEF;   /* Save bits 7:5 and bits 3:0 */
1136                 temp |= (par->PanelDispCntlReg3 & ~0xEF);
1137                 vga_wgfx(NULL, 0x30, temp);
1138         }
1139
1140         vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
1141         vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
1142         vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
1143
1144         if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1145                 vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
1146                 vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
1147                 vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
1148                 vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
1149         }
1150
1151         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
1152                 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1153
1154         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1155             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1156             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1157             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1158                 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1159                 vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
1160                 vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
1161
1162                 clock_hi = 1;
1163         }
1164
1165         /* Program VCLK3 if needed. */
1166         if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
1167                                  || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
1168                                  || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
1169                                                   != (par->VCLK3NumeratorHigh &
1170                                                       ~0x0F))))) {
1171                 vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
1172                 if (clock_hi) {
1173                         temp = vga_rgfx(NULL, 0x8F);
1174                         temp &= 0x0F;   /* Save bits 3:0 */
1175                         temp |= (par->VCLK3NumeratorHigh & ~0x0F);
1176                         vga_wgfx(NULL, 0x8F, temp);
1177                 }
1178                 vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
1179         }
1180
1181         if (par->biosMode)
1182                 vga_wcrt(NULL, 0x23, par->biosMode);
1183
1184         vga_wgfx(NULL, 0x93, 0xc0);     /* Gives 5x faster framebuffer writes !!! */
1185
1186         /* Program vertical extension register */
1187         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1188             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1189             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1190             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1191                 vga_wcrt(NULL, 0x70, par->VerticalExt);
1192         }
1193
1194         vgaHWProtect(0);        /* Turn on screen */
1195
1196         /* Calling this also locks offset registers required in update_start */
1197         neoLock(&par->state);
1198
1199         info->fix.line_length =
1200             info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
1201
1202         switch (info->fix.accel) {
1203                 case FB_ACCEL_NEOMAGIC_NM2200:
1204                 case FB_ACCEL_NEOMAGIC_NM2230: 
1205                 case FB_ACCEL_NEOMAGIC_NM2360: 
1206                 case FB_ACCEL_NEOMAGIC_NM2380: 
1207                         neo2200_accel_init(info, &info->var);
1208                         break;
1209                 default:
1210                         break;
1211         }       
1212         return 0;
1213 }
1214
1215 static void neofb_update_start(struct fb_info *info,
1216                                struct fb_var_screeninfo *var)
1217 {
1218         struct neofb_par *par = info->par;
1219         struct vgastate *state = &par->state;
1220         int oldExtCRTDispAddr;
1221         int Base;
1222
1223         DBG("neofb_update_start");
1224
1225         Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
1226         Base *= (var->bits_per_pixel + 7) / 8;
1227
1228         neoUnlock();
1229
1230         /*
1231          * These are the generic starting address registers.
1232          */
1233         vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
1234         vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
1235
1236         /*
1237          * Make sure we don't clobber some other bits that might already
1238          * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
1239          * be needed.
1240          */
1241         oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
1242         vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
1243
1244         neoLock(state);
1245 }
1246
1247 /*
1248  *    Pan or Wrap the Display
1249  */
1250 static int neofb_pan_display(struct fb_var_screeninfo *var,
1251                              struct fb_info *info)
1252 {
1253         u_int y_bottom;
1254
1255         y_bottom = var->yoffset;
1256
1257         if (!(var->vmode & FB_VMODE_YWRAP))
1258                 y_bottom += var->yres;
1259
1260         if (var->xoffset > (var->xres_virtual - var->xres))
1261                 return -EINVAL;
1262         if (y_bottom > info->var.yres_virtual)
1263                 return -EINVAL;
1264
1265         neofb_update_start(info, var);
1266
1267         info->var.xoffset = var->xoffset;
1268         info->var.yoffset = var->yoffset;
1269
1270         if (var->vmode & FB_VMODE_YWRAP)
1271                 info->var.vmode |= FB_VMODE_YWRAP;
1272         else
1273                 info->var.vmode &= ~FB_VMODE_YWRAP;
1274         return 0;
1275 }
1276
1277 static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1278                            u_int transp, struct fb_info *fb)
1279 {
1280         if (regno >= fb->cmap.len || regno > 255)
1281                 return -EINVAL;
1282
1283         switch (fb->var.bits_per_pixel) {
1284         case 8:
1285                 outb(regno, 0x3c8);
1286
1287                 outb(red >> 10, 0x3c9);
1288                 outb(green >> 10, 0x3c9);
1289                 outb(blue >> 10, 0x3c9);
1290                 break;
1291         case 16:
1292                 ((u32 *) fb->pseudo_palette)[regno] =
1293                                 ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
1294                                 ((blue & 0xf800) >> 11);
1295                 break;
1296         case 24:
1297                 ((u32 *) fb->pseudo_palette)[regno] =
1298                                 ((red & 0xff00) << 8) | ((green & 0xff00)) |
1299                                 ((blue & 0xff00) >> 8);
1300                 break;
1301 #ifdef NO_32BIT_SUPPORT_YET
1302         case 32:
1303                 ((u32 *) fb->pseudo_palette)[regno] =
1304                                 ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
1305                                 ((green & 0xff00)) | ((blue & 0xff00) >> 8);
1306                 break;
1307 #endif
1308         default:
1309                 return 1;
1310         }
1311         return 0;
1312 }
1313
1314 /*
1315  *    (Un)Blank the display.
1316  */
1317 static int neofb_blank(int blank_mode, struct fb_info *info)
1318 {
1319         /*
1320          *  Blank the screen if blank_mode != 0, else unblank.
1321          *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
1322          *  e.g. a video mode which doesn't support it. Implements VESA suspend
1323          *  and powerdown modes for monitors, and backlight control on LCDs.
1324          *    blank_mode == 0: unblanked (backlight on)
1325          *    blank_mode == 1: blank (backlight on)
1326          *    blank_mode == 2: suspend vsync (backlight off)
1327          *    blank_mode == 3: suspend hsync (backlight off)
1328          *    blank_mode == 4: powerdown (backlight off)
1329          *
1330          *  wms...Enable VESA DPMS compatible powerdown mode
1331          *  run "setterm -powersave powerdown" to take advantage
1332          */
1333         struct neofb_par *par = info->par;
1334         int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
1335
1336         /*
1337          * Read back the register bits related to display configuration. They might
1338          * have been changed underneath the driver via Fn key stroke.
1339          */
1340         neoUnlock();
1341         tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
1342         neoLock(&par->state);
1343
1344         /* In case we blank the screen, we want to store the possibly new
1345          * configuration in the driver. During un-blank, we re-apply this setting,
1346          * since the LCD bit will be cleared in order to switch off the backlight.
1347          */
1348         if (par->PanelDispCntlRegRead) {
1349                 par->PanelDispCntlReg1 = tmpdisp;
1350         }
1351         par->PanelDispCntlRegRead = !blank_mode;
1352
1353         switch (blank_mode) {
1354         case FB_BLANK_POWERDOWN:        /* powerdown - both sync lines down */
1355                 seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
1356                 lcdflags = 0;                   /* LCD off */
1357                 dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
1358                             NEO_GR01_SUPPRESS_VSYNC;
1359 #ifdef CONFIG_TOSHIBA
1360                 /* Do we still need this ? */
1361                 /* attempt to turn off backlight on toshiba; also turns off external */
1362                 {
1363                         SMMRegisters regs;
1364
1365                         regs.eax = 0xff00; /* HCI_SET */
1366                         regs.ebx = 0x0002; /* HCI_BACKLIGHT */
1367                         regs.ecx = 0x0000; /* HCI_DISABLE */
1368                         tosh_smm(&regs);
1369                 }
1370 #endif
1371                 break;
1372         case FB_BLANK_HSYNC_SUSPEND:            /* hsync off */
1373                 seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
1374                 lcdflags = 0;                   /* LCD off */
1375                 dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
1376                 break;
1377         case FB_BLANK_VSYNC_SUSPEND:            /* vsync off */
1378                 seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
1379                 lcdflags = 0;                   /* LCD off */
1380                 dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
1381                 break;
1382         case FB_BLANK_NORMAL:           /* just blank screen (backlight stays on) */
1383                 seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
1384                 /*
1385                  * During a blank operation with the LID shut, we might store "LCD off"
1386                  * by mistake. Due to timing issues, the BIOS may switch the lights
1387                  * back on, and we turn it back off once we "unblank".
1388                  *
1389                  * So here is an attempt to implement ">=" - if we are in the process
1390                  * of unblanking, and the LCD bit is unset in the driver but set in the
1391                  * register, we must keep it.
1392                  */
1393                 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
1394                 dpmsflags = 0x00;       /* no hsync/vsync suppression */
1395                 break;
1396         case FB_BLANK_UNBLANK:          /* unblank */
1397                 seqflags = 0;                   /* Enable sequencer */
1398                 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
1399                 dpmsflags = 0x00;       /* no hsync/vsync suppression */
1400 #ifdef CONFIG_TOSHIBA
1401                 /* Do we still need this ? */
1402                 /* attempt to re-enable backlight/external on toshiba */
1403                 {
1404                         SMMRegisters regs;
1405
1406                         regs.eax = 0xff00; /* HCI_SET */
1407                         regs.ebx = 0x0002; /* HCI_BACKLIGHT */
1408                         regs.ecx = 0x0001; /* HCI_ENABLE */
1409                         tosh_smm(&regs);
1410                 }
1411 #endif
1412                 break;
1413         default:        /* Anything else we don't understand; return 1 to tell
1414                          * fb_blank we didn't aactually do anything */
1415                 return 1;
1416         }
1417
1418         neoUnlock();
1419         reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
1420         vga_wseq(NULL, 0x01, reg);
1421         reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
1422         vga_wgfx(NULL, 0x20, reg);
1423         reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
1424         vga_wgfx(NULL, 0x01, reg);
1425         neoLock(&par->state);
1426         return 0;
1427 }
1428
1429 static void
1430 neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1431 {
1432         struct neofb_par *par = info->par;
1433         u_long dst, rop;
1434
1435         dst = rect->dx + rect->dy * info->var.xres_virtual;
1436         rop = rect->rop ? 0x060000 : 0x0c0000;
1437
1438         neo2200_wait_fifo(info, 4);
1439
1440         /* set blt control */
1441         writel(NEO_BC3_FIFO_EN |
1442                NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
1443                //               NEO_BC3_DST_XY_ADDR  |
1444                //               NEO_BC3_SRC_XY_ADDR  |
1445                rop, &par->neo2200->bltCntl);
1446
1447         switch (info->var.bits_per_pixel) {
1448         case 8:
1449                 writel(rect->color, &par->neo2200->fgColor);
1450                 break;
1451         case 16:
1452         case 24:
1453                 writel(((u32 *) (info->pseudo_palette))[rect->color],
1454                        &par->neo2200->fgColor);
1455                 break;
1456         }
1457
1458         writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
1459                &par->neo2200->dstStart);
1460         writel((rect->height << 16) | (rect->width & 0xffff),
1461                &par->neo2200->xyExt);
1462 }
1463
1464 static void
1465 neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1466 {
1467         u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
1468         struct neofb_par *par = info->par;
1469         u_long src, dst, bltCntl;
1470
1471         bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
1472
1473         if ((dy > sy) || ((dy == sy) && (dx > sx))) {
1474                 /* Start with the lower right corner */
1475                 sy += (area->height - 1);
1476                 dy += (area->height - 1);
1477                 sx += (area->width - 1);
1478                 dx += (area->width - 1);
1479
1480                 bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
1481         }
1482
1483         src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
1484         dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
1485
1486         neo2200_wait_fifo(info, 4);
1487
1488         /* set blt control */
1489         writel(bltCntl, &par->neo2200->bltCntl);
1490
1491         writel(src, &par->neo2200->srcStart);
1492         writel(dst, &par->neo2200->dstStart);
1493         writel((area->height << 16) | (area->width & 0xffff),
1494                &par->neo2200->xyExt);
1495 }
1496
1497 static void
1498 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
1499 {
1500         struct neofb_par *par = info->par;
1501         int s_pitch = (image->width * image->depth + 7) >> 3;
1502         int scan_align = info->pixmap.scan_align - 1;
1503         int buf_align = info->pixmap.buf_align - 1;
1504         int bltCntl_flags, d_pitch, data_len;
1505
1506         // The data is padded for the hardware
1507         d_pitch = (s_pitch + scan_align) & ~scan_align;
1508         data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
1509
1510         neo2200_sync(info);
1511
1512         if (image->depth == 1) {
1513                 if (info->var.bits_per_pixel == 24 && image->width < 16) {
1514                         /* FIXME. There is a bug with accelerated color-expanded
1515                          * transfers in 24 bit mode if the image being transferred
1516                          * is less than 16 bits wide. This is due to insufficient
1517                          * padding when writing the image. We need to adjust
1518                          * struct fb_pixmap. Not yet done. */
1519                         return cfb_imageblit(info, image);
1520                 }
1521                 bltCntl_flags = NEO_BC0_SRC_MONO;
1522         } else if (image->depth == info->var.bits_per_pixel) {
1523                 bltCntl_flags = 0;
1524         } else {
1525                 /* We don't currently support hardware acceleration if image
1526                  * depth is different from display */
1527                 return cfb_imageblit(info, image);
1528         }
1529
1530         switch (info->var.bits_per_pixel) {
1531         case 8:
1532                 writel(image->fg_color, &par->neo2200->fgColor);
1533                 writel(image->bg_color, &par->neo2200->bgColor);
1534                 break;
1535         case 16:
1536         case 24:
1537                 writel(((u32 *) (info->pseudo_palette))[image->fg_color],
1538                        &par->neo2200->fgColor);
1539                 writel(((u32 *) (info->pseudo_palette))[image->bg_color],
1540                        &par->neo2200->bgColor);
1541                 break;
1542         }
1543
1544         writel(NEO_BC0_SYS_TO_VID |
1545                 NEO_BC3_SKIP_MAPPING | bltCntl_flags |
1546                 // NEO_BC3_DST_XY_ADDR |
1547                 0x0c0000, &par->neo2200->bltCntl);
1548
1549         writel(0, &par->neo2200->srcStart);
1550 //      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
1551         writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
1552                 image->dy * info->fix.line_length), &par->neo2200->dstStart);
1553         writel((image->height << 16) | (image->width & 0xffff),
1554                &par->neo2200->xyExt);
1555
1556         memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
1557 }
1558
1559 static void
1560 neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1561 {
1562         switch (info->fix.accel) {
1563                 case FB_ACCEL_NEOMAGIC_NM2200:
1564                 case FB_ACCEL_NEOMAGIC_NM2230: 
1565                 case FB_ACCEL_NEOMAGIC_NM2360: 
1566                 case FB_ACCEL_NEOMAGIC_NM2380:
1567                         neo2200_fillrect(info, rect);
1568                         break;
1569                 default:
1570                         cfb_fillrect(info, rect);
1571                         break;
1572         }       
1573 }
1574
1575 static void
1576 neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1577 {
1578         switch (info->fix.accel) {
1579                 case FB_ACCEL_NEOMAGIC_NM2200:
1580                 case FB_ACCEL_NEOMAGIC_NM2230: 
1581                 case FB_ACCEL_NEOMAGIC_NM2360: 
1582                 case FB_ACCEL_NEOMAGIC_NM2380: 
1583                         neo2200_copyarea(info, area);
1584                         break;
1585                 default:
1586                         cfb_copyarea(info, area);
1587                         break;
1588         }       
1589 }
1590
1591 static void
1592 neofb_imageblit(struct fb_info *info, const struct fb_image *image)
1593 {
1594         switch (info->fix.accel) {
1595                 case FB_ACCEL_NEOMAGIC_NM2200:
1596                 case FB_ACCEL_NEOMAGIC_NM2230:
1597                 case FB_ACCEL_NEOMAGIC_NM2360:
1598                 case FB_ACCEL_NEOMAGIC_NM2380:
1599                         neo2200_imageblit(info, image);
1600                         break;
1601                 default:
1602                         cfb_imageblit(info, image);
1603                         break;
1604         }
1605 }
1606
1607 static int 
1608 neofb_sync(struct fb_info *info)
1609 {
1610         switch (info->fix.accel) {
1611                 case FB_ACCEL_NEOMAGIC_NM2200:
1612                 case FB_ACCEL_NEOMAGIC_NM2230: 
1613                 case FB_ACCEL_NEOMAGIC_NM2360: 
1614                 case FB_ACCEL_NEOMAGIC_NM2380: 
1615                         neo2200_sync(info);
1616                         break;
1617                 default:
1618                         break;
1619         }
1620         return 0;               
1621 }
1622
1623 /*
1624 static void
1625 neofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width)
1626 {
1627         //memset_io(info->sprite.addr, 0xff, 1);
1628 }
1629
1630 static int
1631 neofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1632 {
1633         struct neofb_par *par = (struct neofb_par *) info->par;
1634
1635         * Disable cursor *
1636         write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);
1637
1638         if (cursor->set & FB_CUR_SETPOS) {
1639                 u32 x = cursor->image.dx;
1640                 u32 y = cursor->image.dy;
1641
1642                 info->cursor.image.dx = x;
1643                 info->cursor.image.dy = y;
1644                 write_le32(NEOREG_CURSX, x, par);
1645                 write_le32(NEOREG_CURSY, y, par);
1646         }
1647
1648         if (cursor->set & FB_CUR_SETSIZE) {
1649                 info->cursor.image.height = cursor->image.height;
1650                 info->cursor.image.width = cursor->image.width;
1651         }
1652
1653         if (cursor->set & FB_CUR_SETHOT)
1654                 info->cursor.hot = cursor->hot;
1655
1656         if (cursor->set & FB_CUR_SETCMAP) {
1657                 if (cursor->image.depth == 1) {
1658                         u32 fg = cursor->image.fg_color;
1659                         u32 bg = cursor->image.bg_color;
1660
1661                         info->cursor.image.fg_color = fg;
1662                         info->cursor.image.bg_color = bg;
1663
1664                         fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
1665                         bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
1666                         write_le32(NEOREG_CURSFGCOLOR, fg, par);
1667                         write_le32(NEOREG_CURSBGCOLOR, bg, par);
1668                 }
1669         }
1670
1671         if (cursor->set & FB_CUR_SETSHAPE)
1672                 fb_load_cursor_image(info);
1673
1674         if (info->cursor.enable)
1675                 write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);
1676         return 0;
1677 }
1678 */
1679
1680 static struct fb_ops neofb_ops = {
1681         .owner          = THIS_MODULE,
1682         .fb_open        = neofb_open,
1683         .fb_release     = neofb_release,
1684         .fb_check_var   = neofb_check_var,
1685         .fb_set_par     = neofb_set_par,
1686         .fb_setcolreg   = neofb_setcolreg,
1687         .fb_pan_display = neofb_pan_display,
1688         .fb_blank       = neofb_blank,
1689         .fb_sync        = neofb_sync,
1690         .fb_fillrect    = neofb_fillrect,
1691         .fb_copyarea    = neofb_copyarea,
1692         .fb_imageblit   = neofb_imageblit,
1693 };
1694
1695 /* --------------------------------------------------------------------- */
1696
1697 static struct fb_videomode __devinitdata mode800x480 = {
1698         .xres           = 800,
1699         .yres           = 480,
1700         .pixclock       = 25000,
1701         .left_margin    = 88,
1702         .right_margin   = 40,
1703         .upper_margin   = 23,
1704         .lower_margin   = 1,
1705         .hsync_len      = 128,
1706         .vsync_len      = 4,
1707         .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1708         .vmode          = FB_VMODE_NONINTERLACED
1709 };
1710
1711 static int __devinit neo_map_mmio(struct fb_info *info,
1712                                   struct pci_dev *dev)
1713 {
1714         struct neofb_par *par = info->par;
1715
1716         DBG("neo_map_mmio");
1717
1718         switch (info->fix.accel) {
1719                 case FB_ACCEL_NEOMAGIC_NM2070:
1720                         info->fix.mmio_start = pci_resource_start(dev, 0)+
1721                                 0x100000;
1722                         break;
1723                 case FB_ACCEL_NEOMAGIC_NM2090:
1724                 case FB_ACCEL_NEOMAGIC_NM2093:
1725                         info->fix.mmio_start = pci_resource_start(dev, 0)+
1726                                 0x200000;
1727                         break;
1728                 case FB_ACCEL_NEOMAGIC_NM2160:
1729                 case FB_ACCEL_NEOMAGIC_NM2097:
1730                 case FB_ACCEL_NEOMAGIC_NM2200:
1731                 case FB_ACCEL_NEOMAGIC_NM2230:
1732                 case FB_ACCEL_NEOMAGIC_NM2360:
1733                 case FB_ACCEL_NEOMAGIC_NM2380:
1734                         info->fix.mmio_start = pci_resource_start(dev, 1);
1735                         break;
1736                 default:
1737                         info->fix.mmio_start = pci_resource_start(dev, 0);
1738         }
1739         info->fix.mmio_len = MMIO_SIZE;
1740
1741         if (!request_mem_region
1742             (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
1743                 printk("neofb: memory mapped IO in use\n");
1744                 return -EBUSY;
1745         }
1746
1747         par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
1748         if (!par->mmio_vbase) {
1749                 printk("neofb: unable to map memory mapped IO\n");
1750                 release_mem_region(info->fix.mmio_start,
1751                                    info->fix.mmio_len);
1752                 return -ENOMEM;
1753         } else
1754                 printk(KERN_INFO "neofb: mapped io at %p\n",
1755                        par->mmio_vbase);
1756         return 0;
1757 }
1758
1759 static void neo_unmap_mmio(struct fb_info *info)
1760 {
1761         struct neofb_par *par = info->par;
1762
1763         DBG("neo_unmap_mmio");
1764
1765         iounmap(par->mmio_vbase);
1766         par->mmio_vbase = NULL;
1767
1768         release_mem_region(info->fix.mmio_start,
1769                            info->fix.mmio_len);
1770 }
1771
1772 static int __devinit neo_map_video(struct fb_info *info,
1773                                    struct pci_dev *dev, int video_len)
1774 {
1775         //unsigned long addr;
1776
1777         DBG("neo_map_video");
1778
1779         info->fix.smem_start = pci_resource_start(dev, 0);
1780         info->fix.smem_len = video_len;
1781
1782         if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
1783                                 "frame buffer")) {
1784                 printk("neofb: frame buffer in use\n");
1785                 return -EBUSY;
1786         }
1787
1788         info->screen_base =
1789             ioremap(info->fix.smem_start, info->fix.smem_len);
1790         if (!info->screen_base) {
1791                 printk("neofb: unable to map screen memory\n");
1792                 release_mem_region(info->fix.smem_start,
1793                                    info->fix.smem_len);
1794                 return -ENOMEM;
1795         } else
1796                 printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
1797                        info->screen_base);
1798
1799 #ifdef CONFIG_MTRR
1800         ((struct neofb_par *)(info->par))->mtrr =
1801                 mtrr_add(info->fix.smem_start, pci_resource_len(dev, 0),
1802                                 MTRR_TYPE_WRCOMB, 1);
1803 #endif
1804
1805         /* Clear framebuffer, it's all white in memory after boot */
1806         memset_io(info->screen_base, 0, info->fix.smem_len);
1807
1808         /* Allocate Cursor drawing pad.
1809         info->fix.smem_len -= PAGE_SIZE;
1810         addr = info->fix.smem_start + info->fix.smem_len;
1811         write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) |
1812                                         ((0x0ff0 & (addr >> 10)) >> 4), par);
1813         addr = (unsigned long) info->screen_base + info->fix.smem_len;
1814         info->sprite.addr = (u8 *) addr; */
1815         return 0;
1816 }
1817
1818 static void neo_unmap_video(struct fb_info *info)
1819 {
1820         DBG("neo_unmap_video");
1821
1822 #ifdef CONFIG_MTRR
1823         {
1824                 struct neofb_par *par = info->par;
1825
1826                 mtrr_del(par->mtrr, info->fix.smem_start,
1827                          info->fix.smem_len);
1828         }
1829 #endif
1830         iounmap(info->screen_base);
1831         info->screen_base = NULL;
1832
1833         release_mem_region(info->fix.smem_start,
1834                            info->fix.smem_len);
1835 }
1836
1837 static int __devinit neo_scan_monitor(struct fb_info *info)
1838 {
1839         struct neofb_par *par = info->par;
1840         unsigned char type, display;
1841         int w;
1842
1843         // Eventually we will have i2c support.
1844         info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
1845         if (!info->monspecs.modedb)
1846                 return -ENOMEM;
1847         info->monspecs.modedb_len = 1;
1848
1849         /* Determine the panel type */
1850         vga_wgfx(NULL, 0x09, 0x26);
1851         type = vga_rgfx(NULL, 0x21);
1852         display = vga_rgfx(NULL, 0x20);
1853         if (!par->internal_display && !par->external_display) {
1854                 par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
1855                 par->external_display = display & 1;
1856                 printk (KERN_INFO "Autodetected %s display\n",
1857                         par->internal_display && par->external_display ? "simultaneous" :
1858                         par->internal_display ? "internal" : "external");
1859         }
1860
1861         /* Determine panel width -- used in NeoValidMode. */
1862         w = vga_rgfx(NULL, 0x20);
1863         vga_wgfx(NULL, 0x09, 0x00);
1864         switch ((w & 0x18) >> 3) {
1865         case 0x00:
1866                 // 640x480@60
1867                 par->NeoPanelWidth = 640;
1868                 par->NeoPanelHeight = 480;
1869                 memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
1870                 break;
1871         case 0x01:
1872                 par->NeoPanelWidth = 800;
1873                 if (par->libretto) {
1874                         par->NeoPanelHeight = 480;
1875                         memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
1876                 } else {
1877                         // 800x600@60
1878                         par->NeoPanelHeight = 600;
1879                         memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
1880                 }
1881                 break;
1882         case 0x02:
1883                 // 1024x768@60
1884                 par->NeoPanelWidth = 1024;
1885                 par->NeoPanelHeight = 768;
1886                 memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
1887                 break;
1888         case 0x03:
1889                 /* 1280x1024@60 panel support needs to be added */
1890 #ifdef NOT_DONE
1891                 par->NeoPanelWidth = 1280;
1892                 par->NeoPanelHeight = 1024;
1893                 memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
1894                 break;
1895 #else
1896                 printk(KERN_ERR
1897                        "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
1898                 return -1;
1899 #endif
1900         default:
1901                 // 640x480@60
1902                 par->NeoPanelWidth = 640;
1903                 par->NeoPanelHeight = 480;
1904                 memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
1905                 break;
1906         }
1907
1908         printk(KERN_INFO "Panel is a %dx%d %s %s display\n",
1909                par->NeoPanelWidth,
1910                par->NeoPanelHeight,
1911                (type & 0x02) ? "color" : "monochrome",
1912                (type & 0x10) ? "TFT" : "dual scan");
1913         return 0;
1914 }
1915
1916 static int __devinit neo_init_hw(struct fb_info *info)
1917 {
1918         struct neofb_par *par = info->par;
1919         int videoRam = 896;
1920         int maxClock = 65000;
1921         int CursorMem = 1024;
1922         int CursorOff = 0x100;
1923         int linearSize = 1024;
1924         int maxWidth = 1024;
1925         int maxHeight = 1024;
1926
1927         DBG("neo_init_hw");
1928
1929         neoUnlock();
1930
1931 #if 0
1932         printk(KERN_DEBUG "--- Neo extended register dump ---\n");
1933         for (int w = 0; w < 0x85; w++)
1934                 printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
1935                        (void *) vga_rcrt(NULL, w);
1936         for (int w = 0; w < 0xC7; w++)
1937                 printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
1938                        (void *) vga_rgfx(NULL, w));
1939 #endif
1940         switch (info->fix.accel) {
1941         case FB_ACCEL_NEOMAGIC_NM2070:
1942                 videoRam = 896;
1943                 maxClock = 65000;
1944                 CursorMem = 2048;
1945                 CursorOff = 0x100;
1946                 linearSize = 1024;
1947                 maxWidth = 1024;
1948                 maxHeight = 1024;
1949                 break;
1950         case FB_ACCEL_NEOMAGIC_NM2090:
1951         case FB_ACCEL_NEOMAGIC_NM2093:
1952                 videoRam = 1152;
1953                 maxClock = 80000;
1954                 CursorMem = 2048;
1955                 CursorOff = 0x100;
1956                 linearSize = 2048;
1957                 maxWidth = 1024;
1958                 maxHeight = 1024;
1959                 break;
1960         case FB_ACCEL_NEOMAGIC_NM2097:
1961                 videoRam = 1152;
1962                 maxClock = 80000;
1963                 CursorMem = 1024;
1964                 CursorOff = 0x100;
1965                 linearSize = 2048;
1966                 maxWidth = 1024;
1967                 maxHeight = 1024;
1968                 break;
1969         case FB_ACCEL_NEOMAGIC_NM2160:
1970                 videoRam = 2048;
1971                 maxClock = 90000;
1972                 CursorMem = 1024;
1973                 CursorOff = 0x100;
1974                 linearSize = 2048;
1975                 maxWidth = 1024;
1976                 maxHeight = 1024;
1977                 break;
1978         case FB_ACCEL_NEOMAGIC_NM2200:
1979                 videoRam = 2560;
1980                 maxClock = 110000;
1981                 CursorMem = 1024;
1982                 CursorOff = 0x1000;
1983                 linearSize = 4096;
1984                 maxWidth = 1280;
1985                 maxHeight = 1024;       /* ???? */
1986
1987                 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1988                 break;
1989         case FB_ACCEL_NEOMAGIC_NM2230:
1990                 videoRam = 3008;
1991                 maxClock = 110000;
1992                 CursorMem = 1024;
1993                 CursorOff = 0x1000;
1994                 linearSize = 4096;
1995                 maxWidth = 1280;
1996                 maxHeight = 1024;       /* ???? */
1997
1998                 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1999                 break;
2000         case FB_ACCEL_NEOMAGIC_NM2360:
2001                 videoRam = 4096;
2002                 maxClock = 110000;
2003                 CursorMem = 1024;
2004                 CursorOff = 0x1000;
2005                 linearSize = 4096;
2006                 maxWidth = 1280;
2007                 maxHeight = 1024;       /* ???? */
2008
2009                 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2010                 break;
2011         case FB_ACCEL_NEOMAGIC_NM2380:
2012                 videoRam = 6144;
2013                 maxClock = 110000;
2014                 CursorMem = 1024;
2015                 CursorOff = 0x1000;
2016                 linearSize = 8192;
2017                 maxWidth = 1280;
2018                 maxHeight = 1024;       /* ???? */
2019
2020                 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
2021                 break;
2022         }
2023 /*
2024         info->sprite.size = CursorMem;
2025         info->sprite.scan_align = 1;
2026         info->sprite.buf_align = 1;
2027         info->sprite.flags = FB_PIXMAP_IO;
2028         info->sprite.outbuf = neofb_draw_cursor;
2029 */
2030         par->maxClock = maxClock;
2031         par->cursorOff = CursorOff;
2032         return ((videoRam * 1024));
2033 }
2034
2035
2036 static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const struct
2037                                                    pci_device_id *id)
2038 {
2039         struct fb_info *info;
2040         struct neofb_par *par;
2041
2042         info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
2043
2044         if (!info)
2045                 return NULL;
2046
2047         par = info->par;
2048
2049         info->fix.accel = id->driver_data;
2050
2051         par->pci_burst = !nopciburst;
2052         par->lcd_stretch = !nostretch;
2053         par->libretto = libretto;
2054
2055         par->internal_display = internal;
2056         par->external_display = external;
2057         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2058
2059         switch (info->fix.accel) {
2060         case FB_ACCEL_NEOMAGIC_NM2070:
2061                 sprintf(info->fix.id, "MagicGraph 128");
2062                 break;
2063         case FB_ACCEL_NEOMAGIC_NM2090:
2064                 sprintf(info->fix.id, "MagicGraph 128V");
2065                 break;
2066         case FB_ACCEL_NEOMAGIC_NM2093:
2067                 sprintf(info->fix.id, "MagicGraph 128ZV");
2068                 break;
2069         case FB_ACCEL_NEOMAGIC_NM2097:
2070                 sprintf(info->fix.id, "MagicGraph 128ZV+");
2071                 break;
2072         case FB_ACCEL_NEOMAGIC_NM2160:
2073                 sprintf(info->fix.id, "MagicGraph 128XD");
2074                 break;
2075         case FB_ACCEL_NEOMAGIC_NM2200:
2076                 sprintf(info->fix.id, "MagicGraph 256AV");
2077                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
2078                                FBINFO_HWACCEL_COPYAREA |
2079                                FBINFO_HWACCEL_FILLRECT;
2080                 break;
2081         case FB_ACCEL_NEOMAGIC_NM2230:
2082                 sprintf(info->fix.id, "MagicGraph 256AV+");
2083                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
2084                                FBINFO_HWACCEL_COPYAREA |
2085                                FBINFO_HWACCEL_FILLRECT;
2086                 break;
2087         case FB_ACCEL_NEOMAGIC_NM2360:
2088                 sprintf(info->fix.id, "MagicGraph 256ZX");
2089                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
2090                                FBINFO_HWACCEL_COPYAREA |
2091                                FBINFO_HWACCEL_FILLRECT;
2092                 break;
2093         case FB_ACCEL_NEOMAGIC_NM2380:
2094                 sprintf(info->fix.id, "MagicGraph 256XL+");
2095                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
2096                                FBINFO_HWACCEL_COPYAREA |
2097                                FBINFO_HWACCEL_FILLRECT;
2098                 break;
2099         }
2100
2101         info->fix.type = FB_TYPE_PACKED_PIXELS;
2102         info->fix.type_aux = 0;
2103         info->fix.xpanstep = 0;
2104         info->fix.ypanstep = 4;
2105         info->fix.ywrapstep = 0;
2106         info->fix.accel = id->driver_data;
2107
2108         info->fbops = &neofb_ops;
2109         info->pseudo_palette = par->palette;
2110         return info;
2111 }
2112
2113 static void neo_free_fb_info(struct fb_info *info)
2114 {
2115         if (info) {
2116                 /*
2117                  * Free the colourmap
2118                  */
2119                 fb_dealloc_cmap(&info->cmap);
2120                 framebuffer_release(info);
2121         }
2122 }
2123
2124 /* --------------------------------------------------------------------- */
2125
2126 static int __devinit neofb_probe(struct pci_dev *dev,
2127                                  const struct pci_device_id *id)
2128 {
2129         struct fb_info *info;
2130         u_int h_sync, v_sync;
2131         int video_len, err;
2132
2133         DBG("neofb_probe");
2134
2135         err = pci_enable_device(dev);
2136         if (err)
2137                 return err;
2138
2139         err = -ENOMEM;
2140         info = neo_alloc_fb_info(dev, id);
2141         if (!info)
2142                 return err;
2143
2144         err = neo_map_mmio(info, dev);
2145         if (err)
2146                 goto err_map_mmio;
2147
2148         err = neo_scan_monitor(info);
2149         if (err)
2150                 goto err_scan_monitor;
2151
2152         video_len = neo_init_hw(info);
2153         if (video_len < 0) {
2154                 err = video_len;
2155                 goto err_init_hw;
2156         }
2157
2158         err = neo_map_video(info, dev, video_len);
2159         if (err)
2160                 goto err_init_hw;
2161
2162         if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
2163                         info->monspecs.modedb, 16)) {
2164                 printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
2165                 goto err_map_video;
2166         }
2167
2168         /*
2169          * Calculate the hsync and vsync frequencies.  Note that
2170          * we split the 1e12 constant up so that we can preserve
2171          * the precision and fit the results into 32-bit registers.
2172          *  (1953125000 * 512 = 1e12)
2173          */
2174         h_sync = 1953125000 / info->var.pixclock;
2175         h_sync =
2176             h_sync * 512 / (info->var.xres + info->var.left_margin +
2177                             info->var.right_margin + info->var.hsync_len);
2178         v_sync =
2179             h_sync / (info->var.yres + info->var.upper_margin +
2180                       info->var.lower_margin + info->var.vsync_len);
2181
2182         printk(KERN_INFO "neofb v" NEOFB_VERSION
2183                ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2184                info->fix.smem_len >> 10, info->var.xres,
2185                info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
2186
2187         if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
2188                 goto err_map_video;
2189
2190         err = register_framebuffer(info);
2191         if (err < 0)
2192                 goto err_reg_fb;
2193
2194         printk(KERN_INFO "fb%d: %s frame buffer device\n",
2195                info->node, info->fix.id);
2196
2197         /*
2198          * Our driver data
2199          */
2200         pci_set_drvdata(dev, info);
2201         return 0;
2202
2203 err_reg_fb:
2204         fb_dealloc_cmap(&info->cmap);
2205 err_map_video:
2206         neo_unmap_video(info);
2207 err_init_hw:
2208         fb_destroy_modedb(info->monspecs.modedb);
2209 err_scan_monitor:
2210         neo_unmap_mmio(info);
2211 err_map_mmio:
2212         neo_free_fb_info(info);
2213         return err;
2214 }
2215
2216 static void __devexit neofb_remove(struct pci_dev *dev)
2217 {
2218         struct fb_info *info = pci_get_drvdata(dev);
2219
2220         DBG("neofb_remove");
2221
2222         if (info) {
2223                 /*
2224                  * If unregister_framebuffer fails, then
2225                  * we will be leaving hooks that could cause
2226                  * oopsen laying around.
2227                  */
2228                 if (unregister_framebuffer(info))
2229                         printk(KERN_WARNING
2230                                "neofb: danger danger!  Oopsen imminent!\n");
2231
2232                 neo_unmap_video(info);
2233                 fb_destroy_modedb(info->monspecs.modedb);
2234                 neo_unmap_mmio(info);
2235                 neo_free_fb_info(info);
2236
2237                 /*
2238                  * Ensure that the driver data is no longer
2239                  * valid.
2240                  */
2241                 pci_set_drvdata(dev, NULL);
2242         }
2243 }
2244
2245 static struct pci_device_id neofb_devices[] = {
2246         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
2247          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
2248
2249         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
2250          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
2251
2252         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
2253          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
2254
2255         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
2256          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
2257
2258         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
2259          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
2260
2261         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
2262          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
2263
2264         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
2265          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
2266
2267         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
2268          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
2269
2270         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
2271          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
2272
2273         {0, 0, 0, 0, 0, 0, 0}
2274 };
2275
2276 MODULE_DEVICE_TABLE(pci, neofb_devices);
2277
2278 static struct pci_driver neofb_driver = {
2279         .name =         "neofb",
2280         .id_table =     neofb_devices,
2281         .probe =        neofb_probe,
2282         .remove =       __devexit_p(neofb_remove)
2283 };
2284
2285 /* ************************* init in-kernel code ************************** */
2286
2287 #ifndef MODULE
2288 static int __init neofb_setup(char *options)
2289 {
2290         char *this_opt;
2291
2292         DBG("neofb_setup");
2293
2294         if (!options || !*options)
2295                 return 0;
2296
2297         while ((this_opt = strsep(&options, ",")) != NULL) {
2298                 if (!*this_opt)
2299                         continue;
2300
2301                 if (!strncmp(this_opt, "internal", 8))
2302                         internal = 1;
2303                 else if (!strncmp(this_opt, "external", 8))
2304                         external = 1;
2305                 else if (!strncmp(this_opt, "nostretch", 9))
2306                         nostretch = 1;
2307                 else if (!strncmp(this_opt, "nopciburst", 10))
2308                         nopciburst = 1;
2309                 else if (!strncmp(this_opt, "libretto", 8))
2310                         libretto = 1;
2311                 else
2312                         mode_option = this_opt;
2313         }
2314         return 0;
2315 }
2316 #endif  /*  MODULE  */
2317
2318 static int __init neofb_init(void)
2319 {
2320 #ifndef MODULE
2321         char *option = NULL;
2322
2323         if (fb_get_options("neofb", &option))
2324                 return -ENODEV;
2325         neofb_setup(option);
2326 #endif
2327         return pci_register_driver(&neofb_driver);
2328 }
2329
2330 module_init(neofb_init);
2331
2332 #ifdef MODULE
2333 static void __exit neofb_exit(void)
2334 {
2335         pci_unregister_driver(&neofb_driver);
2336 }
2337
2338 module_exit(neofb_exit);
2339 #endif                          /* MODULE */