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