linux-old/drivers/video/bwtwofb.c
<<
>>
Prefs
   1/* $Id: bwtwofb.c,v 1.15 2001/09/19 00:04:33 davem Exp $
   2 * bwtwofb.c: BWtwo frame buffer driver
   3 *
   4 * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
   5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
   6 * Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be)
   7 * Copyright (C) 1998 Pavel Machek    (pavel@ucw.cz)
   8 */
   9
  10#include <linux/config.h>
  11#include <linux/module.h>
  12#include <linux/sched.h>
  13#include <linux/kernel.h>
  14#include <linux/errno.h>
  15#include <linux/string.h>
  16#include <linux/mm.h>
  17#include <linux/tty.h>
  18#include <linux/slab.h>
  19#include <linux/vmalloc.h>
  20#include <linux/delay.h>
  21#include <linux/interrupt.h>
  22#include <linux/fb.h>
  23#include <linux/init.h>
  24#include <linux/selection.h>
  25
  26#include <video/sbusfb.h>
  27#include <asm/io.h>
  28#if !defined(__sparc_v9__) && !defined(__mc68000__)
  29#include <asm/sun4paddr.h>
  30#endif
  31
  32#include <video/fbcon-mfb.h>
  33
  34/* OBio addresses for the bwtwo registers */
  35#define BWTWO_REGISTER_OFFSET 0x400000
  36
  37struct bw2_regs {
  38        struct bt_regs          bt;
  39        volatile u8             control;
  40        volatile u8             status;
  41        volatile u8             cursor_start;
  42        volatile u8             cursor_end;
  43        volatile u8             h_blank_start;
  44        volatile u8             h_blank_end;
  45        volatile u8             h_sync_start;
  46        volatile u8             h_sync_end;
  47        volatile u8             comp_sync_end;
  48        volatile u8             v_blank_start_high;
  49        volatile u8             v_blank_start_low;
  50        volatile u8             v_blank_end;
  51        volatile u8             v_sync_start;
  52        volatile u8             v_sync_end;
  53        volatile u8             xfer_holdoff_start;
  54        volatile u8             xfer_holdoff_end;
  55};
  56
  57/* Status Register Constants */
  58#define BWTWO_SR_RES_MASK       0x70
  59#define BWTWO_SR_1600_1280      0x50
  60#define BWTWO_SR_1152_900_76_A  0x40
  61#define BWTWO_SR_1152_900_76_B  0x60
  62#define BWTWO_SR_ID_MASK        0x0f
  63#define BWTWO_SR_ID_MONO        0x02
  64#define BWTWO_SR_ID_MONO_ECL    0x03
  65#define BWTWO_SR_ID_MSYNC       0x04
  66#define BWTWO_SR_ID_NOCONN      0x0a
  67
  68/* Control Register Constants */
  69#define BWTWO_CTL_ENABLE_INTS   0x80
  70#define BWTWO_CTL_ENABLE_VIDEO  0x40
  71#define BWTWO_CTL_ENABLE_TIMING 0x20
  72#define BWTWO_CTL_ENABLE_CURCMP 0x10
  73#define BWTWO_CTL_XTAL_MASK     0x0C
  74#define BWTWO_CTL_DIVISOR_MASK  0x03
  75
  76/* Status Register Constants */
  77#define BWTWO_STAT_PENDING_INT  0x80
  78#define BWTWO_STAT_MSENSE_MASK  0x70
  79#define BWTWO_STAT_ID_MASK      0x0f
  80
  81static struct sbus_mmap_map bw2_mmap_map[] = {
  82        { 0,                    0,                      SBUS_MMAP_FBSIZE(1) },
  83        { 0,                    0,                      0                   }
  84};
  85
  86static void bw2_blank (struct fb_info_sbusfb *fb)
  87{
  88        unsigned long flags;
  89        u8 tmp;
  90
  91        spin_lock_irqsave(&fb->lock, flags);
  92        tmp = sbus_readb(&fb->s.bw2.regs->control);
  93        tmp &= ~BWTWO_CTL_ENABLE_VIDEO;
  94        sbus_writeb(tmp, &fb->s.bw2.regs->control);
  95        spin_unlock_irqrestore(&fb->lock, flags);
  96}
  97
  98static void bw2_unblank (struct fb_info_sbusfb *fb)
  99{
 100        unsigned long flags;
 101        u8 tmp;
 102
 103        spin_lock_irqsave(&fb->lock, flags);
 104        tmp = sbus_readb(&fb->s.bw2.regs->control);
 105        tmp |= BWTWO_CTL_ENABLE_VIDEO;
 106        sbus_writeb(tmp, &fb->s.bw2.regs->control);
 107        spin_unlock_irqrestore(&fb->lock, flags);
 108}
 109
 110static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p,
 111                         int x_margin, int y_margin)
 112{
 113        p->screen_base += (y_margin - fb->y_margin) *
 114                p->line_length + ((x_margin - fb->x_margin) >> 3);
 115}
 116
 117static u8 bw2regs_1600[] __initdata = {
 118        0x14, 0x8b,     0x15, 0x28,     0x16, 0x03,     0x17, 0x13,
 119        0x18, 0x7b,     0x19, 0x05,     0x1a, 0x34,     0x1b, 0x2e,
 120        0x1c, 0x00,     0x1d, 0x0a,     0x1e, 0xff,     0x1f, 0x01,
 121        0x10, 0x21,     0
 122};
 123
 124static u8 bw2regs_ecl[] __initdata = {
 125        0x14, 0x65,     0x15, 0x1e,     0x16, 0x04,     0x17, 0x0c,
 126        0x18, 0x5e,     0x19, 0x03,     0x1a, 0xa7,     0x1b, 0x23,
 127        0x1c, 0x00,     0x1d, 0x08,     0x1e, 0xff,     0x1f, 0x01,
 128        0x10, 0x20,     0
 129};
 130
 131static u8 bw2regs_analog[] __initdata = {
 132        0x14, 0xbb,     0x15, 0x2b,     0x16, 0x03,     0x17, 0x13,
 133        0x18, 0xb0,     0x19, 0x03,     0x1a, 0xa6,     0x1b, 0x22,
 134        0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
 135        0x10, 0x20,     0
 136};
 137
 138static u8 bw2regs_76hz[] __initdata = {
 139        0x14, 0xb7,     0x15, 0x27,     0x16, 0x03,     0x17, 0x0f,
 140        0x18, 0xae,     0x19, 0x03,     0x1a, 0xae,     0x1b, 0x2a,
 141        0x1c, 0x01,     0x1d, 0x09,     0x1e, 0xff,     0x1f, 0x01,
 142        0x10, 0x24,     0
 143};
 144
 145static u8 bw2regs_66hz[] __initdata = {
 146        0x14, 0xbb,     0x15, 0x2b,     0x16, 0x04,     0x17, 0x14,
 147        0x18, 0xae,     0x19, 0x03,     0x1a, 0xa8,     0x1b, 0x24,
 148        0x1c, 0x01,     0x1d, 0x05,     0x1e, 0xff,     0x1f, 0x01,
 149        0x10, 0x20,     0
 150};
 151
 152static char idstring[60] __initdata = { 0 };
 153
 154char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
 155{
 156        struct fb_fix_screeninfo *fix = &fb->fix;
 157        struct display *disp = &fb->disp;
 158        struct fbtype *type = &fb->type;
 159#ifdef CONFIG_SUN4
 160        unsigned long phys = sun4_bwtwo_physaddr;
 161        struct resource res;
 162#else
 163        unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
 164#endif
 165        struct resource *resp;
 166        unsigned int vaddr;
 167
 168#ifndef FBCON_HAS_MFB
 169        return NULL;
 170#endif
 171
 172#ifdef CONFIG_SUN4
 173        res.start = phys;
 174        res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
 175        res.flags = IORESOURCE_IO | (fb->iospace & 0xff);
 176        resp = &res;
 177#else
 178        resp = &fb->sbdp->resource[0];
 179#endif
 180        if (!fb->s.bw2.regs) {
 181                fb->s.bw2.regs = (struct bw2_regs *)
 182                        sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
 183                                     sizeof(struct bw2_regs), "bw2 regs");
 184                if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
 185                        /* Ugh, broken PROM didn't initialize us.
 186                         * Let's deal with this ourselves.
 187                         */
 188                        u8 status, mon;
 189                        u8 *p;
 190                        int sizechange = 0;
 191
 192                        status = sbus_readb(&fb->s.bw2.regs->status);
 193                        mon = status & BWTWO_SR_RES_MASK;
 194                        switch (status & BWTWO_SR_ID_MASK) {
 195                                case BWTWO_SR_ID_MONO_ECL:
 196                                        if (mon == BWTWO_SR_1600_1280) {
 197                                                p = bw2regs_1600;
 198                                                fb->type.fb_width = 1600;
 199                                                fb->type.fb_height = 1280;
 200                                                sizechange = 1;
 201                                        } else
 202                                                p = bw2regs_ecl;
 203                                        break;
 204                                case BWTWO_SR_ID_MONO:
 205                                        p = bw2regs_analog;
 206                                        break;
 207                                case BWTWO_SR_ID_MSYNC:
 208                                        if (mon == BWTWO_SR_1152_900_76_A ||
 209                                            mon == BWTWO_SR_1152_900_76_B)
 210                                                p = bw2regs_76hz;
 211                                        else
 212                                                p = bw2regs_66hz;
 213                                        break;
 214                                case BWTWO_SR_ID_NOCONN:
 215                                        return NULL;
 216                                default:
 217#ifndef CONFIG_FB_SUN3
 218                                        prom_printf("bw2: can't handle SR %02x\n",
 219                                                    status);
 220                                        prom_halt();
 221#endif                                  
 222                                        return NULL; /* fool gcc. */
 223                        }
 224                        for ( ; *p; p += 2) {
 225                                u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]];
 226                                sbus_writeb(p[1], regp);
 227                        }
 228                }
 229        }
 230
 231        strcpy(fb->info.modename, "BWtwo");
 232        strcpy(fix->id, "BWtwo");
 233        fix->line_length = fb->var.xres_virtual >> 3;
 234        fix->accel = FB_ACCEL_SUN_BWTWO;
 235        
 236        disp->scrollmode = SCROLL_YREDRAW;
 237        disp->inverse = 1;
 238        if (!disp->screen_base) {
 239                disp->screen_base = (char *)
 240                        sbus_ioremap(resp, 0, type->fb_size, "bw2 ram");
 241        }
 242        disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
 243        fb->dispsw = fbcon_mfb;
 244        fix->visual = FB_VISUAL_MONO01;
 245
 246#ifndef CONFIG_SUN4
 247        fb->blank = bw2_blank;
 248        fb->unblank = bw2_unblank;
 249
 250        prom_getproperty(fb->sbdp->prom_node, "address",
 251                         (char *)&vaddr, sizeof(vaddr));
 252        fb->physbase = __get_phys((unsigned long)vaddr);
 253
 254#endif
 255        fb->margins = bw2_margins;
 256        fb->mmap_map = bw2_mmap_map;
 257
 258#ifdef __sparc_v9__
 259        sprintf(idstring, "bwtwo at %016lx", phys);
 260#else   
 261        sprintf(idstring, "bwtwo at %x.%08lx", fb->iospace, phys);
 262#endif
 263        
 264        return idstring;
 265}
 266
 267MODULE_LICENSE("GPL");
 268
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.