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