2 * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
4 * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
7 * Card specific code is based on XFree86's neomagic driver.
8 * Framebuffer framework code is based on code of cyber2000fb.
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.
16 * - got rid of all floating point (dok)
19 * - added module license (dok)
22 * - hardware accelerated clear and move for 2200 and above (dok)
23 * - maximum allowed dotclock is handled now (dok)
26 * - correct panning after X usage (dok)
27 * - added module and kernel parameters (dok)
28 * - no stretching if external display is enabled (dok)
31 * - initial version (dok)
35 * - ioctl for internal/external switching
37 * - 32bit depth support, maybe impossible
38 * - disable pan-on-sync, need specs
41 * - white margin on bootup like with tdfxfb (colormap problem?)
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>
51 #include <linux/tty.h>
52 #include <linux/slab.h>
53 #include <linux/delay.h>
55 #include <linux/pci.h>
56 #include <linux/init.h>
60 #include <asm/pgtable.h>
61 #include <asm/system.h>
62 #include <asm/uaccess.h>
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>
77 #define NEOFB_VERSION "0.3.2"
79 /* --------------------------------------------------------------------- */
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;
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.");
107 /* --------------------------------------------------------------------- */
109 static biosMode bios8[] = {
118 static biosMode bios16[] = {
127 static biosMode bios24[] = {
133 #ifdef NO_32BIT_SUPPORT_YET
134 /* FIXME: guessed values, wrong */
135 static biosMode bios32[] = {
142 static int neoFindMode (int xres, int yres, int depth)
151 size = sizeof(bios8) / sizeof(biosMode);
155 size = sizeof(bios16) / sizeof(biosMode);
159 size = sizeof(bios24) / sizeof(biosMode);
162 #ifdef NO_32BIT_SUPPORT_YET
164 size = sizeof(bios32) / sizeof(biosMode);
172 for (i = 0; i < size; i++)
174 if (xres <= mode[i].x_res)
176 xres_s = mode[i].x_res;
177 for (; i < size; i++)
179 if (mode[i].x_res != xres_s)
180 return mode[i-1].mode;
181 if (yres <= mode[i].y_res)
186 return mode[size - 1].mode;
189 /* -------------------- Hardware specific routines ------------------------- */
192 * Hardware Acceleration for Neo2200+
194 static inline void neo2200_wait_idle (struct neofb_info *fb)
198 while (fb->neo2200->bltStat & 1)
202 static inline void neo2200_wait_fifo (struct neofb_info *fb,
203 int requested_fifo_space)
205 // ndev->neo.waitfifo_calls++;
206 // ndev->neo.waitfifo_sum += requested_fifo_space;
208 /* FIXME: does not work
209 if (neo_fifo_space < requested_fifo_space)
211 neo_fifo_waitcycles++;
215 neo_fifo_space = (neo2200->bltStat >> 8);
216 if (neo_fifo_space >= requested_fifo_space)
222 neo_fifo_cache_hits++;
225 neo_fifo_space -= requested_fifo_space;
228 neo2200_wait_idle (fb);
231 static inline void neo2200_accel_init (struct neofb_info *fb,
232 struct fb_var_screeninfo *var)
234 Neo2200 *neo2200 = fb->neo2200;
237 neo2200_wait_idle (fb);
239 switch (var->bits_per_pixel)
242 bltMod = NEO_MODE1_DEPTH8;
243 pitch = var->xres_virtual;
247 bltMod = NEO_MODE1_DEPTH16;
248 pitch = var->xres_virtual * 2;
251 printk( KERN_ERR "neofb: neo2200_accel_init: unexpected bits per pixel!\n" );
255 neo2200->bltStat = bltMod << 16;
256 neo2200->pitch = (pitch << 16) | pitch;
259 static void neo2200_accel_setup (struct display *p)
261 struct neofb_info *fb = (struct neofb_info *)p->fb_info;
262 struct fb_var_screeninfo *var = &p->fb_info->var;
264 fb->dispsw->setup(p);
266 neo2200_accel_init (fb, var);
270 neo2200_accel_bmove (struct display *p, int sy, int sx, int dy, int dx,
271 int height, int width)
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;
277 int bpp, pitch, inc_y;
282 neo2200_wait_idle (fb);
283 fb->dispsw->bmove(p, sy, sx, dy, dx, height, width);
287 bpp = (var->bits_per_pixel+7) / 8;
288 pitch = var->xres_virtual * bpp;
304 sy += (height - 1) * fh;
305 dy += (height - 1) * fh;
308 neo2200_wait_fifo (fb, 1);
310 /* set blt control */
311 neo2200->bltCntl = NEO_BC3_FIFO_EN |
312 NEO_BC3_SKIP_MAPPING | 0x0c0000;
316 src = sx + sy * pitch;
317 dst = dx + dy * pitch;
319 neo2200_wait_fifo (fb, 3);
321 neo2200->srcStart = src;
322 neo2200->dstStart = dst;
323 neo2200->xyExt = (fh << 16) | (width & 0xffff);
331 neo2200_accel_clear (struct vc_data *conp, struct display *p, int sy, int sx,
332 int height, int width)
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;
339 u32 bgx = attr_bgcol_ec(p, conp);
344 dst = sx * fw + sy * var->xres_virtual * fh;
346 height = height * fh;
348 neo2200_wait_fifo (fb, 4);
350 /* set blt control */
351 neo2200->bltCntl = NEO_BC3_FIFO_EN |
353 NEO_BC3_SKIP_MAPPING | 0x0c0000;
355 switch (var->bits_per_pixel)
358 neo2200->fgColor = bgx;
361 neo2200->fgColor = ((u16 *)(p->fb_info)->pseudo_palette)[bgx];
365 neo2200->dstStart = dst * ((var->bits_per_pixel+7) / 8);
367 neo2200->xyExt = (height << 16) | (width & 0xffff);
371 neo2200_accel_putc (struct vc_data *conp, struct display *p, int c,
374 struct neofb_info *fb = (struct neofb_info *)p->fb_info;
376 neo2200_wait_idle (fb);
377 fb->dispsw->putc(conp, p, c, yy, xx);
381 neo2200_accel_putcs (struct vc_data *conp, struct display *p,
382 const unsigned short *s, int count, int yy, int xx)
384 struct neofb_info *fb = (struct neofb_info *)p->fb_info;
386 neo2200_wait_idle (fb);
387 fb->dispsw->putcs(conp, p, s, count, yy, xx);
390 static void neo2200_accel_revc (struct display *p, int xx, int yy)
392 struct neofb_info *fb = (struct neofb_info *)p->fb_info;
394 neo2200_wait_idle (fb);
395 fb->dispsw->revc (p, xx, yy);
399 neo2200_accel_clear_margins (struct vc_data *conp, struct display *p,
402 struct neofb_info *fb = (struct neofb_info *)p->fb_info;
404 fb->dispsw->clear_margins (conp, p, bottom_only);
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)
419 /* --------------------------------------------------------------------- */
422 * Set a single color register. Return != 0 for invalid regno.
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)
427 struct neofb_info *info = (struct neofb_info *)fb;
429 if (regno >= NR_PALETTE)
432 info->palette[regno].red = red;
433 info->palette[regno].green = green;
434 info->palette[regno].blue = blue;
435 info->palette[regno].transp = transp;
437 switch (fb->var.bits_per_pixel)
439 #ifdef FBCON_HAS_CFB8
443 outb(red >> 10, 0x3c9);
444 outb(green >> 10, 0x3c9);
445 outb(blue >> 10, 0x3c9);
449 #ifdef FBCON_HAS_CFB16
452 ((u16 *)fb->pseudo_palette)[regno] = ((red & 0xf800) ) |
453 ((green & 0xfc00) >> 5) |
454 ((blue & 0xf800) >> 11);
458 #ifdef FBCON_HAS_CFB24
461 ((u32 *)fb->pseudo_palette)[regno] = ((red & 0xff00) << 8) |
462 ((green & 0xff00) ) |
463 ((blue & 0xff00) >> 8);
467 #ifdef NO_32BIT_SUPPORT_YET
468 #ifdef FBCON_HAS_CFB32
471 ((u32 *)fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) |
472 ((red & 0xff00) << 8) |
473 ((green & 0xff00) ) |
474 ((blue & 0xff00) >> 8);
486 static void vgaHWLock (void)
488 /* Protect CRTC[0-7] */
489 VGAwCR (0x11, VGArCR (0x11) | 0x80);
492 static void vgaHWUnlock (void)
494 /* Unprotect CRTC[0-7] */
495 VGAwCR (0x11, VGArCR (0x11) & ~0x80);
498 static void neoLock (void)
504 static void neoUnlock (void)
512 * perform a sequencer reset.
515 vgaHWSeqReset(int start)
518 VGAwSEQ (0x00, 0x01); /* Synchronous Reset */
520 VGAwSEQ (0x00, 0x03); /* End Reset */
531 * Turn off screen and disable sequencer.
533 tmp = VGArSEQ (0x01);
535 vgaHWSeqReset (1); /* start synchronous reset */
536 VGAwSEQ (0x01, tmp | 0x20); /* disable the display */
543 * Reenable sequencer, then turn on screen.
546 tmp = VGArSEQ (0x01);
548 VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */
549 vgaHWSeqReset (0); /* clear synchronousreset */
555 static void vgaHWRestore (const struct neofb_info *info,
556 const struct neofb_par *par)
560 VGAwMISC (par->MiscOutReg);
562 for (i = 1; i < 5; i++)
563 VGAwSEQ (i, par->Sequencer[i]);
565 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
566 VGAwCR (17, par->CRTC[17] & ~0x80);
568 for (i = 0; i < 25; i++)
569 VGAwCR (i, par->CRTC[i]);
571 for (i = 0; i < 9; i++)
572 VGAwGR (i, par->Graphics[i]);
576 for (i = 0; i < 21; i++)
577 VGAwATTR (i, par->Attribute[i]);
582 static void neofb_set_par (struct neofb_info *info,
583 const struct neofb_par *par)
589 DBG("neofb_set_par");
593 vgaHWProtect (1); /* Blank the screen */
595 /* linear colormap for non palettized modes */
611 #ifdef NO_32BIT_SUPPORT_YET
614 for (i=0; i<256; i++)
625 /* alread unlocked above */
626 /* BOGUS VGAwGR (0x09, 0x26);*/
628 /* don't know what this is, but it's 0 from bootup anyway */
631 /* was set to 0x01 by my bios in text and vesa modes */
632 VGAwGR (0x0A, par->GeneralLockReg);
635 * The color mode needs to be set before calling vgaHWRestore
636 * to ensure the DAC is initialized properly.
638 * NOTE: Make sure we don't change bits make sure we don't change
644 case FB_ACCEL_NEOMAGIC_NM2070:
645 temp &= 0xF0; /* Save bits 7:4 */
646 temp |= (par->ExtColorModeSelect & ~0xF0);
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);
664 * In some rare cases a lockup might occur if we don't delay
665 * here. (Reported by Miles Lane)
670 * Disable horizontal and vertical graphics and text expansions so
671 * that vgaHWRestore works properly.
678 * Sleep for 200ms to make sure that the two operations above have
679 * had time to take effect.
684 * This function handles restoring the generic VGA registers. */
685 vgaHWRestore (info, par);
688 VGAwGR(0x0E, par->ExtCRTDispAddr);
689 VGAwGR(0x0F, par->ExtCRTOffset);
691 temp &= 0x0F; /* Save bits 3:0 */
692 temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */
695 VGAwGR(0x11, par->SysIfaceCntl2);
696 VGAwGR(0x15, 0 /*par->SingleAddrPage*/);
697 VGAwGR(0x16, 0 /*par->DualAddrPage*/);
702 case FB_ACCEL_NEOMAGIC_NM2070:
703 temp &= 0xFC; /* Save bits 7:2 */
704 temp |= (par->PanelDispCntlReg1 & ~0xFC);
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);
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);
724 temp &= 0x38; /* Save bits 5:3 */
725 temp |= (par->PanelDispCntlReg2 & ~0x38);
728 if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
731 temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
732 temp |= (par->PanelDispCntlReg3 & ~0xEF);
736 VGAwGR(0x28, par->PanelVertCenterReg1);
737 VGAwGR(0x29, par->PanelVertCenterReg2);
738 VGAwGR(0x2a, par->PanelVertCenterReg3);
740 if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
742 VGAwGR(0x32, par->PanelVertCenterReg4);
743 VGAwGR(0x33, par->PanelHorizCenterReg1);
744 VGAwGR(0x34, par->PanelHorizCenterReg2);
745 VGAwGR(0x35, par->PanelHorizCenterReg3);
748 if (info->accel == FB_ACCEL_NEOMAGIC_NM2160)
749 VGAwGR(0x36, par->PanelHorizCenterReg4);
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)
756 VGAwGR(0x36, par->PanelHorizCenterReg4);
757 VGAwGR(0x37, par->PanelVertCenterReg5);
758 VGAwGR(0x38, par->PanelHorizCenterReg5);
763 /* Program VCLK3 if needed. */
765 && ((VGArGR(0x9B) != par->VCLK3NumeratorLow)
766 || (VGArGR(0x9F) != par->VCLK3Denominator)
767 || (clock_hi && ((VGArGR(0x8F) & ~0x0f)
768 != (par->VCLK3NumeratorHigh & ~0x0F)))))
770 VGAwGR(0x9B, par->VCLK3NumeratorLow);
774 temp &= 0x0F; /* Save bits 3:0 */
775 temp |= (par->VCLK3NumeratorHigh & ~0x0F);
778 VGAwGR(0x9F, par->VCLK3Denominator);
782 VGAwCR(0x23, par->biosMode);
784 VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
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)
792 VGAwCR(0x70, par->VerticalExt);
796 vgaHWProtect (0); /* Turn on screen */
798 /* Calling this also locks offset registers required in update_start */
802 static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var)
804 int oldExtCRTDispAddr;
807 DBG("neofb_update_start");
809 Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
810 Base *= (var->bits_per_pixel + 7) / 8;
815 * These are the generic starting address registers.
817 VGAwCR(0x0C, (Base & 0x00FF00) >> 8);
818 VGAwCR(0x0D, (Base & 0x00FF));
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
825 oldExtCRTDispAddr = VGArGR(0x0E);
826 VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
834 static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
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;
842 /* no colormap allocated? */
847 if (fb->var.bits_per_pixel == 8)
852 err = fb_alloc_cmap (dcmap, size, 0);
856 * we should be able to remove this test once fbcon has been
859 if (!err && con == info->currcon)
861 err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb);
866 fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1);
874 * Determine the closest clock frequency to the one requested.
876 #define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
881 static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq)
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 */
888 for (f = 0; f <= MAX_F; f++)
889 for (n = 0; n <= MAX_N; n++)
890 for (d = 0; d <= MAX_D; d++)
892 long f_out; /* 20.12 */
893 long f_diff; /* 20.12 */
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)
899 f_best_diff = f_diff;
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)
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);
917 par->VCLK3NumeratorLow = n_best | (f_best << 7);
919 par->VCLK3Denominator = d_best;
922 printk ("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
924 par->VCLK3NumeratorLow,
925 par->VCLK3NumeratorHigh,
926 par->VCLK3Denominator,
933 * Handle the initialization, etc. of a screen.
934 * Return FALSE on failure.
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)
942 par->MiscOutReg = 0x23;
944 if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
945 par->MiscOutReg |= 0x40;
947 if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
948 par->MiscOutReg |= 0x80;
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 */
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)
975 | (((timings->VTotal - 2) & 0x200) >> 4)
976 | (((timings->VDisplay - 1) & 0x200) >> 3)
977 | ((timings->VSyncStart & 0x200) >> 2);
979 par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
981 if (timings->dblscan)
982 par->CRTC[9] |= 0x80;
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;
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);
1007 * Graphics Display Controller
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;
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;
1045 static int neofb_decode_var (struct fb_var_screeninfo *var,
1046 const struct neofb_info *info,
1047 struct neofb_par *par)
1049 struct xtimings timings;
1051 int hoffset, voffset;
1052 int memlen, vramlen;
1054 unsigned int pixclock = var->pixclock;
1056 DBG("neofb_decode_var");
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;
1073 if (timings.pixclock > info->maxClock)
1076 /* Is the mode larger than the LCD panel? */
1077 if ((var->xres > info->NeoPanelWidth) ||
1078 (var->yres > info->NeoPanelHeight))
1080 printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
1083 info->NeoPanelWidth,
1084 info->NeoPanelHeight);
1088 /* Is the mode one of the acceptable sizes? */
1092 if (var->yres == 1024)
1096 if (var->yres == 768)
1100 if (var->yres == 600)
1104 if (var->yres == 480)
1111 printk (KERN_INFO "Mode (%dx%d) won't display properly on LCD\n",
1112 var->xres, var->yres);
1117 switch (var->bits_per_pixel)
1119 #ifdef FBCON_HAS_CFB8
1124 #ifdef FBCON_HAS_CFB16
1129 #ifdef FBCON_HAS_CFB24
1134 #ifdef NO_32BIT_SUPPORT_YET
1135 # ifdef FBCON_HAS_CFB32
1145 par->depth = var->bits_per_pixel;
1147 vramlen = info->video.len;
1148 if (vramlen > 4*1024*1024)
1149 vramlen = 4*1024*1024;
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;
1156 memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
1157 if (memlen > vramlen)
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;
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;
1176 * This will allocate the datastructure and initialize all of the
1177 * generic VGA registers.
1180 if (vgaHWInit (var, info, par, &timings))
1184 * The default value assigned by vgaHW.c is 0x41, but this does
1185 * not work for NeoMagic.
1187 par->Attribute[16] = 0x01;
1189 switch (var->bits_per_pixel)
1192 par->CRTC[0x13] = var->xres_virtual >> 3;
1193 par->ExtCRTOffset = var->xres_virtual >> 11;
1194 par->ExtColorModeSelect = 0x11;
1197 par->CRTC[0x13] = var->xres_virtual >> 2;
1198 par->ExtCRTOffset = var->xres_virtual >> 10;
1199 par->ExtColorModeSelect = 0x13;
1202 par->CRTC[0x13] = (var->xres_virtual * 3) >> 3;
1203 par->ExtCRTOffset = (var->xres_virtual * 3) >> 11;
1204 par->ExtColorModeSelect = 0x14;
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;
1217 par->ExtCRTDispAddr = 0x10;
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 );
1225 /* Fast write bursts on unless disabled. */
1226 if (info->pci_burst)
1227 par->SysIfaceCntl1 = 0x30;
1229 par->SysIfaceCntl1 = 0x00;
1231 par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
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;
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;
1246 /* If we are using a fixed mode, then tell the chip we are. */
1250 par->PanelDispCntlReg1 |= 0x60;
1253 par->PanelDispCntlReg1 |= 0x40;
1256 par->PanelDispCntlReg1 |= 0x20;
1263 /* Setup shadow register locking. */
1264 switch (par->PanelDispCntlReg1 & 0x03)
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;
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;
1280 * If the screen is to be stretched, turn on stretching for the
1283 * OPTION_LCD_STRETCH means stretching should be turned off!
1285 par->PanelDispCntlReg2 = 0x00;
1286 par->PanelDispCntlReg3 = 0x00;
1288 if (info->lcd_stretch &&
1289 (par->PanelDispCntlReg1 == 0x02) && /* LCD only */
1290 (var->xres != info->NeoPanelWidth))
1294 case 320: /* Needs testing. KEM -- 24 May 98 */
1295 case 400: /* Needs testing. KEM -- 24 May 98 */
1300 par->PanelDispCntlReg2 |= 0xC6;
1304 /* No stretching in these modes. */
1311 * If the screen is to be centerd, turn on the centering for the
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;
1326 if (par->PanelDispCntlReg1 & 0x02)
1328 if (var->xres == info->NeoPanelWidth)
1331 * No centering required when the requested display width
1332 * equals the panel width.
1337 par->PanelDispCntlReg2 |= 0x01;
1338 par->PanelDispCntlReg3 |= 0x10;
1340 /* Calculate the horizontal and vertical offsets. */
1343 hoffset = ((info->NeoPanelWidth - var->xres) >> 4) - 1;
1344 voffset = ((info->NeoPanelHeight - var->yres) >> 1) - 2;
1348 /* Stretched modes cannot be centered. */
1355 case 320: /* Needs testing. KEM -- 24 May 98 */
1356 par->PanelHorizCenterReg3 = hoffset;
1357 par->PanelVertCenterReg2 = voffset;
1359 case 400: /* Needs testing. KEM -- 24 May 98 */
1360 par->PanelHorizCenterReg4 = hoffset;
1361 par->PanelVertCenterReg1 = voffset;
1364 par->PanelHorizCenterReg1 = hoffset;
1365 par->PanelVertCenterReg3 = voffset;
1368 par->PanelHorizCenterReg2 = hoffset;
1369 par->PanelVertCenterReg4 = voffset;
1372 par->PanelHorizCenterReg5 = hoffset;
1373 par->PanelVertCenterReg5 = voffset;
1377 /* No centering in these modes. */
1383 par->biosMode = neoFindMode (var->xres, var->yres, var->bits_per_pixel);
1386 * Calculate the VCLK that most closely matches the requested dot
1389 neoCalcVCLK (info, par, timings.pixclock);
1391 /* Since we program the clocks ourselves, always use VCLK3. */
1392 par->MiscOutReg |= 0x0C;
1397 static int neofb_set_var (struct fb_var_screeninfo *var, int con,
1400 struct neofb_info *info = (struct neofb_info *)fb;
1401 struct display *display;
1402 struct neofb_par par;
1403 int err, chgvar = 0;
1405 DBG("neofb_set_var");
1407 err = neofb_decode_var (var, info, &par);
1411 if (var->activate & FB_ACTIVATE_TEST)
1421 display = fb_display + con;
1423 if (fb->var.xres != var->xres)
1425 if (fb->var.yres != var->yres)
1427 if (fb->var.xres_virtual != var->xres_virtual)
1429 if (fb->var.yres_virtual != var->yres_virtual)
1431 if (fb->var.bits_per_pixel != var->bits_per_pixel)
1436 var->accel_flags &= ~FB_ACCELF_TEXT;
1438 var->red.msb_right = 0;
1439 var->green.msb_right = 0;
1440 var->blue.msb_right = 0;
1442 switch (var->bits_per_pixel)
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;
1455 fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1456 info->dispsw = &fbcon_cfb8;
1457 display->dispsw_data = NULL;
1458 display->next_line = var->xres_virtual;
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;
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;
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;
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;
1496 var->accel_flags &= ~FB_ACCELF_TEXT;
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;
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;
1517 var->accel_flags &= ~FB_ACCELF_TEXT;
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;
1529 if (var->accel_flags & FB_ACCELF_TEXT)
1530 display->dispsw = &fbcon_neo2200_accel;
1532 display->dispsw = info->dispsw;
1534 fb->fix.line_length = display->next_line;
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;
1547 fb->var.activate &= ~FB_ACTIVATE_ALL;
1550 * Update the old var. The fbcon drivers still use this.
1551 * Once they are using cfb->fb.var, this can be dropped.
1554 display->var = fb->var;
1557 * If we are setting all the virtual consoles, also set the
1558 * defaults used to create new consoles.
1560 if (var->activate & FB_ACTIVATE_ALL)
1561 fb->disp->var = fb->var;
1563 if (chgvar && fb && fb->changevar)
1564 fb->changevar (con);
1566 if (con == info->currcon)
1568 if (chgvar || con < 0)
1569 neofb_set_par (info, &par);
1571 neofb_update_start (info, var);
1572 fb_set_cmap (&fb->cmap, 1, neo_setcolreg, fb);
1574 if (var->accel_flags & FB_ACCELF_TEXT)
1575 neo2200_accel_init (info, var);
1582 * Pan or Wrap the Display
1584 static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
1587 struct neofb_info *info = (struct neofb_info *)fb;
1590 y_bottom = var->yoffset;
1592 if (!(var->vmode & FB_VMODE_YWRAP))
1593 y_bottom += var->yres;
1595 if (var->xoffset > (var->xres_virtual - var->xres))
1597 if (y_bottom > fb->var.yres_virtual)
1600 neofb_update_start (info, var);
1602 fb->var.xoffset = var->xoffset;
1603 fb->var.yoffset = var->yoffset;
1605 if (var->vmode & FB_VMODE_YWRAP)
1606 fb->var.vmode |= FB_VMODE_YWRAP;
1608 fb->var.vmode &= ~FB_VMODE_YWRAP;
1615 * Update the `var' structure (called by fbcon.c)
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.
1620 static int neofb_updatevar (int con, struct fb_info *fb)
1622 struct neofb_info *info = (struct neofb_info *)fb;
1624 neofb_update_start (info, &fb_display[con].var);
1629 static int neofb_switch (int con, struct fb_info *fb)
1631 struct neofb_info *info = (struct neofb_info *)fb;
1632 struct display *disp;
1633 struct fb_cmap *cmap;
1635 if (info->currcon >= 0)
1637 disp = fb_display + info->currcon;
1640 * Save the old colormap and video mode.
1642 disp->var = fb->var;
1644 fb_copy_cmap(&fb->cmap, &disp->cmap, 0);
1647 info->currcon = con;
1648 disp = fb_display + con;
1651 * Install the new colormap and change the video mode. By default,
1652 * fbcon sets all the colormaps and video modes to the default
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.
1662 cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
1664 fb_copy_cmap(cmap, &fb->cmap, 0);
1666 disp->var.activate = FB_ACTIVATE_NOW;
1667 neofb_set_var(&disp->var, con, fb);
1673 * (Un)Blank the display.
1675 static void neofb_blank (int blank, struct fb_info *fb)
1677 // struct neofb_info *info = (struct neofb_info *)fb;
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
1691 * wms...Enable VESA DMPS compatible powerdown mode
1692 * run "setterm -powersave powerdown" to take advantage
1697 case 4: /* powerdown - both sync lines down */
1699 case 3: /* hsync off */
1701 case 2: /* vsync off */
1703 case 1: /* just software blanking of screen */
1705 default: /* case 0, or anything else: unblank */
1711 * Get the currently displayed virtual consoles colormap.
1713 static int gen_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb)
1715 fb_copy_cmap (&fb->cmap, cmap, kspc ? 0 : 2);
1720 * Get the currently displayed virtual consoles fixed part of the display.
1722 static int gen_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
1729 * Get the current user defined part of the display.
1731 static int gen_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb)
1737 static struct fb_ops neofb_ops = {
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,
1747 /* --------------------------------------------------------------------- */
1749 static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
1750 accel_flags: FB_ACCELF_TEXT,
1754 yres_virtual: 30000,
1764 vmode: FB_VMODE_NONINTERLACED
1767 static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = {
1768 accel_flags: FB_ACCELF_TEXT,
1772 yres_virtual: 30000,
1781 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1782 vmode: FB_VMODE_NONINTERLACED
1785 static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = {
1786 accel_flags: FB_ACCELF_TEXT,
1790 yres_virtual: 30000,
1799 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1800 vmode: FB_VMODE_NONINTERLACED
1804 static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
1805 accel_flags: FB_ACCELF_TEXT,
1809 yres_virtual: 30000,
1818 sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1819 vmode: FB_VMODE_NONINTERLACED
1823 static struct fb_var_screeninfo *neofb_var = NULL;
1826 static int __devinit neo_map_mmio (struct neofb_info *info)
1828 DBG("neo_map_mmio");
1830 info->mmio.pbase = pci_resource_start (info->pcidev, 1);
1831 info->mmio.len = MMIO_SIZE;
1833 if (!request_mem_region (info->mmio.pbase, MMIO_SIZE, "memory mapped I/O"))
1835 printk ("neofb: memory mapped IO in use\n");
1839 info->mmio.vbase = ioremap (info->mmio.pbase, MMIO_SIZE);
1840 if (!info->mmio.vbase)
1842 printk ("neofb: unable to map memory mapped IO\n");
1843 release_mem_region (info->mmio.pbase, info->mmio.len);
1847 printk (KERN_INFO "neofb: mapped io at %p\n", info->mmio.vbase);
1849 info->fb.fix.mmio_start = info->mmio.pbase;
1850 info->fb.fix.mmio_len = info->mmio.len;
1855 static void __devinit neo_unmap_mmio (struct neofb_info *info)
1857 DBG("neo_unmap_mmio");
1859 if (info->mmio.vbase)
1861 iounmap (info->mmio.vbase);
1862 info->mmio.vbase = NULL;
1864 release_mem_region (info->mmio.pbase, info->mmio.len);
1868 static int __devinit neo_map_video (struct neofb_info *info, int video_len)
1870 DBG("neo_map_video");
1872 info->video.pbase = pci_resource_start (info->pcidev, 0);
1873 info->video.len = video_len;
1875 if (!request_mem_region (info->video.pbase, info->video.len, "frame buffer"))
1877 printk ("neofb: frame buffer in use\n");
1881 info->video.vbase = ioremap (info->video.pbase, info->video.len);
1882 if (!info->video.vbase)
1884 printk ("neofb: unable to map screen memory\n");
1885 release_mem_region (info->video.pbase, info->video.len);
1889 printk (KERN_INFO "neofb: mapped framebuffer at %p\n", info->video.vbase);
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;
1896 info->video.mtrr = mtrr_add (info->video.pbase, pci_resource_len (info->pcidev, 0), MTRR_TYPE_WRCOMB, 1);
1899 /* Clear framebuffer, it's all white in memory after boot */
1900 memset (info->video.vbase, 0, info->video.len);
1905 static void __devinit neo_unmap_video (struct neofb_info *info)
1907 DBG("neo_unmap_video");
1909 if (info->video.vbase)
1912 mtrr_del (info->video.mtrr, info->video.pbase, info->video.len);
1915 iounmap (info->video.vbase);
1916 info->video.vbase = NULL;
1917 info->fb.screen_base = NULL;
1919 release_mem_region (info->video.pbase, info->video.len);
1923 static int __devinit neo_init_hw (struct neofb_info *info)
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;
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));
1947 /* Determine the panel type */
1949 type = VGArGR(0x21);
1950 display = VGArGR(0x20);
1952 /* Determine panel width -- used in NeoValidMode. */
1955 switch ((w & 0x18) >> 3)
1958 info->NeoPanelWidth = 640;
1959 info->NeoPanelHeight = 480;
1960 neofb_var = &neofb_var640x480x8;
1963 info->NeoPanelWidth = 800;
1964 info->NeoPanelHeight = 600;
1965 neofb_var = &neofb_var800x600x8;
1968 info->NeoPanelWidth = 1024;
1969 info->NeoPanelHeight = 768;
1970 neofb_var = &neofb_var1024x768x8;
1973 /* 1280x1024 panel support needs to be added */
1975 info->NeoPanelWidth = 1280;
1976 info->NeoPanelHeight = 1024;
1977 neofb_var = &neofb_var1280x1024x8;
1980 printk (KERN_ERR "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported\n");
1984 info->NeoPanelWidth = 640;
1985 info->NeoPanelHeight = 480;
1986 neofb_var = &neofb_var640x480x8;
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");
1996 switch (info->accel)
1998 case FB_ACCEL_NEOMAGIC_NM2070:
2007 case FB_ACCEL_NEOMAGIC_NM2090:
2008 case FB_ACCEL_NEOMAGIC_NM2093:
2017 case FB_ACCEL_NEOMAGIC_NM2097:
2026 case FB_ACCEL_NEOMAGIC_NM2160:
2035 case FB_ACCEL_NEOMAGIC_NM2200:
2042 maxHeight = 1024; /* ???? */
2044 info->neo2200 = (Neo2200*) info->mmio.vbase;
2046 case FB_ACCEL_NEOMAGIC_NM2230:
2053 maxHeight = 1024; /* ???? */
2055 info->neo2200 = (Neo2200*) info->mmio.vbase;
2057 case FB_ACCEL_NEOMAGIC_NM2360:
2064 maxHeight = 1024; /* ???? */
2066 info->neo2200 = (Neo2200*) info->mmio.vbase;
2068 case FB_ACCEL_NEOMAGIC_NM2380:
2075 maxHeight = 1024; /* ???? */
2077 info->neo2200 = (Neo2200*) info->mmio.vbase;
2081 info->maxClock = maxClock;
2083 return videoRam * 1024;
2087 static struct neofb_info * __devinit neo_alloc_fb_info (struct pci_dev *dev,
2088 const struct pci_device_id *id)
2090 struct neofb_info *info;
2092 info = kmalloc (sizeof(struct neofb_info) + sizeof(struct display) +
2093 sizeof(u32) * 16, GFP_KERNEL);
2098 memset (info, 0, sizeof(struct neofb_info) + sizeof(struct display));
2102 info->accel = id->driver_data;
2104 info->pci_burst = !nopciburst;
2105 info->lcd_stretch = !nostretch;
2107 if (!internal && !external)
2109 info->internal_display = 1;
2110 info->external_display = 0;
2114 info->internal_display = internal;
2115 info->external_display = external;
2118 switch (info->accel)
2120 case FB_ACCEL_NEOMAGIC_NM2070:
2121 sprintf (info->fb.fix.id, "MagicGraph 128");
2123 case FB_ACCEL_NEOMAGIC_NM2090:
2124 sprintf (info->fb.fix.id, "MagicGraph 128V");
2126 case FB_ACCEL_NEOMAGIC_NM2093:
2127 sprintf (info->fb.fix.id, "MagicGraph 128ZV");
2129 case FB_ACCEL_NEOMAGIC_NM2097:
2130 sprintf (info->fb.fix.id, "MagicGraph 128ZV+");
2132 case FB_ACCEL_NEOMAGIC_NM2160:
2133 sprintf (info->fb.fix.id, "MagicGraph 128XD");
2135 case FB_ACCEL_NEOMAGIC_NM2200:
2136 sprintf (info->fb.fix.id, "MagicGraph 256AV");
2138 case FB_ACCEL_NEOMAGIC_NM2230:
2139 sprintf (info->fb.fix.id, "MagicGraph 256AV+");
2141 case FB_ACCEL_NEOMAGIC_NM2360:
2142 sprintf (info->fb.fix.id, "MagicGraph 256ZX");
2144 case FB_ACCEL_NEOMAGIC_NM2380:
2145 sprintf (info->fb.fix.id, "MagicGraph 256XL+");
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;
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;
2162 strcpy (info->fb.modename, info->fb.fix.id);
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);
2173 fb_alloc_cmap (&info->fb.cmap, NR_PALETTE, 0);
2178 static void __devinit neo_free_fb_info (struct neofb_info *info)
2183 * Free the colourmap
2185 fb_alloc_cmap (&info->fb.cmap, 0, 0);
2191 /* --------------------------------------------------------------------- */
2193 static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_id* id)
2195 struct neofb_info *info;
2196 u_int h_sync, v_sync;
2202 err = pci_enable_device (dev);
2207 info = neo_alloc_fb_info (dev, id);
2211 err = neo_map_mmio (info);
2215 video_len = neo_init_hw (info);
2222 err = neo_map_video (info, video_len);
2226 neofb_set_var (neofb_var, -1, &info->fb);
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)
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);
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);
2246 err = register_framebuffer (&info->fb);
2250 printk (KERN_INFO "fb%d: %s frame buffer device\n",
2251 GET_FB_IDX(info->fb.node), info->fb.modename);
2256 pci_set_drvdata(dev, info);
2261 neo_unmap_video (info);
2262 neo_unmap_mmio (info);
2263 neo_free_fb_info (info);
2268 static void __devexit neofb_remove (struct pci_dev *dev)
2270 struct neofb_info *info = pci_get_drvdata(dev);
2272 DBG("neofb_remove");
2277 * If unregister_framebuffer fails, then
2278 * we will be leaving hooks that could cause
2279 * oopsen laying around.
2281 if (unregister_framebuffer (&info->fb))
2282 printk (KERN_WARNING "neofb: danger danger! Oopsen imminent!\n");
2284 neo_unmap_video (info);
2285 neo_unmap_mmio (info);
2286 neo_free_fb_info (info);
2289 * Ensure that the driver data is no longer
2292 pci_set_drvdata(dev, NULL);
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},
2300 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
2301 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
2303 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
2304 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
2306 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
2307 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
2309 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
2310 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
2312 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
2313 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
2315 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
2316 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
2318 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
2319 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
2321 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
2322 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
2324 {0, 0, 0, 0, 0, 0, 0}
2327 MODULE_DEVICE_TABLE(pci, neofb_devices);
2329 static struct pci_driver neofb_driver = {
2331 id_table: neofb_devices,
2333 remove: __devexit_p(neofb_remove)
2336 /* **************************** init-time only **************************** */
2338 static void __init neo_init (void)
2341 pci_register_driver (&neofb_driver);
2344 /* **************************** exit-time only **************************** */
2346 static void __exit neo_done (void)
2349 pci_unregister_driver (&neofb_driver);
2355 /* ************************* init in-kernel code ************************** */
2357 int __init neofb_setup (char *options)
2363 if (!options || !*options)
2366 for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,","))
2368 if (!*this_opt) continue;
2370 if (!strncmp(this_opt, "disabled", 8))
2372 if (!strncmp(this_opt, "internal", 8))
2374 if (!strncmp(this_opt, "external", 8))
2376 if (!strncmp(this_opt, "nostretch", 9))
2378 if (!strncmp(this_opt, "nopciburst", 10))
2385 static int __initdata initialized = 0;
2387 int __init neofb_init(void)
2400 /* never return failure, user can hotplug card later... */
2406 /* *************************** init module code **************************** */
2408 int __init init_module(void)
2417 /* never return failure; user can hotplug card later... */
2423 module_exit(neo_done);