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