Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / drivers / video / macfb.c
blob78538935a9b94d0adb3166b27279d41e7712beb4
1 /* macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
2 don't know how to set */
4 /* (c) 1999 David Huggins-Daines <dhd@debian.org>
6 Primarily based on vesafb.c, by Gerd Knorr
7 (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
9 Also uses information and code from:
11 The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
12 Mellinger, Mikael Forselius, Michael Schmitz, and others.
14 valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
15 Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
17 This code is free software. You may copy, modify, and distribute
18 it subject to the terms and conditions of the GNU General Public
19 License, version 2, or any later version, at your convenience. */
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
26 #include <linux/mm.h>
27 #include <linux/tty.h>
28 #include <linux/malloc.h>
29 #include <linux/delay.h>
30 #include <linux/nubus.h>
31 #include <linux/init.h>
32 #include <linux/fb.h>
34 #include <asm/setup.h>
35 #include <asm/bootinfo.h>
36 #include <asm/uaccess.h>
37 #include <asm/pgtable.h>
38 #include <asm/irq.h>
39 #include <asm/macintosh.h>
40 #include <asm/io.h>
41 #include <asm/machw.h>
43 #include <video/fbcon.h>
44 #include <video/fbcon-mfb.h>
45 #include <video/fbcon-cfb2.h>
46 #include <video/fbcon-cfb4.h>
47 #include <video/fbcon-cfb8.h>
48 #include <video/fbcon-cfb16.h>
49 #include <video/fbcon-cfb24.h>
50 #include <video/fbcon-cfb32.h>
52 #if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_CFB2)
54 /* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
55 #define DAC_BASE 0x50f24000
57 /* Some addresses for the DAFB */
58 #define DAFB_BASE 0xf9800200
60 /* Address for the built-in Civic framebuffer in Quadra AVs */
61 #define CIVIC_BASE 0x50f30800 /* Only tested on 660AV! */
63 /* GSC (Gray Scale Controller) base address */
64 #define GSC_BASE 0x50F20000
66 /* CSC (Color Screen Controller) base address */
67 #define CSC_BASE 0x50F20000
69 static int (*macfb_setpalette) (unsigned int regno, unsigned int red,
70 unsigned int green, unsigned int blue) = NULL;
71 static int valkyrie_setpalette (unsigned int regno, unsigned int red,
72 unsigned int green, unsigned int blue);
73 static int dafb_setpalette (unsigned int regno, unsigned int red,
74 unsigned int green, unsigned int blue);
75 static int rbv_setpalette (unsigned int regno, unsigned int red,
76 unsigned int green, unsigned int blue);
77 static int mdc_setpalette (unsigned int regno, unsigned int red,
78 unsigned int green, unsigned int blue);
79 static int toby_setpalette (unsigned int regno, unsigned int red,
80 unsigned int green, unsigned int blue);
81 static int civic_setpalette (unsigned int regno, unsigned int red,
82 unsigned int green, unsigned int blue);
83 static int csc_setpalette (unsigned int regno, unsigned int red,
84 unsigned int green, unsigned int blue);
86 static volatile struct {
87 unsigned char addr;
88 /* Note: word-aligned */
89 char pad[3];
90 unsigned char lut;
91 } *valkyrie_cmap_regs;
93 static volatile struct {
94 unsigned char addr;
95 unsigned char lut;
96 } *v8_brazil_cmap_regs;
98 static volatile struct {
99 unsigned char addr;
100 char pad1[3]; /* word aligned */
101 unsigned char lut;
102 char pad2[3]; /* word aligned */
103 unsigned char cntl; /* a guess as to purpose */
104 } *rbv_cmap_regs;
106 static volatile struct {
107 unsigned long reset;
108 unsigned long pad1[3];
109 unsigned char pad2[3];
110 unsigned char lut;
111 } *dafb_cmap_regs;
113 static volatile struct {
114 unsigned char addr; /* OFFSET: 0x00 */
115 unsigned char pad1[15];
116 unsigned char lut; /* OFFSET: 0x10 */
117 unsigned char pad2[15];
118 unsigned char status; /* OFFSET: 0x20 */
119 unsigned char pad3[7];
120 unsigned long vbl_addr; /* OFFSET: 0x28 */
121 unsigned int status2; /* OFFSET: 0x2C */
122 } *civic_cmap_regs;
124 static volatile struct {
125 char pad1[0x40];
126 unsigned char clut_waddr; /* 0x40 */
127 char pad2;
128 unsigned char clut_data; /* 0x42 */
129 char pad3[0x3];
130 unsigned char clut_raddr; /* 0x46 */
131 } *csc_cmap_regs;
133 /* We will leave these the way they are for the time being */
134 struct mdc_cmap_regs {
135 char pad1[0x200200];
136 unsigned char addr;
137 char pad2[6];
138 unsigned char lut;
141 struct toby_cmap_regs {
142 char pad1[0x90018];
143 unsigned char lut; /* TFBClutWDataReg, offset 0x90018 */
144 char pad2[3];
145 unsigned char addr; /* TFBClutAddrReg, offset 0x9001C */
148 struct jet_cmap_regs {
149 char pad1[0xe0e000];
150 unsigned char addr;
151 unsigned char lut;
154 #endif
156 #define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */
158 static char* video_base;
159 static int video_size;
160 static char* video_vbase; /* mapped */
162 /* mode */
163 static int video_bpp;
164 static int video_width;
165 static int video_height;
166 static int video_type = FB_TYPE_PACKED_PIXELS;
167 static int video_visual;
168 static int video_linelength;
169 static int video_cmap_len;
170 static int video_slot = 0;
172 static struct fb_var_screeninfo macfb_defined={
173 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/
174 0,0, /* virtual -> visible no offset */
175 8, /* depth -> load bits_per_pixel */
176 0, /* greyscale ? */
177 {0,0,0}, /* R */
178 {0,0,0}, /* G */
179 {0,0,0}, /* B */
180 {0,0,0}, /* transparency */
181 0, /* standard pixel format */
182 FB_ACTIVATE_NOW,
183 -1, -1,
184 FB_ACCEL_NONE, /* The only way to accelerate a mac is .. */
185 0L,0L,0L,0L,0L,
186 0L,0L,0, /* No sync info */
187 FB_VMODE_NONINTERLACED,
188 {0,0,0,0,0,0}
191 static struct display disp;
192 static struct fb_info fb_info;
193 static struct { u_short blue, green, red, pad; } palette[256];
194 static union {
195 #ifdef FBCON_HAS_CFB16
196 u16 cfb16[16];
197 #endif
198 #ifdef FBCON_HAS_CFB24
199 u32 cfb24[16];
200 #endif
201 #ifdef FBCON_HAS_CFB32
202 u32 cfb32[16];
203 #endif
204 } fbcon_cmap;
206 static int inverse = 0;
207 static int vidtest = 0;
208 static int currcon = 0;
210 static int macfb_update_var(int con, struct fb_info *info)
212 return 0;
215 static int macfb_get_fix(struct fb_fix_screeninfo *fix, int con,
216 struct fb_info *info)
218 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
219 strcpy(fix->id, "Mac Generic");
221 fix->smem_start = video_base;
222 fix->smem_len = video_size;
223 fix->type = video_type;
224 fix->visual = video_visual;
225 fix->xpanstep = 0;
226 fix->ypanstep = 0;
227 fix->line_length=video_linelength;
228 return 0;
231 static int macfb_get_var(struct fb_var_screeninfo *var, int con,
232 struct fb_info *info)
234 if(con==-1)
235 memcpy(var, &macfb_defined, sizeof(struct fb_var_screeninfo));
236 else
237 *var=fb_display[con].var;
238 return 0;
241 static void macfb_set_disp(int con)
243 struct fb_fix_screeninfo fix;
244 struct display *display;
246 if (con >= 0)
247 display = &fb_display[con];
248 else
249 display = &disp; /* used during initialization */
251 macfb_get_fix(&fix, con, &fb_info);
253 memset(display, 0, sizeof(struct display));
254 display->screen_base = video_vbase;
255 display->visual = fix.visual;
256 display->type = fix.type;
257 display->type_aux = fix.type_aux;
258 display->ypanstep = fix.ypanstep;
259 display->ywrapstep = fix.ywrapstep;
260 display->line_length = fix.line_length;
261 display->next_line = fix.line_length;
262 display->can_soft_blank = 0;
263 display->inverse = inverse;
264 display->scrollmode = SCROLL_YREDRAW;
265 macfb_get_var(&display->var, -1, &fb_info);
267 switch (video_bpp) {
268 #ifdef FBCON_HAS_MFB
269 case 1:
270 display->dispsw = &fbcon_mfb;
271 break;
272 #endif
273 #ifdef FBCON_HAS_CFB2
274 case 2:
275 display->dispsw = &fbcon_cfb2;
276 break;
277 #endif
278 #ifdef FBCON_HAS_CFB4
279 case 4:
280 display->dispsw = &fbcon_cfb4;
281 break;
282 #endif
283 #ifdef FBCON_HAS_CFB8
284 case 8:
285 display->dispsw = &fbcon_cfb8;
286 break;
287 #endif
288 #ifdef FBCON_HAS_CFB16
289 case 15:
290 case 16:
291 display->dispsw = &fbcon_cfb16;
292 display->dispsw_data = fbcon_cmap.cfb16;
293 break;
294 #endif
295 #ifdef FBCON_HAS_CFB24
296 case 24:
297 display->dispsw = &fbcon_cfb24;
298 display->dispsw_data = fbcon_cmap.cfb24;
299 break;
300 #endif
301 #ifdef FBCON_HAS_CFB32
302 case 32:
303 display->dispsw = &fbcon_cfb32;
304 display->dispsw_data = fbcon_cmap.cfb32;
305 break;
306 #endif
307 default:
308 display->dispsw = &fbcon_dummy;
309 return;
313 static int macfb_set_var(struct fb_var_screeninfo *var, int con,
314 struct fb_info *info)
316 static int first = 1;
318 if (var->xres != macfb_defined.xres ||
319 var->yres != macfb_defined.yres ||
320 var->xres_virtual != macfb_defined.xres_virtual ||
321 var->yres_virtual != macfb_defined.yres ||
322 var->xoffset ||
323 var->bits_per_pixel != macfb_defined.bits_per_pixel ||
324 var->nonstd) {
325 if (first) {
326 printk("macfb does not support changing the video mode\n");
327 first = 0;
329 return -EINVAL;
332 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
333 return 0;
335 if (var->yoffset)
336 return -EINVAL;
337 return 0;
340 #if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_CFB2)
341 static int valkyrie_setpalette (unsigned int regno, unsigned int red,
342 unsigned int green, unsigned int blue)
344 unsigned long flags;
346 red >>= 8;
347 green >>= 8;
348 blue >>= 8;
350 save_flags(flags);
351 cli();
353 /* tell clut which address to fill */
354 writeb(regno, &valkyrie_cmap_regs->addr);
355 nop();
357 /* send one color channel at a time */
358 writeb(red, &valkyrie_cmap_regs->lut);
359 nop();
360 writeb(green, &valkyrie_cmap_regs->lut);
361 nop();
362 writeb(blue, &valkyrie_cmap_regs->lut);
364 restore_flags(flags);
366 return 0;
369 /* Unlike the Valkyrie, the DAFB cannot set individual colormap
370 registers. Therefore, we do what the MacOS driver does (no
371 kidding!) and simply set them one by one until we hit the one we
372 want. */
373 static int dafb_setpalette (unsigned int regno, unsigned int red,
374 unsigned int green, unsigned int blue)
376 /* FIXME: really, really need to use ioremap() here,
377 phys_to_virt() doesn't work anymore */
378 static int lastreg = -1;
379 unsigned long flags;
381 red >>= 8;
382 green >>= 8;
383 blue >>= 8;
385 save_flags(flags);
386 cli();
388 /* fbcon will set an entire colourmap, but X won't. Hopefully
389 this should accomodate both of them */
390 if (regno != lastreg+1) {
391 int i;
393 /* Stab in the dark trying to reset the CLUT pointer */
394 writel(0, &dafb_cmap_regs->reset);
395 nop();
397 /* Loop until we get to the register we want */
398 for (i = 0; i < regno; i++) {
399 writeb(palette[i].red >> 8, &dafb_cmap_regs->lut);
400 nop();
401 writeb(palette[i].green >> 8, &dafb_cmap_regs->lut);
402 nop();
403 writeb(palette[i].blue >> 8, &dafb_cmap_regs->lut);
404 nop();
408 writeb(red, &dafb_cmap_regs->lut);
409 nop();
410 writeb(green, &dafb_cmap_regs->lut);
411 nop();
412 writeb(blue, &dafb_cmap_regs->lut);
414 restore_flags(flags);
416 lastreg = regno;
417 return 0;
420 /* V8 and Brazil seem to use the same DAC. Sonora does as well. */
421 static int v8_brazil_setpalette (unsigned int regno, unsigned int red,
422 unsigned int green, unsigned int blue)
424 unsigned char _red =red>>8;
425 unsigned char _green=green>>8;
426 unsigned char _blue =blue>>8;
427 unsigned char _regno;
428 unsigned long flags;
430 if (video_bpp>8) return 1; /* failsafe */
432 save_flags(flags);
433 cli();
435 /* On these chips, the CLUT register numbers are spread out
436 across the register space. Thus:
438 In 8bpp, all regnos are valid.
440 In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
442 In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff */
443 _regno = (regno<<(8-video_bpp)) | (0xFF>>video_bpp);
444 writeb(_regno, &v8_brazil_cmap_regs->addr); nop();
446 /* send one color channel at a time */
447 writeb(_red, &v8_brazil_cmap_regs->lut); nop();
448 writeb(_green, &v8_brazil_cmap_regs->lut); nop();
449 writeb(_blue, &v8_brazil_cmap_regs->lut);
451 restore_flags(flags);
453 return 0;
456 static int rbv_setpalette (unsigned int regno, unsigned int red,
457 unsigned int green, unsigned int blue)
459 /* use MSBs */
460 unsigned char _red =red>>8;
461 unsigned char _green=green>>8;
462 unsigned char _blue =blue>>8;
463 unsigned char _regno;
464 unsigned long flags;
466 if (video_bpp>8) return 1; /* failsafe */
468 save_flags(flags);
469 cli();
471 /* From the VideoToolbox driver. Seems to be saying that
472 * regno #254 and #255 are the important ones for 1-bit color,
473 * regno #252-255 are the important ones for 2-bit color, etc.
475 _regno = regno + (256-(1<<video_bpp));
477 /* reset clut? (VideoToolbox sez "not necessary") */
478 writeb(0xFF, &rbv_cmap_regs->cntl); nop();
480 /* tell clut which address to use. */
481 writeb(_regno, &rbv_cmap_regs->addr); nop();
483 /* send one color channel at a time. */
484 writeb(_red, &rbv_cmap_regs->lut); nop();
485 writeb(_green, &rbv_cmap_regs->lut); nop();
486 writeb(_blue, &rbv_cmap_regs->lut);
488 restore_flags(flags);
489 /* done. */
490 return 0;
493 /* Macintosh Display Card (8x24) */
494 static int mdc_setpalette(unsigned int regno, unsigned int red,
495 unsigned int green, unsigned int blue)
497 volatile struct mdc_cmap_regs *cmap_regs =
498 nubus_slot_addr(video_slot);
499 /* use MSBs */
500 unsigned char _red =red>>8;
501 unsigned char _green=green>>8;
502 unsigned char _blue =blue>>8;
503 unsigned char _regno=regno;
504 unsigned long flags;
506 save_flags(flags);
507 cli();
509 /* the nop's are there to order writes. */
510 writeb(_regno, &cmap_regs->addr); nop();
511 writeb(_red, &cmap_regs->lut); nop();
512 writeb(_green, &cmap_regs->lut); nop();
513 writeb(_blue, &cmap_regs->lut);
515 restore_flags(flags);
516 return 0;
519 /* Toby frame buffer */
520 static int toby_setpalette(unsigned int regno, unsigned int red,
521 unsigned int green, unsigned int blue)
523 volatile struct toby_cmap_regs *cmap_regs =
524 nubus_slot_addr(video_slot);
525 /* use MSBs */
526 unsigned char _red =~(red>>8);
527 unsigned char _green=~(green>>8);
528 unsigned char _blue =~(blue>>8);
529 unsigned char _regno = (regno<<(8-video_bpp)) | (0xFF>>video_bpp);
530 unsigned long flags;
532 save_flags(flags);
533 cli();
535 writeb(_regno, &cmap_regs->addr); nop();
536 writeb(_red, &cmap_regs->lut); nop();
537 writeb(_green, &cmap_regs->lut); nop();
538 writeb(_blue, &cmap_regs->lut);
540 restore_flags(flags);
541 return 0;
544 /* Jet frame buffer */
545 static int jet_setpalette(unsigned int regno, unsigned int red,
546 unsigned int green, unsigned int blue)
548 volatile struct jet_cmap_regs *cmap_regs =
549 nubus_slot_addr(video_slot);
550 /* use MSBs */
551 unsigned char _red = (red>>8);
552 unsigned char _green = (green>>8);
553 unsigned char _blue = (blue>>8);
554 unsigned long flags;
556 save_flags(flags);
557 cli();
559 writeb(regno, &cmap_regs->addr); nop();
560 writeb(_red, &cmap_regs->lut); nop();
561 writeb(_green, &cmap_regs->lut); nop();
562 writeb(_blue, &cmap_regs->lut);
564 restore_flags(flags);
565 return 0;
569 * Civic framebuffer -- Quadra AV built-in video. A chip
570 * called Sebastian holds the actual color palettes, and
571 * apparently, there are two different banks of 512K RAM
572 * which can act as separate framebuffers for doing video
573 * input and viewing the screen at the same time! The 840AV
574 * Can add another 1MB RAM to give the two framebuffers
575 * 1MB RAM apiece.
577 * FIXME: this doesn't seem to work anymore.
579 static int civic_setpalette (unsigned int regno, unsigned int red,
580 unsigned int green, unsigned int blue)
582 static int lastreg = -1;
583 unsigned long flags;
584 int clut_status;
586 if (video_bpp > 8) return 1; /* failsafe */
588 red >>= 8;
589 green >>= 8;
590 blue >>= 8;
592 save_flags(flags);
593 cli();
596 * Set the register address
598 writeb(regno, &civic_cmap_regs->addr); nop();
601 * Wait for VBL interrupt here;
602 * They're usually not enabled from Penguin, so we won't check
604 #if 0
606 #define CIVIC_VBL_OFFSET 0x120
607 volatile unsigned long *vbl = readl(civic_cmap_regs->vbl_addr + CIVIC_VBL_OFFSET);
608 /* do interrupt setup stuff here? */
609 *vbl = 0L; nop(); /* clear */
610 *vbl = 1L; nop(); /* set */
611 while (*vbl != 0L) /* wait for next vbl */
613 usleep(10); /* needed? */
615 /* do interrupt shutdown stuff here? */
617 #endif
620 * Grab a status word and do some checking;
621 * Then finally write the clut!
623 clut_status = readb(&civic_cmap_regs->status2);
625 if ((clut_status & 0x0008) == 0)
627 #if 0
628 if ((clut_status & 0x000D) != 0)
630 writeb(0x00, &civic_cmap_regs->lut); nop();
631 writeb(0x00, &civic_cmap_regs->lut); nop();
633 #endif
635 writeb( red, &civic_cmap_regs->lut); nop();
636 writeb(green, &civic_cmap_regs->lut); nop();
637 writeb( blue, &civic_cmap_regs->lut); nop();
638 writeb( 0x00, &civic_cmap_regs->lut); nop();
640 else
642 unsigned char junk;
644 junk = readb(&civic_cmap_regs->lut); nop();
645 junk = readb(&civic_cmap_regs->lut); nop();
646 junk = readb(&civic_cmap_regs->lut); nop();
647 junk = readb(&civic_cmap_regs->lut); nop();
649 if ((clut_status & 0x000D) != 0)
651 writeb(0x00, &civic_cmap_regs->lut); nop();
652 writeb(0x00, &civic_cmap_regs->lut); nop();
655 writeb( red, &civic_cmap_regs->lut); nop();
656 writeb(green, &civic_cmap_regs->lut); nop();
657 writeb( blue, &civic_cmap_regs->lut); nop();
658 writeb( junk, &civic_cmap_regs->lut); nop();
661 restore_flags(flags);
663 lastreg = regno;
664 return 0;
668 * The CSC is the framebuffer on the PowerBook 190 series
669 * (and the 5300 too, but that's a PowerMac). This function
670 * brought to you in part by the ECSC driver for MkLinux.
673 static int csc_setpalette (unsigned int regno, unsigned int red,
674 unsigned int green, unsigned int blue)
676 mdelay(1);
677 csc_cmap_regs->clut_waddr = regno;
678 csc_cmap_regs->clut_data = red;
679 csc_cmap_regs->clut_data = green;
680 csc_cmap_regs->clut_data = blue;
681 return 0;
684 #endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB4 || FBCON_HAS_CFB2 */
686 static int macfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
687 unsigned *blue, unsigned *transp,
688 struct fb_info *fb_info)
691 * Read a single color register and split it into colors/transparent.
692 * Return != 0 for invalid regno.
695 if (regno >= video_cmap_len)
696 return 1;
698 *red = palette[regno].red;
699 *green = palette[regno].green;
700 *blue = palette[regno].blue;
701 *transp = 0;
702 return 0;
705 static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
706 unsigned blue, unsigned transp,
707 struct fb_info *fb_info)
710 * Set a single color register. The values supplied are
711 * already rounded down to the hardware's capabilities
712 * (according to the entries in the `var' structure). Return
713 * != 0 for invalid regno.
716 if (regno >= video_cmap_len)
717 return 1;
719 palette[regno].red = red;
720 palette[regno].green = green;
721 palette[regno].blue = blue;
723 switch (video_bpp) {
724 #ifdef FBCON_HAS_MFB
725 case 1:
726 /* We shouldn't get here */
727 break;
728 #endif
729 #ifdef FBCON_HAS_CFB2
730 case 2:
731 if (macfb_setpalette)
732 macfb_setpalette(regno, red, green, blue);
733 else
734 return 1;
735 break;
736 #endif
737 #ifdef FBCON_HAS_CFB4
738 case 4:
739 if (macfb_setpalette)
740 macfb_setpalette(regno, red, green, blue);
741 else
742 return 1;
743 break;
744 #endif
745 #ifdef FBCON_HAS_CFB8
746 case 8:
747 if (macfb_setpalette)
748 macfb_setpalette(regno, red, green, blue);
749 else
750 return 1;
751 break;
752 #endif
753 #ifdef FBCON_HAS_CFB16
754 case 15:
755 case 16:
756 /* 1:5:5:5 */
757 fbcon_cmap.cfb16[regno] =
758 ((red & 0xf800) >> 1) |
759 ((green & 0xf800) >> 6) |
760 ((blue & 0xf800) >> 11) |
761 ((transp != 0) << 15);
762 break;
763 #endif
764 /* I'm pretty sure that one or the other of these
765 doesn't exist on 68k Macs */
766 #ifdef FBCON_HAS_CFB24
767 case 24:
768 red >>= 8;
769 green >>= 8;
770 blue >>= 8;
771 fbcon_cmap.cfb24[regno] =
772 (red << macfb_defined.red.offset) |
773 (green << macfb_defined.green.offset) |
774 (blue << macfb_defined.blue.offset);
775 break;
776 #endif
777 #ifdef FBCON_HAS_CFB32
778 case 32:
779 red >>= 8;
780 green >>= 8;
781 blue >>= 8;
782 fbcon_cmap.cfb32[regno] =
783 (red << macfb_defined.red.offset) |
784 (green << macfb_defined.green.offset) |
785 (blue << macfb_defined.blue.offset);
786 break;
787 #endif
789 return 0;
792 static void do_install_cmap(int con, struct fb_info *info)
794 if (con != currcon)
795 return;
796 if (fb_display[con].cmap.len)
797 fb_set_cmap(&fb_display[con].cmap, 1, macfb_setcolreg, info);
798 else
799 fb_set_cmap(fb_default_cmap(video_cmap_len), 1,
800 macfb_setcolreg, info);
803 static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
804 struct fb_info *info)
806 if (con == currcon) /* current console? */
807 return fb_get_cmap(cmap, kspc, macfb_getcolreg, info);
808 else if (fb_display[con].cmap.len) /* non default colormap? */
809 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
810 else
811 fb_copy_cmap(fb_default_cmap(video_cmap_len),
812 cmap, kspc ? 0 : 2);
813 return 0;
816 static int macfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
817 struct fb_info *info)
819 int err;
821 if (!fb_display[con].cmap.len) { /* no colormap allocated? */
822 err = fb_alloc_cmap(&fb_display[con].cmap,video_cmap_len,0);
823 if (err)
824 return err;
826 if (con == currcon) /* current console? */
827 return fb_set_cmap(cmap, kspc, macfb_setcolreg, info);
828 else
829 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
830 return 0;
833 static struct fb_ops macfb_ops = {
834 owner: THIS_MODULE,
835 fb_get_fix: macfb_get_fix,
836 fb_get_var: macfb_get_var,
837 fb_set_var: macfb_set_var,
838 fb_get_cmap: macfb_get_cmap,
839 fb_set_cmap: macfb_set_cmap,
842 void __init macfb_setup(char *options, int *ints)
844 char *this_opt;
846 fb_info.fontname[0] = '\0';
848 if (!options || !*options)
849 return;
851 for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
852 if (!*this_opt) continue;
854 if (! strcmp(this_opt, "inverse"))
855 inverse=1;
856 else if (!strncmp(this_opt, "font:", 5))
857 strcpy(fb_info.fontname, this_opt+5);
858 /* This means "turn on experimental CLUT code" */
859 else if (!strcmp(this_opt, "vidtest"))
860 vidtest=1;
864 static int macfb_switch(int con, struct fb_info *info)
866 /* Do we have to save the colormap? */
867 if (fb_display[currcon].cmap.len)
868 fb_get_cmap(&fb_display[currcon].cmap, 1, macfb_getcolreg,
869 info);
871 currcon = con;
872 /* Install new colormap */
873 do_install_cmap(con, info);
874 macfb_update_var(con, info);
875 return 1;
878 static void macfb_blank(int blank, struct fb_info *info)
880 /* Not supported */
883 void __init macfb_init(void)
885 struct nubus_dev* ndev = NULL;
886 int video_is_nubus = 0;
888 if (!MACH_IS_MAC)
889 return;
891 /* There can only be one internal video controller anyway so
892 we're not too worried about this */
893 video_width = mac_bi_data.dimensions & 0xFFFF;
894 video_height = mac_bi_data.dimensions >> 16;
895 video_bpp = mac_bi_data.videodepth;
896 video_linelength = mac_bi_data.videorow;
897 video_size = video_linelength * video_height;
898 /* Note: physical address (since 2.1.127) */
899 video_base = (void*) mac_bi_data.videoaddr;
900 /* This is actually redundant with the initial mappings.
901 However, there are some non-obvious aspects to the way
902 those mappings are set up, so this is in fact the safest
903 way to ensure that this driver will work on every possible
904 Mac */
905 video_vbase = ioremap(mac_bi_data.videoaddr, video_size);
907 printk("macfb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
908 video_base, video_vbase, video_size/1024);
909 printk("macfb: mode is %dx%dx%d, linelength=%d\n",
910 video_width, video_height, video_bpp, video_linelength);
913 * Fill in the available video resolution
916 macfb_defined.xres = video_width;
917 macfb_defined.yres = video_height;
918 macfb_defined.xres_virtual = video_width;
919 macfb_defined.yres_virtual = video_height;
920 macfb_defined.bits_per_pixel = video_bpp;
921 macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
922 macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
924 printk("macfb: scrolling: redraw\n");
925 macfb_defined.yres_virtual = video_height;
927 /* some dummy values for timing to make fbset happy */
928 macfb_defined.pixclock = 10000000 / video_width * 1000 / video_height;
929 macfb_defined.left_margin = (video_width / 8) & 0xf8;
930 macfb_defined.right_margin = 32;
931 macfb_defined.upper_margin = 16;
932 macfb_defined.lower_margin = 4;
933 macfb_defined.hsync_len = (video_width / 8) & 0xf8;
934 macfb_defined.vsync_len = 4;
936 switch (video_bpp) {
937 case 1:
938 /* XXX: I think this will catch any program that tries
939 to do FBIO_PUTCMAP when the visual is monochrome */
940 video_cmap_len = 0;
941 video_visual = FB_VISUAL_MONO01;
942 break;
943 case 2:
944 case 4:
945 case 8:
946 macfb_defined.red.length = video_bpp;
947 macfb_defined.green.length = video_bpp;
948 macfb_defined.blue.length = video_bpp;
949 video_cmap_len = 1 << video_bpp;
950 video_visual = FB_VISUAL_PSEUDOCOLOR;
951 break;
952 case 16:
953 macfb_defined.transp.offset = 15;
954 macfb_defined.transp.length = 1;
955 macfb_defined.red.offset = 10;
956 macfb_defined.red.length = 5;
957 macfb_defined.green.offset = 5;
958 macfb_defined.green.length = 5;
959 macfb_defined.blue.offset = 0;
960 macfb_defined.blue.length = 5;
961 printk("macfb: directcolor: "
962 "size=1:5:5:5, shift=15:10:5:0\n");
963 video_cmap_len = 16;
964 /* Should actually be FB_VISUAL_DIRECTCOLOR, but this
965 works too */
966 video_visual = FB_VISUAL_TRUECOLOR;
967 break;
968 case 24:
969 case 32:
970 /* XXX: have to test these... can any 68k Macs
971 actually do this on internal video? */
972 macfb_defined.red.offset = 16;
973 macfb_defined.red.length = 8;
974 macfb_defined.green.offset = 8;
975 macfb_defined.green.length = 8;
976 macfb_defined.blue.offset = 0;
977 macfb_defined.blue.length = 8;
978 printk("macfb: truecolor: "
979 "size=0:8:8:8, shift=0:16:8:0\n");
980 video_cmap_len = 16;
981 video_visual = FB_VISUAL_TRUECOLOR;
982 default:
983 video_cmap_len = 0;
984 video_visual = FB_VISUAL_MONO01;
985 printk("macfb: unknown or unsupported bit depth: %d\n", video_bpp);
986 break;
989 /* Hardware dependent stuff */
990 /* We take a wild guess that if the video physical address is
991 * in nubus slot space, that the nubus card is driving video.
992 * Penguin really ought to tell us whether we are using internal
993 * video or not.
995 /* Hopefully we only find one of them. Otherwise our NuBus
996 code is really broken :-) */
998 while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev))
999 != NULL)
1001 if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr
1002 && (mac_bi_data.videoaddr <
1003 (unsigned long)nubus_slot_addr(ndev->board->slot+1))))
1004 continue;
1005 video_is_nubus = 1;
1006 /* We should probably just use the slot address... */
1007 video_slot = ndev->board->slot;
1009 switch(ndev->dr_hw) {
1010 case NUBUS_DRHW_APPLE_MDC:
1011 strcpy( fb_info.modename, "Macintosh Display Card" );
1012 macfb_setpalette = mdc_setpalette;
1013 macfb_defined.activate = FB_ACTIVATE_NOW;
1014 break;
1015 case NUBUS_DRHW_APPLE_TFB:
1016 strcpy( fb_info.modename, "Toby" );
1017 macfb_setpalette = toby_setpalette;
1018 macfb_defined.activate = FB_ACTIVATE_NOW;
1019 break;
1020 case NUBUS_DRHW_APPLE_JET:
1021 strcpy(fb_info.modename, "Jet");
1022 macfb_setpalette = jet_setpalette;
1023 macfb_defined.activate = FB_ACTIVATE_NOW;
1024 break;
1025 default:
1026 strcpy( fb_info.modename, "Generic NuBus" );
1027 break;
1031 /* If it's not a NuBus card, it must be internal video */
1032 /* FIXME: this function is getting way too big. (this driver
1033 is too...) */
1034 if (!video_is_nubus)
1035 switch( mac_bi_data.id )
1037 /* These don't have onboard video. Eventually, we may
1038 be able to write separate framebuffer drivers for
1039 them (tobyfb.c, hiresfb.c, etc, etc) */
1040 case MAC_MODEL_II:
1041 case MAC_MODEL_IIX:
1042 case MAC_MODEL_IICX:
1043 case MAC_MODEL_IIFX:
1044 strcpy( fb_info.modename, "Generic NuBus" );
1045 break;
1047 /* Valkyrie Quadras */
1048 case MAC_MODEL_Q630:
1049 /* I'm not sure about this one */
1050 case MAC_MODEL_P588:
1051 strcpy( fb_info.modename, "Valkyrie built-in" );
1052 macfb_setpalette = valkyrie_setpalette;
1053 macfb_defined.activate = FB_ACTIVATE_NOW;
1054 valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
1055 break;
1057 /* DAFB Quadras */
1058 /* Note: these first four have the v7 DAFB, which is
1059 known to be rather unlike the ones used in the
1060 other models */
1061 case MAC_MODEL_P475:
1062 case MAC_MODEL_P475F:
1063 case MAC_MODEL_P575:
1064 case MAC_MODEL_Q605:
1066 case MAC_MODEL_Q800:
1067 case MAC_MODEL_Q650:
1068 case MAC_MODEL_Q610:
1069 case MAC_MODEL_C650:
1070 case MAC_MODEL_C610:
1071 case MAC_MODEL_Q700:
1072 case MAC_MODEL_Q900:
1073 case MAC_MODEL_Q950:
1074 strcpy( fb_info.modename, "DAFB built-in" );
1075 macfb_setpalette = dafb_setpalette;
1076 macfb_defined.activate = FB_ACTIVATE_NOW;
1077 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
1078 break;
1080 /* LC II uses the V8 framebuffer */
1081 case MAC_MODEL_LCII:
1082 strcpy( fb_info.modename, "V8 built-in" );
1083 macfb_setpalette = v8_brazil_setpalette;
1084 macfb_defined.activate = FB_ACTIVATE_NOW;
1085 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
1086 break;
1088 /* IIvi, IIvx use the "Brazil" framebuffer (which is
1089 very much like the V8, it seems, and probably uses
1090 the same DAC) */
1091 case MAC_MODEL_IIVI:
1092 case MAC_MODEL_IIVX:
1093 case MAC_MODEL_P600:
1094 strcpy( fb_info.modename, "Brazil built-in" );
1095 macfb_setpalette = v8_brazil_setpalette;
1096 macfb_defined.activate = FB_ACTIVATE_NOW;
1097 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
1098 break;
1100 /* LC III (and friends) use the Sonora framebuffer */
1101 /* Incidentally this is also used in the non-AV models
1102 of the x100 PowerMacs */
1103 /* These do in fact seem to use the same DAC interface
1104 as the LC II. */
1105 case MAC_MODEL_LCIII:
1106 case MAC_MODEL_P520:
1107 case MAC_MODEL_P550:
1108 case MAC_MODEL_P460:
1109 macfb_setpalette = v8_brazil_setpalette;
1110 macfb_defined.activate = FB_ACTIVATE_NOW;
1111 strcpy( fb_info.modename, "Sonora built-in" );
1112 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
1113 break;
1115 /* IIci and IIsi use the infamous RBV chip
1116 (the IIsi is just a rebadged and crippled
1117 IIci in a different case, BTW) */
1118 case MAC_MODEL_IICI:
1119 case MAC_MODEL_IISI:
1120 macfb_setpalette = rbv_setpalette;
1121 macfb_defined.activate = FB_ACTIVATE_NOW;
1122 strcpy( fb_info.modename, "RBV built-in" );
1123 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
1124 break;
1126 /* AVs use the Civic framebuffer */
1127 case MAC_MODEL_Q840:
1128 case MAC_MODEL_C660:
1129 macfb_setpalette = civic_setpalette;
1130 macfb_defined.activate = FB_ACTIVATE_NOW;
1131 strcpy( fb_info.modename, "Civic built-in" );
1132 civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
1133 break;
1136 /* Write a setpalette function for your machine, then
1137 you can add something similar here. These are
1138 grouped by classes of video chipsets. Some of this
1139 information is from the VideoToolbox "Bugs" web
1140 page at
1141 http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
1143 /* Assorted weirdos */
1144 /* We think this may be like the LC II */
1145 case MAC_MODEL_LC:
1146 if (vidtest) {
1147 macfb_setpalette = v8_brazil_setpalette;
1148 macfb_defined.activate = FB_ACTIVATE_NOW;
1149 v8_brazil_cmap_regs =
1150 ioremap(DAC_BASE, 0x1000);
1152 strcpy( fb_info.modename, "LC built-in" );
1153 break;
1154 /* We think this may be like the LC II */
1155 case MAC_MODEL_CCL:
1156 if (vidtest) {
1157 macfb_setpalette = v8_brazil_setpalette;
1158 macfb_defined.activate = FB_ACTIVATE_NOW;
1159 v8_brazil_cmap_regs =
1160 ioremap(DAC_BASE, 0x1000);
1162 strcpy( fb_info.modename, "Color Classic built-in" );
1163 break;
1165 /* And we *do* mean "weirdos" */
1166 case MAC_MODEL_TV:
1167 strcpy( fb_info.modename, "Mac TV built-in" );
1168 break;
1170 /* These don't have colour, so no need to worry */
1171 case MAC_MODEL_SE30:
1172 case MAC_MODEL_CLII:
1173 strcpy( fb_info.modename, "Monochrome built-in" );
1174 break;
1176 /* Powerbooks are particularly difficult. Many of
1177 them have separate framebuffers for external and
1178 internal video, which is admittedly pretty cool,
1179 but will be a bit of a headache to support here.
1180 Also, many of them are grayscale, and we don't
1181 really support that. */
1183 case MAC_MODEL_PB140:
1184 case MAC_MODEL_PB145:
1185 case MAC_MODEL_PB170:
1186 strcpy( fb_info.modename, "DDC built-in" );
1187 break;
1189 /* Internal is GSC, External (if present) is ViSC */
1190 case MAC_MODEL_PB150: /* no external video */
1191 case MAC_MODEL_PB160:
1192 case MAC_MODEL_PB165:
1193 case MAC_MODEL_PB180:
1194 case MAC_MODEL_PB210:
1195 case MAC_MODEL_PB230:
1196 strcpy( fb_info.modename, "GSC built-in" );
1197 break;
1199 /* Internal is TIM, External is ViSC */
1200 case MAC_MODEL_PB165C:
1201 case MAC_MODEL_PB180C:
1202 strcpy( fb_info.modename, "TIM built-in" );
1203 break;
1205 /* Internal is CSC, External is Keystone+Ariel. */
1206 case MAC_MODEL_PB190: /* external video is optional */
1207 case MAC_MODEL_PB520:
1208 case MAC_MODEL_PB250:
1209 case MAC_MODEL_PB270C:
1210 case MAC_MODEL_PB280:
1211 case MAC_MODEL_PB280C:
1212 macfb_setpalette = csc_setpalette;
1213 macfb_defined.activate = FB_ACTIVATE_NOW;
1214 strcpy( fb_info.modename, "CSC built-in" );
1215 csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
1216 break;
1218 default:
1219 strcpy( fb_info.modename, "Unknown/Unsupported built-in" );
1220 break;
1223 fb_info.changevar = NULL;
1224 fb_info.node = -1;
1225 fb_info.fbops = &macfb_ops;
1226 fb_info.disp = &disp;
1227 fb_info.switch_con = &macfb_switch;
1228 fb_info.updatevar = &macfb_update_var;
1229 fb_info.blank = &macfb_blank;
1230 fb_info.flags = FBINFO_FLAG_DEFAULT;
1231 macfb_set_disp(-1);
1232 do_install_cmap(0, &fb_info);
1234 if (register_framebuffer(&fb_info) < 0)
1235 return;
1237 printk("fb%d: %s frame buffer device\n",
1238 GET_FB_IDX(fb_info.node), fb_info.modename);