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