linux-old/drivers/video/cgfourteenfb.c
<<
>>
Prefs
   1/* $Id: cgfourteenfb.c,v 1.11 2001/09/19 00:04:33 davem Exp $
   2 * cgfourteenfb.c: CGfourteen frame buffer driver
   3 *
   4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
   5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/sched.h>
  10#include <linux/kernel.h>
  11#include <linux/errno.h>
  12#include <linux/string.h>
  13#include <linux/mm.h>
  14#include <linux/tty.h>
  15#include <linux/slab.h>
  16#include <linux/vmalloc.h>
  17#include <linux/delay.h>
  18#include <linux/interrupt.h>
  19#include <linux/fb.h>
  20#include <linux/init.h>
  21#include <linux/selection.h>
  22
  23#include <video/sbusfb.h>
  24#include <asm/io.h>
  25#include <asm/pgtable.h>
  26#include <asm/uaccess.h>
  27
  28#include <video/fbcon-cfb8.h>
  29
  30#define CG14_MCR_INTENABLE_SHIFT        7
  31#define CG14_MCR_INTENABLE_MASK         0x80
  32#define CG14_MCR_VIDENABLE_SHIFT        6
  33#define CG14_MCR_VIDENABLE_MASK         0x40
  34#define CG14_MCR_PIXMODE_SHIFT          4
  35#define CG14_MCR_PIXMODE_MASK           0x30
  36#define CG14_MCR_TMR_SHIFT              2
  37#define CG14_MCR_TMR_MASK               0x0c
  38#define CG14_MCR_TMENABLE_SHIFT         1
  39#define CG14_MCR_TMENABLE_MASK          0x02
  40#define CG14_MCR_RESET_SHIFT            0
  41#define CG14_MCR_RESET_MASK             0x01
  42#define CG14_REV_REVISION_SHIFT         4
  43#define CG14_REV_REVISION_MASK          0xf0
  44#define CG14_REV_IMPL_SHIFT             0
  45#define CG14_REV_IMPL_MASK              0x0f
  46#define CG14_VBR_FRAMEBASE_SHIFT        12
  47#define CG14_VBR_FRAMEBASE_MASK         0x00fff000
  48#define CG14_VMCR1_SETUP_SHIFT          0
  49#define CG14_VMCR1_SETUP_MASK           0x000001ff
  50#define CG14_VMCR1_VCONFIG_SHIFT        9
  51#define CG14_VMCR1_VCONFIG_MASK         0x00000e00
  52#define CG14_VMCR2_REFRESH_SHIFT        0
  53#define CG14_VMCR2_REFRESH_MASK         0x00000001
  54#define CG14_VMCR2_TESTROWCNT_SHIFT     1
  55#define CG14_VMCR2_TESTROWCNT_MASK      0x00000002
  56#define CG14_VMCR2_FBCONFIG_SHIFT       2
  57#define CG14_VMCR2_FBCONFIG_MASK        0x0000000c
  58#define CG14_VCR_REFRESHREQ_SHIFT       0
  59#define CG14_VCR_REFRESHREQ_MASK        0x000003ff
  60#define CG14_VCR1_REFRESHENA_SHIFT      10
  61#define CG14_VCR1_REFRESHENA_MASK       0x00000400
  62#define CG14_VCA_CAD_SHIFT              0
  63#define CG14_VCA_CAD_MASK               0x000003ff
  64#define CG14_VCA_VERS_SHIFT             10
  65#define CG14_VCA_VERS_MASK              0x00000c00
  66#define CG14_VCA_RAMSPEED_SHIFT         12
  67#define CG14_VCA_RAMSPEED_MASK          0x00001000
  68#define CG14_VCA_8MB_SHIFT              13
  69#define CG14_VCA_8MB_MASK               0x00002000
  70
  71#define CG14_MCR_PIXMODE_8              0
  72#define CG14_MCR_PIXMODE_16             2
  73#define CG14_MCR_PIXMODE_32             3
  74
  75MODULE_LICENSE("GPL");
  76
  77struct cg14_regs{
  78        volatile u8 mcr;        /* Master Control Reg */
  79        volatile u8 ppr;        /* Packed Pixel Reg */
  80        volatile u8 tms[2];     /* Test Mode Status Regs */
  81        volatile u8 msr;        /* Master Status Reg */
  82        volatile u8 fsr;        /* Fault Status Reg */
  83        volatile u8 rev;        /* Revision & Impl */
  84        volatile u8 ccr;        /* Clock Control Reg */
  85        volatile u32 tmr;       /* Test Mode Read Back */
  86        volatile u8 mod;        /* Monitor Operation Data Reg */
  87        volatile u8 acr;        /* Aux Control */
  88        u8 xxx0[6];
  89        volatile u16 hct;       /* Hor Counter */
  90        volatile u16 vct;       /* Vert Counter */
  91        volatile u16 hbs;       /* Hor Blank Start */
  92        volatile u16 hbc;       /* Hor Blank Clear */
  93        volatile u16 hss;       /* Hor Sync Start */
  94        volatile u16 hsc;       /* Hor Sync Clear */
  95        volatile u16 csc;       /* Composite Sync Clear */
  96        volatile u16 vbs;       /* Vert Blank Start */
  97        volatile u16 vbc;       /* Vert Blank Clear */
  98        volatile u16 vss;       /* Vert Sync Start */
  99        volatile u16 vsc;       /* Vert Sync Clear */
 100        volatile u16 xcs;
 101        volatile u16 xcc;
 102        volatile u16 fsa;       /* Fault Status Address */
 103        volatile u16 adr;       /* Address Registers */
 104        u8 xxx1[0xce];
 105        volatile u8 pcg[0x100]; /* Pixel Clock Generator */
 106        volatile u32 vbr;       /* Frame Base Row */
 107        volatile u32 vmcr;      /* VBC Master Control */
 108        volatile u32 vcr;       /* VBC refresh */
 109        volatile u32 vca;       /* VBC Config */
 110};
 111
 112#define CG14_CCR_ENABLE 0x04
 113#define CG14_CCR_SELECT 0x02    /* HW/Full screen */
 114
 115struct cg14_cursor {
 116        volatile u32 cpl0[32];  /* Enable plane 0 */
 117        volatile u32 cpl1[32];  /* Color selection plane */
 118        volatile u8 ccr;        /* Cursor Control Reg */
 119        u8 xxx0[3];
 120        volatile u16 cursx;     /* Cursor x,y position */
 121        volatile u16 cursy;     /* Cursor x,y position */
 122        volatile u32 color0;
 123        volatile u32 color1;
 124        u32 xxx1[0x1bc];
 125        volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */
 126        volatile u32 cpl1i[32]; /* Color selection autoinc */
 127};
 128
 129struct cg14_dac {
 130        volatile u8 addr;       /* Address Register */
 131        u8 xxx0[255];
 132        volatile u8 glut;       /* Gamma table */
 133        u8 xxx1[255];
 134        volatile u8 select;     /* Register Select */
 135        u8 xxx2[255];
 136        volatile u8 mode;       /* Mode Register */
 137};
 138
 139struct cg14_xlut{
 140        volatile u8 x_xlut [256];
 141        volatile u8 x_xlutd [256];
 142        u8 xxx0[0x600];
 143        volatile u8 x_xlut_inc [256];
 144        volatile u8 x_xlutd_inc [256];
 145};
 146
 147/* Color look up table (clut) */
 148/* Each one of these arrays hold the color lookup table (for 256
 149 * colors) for each MDI page (I assume then there should be 4 MDI
 150 * pages, I still wonder what they are.  I have seen NeXTStep split
 151 * the screen in four parts, while operating in 24 bits mode.  Each
 152 * integer holds 4 values: alpha value (transparency channel, thanks
 153 * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
 154 *
 155 * I currently use the clut instead of the Xlut
 156 */
 157struct cg14_clut {
 158        u32 c_clut [256];
 159        u32 c_clutd [256];    /* i wonder what the 'd' is for */
 160        u32 c_clut_inc [256];
 161        u32 c_clutd_inc [256];
 162};
 163
 164static struct sbus_mmap_map cg14_mmap_map[] __initdata = {
 165        { CG14_REGS,            0x80000000,             0x1000              },
 166        { CG14_XLUT,            0x80003000,             0x1000              },
 167        { CG14_CLUT1,           0x80004000,             0x1000              },
 168        { CG14_CLUT2,           0x80005000,             0x1000              },
 169        { CG14_CLUT3,           0x80006000,             0x1000              },
 170        { CG3_MMAP_OFFSET - 
 171          0x7000,               0x80000000,             0x7000              },
 172        { CG3_MMAP_OFFSET,      0x00000000,             SBUS_MMAP_FBSIZE(1) },
 173        { MDI_CURSOR_MAP,       0x80001000,             0x1000              },
 174        { MDI_CHUNKY_BGR_MAP,   0x01000000,             0x400000            },
 175        { MDI_PLANAR_X16_MAP,   0x02000000,             0x200000            },
 176        { MDI_PLANAR_C16_MAP,   0x02800000,             0x200000            },
 177        { MDI_PLANAR_X32_MAP,   0x03000000,             0x100000            },
 178        { MDI_PLANAR_B32_MAP,   0x03400000,             0x100000            },
 179        { MDI_PLANAR_G32_MAP,   0x03800000,             0x100000            },
 180        { MDI_PLANAR_R32_MAP,   0x03c00000,             0x100000            },
 181        { 0,                    0,                      0                   }
 182};
 183
 184static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p,
 185                           int index, int count)
 186{
 187        struct cg14_clut *clut = fb->s.cg14.clut;
 188        unsigned long flags;
 189                
 190        spin_lock_irqsave(&fb->lock, flags);
 191        for (; count--; index++) {
 192                u32 val;
 193
 194                val = ((fb->color_map CM(index,2) << 16) |
 195                       (fb->color_map CM(index,1) << 8) |
 196                       (fb->color_map CM(index,0)));
 197                sbus_writel(val, &clut->c_clut[index]);
 198        }
 199        spin_unlock_irqrestore(&fb->lock, flags);
 200}
 201
 202static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p,
 203                          int x_margin, int y_margin)
 204{
 205        p->screen_base += (y_margin - fb->y_margin) *
 206                p->line_length + (x_margin - fb->x_margin);
 207}
 208
 209static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 210{
 211        struct cg14_cursor *cur = fb->s.cg14.cursor;
 212        unsigned long flags;
 213        
 214        spin_lock_irqsave(&fb->lock, flags);
 215        sbus_writel(((red[0]) | (green[0] << 8) | (blue[0] << 16)), &cur->color0);
 216        sbus_writel(((red[1]) | (green[1] << 8) | (blue[1] << 16)), &cur->color1);
 217        spin_unlock_irqrestore(&fb->lock, flags);
 218}
 219
 220/* Set cursor shape */
 221static void cg14_setcurshape (struct fb_info_sbusfb *fb)
 222{
 223        struct cg14_cursor *cur = fb->s.cg14.cursor;
 224        unsigned long flags;
 225        int i;
 226
 227        spin_lock_irqsave(&fb->lock, flags);
 228        for (i = 0; i < 32; i++){
 229                sbus_writel(fb->cursor.bits[0][i], &cur->cpl0[i]);
 230                sbus_writel(fb->cursor.bits[1][i], &cur->cpl1[i]);
 231        }
 232        spin_unlock_irqrestore(&fb->lock, flags);
 233}
 234
 235/* Load cursor information */
 236static void cg14_setcursor (struct fb_info_sbusfb *fb)
 237{
 238        struct cg_cursor *c = &fb->cursor;
 239        struct cg14_cursor *cur = fb->s.cg14.cursor;
 240        unsigned long flags;
 241                
 242        spin_lock_irqsave(&fb->lock, flags);
 243        if (c->enable) {
 244                u8 tmp = sbus_readb(&cur->ccr);
 245
 246                tmp |= CG14_CCR_ENABLE;
 247                sbus_writeb(tmp, &cur->ccr);
 248        } else {
 249                u8 tmp = sbus_readb(&cur->ccr);
 250
 251                tmp &= ~CG14_CCR_ENABLE;
 252                sbus_writeb(tmp, &cur->ccr);
 253        }
 254        sbus_writew(((c->cpos.fbx - c->chot.fbx) & 0xfff), &cur->cursx);
 255        sbus_writew(((c->cpos.fby - c->chot.fby) & 0xfff), &cur->cursy);
 256        spin_unlock_irqrestore(&fb->lock, flags);
 257}
 258
 259static void cg14_switch_from_graph (struct fb_info_sbusfb *fb)
 260{
 261        unsigned long flags;
 262
 263        spin_lock_irqsave(&fb->lock, flags);
 264
 265        /* Set the 8-bpp mode */
 266        if (fb->open && fb->mmaped){
 267                volatile char *mcr = &fb->s.cg14.regs->mcr;
 268                char tmp;
 269                                        
 270                fb->s.cg14.mode = 8;
 271                tmp = sbus_readb(mcr);
 272                tmp &= ~(CG14_MCR_PIXMODE_MASK);
 273                sbus_writeb(tmp, mcr);
 274        }
 275        spin_unlock_irqrestore(&fb->lock, flags);
 276}
 277
 278static void cg14_reset (struct fb_info_sbusfb *fb)
 279{
 280        volatile char *mcr = &fb->s.cg14.regs->mcr;
 281        unsigned long flags;
 282        char tmp;
 283                
 284        spin_lock_irqsave(&fb->lock, flags);
 285        tmp = sbus_readb(mcr);
 286        tmp &= ~(CG14_MCR_PIXMODE_MASK);
 287        sbus_writeb(tmp, mcr);
 288        spin_unlock_irqrestore(&fb->lock, flags);
 289}
 290
 291static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg)
 292{
 293        volatile char *mcr = &fb->s.cg14.regs->mcr;
 294        struct mdi_cfginfo *mdii;
 295        unsigned long flags;
 296        int mode, ret = 0;
 297        char tmp;
 298                
 299        switch (cmd) {
 300        case MDI_RESET:
 301                spin_lock_irqsave(&fb->lock, flags);
 302                tmp = sbus_readb(mcr);
 303                tmp &= ~CG14_MCR_PIXMODE_MASK;
 304                sbus_writeb(tmp, mcr);
 305                spin_unlock_irqrestore(&fb->lock, flags);
 306                break;
 307        case MDI_GET_CFGINFO:
 308                mdii = (struct mdi_cfginfo *)arg;
 309                if (put_user(FBTYPE_MDICOLOR, &mdii->mdi_type) ||
 310                    __put_user(fb->type.fb_height, &mdii->mdi_height) ||
 311                    __put_user(fb->type.fb_width, &mdii->mdi_width) ||
 312                    __put_user(fb->s.cg14.mode, &mdii->mdi_mode) ||
 313                    __put_user(72, &mdii->mdi_pixfreq) || /* FIXME */
 314                    __put_user(fb->s.cg14.ramsize, &mdii->mdi_size))
 315                        return -EFAULT;
 316                break;
 317        case MDI_SET_PIXELMODE:
 318                if (get_user(mode, (int *)arg))
 319                        return -EFAULT;
 320
 321                spin_lock_irqsave(&fb->lock, flags);
 322                tmp = sbus_readb(mcr);
 323                switch (mode){
 324                case MDI_32_PIX:
 325                        tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) |
 326                                (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT);
 327                        break;
 328                case MDI_16_PIX:
 329                        tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | 0x20;
 330                        break;
 331                case MDI_8_PIX:
 332                        tmp = (tmp & ~CG14_MCR_PIXMODE_MASK);
 333                        break;
 334                default:
 335                        ret = -ENOSYS;
 336                        break;
 337                };
 338                if (ret == 0) {
 339                        sbus_writeb(tmp, mcr);
 340                        fb->s.cg14.mode = mode;
 341                }
 342                spin_unlock_irqrestore(&fb->lock, flags);
 343                break;
 344        default:
 345                ret = -EINVAL;
 346        };
 347
 348        return ret;
 349}
 350
 351static unsigned long __init get_phys(unsigned long addr)
 352{
 353        return __get_phys(addr);
 354}
 355
 356static int __init get_iospace(unsigned long addr)
 357{
 358        return __get_iospace(addr);
 359}
 360
 361static char idstring[60] __initdata = { 0 };
 362
 363char __init *cgfourteenfb_init(struct fb_info_sbusfb *fb)
 364{
 365        struct fb_fix_screeninfo *fix = &fb->fix;
 366        struct display *disp = &fb->disp;
 367        struct fbtype *type = &fb->type;
 368        unsigned long rphys, phys;
 369        u32 bases[6];
 370        int is_8mb, i;
 371
 372#ifndef FBCON_HAS_CFB8
 373        return NULL;
 374#endif
 375        prom_getproperty (fb->prom_node, "address", (char *) &bases[0], 8);
 376        if (!bases[0]) {
 377                printk("cg14 not mmaped\n");
 378                return NULL;
 379        }
 380        if (get_iospace(bases[0]) != get_iospace(bases[1])) {
 381                printk("Ugh. cg14 iospaces don't match\n");
 382                return NULL;
 383        }
 384        fb->physbase = phys = get_phys(bases[1]);
 385        rphys = get_phys(bases[0]);
 386        fb->iospace = get_iospace(bases[0]);
 387        fb->s.cg14.regs = (struct cg14_regs *)(unsigned long)bases[0];
 388        fb->s.cg14.clut = (void *)((unsigned long)bases[0]+CG14_CLUT1);
 389        fb->s.cg14.cursor = (void *)((unsigned long)bases[0]+CG14_CURSORREGS);
 390        disp->screen_base = (char *)bases[1];
 391        
 392        /* CG14_VCA_8MB_MASK is not correctly set on the 501-2482
 393         * VSIMM, so we read the memory size from the PROM
 394         */
 395        prom_getproperty(fb->prom_node, "reg", (char *) &bases[0], 24);
 396        is_8mb = bases[5] == 0x800000;
 397
 398        fb->mmap_map = kmalloc(sizeof(cg14_mmap_map), GFP_KERNEL);
 399        if (!fb->mmap_map)
 400                return NULL;
 401
 402        for (i = 0; ; i++) {
 403                fb->mmap_map[i].voff = cg14_mmap_map[i].voff;
 404                fb->mmap_map[i].poff = (cg14_mmap_map[i].poff & 0x80000000) ?
 405                                       (cg14_mmap_map[i].poff & 0x7fffffff) + rphys - phys :
 406                                       cg14_mmap_map[i].poff;
 407                fb->mmap_map[i].size = cg14_mmap_map[i].size;
 408                if (is_8mb && fb->mmap_map[i].size >= 0x100000 &&
 409                    fb->mmap_map[i].size <= 0x400000)
 410                        fb->mmap_map[i].size <<= 1;
 411                if (!cg14_mmap_map[i].size)
 412                        break;
 413        }
 414
 415        strcpy(fb->info.modename, "CGfourteen");
 416        strcpy(fix->id, "CGfourteen");
 417        fix->line_length = fb->var.xres_virtual;
 418        fix->accel = FB_ACCEL_SUN_CG14;
 419        
 420        disp->scrollmode = SCROLL_YREDRAW;
 421        disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
 422        fb->dispsw = fbcon_cfb8;
 423        
 424        type->fb_depth = 24;
 425        fb->emulations[1] = FBTYPE_SUN3COLOR;
 426
 427        fb->margins = cg14_margins;
 428        fb->loadcmap = cg14_loadcmap;
 429        fb->setcursor = cg14_setcursor;
 430        fb->setcursormap = cg14_setcursormap;
 431        fb->setcurshape = cg14_setcurshape;
 432        fb->reset = cg14_reset;
 433        fb->switch_from_graph = cg14_switch_from_graph;
 434        fb->ioctl = cg14_ioctl;
 435
 436        fb->s.cg14.mode = 8;
 437        fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000;
 438        
 439        cg14_reset(fb);
 440        
 441        sprintf(idstring, "cgfourteen at %x.%08lx, %dMB, rev=%d, impl=%d", fb->iospace, phys,
 442                is_8mb ? 8 : 4, fb->s.cg14.regs->rev >> 4, fb->s.cg14.regs->rev & 0xf);
 443        
 444        return idstring;
 445}
 446