diff options
author | Harald Koerfgen <hkoerfg@web.de> | 2000-12-30 15:55:57 +0000 |
---|---|---|
committer | Harald Koerfgen <hkoerfg@web.de> | 2000-12-30 15:55:57 +0000 |
commit | 5ffede5ab53ed46d1fe59f902062ba06bde59bbd (patch) | |
tree | 5ecd8d67d3f1f6c5896e3feff2bda63b1538a338 /drivers/video | |
parent | 2cb8ea0ed322d8fdf15bfb726dd0d684b9eafdaf (diff) |
LK201 keyboard and PMAG-BA framebuffer driver for DECstations
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Config.in | 5 | ||||
-rw-r--r-- | drivers/video/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 5 | ||||
-rw-r--r-- | drivers/video/pmag-ba-fb.c | 440 |
4 files changed, 452 insertions, 0 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 2a48d4d7c..866df0ea5 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -155,6 +155,11 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_HD64461" = "y" ]; then tristate ' HD64461 Frame Buffer support' CONFIG_FB_HIT fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + if [ "$CONFIG_TC" = "y" ]; then + bool ' PMAG-BA TURBOchannel framebuffer support' CONFIG_FB_PMAGBA + fi + fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 331343d15..96de87f86 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -89,6 +89,7 @@ obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o +obj-$(CONFIG_FB_PMAGBA) += pmag-ba-fb.o ifeq ($(CONFIG_FB_MATROX),y) SUB_DIRS += matrox @@ -183,3 +184,4 @@ promcon_tbl.c: prom.uni ../char/conmakehash -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h + diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7b3d49822..ba6d70289 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -113,6 +113,8 @@ extern int tdfxfb_init(void); extern int tdfxfb_setup(char*); extern int sisfb_init(void); extern int sisfb_setup(char*); +extern int pmagbafb_init(void); +extern int pmagbafb_setup(char *); static struct { const char *name; @@ -267,6 +269,9 @@ static struct { /* Not a real frame buffer device... */ { "resolver", NULL, resolver_video_setup }, #endif +#ifdef CONFIG_FB_PMAGBA + { "pmagbafb", pmagbafb_init, pmagbafb_setup }, +#endif #ifdef CONFIG_FB_VIRTUAL /* diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c new file mode 100644 index 000000000..7987082fc --- /dev/null +++ b/drivers/video/pmag-ba-fb.c @@ -0,0 +1,440 @@ +/* + * linux/drivers/video/pmagbafb.c + * + * PMAG-BA TurboChannel framebuffer card support ... derived from: + * "HP300 Topcat framebuffer support (derived from macfb of all things) + * Phil Blundell <philb@gnu.org> 1998", the original code can be + * found in the file hpfb.c in the same directory. + * + * Based on digital document: + * "PMAG-BA TURBOchannel Color Frame Buffer + * Functional Specification", Revision 1.2, August 27, 1990 + * + * DECstation related code Copyright (C) 1999, 2000 by + * Michael Engel <engel@unix-ag.org>, Karsten Merker <merker@guug.de> + * and Harald Koerfgen <harald@unix-ag.org>. + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + * + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/fb.h> +#include <asm/bootinfo.h> +#include <asm/dec/machtype.h> +#include <asm/dec/tc.h> + +#include <video/fbcon.h> +#include <video/fbcon-mfb.h> +#include <video/fbcon-cfb2.h> +#include <video/fbcon-cfb4.h> +#include <video/fbcon-cfb8.h> + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +/* + * Bt459 RAM DAC register base offset (rel. to TC slot base address) + */ +#define BT459_OFFSET 0x00200000 + +/* + * Begin of DECstation 5000/xx onboard framebuffer memory, resolution + * is 1024x864x8 + */ +#define PMAG_BA_ONBOARD_FBMEM_OFFSET 0x00000000 + +struct ramdac_regs { + unsigned char addr_low; + unsigned char pad0[3]; + unsigned char addr_hi; + unsigned char pad1[3]; + unsigned char data; + unsigned char pad2[3]; + unsigned char cmap; +}; + +struct my_fb_info { + struct fb_info info; + struct ramdac_regs *bt459_regs; + unsigned long pmagba_fb_start; + unsigned long pmagba_fb_size; + unsigned long pmagba_fb_line_length; +}; + +static struct display disp; +/* + * Max 3 TURBOchannel slots -> max 3 PMAG-BA :) + */ +static struct my_fb_info pmagba_fb_info[3]; + +static struct fb_var_screeninfo pmagbafb_defined = { + 0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */ + 0, 0, /* virtual -> visible no offset */ + 0, /* depth -> load bits_per_pixel */ + 0, /* greyscale ? */ + {0, 0, 0}, /* R */ + {0, 0, 0}, /* G */ + {0, 0, 0}, /* B */ + {0, 0, 0}, /* transparency */ + 0, /* standard pixel format */ + FB_ACTIVATE_NOW, + 274, 195, /* 14" monitor */ + FB_ACCEL_NONE, + 0L, 0L, 0L, 0L, 0L, + 0L, 0L, 0, /* No sync info */ + FB_VMODE_NONINTERLACED, + {0, 0, 0, 0, 0, 0} +}; + +struct pmagbafb_par { +}; + +static int currcon = 0; +struct pmagbafb_par current_par; + +static void pmagbafb_encode_var(struct fb_var_screeninfo *var, + struct pmagbafb_par *par) +{ + int i = 0; + var->xres = 1024; + var->yres = 864; + var->xres_virtual = 1024; + var->yres_virtual = 864; + var->xoffset = 0; + var->yoffset = 0; + var->bits_per_pixel = 8; + var->grayscale = 0; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->nonstd = 0; + var->activate = 1; + var->height = -1; + var->width = -1; + var->vmode = FB_VMODE_NONINTERLACED; + var->pixclock = 0; + var->sync = 0; + var->left_margin = 0; + var->right_margin = 0; + var->upper_margin = 0; + var->lower_margin = 0; + var->hsync_len = 0; + var->vsync_len = 0; + for (i = 0; i < arraysize(var->reserved); i++) + var->reserved[i] = 0; +} + +static void pmagbafb_get_par(struct pmagbafb_par *par) +{ + *par = current_par; +} + +static int pmagba_fb_update_var(int con, struct fb_info *info) +{ + return 0; +} + +static int pmagba_do_fb_set_var(struct fb_var_screeninfo *var, + int isactive) +{ + struct pmagbafb_par par; + + pmagbafb_get_par(&par); + pmagbafb_encode_var(var, &par); + return 0; +} + +/* + * Turn hardware cursor off + */ +void pmagbafb_erase_cursor(struct my_fb_info *info) +{ + info->bt459_regs->addr_low = 0; + info->bt459_regs->addr_hi = 3; + info->bt459_regs->data = 0; +} + +/* + * Write to a Bt459 color map register + */ +void bt459_write_colormap(struct my_fb_info *info, + int reg, __u8 red, __u8 green, __u8 blue) +{ + info->bt459_regs->addr_low = (__u8) reg; + info->bt459_regs->addr_hi = 0; + info->bt459_regs->cmap = red; + info->bt459_regs->cmap = green; + info->bt459_regs->cmap = blue; +} + +/* + * Get the palette + */ + +static int pmagbafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + unsigned int i; + unsigned int length; + + if (((cmap->start) + (cmap->len)) >= 256) { + length = 256 - (cmap->start); + } else { + length = cmap->len; + } + for (i = 0; i < length; i++) { + /* + * TODO + */ + } + return 0; +} + +/* + * Set the palette. + */ +static int pmagbafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + unsigned int i; + __u8 cmap_red, cmap_green, cmap_blue; + unsigned int length; + + if (((cmap->start) + (cmap->len)) >= 256) + length = 256 - (cmap->start); + else + length = cmap->len; + + for (i = 0; i < length; i++) { + cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits */ + cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */ + cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */ + + bt459_write_colormap((struct my_fb_info *) info, + cmap->start + i, cmap_red, cmap_green, + cmap_blue); + } + return 0; +} + +static int pmagbafb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct pmagbafb_par par; + if (con == -1) { + pmagbafb_get_par(&par); + pmagbafb_encode_var(var, &par); + } else + *var = fb_display[con].var; + return 0; +} + + +static int pmagbafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err; + + if ((err = pmagba_do_fb_set_var(var, 1))) + return err; + return 0; +} + +static void pmagbafb_encode_fix(struct fb_fix_screeninfo *fix, + struct pmagbafb_par *par, + struct my_fb_info *info) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "PMAG-BA"); + + /* + * X works, but screen wraps ... + */ + fix->smem_start = info->pmagba_fb_start; + fix->smem_len = info->pmagba_fb_size; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + fix->xpanstep = 0; + fix->ypanstep = 0; + fix->ywrapstep = 0; + fix->line_length = info->pmagba_fb_line_length; +} + +static int pmagbafb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct pmagbafb_par par; + + pmagbafb_get_par(&par); + pmagbafb_encode_fix(fix, &par, (struct my_fb_info *) info); + + return 0; +} + + +static int pmagbafb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + return -EINVAL; +} + +static int pmagbafb_switch(int con, struct fb_info *info) +{ + pmagba_do_fb_set_var(&fb_display[con].var, 1); + currcon = con; + + return 0; +} + +/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ + +static void pmagbafb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +static int pmagbafb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return (0); +} + +static void pmagbafb_set_disp(int con, struct my_fb_info *info) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + pmagbafb_get_fix(&fix, con, (struct fb_info *) info); + + display->screen_base = (char *) fix.smem_start; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + display->next_line = fix.line_length; + display->can_soft_blank = 0; + display->inverse = 0; + + display->dispsw = &fbcon_cfb8; +} + +static int pmagbafb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return (0); +} + +static struct fb_ops pmagbafb_ops = { + owner: THIS_MODULE, + fb_open: pmagbafb_open, + fb_release: pmagbafb_release, + fb_get_fix: pmagbafb_get_fix, + fb_get_var: pmagbafb_get_var, + fb_set_var: pmagbafb_set_var, + fb_get_cmap: pmagbafb_get_cmap, + fb_set_cmap: pmagbafb_set_cmap, + fb_ioctl: pmagbafb_ioctl, + fb_mmap: 0, + fb_rasterimg: 0 +}; + +int __init pmagbafb_init_one(int slot) +{ + unsigned long base_addr = get_tc_base_addr(slot); + struct my_fb_info *ip = + (struct my_fb_info *) &pmagba_fb_info[slot]; + + printk("PMAG-BA framebuffer in slot %d\n", slot); + + /* + * Framebuffer display memory base address and friends + */ + ip->bt459_regs = (struct ramdac_regs *) (base_addr + BT459_OFFSET); + ip->pmagba_fb_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET; + ip->pmagba_fb_size = 1024 * 864; + ip->pmagba_fb_line_length = 1024; + + /* + * Configure the Bt459 RAM DAC + */ + pmagbafb_erase_cursor(ip); + + /* + * Fill in the available video resolution + */ + + pmagbafb_defined.xres = 1024; + pmagbafb_defined.yres = 864; + pmagbafb_defined.xres_virtual = 1024; + pmagbafb_defined.yres_virtual = 864; + pmagbafb_defined.bits_per_pixel = 8; + + /* + * Let there be consoles.. + */ + strcpy(ip->info.modename, "PMAG-BA"); + ip->info.changevar = NULL; + ip->info.node = -1; + ip->info.fbops = &pmagbafb_ops; + ip->info.disp = &disp; + ip->info.switch_con = &pmagbafb_switch; + ip->info.updatevar = &pmagba_fb_update_var; + ip->info.blank = &pmagbafb_blank; + ip->info.flags = FBINFO_FLAG_DEFAULT; + + pmagba_do_fb_set_var(&pmagbafb_defined, 1); + pmagbafb_get_var(&disp.var, -1, (struct fb_info *) ip); + pmagbafb_set_disp(-1, ip); + + if (register_framebuffer((struct fb_info *) ip) < 0) + return 1; + + return 0; +} + +/* + * Initialise the framebuffer + */ + +int __init pmagbafb_init(void) +{ + int sid; + int found = 0; + + if (TURBOCHANNEL) { + while ((sid = search_tc_card("PMAG-BA")) >= 0) { + found = 1; + claim_tc_card(sid); + pmagbafb_init_one(sid); + } + return found ? 0 : -ENODEV; + } else { + return -ENODEV; + } +} + +int __init pmagbafb_setup(char *options) +{ + return 0; +} |