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