2 * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
4 * Copyright (c) 2001-2002 Denis Oliver Kropp <dok@directfb.org>
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 * - Cosmetic changes (dok)
19 * - Toshiba Libretto support, allow modes larger than LCD size if
20 * LCD is disabled, keep BIOS settings if internal/external display
21 * haven't been enabled explicitly
22 * (Thomas J. Moore <dark@mama.indstate.edu>)
25 * - Porting over to new fbdev api. (jsimmons)
28 * - got rid of all floating point (dok)
31 * - added module license (dok)
34 * - hardware accelerated clear and move for 2200 and above (dok)
35 * - maximum allowed dotclock is handled now (dok)
38 * - correct panning after X usage (dok)
39 * - added module and kernel parameters (dok)
40 * - no stretching if external display is enabled (dok)
43 * - initial version (dok)
47 * - ioctl for internal/external switching
49 * - 32bit depth support, maybe impossible
50 * - disable pan-on-sync, need specs
53 * - white margin on bootup like with tdfxfb (colormap problem?)
57 #include <linux/config.h>
58 #include <linux/module.h>
59 #include <linux/kernel.h>
60 #include <linux/errno.h>
61 #include <linux/string.h>
63 #include <linux/tty.h>
64 #include <linux/slab.h>
65 #include <linux/delay.h>
67 #include <linux/pci.h>
68 #include <linux/init.h>
70 #include <linux/toshiba.h>
71 extern int tosh_smm(SMMRegisters
*regs
);
76 #include <asm/pgtable.h>
77 #include <asm/system.h>
78 #include <asm/uaccess.h>
84 #include <video/neomagic.h>
86 #define NEOFB_VERSION "0.4.1"
88 /* --------------------------------------------------------------------- */
95 static int nopciburst
;
100 MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>");
101 MODULE_LICENSE("GPL");
102 MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
103 MODULE_PARM(disabled
, "i");
104 MODULE_PARM_DESC(disabled
, "Disable this driver's initialization.");
105 MODULE_PARM(internal
, "i");
106 MODULE_PARM_DESC(internal
, "Enable output on internal LCD Display.");
107 MODULE_PARM(external
, "i");
108 MODULE_PARM_DESC(external
, "Enable output on external CRT.");
109 MODULE_PARM(libretto
, "i");
110 MODULE_PARM_DESC(libretto
, "Force Libretto 100/110 800x480 LCD.");
111 MODULE_PARM(nostretch
, "i");
112 MODULE_PARM_DESC(nostretch
,
113 "Disable stretching of modes smaller than LCD.");
114 MODULE_PARM(nopciburst
, "i");
115 MODULE_PARM_DESC(nopciburst
, "Disable PCI burst mode.");
120 /* --------------------------------------------------------------------- */
122 static biosMode bios8
[] = {
131 static biosMode bios16
[] = {
140 static biosMode bios24
[] = {
146 #ifdef NO_32BIT_SUPPORT_YET
147 /* FIXME: guessed values, wrong */
148 static biosMode bios32
[] = {
155 static int neoFindMode(int xres
, int yres
, int depth
)
163 size
= sizeof(bios8
) / sizeof(biosMode
);
167 size
= sizeof(bios16
) / sizeof(biosMode
);
171 size
= sizeof(bios24
) / sizeof(biosMode
);
174 #ifdef NO_32BIT_SUPPORT_YET
176 size
= sizeof(bios32
) / sizeof(biosMode
);
184 for (i
= 0; i
< size
; i
++) {
185 if (xres
<= mode
[i
].x_res
) {
186 xres_s
= mode
[i
].x_res
;
187 for (; i
< size
; i
++) {
188 if (mode
[i
].x_res
!= xres_s
)
189 return mode
[i
- 1].mode
;
190 if (yres
<= mode
[i
].y_res
)
195 return mode
[size
- 1].mode
;
201 * Determine the closest clock frequency to the one requested.
203 #define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */
208 static void neoCalcVCLK(const struct fb_info
*info
,
209 struct neofb_par
*par
, long freq
)
212 int n_best
= 0, d_best
= 0, f_best
= 0;
213 long f_best_diff
= (0x7ffff << 12); /* 20.12 */
214 long f_target
= (freq
<< 12) / 1000; /* 20.12 */
216 for (f
= 0; f
<= MAX_F
; f
++)
217 for (n
= 0; n
<= MAX_N
; n
++)
218 for (d
= 0; d
<= MAX_D
; d
++) {
219 long f_out
; /* 20.12 */
220 long f_diff
; /* 20.12 */
223 ((((n
+ 1) << 12) / ((d
+
227 f_diff
= abs(f_out
- f_target
);
228 if (f_diff
< f_best_diff
) {
229 f_best_diff
= f_diff
;
236 if (info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2200
||
237 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2230
||
238 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2360
||
239 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2380
) {
240 /* NOT_DONE: We are trying the full range of the 2200 clock.
241 We should be able to try n up to 2047 */
242 par
->VCLK3NumeratorLow
= n_best
;
243 par
->VCLK3NumeratorHigh
= (f_best
<< 7);
245 par
->VCLK3NumeratorLow
= n_best
| (f_best
<< 7);
247 par
->VCLK3Denominator
= d_best
;
250 printk("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",
252 par
->VCLK3NumeratorLow
,
253 par
->VCLK3NumeratorHigh
,
254 par
->VCLK3Denominator
, f_best_diff
>> 12);
260 * Handle the initialization, etc. of a screen.
261 * Return FALSE on failure.
264 static int vgaHWInit(const struct fb_var_screeninfo
*var
,
265 const struct fb_info
*info
,
266 struct neofb_par
*par
, struct xtimings
*timings
)
268 par
->MiscOutReg
= 0x23;
270 if (!(timings
->sync
& FB_SYNC_HOR_HIGH_ACT
))
271 par
->MiscOutReg
|= 0x40;
273 if (!(timings
->sync
& FB_SYNC_VERT_HIGH_ACT
))
274 par
->MiscOutReg
|= 0x80;
279 par
->Sequencer
[0] = 0x00;
280 par
->Sequencer
[1] = 0x01;
281 par
->Sequencer
[2] = 0x0F;
282 par
->Sequencer
[3] = 0x00; /* Font select */
283 par
->Sequencer
[4] = 0x0E; /* Misc */
288 par
->CRTC
[0] = (timings
->HTotal
>> 3) - 5;
289 par
->CRTC
[1] = (timings
->HDisplay
>> 3) - 1;
290 par
->CRTC
[2] = (timings
->HDisplay
>> 3) - 1;
291 par
->CRTC
[3] = (((timings
->HTotal
>> 3) - 1) & 0x1F) | 0x80;
292 par
->CRTC
[4] = (timings
->HSyncStart
>> 3);
293 par
->CRTC
[5] = ((((timings
->HTotal
>> 3) - 1) & 0x20) << 2)
294 | (((timings
->HSyncEnd
>> 3)) & 0x1F);
295 par
->CRTC
[6] = (timings
->VTotal
- 2) & 0xFF;
296 par
->CRTC
[7] = (((timings
->VTotal
- 2) & 0x100) >> 8)
297 | (((timings
->VDisplay
- 1) & 0x100) >> 7)
298 | ((timings
->VSyncStart
& 0x100) >> 6)
299 | (((timings
->VDisplay
- 1) & 0x100) >> 5)
300 | 0x10 | (((timings
->VTotal
- 2) & 0x200) >> 4)
301 | (((timings
->VDisplay
- 1) & 0x200) >> 3)
302 | ((timings
->VSyncStart
& 0x200) >> 2);
304 par
->CRTC
[9] = (((timings
->VDisplay
- 1) & 0x200) >> 4) | 0x40;
306 if (timings
->dblscan
)
307 par
->CRTC
[9] |= 0x80;
309 par
->CRTC
[10] = 0x00;
310 par
->CRTC
[11] = 0x00;
311 par
->CRTC
[12] = 0x00;
312 par
->CRTC
[13] = 0x00;
313 par
->CRTC
[14] = 0x00;
314 par
->CRTC
[15] = 0x00;
315 par
->CRTC
[16] = timings
->VSyncStart
& 0xFF;
316 par
->CRTC
[17] = (timings
->VSyncEnd
& 0x0F) | 0x20;
317 par
->CRTC
[18] = (timings
->VDisplay
- 1) & 0xFF;
318 par
->CRTC
[19] = var
->xres_virtual
>> 4;
319 par
->CRTC
[20] = 0x00;
320 par
->CRTC
[21] = (timings
->VDisplay
- 1) & 0xFF;
321 par
->CRTC
[22] = (timings
->VTotal
- 1) & 0xFF;
322 par
->CRTC
[23] = 0xC3;
323 par
->CRTC
[24] = 0xFF;
326 * are these unnecessary?
327 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
328 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
332 * Graphics Display Controller
334 par
->Graphics
[0] = 0x00;
335 par
->Graphics
[1] = 0x00;
336 par
->Graphics
[2] = 0x00;
337 par
->Graphics
[3] = 0x00;
338 par
->Graphics
[4] = 0x00;
339 par
->Graphics
[5] = 0x40;
340 par
->Graphics
[6] = 0x05; /* only map 64k VGA memory !!!! */
341 par
->Graphics
[7] = 0x0F;
342 par
->Graphics
[8] = 0xFF;
345 par
->Attribute
[0] = 0x00; /* standard colormap translation */
346 par
->Attribute
[1] = 0x01;
347 par
->Attribute
[2] = 0x02;
348 par
->Attribute
[3] = 0x03;
349 par
->Attribute
[4] = 0x04;
350 par
->Attribute
[5] = 0x05;
351 par
->Attribute
[6] = 0x06;
352 par
->Attribute
[7] = 0x07;
353 par
->Attribute
[8] = 0x08;
354 par
->Attribute
[9] = 0x09;
355 par
->Attribute
[10] = 0x0A;
356 par
->Attribute
[11] = 0x0B;
357 par
->Attribute
[12] = 0x0C;
358 par
->Attribute
[13] = 0x0D;
359 par
->Attribute
[14] = 0x0E;
360 par
->Attribute
[15] = 0x0F;
361 par
->Attribute
[16] = 0x41;
362 par
->Attribute
[17] = 0xFF;
363 par
->Attribute
[18] = 0x0F;
364 par
->Attribute
[19] = 0x00;
365 par
->Attribute
[20] = 0x00;
370 static void vgaHWLock(void)
372 /* Protect CRTC[0-7] */
373 VGAwCR(0x11, VGArCR(0x11) | 0x80);
376 static void vgaHWUnlock(void)
378 /* Unprotect CRTC[0-7] */
379 VGAwCR(0x11, VGArCR(0x11) & ~0x80);
382 static void neoLock(void)
388 static void neoUnlock(void)
396 * perform a sequencer reset.
398 void vgaHWSeqReset(int start
)
401 VGAwSEQ(0x00, 0x01); /* Synchronous Reset */
403 VGAwSEQ(0x00, 0x03); /* End Reset */
406 void vgaHWProtect(int on
)
412 * Turn off screen and disable sequencer.
416 vgaHWSeqReset(1); /* start synchronous reset */
417 VGAwSEQ(0x01, tmp
| 0x20); /* disable the display */
422 * Reenable sequencer, then turn on screen.
427 VGAwSEQ(0x01, tmp
& ~0x20); /* reenable display */
428 vgaHWSeqReset(0); /* clear synchronousreset */
434 static void vgaHWRestore(const struct fb_info
*info
,
435 const struct neofb_par
*par
)
439 VGAwMISC(par
->MiscOutReg
);
441 for (i
= 1; i
< 5; i
++)
442 VGAwSEQ(i
, par
->Sequencer
[i
]);
444 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
445 VGAwCR(17, par
->CRTC
[17] & ~0x80);
447 for (i
= 0; i
< 25; i
++)
448 VGAwCR(i
, par
->CRTC
[i
]);
450 for (i
= 0; i
< 9; i
++)
451 VGAwGR(i
, par
->Graphics
[i
]);
455 for (i
= 0; i
< 21; i
++)
456 VGAwATTR(i
, par
->Attribute
[i
]);
462 /* -------------------- Hardware specific routines ------------------------- */
465 * Hardware Acceleration for Neo2200+
467 static inline int neo2200_sync(struct fb_info
*info
)
469 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
472 while (par
->neo2200
->bltStat
& 1)
477 static inline void neo2200_wait_fifo(struct fb_info
*info
,
478 int requested_fifo_space
)
480 // ndev->neo.waitfifo_calls++;
481 // ndev->neo.waitfifo_sum += requested_fifo_space;
483 /* FIXME: does not work
484 if (neo_fifo_space < requested_fifo_space)
486 neo_fifo_waitcycles++;
490 neo_fifo_space = (neo2200->bltStat >> 8);
491 if (neo_fifo_space >= requested_fifo_space)
497 neo_fifo_cache_hits++;
500 neo_fifo_space -= requested_fifo_space;
506 static inline void neo2200_accel_init(struct fb_info
*info
,
507 struct fb_var_screeninfo
*var
)
509 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
510 Neo2200
*neo2200
= par
->neo2200
;
515 switch (var
->bits_per_pixel
) {
517 bltMod
= NEO_MODE1_DEPTH8
;
518 pitch
= var
->xres_virtual
;
522 bltMod
= NEO_MODE1_DEPTH16
;
523 pitch
= var
->xres_virtual
* 2;
527 "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
531 neo2200
->bltStat
= bltMod
<< 16;
532 neo2200
->pitch
= (pitch
<< 16) | pitch
;
535 /* --------------------------------------------------------------------- */
538 neofb_check_var(struct fb_var_screeninfo
*var
, struct fb_info
*info
)
540 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
541 unsigned int pixclock
= var
->pixclock
;
542 struct xtimings timings
;
546 DBG("neofb_check_var");
549 pixclock
= 10000; /* 10ns = 100MHz */
550 timings
.pixclock
= 1000000000 / pixclock
;
551 if (timings
.pixclock
< 1)
552 timings
.pixclock
= 1;
554 if (timings
.pixclock
> par
->maxClock
)
557 timings
.dblscan
= var
->vmode
& FB_VMODE_DOUBLE
;
558 timings
.interlaced
= var
->vmode
& FB_VMODE_INTERLACED
;
559 timings
.HDisplay
= var
->xres
;
560 timings
.HSyncStart
= timings
.HDisplay
+ var
->right_margin
;
561 timings
.HSyncEnd
= timings
.HSyncStart
+ var
->hsync_len
;
562 timings
.HTotal
= timings
.HSyncEnd
+ var
->left_margin
;
563 timings
.VDisplay
= var
->yres
;
564 timings
.VSyncStart
= timings
.VDisplay
+ var
->lower_margin
;
565 timings
.VSyncEnd
= timings
.VSyncStart
+ var
->vsync_len
;
566 timings
.VTotal
= timings
.VSyncEnd
+ var
->upper_margin
;
567 timings
.sync
= var
->sync
;
569 /* Is the mode larger than the LCD panel? */
570 if (par
->internal_display
&&
571 ((var
->xres
> par
->NeoPanelWidth
) ||
572 (var
->yres
> par
->NeoPanelHeight
))) {
574 "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
575 var
->xres
, var
->yres
, par
->NeoPanelWidth
,
576 par
->NeoPanelHeight
);
580 /* Is the mode one of the acceptable sizes? */
581 if (!par
->internal_display
)
586 if (var
->yres
== 1024)
590 if (var
->yres
== 768)
594 if (var
->yres
== (par
->libretto
? 480 : 600))
598 if (var
->yres
== 480)
606 "Mode (%dx%d) won't display properly on LCD\n",
607 var
->xres
, var
->yres
);
611 var
->red
.msb_right
= 0;
612 var
->green
.msb_right
= 0;
613 var
->blue
.msb_right
= 0;
615 switch (var
->bits_per_pixel
) {
616 case 8: /* PSEUDOCOLOUR, 256 */
617 var
->transp
.offset
= 0;
618 var
->transp
.length
= 0;
621 var
->green
.offset
= 0;
622 var
->green
.length
= 8;
623 var
->blue
.offset
= 0;
624 var
->blue
.length
= 8;
627 case 16: /* DIRECTCOLOUR, 64k */
628 var
->transp
.offset
= 0;
629 var
->transp
.length
= 0;
630 var
->red
.offset
= 11;
632 var
->green
.offset
= 5;
633 var
->green
.length
= 6;
634 var
->blue
.offset
= 0;
635 var
->blue
.length
= 5;
638 case 24: /* TRUECOLOUR, 16m */
639 var
->transp
.offset
= 0;
640 var
->transp
.length
= 0;
641 var
->red
.offset
= 16;
643 var
->green
.offset
= 8;
644 var
->green
.length
= 8;
645 var
->blue
.offset
= 0;
648 #ifdef NO_32BIT_SUPPORT_YET
649 case 32: /* TRUECOLOUR, 16m */
650 var
->transp
.offset
= 24;
651 var
->transp
.length
= 8;
652 var
->red
.offset
= 16;
654 var
->green
.offset
= 8;
655 var
->green
.length
= 8;
656 var
->blue
.offset
= 0;
657 var
->blue
.length
= 8;
661 printk(KERN_WARNING
"neofb: no support for %dbpp\n",
662 var
->bits_per_pixel
);
666 vramlen
= info
->fix
.smem_len
;
667 if (vramlen
> 4 * 1024 * 1024)
668 vramlen
= 4 * 1024 * 1024;
670 if (var
->yres_virtual
< var
->yres
)
671 var
->yres_virtual
= var
->yres
;
672 if (var
->xres_virtual
< var
->xres
)
673 var
->xres_virtual
= var
->xres
;
676 var
->xres_virtual
* var
->bits_per_pixel
* var
->yres_virtual
/
678 if (memlen
> vramlen
) {
680 vramlen
* 8 / (var
->xres_virtual
*
681 var
->bits_per_pixel
);
683 var
->xres_virtual
* var
->bits_per_pixel
*
684 var
->yres_virtual
/ 8;
687 /* we must round yres/xres down, we already rounded y/xres_virtual up
688 if it was possible. We should return -EINVAL, but I disagree */
689 if (var
->yres_virtual
< var
->yres
)
690 var
->yres
= var
->yres_virtual
;
691 if (var
->xres_virtual
< var
->xres
)
692 var
->xres
= var
->xres_virtual
;
693 if (var
->xoffset
+ var
->xres
> var
->xres_virtual
)
694 var
->xoffset
= var
->xres_virtual
- var
->xres
;
695 if (var
->yoffset
+ var
->yres
> var
->yres_virtual
)
696 var
->yoffset
= var
->yres_virtual
- var
->yres
;
702 if (var
->bits_per_pixel
>= 24 || !par
->neo2200
)
703 var
->accel_flags
&= ~FB_ACCELF_TEXT
;
707 static int neofb_set_par(struct fb_info
*info
)
709 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
710 struct xtimings timings
;
714 int hoffset
, voffset
;
716 DBG("neofb_set_par");
720 vgaHWProtect(1); /* Blank the screen */
722 timings
.dblscan
= info
->var
.vmode
& FB_VMODE_DOUBLE
;
723 timings
.interlaced
= info
->var
.vmode
& FB_VMODE_INTERLACED
;
724 timings
.HDisplay
= info
->var
.xres
;
725 timings
.HSyncStart
= timings
.HDisplay
+ info
->var
.right_margin
;
726 timings
.HSyncEnd
= timings
.HSyncStart
+ info
->var
.hsync_len
;
727 timings
.HTotal
= timings
.HSyncEnd
+ info
->var
.left_margin
;
728 timings
.VDisplay
= info
->var
.yres
;
729 timings
.VSyncStart
= timings
.VDisplay
+ info
->var
.lower_margin
;
730 timings
.VSyncEnd
= timings
.VSyncStart
+ info
->var
.vsync_len
;
731 timings
.VTotal
= timings
.VSyncEnd
+ info
->var
.upper_margin
;
732 timings
.sync
= info
->var
.sync
;
733 timings
.pixclock
= PICOS2KHZ(info
->var
.pixclock
);
735 if (timings
.pixclock
< 1)
736 timings
.pixclock
= 1;
739 * This will allocate the datastructure and initialize all of the
740 * generic VGA registers.
743 if (vgaHWInit(&info
->var
, info
, par
, &timings
))
747 * The default value assigned by vgaHW.c is 0x41, but this does
748 * not work for NeoMagic.
750 par
->Attribute
[16] = 0x01;
752 switch (info
->var
.bits_per_pixel
) {
754 par
->CRTC
[0x13] = info
->var
.xres_virtual
>> 3;
755 par
->ExtCRTOffset
= info
->var
.xres_virtual
>> 11;
756 par
->ExtColorModeSelect
= 0x11;
759 par
->CRTC
[0x13] = info
->var
.xres_virtual
>> 2;
760 par
->ExtCRTOffset
= info
->var
.xres_virtual
>> 10;
761 par
->ExtColorModeSelect
= 0x13;
764 par
->CRTC
[0x13] = (info
->var
.xres_virtual
* 3) >> 3;
765 par
->ExtCRTOffset
= (info
->var
.xres_virtual
* 3) >> 11;
766 par
->ExtColorModeSelect
= 0x14;
768 #ifdef NO_32BIT_SUPPORT_YET
769 case 32: /* FIXME: guessed values */
770 par
->CRTC
[0x13] = info
->var
.xres_virtual
>> 1;
771 par
->ExtCRTOffset
= info
->var
.xres_virtual
>> 9;
772 par
->ExtColorModeSelect
= 0x15;
779 par
->ExtCRTDispAddr
= 0x10;
781 /* Vertical Extension */
782 par
->VerticalExt
= (((timings
.VTotal
- 2) & 0x400) >> 10)
783 | (((timings
.VDisplay
- 1) & 0x400) >> 9)
784 | (((timings
.VSyncStart
) & 0x400) >> 8)
785 | (((timings
.VSyncStart
) & 0x400) >> 7);
787 /* Fast write bursts on unless disabled. */
789 par
->SysIfaceCntl1
= 0x30;
791 par
->SysIfaceCntl1
= 0x00;
793 par
->SysIfaceCntl2
= 0xc0; /* VESA Bios sets this to 0x80! */
795 /* Enable any user specified display devices. */
796 par
->PanelDispCntlReg1
= 0x00;
797 if (par
->internal_display
)
798 par
->PanelDispCntlReg1
|= 0x02;
799 if (par
->external_display
)
800 par
->PanelDispCntlReg1
|= 0x01;
802 /* If the user did not specify any display devices, then... */
803 if (par
->PanelDispCntlReg1
== 0x00) {
804 /* Default to internal (i.e., LCD) only. */
805 par
->PanelDispCntlReg1
|= 0x02;
808 /* If we are using a fixed mode, then tell the chip we are. */
809 switch (info
->var
.xres
) {
811 par
->PanelDispCntlReg1
|= 0x60;
814 par
->PanelDispCntlReg1
|= 0x40;
817 par
->PanelDispCntlReg1
|= 0x20;
824 /* Setup shadow register locking. */
825 switch (par
->PanelDispCntlReg1
& 0x03) {
826 case 0x01: /* External CRT only mode: */
827 par
->GeneralLockReg
= 0x00;
828 /* We need to program the VCLK for external display only mode. */
829 par
->ProgramVCLK
= 1;
831 case 0x02: /* Internal LCD only mode: */
832 case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */
833 par
->GeneralLockReg
= 0x01;
834 /* Don't program the VCLK when using the LCD. */
835 par
->ProgramVCLK
= 0;
840 * If the screen is to be stretched, turn on stretching for the
843 * OPTION_LCD_STRETCH means stretching should be turned off!
845 par
->PanelDispCntlReg2
= 0x00;
846 par
->PanelDispCntlReg3
= 0x00;
848 if (par
->lcd_stretch
&& (par
->PanelDispCntlReg1
== 0x02) && /* LCD only */
849 (info
->var
.xres
!= par
->NeoPanelWidth
)) {
850 switch (info
->var
.xres
) {
851 case 320: /* Needs testing. KEM -- 24 May 98 */
852 case 400: /* Needs testing. KEM -- 24 May 98 */
857 par
->PanelDispCntlReg2
|= 0xC6;
861 /* No stretching in these modes. */
867 * If the screen is to be centerd, turn on the centering for the
870 par
->PanelVertCenterReg1
= 0x00;
871 par
->PanelVertCenterReg2
= 0x00;
872 par
->PanelVertCenterReg3
= 0x00;
873 par
->PanelVertCenterReg4
= 0x00;
874 par
->PanelVertCenterReg5
= 0x00;
875 par
->PanelHorizCenterReg1
= 0x00;
876 par
->PanelHorizCenterReg2
= 0x00;
877 par
->PanelHorizCenterReg3
= 0x00;
878 par
->PanelHorizCenterReg4
= 0x00;
879 par
->PanelHorizCenterReg5
= 0x00;
882 if (par
->PanelDispCntlReg1
& 0x02) {
883 if (info
->var
.xres
== par
->NeoPanelWidth
) {
885 * No centering required when the requested display width
886 * equals the panel width.
889 par
->PanelDispCntlReg2
|= 0x01;
890 par
->PanelDispCntlReg3
|= 0x10;
892 /* Calculate the horizontal and vertical offsets. */
895 ((par
->NeoPanelWidth
-
896 info
->var
.xres
) >> 4) - 1;
898 ((par
->NeoPanelHeight
-
899 info
->var
.yres
) >> 1) - 2;
901 /* Stretched modes cannot be centered. */
906 switch (info
->var
.xres
) {
907 case 320: /* Needs testing. KEM -- 24 May 98 */
908 par
->PanelHorizCenterReg3
= hoffset
;
909 par
->PanelVertCenterReg2
= voffset
;
911 case 400: /* Needs testing. KEM -- 24 May 98 */
912 par
->PanelHorizCenterReg4
= hoffset
;
913 par
->PanelVertCenterReg1
= voffset
;
916 par
->PanelHorizCenterReg1
= hoffset
;
917 par
->PanelVertCenterReg3
= voffset
;
920 par
->PanelHorizCenterReg2
= hoffset
;
921 par
->PanelVertCenterReg4
= voffset
;
924 par
->PanelHorizCenterReg5
= hoffset
;
925 par
->PanelVertCenterReg5
= voffset
;
929 /* No centering in these modes. */
936 neoFindMode(info
->var
.xres
, info
->var
.yres
,
937 info
->var
.bits_per_pixel
);
940 * Calculate the VCLK that most closely matches the requested dot
943 neoCalcVCLK(info
, par
, timings
.pixclock
);
945 /* Since we program the clocks ourselves, always use VCLK3. */
946 par
->MiscOutReg
|= 0x0C;
948 /* linear colormap for non palettized modes */
949 switch (info
->var
.bits_per_pixel
) {
951 /* PseudoColor, 256 */
952 info
->fix
.visual
= FB_VISUAL_PSEUDOCOLOR
;
955 /* DirectColor, 64k */
956 info
->fix
.visual
= FB_VISUAL_DIRECTCOLOR
;
958 for (i
= 0; i
< 64; i
++) {
967 #ifdef NO_32BIT_SUPPORT_YET
971 info
->fix
.visual
= FB_VISUAL_TRUECOLOR
;
973 for (i
= 0; i
< 256; i
++) {
983 /* alread unlocked above */
984 /* BOGUS VGAwGR (0x09, 0x26); */
986 /* don't know what this is, but it's 0 from bootup anyway */
989 /* was set to 0x01 by my bios in text and vesa modes */
990 VGAwGR(0x0A, par
->GeneralLockReg
);
993 * The color mode needs to be set before calling vgaHWRestore
994 * to ensure the DAC is initialized properly.
996 * NOTE: Make sure we don't change bits make sure we don't change
1000 switch (info
->fix
.accel
) {
1001 case FB_ACCEL_NEOMAGIC_NM2070
:
1002 temp
&= 0xF0; /* Save bits 7:4 */
1003 temp
|= (par
->ExtColorModeSelect
& ~0xF0);
1005 case FB_ACCEL_NEOMAGIC_NM2090
:
1006 case FB_ACCEL_NEOMAGIC_NM2093
:
1007 case FB_ACCEL_NEOMAGIC_NM2097
:
1008 case FB_ACCEL_NEOMAGIC_NM2160
:
1009 case FB_ACCEL_NEOMAGIC_NM2200
:
1010 case FB_ACCEL_NEOMAGIC_NM2230
:
1011 case FB_ACCEL_NEOMAGIC_NM2360
:
1012 case FB_ACCEL_NEOMAGIC_NM2380
:
1013 temp
&= 0x70; /* Save bits 6:4 */
1014 temp
|= (par
->ExtColorModeSelect
& ~0x70);
1021 * In some rare cases a lockup might occur if we don't delay
1022 * here. (Reported by Miles Lane)
1027 * Disable horizontal and vertical graphics and text expansions so
1028 * that vgaHWRestore works properly.
1030 temp
= VGArGR(0x25);
1035 * Sleep for 200ms to make sure that the two operations above have
1036 * had time to take effect.
1041 * This function handles restoring the generic VGA registers. */
1042 vgaHWRestore(info
, par
);
1045 VGAwGR(0x0E, par
->ExtCRTDispAddr
);
1046 VGAwGR(0x0F, par
->ExtCRTOffset
);
1047 temp
= VGArGR(0x10);
1048 temp
&= 0x0F; /* Save bits 3:0 */
1049 temp
|= (par
->SysIfaceCntl1
& ~0x0F); /* VESA Bios sets bit 1! */
1052 VGAwGR(0x11, par
->SysIfaceCntl2
);
1053 VGAwGR(0x15, 0 /*par->SingleAddrPage */ );
1054 VGAwGR(0x16, 0 /*par->DualAddrPage */ );
1056 temp
= VGArGR(0x20);
1057 switch (info
->fix
.accel
) {
1058 case FB_ACCEL_NEOMAGIC_NM2070
:
1059 temp
&= 0xFC; /* Save bits 7:2 */
1060 temp
|= (par
->PanelDispCntlReg1
& ~0xFC);
1062 case FB_ACCEL_NEOMAGIC_NM2090
:
1063 case FB_ACCEL_NEOMAGIC_NM2093
:
1064 case FB_ACCEL_NEOMAGIC_NM2097
:
1065 case FB_ACCEL_NEOMAGIC_NM2160
:
1066 temp
&= 0xDC; /* Save bits 7:6,4:2 */
1067 temp
|= (par
->PanelDispCntlReg1
& ~0xDC);
1069 case FB_ACCEL_NEOMAGIC_NM2200
:
1070 case FB_ACCEL_NEOMAGIC_NM2230
:
1071 case FB_ACCEL_NEOMAGIC_NM2360
:
1072 case FB_ACCEL_NEOMAGIC_NM2380
:
1073 temp
&= 0x98; /* Save bits 7,4:3 */
1074 temp
|= (par
->PanelDispCntlReg1
& ~0x98);
1079 temp
= VGArGR(0x25);
1080 temp
&= 0x38; /* Save bits 5:3 */
1081 temp
|= (par
->PanelDispCntlReg2
& ~0x38);
1084 if (info
->fix
.accel
!= FB_ACCEL_NEOMAGIC_NM2070
) {
1085 temp
= VGArGR(0x30);
1086 temp
&= 0xEF; /* Save bits 7:5 and bits 3:0 */
1087 temp
|= (par
->PanelDispCntlReg3
& ~0xEF);
1091 VGAwGR(0x28, par
->PanelVertCenterReg1
);
1092 VGAwGR(0x29, par
->PanelVertCenterReg2
);
1093 VGAwGR(0x2a, par
->PanelVertCenterReg3
);
1095 if (info
->fix
.accel
!= FB_ACCEL_NEOMAGIC_NM2070
) {
1096 VGAwGR(0x32, par
->PanelVertCenterReg4
);
1097 VGAwGR(0x33, par
->PanelHorizCenterReg1
);
1098 VGAwGR(0x34, par
->PanelHorizCenterReg2
);
1099 VGAwGR(0x35, par
->PanelHorizCenterReg3
);
1102 if (info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2160
)
1103 VGAwGR(0x36, par
->PanelHorizCenterReg4
);
1105 if (info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2200
||
1106 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2230
||
1107 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2360
||
1108 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2380
) {
1109 VGAwGR(0x36, par
->PanelHorizCenterReg4
);
1110 VGAwGR(0x37, par
->PanelVertCenterReg5
);
1111 VGAwGR(0x38, par
->PanelHorizCenterReg5
);
1116 /* Program VCLK3 if needed. */
1117 if (par
->ProgramVCLK
&& ((VGArGR(0x9B) != par
->VCLK3NumeratorLow
)
1118 || (VGArGR(0x9F) != par
->VCLK3Denominator
)
1119 || (clock_hi
&& ((VGArGR(0x8F) & ~0x0f)
1121 VCLK3NumeratorHigh
&
1123 VGAwGR(0x9B, par
->VCLK3NumeratorLow
);
1125 temp
= VGArGR(0x8F);
1126 temp
&= 0x0F; /* Save bits 3:0 */
1127 temp
|= (par
->VCLK3NumeratorHigh
& ~0x0F);
1130 VGAwGR(0x9F, par
->VCLK3Denominator
);
1134 VGAwCR(0x23, par
->biosMode
);
1136 VGAwGR(0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
1138 /* Program vertical extension register */
1139 if (info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2200
||
1140 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2230
||
1141 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2360
||
1142 info
->fix
.accel
== FB_ACCEL_NEOMAGIC_NM2380
) {
1143 VGAwCR(0x70, par
->VerticalExt
);
1146 vgaHWProtect(0); /* Turn on screen */
1148 /* Calling this also locks offset registers required in update_start */
1151 info
->fix
.line_length
=
1152 info
->var
.xres_virtual
* (info
->var
.bits_per_pixel
>> 3);
1154 switch (info
->fix
.accel
) {
1155 case FB_ACCEL_NEOMAGIC_NM2200
:
1156 case FB_ACCEL_NEOMAGIC_NM2230
:
1157 case FB_ACCEL_NEOMAGIC_NM2360
:
1158 case FB_ACCEL_NEOMAGIC_NM2380
:
1159 neo2200_accel_init(info
, &info
->var
);
1167 static void neofb_update_start(struct fb_info
*info
,
1168 struct fb_var_screeninfo
*var
)
1170 int oldExtCRTDispAddr
;
1173 DBG("neofb_update_start");
1175 Base
= (var
->yoffset
* var
->xres_virtual
+ var
->xoffset
) >> 2;
1176 Base
*= (var
->bits_per_pixel
+ 7) / 8;
1181 * These are the generic starting address registers.
1183 VGAwCR(0x0C, (Base
& 0x00FF00) >> 8);
1184 VGAwCR(0x0D, (Base
& 0x00FF));
1187 * Make sure we don't clobber some other bits that might already
1188 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
1191 oldExtCRTDispAddr
= VGArGR(0x0E);
1192 VGAwGR(0x0E, (((Base
>> 16) & 0x0f) | (oldExtCRTDispAddr
& 0xf0)));
1198 * Pan or Wrap the Display
1200 static int neofb_pan_display(struct fb_var_screeninfo
*var
,
1201 struct fb_info
*info
)
1205 y_bottom
= var
->yoffset
;
1207 if (!(var
->vmode
& FB_VMODE_YWRAP
))
1208 y_bottom
+= var
->yres
;
1210 if (var
->xoffset
> (var
->xres_virtual
- var
->xres
))
1212 if (y_bottom
> info
->var
.yres_virtual
)
1215 neofb_update_start(info
, var
);
1217 info
->var
.xoffset
= var
->xoffset
;
1218 info
->var
.yoffset
= var
->yoffset
;
1220 if (var
->vmode
& FB_VMODE_YWRAP
)
1221 info
->var
.vmode
|= FB_VMODE_YWRAP
;
1223 info
->var
.vmode
&= ~FB_VMODE_YWRAP
;
1227 static int neofb_setcolreg(u_int regno
, u_int red
, u_int green
, u_int blue
,
1228 u_int transp
, struct fb_info
*fb
)
1230 if (regno
>= NR_PALETTE
)
1233 switch (fb
->var
.bits_per_pixel
) {
1237 outb(red
>> 10, 0x3c9);
1238 outb(green
>> 10, 0x3c9);
1239 outb(blue
>> 10, 0x3c9);
1243 ((u16
*) fb
->pseudo_palette
)[regno
] =
1244 ((red
& 0xf800)) | ((green
& 0xfc00) >> 5) |
1245 ((blue
& 0xf800) >> 11);
1249 ((u32
*) fb
->pseudo_palette
)[regno
] =
1250 ((red
& 0xff00) << 8) | ((green
& 0xff00)) |
1251 ((blue
& 0xff00) >> 8);
1253 #ifdef NO_32BIT_SUPPORT_YET
1256 ((u32
*) fb
->pseudo_palette
)[regno
] =
1257 ((transp
& 0xff00) << 16) | ((red
& 0xff00) <<
1260 ((blue
& 0xff00) >> 8);
1270 * (Un)Blank the display.
1272 static int neofb_blank(int blank
, struct fb_info
*info
)
1275 * Blank the screen if blank_mode != 0, else unblank. If
1276 * blank == NULL then the caller blanks by setting the CLUT
1277 * (Color Look Up Table) to all black. Return 0 if blanking
1278 * succeeded, != 0 if un-/blanking failed due to e.g. a
1279 * video mode which doesn't support it. Implements VESA
1280 * suspend and powerdown modes on hardware that supports
1281 * disabling hsync/vsync:
1282 * blank_mode == 2: suspend vsync
1283 * blank_mode == 3: suspend hsync
1284 * blank_mode == 4: powerdown
1286 * wms...Enable VESA DMPS compatible powerdown mode
1287 * run "setterm -powersave powerdown" to take advantage
1291 case 4: /* powerdown - both sync lines down */
1292 #ifdef CONFIG_TOSHIBA
1293 /* attempt to turn off backlight on toshiba; also turns off external */
1297 regs
.eax
= 0xff00; /* HCI_SET */
1298 regs
.ebx
= 0x0002; /* HCI_BACKLIGHT */
1299 regs
.ecx
= 0x0000; /* HCI_DISABLE */
1304 case 3: /* hsync off */
1306 case 2: /* vsync off */
1308 case 1: /* just software blanking of screen */
1310 default: /* case 0, or anything else: unblank */
1311 #ifdef CONFIG_TOSHIBA
1312 /* attempt to re-enable backlight/external on toshiba */
1316 regs
.eax
= 0xff00; /* HCI_SET */
1317 regs
.ebx
= 0x0002; /* HCI_BACKLIGHT */
1318 regs
.ecx
= 0x0001; /* HCI_ENABLE */
1328 neo2200_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
1330 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1333 dst
= rect
->dx
+ rect
->dy
* info
->var
.xres_virtual
;
1334 rop
= rect
->rop
? 0x060000 : 0x0c0000;
1336 neo2200_wait_fifo(info
, 4);
1338 /* set blt control */
1339 par
->neo2200
->bltCntl
= NEO_BC3_FIFO_EN
|
1340 NEO_BC0_SRC_IS_FG
| NEO_BC3_SKIP_MAPPING
|
1341 // NEO_BC3_DST_XY_ADDR |
1342 // NEO_BC3_SRC_XY_ADDR |
1345 switch (info
->var
.bits_per_pixel
) {
1347 par
->neo2200
->fgColor
= rect
->color
;
1350 par
->neo2200
->fgColor
=
1351 ((u16
*) (info
->pseudo_palette
))[rect
->color
];
1355 par
->neo2200
->dstStart
=
1356 dst
* ((info
->var
.bits_per_pixel
+ 7) / 8);
1357 par
->neo2200
->xyExt
=
1358 (rect
->height
<< 16) | (rect
->width
& 0xffff);
1362 neo2200_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
1364 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1365 u32 sx
= area
->sx
, sy
= area
->sy
, dx
= area
->dx
, dy
= area
->dy
;
1366 u_long src
, dst
, bltCntl
;
1368 bltCntl
= NEO_BC3_FIFO_EN
| NEO_BC3_SKIP_MAPPING
| 0x0C0000;
1371 sy
+= (area
->height
- 1);
1372 dy
+= (area
->height
- 1);
1374 bltCntl
|= NEO_BC0_DST_Y_DEC
| NEO_BC0_SRC_Y_DEC
;
1377 if (area
->sx
< area
->dx
) {
1378 sx
+= (area
->width
- 1);
1379 dx
+= (area
->width
- 1);
1381 bltCntl
|= NEO_BC0_X_DEC
;
1384 src
= sx
* (info
->var
.bits_per_pixel
>> 3) + sy
*info
->fix
.line_length
;
1385 dst
= dx
* (info
->var
.bits_per_pixel
>> 3) + dy
*info
->fix
.line_length
;
1387 neo2200_wait_fifo(info
, 4);
1389 /* set blt control */
1390 par
->neo2200
->bltCntl
= bltCntl
;
1392 par
->neo2200
->srcStart
= src
;
1393 par
->neo2200
->dstStart
= dst
;
1394 par
->neo2200
->xyExt
=
1395 (area
->height
<< 16) | (area
->width
& 0xffff);
1399 neo2200_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
1401 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1405 switch (info
->var
.bits_per_pixel
) {
1407 par
->neo2200
->fgColor
= image
->fg_color
;
1408 par
->neo2200
->bgColor
= image
->bg_color
;
1411 par
->neo2200
->fgColor
=
1412 ((u16
*) (info
->pseudo_palette
))[image
->fg_color
];
1413 par
->neo2200
->bgColor
=
1414 ((u16
*) (info
->pseudo_palette
))[image
->bg_color
];
1418 par
->neo2200
->bltCntl
= NEO_BC0_SYS_TO_VID
|
1419 NEO_BC0_SRC_MONO
| NEO_BC3_SKIP_MAPPING
|
1420 // NEO_BC3_DST_XY_ADDR |
1423 par
->neo2200
->srcStart
= 0;
1424 // par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
1425 par
->neo2200
->dstStart
=
1426 ((image
->dx
& 0xffff) * (info
->var
.bits_per_pixel
>> 3) +
1427 image
->dy
* info
->fix
.line_length
);
1428 par
->neo2200
->xyExt
=
1429 (image
->height
<< 16) | (image
->width
& 0xffff);
1431 memcpy(par
->mmio_vbase
+ 0x100000, image
->data
,
1432 (image
->width
* image
->height
) >> 3);
1436 neofb_fillrect(struct fb_info
*info
, const struct fb_fillrect
*rect
)
1438 switch (info
->fix
.accel
) {
1439 case FB_ACCEL_NEOMAGIC_NM2200
:
1440 case FB_ACCEL_NEOMAGIC_NM2230
:
1441 case FB_ACCEL_NEOMAGIC_NM2360
:
1442 case FB_ACCEL_NEOMAGIC_NM2380
:
1443 neo2200_fillrect(info
, rect
);
1446 cfb_fillrect(info
, rect
);
1452 neofb_copyarea(struct fb_info
*info
, const struct fb_copyarea
*area
)
1454 switch (info
->fix
.accel
) {
1455 case FB_ACCEL_NEOMAGIC_NM2200
:
1456 case FB_ACCEL_NEOMAGIC_NM2230
:
1457 case FB_ACCEL_NEOMAGIC_NM2360
:
1458 case FB_ACCEL_NEOMAGIC_NM2380
:
1459 neo2200_copyarea(info
, area
);
1462 cfb_copyarea(info
, area
);
1468 neofb_imageblit(struct fb_info
*info
, const struct fb_image
*image
)
1470 switch (info
->fix
.accel
) {
1471 case FB_ACCEL_NEOMAGIC_NM2200
:
1472 case FB_ACCEL_NEOMAGIC_NM2230
:
1473 case FB_ACCEL_NEOMAGIC_NM2360
:
1474 case FB_ACCEL_NEOMAGIC_NM2380
:
1475 neo2200_imageblit(info
, image
);
1478 cfb_imageblit(info
, image
);
1484 neofb_sync(struct fb_info
*info
)
1486 switch (info
->fix
.accel
) {
1487 case FB_ACCEL_NEOMAGIC_NM2200
:
1488 case FB_ACCEL_NEOMAGIC_NM2230
:
1489 case FB_ACCEL_NEOMAGIC_NM2360
:
1490 case FB_ACCEL_NEOMAGIC_NM2380
:
1499 static struct fb_ops neofb_ops
= {
1500 .owner
= THIS_MODULE
,
1501 .fb_check_var
= neofb_check_var
,
1502 .fb_set_par
= neofb_set_par
,
1503 .fb_setcolreg
= neofb_setcolreg
,
1504 .fb_pan_display
= neofb_pan_display
,
1505 .fb_blank
= neofb_blank
,
1506 .fb_sync
= neofb_sync
,
1507 .fb_fillrect
= neofb_fillrect
,
1508 .fb_copyarea
= neofb_copyarea
,
1509 .fb_imageblit
= neofb_imageblit
,
1510 .fb_cursor
= soft_cursor
,
1513 /* --------------------------------------------------------------------- */
1515 static struct fb_var_screeninfo __devinitdata neofb_var640x480x8
= {
1516 .accel_flags
= FB_ACCELF_TEXT
,
1519 .xres_virtual
= 640,
1520 .yres_virtual
= 30000,
1521 .bits_per_pixel
= 8,
1529 .vmode
= FB_VMODE_NONINTERLACED
1532 static struct fb_var_screeninfo __devinitdata neofb_var800x600x8
= {
1533 .accel_flags
= FB_ACCELF_TEXT
,
1536 .xres_virtual
= 800,
1537 .yres_virtual
= 30000,
1538 .bits_per_pixel
= 8,
1546 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
1547 .vmode
= FB_VMODE_NONINTERLACED
1550 static struct fb_var_screeninfo __devinitdata neofb_var800x480x8
= {
1551 .accel_flags
= FB_ACCELF_TEXT
,
1554 .xres_virtual
= 800,
1555 .yres_virtual
= 30000,
1556 .bits_per_pixel
= 8,
1564 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
1565 .vmode
= FB_VMODE_NONINTERLACED
1568 static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8
= {
1569 .accel_flags
= FB_ACCELF_TEXT
,
1572 .xres_virtual
= 1024,
1573 .yres_virtual
= 30000,
1574 .bits_per_pixel
= 8,
1582 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
1583 .vmode
= FB_VMODE_NONINTERLACED
1587 static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8
= {
1588 .accel_flags
= FB_ACCELF_TEXT
,
1591 .xres_virtual
= 1280,
1592 .yres_virtual
= 30000,
1593 .bits_per_pixel
= 8,
1601 .sync
= FB_SYNC_HOR_HIGH_ACT
| FB_SYNC_VERT_HIGH_ACT
,
1602 .vmode
= FB_VMODE_NONINTERLACED
1606 static int __devinit
neo_map_mmio(struct fb_info
*info
,
1607 struct pci_dev
*dev
)
1609 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1611 DBG("neo_map_mmio");
1613 info
->fix
.mmio_start
= pci_resource_start(dev
, 1);
1614 info
->fix
.mmio_len
= MMIO_SIZE
;
1616 if (!request_mem_region
1617 (info
->fix
.mmio_start
, MMIO_SIZE
, "memory mapped I/O")) {
1618 printk("neofb: memory mapped IO in use\n");
1622 par
->mmio_vbase
= ioremap(info
->fix
.mmio_start
, MMIO_SIZE
);
1623 if (!par
->mmio_vbase
) {
1624 printk("neofb: unable to map memory mapped IO\n");
1625 release_mem_region(info
->fix
.mmio_start
,
1626 info
->fix
.mmio_len
);
1629 printk(KERN_INFO
"neofb: mapped io at %p\n",
1634 static void __devinit
neo_unmap_mmio(struct fb_info
*info
)
1636 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1638 DBG("neo_unmap_mmio");
1640 if (par
->mmio_vbase
) {
1641 iounmap(par
->mmio_vbase
);
1642 par
->mmio_vbase
= NULL
;
1644 release_mem_region(info
->fix
.mmio_start
,
1645 info
->fix
.mmio_len
);
1649 static int __devinit
neo_map_video(struct fb_info
*info
,
1650 struct pci_dev
*dev
, int video_len
)
1652 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1654 DBG("neo_map_video");
1656 info
->fix
.smem_start
= pci_resource_start(dev
, 0);
1657 info
->fix
.smem_len
= video_len
;
1659 if (!request_mem_region
1660 (info
->fix
.smem_start
, info
->fix
.smem_len
, "frame buffer")) {
1661 printk("neofb: frame buffer in use\n");
1666 ioremap(info
->fix
.smem_start
, info
->fix
.smem_len
);
1667 if (!info
->screen_base
) {
1668 printk("neofb: unable to map screen memory\n");
1669 release_mem_region(info
->fix
.smem_start
,
1670 info
->fix
.smem_len
);
1673 printk(KERN_INFO
"neofb: mapped framebuffer at %p\n",
1678 mtrr_add(info
->fix
.smem_start
, pci_resource_len(dev
, 0),
1679 MTRR_TYPE_WRCOMB
, 1);
1682 /* Clear framebuffer, it's all white in memory after boot */
1683 memset(info
->screen_base
, 0, info
->fix
.smem_len
);
1687 static void __devinit
neo_unmap_video(struct fb_info
*info
)
1689 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1691 DBG("neo_unmap_video");
1693 if (info
->screen_base
) {
1695 mtrr_del(par
->mtrr
, info
->fix
.smem_start
,
1696 info
->fix
.smem_len
);
1699 iounmap(info
->screen_base
);
1700 info
->screen_base
= NULL
;
1702 release_mem_region(info
->fix
.smem_start
,
1703 info
->fix
.smem_len
);
1707 static int __devinit
neo_init_hw(struct fb_info
*info
)
1709 struct neofb_par
*par
= (struct neofb_par
*) info
->par
;
1710 unsigned char type
, display
;
1712 int maxClock
= 65000;
1713 int CursorMem
= 1024;
1714 int CursorOff
= 0x100;
1715 int linearSize
= 1024;
1716 int maxWidth
= 1024;
1717 int maxHeight
= 1024;
1725 printk(KERN_DEBUG
"--- Neo extended register dump ---\n");
1726 for (w
= 0; w
< 0x85; w
++)
1727 printk(KERN_DEBUG
"CR %p: %p\n", (void *) w
,
1728 (void *) VGArCR(w
));
1729 for (w
= 0; w
< 0xC7; w
++)
1730 printk(KERN_DEBUG
"GR %p: %p\n", (void *) w
,
1731 (void *) VGArGR(w
));
1734 /* Determine the panel type */
1736 type
= VGArGR(0x21);
1737 display
= VGArGR(0x20);
1738 if (!par
->internal_display
&& !par
->external_display
) {
1739 par
->internal_display
= display
& 2 || !(display
& 3) ? 1 : 0;
1740 par
->external_display
= display
& 1;
1741 printk (KERN_INFO
"Autodetected %s display\n",
1742 par
->internal_display
&& par
->external_display
? "simultaneous" :
1743 par
->internal_display
? "internal" : "external");
1746 /* Determine panel width -- used in NeoValidMode. */
1749 switch ((w
& 0x18) >> 3) {
1751 par
->NeoPanelWidth
= 640;
1752 par
->NeoPanelHeight
= 480;
1753 info
->var
= neofb_var640x480x8
;
1756 par
->NeoPanelWidth
= 800;
1757 par
->NeoPanelHeight
= par
->libretto
? 480 : 600;
1758 info
->var
= par
->libretto
? neofb_var800x480x8
: neofb_var800x600x8
;
1761 par
->NeoPanelWidth
= 1024;
1762 par
->NeoPanelHeight
= 768;
1763 info
->var
= neofb_var1024x768x8
;
1766 /* 1280x1024 panel support needs to be added */
1768 par
->NeoPanelWidth
= 1280;
1769 par
->NeoPanelHeight
= 1024;
1770 info
->var
= neofb_var1280x1024x8
;
1774 "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
1778 par
->NeoPanelWidth
= 640;
1779 par
->NeoPanelHeight
= 480;
1780 info
->var
= neofb_var640x480x8
;
1784 printk(KERN_INFO
"Panel is a %dx%d %s %s display\n",
1786 par
->NeoPanelHeight
,
1787 (type
& 0x02) ? "color" : "monochrome",
1788 (type
& 0x10) ? "TFT" : "dual scan");
1790 switch (info
->fix
.accel
) {
1791 case FB_ACCEL_NEOMAGIC_NM2070
:
1800 case FB_ACCEL_NEOMAGIC_NM2090
:
1801 case FB_ACCEL_NEOMAGIC_NM2093
:
1810 case FB_ACCEL_NEOMAGIC_NM2097
:
1819 case FB_ACCEL_NEOMAGIC_NM2160
:
1828 case FB_ACCEL_NEOMAGIC_NM2200
:
1835 maxHeight
= 1024; /* ???? */
1837 par
->neo2200
= (Neo2200
*) par
->mmio_vbase
;
1839 case FB_ACCEL_NEOMAGIC_NM2230
:
1846 maxHeight
= 1024; /* ???? */
1848 par
->neo2200
= (Neo2200
*) par
->mmio_vbase
;
1850 case FB_ACCEL_NEOMAGIC_NM2360
:
1857 maxHeight
= 1024; /* ???? */
1859 par
->neo2200
= (Neo2200
*) par
->mmio_vbase
;
1861 case FB_ACCEL_NEOMAGIC_NM2380
:
1868 maxHeight
= 1024; /* ???? */
1870 par
->neo2200
= (Neo2200
*) par
->mmio_vbase
;
1874 par
->maxClock
= maxClock
;
1876 return videoRam
* 1024;
1880 static struct fb_info
*__devinit
neo_alloc_fb_info(struct pci_dev
*dev
, const struct
1883 struct fb_info
*info
;
1884 struct neofb_par
*par
;
1886 info
= kmalloc(sizeof(struct fb_info
) + sizeof(struct neofb_par
) +
1887 sizeof(u32
) * 17, GFP_KERNEL
);
1892 memset(info
, 0, sizeof(struct fb_info
) + sizeof(struct neofb_par
) + sizeof(u32
) * 17);
1894 par
= (struct neofb_par
*) (info
+ 1);
1896 info
->fix
.accel
= id
->driver_data
;
1898 par
->pci_burst
= !nopciburst
;
1899 par
->lcd_stretch
= !nostretch
;
1900 par
->libretto
= libretto
;
1902 par
->internal_display
= internal
;
1903 par
->external_display
= external
;
1905 switch (info
->fix
.accel
) {
1906 case FB_ACCEL_NEOMAGIC_NM2070
:
1907 sprintf(info
->fix
.id
, "MagicGraph 128");
1909 case FB_ACCEL_NEOMAGIC_NM2090
:
1910 sprintf(info
->fix
.id
, "MagicGraph 128V");
1912 case FB_ACCEL_NEOMAGIC_NM2093
:
1913 sprintf(info
->fix
.id
, "MagicGraph 128ZV");
1915 case FB_ACCEL_NEOMAGIC_NM2097
:
1916 sprintf(info
->fix
.id
, "MagicGraph 128ZV+");
1918 case FB_ACCEL_NEOMAGIC_NM2160
:
1919 sprintf(info
->fix
.id
, "MagicGraph 128XD");
1921 case FB_ACCEL_NEOMAGIC_NM2200
:
1922 sprintf(info
->fix
.id
, "MagicGraph 256AV");
1924 case FB_ACCEL_NEOMAGIC_NM2230
:
1925 sprintf(info
->fix
.id
, "MagicGraph 256AV+");
1927 case FB_ACCEL_NEOMAGIC_NM2360
:
1928 sprintf(info
->fix
.id
, "MagicGraph 256ZX");
1930 case FB_ACCEL_NEOMAGIC_NM2380
:
1931 sprintf(info
->fix
.id
, "MagicGraph 256XL+");
1935 info
->fix
.type
= FB_TYPE_PACKED_PIXELS
;
1936 info
->fix
.type_aux
= 0;
1937 info
->fix
.xpanstep
= 0;
1938 info
->fix
.ypanstep
= 4;
1939 info
->fix
.ywrapstep
= 0;
1940 info
->fix
.accel
= id
->driver_data
;
1942 info
->fbops
= &neofb_ops
;
1943 info
->flags
= FBINFO_FLAG_DEFAULT
;
1945 info
->pseudo_palette
= (void *) (par
+ 1);
1947 fb_alloc_cmap(&info
->cmap
, NR_PALETTE
, 0);
1952 static void __devinit
neo_free_fb_info(struct fb_info
*info
)
1956 * Free the colourmap
1958 fb_alloc_cmap(&info
->cmap
, 0, 0);
1964 /* --------------------------------------------------------------------- */
1966 static int __devinit
neofb_probe(struct pci_dev
*dev
,
1967 const struct pci_device_id
*id
)
1969 struct fb_info
*info
;
1970 u_int h_sync
, v_sync
;
1976 err
= pci_enable_device(dev
);
1981 info
= neo_alloc_fb_info(dev
, id
);
1985 err
= neo_map_mmio(info
, dev
);
1989 video_len
= neo_init_hw(info
);
1990 if (video_len
< 0) {
1995 err
= neo_map_video(info
, dev
, video_len
);
2000 * Calculate the hsync and vsync frequencies. Note that
2001 * we split the 1e12 constant up so that we can preserve
2002 * the precision and fit the results into 32-bit registers.
2003 * (1953125000 * 512 = 1e12)
2005 h_sync
= 1953125000 / info
->var
.pixclock
;
2007 h_sync
* 512 / (info
->var
.xres
+ info
->var
.left_margin
+
2008 info
->var
.right_margin
+ info
->var
.hsync_len
);
2010 h_sync
/ (info
->var
.yres
+ info
->var
.upper_margin
+
2011 info
->var
.lower_margin
+ info
->var
.vsync_len
);
2013 printk(KERN_INFO
"neofb v" NEOFB_VERSION
2014 ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2015 info
->fix
.smem_len
>> 10, info
->var
.xres
,
2016 info
->var
.yres
, h_sync
/ 1000, h_sync
% 1000, v_sync
);
2019 err
= register_framebuffer(info
);
2023 printk(KERN_INFO
"fb%d: %s frame buffer device\n",
2024 info
->node
, info
->fix
.id
);
2029 pci_set_drvdata(dev
, info
);
2033 neo_unmap_video(info
);
2034 neo_unmap_mmio(info
);
2035 neo_free_fb_info(info
);
2040 static void __devexit
neofb_remove(struct pci_dev
*dev
)
2042 struct fb_info
*info
= pci_get_drvdata(dev
);
2044 DBG("neofb_remove");
2048 * If unregister_framebuffer fails, then
2049 * we will be leaving hooks that could cause
2050 * oopsen laying around.
2052 if (unregister_framebuffer(info
))
2054 "neofb: danger danger! Oopsen imminent!\n");
2056 neo_unmap_video(info
);
2057 neo_unmap_mmio(info
);
2058 neo_free_fb_info(info
);
2061 * Ensure that the driver data is no longer
2064 pci_set_drvdata(dev
, NULL
);
2068 static struct pci_device_id neofb_devices
[] __devinitdata
= {
2069 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2070
,
2070 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2070
},
2072 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2090
,
2073 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2090
},
2075 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2093
,
2076 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2093
},
2078 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2097
,
2079 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2097
},
2081 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2160
,
2082 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2160
},
2084 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2200
,
2085 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2200
},
2087 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2230
,
2088 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2230
},
2090 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2360
,
2091 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2360
},
2093 {PCI_VENDOR_ID_NEOMAGIC
, PCI_CHIP_NM2380
,
2094 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, FB_ACCEL_NEOMAGIC_NM2380
},
2096 {0, 0, 0, 0, 0, 0, 0}
2099 MODULE_DEVICE_TABLE(pci
, neofb_devices
);
2101 static struct pci_driver neofb_driver
= {
2103 .id_table
= neofb_devices
,
2104 .probe
= neofb_probe
,
2105 .remove
= __devexit_p(neofb_remove
)
2108 /* **************************** init-time only **************************** */
2110 static void __init
neo_init(void)
2113 pci_register_driver(&neofb_driver
);
2116 /* **************************** exit-time only **************************** */
2118 static void __exit
neo_done(void)
2121 pci_unregister_driver(&neofb_driver
);
2126 /* ************************* init in-kernel code ************************** */
2128 int __init
neofb_setup(char *options
)
2134 if (!options
|| !*options
)
2137 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
2141 if (!strncmp(this_opt
, "disabled", 8))
2143 if (!strncmp(this_opt
, "internal", 8))
2145 if (!strncmp(this_opt
, "external", 8))
2147 if (!strncmp(this_opt
, "nostretch", 9))
2149 if (!strncmp(this_opt
, "nopciburst", 10))
2151 if (!strncmp(this_opt
, "libretto", 8))
2158 static int __initdata initialized
= 0;
2160 int __init
neofb_init(void)
2172 /* never return failure, user can hotplug card later... */
2178 /* *************************** init module code **************************** */
2180 int __init
init_module(void)
2189 /* never return failure; user can hotplug card later... */
2195 module_exit(neo_done
);