diff options
author | Harald Koerfgen <hkoerfg@web.de> | 2001-01-28 10:54:14 +0000 |
---|---|---|
committer | Harald Koerfgen <hkoerfg@web.de> | 2001-01-28 10:54:14 +0000 |
commit | a24f6673f6d58683abe7eacacb1b524d58837409 (patch) | |
tree | c5740888452cf739153875d565e6ce67023fbb17 /drivers | |
parent | 1b9c243c58a4aa70456f681513b5a16aa6f7c152 (diff) |
DECstation framebuffer drivers from Michael Engel and Karsten Merker
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/Config.in | 8 | ||||
-rw-r--r-- | drivers/video/Makefile | 5 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 17 | ||||
-rw-r--r-- | drivers/video/maxinefb.c | 425 | ||||
-rw-r--r-- | drivers/video/maxinefb.h | 37 | ||||
-rw-r--r-- | drivers/video/pmag-ba-fb.c | 93 | ||||
-rw-r--r-- | drivers/video/pmagb-b-fb.c | 434 | ||||
-rw-r--r-- | drivers/video/pmagb-b-fb.h | 32 |
8 files changed, 996 insertions, 55 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 4a41ab8f6..dfd8e10c5 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -158,7 +158,9 @@ if [ "$CONFIG_FB" = "y" ]; then fi if [ "$CONFIG_DECSTATION" = "y" ]; then if [ "$CONFIG_TC" = "y" ]; then - bool ' PMAG-BA TURBOchannel framebuffer support' CONFIG_FB_PMAGBA + bool ' PMAG-BA TURBOchannel framebuffer support' CONFIG_FB_PMAG_BA + bool ' PMAGB-B TURBOchannel framebuffer spport' CONFIG_FB_PMAGB_B + bool ' Maxine (Personal DECstation) onboard framebuffer spport' CONFIG_FB_MAXINE fi fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then @@ -227,6 +229,8 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_RIVA" = "y" -o \ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \ + "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \ + "$CONFIG_FB_MAXINE" = "y" -o \ "$CONFIG_FB_SIS" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else @@ -244,6 +248,8 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ + "$CONFIG_FB_PMAG_BA" = "m" -o "CONFIG_FB_PMAGB_B" = "m" -o \ + "$CONFIG_FB_MAXINE" = "m" -o \ "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then define_tristate CONFIG_FBCON_CFB8 m fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 778af1db6..38403b55a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -78,7 +78,10 @@ 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 +obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o +obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o +obj-$(CONFIG_FB_MAXINE) += maxinefb.o + subdir-$(CONFIG_FB_MATROX) += matrox ifeq ($(CONFIG_FB_MATROX),y) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 75b6aee16..a951ccf5e 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -117,6 +117,10 @@ extern int stifb_init(void); extern int stifb_setup(char*); extern int pmagbafb_init(void); extern int pmagbafb_setup(char *); +extern int pmagbbfb_init(void); +extern int pmagbbfb_setup(char *options, int *ints); +extern void maxinefb_init(void); +extern void maxinefb_setup(char *options, int *ints); static struct { const char *name; @@ -274,10 +278,19 @@ static struct { /* Not a real frame buffer device... */ { "resolver", NULL, resolver_video_setup }, #endif -#ifdef CONFIG_FB_PMAGBA - { "pmagbafb", pmagbafb_init, pmagbafb_setup }, + +#ifdef CONFIG_FB_PMAG_BA + { "pmagbafb", pmagbafb_init, pmagbafb_setup }, +#endif +#ifdef CONFIG_FB_PMAGB_B + { "pmagbbfb", pmagbbfb_init, pmagbbfb_setup }, #endif +#ifdef CONFIG_FB_MAXINE + { "maxinefb", maxinefb_init, maxinefb_setup }, +#endif + + #ifdef CONFIG_FB_VIRTUAL /* * Vfb must be last to avoid that it becomes your primary display if diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c new file mode 100644 index 000000000..76039c289 --- /dev/null +++ b/drivers/video/maxinefb.c @@ -0,0 +1,425 @@ +/* + * linux/drivers/video/maxinefb.c + * + * DECstation 5000/xx onboard framebuffer 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. + * + * DECstation related code Copyright (C) 1999,2000,2001 by + * Michael Engel <engel@unix-ag.org> and + * Karsten Merker <merker@linuxtag.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. + * + */ + +/* + * Changes: + * 2001/01/27 removed debugging and testing code, fixed fb_ops + * initialization which had caused a crash before, + * general cleanup, first official release (KM) + * + */ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.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 <video/fbcon.h> +#include "maxinefb.h" + +/* bootinfo.h defines the machine type values, needed when checking */ +/* whether are really running on a maxine, KM */ +#include <asm/bootinfo.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))) + +static struct display disp; +static struct fb_info fb_info; + +unsigned long fb_start, fb_size = 1024 * 768, fb_line_length = 1024; +unsigned long fb_regs; +unsigned char fb_bitmask; + +static struct fb_var_screeninfo maxinefb_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 maxinefb_par { +}; + +static int currcon = 0; +struct maxinefb_par current_par; + +/* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */ +extern unsigned long mips_machtype; + + +/* Handle the funny Inmos RamDAC/video controller ... */ + +void maxinefb_ims332_write_register(int regno, register unsigned int val) +{ + register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS; + unsigned char *wptr; + + wptr = regs + 0xa0000 + (regno << 4); + *((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00; + *((volatile unsigned short *) (wptr)) = val; +} + +unsigned int maxinefb_ims332_read_register(int regno) +{ + register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS; + unsigned char *rptr; + register unsigned int j, k; + + rptr = regs + 0x80000 + (regno << 4); + j = *((volatile unsigned short *) rptr); + k = *((volatile unsigned short *) regs); + + return (j & 0xffff) | ((k & 0xff00) << 8); +} + + +static void maxinefb_encode_var(struct fb_var_screeninfo *var, + struct maxinefb_par *par) +{ + int i = 0; + var->xres = 1024; + var->yres = 768; + var->xres_virtual = 1024; + var->yres_virtual = 768; + 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 maxinefb_get_par(struct maxinefb_par *par) +{ + *par = current_par; +} + +static int maxinefb_fb_update_var(int con, struct fb_info *info) +{ + return 0; +} + +static int maxinefb_do_fb_set_var(struct fb_var_screeninfo *var, + int isactive) +{ + struct maxinefb_par par; + + maxinefb_get_par(&par); + maxinefb_encode_var(var, &par); + return 0; +} + + +/* Get the palette */ + +static int maxinefb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + unsigned int i; + unsigned long hw_colorvalue = 0; /* raw color value from the register */ + unsigned int length; + + if (((cmap->start) + (cmap->len)) >= 256) { + length = 256 - (cmap->start); + } else { + length = cmap->len; + } + for (i = 0; i < length; i++) { + hw_colorvalue = + maxinefb_ims332_read_register(IMS332_REG_COLOR_PALETTE + + cmap->start + i); + (cmap->red[i]) = ((hw_colorvalue & 0x0000ff)); + (cmap->green[i]) = ((hw_colorvalue & 0x00ff00) >> 8); + (cmap->blue[i]) = ((hw_colorvalue & 0xff0000) >> 16); + + } + return 0; +} + + +/* Set the palette */ + +static int maxinefb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + unsigned int i; + unsigned long hw_colorvalue; /* value to be written into the palette reg. */ + unsigned short cmap_red; + unsigned short cmap_green; + unsigned short cmap_blue; + unsigned int length; + + hw_colorvalue = 0; + 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 */ + + hw_colorvalue = + (cmap_blue << 16) + (cmap_green << 8) + (cmap_red); + maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + + cmap->start + i, + hw_colorvalue); + } + return 0; +} + +static int maxinefb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct maxinefb_par par; + if (con == -1) { + maxinefb_get_par(&par); + maxinefb_encode_var(var, &par); + } else + *var = fb_display[con].var; + return 0; +} + + +static int maxinefb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err; + + if ((err = maxinefb_do_fb_set_var(var, 1))) + return err; + return 0; +} +static void maxinefb_encode_fix(struct fb_fix_screeninfo *fix, + struct maxinefb_par *par) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "maxinefb"); + /* fix->id is a char[16], so a maximum of 15 characters, KM */ + + fix->smem_start = (char *) fb_start; /* display memory base address, KM */ + fix->smem_len = 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 = fb_line_length; +} + +static int maxinefb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct maxinefb_par par; + maxinefb_get_par(&par); + maxinefb_encode_fix(fix, &par); + return 0; +} + + +static int maxinefb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + return -EINVAL; +} + +static int maxinefb_switch(int con, struct fb_info *info) +{ + maxinefb_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 maxinefb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +static int maxinefb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return (0); +} + +static void maxinefb_set_disp(int con) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + maxinefb_get_fix(&fix, con, 0); + + display->screen_base = 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 maxinefb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return (0); +} + +static struct fb_ops maxinefb_ops = { + owner:THIS_MODULE, + fb_open:maxinefb_open, + fb_release:maxinefb_release, + fb_get_fix:maxinefb_get_fix, + fb_get_var:maxinefb_get_var, + fb_set_var:maxinefb_set_var, + fb_get_cmap:maxinefb_get_cmap, + fb_set_cmap:maxinefb_set_cmap, + fb_ioctl:maxinefb_ioctl, + fb_mmap:0, + fb_rasterimg:0 +}; + +int __init maxinefb_init_one() +{ + volatile unsigned char *fboff; + int i; + + /* Framebuffer display memory base address */ + fb_start = DS5000_xx_ONBOARD_FBMEM_START; + + /* Clear screen */ + for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++) + *fboff = 0x0; + + /* erase hardware cursor */ + for (i = 0; i < 512; i++) { + maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i, + 0); + /* + if (i&0x8 == 0) + maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0x0f); + else + maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0xf0); + */ + } + + /* Fill in the available video resolution */ + maxinefb_defined.xres = 1024; + maxinefb_defined.yres = 768; + maxinefb_defined.xres_virtual = 1024; + maxinefb_defined.yres_virtual = 768; + maxinefb_defined.bits_per_pixel = 8; + + /* Let there be consoles... */ + + strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8"); + /* fb_info.modename: maximum of 39 characters + trailing nullbyte, KM */ + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &maxinefb_ops; + fb_info.disp = &disp; + fb_info.switch_con = &maxinefb_switch; + fb_info.updatevar = &maxinefb_fb_update_var; + fb_info.blank = &maxinefb_blank; + fb_info.flags = FBINFO_FLAG_DEFAULT; + maxinefb_do_fb_set_var(&maxinefb_defined, 1); + + maxinefb_get_var(&disp.var, -1, &fb_info); + maxinefb_set_disp(-1); + + if (register_framebuffer(&fb_info) < 0) + return 1; + + return 0; +} + + +/* Initialise the framebuffer */ + +void __init maxinefb_init() +{ + unsigned int sid; + + if (mips_machtype == MACH_DS5000_XX) { + printk("Maxinefb: Personal DECstation detected\n"); + printk("Maxinefb: initializing onboard framebuffer\n"); + + maxinefb_init_one(); + + } + +} + +void __init maxinefb_setup(char *options, int *ints) +{ +} diff --git a/drivers/video/maxinefb.h b/drivers/video/maxinefb.h new file mode 100644 index 000000000..f85b718b8 --- /dev/null +++ b/drivers/video/maxinefb.h @@ -0,0 +1,37 @@ +/* + * linux/drivers/video/maxinefb.h + * + * DECstation 5000/xx onboard framebuffer support, Copyright (C) 1999 by + * Michael Engel <engel@unix-ag.org> and Karsten Merker <merker@guug.de> + * 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. + */ + + +/* + * IMS332 video controller register base address + */ +#define MAXINEFB_IMS332_ADDRESS 0xbc140000 + +/* + * Begin of DECstation 5000/xx onboard framebuffer memory, default resolution + * is 1024x768x8 + */ +#define DS5000_xx_ONBOARD_FBMEM_START 0xaa000000 + +/* + * The IMS 332 video controller used in the DECstation 5000/xx series + * uses 32 bits wide registers; the following defines declare the + * register numbers, to get the real offset, these have to be multiplied + * by four. + */ + +#define IMS332_REG_CURSOR_RAM 0x200 /* hardware cursor bitmap */ + +/* + * The color palette entries have the form 0x00BBGGRR + */ +#define IMS332_REG_COLOR_PALETTE 0x100 /* color palette, 256 entries */ +#define IMS332_REG_CURSOR_COLOR_PALETTE 0x0a1 /* cursor color palette, */ + /* 3 entries */ diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index 7987082fc..1ba65e446 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -1,5 +1,5 @@ /* - * linux/drivers/video/pmagbafb.c + * linux/drivers/video/pmag-ba-fb.c * * PMAG-BA TurboChannel framebuffer card support ... derived from: * "HP300 Topcat framebuffer support (derived from macfb of all things) @@ -10,9 +10,10 @@ * "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>. + * DECstation related code Copyright (C) 1999, 2000, 2001 by + * Michael Engel <engel@unix-ag.org>, + * Karsten Merker <merker@linuxtag.org> 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. @@ -33,6 +34,7 @@ #include <asm/bootinfo.h> #include <asm/dec/machtype.h> #include <asm/dec/tc.h> +#include "pmag-ba-fb.h" #include <video/fbcon.h> #include <video/fbcon-mfb.h> @@ -42,18 +44,7 @@ #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 { +struct pmag_ba_ramdac_regs { unsigned char addr_low; unsigned char pad0[3]; unsigned char addr_hi; @@ -63,9 +54,9 @@ struct ramdac_regs { unsigned char cmap; }; -struct my_fb_info { +struct pmag_ba_my_fb_info { struct fb_info info; - struct ramdac_regs *bt459_regs; + struct pmag_ba_ramdac_regs *bt459_regs; unsigned long pmagba_fb_start; unsigned long pmagba_fb_size; unsigned long pmagba_fb_line_length; @@ -75,7 +66,7 @@ static struct display disp; /* * Max 3 TURBOchannel slots -> max 3 PMAG-BA :) */ -static struct my_fb_info pmagba_fb_info[3]; +static struct pmag_ba_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 */ @@ -157,7 +148,7 @@ static int pmagba_do_fb_set_var(struct fb_var_screeninfo *var, /* * Turn hardware cursor off */ -void pmagbafb_erase_cursor(struct my_fb_info *info) +void pmagbafb_erase_cursor(struct pmag_ba_my_fb_info *info) { info->bt459_regs->addr_low = 0; info->bt459_regs->addr_hi = 3; @@ -167,8 +158,8 @@ void pmagbafb_erase_cursor(struct my_fb_info *info) /* * Write to a Bt459 color map register */ -void bt459_write_colormap(struct my_fb_info *info, - int reg, __u8 red, __u8 green, __u8 blue) +void pmag_ba_bt459_write_colormap(struct pmag_ba_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; @@ -193,9 +184,9 @@ static int pmagbafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, length = cmap->len; } for (i = 0; i < length; i++) { - /* - * TODO - */ + /* + * TODO + */ } return 0; } @@ -220,9 +211,10 @@ static int pmagbafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 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); + pmag_ba_bt459_write_colormap((struct pmag_ba_my_fb_info *) + info, cmap->start + i, + cmap_red, cmap_green, + cmap_blue); } return 0; } @@ -252,14 +244,11 @@ static int pmagbafb_set_var(struct fb_var_screeninfo *var, int con, static void pmagbafb_encode_fix(struct fb_fix_screeninfo *fix, struct pmagbafb_par *par, - struct my_fb_info *info) + struct pmag_ba_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; @@ -274,10 +263,10 @@ 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); - + pmagbafb_encode_fix(fix, &par, (struct pmag_ba_my_fb_info *) info); + return 0; } @@ -293,7 +282,7 @@ static int pmagbafb_switch(int con, struct fb_info *info) { pmagba_do_fb_set_var(&fb_display[con].var, 1); currcon = con; - + return 0; } @@ -313,7 +302,7 @@ static int pmagbafb_open(struct fb_info *info, int user) return (0); } -static void pmagbafb_set_disp(int con, struct my_fb_info *info) +static void pmagbafb_set_disp(int con, struct pmag_ba_my_fb_info *info) { struct fb_fix_screeninfo fix; struct display *display; @@ -346,31 +335,33 @@ static int pmagbafb_release(struct fb_info *info, int user) } 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 + 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]; + struct pmag_ba_my_fb_info *ip = + (struct pmag_ba_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->bt459_regs = + (struct pmag_ba_ramdac_regs *) (base_addr + + PMAG_BA_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; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c new file mode 100644 index 000000000..3b642b173 --- /dev/null +++ b/drivers/video/pmagb-b-fb.c @@ -0,0 +1,434 @@ +/* + * linux/drivers/video/pmagb-b-fb.c + * + * PMAGB-B 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. + * + * DECstation related code Copyright (C) 1999, 2000, 2001 by + * Michael Engel <engel@unix-ag.org>, + * Karsten Merker <merker@linuxtag.org> 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. + * + */ + +/* + * We currently only support the PMAGB-B in high resolution mode + * as I know of no way to detect low resolution mode set via jumper. + * KM, 2001/01/07 + */ + +#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 "pmagb-b-fb.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))) + +struct pmagb_b_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 pmagb_b_my_fb_info { + struct fb_info info; + struct pmagb_b_ramdac_regs *bt459_regs; + unsigned long pmagbb_fb_start; + unsigned long pmagbb_fb_size; + unsigned long pmagbb_fb_line_length; +}; + +static struct display disp; +/* + * Max 3 TURBOchannel slots -> max 3 PMAGB-B :) + */ +static struct pmagb_b_my_fb_info pmagbb_fb_info[3]; + +static struct fb_var_screeninfo pmagbbfb_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 pmagbbfb_par { +}; + +static int currcon = 0; +struct pmagbbfb_par current_par; + +static void pmagbbfb_encode_var(struct fb_var_screeninfo *var, + struct pmagbbfb_par *par) +{ + int i = 0; + var->xres = 1280; + var->yres = 1024; + var->xres_virtual = 1280; + var->yres_virtual = 1024; + 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 pmagbbfb_get_par(struct pmagbbfb_par *par) +{ + *par = current_par; +} + +static int pmagbb_fb_update_var(int con, struct fb_info *info) +{ + return 0; +} + +static int pmagbb_do_fb_set_var(struct fb_var_screeninfo *var, + int isactive) +{ + struct pmagbbfb_par par; + + pmagbbfb_get_par(&par); + pmagbbfb_encode_var(var, &par); + return 0; +} + +/* + * Turn hardware cursor off + */ +void pmagbbfb_erase_cursor(struct pmagb_b_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 pmagb_b_bt459_write_colormap(struct pmagb_b_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 pmagbbfb_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 pmagbbfb_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 */ + + pmagb_b_bt459_write_colormap((struct pmagb_b_my_fb_info *) + info, cmap->start + i, + cmap_red, cmap_green, + cmap_blue); + } + return 0; +} + +static int pmagbbfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct pmagbbfb_par par; + if (con == -1) { + pmagbbfb_get_par(&par); + pmagbbfb_encode_var(var, &par); + } else + *var = fb_display[con].var; + return 0; +} + + +static int pmagbbfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err; + + if ((err = pmagbb_do_fb_set_var(var, 1))) + return err; + return 0; +} + +static void pmagbbfb_encode_fix(struct fb_fix_screeninfo *fix, + struct pmagbbfb_par *par, + struct pmagb_b_my_fb_info *info) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "PMAGB-BA"); + + fix->smem_start = info->pmagbb_fb_start; + fix->smem_len = info->pmagbb_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->pmagbb_fb_line_length; +} + +static int pmagbbfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct pmagbbfb_par par; + + pmagbbfb_get_par(&par); + pmagbbfb_encode_fix(fix, &par, (struct pmagb_b_my_fb_info *) info); + + return 0; +} + + +static int pmagbbfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + return -EINVAL; +} + +static int pmagbbfb_switch(int con, struct fb_info *info) +{ + pmagbb_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 pmagbbfb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +static int pmagbbfb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return (0); +} + +static void pmagbbfb_set_disp(int con, struct pmagb_b_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 */ + + pmagbbfb_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 pmagbbfb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return (0); +} + +static struct fb_ops pmagbbfb_ops = { + owner:THIS_MODULE, + fb_open:pmagbbfb_open, + fb_release:pmagbbfb_release, + fb_get_fix:pmagbbfb_get_fix, + fb_get_var:pmagbbfb_get_var, + fb_set_var:pmagbbfb_set_var, + fb_get_cmap:pmagbbfb_get_cmap, + fb_set_cmap:pmagbbfb_set_cmap, + fb_ioctl:pmagbbfb_ioctl, + fb_mmap:0, + fb_rasterimg:0 +}; + +int __init pmagbbfb_init_one(int slot) +{ + unsigned long base_addr = get_tc_base_addr(slot); + struct pmagb_b_my_fb_info *ip = + (struct pmagb_b_my_fb_info *) &pmagbb_fb_info[slot]; + + printk("PMAGB-BA framebuffer in slot %d\n", slot); + + /* + * Framebuffer display memory base address and friends + */ + ip->bt459_regs = + (struct pmagb_b_ramdac_regs *) (base_addr + + PMAGB_B_BT459_OFFSET); + ip->pmagbb_fb_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET; + ip->pmagbb_fb_size = 1280 * 1024; + ip->pmagbb_fb_line_length = 1280; + + /* + * Configure the Bt459 RAM DAC + */ + pmagbbfb_erase_cursor(ip); + + /* + * Fill in the available video resolution + */ + + pmagbbfb_defined.xres = 1280; + pmagbbfb_defined.yres = 1024; + pmagbbfb_defined.xres_virtual = 1280; + pmagbbfb_defined.yres_virtual = 1024; + pmagbbfb_defined.bits_per_pixel = 8; + + /* + * Let there be consoles.. + */ + strcpy(ip->info.modename, "PMAGB-BA"); + ip->info.changevar = NULL; + ip->info.node = -1; + ip->info.fbops = &pmagbbfb_ops; + ip->info.disp = &disp; + ip->info.switch_con = &pmagbbfb_switch; + ip->info.updatevar = &pmagbb_fb_update_var; + ip->info.blank = &pmagbbfb_blank; + ip->info.flags = FBINFO_FLAG_DEFAULT; + + pmagbb_do_fb_set_var(&pmagbbfb_defined, 1); + pmagbbfb_get_var(&disp.var, -1, (struct fb_info *) ip); + pmagbbfb_set_disp(-1, ip); + + if (register_framebuffer((struct fb_info *) ip) < 0) + return 1; + + return 0; +} + +/* + * Initialise the framebuffer + */ + +int __init pmagbbfb_init(void) +{ + int sid; + int found = 0; + + if (TURBOCHANNEL) { + while ((sid = search_tc_card("PMAGB-BA")) >= 0) { + found = 1; + claim_tc_card(sid); + pmagbbfb_init_one(sid); + } + return found ? 0 : -ENODEV; + } else { + return -ENODEV; + } +} + +int __init pmagbbfb_setup(char *options) +{ + return 0; +} diff --git a/drivers/video/pmagb-b-fb.h b/drivers/video/pmagb-b-fb.h new file mode 100644 index 000000000..e93eafa49 --- /dev/null +++ b/drivers/video/pmagb-b-fb.h @@ -0,0 +1,32 @@ +/* + * linux/drivers/video/pmagb-b-fb.h + * + * TurboChannel PMAGB-B framebuffer card support, + * Copyright (C) 1999, 2000, 2001 by + * Michael Engel <engel@unix-ag.org> and + * Karsten Merker <merker@linxutag.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. + */ + + +/* + * Bt459 RAM DAC register base offset (rel. to TC slot base address) + */ +#define PMAGB_B_BT459_OFFSET 0x001C0000 + +/* + * Begin of PMAGB-B framebuffer memory, resolution is configurable: + * 1024x864x8 or 1280x1024x8, settable by jumper on the card + */ +#define PMAGB_B_ONBOARD_FBMEM_OFFSET 0x00201000 + +/* + * Bt459 register offsets, byte-wide registers + */ + +#define BT459_ADR_LOW BT459_OFFSET + 0x00 /* addr. low */ +#define BT459_ADR_HIGH BT459_OFFSET + 0x04 /* addr. high */ +#define BT459_DATA BT459_OFFSET + 0x08 /* r/w data */ +#define BT459_CMAP BT459_OFFSET + 0x0C /* color map */ |