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