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