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