blob: ee380d5f34107d0713b582b9a29cd6259a327119 [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 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 .type = FB_TYPE_PACKED_PIXELS,
168 .accel = FB_ACCEL_NONE,
169};
170
171static struct fb_info fb_info;
Antonino A. Daplas24fc7222007-07-17 04:05:37 -0700172static u32 pseudo_palette[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173static int inverse = 0;
174static int vidtest = 0;
175
176static int valkyrie_setpalette (unsigned int regno, unsigned int red,
177 unsigned int green, unsigned int blue,
178 struct fb_info *info)
179{
180 unsigned long flags;
181
182 red >>= 8;
183 green >>= 8;
184 blue >>= 8;
185
186 local_irq_save(flags);
187
188 /* tell clut which address to fill */
189 nubus_writeb(regno, &valkyrie_cmap_regs->addr);
190 nop();
191
192 /* send one color channel at a time */
193 nubus_writeb(red, &valkyrie_cmap_regs->lut);
194 nop();
195 nubus_writeb(green, &valkyrie_cmap_regs->lut);
196 nop();
197 nubus_writeb(blue, &valkyrie_cmap_regs->lut);
198
199 local_irq_restore(flags);
200 return 0;
201}
202
203/* Unlike the Valkyrie, the DAFB cannot set individual colormap
204 registers. Therefore, we do what the MacOS driver does (no
205 kidding!) and simply set them one by one until we hit the one we
206 want. */
207static int dafb_setpalette (unsigned int regno, unsigned int red,
208 unsigned int green, unsigned int blue,
209 struct fb_info *info)
210{
211 /* FIXME: really, really need to use ioremap() here,
212 phys_to_virt() doesn't work anymore */
213 static int lastreg = -1;
214 unsigned long flags;
215
216 red >>= 8;
217 green >>= 8;
218 blue >>= 8;
219
220 local_irq_save(flags);
221
222 /* fbdev will set an entire colourmap, but X won't. Hopefully
223 this should accommodate both of them */
224 if (regno != lastreg+1) {
225 int i;
226
227 /* Stab in the dark trying to reset the CLUT pointer */
228 nubus_writel(0, &dafb_cmap_regs->reset);
229 nop();
230
231 /* Loop until we get to the register we want */
232 for (i = 0; i < regno; i++) {
233 nubus_writeb(info->cmap.red[i] >> 8, &dafb_cmap_regs->lut);
234 nop();
235 nubus_writeb(info->cmap.green[i] >> 8, &dafb_cmap_regs->lut);
236 nop();
237 nubus_writeb(info->cmap.blue[i] >> 8, &dafb_cmap_regs->lut);
238 nop();
239 }
240 }
241
242 nubus_writeb(red, &dafb_cmap_regs->lut);
243 nop();
244 nubus_writeb(green, &dafb_cmap_regs->lut);
245 nop();
246 nubus_writeb(blue, &dafb_cmap_regs->lut);
247
248 local_irq_restore(flags);
249 lastreg = regno;
250 return 0;
251}
252
253/* V8 and Brazil seem to use the same DAC. Sonora does as well. */
254static int v8_brazil_setpalette (unsigned int regno, unsigned int red,
255 unsigned int green, unsigned int blue,
256 struct fb_info *info)
257{
258 unsigned int bpp = info->var.bits_per_pixel;
259 unsigned char _red =red>>8;
260 unsigned char _green=green>>8;
261 unsigned char _blue =blue>>8;
262 unsigned char _regno;
263 unsigned long flags;
264
265 if (bpp > 8) return 1; /* failsafe */
266
267 local_irq_save(flags);
268
269 /* On these chips, the CLUT register numbers are spread out
270 across the register space. Thus:
271
272 In 8bpp, all regnos are valid.
273
274 In 4bpp, the regnos are 0x0f, 0x1f, 0x2f, etc, etc
275
276 In 2bpp, the regnos are 0x3f, 0x7f, 0xbf, 0xff */
277 _regno = (regno << (8 - bpp)) | (0xFF >> bpp);
278 nubus_writeb(_regno, &v8_brazil_cmap_regs->addr); nop();
279
280 /* send one color channel at a time */
281 nubus_writeb(_red, &v8_brazil_cmap_regs->lut); nop();
282 nubus_writeb(_green, &v8_brazil_cmap_regs->lut); nop();
283 nubus_writeb(_blue, &v8_brazil_cmap_regs->lut);
284
285 local_irq_restore(flags);
286 return 0;
287}
288
289static int rbv_setpalette (unsigned int regno, unsigned int red,
290 unsigned int green, unsigned int blue,
291 struct fb_info *info)
292{
293 /* use MSBs */
294 unsigned char _red =red>>8;
295 unsigned char _green=green>>8;
296 unsigned char _blue =blue>>8;
297 unsigned char _regno;
298 unsigned long flags;
299
300 if (info->var.bits_per_pixel > 8) return 1; /* failsafe */
301
302 local_irq_save(flags);
303
304 /* From the VideoToolbox driver. Seems to be saying that
305 * regno #254 and #255 are the important ones for 1-bit color,
306 * regno #252-255 are the important ones for 2-bit color, etc.
307 */
308 _regno = regno + (256-(1 << info->var.bits_per_pixel));
309
310 /* reset clut? (VideoToolbox sez "not necessary") */
311 nubus_writeb(0xFF, &rbv_cmap_regs->cntl); nop();
312
313 /* tell clut which address to use. */
314 nubus_writeb(_regno, &rbv_cmap_regs->addr); nop();
315
316 /* send one color channel at a time. */
317 nubus_writeb(_red, &rbv_cmap_regs->lut); nop();
318 nubus_writeb(_green, &rbv_cmap_regs->lut); nop();
319 nubus_writeb(_blue, &rbv_cmap_regs->lut);
320
321 local_irq_restore(flags); /* done. */
322 return 0;
323}
324
325/* Macintosh Display Card (8x24) */
326static int mdc_setpalette(unsigned int regno, unsigned int red,
327 unsigned int green, unsigned int blue,
328 struct fb_info *info)
329{
330 volatile struct mdc_cmap_regs *cmap_regs =
331 nubus_slot_addr(video_slot);
332 /* use MSBs */
333 unsigned char _red =red>>8;
334 unsigned char _green=green>>8;
335 unsigned char _blue =blue>>8;
336 unsigned char _regno=regno;
337 unsigned long flags;
338
339 local_irq_save(flags);
340
341 /* the nop's are there to order writes. */
342 nubus_writeb(_regno, &cmap_regs->addr); nop();
343 nubus_writeb(_red, &cmap_regs->lut); nop();
344 nubus_writeb(_green, &cmap_regs->lut); nop();
345 nubus_writeb(_blue, &cmap_regs->lut);
346
347 local_irq_restore(flags);
348 return 0;
349}
350
351/* Toby frame buffer */
352static int toby_setpalette(unsigned int regno, unsigned int red,
353 unsigned int green, unsigned int blue,
354 struct fb_info *info)
355{
356 volatile struct toby_cmap_regs *cmap_regs =
357 nubus_slot_addr(video_slot);
358 unsigned int bpp = info->var.bits_per_pixel;
359 /* use MSBs */
360 unsigned char _red =~(red>>8);
361 unsigned char _green=~(green>>8);
362 unsigned char _blue =~(blue>>8);
363 unsigned char _regno = (regno << (8 - bpp)) | (0xFF >> bpp);
364 unsigned long flags;
365
366 local_irq_save(flags);
367
368 nubus_writeb(_regno, &cmap_regs->addr); nop();
369 nubus_writeb(_red, &cmap_regs->lut); nop();
370 nubus_writeb(_green, &cmap_regs->lut); nop();
371 nubus_writeb(_blue, &cmap_regs->lut);
372
373 local_irq_restore(flags);
374 return 0;
375}
376
377/* Jet frame buffer */
378static int jet_setpalette(unsigned int regno, unsigned int red,
379 unsigned int green, unsigned int blue,
380 struct fb_info *info)
381{
382 volatile struct jet_cmap_regs *cmap_regs =
383 nubus_slot_addr(video_slot);
384 /* use MSBs */
385 unsigned char _red = (red>>8);
386 unsigned char _green = (green>>8);
387 unsigned char _blue = (blue>>8);
388 unsigned long flags;
389
390 local_irq_save(flags);
391
392 nubus_writeb(regno, &cmap_regs->addr); nop();
393 nubus_writeb(_red, &cmap_regs->lut); nop();
394 nubus_writeb(_green, &cmap_regs->lut); nop();
395 nubus_writeb(_blue, &cmap_regs->lut);
396
397 local_irq_restore(flags);
398 return 0;
399}
400
401/*
402 * Civic framebuffer -- Quadra AV built-in video. A chip
403 * called Sebastian holds the actual color palettes, and
404 * apparently, there are two different banks of 512K RAM
405 * which can act as separate framebuffers for doing video
406 * input and viewing the screen at the same time! The 840AV
407 * Can add another 1MB RAM to give the two framebuffers
408 * 1MB RAM apiece.
409 *
410 * FIXME: this doesn't seem to work anymore.
411 */
412static int civic_setpalette (unsigned int regno, unsigned int red,
413 unsigned int green, unsigned int blue,
414 struct fb_info *info)
415{
416 static int lastreg = -1;
417 unsigned long flags;
418 int clut_status;
419
420 if (info->var.bits_per_pixel > 8) return 1; /* failsafe */
421
422 red >>= 8;
423 green >>= 8;
424 blue >>= 8;
425
426 local_irq_save(flags);
427
428 /*
429 * Set the register address
430 */
431 nubus_writeb(regno, &civic_cmap_regs->addr); nop();
432
433 /*
434 * Wait for VBL interrupt here;
435 * They're usually not enabled from Penguin, so we won't check
436 */
437#if 0
438 {
439#define CIVIC_VBL_OFFSET 0x120
440 volatile unsigned long *vbl = nubus_readl(civic_cmap_regs->vbl_addr + CIVIC_VBL_OFFSET);
441 /* do interrupt setup stuff here? */
442 *vbl = 0L; nop(); /* clear */
443 *vbl = 1L; nop(); /* set */
444 while (*vbl != 0L) /* wait for next vbl */
445 {
446 usleep(10); /* needed? */
447 }
448 /* do interrupt shutdown stuff here? */
449 }
450#endif
451
452 /*
453 * Grab a status word and do some checking;
454 * Then finally write the clut!
455 */
456 clut_status = nubus_readb(&civic_cmap_regs->status2);
457
458 if ((clut_status & 0x0008) == 0)
459 {
460#if 0
461 if ((clut_status & 0x000D) != 0)
462 {
463 nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
464 nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
465 }
466#endif
467
468 nubus_writeb( red, &civic_cmap_regs->lut); nop();
469 nubus_writeb(green, &civic_cmap_regs->lut); nop();
470 nubus_writeb( blue, &civic_cmap_regs->lut); nop();
471 nubus_writeb( 0x00, &civic_cmap_regs->lut); nop();
472 }
473 else
474 {
475 unsigned char junk;
476
477 junk = nubus_readb(&civic_cmap_regs->lut); nop();
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
482 if ((clut_status & 0x000D) != 0)
483 {
484 nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
485 nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
486 }
487
488 nubus_writeb( red, &civic_cmap_regs->lut); nop();
489 nubus_writeb(green, &civic_cmap_regs->lut); nop();
490 nubus_writeb( blue, &civic_cmap_regs->lut); nop();
491 nubus_writeb( junk, &civic_cmap_regs->lut); nop();
492 }
493
494 local_irq_restore(flags);
495 lastreg = regno;
496 return 0;
497}
498
499/*
500 * The CSC is the framebuffer on the PowerBook 190 series
501 * (and the 5300 too, but that's a PowerMac). This function
502 * brought to you in part by the ECSC driver for MkLinux.
503 */
504
505static int csc_setpalette (unsigned int regno, unsigned int red,
506 unsigned int green, unsigned int blue,
507 struct fb_info *info)
508{
509 mdelay(1);
510 csc_cmap_regs->clut_waddr = regno;
511 csc_cmap_regs->clut_data = red;
512 csc_cmap_regs->clut_data = green;
513 csc_cmap_regs->clut_data = blue;
514 return 0;
515}
516
517static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
518 unsigned blue, unsigned transp,
519 struct fb_info *fb_info)
520{
521 /*
522 * Set a single color register. The values supplied are
523 * already rounded down to the hardware's capabilities
524 * (according to the entries in the `var' structure). Return
525 * != 0 for invalid regno.
526 */
527
528 if (regno >= fb_info->cmap.len)
529 return 1;
530
Antonino A. Daplas24fc7222007-07-17 04:05:37 -0700531 if (fb_info->var.bits_per_pixel <= 8) {
532 switch (fb_info->var.bits_per_pixel) {
533 case 1:
534 /* We shouldn't get here */
535 break;
536 case 2:
537 case 4:
538 case 8:
539 if (macfb_setpalette)
540 macfb_setpalette(regno, red, green, blue,
541 fb_info);
542 else
543 return 1;
544 break;
545 }
546 } else if (regno < 16) {
547 switch (fb_info->var.bits_per_pixel) {
548 case 16:
549 if (fb_info->var.red.offset == 10) {
550 /* 1:5:5:5 */
551 ((u32*) (fb_info->pseudo_palette))[regno] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 ((red & 0xf800) >> 1) |
553 ((green & 0xf800) >> 6) |
554 ((blue & 0xf800) >> 11) |
555 ((transp != 0) << 15);
Antonino A. Daplas24fc7222007-07-17 04:05:37 -0700556 } else {
557 /* 0:5:6:5 */
558 ((u32*) (fb_info->pseudo_palette))[regno] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559 ((red & 0xf800) ) |
560 ((green & 0xfc00) >> 5) |
561 ((blue & 0xf800) >> 11);
Antonino A. Daplas24fc7222007-07-17 04:05:37 -0700562 }
563 break;
564 /* I'm pretty sure that one or the other of these
565 doesn't exist on 68k Macs */
566 case 24:
567 red >>= 8;
568 green >>= 8;
569 blue >>= 8;
570 ((u32 *)(fb_info->pseudo_palette))[regno] =
571 (red << fb_info->var.red.offset) |
572 (green << fb_info->var.green.offset) |
573 (blue << fb_info->var.blue.offset);
574 break;
575 case 32:
576 red >>= 8;
577 green >>= 8;
578 blue >>= 8;
579 ((u32 *)(fb_info->pseudo_palette))[regno] =
580 (red << fb_info->var.red.offset) |
581 (green << fb_info->var.green.offset) |
582 (blue << fb_info->var.blue.offset);
583 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 }
Antonino A. Daplas24fc7222007-07-17 04:05:37 -0700585 }
586
587 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588}
589
590static struct fb_ops macfb_ops = {
591 .owner = THIS_MODULE,
592 .fb_setcolreg = macfb_setcolreg,
593 .fb_fillrect = cfb_fillrect,
594 .fb_copyarea = cfb_copyarea,
595 .fb_imageblit = cfb_imageblit,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596};
597
Adrian Bunk511e7482008-07-25 19:46:26 -0700598static void __init macfb_setup(char *options)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599{
600 char *this_opt;
601
602 if (!options || !*options)
603 return;
604
605 while ((this_opt = strsep(&options, ",")) != NULL) {
606 if (!*this_opt) continue;
607
608 if (! strcmp(this_opt, "inverse"))
609 inverse=1;
610 /* This means "turn on experimental CLUT code" */
611 else if (!strcmp(this_opt, "vidtest"))
612 vidtest=1;
613 }
614}
615
Amol Lad164a7652006-12-08 02:40:09 -0800616static void __init iounmap_macfb(void)
617{
618 if (valkyrie_cmap_regs)
619 iounmap(valkyrie_cmap_regs);
620 if (dafb_cmap_regs)
621 iounmap(dafb_cmap_regs);
622 if (v8_brazil_cmap_regs)
623 iounmap(v8_brazil_cmap_regs);
624 if (rbv_cmap_regs)
625 iounmap(rbv_cmap_regs);
626 if (civic_cmap_regs)
627 iounmap(civic_cmap_regs);
628 if (csc_cmap_regs)
629 iounmap(csc_cmap_regs);
630}
631
Al Viroed1705a2006-01-12 01:06:39 -0800632static int __init macfb_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634 int video_cmap_len, video_is_nubus = 0;
635 struct nubus_dev* ndev = NULL;
636 char *option = NULL;
Al Viroed1705a2006-01-12 01:06:39 -0800637 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
639 if (fb_get_options("macfb", &option))
640 return -ENODEV;
641 macfb_setup(option);
642
643 if (!MACH_IS_MAC)
Al Viroed1705a2006-01-12 01:06:39 -0800644 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
646 /* There can only be one internal video controller anyway so
647 we're not too worried about this */
648 macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
649 macfb_defined.yres = mac_bi_data.dimensions >> 16;
650 macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
651 macfb_fix.line_length = mac_bi_data.videorow;
652 macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres;
653 /* Note: physical address (since 2.1.127) */
654 macfb_fix.smem_start = mac_bi_data.videoaddr;
655 /* This is actually redundant with the initial mappings.
656 However, there are some non-obvious aspects to the way
657 those mappings are set up, so this is in fact the safest
658 way to ensure that this driver will work on every possible
659 Mac */
660 fb_info.screen_base = ioremap(mac_bi_data.videoaddr, macfb_fix.smem_len);
661
662 printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
663 macfb_fix.smem_start, fb_info.screen_base, macfb_fix.smem_len/1024);
664 printk("macfb: mode is %dx%dx%d, linelength=%d\n",
665 macfb_defined.xres, macfb_defined.yres, macfb_defined.bits_per_pixel, macfb_fix.line_length);
666
667 /*
668 * Fill in the available video resolution
669 */
670
671 macfb_defined.xres_virtual = macfb_defined.xres;
672 macfb_defined.yres_virtual = macfb_defined.yres;
673 macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
674 macfb_defined.width = PIXEL_TO_MM(macfb_defined.xres);
675
676 printk("macfb: scrolling: redraw\n");
677 macfb_defined.yres_virtual = macfb_defined.yres;
678
679 /* some dummy values for timing to make fbset happy */
680 macfb_defined.pixclock = 10000000 / macfb_defined.xres * 1000 / macfb_defined.yres;
681 macfb_defined.left_margin = (macfb_defined.xres / 8) & 0xf8;
682 macfb_defined.hsync_len = (macfb_defined.xres / 8) & 0xf8;
683
684 switch (macfb_defined.bits_per_pixel) {
685 case 1:
686 /* XXX: I think this will catch any program that tries
687 to do FBIO_PUTCMAP when the visual is monochrome */
688 macfb_defined.red.length = macfb_defined.bits_per_pixel;
689 macfb_defined.green.length = macfb_defined.bits_per_pixel;
690 macfb_defined.blue.length = macfb_defined.bits_per_pixel;
691 video_cmap_len = 0;
692 macfb_fix.visual = FB_VISUAL_MONO01;
693 break;
694 case 2:
695 case 4:
696 case 8:
697 macfb_defined.red.length = macfb_defined.bits_per_pixel;
698 macfb_defined.green.length = macfb_defined.bits_per_pixel;
699 macfb_defined.blue.length = macfb_defined.bits_per_pixel;
700 video_cmap_len = 1 << macfb_defined.bits_per_pixel;
701 macfb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
702 break;
703 case 16:
704 macfb_defined.transp.offset = 15;
705 macfb_defined.transp.length = 1;
706 macfb_defined.red.offset = 10;
707 macfb_defined.red.length = 5;
708 macfb_defined.green.offset = 5;
709 macfb_defined.green.length = 5;
710 macfb_defined.blue.offset = 0;
711 macfb_defined.blue.length = 5;
712 printk("macfb: directcolor: "
713 "size=1:5:5:5, shift=15:10:5:0\n");
714 video_cmap_len = 16;
715 /* Should actually be FB_VISUAL_DIRECTCOLOR, but this
716 works too */
717 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
718 break;
719 case 24:
720 case 32:
721 /* XXX: have to test these... can any 68k Macs
722 actually do this on internal video? */
723 macfb_defined.red.offset = 16;
724 macfb_defined.red.length = 8;
725 macfb_defined.green.offset = 8;
726 macfb_defined.green.length = 8;
727 macfb_defined.blue.offset = 0;
728 macfb_defined.blue.length = 8;
729 printk("macfb: truecolor: "
730 "size=0:8:8:8, shift=0:16:8:0\n");
731 video_cmap_len = 16;
732 macfb_fix.visual = FB_VISUAL_TRUECOLOR;
733 default:
734 video_cmap_len = 0;
735 macfb_fix.visual = FB_VISUAL_MONO01;
736 printk("macfb: unknown or unsupported bit depth: %d\n", macfb_defined.bits_per_pixel);
737 break;
738 }
739
740 /* Hardware dependent stuff */
741 /* We take a wild guess that if the video physical address is
742 * in nubus slot space, that the nubus card is driving video.
743 * Penguin really ought to tell us whether we are using internal
744 * video or not.
745 */
746 /* Hopefully we only find one of them. Otherwise our NuBus
747 code is really broken :-) */
748
749 while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev))
750 != NULL)
751 {
752 if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr
753 && (mac_bi_data.videoaddr <
754 (unsigned long)nubus_slot_addr(ndev->board->slot+1))))
755 continue;
756 video_is_nubus = 1;
757 /* We should probably just use the slot address... */
758 video_slot = ndev->board->slot;
759
760 switch(ndev->dr_hw) {
761 case NUBUS_DRHW_APPLE_MDC:
Finn Thain89c223a2008-11-18 20:40:40 +0100762 strcpy(macfb_fix.id, "Mac Disp. Card");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 macfb_setpalette = mdc_setpalette;
764 macfb_defined.activate = FB_ACTIVATE_NOW;
765 break;
766 case NUBUS_DRHW_APPLE_TFB:
Finn Thain89c223a2008-11-18 20:40:40 +0100767 strcpy(macfb_fix.id, "Toby");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 macfb_setpalette = toby_setpalette;
769 macfb_defined.activate = FB_ACTIVATE_NOW;
770 break;
771 case NUBUS_DRHW_APPLE_JET:
Finn Thain89c223a2008-11-18 20:40:40 +0100772 strcpy(macfb_fix.id, "Jet");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 macfb_setpalette = jet_setpalette;
774 macfb_defined.activate = FB_ACTIVATE_NOW;
775 break;
776 default:
Finn Thain89c223a2008-11-18 20:40:40 +0100777 strcpy(macfb_fix.id, "Generic NuBus");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 break;
779 }
780 }
781
782 /* If it's not a NuBus card, it must be internal video */
783 /* FIXME: this function is getting way too big. (this driver
784 is too...) */
785 if (!video_is_nubus)
786 switch( mac_bi_data.id )
787 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 /* Valkyrie Quadras */
789 case MAC_MODEL_Q630:
790 /* I'm not sure about this one */
791 case MAC_MODEL_P588:
Finn Thain89c223a2008-11-18 20:40:40 +0100792 strcpy(macfb_fix.id, "Valkyrie");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 macfb_setpalette = valkyrie_setpalette;
794 macfb_defined.activate = FB_ACTIVATE_NOW;
795 valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
796 break;
797
798 /* DAFB Quadras */
799 /* Note: these first four have the v7 DAFB, which is
800 known to be rather unlike the ones used in the
801 other models */
802 case MAC_MODEL_P475:
803 case MAC_MODEL_P475F:
804 case MAC_MODEL_P575:
805 case MAC_MODEL_Q605:
806
807 case MAC_MODEL_Q800:
808 case MAC_MODEL_Q650:
809 case MAC_MODEL_Q610:
810 case MAC_MODEL_C650:
811 case MAC_MODEL_C610:
812 case MAC_MODEL_Q700:
813 case MAC_MODEL_Q900:
814 case MAC_MODEL_Q950:
Finn Thain89c223a2008-11-18 20:40:40 +0100815 strcpy(macfb_fix.id, "DAFB");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 macfb_setpalette = dafb_setpalette;
817 macfb_defined.activate = FB_ACTIVATE_NOW;
818 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
819 break;
820
821 /* LC II uses the V8 framebuffer */
822 case MAC_MODEL_LCII:
Finn Thain89c223a2008-11-18 20:40:40 +0100823 strcpy(macfb_fix.id, "V8");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 macfb_setpalette = v8_brazil_setpalette;
825 macfb_defined.activate = FB_ACTIVATE_NOW;
826 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
827 break;
828
829 /* IIvi, IIvx use the "Brazil" framebuffer (which is
830 very much like the V8, it seems, and probably uses
831 the same DAC) */
832 case MAC_MODEL_IIVI:
833 case MAC_MODEL_IIVX:
834 case MAC_MODEL_P600:
Finn Thain89c223a2008-11-18 20:40:40 +0100835 strcpy(macfb_fix.id, "Brazil");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 macfb_setpalette = v8_brazil_setpalette;
837 macfb_defined.activate = FB_ACTIVATE_NOW;
838 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
839 break;
840
841 /* LC III (and friends) use the Sonora framebuffer */
842 /* Incidentally this is also used in the non-AV models
843 of the x100 PowerMacs */
844 /* These do in fact seem to use the same DAC interface
845 as the LC II. */
846 case MAC_MODEL_LCIII:
847 case MAC_MODEL_P520:
848 case MAC_MODEL_P550:
849 case MAC_MODEL_P460:
850 macfb_setpalette = v8_brazil_setpalette;
851 macfb_defined.activate = FB_ACTIVATE_NOW;
Finn Thain89c223a2008-11-18 20:40:40 +0100852 strcpy(macfb_fix.id, "Sonora");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
854 break;
855
856 /* IIci and IIsi use the infamous RBV chip
857 (the IIsi is just a rebadged and crippled
858 IIci in a different case, BTW) */
859 case MAC_MODEL_IICI:
860 case MAC_MODEL_IISI:
861 macfb_setpalette = rbv_setpalette;
862 macfb_defined.activate = FB_ACTIVATE_NOW;
Finn Thain89c223a2008-11-18 20:40:40 +0100863 strcpy(macfb_fix.id, "RBV");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
865 break;
866
867 /* AVs use the Civic framebuffer */
868 case MAC_MODEL_Q840:
869 case MAC_MODEL_C660:
870 macfb_setpalette = civic_setpalette;
871 macfb_defined.activate = FB_ACTIVATE_NOW;
Finn Thain89c223a2008-11-18 20:40:40 +0100872 strcpy(macfb_fix.id, "Civic");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
874 break;
875
876
877 /* Write a setpalette function for your machine, then
878 you can add something similar here. These are
879 grouped by classes of video chipsets. Some of this
880 information is from the VideoToolbox "Bugs" web
881 page at
882 http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
883
884 /* Assorted weirdos */
885 /* We think this may be like the LC II */
886 case MAC_MODEL_LC:
887 if (vidtest) {
888 macfb_setpalette = v8_brazil_setpalette;
889 macfb_defined.activate = FB_ACTIVATE_NOW;
890 v8_brazil_cmap_regs =
891 ioremap(DAC_BASE, 0x1000);
892 }
Finn Thain89c223a2008-11-18 20:40:40 +0100893 strcpy(macfb_fix.id, "LC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 break;
895 /* We think this may be like the LC II */
896 case MAC_MODEL_CCL:
897 if (vidtest) {
898 macfb_setpalette = v8_brazil_setpalette;
899 macfb_defined.activate = FB_ACTIVATE_NOW;
900 v8_brazil_cmap_regs =
901 ioremap(DAC_BASE, 0x1000);
902 }
Finn Thain89c223a2008-11-18 20:40:40 +0100903 strcpy(macfb_fix.id, "Color Classic");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 break;
905
906 /* And we *do* mean "weirdos" */
907 case MAC_MODEL_TV:
Finn Thain89c223a2008-11-18 20:40:40 +0100908 strcpy(macfb_fix.id, "Mac TV");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 break;
910
911 /* These don't have colour, so no need to worry */
912 case MAC_MODEL_SE30:
913 case MAC_MODEL_CLII:
Finn Thain89c223a2008-11-18 20:40:40 +0100914 strcpy(macfb_fix.id, "Monochrome");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 break;
916
917 /* Powerbooks are particularly difficult. Many of
918 them have separate framebuffers for external and
919 internal video, which is admittedly pretty cool,
920 but will be a bit of a headache to support here.
921 Also, many of them are grayscale, and we don't
922 really support that. */
923
924 case MAC_MODEL_PB140:
925 case MAC_MODEL_PB145:
926 case MAC_MODEL_PB170:
Finn Thain89c223a2008-11-18 20:40:40 +0100927 strcpy(macfb_fix.id, "DDC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 break;
929
930 /* Internal is GSC, External (if present) is ViSC */
931 case MAC_MODEL_PB150: /* no external video */
932 case MAC_MODEL_PB160:
933 case MAC_MODEL_PB165:
934 case MAC_MODEL_PB180:
935 case MAC_MODEL_PB210:
936 case MAC_MODEL_PB230:
Finn Thain89c223a2008-11-18 20:40:40 +0100937 strcpy(macfb_fix.id, "GSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 break;
939
940 /* Internal is TIM, External is ViSC */
941 case MAC_MODEL_PB165C:
942 case MAC_MODEL_PB180C:
Finn Thain89c223a2008-11-18 20:40:40 +0100943 strcpy(macfb_fix.id, "TIM");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 break;
945
946 /* Internal is CSC, External is Keystone+Ariel. */
947 case MAC_MODEL_PB190: /* external video is optional */
948 case MAC_MODEL_PB520:
949 case MAC_MODEL_PB250:
950 case MAC_MODEL_PB270C:
951 case MAC_MODEL_PB280:
952 case MAC_MODEL_PB280C:
953 macfb_setpalette = csc_setpalette;
954 macfb_defined.activate = FB_ACTIVATE_NOW;
Finn Thain89c223a2008-11-18 20:40:40 +0100955 strcpy(macfb_fix.id, "CSC");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
957 break;
958
959 default:
Finn Thain89c223a2008-11-18 20:40:40 +0100960 strcpy(macfb_fix.id, "Unknown");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 break;
962 }
963
964 fb_info.fbops = &macfb_ops;
965 fb_info.var = macfb_defined;
966 fb_info.fix = macfb_fix;
967 fb_info.pseudo_palette = pseudo_palette;
968 fb_info.flags = FBINFO_DEFAULT;
969
Finn Thain89c223a2008-11-18 20:40:40 +0100970 err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
971 if (err)
972 goto fail_unmap;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Al Viroed1705a2006-01-12 01:06:39 -0800974 err = register_framebuffer(&fb_info);
Finn Thain89c223a2008-11-18 20:40:40 +0100975 if (err)
976 goto fail_dealloc;
977
978 printk("fb%d: %s frame buffer device\n",
979 fb_info.node, fb_info.fix.id);
980 return 0;
981
982fail_dealloc:
983 fb_dealloc_cmap(&fb_info.cmap);
984fail_unmap:
985 iounmap(fb_info.screen_base);
986 iounmap_macfb();
Al Viroed1705a2006-01-12 01:06:39 -0800987 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988}
989
990module_init(macfb_init);
991MODULE_LICENSE("GPL");