/* $Id: bwtwo.c,v 1.18 1997/07/17 02:21:43 davem Exp $ * bwtwo.c: bwtwo console driver * * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) */ #include #include #include #include #include #include #include #include /* These must be included after asm/fbio.h */ #include #include #include #include "fb.h" #include "cg_common.h" /* OBio addresses for the bwtwo registers */ #define BWTWO_REGISTER_OFFSET 0x400000 struct bwtwo_regs { __volatile__ struct bt_regs bt; __volatile__ __u8 control; __volatile__ __u8 status; __volatile__ __u8 cursor_start; __volatile__ __u8 cursor_end; __volatile__ __u8 h_blank_start; __volatile__ __u8 h_blank_end; __volatile__ __u8 h_sync_start; __volatile__ __u8 h_sync_end; __volatile__ __u8 comp_sync_end; __volatile__ __u8 v_blank_start_high; __volatile__ __u8 v_blank_start_low; __volatile__ __u8 v_blank_end; __volatile__ __u8 v_sync_start; __volatile__ __u8 v_sync_end; __volatile__ __u8 xfer_holdoff_start; __volatile__ __u8 xfer_holdoff_end; }; /* Status Register Constants */ #define BWTWO_SR_RES_MASK 0x70 #define BWTWO_SR_1600_1280 0x50 #define BWTWO_SR_1152_900_76_A 0x40 #define BWTWO_SR_1152_900_76_B 0x60 #define BWTWO_SR_ID_MASK 0x0f #define BWTWO_SR_ID_MONO 0x02 #define BWTWO_SR_ID_MONO_ECL 0x03 #define BWTWO_SR_ID_MSYNC 0x04 /* Control Register Constants */ #define BWTWO_CTL_ENABLE_INTS 0x80 #define BWTWO_CTL_ENABLE_VIDEO 0x40 #define BWTWO_CTL_ENABLE_TIMING 0x20 #define BWTWO_CTL_ENABLE_CURCMP 0x10 #define BWTWO_CTL_XTAL_MASK 0x0C #define BWTWO_CTL_DIVISOR_MASK 0x03 /* Status Register Constants */ #define BWTWO_STAT_PENDING_INT 0x80 #define BWTWO_STAT_MSENSE_MASK 0x70 #define BWTWO_STAT_ID_MASK 0x0f static int bwtwo_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, long base, fbinfo_t *fb) { uint size, r; unsigned long map_offset; int map_size; map_size = size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) return -ENXIO; /* To stop the swapper from even considering these pages */ vma->vm_flags |= FB_MMAP_VM_FLAGS; /* This routine should also map the register if asked for, * but we don't do that yet. */ map_offset = get_phys ((unsigned long) fb->base); r = io_remap_page_range (vma->vm_start, map_offset, map_size, vma->vm_page_prot, fb->space); if (r) return -EAGAIN; vma->vm_dentry = dget(file->f_dentry); return 0; } static void bwtwo_blank (fbinfo_t *fb) { fb->info.bwtwo.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO; } static void bwtwo_unblank (fbinfo_t *fb) { fb->info.bwtwo.regs->control |= BWTWO_CTL_ENABLE_VIDEO; } static u8 bw2regs_1600[] __initdata = { 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13, 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e, 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x21, 0 }; static u8 bw2regs_ecl[] __initdata = { 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c, 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23, 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; static u8 bw2regs_analog[] __initdata = { 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13, 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22, 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; static u8 bw2regs_76hz[] __initdata = { 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a, 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x24, 0 }; static u8 bw2regs_66hz[] __initdata = { 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14, 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24, 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, 0x10, 0x20, 0 }; __initfunc(void bwtwo_setup (fbinfo_t *fb, int slot, u32 bwtwo, int bw2_io, struct linux_sbus_device *sbdp)) { printk ("bwtwo%d at 0x%8.8x\n", slot, bwtwo); fb->type.fb_cmsize = 0; fb->mmap = bwtwo_mmap; fb->loadcmap = 0; fb->ioctl = 0; fb->reset = 0; fb->blank = bwtwo_blank; fb->unblank = bwtwo_unblank; fb->info.bwtwo.regs = sparc_alloc_io (bwtwo + BWTWO_REGISTER_OFFSET, 0, sizeof (struct bwtwo_regs), "bwtwo_regs", bw2_io, 0); if (!prom_getbool(sbdp->prom_node, "width")) { /* Ugh, broken PROM didn't initialize us. * Let's deal with this ourselves. */ u8 status, mon; u8 *p; status = fb->info.bwtwo.regs->status; mon = status & BWTWO_SR_RES_MASK; switch (status & BWTWO_SR_ID_MASK) { case BWTWO_SR_ID_MONO_ECL: if (mon == BWTWO_SR_1600_1280) { p = bw2regs_1600; fb->type.fb_width = 1600; fb->type.fb_height = 1280; } else { p = bw2regs_ecl; } break; case BWTWO_SR_ID_MONO: p = bw2regs_analog; break; case BWTWO_SR_ID_MSYNC: if (mon == BWTWO_SR_1152_900_76_A || mon == BWTWO_SR_1152_900_76_B) { p = bw2regs_76hz; } else { p = bw2regs_66hz; } break; default: prom_printf("bwtwo: can't handle SR %02x\n", status); prom_halt(); return; /* fool gcc. */ } for ( ; *p; p += 2) ((u8 *)fb->info.bwtwo.regs)[p[0]] = p[1]; } if(!fb->base) fb->base = (unsigned long) sparc_alloc_io(bwtwo, 0, ((fb->type.fb_depth*fb->type.fb_height*fb->type.fb_width)/8), "bwtwo_fbase", bw2_io, 0); if (slot && sun_prom_console_id != slot) bwtwo_blank (fb); }