1/* 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>
23#include <linux/errno.h>
24#include <linux/string.h>
25#include <linux/mm.h>
26#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;
173static u32 pseudo_palette[17];
174static 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	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
400static int civic_setpalette (unsigned int regno, unsigned int red,
401			     unsigned int green, unsigned int blue,
402			     struct fb_info *info)
403{
404	static int lastreg = -1;
405	unsigned long flags;
406	int clut_status;
407
408	if (info->var.bits_per_pixel > 8) return 1; /* failsafe */
409
410	red   >>= 8;
411	green >>= 8;
412	blue  >>= 8;
413
414	local_irq_save(flags);
415
416	/*
417	 * Set the register address
418	 */
419	nubus_writeb(regno, &civic_cmap_regs->addr); nop();
420
421	/*
422	 * Wait for VBL interrupt here;
423	 * They're usually not enabled from Penguin, so we won't check
424	 */
425
426	/*
427	 * Grab a status word and do some checking;
428	 * Then finally write the clut!
429	 */
430	clut_status =  nubus_readb(&civic_cmap_regs->status2);
431
432	if ((clut_status & 0x0008) == 0)
433	{
434
435		nubus_writeb(  red, &civic_cmap_regs->lut); nop();
436		nubus_writeb(green, &civic_cmap_regs->lut); nop();
437		nubus_writeb( blue, &civic_cmap_regs->lut); nop();
438		nubus_writeb( 0x00, &civic_cmap_regs->lut); nop();
439	}
440	else
441	{
442		unsigned char junk;
443
444		junk = nubus_readb(&civic_cmap_regs->lut); nop();
445		junk = nubus_readb(&civic_cmap_regs->lut); nop();
446		junk = nubus_readb(&civic_cmap_regs->lut); nop();
447		junk = nubus_readb(&civic_cmap_regs->lut); nop();
448
449		if ((clut_status & 0x000D) != 0)
450		{
451			nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
452			nubus_writeb(0x00, &civic_cmap_regs->lut); nop();
453		}
454
455		nubus_writeb(  red, &civic_cmap_regs->lut); nop();
456		nubus_writeb(green, &civic_cmap_regs->lut); nop();
457		nubus_writeb( blue, &civic_cmap_regs->lut); nop();
458		nubus_writeb( junk, &civic_cmap_regs->lut); nop();
459	}
460
461	local_irq_restore(flags);
462	lastreg = regno;
463	return 0;
464}
465
466/*
467 * The CSC is the framebuffer on the PowerBook 190 series
468 * (and the 5300 too, but that's a PowerMac). This function
469 * brought to you in part by the ECSC driver for MkLinux.
470 */
471
472static int csc_setpalette (unsigned int regno, unsigned int red,
473			   unsigned int green, unsigned int blue,
474			   struct fb_info *info)
475{
476	mdelay(1);
477	csc_cmap_regs->clut_waddr = regno;
478	csc_cmap_regs->clut_data = red;
479	csc_cmap_regs->clut_data = green;
480	csc_cmap_regs->clut_data = blue;
481	return 0;
482}
483
484static int macfb_setcolreg(unsigned regno, unsigned red, unsigned green,
485			   unsigned blue, unsigned transp,
486			   struct fb_info *fb_info)
487{
488	/*
489	 *  Set a single color register. The values supplied are
490	 *  already rounded down to the hardware's capabilities
491	 *  (according to the entries in the `var' structure). Return
492	 *  != 0 for invalid regno.
493	 */
494
495	if (regno >= fb_info->cmap.len)
496		return 1;
497
498	switch (fb_info->var.bits_per_pixel) {
499	case 1:
500		/* We shouldn't get here */
501		break;
502	case 2:
503	case 4:
504	case 8:
505		if (macfb_setpalette)
506			macfb_setpalette(regno, red, green, blue, fb_info);
507		else
508			return 1;
509		break;
510	case 16:
511		if (fb_info->var.red.offset == 10) {
512			/* 1:5:5:5 */
513			((u32*) (fb_info->pseudo_palette))[regno] =
514					((red   & 0xf800) >>  1) |
515					((green & 0xf800) >>  6) |
516					((blue  & 0xf800) >> 11) |
517					((transp != 0) << 15);
518		} else {
519			/* 0:5:6:5 */
520			((u32*) (fb_info->pseudo_palette))[regno] =
521					((red   & 0xf800)      ) |
522					((green & 0xfc00) >>  5) |
523					((blue  & 0xf800) >> 11);
524		}
525		break;
526		/* I'm pretty sure that one or the other of these
527		   doesn't exist on 68k Macs */
528	case 24:
529		red   >>= 8;
530		green >>= 8;
531		blue  >>= 8;
532		((u32 *)(fb_info->pseudo_palette))[regno] =
533			(red   << fb_info->var.red.offset)   |
534			(green << fb_info->var.green.offset) |
535			(blue  << fb_info->var.blue.offset);
536		break;
537	case 32:
538		red   >>= 8;
539		green >>= 8;
540		blue  >>= 8;
541		((u32 *)(fb_info->pseudo_palette))[regno] =
542			(red   << fb_info->var.red.offset)   |
543			(green << fb_info->var.green.offset) |
544			(blue  << fb_info->var.blue.offset);
545		break;
546    }
547    return 0;
548}
549
550static struct fb_ops macfb_ops = {
551	.owner		= THIS_MODULE,
552	.fb_setcolreg	= macfb_setcolreg,
553	.fb_fillrect	= cfb_fillrect,
554	.fb_copyarea	= cfb_copyarea,
555	.fb_imageblit	= cfb_imageblit,
556};
557
558void __init macfb_setup(char *options)
559{
560	char *this_opt;
561
562	if (!options || !*options)
563		return;
564
565	while ((this_opt = strsep(&options, ",")) != NULL) {
566		if (!*this_opt) continue;
567
568		if (! strcmp(this_opt, "inverse"))
569			inverse=1;
570		/* This means "turn on experimental CLUT code" */
571		else if (!strcmp(this_opt, "vidtest"))
572			vidtest=1;
573	}
574}
575
576static void __init iounmap_macfb(void)
577{
578	if (valkyrie_cmap_regs)
579		iounmap(valkyrie_cmap_regs);
580	if (dafb_cmap_regs)
581		iounmap(dafb_cmap_regs);
582	if (v8_brazil_cmap_regs)
583		iounmap(v8_brazil_cmap_regs);
584	if (rbv_cmap_regs)
585		iounmap(rbv_cmap_regs);
586	if (civic_cmap_regs)
587		iounmap(civic_cmap_regs);
588	if (csc_cmap_regs)
589		iounmap(csc_cmap_regs);
590}
591
592static int __init macfb_init(void)
593{
594	int video_cmap_len, video_is_nubus = 0;
595	struct nubus_dev* ndev = NULL;
596	char *option = NULL;
597	int err;
598
599	if (fb_get_options("macfb", &option))
600		return -ENODEV;
601	macfb_setup(option);
602
603	if (!MACH_IS_MAC)
604		return -ENODEV;
605
606	/* There can only be one internal video controller anyway so
607	   we're not too worried about this */
608	macfb_defined.xres = mac_bi_data.dimensions & 0xFFFF;
609	macfb_defined.yres = mac_bi_data.dimensions >> 16;
610	macfb_defined.bits_per_pixel = mac_bi_data.videodepth;
611	macfb_fix.line_length = mac_bi_data.videorow;
612	macfb_fix.smem_len = macfb_fix.line_length * macfb_defined.yres;
613	/* Note: physical address (since 2.1.127) */
614	macfb_fix.smem_start = mac_bi_data.videoaddr;
615	/* This is actually redundant with the initial mappings.
616	   However, there are some non-obvious aspects to the way
617	   those mappings are set up, so this is in fact the safest
618	   way to ensure that this driver will work on every possible
619	   Mac */
620	fb_info.screen_base = ioremap(mac_bi_data.videoaddr, macfb_fix.smem_len);
621
622	printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
623	       macfb_fix.smem_start, fb_info.screen_base, macfb_fix.smem_len/1024);
624	printk("macfb: mode is %dx%dx%d, linelength=%d\n",
625	       macfb_defined.xres, macfb_defined.yres, macfb_defined.bits_per_pixel, macfb_fix.line_length);
626
627	/*
628	 *	Fill in the available video resolution
629	 */
630
631	macfb_defined.xres_virtual   = macfb_defined.xres;
632	macfb_defined.yres_virtual   = macfb_defined.yres;
633	macfb_defined.height = PIXEL_TO_MM(macfb_defined.yres);
634	macfb_defined.width  = PIXEL_TO_MM(macfb_defined.xres);
635
636	printk("macfb: scrolling: redraw\n");
637	macfb_defined.yres_virtual = macfb_defined.yres;
638
639	/* some dummy values for timing to make fbset happy */
640	macfb_defined.pixclock     = 10000000 / macfb_defined.xres * 1000 / macfb_defined.yres;
641	macfb_defined.left_margin  = (macfb_defined.xres / 8) & 0xf8;
642	macfb_defined.hsync_len    = (macfb_defined.xres / 8) & 0xf8;
643
644	switch (macfb_defined.bits_per_pixel) {
645	case 1:
646		macfb_defined.red.length = macfb_defined.bits_per_pixel;
647		macfb_defined.green.length = macfb_defined.bits_per_pixel;
648		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
649		video_cmap_len = 0;
650		macfb_fix.visual = FB_VISUAL_MONO01;
651		break;
652	case 2:
653	case 4:
654	case 8:
655		macfb_defined.red.length = macfb_defined.bits_per_pixel;
656		macfb_defined.green.length = macfb_defined.bits_per_pixel;
657		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
658		video_cmap_len = 1 << macfb_defined.bits_per_pixel;
659		macfb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
660		break;
661	case 16:
662		macfb_defined.transp.offset = 15;
663		macfb_defined.transp.length = 1;
664		macfb_defined.red.offset = 10;
665		macfb_defined.red.length = 5;
666		macfb_defined.green.offset = 5;
667		macfb_defined.green.length = 5;
668		macfb_defined.blue.offset = 0;
669		macfb_defined.blue.length = 5;
670		printk("macfb: directcolor: "
671		       "size=1:5:5:5, shift=15:10:5:0\n");
672		video_cmap_len = 16;
673		/* Should actually be FB_VISUAL_DIRECTCOLOR, but this
674		   works too */
675		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
676		break;
677	case 24:
678	case 32:
679		macfb_defined.red.offset = 16;
680		macfb_defined.red.length = 8;
681		macfb_defined.green.offset = 8;
682		macfb_defined.green.length = 8;
683		macfb_defined.blue.offset = 0;
684		macfb_defined.blue.length = 8;
685		printk("macfb: truecolor: "
686		       "size=0:8:8:8, shift=0:16:8:0\n");
687		video_cmap_len = 16;
688		macfb_fix.visual = FB_VISUAL_TRUECOLOR;
689	default:
690		video_cmap_len = 0;
691		macfb_fix.visual = FB_VISUAL_MONO01;
692		printk("macfb: unknown or unsupported bit depth: %d\n", macfb_defined.bits_per_pixel);
693		break;
694	}
695
696	/* Hardware dependent stuff */
697	/*  We take a wild guess that if the video physical address is
698	 *  in nubus slot space, that the nubus card is driving video.
699	 *  Penguin really ought to tell us whether we are using internal
700	 *  video or not.
701	 */
702	/* Hopefully we only find one of them.  Otherwise our NuBus
703           code is really broken :-) */
704
705	while ((ndev = nubus_find_type(NUBUS_CAT_DISPLAY, NUBUS_TYPE_VIDEO, ndev))
706		!= NULL)
707	{
708		if (!(mac_bi_data.videoaddr >= ndev->board->slot_addr
709		      && (mac_bi_data.videoaddr <
710			  (unsigned long)nubus_slot_addr(ndev->board->slot+1))))
711			continue;
712		video_is_nubus = 1;
713		/* We should probably just use the slot address... */
714		video_slot = ndev->board->slot;
715
716		switch(ndev->dr_hw) {
717		case NUBUS_DRHW_APPLE_MDC:
718			strcat( macfb_fix.id, "Display Card" );
719			macfb_setpalette = mdc_setpalette;
720			macfb_defined.activate = FB_ACTIVATE_NOW;
721			break;
722		case NUBUS_DRHW_APPLE_TFB:
723			strcat( macfb_fix.id, "Toby" );
724			macfb_setpalette = toby_setpalette;
725			macfb_defined.activate = FB_ACTIVATE_NOW;
726			break;
727		case NUBUS_DRHW_APPLE_JET:
728			strcat( macfb_fix.id, "Jet");
729			macfb_setpalette = jet_setpalette;
730			macfb_defined.activate = FB_ACTIVATE_NOW;
731			break;
732		default:
733			strcat( macfb_fix.id, "Generic NuBus" );
734			break;
735		}
736	}
737
738	/* If it's not a NuBus card, it must be internal video */
739	if (!video_is_nubus)
740		switch( mac_bi_data.id )
741		{
742			/* These don't have onboard video.  Eventually, we may
743			   be able to write separate framebuffer drivers for
744			   them (tobyfb.c, hiresfb.c, etc, etc) */
745		case MAC_MODEL_II:
746		case MAC_MODEL_IIX:
747		case MAC_MODEL_IICX:
748		case MAC_MODEL_IIFX:
749			strcat( macfb_fix.id, "Generic NuBus" );
750			break;
751
752			/* Valkyrie Quadras */
753		case MAC_MODEL_Q630:
754			/* I'm not sure about this one */
755		case MAC_MODEL_P588:
756			strcat( macfb_fix.id, "Valkyrie built-in" );
757			macfb_setpalette = valkyrie_setpalette;
758			macfb_defined.activate = FB_ACTIVATE_NOW;
759			valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000);
760			break;
761
762			/* DAFB Quadras */
763			/* Note: these first four have the v7 DAFB, which is
764			   known to be rather unlike the ones used in the
765			   other models */
766		case MAC_MODEL_P475:
767		case MAC_MODEL_P475F:
768		case MAC_MODEL_P575:
769		case MAC_MODEL_Q605:
770
771		case MAC_MODEL_Q800:
772		case MAC_MODEL_Q650:
773		case MAC_MODEL_Q610:
774		case MAC_MODEL_C650:
775		case MAC_MODEL_C610:
776		case MAC_MODEL_Q700:
777		case MAC_MODEL_Q900:
778		case MAC_MODEL_Q950:
779			strcat( macfb_fix.id, "DAFB built-in" );
780			macfb_setpalette = dafb_setpalette;
781			macfb_defined.activate = FB_ACTIVATE_NOW;
782			dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
783			break;
784
785			/* LC II uses the V8 framebuffer */
786		case MAC_MODEL_LCII:
787			strcat( macfb_fix.id, "V8 built-in" );
788			macfb_setpalette = v8_brazil_setpalette;
789			macfb_defined.activate = FB_ACTIVATE_NOW;
790			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
791			break;
792
793			/* IIvi, IIvx use the "Brazil" framebuffer (which is
794			   very much like the V8, it seems, and probably uses
795			   the same DAC) */
796		case MAC_MODEL_IIVI:
797		case MAC_MODEL_IIVX:
798		case MAC_MODEL_P600:
799			strcat( macfb_fix.id, "Brazil built-in" );
800			macfb_setpalette = v8_brazil_setpalette;
801			macfb_defined.activate = FB_ACTIVATE_NOW;
802			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
803			break;
804
805			/* LC III (and friends) use the Sonora framebuffer */
806			/* Incidentally this is also used in the non-AV models
807			   of the x100 PowerMacs */
808			/* These do in fact seem to use the same DAC interface
809			   as the LC II. */
810		case MAC_MODEL_LCIII:
811		case MAC_MODEL_P520:
812		case MAC_MODEL_P550:
813		case MAC_MODEL_P460:
814			macfb_setpalette = v8_brazil_setpalette;
815			macfb_defined.activate = FB_ACTIVATE_NOW;
816			strcat( macfb_fix.id, "Sonora built-in" );
817			v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
818			break;
819
820			/* IIci and IIsi use the infamous RBV chip
821                           (the IIsi is just a rebadged and crippled
822                           IIci in a different case, BTW) */
823		case MAC_MODEL_IICI:
824		case MAC_MODEL_IISI:
825			macfb_setpalette = rbv_setpalette;
826			macfb_defined.activate = FB_ACTIVATE_NOW;
827			strcat( macfb_fix.id, "RBV built-in" );
828			rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
829			break;
830
831			/* AVs use the Civic framebuffer */
832		case MAC_MODEL_Q840:
833		case MAC_MODEL_C660:
834			macfb_setpalette = civic_setpalette;
835			macfb_defined.activate = FB_ACTIVATE_NOW;
836			strcat( macfb_fix.id, "Civic built-in" );
837			civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
838			break;
839
840
841			/* Write a setpalette function for your machine, then
842			   you can add something similar here.  These are
843			   grouped by classes of video chipsets.  Some of this
844			   information is from the VideoToolbox "Bugs" web
845			   page at
846			   http://rajsky.psych.nyu.edu/Tips/VideoBugs.html */
847
848			/* Assorted weirdos */
849			/* We think this may be like the LC II */
850		case MAC_MODEL_LC:
851			if (vidtest) {
852				macfb_setpalette = v8_brazil_setpalette;
853				macfb_defined.activate = FB_ACTIVATE_NOW;
854				v8_brazil_cmap_regs =
855					ioremap(DAC_BASE, 0x1000);
856			}
857			strcat( macfb_fix.id, "LC built-in" );
858			break;
859			/* We think this may be like the LC II */
860		case MAC_MODEL_CCL:
861			if (vidtest) {
862				macfb_setpalette = v8_brazil_setpalette;
863				macfb_defined.activate = FB_ACTIVATE_NOW;
864				v8_brazil_cmap_regs =
865					ioremap(DAC_BASE, 0x1000);
866			}
867			strcat( macfb_fix.id, "Color Classic built-in" );
868			break;
869
870			/* And we *do* mean "weirdos" */
871		case MAC_MODEL_TV:
872			strcat( macfb_fix.id, "Mac TV built-in" );
873			break;
874
875			/* These don't have colour, so no need to worry */
876		case MAC_MODEL_SE30:
877		case MAC_MODEL_CLII:
878			strcat( macfb_fix.id, "Monochrome built-in" );
879			break;
880
881			/* Powerbooks are particularly difficult.  Many of
882			   them have separate framebuffers for external and
883			   internal video, which is admittedly pretty cool,
884			   but will be a bit of a headache to support here.
885			   Also, many of them are grayscale, and we don't
886			   really support that. */
887
888		case MAC_MODEL_PB140:
889		case MAC_MODEL_PB145:
890		case MAC_MODEL_PB170:
891			strcat( macfb_fix.id, "DDC built-in" );
892			break;
893
894			/* Internal is GSC, External (if present) is ViSC */
895		case MAC_MODEL_PB150:	/* no external video */
896		case MAC_MODEL_PB160:
897		case MAC_MODEL_PB165:
898		case MAC_MODEL_PB180:
899		case MAC_MODEL_PB210:
900		case MAC_MODEL_PB230:
901			strcat( macfb_fix.id, "GSC built-in" );
902			break;
903
904			/* Internal is TIM, External is ViSC */
905		case MAC_MODEL_PB165C:
906		case MAC_MODEL_PB180C:
907			strcat( macfb_fix.id, "TIM built-in" );
908			break;
909
910			/* Internal is CSC, External is Keystone+Ariel. */
911		case MAC_MODEL_PB190:	/* external video is optional */
912		case MAC_MODEL_PB520:
913		case MAC_MODEL_PB250:
914		case MAC_MODEL_PB270C:
915		case MAC_MODEL_PB280:
916		case MAC_MODEL_PB280C:
917			macfb_setpalette = csc_setpalette;
918			macfb_defined.activate = FB_ACTIVATE_NOW;
919			strcat( macfb_fix.id, "CSC built-in" );
920			csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
921			break;
922
923		default:
924			strcat( macfb_fix.id, "Unknown/Unsupported built-in" );
925			break;
926		}
927
928	fb_info.fbops		= &macfb_ops;
929	fb_info.var		= macfb_defined;
930	fb_info.fix		= macfb_fix;
931	fb_info.pseudo_palette	= pseudo_palette;
932	fb_info.flags		= FBINFO_DEFAULT;
933
934	fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
935
936	err = register_framebuffer(&fb_info);
937	if (!err)
938		printk("fb%d: %s frame buffer device\n",
939		       fb_info.node, fb_info.fix.id);
940	else {
941		iounmap(fb_info.screen_base);
942		iounmap_macfb();
943	}
944	return err;
945}
946
947module_init(macfb_init);
948MODULE_LICENSE("GPL");
949