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