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