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>
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>
34 #include <asm/setup.h>
35 #include <asm/bootinfo.h>
36 #include <asm/uaccess.h>
37 #include <asm/pgtable.h>
39 #include <asm/macintosh.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 {
88 /* Note: word-aligned */
91 } *valkyrie_cmap_regs
;
93 static volatile struct {
96 } *v8_brazil_cmap_regs
;
98 static volatile struct {
100 char pad1
[3]; /* word aligned */
102 char pad2
[3]; /* word aligned */
103 unsigned char cntl
; /* a guess as to purpose */
106 static volatile struct {
108 unsigned long pad1
[3];
109 unsigned char pad2
[3];
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 */
124 static volatile struct {
126 unsigned char clut_waddr
; /* 0x40 */
128 unsigned char clut_data
; /* 0x42 */
130 unsigned char clut_raddr
; /* 0x46 */
133 /* We will leave these the way they are for the time being */
134 struct mdc_cmap_regs
{
141 struct toby_cmap_regs
{
143 unsigned char lut
; /* TFBClutWDataReg, offset 0x90018 */
145 unsigned char addr
; /* TFBClutAddrReg, offset 0x9001C */
148 struct jet_cmap_regs
{
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 */
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 */
180 {0,0,0}, /* transparency */
181 0, /* standard pixel format */
184 FB_ACCEL_NONE
, /* The only way to accelerate a mac is .. */
186 0L,0L,0, /* No sync info */
187 FB_VMODE_NONINTERLACED
,
191 static struct display disp
;
192 static struct fb_info fb_info
;
193 static struct { u_short blue
, green
, red
, pad
; } palette
[256];
195 #ifdef FBCON_HAS_CFB16
198 #ifdef FBCON_HAS_CFB24
201 #ifdef FBCON_HAS_CFB32
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
)
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
;
227 fix
->line_length
=video_linelength
;
231 static int macfb_get_var(struct fb_var_screeninfo
*var
, int con
,
232 struct fb_info
*info
)
235 memcpy(var
, &macfb_defined
, sizeof(struct fb_var_screeninfo
));
237 *var
=fb_display
[con
].var
;
241 static void macfb_set_disp(int con
)
243 struct fb_fix_screeninfo fix
;
244 struct display
*display
;
247 display
= &fb_display
[con
];
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
);
270 display
->dispsw
= &fbcon_mfb
;
273 #ifdef FBCON_HAS_CFB2
275 display
->dispsw
= &fbcon_cfb2
;
278 #ifdef FBCON_HAS_CFB4
280 display
->dispsw
= &fbcon_cfb4
;
283 #ifdef FBCON_HAS_CFB8
285 display
->dispsw
= &fbcon_cfb8
;
288 #ifdef FBCON_HAS_CFB16
291 display
->dispsw
= &fbcon_cfb16
;
292 display
->dispsw_data
= fbcon_cmap
.cfb16
;
295 #ifdef FBCON_HAS_CFB24
297 display
->dispsw
= &fbcon_cfb24
;
298 display
->dispsw_data
= fbcon_cmap
.cfb24
;
301 #ifdef FBCON_HAS_CFB32
303 display
->dispsw
= &fbcon_cfb32
;
304 display
->dispsw_data
= fbcon_cmap
.cfb32
;
308 display
->dispsw
= &fbcon_dummy
;
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
||
323 var
->bits_per_pixel
!= macfb_defined
.bits_per_pixel
||
326 printk("macfb does not support changing the video mode\n");
332 if ((var
->activate
& FB_ACTIVATE_MASK
) == FB_ACTIVATE_TEST
)
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
)
353 /* tell clut which address to fill */
354 writeb(regno
, &valkyrie_cmap_regs
->addr
);
357 /* send one color channel at a time */
358 writeb(red
, &valkyrie_cmap_regs
->lut
);
360 writeb(green
, &valkyrie_cmap_regs
->lut
);
362 writeb(blue
, &valkyrie_cmap_regs
->lut
);
364 restore_flags(flags
);
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
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;
388 /* fbcon will set an entire colourmap, but X won't. Hopefully
389 this should accomodate both of them */
390 if (regno
!= lastreg
+1) {
393 /* Stab in the dark trying to reset the CLUT pointer */
394 writel(0, &dafb_cmap_regs
->reset
);
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
);
401 writeb(palette
[i
].green
>> 8, &dafb_cmap_regs
->lut
);
403 writeb(palette
[i
].blue
>> 8, &dafb_cmap_regs
->lut
);
408 writeb(red
, &dafb_cmap_regs
->lut
);
410 writeb(green
, &dafb_cmap_regs
->lut
);
412 writeb(blue
, &dafb_cmap_regs
->lut
);
414 restore_flags(flags
);
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
;
430 if (video_bpp
>8) return 1; /* failsafe */
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
);
456 static int rbv_setpalette (unsigned int regno
, unsigned int red
,
457 unsigned int green
, unsigned int blue
)
460 unsigned char _red
=red
>>8;
461 unsigned char _green
=green
>>8;
462 unsigned char _blue
=blue
>>8;
463 unsigned char _regno
;
466 if (video_bpp
>8) return 1; /* failsafe */
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
);
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
);
500 unsigned char _red
=red
>>8;
501 unsigned char _green
=green
>>8;
502 unsigned char _blue
=blue
>>8;
503 unsigned char _regno
=regno
;
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
);
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
);
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
);
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
);
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
);
551 unsigned char _red
= (red
>>8);
552 unsigned char _green
= (green
>>8);
553 unsigned char _blue
= (blue
>>8);
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
);
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
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;
586 if (video_bpp
> 8) return 1; /* failsafe */
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
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? */
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)
628 if ((clut_status
& 0x000D) != 0)
630 writeb(0x00, &civic_cmap_regs
->lut
); nop();
631 writeb(0x00, &civic_cmap_regs
->lut
); nop();
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();
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
);
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
)
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
;
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
)
698 *red
= palette
[regno
].red
;
699 *green
= palette
[regno
].green
;
700 *blue
= palette
[regno
].blue
;
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
)
719 palette
[regno
].red
= red
;
720 palette
[regno
].green
= green
;
721 palette
[regno
].blue
= blue
;
726 /* We shouldn't get here */
729 #ifdef FBCON_HAS_CFB2
731 if (macfb_setpalette
)
732 macfb_setpalette(regno
, red
, green
, blue
);
737 #ifdef FBCON_HAS_CFB4
739 if (macfb_setpalette
)
740 macfb_setpalette(regno
, red
, green
, blue
);
745 #ifdef FBCON_HAS_CFB8
747 if (macfb_setpalette
)
748 macfb_setpalette(regno
, red
, green
, blue
);
753 #ifdef FBCON_HAS_CFB16
757 fbcon_cmap
.cfb16
[regno
] =
758 ((red
& 0xf800) >> 1) |
759 ((green
& 0xf800) >> 6) |
760 ((blue
& 0xf800) >> 11) |
761 ((transp
!= 0) << 15);
764 /* I'm pretty sure that one or the other of these
765 doesn't exist on 68k Macs */
766 #ifdef FBCON_HAS_CFB24
771 fbcon_cmap
.cfb24
[regno
] =
772 (red
<< macfb_defined
.red
.offset
) |
773 (green
<< macfb_defined
.green
.offset
) |
774 (blue
<< macfb_defined
.blue
.offset
);
777 #ifdef FBCON_HAS_CFB32
782 fbcon_cmap
.cfb32
[regno
] =
783 (red
<< macfb_defined
.red
.offset
) |
784 (green
<< macfb_defined
.green
.offset
) |
785 (blue
<< macfb_defined
.blue
.offset
);
792 static void do_install_cmap(int con
, struct fb_info
*info
)
796 if (fb_display
[con
].cmap
.len
)
797 fb_set_cmap(&fb_display
[con
].cmap
, 1, macfb_setcolreg
, info
);
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);
811 fb_copy_cmap(fb_default_cmap(video_cmap_len
),
816 static int macfb_set_cmap(struct fb_cmap
*cmap
, int kspc
, int con
,
817 struct fb_info
*info
)
821 if (!fb_display
[con
].cmap
.len
) { /* no colormap allocated? */
822 err
= fb_alloc_cmap(&fb_display
[con
].cmap
,video_cmap_len
,0);
826 if (con
== currcon
) /* current console? */
827 return fb_set_cmap(cmap
, kspc
, macfb_setcolreg
, info
);
829 fb_copy_cmap(cmap
, &fb_display
[con
].cmap
, kspc
? 0 : 1);
833 static struct fb_ops macfb_ops
= {
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 macfb_setup(char *options
, int *ints
)
846 fb_info
.fontname
[0] = '\0';
848 if (!options
|| !*options
)
851 for(this_opt
=strtok(options
,","); this_opt
; this_opt
=strtok(NULL
,",")) {
852 if (!*this_opt
) continue;
854 if (! strcmp(this_opt
, "inverse"))
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"))
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
,
872 /* Install new colormap */
873 do_install_cmap(con
, info
);
874 macfb_update_var(con
, info
);
878 static void macfb_blank(int blank
, struct fb_info
*info
)
883 void __init
macfb_init(void)
885 struct nubus_dev
* ndev
= NULL
;
886 int video_is_nubus
= 0;
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
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;
938 /* XXX: I think this will catch any program that tries
939 to do FBIO_PUTCMAP when the visual is monochrome */
941 video_visual
= FB_VISUAL_MONO01
;
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
;
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");
964 /* Should actually be FB_VISUAL_DIRECTCOLOR, but this
966 video_visual
= FB_VISUAL_TRUECOLOR
;
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");
981 video_visual
= FB_VISUAL_TRUECOLOR
;
984 video_visual
= FB_VISUAL_MONO01
;
985 printk("macfb: unknown or unsupported bit depth: %d\n", video_bpp
);
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
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
))
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))))
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
;
1015 case NUBUS_DRHW_APPLE_TFB
:
1016 strcpy( fb_info
.modename
, "Toby" );
1017 macfb_setpalette
= toby_setpalette
;
1018 macfb_defined
.activate
= FB_ACTIVATE_NOW
;
1020 case NUBUS_DRHW_APPLE_JET
:
1021 strcpy(fb_info
.modename
, "Jet");
1022 macfb_setpalette
= jet_setpalette
;
1023 macfb_defined
.activate
= FB_ACTIVATE_NOW
;
1026 strcpy( fb_info
.modename
, "Generic NuBus" );
1031 /* If it's not a NuBus card, it must be internal video */
1032 /* FIXME: this function is getting way too big. (this driver
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) */
1042 case MAC_MODEL_IICX
:
1043 case MAC_MODEL_IIFX
:
1044 strcpy( fb_info
.modename
, "Generic NuBus" );
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);
1058 /* Note: these first four have the v7 DAFB, which is
1059 known to be rather unlike the ones used in the
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);
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);
1088 /* IIvi, IIvx use the "Brazil" framebuffer (which is
1089 very much like the V8, it seems, and probably uses
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);
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
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);
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);
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);
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
1141 http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
1143 /* Assorted weirdos */
1144 /* We think this may be like the LC II */
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" );
1154 /* We think this may be like the LC II */
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" );
1165 /* And we *do* mean "weirdos" */
1167 strcpy( fb_info
.modename
, "Mac TV built-in" );
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" );
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" );
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" );
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" );
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);
1219 strcpy( fb_info
.modename
, "Unknown/Unsupported built-in" );
1223 fb_info
.changevar
= NULL
;
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
;
1232 do_install_cmap(0, &fb_info
);
1234 if (register_framebuffer(&fb_info
) < 0)
1237 printk("fb%d: %s frame buffer device\n",
1238 GET_FB_IDX(fb_info
.node
), fb_info
.modename
);