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