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