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