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