Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/*
2 * macfb.c: Generic framebuffer for Macs whose colourmaps/modes we
3 * don't know how to set.
4 *
5 * (c) 1999 David Huggins-Daines <dhd@debian.org>
6 *
7 * Primarily based on vesafb.c, by Gerd Knorr
8 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
9 *
10 * Also uses information and code from:
11 *
12 * The original macfb.c from Linux/mac68k 2.0, by Alan Cox, Juergen
13 * Mellinger, Mikael Forselius, Michael Schmitz, and others.
14 *
15 * valkyriefb.c, by Martin Costabel, Kevin Schoedel, Barry Nathan, Dan
16 * Jacobowitz, Paul Mackerras, Fabio Riccardi, and Geert Uytterhoeven.
17 *
18 * The VideoToolbox "Bugs" web page at
19 * http://rajsky.psych.nyu.edu/Tips/VideoBugs.html
20 *
21 * This code is free software. You may copy, modify, and distribute
22 * it subject to the terms and conditions of the GNU General Public
23 * License, version 2, or any later version, at your convenience.
24 */
25
26#include <linux/module.h>
27#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/string.h>
30#include <linux/mm.h>
31#include <linux/delay.h>
32#include <linux/nubus.h>
33#include <linux/init.h>
34#include <linux/fb.h>
35
36#include <asm/setup.h>
37#include <asm/macintosh.h>
38#include <asm/io.h>
39
40/* Common DAC base address for the LC, RBV, Valkyrie, and IIvx */
41#define DAC_BASE 0x50f24000
42
43/* Some addresses for the DAFB */
44#define DAFB_BASE 0xf9800200
45
46/* Address for the built-in Civic framebuffer in Quadra AVs */
47#define CIVIC_BASE 0x50f30800
48
49/* GSC (Gray Scale Controller) base address */
50#define GSC_BASE 0x50F20000
51
52/* CSC (Color Screen Controller) base address */
53#define CSC_BASE 0x50F20000
54
55static int (*macfb_setpalette)(unsigned int regno, unsigned int red,
56 unsigned int green, unsigned int blue,
57 struct fb_info *info);
58
59static struct {
60 unsigned char addr;
61 unsigned char lut;
62} __iomem *v8_brazil_cmap_regs;
63
64static struct {
65 unsigned char addr;
66 char pad1[3]; /* word aligned */
67 unsigned char lut;
68 char pad2[3]; /* word aligned */
69 unsigned char cntl; /* a guess as to purpose */
70} __iomem *rbv_cmap_regs;
71
72static struct {
73 unsigned long reset;
74 unsigned long pad1[3];
75 unsigned char pad2[3];
76 unsigned char lut;
77} __iomem *dafb_cmap_regs;
78
79static struct {
80 unsigned char addr; /* OFFSET: 0x00 */
81 unsigned char pad1[15];
82 unsigned char lut; /* OFFSET: 0x10 */
83 unsigned char pad2[15];
84 unsigned char status; /* OFFSET: 0x20 */
85 unsigned char pad3[7];
86 unsigned long vbl_addr; /* OFFSET: 0x28 */
87 unsigned int status2; /* OFFSET: 0x2C */
88} __iomem *civic_cmap_regs;
89
90static struct {
91 char pad1[0x40];
92 unsigned char clut_waddr; /* 0x40 */
93 char pad2;
94 unsigned char clut_data; /* 0x42 */
95 char pad3[0x3];
96 unsigned char clut_raddr; /* 0x46 */
97} __iomem *csc_cmap_regs;
98
99/* The registers in these structs are in NuBus slot space */
100struct mdc_cmap_regs {
101 char pad1[0x200200];
102 unsigned char addr;
103 char pad2[6];
104 unsigned char lut;
105};
106
107struct toby_cmap_regs {
108 char pad1[0x90018];
109 unsigned char lut; /* TFBClutWDataReg, offset 0x90018 */
110 char pad2[3];
111 unsigned char addr; /* TFBClutAddrReg, offset 0x9001C */
112};
113
114struct jet_cmap_regs {
115 char pad1[0xe0e000];
116 unsigned char addr;
117 unsigned char lut;
118};
119
120#define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */
121
122static struct fb_var_screeninfo macfb_defined = {
123 .activate = FB_ACTIVATE_NOW,
124 .right_margin = 32,
125 .upper_margin = 16,
126 .lower_margin = 4,
127 .vsync_len = 4,
128 .vmode = FB_VMODE_NONINTERLACED,
129};
130
131static struct fb_fix_screeninfo macfb_fix = {
132 .type = FB_TYPE_PACKED_PIXELS,
133 .accel = FB_ACCEL_NONE,
134};
135
136static void *slot_addr;
137static struct fb_info fb_info;
138static u32 pseudo_palette[16];
139static int vidtest;
140
141/*
142 * Unlike the Valkyrie, the DAFB cannot set individual colormap
143 * registers. Therefore, we do what the MacOS driver does (no
144 * kidding!) and simply set them one by one until we hit the one we
145 * want.
146 */
147static int dafb_setpalette(unsigned int regno, unsigned int red,
148 unsigned int green, unsigned int blue,
149 struct fb_info *info)
150{
151 static int lastreg = -2;
152 unsigned long flags;
153
154 local_irq_save(flags);
155
156 /*
157 * fbdev will set an entire colourmap, but X won't. Hopefully
158 * this should accommodate both of them
159 */
160 if (regno != lastreg + 1) {
161 int i;
162
163 /* Stab in the dark trying to reset the CLUT pointer */
164 nubus_writel(0, &dafb_cmap_regs->reset);
165 nop();
166
167 /* Loop until we get to the register we want */
168 for (i = 0; i < regno; i++) {
169 nubus_writeb(info->cmap.red[i] >> 8,
170 &dafb_cmap_regs->lut);
171 nop();
172 nubus_writeb(info->cmap.green[i] >> 8,
173 &dafb_cmap_regs->lut);
174 nop();
175 nubus_writeb(info->cmap.blue[i] >> 8,
176 &dafb_cmap_regs->lut);
177 nop();
178 }
179 }
180
181 nubus_writeb(red, &dafb_cmap_regs->lut);
182 nop();
183 nubus_writeb(green, &dafb_cmap_regs->lut);
184 nop();
185 nubus_writeb(blue, &dafb_cmap_regs->lut);
186
187 local_irq_restore(flags);
188 lastreg = regno;
189 return 0;
190}
191
192/* V8 and Brazil seem to use the same DAC. Sonora does as well. */
193static int v8_brazil_setpalette(unsigned int regno, unsigned int red,
194 unsigned int green, unsigned int blue,
195 struct fb_info *info)
196{
197 unsigned int bpp = info->var.bits_per_pixel;
198 unsigned long flags;
199
200 local_irq_save(flags);
201
202 /* On these chips, the CLUT register numbers are spread out
203 * across the register space. Thus:
204 * In 8bpp, all regnos are valid.
205 * In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
206 * In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff
207 */
208 regno = (regno << (8 - bpp)) | (0xFF >> bpp);
209 nubus_writeb(regno, &v8_brazil_cmap_regs->addr);
210 nop();
211
212 /* send one color channel at a time */
213 nubus_writeb(red, &v8_brazil_cmap_regs->lut);
214 nop();
215 nubus_writeb(green, &v8_brazil_cmap_regs->lut);
216 nop();
217 nubus_writeb(blue, &v8_brazil_cmap_regs->lut);
218
219 local_irq_restore(flags);
220 return 0;
221}
222
223/* RAM-Based Video */
224static int rbv_setpalette(unsigned int regno, unsigned int red,
225 unsigned int green, unsigned int blue,
226 struct fb_info *info)
227{
228 unsigned long flags;
229
230 local_irq_save(flags);
231
232 /* From the VideoToolbox driver. Seems to be saying that
233 * regno #254 and #255 are the important ones for 1-bit color,
234 * regno #252-255 are the important ones for 2-bit color, etc.
235 */
236 regno += 256 - (1 << info->var.bits_per_pixel);
237
238 /* reset clut? (VideoToolbox sez "not necessary") */
239 nubus_writeb(0xFF, &rbv_cmap_regs->cntl);
240 nop();
241
242 /* tell clut which address to use. */
243 nubus_writeb(regno, &rbv_cmap_regs->addr);
244 nop();
245
246 /* send one color channel at a time. */
247 nubus_writeb(red, &rbv_cmap_regs->lut);
248 nop();
249 nubus_writeb(green, &rbv_cmap_regs->lut);
250 nop();
251 nubus_writeb(blue, &rbv_cmap_regs->lut);
252
253 local_irq_restore(flags);
254 return 0;
255}
256
257/* Macintosh Display Card (8*24) */
258static int mdc_setpalette(unsigned int regno, unsigned int red,
259 unsigned int green, unsigned int blue,
260 struct fb_info *info)
261{
262 struct mdc_cmap_regs *cmap_regs = slot_addr;
263 unsigned long flags;
264
265 local_irq_save(flags);
266
267 /* the nop's are there to order writes. */
268 nubus_writeb(regno, &cmap_regs->addr);
269 nop();
270 nubus_writeb(red, &cmap_regs->lut);
271 nop();
272 nubus_writeb(green, &cmap_regs->lut);
273 nop();
274 nubus_writeb(blue, &cmap_regs->lut);
275
276 local_irq_restore(flags);
277 return 0;
278}
279
280/* Toby frame buffer */
281static int toby_setpalette(unsigned int regno, unsigned int red,
282 unsigned int green, unsigned int blue,
283 struct fb_info *info)
284{
285 struct toby_cmap_regs *cmap_regs = slot_addr;
286 unsigned int bpp = info->var.bits_per_pixel;
287 unsigned long flags;
288
289 red = ~red;
290 green = ~green;
291 blue = ~blue;
292 regno = (regno << (8 - bpp)) | (0xFF >> bpp);
293
294 local_irq_save(flags);
295
296 nubus_writeb(regno, &cmap_regs->addr);
297 nop();
298 nubus_writeb(red, &cmap_regs->lut);
299 nop();
300 nubus_writeb(green, &cmap_regs->lut);
301 nop();
302 nubus_writeb(blue, &cmap_regs->lut);
303
304 local_irq_restore(flags);
305 return 0;
306}
307
308/* Jet frame buffer */
309static int jet_setpalette(unsigned int regno, unsigned int red,
310 unsigned int green, unsigned int blue,
311 struct fb_info *info)
312{
313 struct jet_cmap_regs *cmap_regs = slot_addr;
314 unsigned long flags;
315
316 local_irq_save(flags);
317
318 nubus_writeb(regno, &cmap_regs->addr);
319 nop();
320 nubus_writeb(red, &cmap_regs->lut);
321 nop();
322 nubus_writeb(green, &cmap_regs->lut);
323 nop();
324 nubus_writeb(blue, &cmap_regs->lut);
325
326 local_irq_restore(flags);
327 return 0;
328}
329
330/*
331 * Civic framebuffer -- Quadra AV built-in video. A chip
332 * called Sebastian holds the actual color palettes, and
333 * apparently, there are two different banks of 512K RAM
334 * which can act as separate framebuffers for doing video
335 * input and viewing the screen at the same time! The 840AV
336 * Can add another 1MB RAM to give the two framebuffers
337 * 1MB RAM apiece.
338 */
339static int civic_setpalette(unsigned int regno, unsigned int red,
340 unsigned int green, unsigned int blue,
341 struct fb_info *info)
342{
343 unsigned long flags;
344 int clut_status;
345
346 local_irq_save(flags);
347
348 /* Set the register address */
349 nubus_writeb(regno, &civic_cmap_regs->addr);
350 nop();
351
352 /*
353 * Grab a status word and do some checking;
354 * Then finally write the clut!
355 */
356 clut_status = nubus_readb(&civic_cmap_regs->status2);
357
358 if ((clut_status & 0x0008) == 0)
359 {
360#if 0
361 if ((clut_status & 0x000D) != 0)
362 {
363 nubus_writeb(0x00, &civic_cmap_regs->lut);
364 nop();
365 nubus_writeb(0x00, &civic_cmap_regs->lut);
366 nop();
367 }
368#endif
369
370 nubus_writeb(red, &civic_cmap_regs->lut);
371 nop();
372 nubus_writeb(green, &civic_cmap_regs->lut);
373 nop();
374 nubus_writeb(blue, &civic_cmap_regs->lut);
375 nop();
376 nubus_writeb(0x00, &civic_cmap_regs->lut);
377 }
378 else
379 {
380 unsigned char junk;
381
382 junk = nubus_readb(&civic_cmap_regs->lut);
383 nop();
384 junk = nubus_readb(&civic_cmap_regs->lut);
385 nop();
386 junk = nubus_readb(&civic_cmap_regs->lut);
387 nop();
388 junk = nubus_readb(&civic_cmap_regs->lut);
389 nop();
390
391 if ((clut_status & 0x000D) != 0)
392 {
393 nubus_writeb(0x00, &civic_cmap_regs->lut);
394 nop();
395 nubus_writeb(0x00, &civic_cmap_regs->lut);
396 nop();
397 }
398
399 nubus_writeb(red, &civic_cmap_regs->lut);
400 nop();
401 nubus_writeb(green, &civic_cmap_regs->lut);
402 nop();
403 nubus_writeb(blue, &civic_cmap_regs->lut);
404 nop();
405 nubus_writeb(junk, &civic_cmap_regs->lut);
406 }
407
408 local_irq_restore(flags);
409 return 0;
410}
411
412/*
413 * The CSC is the framebuffer on the PowerBook 190 series
414 * (and the 5300 too, but that's a PowerMac). This function
415 * brought to you in part by the ECSC driver for MkLinux.
416 */
417static int csc_setpalette(unsigned int regno, unsigned int red,
418 unsigned int green, unsigned int blue,
419 struct fb_info *info)
420{
421 unsigned long flags;
422
423 local_irq_save(flags);
424
425 udelay(1); /* mklinux on PB 5300 waits for 260 ns */
426 nubus_writeb(regno, &csc_cmap_regs->clut_waddr);
427 nubus_writeb(red, &csc_cmap_regs->clut_data);
428 nubus_writeb(green, &csc_cmap_regs->clut_data);
429 nubus_writeb(blue, &csc_cmap_regs->clut_data);
430
431 local_irq_restore(flags);
432 return 0;
433}
434
435static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
436 unsigned blue, unsigned transp,
437 struct fb_info *fb_info)
438{
439 /*
440 * Set a single color register. The values supplied are
441 * already rounded down to the hardware's capabilities
442 * (according to the entries in the `var' structure).
443 * Return non-zero for invalid regno.
444 */
445
446 if (regno >= fb_info->cmap.len)
447 return 1;
448
449 if (fb_info->var.bits_per_pixel <= 8) {
450 switch (fb_info->var.bits_per_pixel) {
451 case 1:
452 /* We shouldn't get here */
453 break;
454 case 2:
455 case 4:
456 case 8:
457 if (macfb_setpalette)
458 macfb_setpalette(regno, red >> 8, green >> 8,
459 blue >> 8, fb_info);
460 else
461 return 1;
462 break;
463 }
464 } else if (regno < 16) {
465 switch (fb_info->var.bits_per_pixel) {
466 case 16:
467 if (fb_info->var.red.offset == 10) {
468 /* 1:5:5:5 */
469 ((u32*) (fb_info->pseudo_palette))[regno] =
470 ((red & 0xf800) >> 1) |
471 ((green & 0xf800) >> 6) |
472 ((blue & 0xf800) >> 11) |
473 ((transp != 0) << 15);
474 } else {
475 /* 0:5:6:5 */
476 ((u32*) (fb_info->pseudo_palette))[regno] =
477 ((red & 0xf800) >> 0) |
478 ((green & 0xfc00) >> 5) |
479 ((blue & 0xf800) >> 11);
480 }
481 break;
482 /*
483 * 24-bit colour almost doesn't exist on 68k Macs --
484 * http://support.apple.com/kb/TA28634 (Old Article: 10992)
485 */
486 case 24:
487 case 32:
488 red >>= 8;
489 green >>= 8;
490 blue >>= 8;
491 ((u32 *)(fb_info->pseudo_palette))[regno] =
492 (red << fb_info->var.red.offset) |
493 (green << fb_info->var.green.offset) |
494 (blue << fb_info->var.blue.offset);
495 break;
496 }
497 }
498
499 return 0;
500}
501
502static struct fb_ops macfb_ops = {
503 .owner = THIS_MODULE,
504 .fb_setcolreg = macfb_setcolreg,
505 .fb_fillrect = cfb_fillrect,
506 .fb_copyarea = cfb_copyarea,
507 .fb_imageblit = cfb_imageblit,
508};
509
510static void __init macfb_setup(char *options)
511{
512 char *this_opt;
513
514 if (!options || !*options)
515 return;
516
517 while ((this_opt = strsep(&options, ",")) != NULL) {
518 if (!*this_opt)
519 continue;
520
521 if (!strcmp(this_opt, "inverse"))
522 fb_invert_cmaps();
523 else
524 if (!strcmp(this_opt, "vidtest"))
525 vidtest = 1; /* enable experimental CLUT code */
526 }
527}
528
529static void __init iounmap_macfb(void)
530{
531 if (dafb_cmap_regs)
532 iounmap(dafb_cmap_regs);
533 if (v8_brazil_cmap_regs)
534 iounmap(v8_brazil_cmap_regs);
535 if (rbv_cmap_regs)
536 iounmap(rbv_cmap_regs);
537 if (civic_cmap_regs)
538 iounmap(civic_cmap_regs);
539 if (csc_cmap_regs)
540 iounmap(csc_cmap_regs);
541}
542
543static int __init macfb_init(void)
544{
545 int video_cmap_len, video_is_nubus = 0;
546 struct nubus_rsrc *ndev = NULL;
547 char *option = NULL;
548 int err;
549
550 if (fb_get_options("macfb", &option))
551 return -ENODEV;
552 macfb_setup(option);
553
554 if (!MACH_IS_MAC)
555 return -ENODEV;
556
557 if (mac_bi_data.id == MAC_MODEL_Q630 ||
558 mac_bi_data.id == MAC_MODEL_P588)
559 return -ENODEV; /* See valkyriefb.c */
560
561 macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
562 macfb_defined.yres = mac_bi_data.dimensions >> 16;
563 macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
564
565 macfb_fix.line_length = mac_bi_data.videorow;
566 macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres;
567 /* Note: physical address (since 2.1.127) */
568 macfb_fix.smem_start = mac_bi_data.videoaddr;
569
570 /*
571 * This is actually redundant with the initial mappings.
572 * However, there are some non-obvious aspects to the way
573 * those mappings are set up, so this is in fact the safest
574 * way to ensure that this driver will work on every possible Mac
575 */
576 fb_info.screen_base = ioremap(mac_bi_data.videoaddr,
577 macfb_fix.smem_len);
578 if (!fb_info.screen_base)
579 return -ENODEV;
580
581 pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
582 macfb_fix.smem_start, fb_info.screen_base,
583 macfb_fix.smem_len / 1024);
584 pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
585 macfb_defined.xres, macfb_defined.yres,
586 macfb_defined.bits_per_pixel, macfb_fix.line_length);
587
588 /* Fill in the available video resolution */
589 macfb_defined.xres_virtual = macfb_defined.xres;
590 macfb_defined.yres_virtual = macfb_defined.yres;
591 macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
592 macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
593
594 /* Some dummy values for timing to make fbset happy */
595 macfb_defined.pixclock = 10000000 / macfb_defined.xres *
596 1000 / macfb_defined.yres;
597 macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8;
598 macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8;
599
600 switch (macfb_defined.bits_per_pixel) {
601 case 1:
602 macfb_defined.red.length = macfb_defined.bits_per_pixel;
603 macfb_defined.green.length = macfb_defined.bits_per_pixel;
604 macfb_defined.blue.length = macfb_defined.bits_per_pixel;
605 video_cmap_len = 2;
606 macfb_fix.visual = FB_VISUAL_MONO01;
607 break;
608 case 2:
609 case 4:
610 case 8:
611 macfb_defined.red.length = macfb_defined.bits_per_pixel;
612 macfb_defined.green.length = macfb_defined.bits_per_pixel;
613 macfb_defined.blue.length = macfb_defined.bits_per_pixel;
614 video_cmap_len = 1 << macfb_defined.bits_per_pixel;
615 macfb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
616 break;
617 case 16:
618 macfb_defined.transp.offset = 15;
619 macfb_defined.transp.length = 1;
620 macfb_defined.red.offset = 10;
621 macfb_defined.red.length = 5;
622 macfb_defined.green.offset = 5;
623 macfb_defined.green.length = 5;
624 macfb_defined.blue.offset = 0;
625 macfb_defined.blue.length = 5;
626 video_cmap_len = 16;
627 /*
628 * Should actually be FB_VISUAL_DIRECTCOLOR, but this
629 * works too
630 */
631 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
632 break;
633 case 24:
634 case 32:
635 macfb_defined.red.offset = 16;
636 macfb_defined.red.length = 8;
637 macfb_defined.green.offset = 8;
638 macfb_defined.green.length = 8;
639 macfb_defined.blue.offset = 0;
640 macfb_defined.blue.length = 8;
641 video_cmap_len = 16;
642 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
643 break;
644 default:
645 pr_err("macfb: unknown or unsupported bit depth: %d\n",
646 macfb_defined.bits_per_pixel);
647 err = -EINVAL;
648 goto fail_unmap;
649 }
650
651 /*
652 * We take a wild guess that if the video physical address is
653 * in nubus slot space, that the nubus card is driving video.
654 * Penguin really ought to tell us whether we are using internal
655 * video or not.
656 * Hopefully we only find one of them. Otherwise our NuBus
657 * code is really broken :-)
658 */
659
660 for_each_func_rsrc(ndev) {
661 unsigned long base = ndev->board->slot_addr;
662
663 if (mac_bi_data.videoaddr < base ||
664 mac_bi_data.videoaddr - base > 0xFFFFFF)
665 continue;
666
667 if (ndev->category != NUBUS_CAT_DISPLAY ||
668 ndev->type != NUBUS_TYPE_VIDEO)
669 continue;
670
671 video_is_nubus = 1;
672 slot_addr = (unsigned char *)base;
673
674 switch(ndev->dr_hw) {
675 case NUBUS_DRHW_APPLE_MDC:
676 strcpy(macfb_fix.id, "Mac Disp. Card");
677 macfb_setpalette = mdc_setpalette;
678 break;
679 case NUBUS_DRHW_APPLE_TFB:
680 strcpy(macfb_fix.id, "Toby");
681 macfb_setpalette = toby_setpalette;
682 break;
683 case NUBUS_DRHW_APPLE_JET:
684 strcpy(macfb_fix.id, "Jet");
685 macfb_setpalette = jet_setpalette;
686 break;
687 default:
688 strcpy(macfb_fix.id, "Generic NuBus");
689 break;
690 }
691 }
692
693 /* If it's not a NuBus card, it must be internal video */
694 if (!video_is_nubus)
695 switch (mac_bi_data.id) {
696 /*
697 * DAFB Quadras
698 * Note: these first four have the v7 DAFB, which is
699 * known to be rather unlike the ones used in the
700 * other models
701 */
702 case MAC_MODEL_P475:
703 case MAC_MODEL_P475F:
704 case MAC_MODEL_P575:
705 case MAC_MODEL_Q605:
706
707 case MAC_MODEL_Q800:
708 case MAC_MODEL_Q650:
709 case MAC_MODEL_Q610:
710 case MAC_MODEL_C650:
711 case MAC_MODEL_C610:
712 case MAC_MODEL_Q700:
713 case MAC_MODEL_Q900:
714 case MAC_MODEL_Q950:
715 strcpy(macfb_fix.id, "DAFB");
716 macfb_setpalette = dafb_setpalette;
717 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
718 break;
719
720 /*
721 * LC II uses the V8 framebuffer
722 */
723 case MAC_MODEL_LCII:
724 strcpy(macfb_fix.id, "V8");
725 macfb_setpalette = v8_brazil_setpalette;
726 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
727 break;
728
729 /*
730 * IIvi, IIvx use the "Brazil" framebuffer (which is
731 * very much like the V8, it seems, and probably uses
732 * the same DAC)
733 */
734 case MAC_MODEL_IIVI:
735 case MAC_MODEL_IIVX:
736 case MAC_MODEL_P600:
737 strcpy(macfb_fix.id, "Brazil");
738 macfb_setpalette = v8_brazil_setpalette;
739 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
740 break;
741
742 /*
743 * LC III (and friends) use the Sonora framebuffer
744 * Incidentally this is also used in the non-AV models
745 * of the x100 PowerMacs
746 * These do in fact seem to use the same DAC interface
747 * as the LC II.
748 */
749 case MAC_MODEL_LCIII:
750 case MAC_MODEL_P520:
751 case MAC_MODEL_P550:
752 case MAC_MODEL_P460:
753 strcpy(macfb_fix.id, "Sonora");
754 macfb_setpalette = v8_brazil_setpalette;
755 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
756 break;
757
758 /*
759 * IIci and IIsi use the infamous RBV chip
760 * (the IIsi is just a rebadged and crippled
761 * IIci in a different case, BTW)
762 */
763 case MAC_MODEL_IICI:
764 case MAC_MODEL_IISI:
765 strcpy(macfb_fix.id, "RBV");
766 macfb_setpalette = rbv_setpalette;
767 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
768 break;
769
770 /*
771 * AVs use the Civic framebuffer
772 */
773 case MAC_MODEL_Q840:
774 case MAC_MODEL_C660:
775 strcpy(macfb_fix.id, "Civic");
776 macfb_setpalette = civic_setpalette;
777 civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
778 break;
779
780
781 /*
782 * Assorted weirdos
783 * We think this may be like the LC II
784 */
785 case MAC_MODEL_LC:
786 strcpy(macfb_fix.id, "LC");
787 if (vidtest) {
788 macfb_setpalette = v8_brazil_setpalette;
789 v8_brazil_cmap_regs =
790 ioremap(DAC_BASE, 0x1000);
791 }
792 break;
793
794 /*
795 * We think this may be like the LC II
796 */
797 case MAC_MODEL_CCL:
798 strcpy(macfb_fix.id, "Color Classic");
799 if (vidtest) {
800 macfb_setpalette = v8_brazil_setpalette;
801 v8_brazil_cmap_regs =
802 ioremap(DAC_BASE, 0x1000);
803 }
804 break;
805
806 /*
807 * And we *do* mean "weirdos"
808 */
809 case MAC_MODEL_TV:
810 strcpy(macfb_fix.id, "Mac TV");
811 break;
812
813 /*
814 * These don't have colour, so no need to worry
815 */
816 case MAC_MODEL_SE30:
817 case MAC_MODEL_CLII:
818 strcpy(macfb_fix.id, "Monochrome");
819 break;
820
821 /*
822 * Powerbooks are particularly difficult. Many of
823 * them have separate framebuffers for external and
824 * internal video, which is admittedly pretty cool,
825 * but will be a bit of a headache to support here.
826 * Also, many of them are grayscale, and we don't
827 * really support that.
828 */
829
830 /*
831 * Slot 0 ROM says TIM. No external video. B&W.
832 */
833 case MAC_MODEL_PB140:
834 case MAC_MODEL_PB145:
835 case MAC_MODEL_PB170:
836 strcpy(macfb_fix.id, "DDC");
837 break;
838
839 /*
840 * Internal is GSC, External (if present) is ViSC
841 */
842 case MAC_MODEL_PB150: /* no external video */
843 case MAC_MODEL_PB160:
844 case MAC_MODEL_PB165:
845 case MAC_MODEL_PB180:
846 case MAC_MODEL_PB210:
847 case MAC_MODEL_PB230:
848 strcpy(macfb_fix.id, "GSC");
849 break;
850
851 /*
852 * Internal is TIM, External is ViSC
853 */
854 case MAC_MODEL_PB165C:
855 case MAC_MODEL_PB180C:
856 strcpy(macfb_fix.id, "TIM");
857 break;
858
859 /*
860 * Internal is CSC, External is Keystone+Ariel.
861 */
862 case MAC_MODEL_PB190: /* external video is optional */
863 case MAC_MODEL_PB520:
864 case MAC_MODEL_PB250:
865 case MAC_MODEL_PB270C:
866 case MAC_MODEL_PB280:
867 case MAC_MODEL_PB280C:
868 strcpy(macfb_fix.id, "CSC");
869 macfb_setpalette = csc_setpalette;
870 csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
871 break;
872
873 default:
874 strcpy(macfb_fix.id, "Unknown");
875 break;
876 }
877
878 fb_info.fbops = &macfb_ops;
879 fb_info.var = macfb_defined;
880 fb_info.fix = macfb_fix;
881 fb_info.pseudo_palette = pseudo_palette;
882 fb_info.flags = FBINFO_DEFAULT;
883
884 err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
885 if (err)
886 goto fail_unmap;
887
888 err = register_framebuffer(&fb_info);
889 if (err)
890 goto fail_dealloc;
891
892 fb_info(&fb_info, "%s frame buffer device\n", fb_info.fix.id);
893
894 return 0;
895
896fail_dealloc:
897 fb_dealloc_cmap(&fb_info.cmap);
898fail_unmap:
899 iounmap(fb_info.screen_base);
900 iounmap_macfb();
901 return err;
902}
903
904module_init(macfb_init);
905MODULE_LICENSE("GPL");