diff options
Diffstat (limited to 'drivers/video')
59 files changed, 8600 insertions, 4327 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 06dacf03f..9fb8d3905 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -6,7 +6,8 @@ if [ "$CONFIG_FB" = "y" ]; then define_bool CONFIG_DUMMY_CONSOLE y if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then - bool 'Permedia2 support (experimental)' CONFIG_FB_PM2 + tristate 'Cirrus Logic suport (experimental)' CONFIG_FB_CLGEN + tristate 'Permedia2 support (experimental)' CONFIG_FB_PM2 if [ "$CONFIG_FB_PM2" = "y" ]; then if [ "$CONFIG_PCI" = "y" ]; then bool ' enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT @@ -43,13 +44,12 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3 - tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN bool 'Amiga FrameMaster II/Rainbow II support (experimental)' CONFIG_FB_FM2 fi fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Atari native chipset support' CONFIG_FB_ATARI - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY fi if [ "$CONFIG_PPC" = "y" ]; then bool 'Open Firmware frame buffer device support' CONFIG_FB_OF @@ -57,11 +57,12 @@ if [ "$CONFIG_FB" = "y" ]; then bool 'Apple "control" display support' CONFIG_FB_CONTROL bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT bool 'Chips 65550 display support' CONFIG_FB_CT65550 bool 'S3 Trio display support' CONFIG_FB_S3TRIO fi + tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16 fi if [ "$CONFIG_MAC" = "y" ]; then define_bool CONFIG_FB_MAC y @@ -74,7 +75,7 @@ if [ "$CONFIG_FB" = "y" ]; then fi if [ "$ARCH" = "i386" ]; then bool 'VESA VGA graphics console' CONFIG_FB_VESA - bool 'VGA 16-color graphics console' CONFIG_FB_VGA16 + tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16 define_bool CONFIG_VIDEO_SELECT y fi if [ "$CONFIG_VISWS" = "y" ]; then @@ -86,10 +87,10 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_FB_MATROX" != "n" ]; then bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM bool ' Mystique support' CONFIG_FB_MATROX_MYSTIQUE - bool ' G100/G200 support' CONFIG_FB_MATROX_G100 + bool ' G100/G200/G400 support' CONFIG_FB_MATROX_G100 bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi - bool 'ATI Mach64 display support' CONFIG_FB_ATY + tristate 'ATI Mach64 display support' CONFIG_FB_ATY fi fi if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then @@ -104,6 +105,7 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$ARCH" = "sparc" ]; then bool ' TCX (SS4/SS5 only) support' CONFIG_FB_TCX bool ' CGfourteen (SX) support' CONFIG_FB_CGFOURTEEN + bool ' P9100 (Sparcbook 3 only) support' CONFIG_FB_P9100 fi bool ' Leo (ZX) support' CONFIG_FB_LEO fi @@ -120,7 +122,7 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_PCI" != "n" ]; then bool 'PCI framebuffers' CONFIG_FB_PCI if [ "$CONFIG_FB_PCI" != "n" ]; then - bool ' ATI Mach64 display support' CONFIG_FB_ATY + tristate ' ATI Mach64 display support' CONFIG_FB_ATY fi fi fi @@ -142,7 +144,7 @@ if [ "$CONFIG_FB" = "y" ]; then tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 # tristate 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC - bool 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES + tristate 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA else # Guess what we need @@ -183,6 +185,7 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ + "$CONFIG_FB_P9100" = "y" -o \ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" ]; then define_bool CONFIG_FBCON_CFB8 y else @@ -197,6 +200,7 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ + "$CONFIG_FB_P9100" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then define_bool CONFIG_FBCON_CFB8 m fi @@ -287,6 +291,10 @@ if [ "$CONFIG_FB" = "y" ]; then fi if [ "$CONFIG_FB_VGA16" = "y" ]; then define_bool CONFIG_FBCON_VGA_PLANES y + else + if [ "$CONFIG_FB_VGA16" = "m" ]; then + define_bool CONFIG_FBCON_VGA_PLANES m + fi fi if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then define_bool CONFIG_FBCON_VGA y diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 24f5218c6..8e328ed1e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -37,7 +37,7 @@ endif ifeq ($(CONFIG_FB),y) L_OBJS += fonts.o - OX_OBJS += fbcon.o fbcmap.o fbmem.o + OX_OBJS += fbcon.o fbcmap.o fbmem.o modedb.o ifeq ($(CONFIG_FONT_8x8),y) L_OBJS += font_8x8.o endif @@ -82,6 +82,11 @@ endif ifeq ($(CONFIG_FB_PM2),y) L_OBJS += pm2fb.o CONFIG_FBGEN_BUILTIN = y +else + ifeq ($(CONFIG_FB_PM2),m) + M_OBJS += pm2fb.o + CONFIG_FBGEN_MODULE = y + endif endif ifeq ($(CONFIG_FB_APOLLO),y) @@ -102,6 +107,10 @@ endif ifeq ($(CONFIG_FB_ATY),y) L_OBJS += atyfb.o +else + ifeq ($(CONFIG_FB_ATY),m) + M_OBJS += atyfb.o + endif endif ifeq ($(CONFIG_FB_IGA),y) @@ -206,6 +215,10 @@ endif ifeq ($(CONFIG_FB_VGA16),y) L_OBJS += vga16fb.o +else + ifeq ($(CONFIG_FB_VGA16),m) + M_OBJS += vga16fb.o + endif endif ifeq ($(CONFIG_FB_VIRGE),y) @@ -272,6 +285,13 @@ L_OBJS += sbusfb.o M_OBJS += cgfourteenfb.o endif endif + ifeq ($(CONFIG_FB_P9100),y) + L_OBJS += p9100fb.o + else + ifeq ($(CONFIG_FB_P9100),m) + M_OBJS += p9100fb.o + endif + endif ifeq ($(CONFIG_FB_LEO),y) L_OBJS += leofb.o else @@ -324,6 +344,13 @@ else M_OBJS += cgfourteenfb.o endif endif + ifeq ($(CONFIG_FB_P9100),y) + M_OBJS += p9100fb.o + else + ifeq ($(CONFIG_FB_P9100),m) + M_OBJS += p9100fb.o + endif + endif ifeq ($(CONFIG_FB_LEO),y) M_OBJS += leofb.o else diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index c83c83c96..22fb32ab1 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -99,7 +99,7 @@ static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -void s3triofb_init(void); +int s3triofb_init(void); static int s3triofbcon_switch(int con, struct fb_info *info); static int s3triofbcon_updatevar(int con, struct fb_info *info); static void s3triofbcon_blank(int blank, struct fb_info *info); @@ -288,7 +288,7 @@ static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd, return -EINVAL; } -__initfunc(void s3triofb_init(void)) +int __init s3triofb_init(void) { #ifdef __powerpc__ /* We don't want to be called like this. */ @@ -296,9 +296,10 @@ __initfunc(void s3triofb_init(void)) #else /* !__powerpc__ */ /* To be merged with cybervision */ #endif /* !__powerpc__ */ + return 0; } -__initfunc(void s3trio_resetaccel(void)) { +void __init s3trio_resetaccel(void){ #define EC01_ENH_ENB 0x0005 @@ -341,7 +342,7 @@ __initfunc(void s3trio_resetaccel(void)) { outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX, 0xbee8); } -__initfunc(int s3trio_init(struct device_node *dp)) { +int __init s3trio_init(struct device_node *dp){ u_char bus, dev; unsigned int t32; @@ -402,7 +403,7 @@ __initfunc(int s3trio_init(struct device_node *dp)) { * We heavily rely on OF for the moment. This needs fixing. */ -__initfunc(void s3triofb_init_of(struct device_node *dp)) +void __init s3triofb_init_of(struct device_node *dp) { int i, *pp, len; unsigned long address; @@ -445,11 +446,11 @@ __initfunc(void s3triofb_init_of(struct device_node *dp)) s3trio_init(dp); address = 0xc6000000; s3trio_base = ioremap(address,64*1024*1024); - fb_fix.smem_start = (char *)address; + fb_fix.smem_start = address; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; fb_fix.accel = FB_ACCEL_S3_TRIO64; - fb_fix.mmio_start = (char *)address+0x1000000; + fb_fix.mmio_start = address+0x1000000; fb_fix.mmio_len = 0x1000000; fb_fix.xpanstep = 1; @@ -721,9 +722,9 @@ static void do_install_cmap(int con, struct fb_info *info) s3trio_setcolreg, &fb_info); } -void s3triofb_setup(char *options, int *ints) { +int s3triofb_setup(char *options) { - return; + return 0; } diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 42485a999..8efdcbe59 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -34,6 +34,7 @@ #include <video/fbcon-cfb4.h> #include <video/fbcon-cfb8.h> #include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb32.h> /* * Default resolution. @@ -58,7 +59,7 @@ #endif #define EXTEND8(x) ((x)|(x)<<8) -#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<16) +#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12) struct vidc20_palette { u_int red:8; @@ -554,14 +555,14 @@ acornfb_vidc20_find_rates(struct vidc_timing *vidc, bandwidth = var->pixclock * 8 / var->bits_per_pixel; /* Encode bandwidth as VIDC20 setting */ - if (bandwidth > 16667*2) - vidc->control |= VIDC20_CTRL_FIFO_16; - else if (bandwidth > 13333*2) - vidc->control |= VIDC20_CTRL_FIFO_20; - else if (bandwidth > 11111*2) - vidc->control |= VIDC20_CTRL_FIFO_24; + if (bandwidth > 33334) + vidc->control |= VIDC20_CTRL_FIFO_16; /* < 30.0MB/s */ + else if (bandwidth > 26666) + vidc->control |= VIDC20_CTRL_FIFO_20; /* < 37.5MB/s */ + else if (bandwidth > 22222) + vidc->control |= VIDC20_CTRL_FIFO_24; /* < 45.0MB/s */ else - vidc->control |= VIDC20_CTRL_FIFO_28; + vidc->control |= VIDC20_CTRL_FIFO_28; /* > 45.0MB/s */ /* Find the PLL values */ vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div); @@ -742,7 +743,7 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue, * Before selecting the timing parameters, adjust * the resolution to fit the rules. */ -static void +static int acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con) { u_int font_line_len; @@ -785,6 +786,13 @@ acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con) font_line_len = var->xres * var->bits_per_pixel * fontht / 8; min_size = var->xres * var->yres * var->bits_per_pixel / 8; + /* + * If minimum screen size is greater than that we have + * available, reject it. + */ + if (min_size > current_par.screen_size) + return -EINVAL; + /* Find int 'y', such that y * fll == s * sam < maxsize * y = s * sam / fll; s = maxsize / sam */ @@ -820,6 +828,7 @@ acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con) if (var->yoffset + var->yres > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; } + return 0; } /* @@ -897,32 +906,75 @@ acornfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, return 0; } +/* + * We have to take note of the VIDC20's 16-bit palette here. + * The VIDC20 looks up a 16 bit pixel as follows: + * + * bits 111111 + * 5432109876543210 + * red ++++++++ (8 bits, 7 to 0) + * green ++++++++ (8 bits, 11 to 4) + * blue ++++++++ (8 bits, 15 to 8) + * + * We use a pixel which looks like: + * + * bits 111111 + * 5432109876543210 + * red +++++ (5 bits, 4 to 0) + * green +++++ (5 bits, 9 to 5) + * blue +++++ (5 bits, 14 to 10) + */ static int acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info) { union palette pal; + int bpp = fb_display[current_par.currcon].var.bits_per_pixel; if (regno >= current_par.palette_size) return 1; pal = acornfb_palette_encode(regno, red, green, blue, trans); - acornfb_palette_write(regno, pal); current_par.palette[regno] = pal; +#ifdef HAS_VIDC20 if (regno < 16) { - switch (info->disp->var.bits_per_pixel) { + switch (bpp) { #ifdef FBCON_HAS_CFB16 - case 16: /* RGB555 */ - current_par.cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno; + case 16: + current_par.cmap.cfb16[regno] = + regno | regno << 5 | regno << 10; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + current_par.cmap.cfb32[regno] = + regno | regno << 8 | regno << 16; break; #endif - default: break; } } +#ifdef FBCON_HAS_CFB16 + if (bpp == 16) { + int i; + + pal.p = 0; + outl(0x10000000, IO_VIDC_BASE); + for (i = 0; i < 256; i += 1) { + pal.vidc20.red = current_par.palette[ i & 31].vidc20.red; + pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green; + pal.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue; + outl(pal.p, IO_VIDC_BASE); + /* Palette register pointer auto-increments */ + } + } else +#endif +#endif + acornfb_palette_write(regno, pal); + return 0; } @@ -965,6 +1017,8 @@ acornfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual) { + int err; + switch (var->bits_per_pixel) { #ifdef FBCON_HAS_MFB case 1: @@ -990,10 +1044,18 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual) *visual = FB_VISUAL_PSEUDOCOLOR; break; #endif +#ifdef HAS_VIDC20 +#ifdef FBCON_HAS_CFB16 case 16: - case 24: + *visual = FB_VISUAL_DIRECTCOLOR; + break; +#endif +#ifdef FBCON_HAS_CFB32 case 32: *visual = FB_VISUAL_TRUECOLOR; + break; +#endif +#endif default: return -EINVAL; } @@ -1002,20 +1064,52 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual) return -EINVAL; /* - * Adjust the resolution before using it. + * Validate and adjust the resolution + * before using it. */ - acornfb_pre_adjust_timing(var, con); + err = acornfb_pre_adjust_timing(var, con); + if (err) + return err; #if defined(HAS_VIDC20) - var->red.length = 8; - var->transp.length = 4; + switch (var->bits_per_pixel) { + case 1: case 2: case 4: case 8: + var->red.offset = 0; + var->red.length = 8; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 4; + break; + + case 16: + var->red.offset = 0; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 10; + var->blue.length = 5; + var->transp.offset = 15; + var->transp.length = 1; + break; + + case 32: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 4; + break; + } #elif defined(HAS_VIDC) var->red.length = 4; + var->green = var->red; + var->blue = var->red; var->transp.length = 1; #endif - var->green = var->red; - var->blue = var->red; - /* * Now adjust the timing parameters */ @@ -1037,7 +1131,7 @@ acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) else display = &global_disp; - fix->smem_start = (char *)current_par.screen_base_p; + fix->smem_start = current_par.screen_base_p; fix->smem_len = current_par.screen_size; fix->type = display->type; fix->type_aux = display->type_aux; @@ -1153,11 +1247,18 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) #endif #ifdef FBCON_HAS_CFB16 case 16: - current_par.palette_size = VIDC_PALETTE_SIZE; + current_par.palette_size = 32; display->dispsw = &fbcon_cfb16; display->dispsw_data = current_par.cmap.cfb16; break; #endif +#ifdef FBCON_HAS_CFB32 + case 32: + current_par.palette_size = VIDC_PALETTE_SIZE; + display->dispsw = &fbcon_cfb32; + display->dispsw_data = current_par.cmap.cfb32; + break; +#endif default: display->dispsw = &fbcon_dummy; break; @@ -1290,19 +1391,32 @@ acornfb_switch(int con, struct fb_info *info) static void acornfb_blank(int blank, struct fb_info *info) { - int i; + union palette p; + int i, bpp = fb_display[current_par.currcon].var.bits_per_pixel; - if (blank) + if (bpp != 16) { for (i = 0; i < current_par.palette_size; i++) { - union palette p; - - p = acornfb_palette_encode(i, 0, 0, 0, 0); + if (blank) + p = acornfb_palette_encode(i, 0, 0, 0, 0); + else + p = current_par.palette[i]; acornfb_palette_write(i, p); } - else - for (i = 0; i < current_par.palette_size; i++) + } else { + p.p = 0; + + for (i = 0; i < 256; i++) { + if (blank) + p = acornfb_palette_encode(i, 0, 0, 0, 0); + else { + p.vidc20.red = current_par.palette[ i & 31].vidc20.red; + p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green; + p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue; + } acornfb_palette_write(i, current_par.palette[i]); + } + } } /* @@ -1429,8 +1543,8 @@ static const struct modex_params modex_params[] __initdata = { } }; -__initfunc(static int -acornfb_lookup_timing(struct fb_var_screeninfo *var)) +static int __init +acornfb_lookup_timing(struct fb_var_screeninfo *var) { const struct modex_params *x; const struct modey_params *y; @@ -1518,8 +1632,8 @@ found: return 0; } -__initfunc(static void -acornfb_init_fbinfo(void)) +static void __init +acornfb_init_fbinfo(void) { static int first = 1; @@ -1612,14 +1726,14 @@ acornfb_init_fbinfo(void)) * size can optionally be followed by 'M' or 'K' for * MB or KB respectively. */ -__initfunc(static void -acornfb_parse_font(char *opt)) +static void __init +acornfb_parse_font(char *opt) { strcpy(fb_info.fontname, opt); } -__initfunc(static void -acornfb_parse_mon(char *opt)) +static void __init +acornfb_parse_mon(char *opt) { fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0); if (*opt == '-') @@ -1652,8 +1766,8 @@ acornfb_parse_mon(char *opt)) init_var.height = simple_strtoul(opt + 1, NULL, 0); } -__initfunc(static void -acornfb_parse_montype(char *opt)) +static void __init +acornfb_parse_montype(char *opt) { current_par.montype = -2; @@ -1694,8 +1808,8 @@ acornfb_parse_montype(char *opt)) } } -__initfunc(static void -acornfb_parse_dram(char *opt)) +static void __init +acornfb_parse_dram(char *opt) { unsigned int size; @@ -1728,14 +1842,14 @@ static struct options { { NULL, NULL } }; -__initfunc(void -acornfb_setup(char *options, int *ints)) +int __init +acornfb_setup(char *options) { struct options *optp; char *opt; if (!options || !*options) - return; + return 0; acornfb_init_fbinfo(); @@ -1759,14 +1873,15 @@ acornfb_setup(char *options, int *ints)) printk(KERN_ERR "acornfb: unknown parameter: %s\n", opt); } + return 0; } /* * Detect type of monitor connected * For now, we just assume SVGA */ -__initfunc(static int -acornfb_detect_monitortype(void)) +static int __init +acornfb_detect_monitortype(void) { return 4; } @@ -1802,8 +1917,8 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end) printk("acornfb: freed %dK memory\n", mb_freed); } -__initfunc(void -acornfb_init(void)) +int __init +acornfb_init(void) { unsigned long size; u_int h_sync, v_sync; @@ -1841,7 +1956,7 @@ acornfb_init(void)) size = PAGE_ALIGN(size); -#ifdef CONFIG_ARCH_RPC +#if defined(HAS_VIDC20) if (!current_par.using_vram) { /* * RiscPC needs to allocate the DRAM memory @@ -1849,17 +1964,30 @@ acornfb_init(void)) * VRAM. Archimedes/A5000 machines use a * fixed address for their framebuffers. */ - current_par.screen_base = (unsigned long)kmalloc(size, GFP_KERNEL); + int order = 0; + unsigned long page, top; + while (size > (PAGE_SIZE * (1 << order))) + order++; + current_par.screen_base = __get_free_pages(GFP_KERNEL, order); if (current_par.screen_base == 0) { printk(KERN_ERR "acornfb: unable to allocate screen " "memory\n"); return; } + top = current_par.screen_base + (PAGE_SIZE * (1 << order)); + /* Mark the framebuffer pages as reserved so mmap will work. */ + for (page = current_par.screen_base; + page < PAGE_ALIGN(current_par.screen_base + size); + page += PAGE_SIZE) + mem_map[MAP_NR(page)].flags |= (1 << PG_reserved); + /* Hand back any excess pages that we allocated. */ + for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE) + free_page(page); current_par.screen_base_p = virt_to_phys(current_par.screen_base); } #endif -#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_ARC) +#if defined(HAS_VIDC) #define MAX_SIZE 480*1024 /* * Limit maximum screen size. @@ -1904,5 +2032,7 @@ acornfb_init(void)) VIDC_NAME, init_var.xres, init_var.yres, h_sync / 1000, h_sync % 1000, v_sync); - register_framebuffer(&fb_info); + if (register_framebuffer(&fb_info) < 0) + return -EINVAL; + return 0; } diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 2aa4a29e3..47531e1bb 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -805,138 +805,86 @@ static char amifb_name[16] = "Amiga "; * */ -static struct fb_videomode amifb_predefined[] __initdata = { +static struct fb_videomode ami_modedb[] __initdata = { /* * AmigaOS Video Modes + * + * If you change these, make sure to update DEFMODE_* as well! */ { - "ntsc", { /* 640x200, 15 kHz, 60 Hz (NTSC) */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 44, 16, 76, 2, - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x200, 15 kHz, 60 Hz (NTSC) */ + "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2, + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "ntsc-lace", { /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 88, 33, 76, 4, - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ + "ntsc-lace", 60, 640, TAG_HIRES, 106, 86, 88, 33, 76, 4, + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "pal", { /* 640x256, 15 kHz, 50 Hz (PAL) */ - 640, 256, 640, 256, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 40, 14, 76, 2, - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x256, 15 kHz, 50 Hz (PAL) */ + "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2, + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "pal-lace", { /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ - 640, 512, 640, 512, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 80, 29, 76, 4, - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ + "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4, + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "multiscan", { /* 640x480, 29 kHz, 57 Hz */ - 640, 480, 640, 480, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 29, 8, 72, 8, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x480, 29 kHz, 57 Hz */ + "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "multiscan-lace", { /* 640x960, 29 kHz, 57 Hz interlaced */ - 640, 960, 640, 960, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 58, 16, 72, 16, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x960, 29 kHz, 57 Hz interlaced */ + "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "euro36", { /* 640x200, 15 kHz, 72 Hz */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 6, 6, 52, 5, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x200, 15 kHz, 72 Hz */ + "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "euro36-lace", { /* 640x400, 15 kHz, 72 Hz interlaced */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 12, 12, 52, 10, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x400, 15 kHz, 72 Hz interlaced */ + "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "euro72", { /* 640x400, 29 kHz, 68 Hz */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 9, 9, 80, 8, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x400, 29 kHz, 68 Hz */ + "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "euro72-lace", { /* 640x800, 29 kHz, 68 Hz interlaced */ - 640, 800, 640, 800, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 18, 18, 80, 16, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x800, 29 kHz, 68 Hz interlaced */ + "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "super72", { /* 800x300, 23 kHz, 70 Hz */ - 800, 300, 800, 300, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 10, 11, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 800x300, 23 kHz, 70 Hz */ + "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "super72-lace", { /* 800x600, 23 kHz, 70 Hz interlaced */ - 800, 600, 800, 600, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 20, 22, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 800x600, 23 kHz, 70 Hz interlaced */ + "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "dblntsc", { /* 640x200, 27 kHz, 57 Hz doublescan */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 18, 17, 80, 4, - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP - } + /* 640x200, 27 kHz, 57 Hz doublescan */ + "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4, + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP }, { - "dblntsc-ff", { /* 640x400, 27 kHz, 57 Hz */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 36, 35, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x400, 27 kHz, 57 Hz */ + "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "dblntsc-lace", { /* 640x800, 27 kHz, 57 Hz interlaced */ - 640, 800, 640, 800, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 72, 70, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x800, 27 kHz, 57 Hz interlaced */ + "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { - "dblpal", { /* 640x256, 27 kHz, 47 Hz doublescan */ - 640, 256, 640, 256, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 14, 13, 80, 4, - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP - } + /* 640x256, 27 kHz, 47 Hz doublescan */ + "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4, + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP }, { - "dblpal-ff", { /* 640x512, 27 kHz, 47 Hz */ - 640, 512, 640, 512, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 28, 27, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x512, 27 kHz, 47 Hz */ + "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "dblpal-lace", { /* 640x1024, 27 kHz, 47 Hz interlaced */ - 640, 1024, 640, 1024, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 56, 54, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - } + /* 640x1024, 27 kHz, 47 Hz interlaced */ + "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, /* @@ -944,19 +892,13 @@ static struct fb_videomode amifb_predefined[] __initdata = { */ { - "vga", { /* 640x480, 31 kHz, 60 Hz (VGA) */ - 640, 480, 640, 480, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 30, 9, 112, 2, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x480, 31 kHz, 60 Hz (VGA) */ + "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "vga70", { /* 640x400, 31 kHz, 70 Hz (VGA) */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 35, 12, 112, 2, - FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 640x400, 31 kHz, 70 Hz (VGA) */ + "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2, + FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, #if 0 @@ -967,41 +909,36 @@ static struct fb_videomode amifb_predefined[] __initdata = { */ { - "a2024-10", { /* 1024x800, 10 Hz */ - 1024, 800, 1024, 800, 0, 0, 2, 0, - {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 1024x800, 10 Hz */ + "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { - "a2024-15", { /* 1024x800, 15 Hz */ - 1024, 800, 1024, 800, 0, 0, 2, 0, - {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - } + /* 1024x800, 15 Hz */ + "a2024-15", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP } #endif }; -#define NUM_TOTAL_MODES arraysize(amifb_predefined) +#define NUM_TOTAL_MODES arraysize(ami_modedb) -static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ -static int amifb_inverse = 0; -static int amifb_usermode __initdata = 0; -static int amifb_userdepth __initdata = -1; +static const char *mode_option __initdata = NULL; +static int round_down_bpp = 1; /* for mode probing */ /* * Some default modes */ -#define DEFMODE_PAL "pal" /* for PAL OCS/ECS */ -#define DEFMODE_NTSC "ntsc" /* for NTSC OCS/ECS */ -#define DEFMODE_AMBER_PAL "pal-lace" /* for flicker fixed PAL (A3000) */ -#define DEFMODE_AMBER_NTSC "ntsc-lace" /* for flicker fixed NTSC (A3000) */ -#define DEFMODE_AGA "vga70" /* for AGA */ -static struct fb_var_screeninfo amifb_default; +#define DEFMODE_PAL 2 /* "pal" for PAL OCS/ECS */ +#define DEFMODE_NTSC 0 /* "ntsc" for NTSC OCS/ECS */ +#define DEFMODE_AMBER_PAL 3 /* "pal-lace" for flicker fixed PAL (A3000) */ +#define DEFMODE_AMBER_NTSC 1 /* "ntsc-lace" for flicker fixed NTSC (A3000) */ +#define DEFMODE_AGA 19 /* "vga70" for AGA */ + + +static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ +static int amifb_inverse = 0; /* @@ -1162,7 +1099,7 @@ static u_short sprfetchmode[3] = { * Interface used by the world */ -void amifb_setup(char *options, int *ints); +int amifb_setup(char*); static int amifb_open(struct fb_info *info, int user); static int amifb_release(struct fb_info *info, int user); @@ -1193,7 +1130,7 @@ static int amifb_set_cursorstate(struct fb_cursorstate *state, int con); * Interface to the low level console driver */ -void amifb_init(void); +int amifb_init(void); static int amifbcon_switch(int con, struct fb_info *info); static int amifbcon_updatevar(int con, struct fb_info *info); static void amifbcon_blank(int blank, struct fb_info *info); @@ -1205,8 +1142,6 @@ static void amifbcon_blank(int blank, struct fb_info *info); static void do_install_cmap(int con, struct fb_info *info); static int flash_cursor(void); static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp); -static void get_video_mode(const char *name); -static void check_default_mode(void); static u_long chipalloc(u_long size); static char *strtoke(char *s,const char *ct); @@ -1259,8 +1194,7 @@ static struct fb_ops amifb_ops = { amifb_pan_display, amifb_ioctl }; - -__initfunc(void amifb_setup(char *options, int *ints)) +int __init amifb_setup(char *options) { char *this_opt; char mcap_spec[80]; @@ -1269,11 +1203,9 @@ __initfunc(void amifb_setup(char *options, int *ints)) fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { - char *p; - if (!strcmp(this_opt, "inverse")) { amifb_inverse = 1; fb_invert_cmaps(); @@ -1285,54 +1217,8 @@ __initfunc(void amifb_setup(char *options, int *ints)) strcpy(fb_info.fontname, this_opt+5); else if (!strncmp(this_opt, "fstart:", 7)) min_fstrt = simple_strtoul(this_opt+7, NULL, 0); - else if (!strncmp(this_opt, "depth:", 6)) - amifb_userdepth = simple_strtoul(this_opt+6, NULL, 0); - else if (!strncmp(this_opt, "size:", 5)) { - p = this_opt + 5; - if (*p != ';') - amifb_default.xres = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p != ';') - amifb_default.yres = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p != ';') - amifb_default.xres_virtual = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p != ';') - amifb_default.yres_virtual = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p) - amifb_default.bits_per_pixel = simple_strtoul(p, NULL, 0); - } else if (!strncmp(this_opt, "timing:", 7)) { - p = this_opt + 7; - if (*p != ';') - amifb_default.left_margin = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p != ';') - amifb_default.right_margin = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p != ';') - amifb_default.upper_margin = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p) - amifb_default.lower_margin = simple_strtoul(p, NULL, 0); - } else if (!strncmp(this_opt, "sync:", 5)) { - p = this_opt + 5; - if (*p != ';') - amifb_default.hsync_len = simple_strtoul(p, NULL, 0); - if (!(p = strchr(p, ';'))) - continue; - if (*++p) - amifb_default.vsync_len = simple_strtoul(p, NULL, 0); - } else - get_video_mode(this_opt); + else + mode_option = this_opt; } if (min_fstrt < 48) @@ -1375,6 +1261,7 @@ __initfunc(void amifb_setup(char *options, int *ints)) cap_invalid: ; } + return 0; } /* @@ -1715,13 +1602,15 @@ static int amifb_set_cursorstate(struct fb_cursorstate *state, int con) * Initialisation */ -__initfunc(void amifb_init(void)) +int __init amifb_init(void) { int tag, i; u_long chipptr; + u_int defmode; + struct fb_var_screeninfo var; if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return; + return -ENXIO; /* * TODO: where should we put this? The DMI Resolver doesn't have a @@ -1732,7 +1621,7 @@ __initfunc(void amifb_init(void)) if (amifb_resolver){ custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | DMAF_BLITTER | DMAF_SPRITE; - return; + return 0; } #endif @@ -1748,9 +1637,8 @@ default_chipset: maxdepth[TAG_HIRES] = 4; maxdepth[TAG_LORES] = 6; maxfmode = TAG_FMODE_1; - if (!amifb_usermode) /* Set the Default Video Mode */ - get_video_mode(amiga_vblank == 50 ? - DEFMODE_PAL : DEFMODE_NTSC); + defmode = amiga_vblank == 50 ? DEFMODE_PAL + : DEFMODE_NTSC; videomemorysize = VIDEOMEMSIZE_OCS; break; #endif /* CONFIG_FB_AMIGA_OCS */ @@ -1763,14 +1651,12 @@ default_chipset: maxdepth[TAG_HIRES] = 4; maxdepth[TAG_LORES] = 6; maxfmode = TAG_FMODE_1; - if (!amifb_usermode) { /* Set the Default Video Mode */ - if (AMIGAHW_PRESENT(AMBER_FF)) - get_video_mode(amiga_vblank == 50 ? - DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC); - else - get_video_mode(amiga_vblank == 50 ? - DEFMODE_PAL : DEFMODE_NTSC); - } + if (AMIGAHW_PRESENT(AMBER_FF)) + defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL + : DEFMODE_AMBER_NTSC; + else + defmode = amiga_vblank == 50 ? DEFMODE_PAL + : DEFMODE_NTSC; if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > VIDEOMEMSIZE_ECS_1M) videomemorysize = VIDEOMEMSIZE_ECS_2M; @@ -1787,8 +1673,7 @@ default_chipset: maxdepth[TAG_HIRES] = 8; maxdepth[TAG_LORES] = 8; maxfmode = TAG_FMODE_4; - if (!amifb_usermode) /* Set the Default Video Mode */ - get_video_mode(DEFMODE_AGA); + defmode = DEFMODE_AGA; if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > VIDEOMEMSIZE_AGA_1M) videomemorysize = VIDEOMEMSIZE_AGA_2M; @@ -1803,7 +1688,7 @@ default_chipset: strcat(amifb_name, "Unknown"); goto default_chipset; #else /* CONFIG_FB_AMIGA_OCS */ - return; + return -ENXIO; #endif /* CONFIG_FB_AMIGA_OCS */ break; } @@ -1824,23 +1709,13 @@ default_chipset: * Replace the Tag Values with the Real Pixel Clock Values */ - if (amifb_userdepth != -1) - amifb_default.bits_per_pixel = amifb_userdepth; for (i = 0; i < NUM_TOTAL_MODES; i++) { - struct fb_var_screeninfo *var = &amifb_predefined[i].var; - tag = var->pixclock; + struct fb_videomode *mode = &ami_modedb[i]; + tag = mode->pixclock; if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { - var->pixclock = pixclock[tag]; - if (var->bits_per_pixel > maxdepth[tag]) - var->bits_per_pixel = maxdepth[tag]; + mode->pixclock = pixclock[tag]; } } - tag = amifb_default.pixclock; - if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { - amifb_default.pixclock = pixclock[tag]; - if (amifb_default.bits_per_pixel > maxdepth[tag]) - amifb_default.bits_per_pixel = maxdepth[tag]; - } /* * These monitor specs are for a typical Amiga monitor (e.g. A1960) @@ -1862,6 +1737,11 @@ default_chipset: fb_info.blank = &amifbcon_blank; fb_info.flags = FBINFO_FLAG_DEFAULT; + if (!fb_find_mode(&var, &fb_info, mode_option, ami_modedb, + NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) + panic("Can't find any usable video mode"); + + round_down_bpp = 0; chipptr = chipalloc(videomemorysize+ SPRITEMEMSIZE+ DUMMYSPRITEMEMSIZE+ @@ -1904,9 +1784,7 @@ default_chipset: ami_init_copper(); - check_default_mode(); - - if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, IRQ_FLG_LOCK, + if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0, "fb vertb handler", NULL)) panic("Couldn't add vblank interrupt\n"); ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER; @@ -1914,10 +1792,10 @@ default_chipset: custom.intena = IF_VERTB; custom.intena = IF_SETCLR | IF_COPER; - amifb_set_var(&amifb_default, -1, &fb_info); + amifb_set_var(&var, -1, &fb_info); if (register_framebuffer(&fb_info) < 0) - return; + return -EINVAL; printk("fb%d: %s frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), fb_info.modename, @@ -1925,6 +1803,8 @@ default_chipset: /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; + + return 0; } static int amifbcon_switch(int con, struct fb_info *info) @@ -2050,47 +1930,10 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp) } /* - * Get a Video Mode - */ - -__initfunc(static void get_video_mode(const char *name)) -{ - int i; - - for (i = 0; i < NUM_TOTAL_MODES; i++) { - if (!strcmp(name, amifb_predefined[i].name)) { - amifb_default = amifb_predefined[i].var; - amifb_usermode = i; - return; - } - } -} - - /* - * Probe the Video Modes - */ - -__initfunc(static void check_default_mode(void)) -{ - struct amifb_par par; - int mode; - - if (!ami_decode_var(&amifb_default, &par)) - return; - printk("Can't use default video mode. Probing video modes...\n"); - for (mode = 0; mode < NUM_TOTAL_MODES; mode++) - if (!ami_decode_var(&amifb_predefined[mode].var, &par)) { - amifb_default = amifb_predefined[mode].var; - return; - } - panic("Can't find any usable video mode"); -} - - /* * Allocate, Clear and Align a Block of Chip Memory */ -__initfunc(static u_long chipalloc(u_long size)) +static u_long __init chipalloc(u_long size) { u_long ptr; @@ -2107,7 +1950,7 @@ __initfunc(static u_long chipalloc(u_long size)) * A strtok which returns empty strings, too */ -__initfunc(static char *strtoke(char *s,const char *ct)) +static char __init *strtoke(char *s,const char *ct) { char *sbegin, *send; static char *ssave = NULL; @@ -2138,7 +1981,7 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, amifb_name); - fix->smem_start = (char *)videomemory_phys; + fix->smem_start = videomemory_phys; fix->smem_len = videomemorysize; #ifdef FBCON_HAS_MFB @@ -2215,8 +2058,12 @@ static int ami_decode_var(struct fb_var_screeninfo *var, if (par->bpp < 1) par->bpp = 1; if (par->bpp > maxdepth[clk_shift]) { - DPRINTK("invalid bpp\n"); - return -EINVAL; + if (round_down_bpp && maxdepth[clk_shift]) + par->bpp = maxdepth[clk_shift]; + else { + DPRINTK("invalid bpp\n"); + return -EINVAL; + } } } else if (var->nonstd == FB_NONSTD_HAM) { if (par->bpp < 6) @@ -3314,7 +3161,7 @@ static void ami_set_sprite(void) * Initialise the Copper Initialisation List */ -__initfunc(static void ami_init_copper(void)) +static void __init ami_init_copper(void) { copins *cop = copdisplay.init; u_long p; @@ -3520,8 +3367,7 @@ static void ami_rebuild_copper(void) #ifdef MODULE int init_module(void) { - amifb_init(); - return 0; + return amifb_init(); } void cleanup_module(void) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index e35a79e0b..8f163cd8c 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -2745,14 +2745,14 @@ atafb_blank(int blank, struct fb_info *info) do_install_cmap(currcon, info); } -__initfunc(void atafb_init(void)) +int __init atafb_init(void) { int pad; int detected_mode; unsigned long mem_req; if (!MACH_IS_ATARI) - return; + return -ENXIO; do { #ifdef ATAFB_EXT @@ -2828,9 +2828,12 @@ __initfunc(void atafb_init(void)) /* Map the video memory (physical address given) to somewhere * in the kernel address space. */ - external_addr = ioremap_writethrough(external_addr, external_len); + external_addr = + ioremap_writethrough((unsigned long)external_addr, + external_len); if (external_vgaiobase) - external_vgaiobase = ioremap(external_vgaiobase, 0x10000 ); + external_vgaiobase = + (unsigned long)ioremap(external_vgaiobase, 0x10000); screen_base = real_screen_base = external_addr; screen_len = external_len & PAGE_MASK; @@ -2855,7 +2858,7 @@ __initfunc(void atafb_init(void)) do_install_cmap(0, &fb_info); if (register_framebuffer(&fb_info) < 0) - return; + return -EINVAL; printk("Determined %dx%d, depth %d\n", disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); @@ -2868,6 +2871,8 @@ __initfunc(void atafb_init(void)) /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; + + return 0; } /* a strtok which returns empty strings, too */ @@ -2892,7 +2897,7 @@ static char * strtoke(char * s,const char * ct) return sbegin; } -__initfunc(void atafb_setup( char *options, int *ints )) +int __init atafb_setup( char *options ) { char *this_opt; int temp; @@ -2907,7 +2912,7 @@ __initfunc(void atafb_setup( char *options, int *ints )) fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; @@ -3069,7 +3074,7 @@ __initfunc(void atafb_setup( char *options, int *ints )) external_yres = yres; external_depth = depth; external_pmode = planes; - external_addr = addr; + external_addr = (void *)addr; external_len = len; if (external_card_type == IS_MV300) @@ -3143,13 +3148,13 @@ __initfunc(void atafb_setup( char *options, int *ints )) user_invalid: ; } + return 0; } #ifdef MODULE int init_module(void) { - atafb_init(); - return 0; + return atafb_init(); } void cleanup_module(void) diff --git a/drivers/video/aty.h b/drivers/video/aty.h index 667e7c3ec..e7b6620ad 100644 --- a/drivers/video/aty.h +++ b/drivers/video/aty.h @@ -88,6 +88,8 @@ #define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 0_2D */ #define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 0_2E */ +#define I2C_CNTL_1 0x00BC /* Dword offset 0_2F */ + #define DAC_REGS 0x00C0 /* Dword offset 0_30 */ #define DAC_W_INDEX 0x00C0 /* Dword offset 0_30 */ #define DAC_DATA 0x00C1 /* Dword offset 0_30 */ diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index 522b790ed..f12fec6e1 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $ +/* $Id: atyfb.c,v 1.122 1999/09/06 20:44:08 geert Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -72,8 +72,8 @@ #ifdef __sparc__ #include <asm/pbm.h> #include <asm/fbio.h> -#include <asm/uaccess.h> #endif +#include <asm/uaccess.h> #include <video/fbcon.h> #include <video/fbcon-cfb8.h> @@ -89,8 +89,34 @@ */ #undef DEBUG +/* Definitions for the ICS 2595 == ATI 18818_1 Clockchip */ + +#define REF_FREQ_2595 1432 /* 14.33 MHz (exact 14.31818) */ +#define REF_DIV_2595 46 /* really 43 on ICS 2595 !!! */ + /* ohne Prescaler */ +#define MAX_FREQ_2595 15938 /* 159.38 MHz (really 170.486) */ +#define MIN_FREQ_2595 8000 /* 80.00 MHz ( 85.565) */ + /* mit Prescaler 2, 4, 8 */ +#define ABS_MIN_FREQ_2595 1000 /* 10.00 MHz (really 10.697) */ +#define N_ADJ_2595 257 + +#define STOP_BITS_2595 0x1800 + + +#define MIN_N_408 2 + +#define MIN_N_1703 6 -#define GUI_RESERVE 0x00001000 +#define MIN_M 2 +#define MAX_M 30 +#define MIN_N 35 +#define MAX_N 255-8 + + +/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */ +/* - must be large enough to catch all GUI-Regs */ +/* - must be aligned to a PAGE boundary */ +#define GUI_RESERVE (1 * PAGE_SIZE) #ifndef __powerpc__ @@ -126,6 +152,14 @@ struct pll_gx { u8 n; }; +struct pll_18818 +{ + u32 program_bits; + u32 locationAddr; + u32 period_in_ps; + u32 post_divider; +}; + struct pll_ct { u8 pll_ref_div; u8 pll_gen_cntl; @@ -136,6 +170,8 @@ struct pll_ct { u8 pll_ext_cntl; u32 dsp_config; /* Mach64 GTB DSP */ u32 dsp_on_off; /* Mach64 GTB DSP */ + u8 mclk_post_div_real; + u8 vclk_post_div_real; }; @@ -148,6 +184,7 @@ struct atyfb_par { union { struct pll_gx gx; struct pll_ct ct; + struct pll_18818 ics2595; } pll; u32 accel_flags; }; @@ -189,10 +226,12 @@ struct aty_cursor { struct fb_info_aty { struct fb_info fb_info; + struct fb_info_aty *next; unsigned long ati_regbase_phys; unsigned long ati_regbase; unsigned long frame_buffer_phys; unsigned long frame_buffer; + unsigned long clk_wr_offset; struct pci_mmap_map *mmap_map; struct aty_cursor *cursor; struct aty_cmap_regs *aty_cmap_regs; @@ -210,6 +249,7 @@ struct fb_info_aty { u8 bus_type; u8 ram_type; u8 dac_type; + u8 dac_subtype; u8 clk_type; u8 mem_refresh_rate; struct display disp; @@ -259,6 +299,7 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma); #endif +static int atyfb_rasterimg(struct fb_info *info, int start); /* @@ -325,6 +366,7 @@ static char *strtoke(char *s, const char *ct); static void reset_engine(const struct fb_info_aty *info); static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info); + static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info); static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info); static u8 aty_ld_pll(int offset, const struct fb_info_aty *info); @@ -338,18 +380,51 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var); static void aty_set_pll_gx(const struct fb_info_aty *info, const struct pll_gx *pll); -static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll); + +static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp, + u32 AccelMode); +static int aty_set_dac_ATT21C498(const struct fb_info_aty *info, + const struct pll_18818 *pll, u32 bpp); +void aty_dac_waste4(const struct fb_info_aty *info); + +static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll); +static u32 aty_pll_18818_to_var(const struct pll_18818 *pll); +static void aty_set_pll18818(const struct fb_info_aty *info, + const struct pll_18818 *pll); + +static void aty_StrobeClock(const struct fb_info_aty *info); + +static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info); + +static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll); +static u32 aty_pll_408_to_var(const struct pll_18818 *pll); +static void aty_set_pll_408(const struct fb_info_aty *info, + const struct pll_18818 *pll); + +static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll); +static u32 aty_pll_1703_to_var(const struct pll_18818 *pll); +static void aty_set_pll_1703(const struct fb_info_aty *info, + const struct pll_18818 *pll); + +static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll); +static u32 aty_pll_8398_to_var(const struct pll_18818 *pll); +static void aty_set_pll_8398(const struct fb_info_aty *info, + const struct pll_18818 *pll); + static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll); -static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per, +static u32 aty_pll_gx_to_var(const struct pll_gx *pll, const struct fb_info_aty *info); static void aty_set_pll_ct(const struct fb_info_aty *info, const struct pll_ct *pll); -static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, - u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div, - u8 bpp, struct pll_ct *pll); +static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per, + struct pll_ct *pll); +static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp, + struct pll_ct *pll); +static void aty_calc_pll_ct(const struct fb_info_aty *info, + struct pll_ct *pll); static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, u8 bpp, struct pll_ct *pll); -static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per, +static u32 aty_pll_ct_to_var(const struct pll_ct *pll, const struct fb_info_aty *info); static void atyfb_set_par(const struct atyfb_par *par, struct fb_info_aty *info); @@ -380,11 +455,13 @@ static int read_aty_sense(const struct fb_info_aty *info); * Interface used by the world */ -void atyfb_init(void); +int atyfb_init(void); #ifdef CONFIG_FB_OF void atyfb_of_init(struct device_node *dp); #endif -void atyfb_setup(char *options, int *ints); +#ifndef MODULE +int atyfb_setup(char*); +#endif static int currcon = 0; @@ -392,10 +469,11 @@ static struct fb_ops atyfb_ops = { atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var, atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl, #ifdef __sparc__ - atyfb_mmap + atyfb_mmap, #else - NULL + NULL, #endif + atyfb_rasterimg }; static char atyfb_name[16] = "ATY Mach64"; @@ -406,6 +484,10 @@ static u32 default_vram __initdata = 0; static int default_pll __initdata = 0; static int default_mclk __initdata = 0; +#ifndef MODULE +static const char *mode_option __initdata = NULL; +#endif + #if defined(CONFIG_PPC) static int default_vmode __initdata = VMODE_NVRAM; static int default_cmode __initdata = CMODE_NVRAM; @@ -465,7 +547,7 @@ static const char *aty_ct_ram[8] __initdata = { }; -static inline u32 aty_ld_le32(volatile unsigned int regindex, +static inline u32 aty_ld_le32(unsigned int regindex, const struct fb_info_aty *info) { unsigned long temp; @@ -473,10 +555,10 @@ static inline u32 aty_ld_le32(volatile unsigned int regindex, #if defined(__powerpc__) temp = info->ati_regbase; - asm("lwbrx %0,%1,%2" : "=r"(val) : "r" (regindex), "r" (temp)); + asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp)); #elif defined(__sparc_v9__) temp = info->ati_regbase + regindex; - asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL)); + val = readl(temp); #else temp = info->ati_regbase+regindex; val = le32_to_cpu(*((volatile u32 *)(temp))); @@ -484,34 +566,42 @@ static inline u32 aty_ld_le32(volatile unsigned int regindex, return val; } -static inline void aty_st_le32(volatile unsigned int regindex, u32 val, +static inline void aty_st_le32(unsigned int regindex, u32 val, const struct fb_info_aty *info) { unsigned long temp; #if defined(__powerpc__) temp = info->ati_regbase; - asm("stwbrx %0,%1,%2" : : "r" (val), "r" (regindex), "r" (temp) : + asm volatile("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) : "memory"); #elif defined(__sparc_v9__) temp = info->ati_regbase + regindex; - asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory"); + writel(val, temp); #else temp = info->ati_regbase+regindex; *((volatile u32 *)(temp)) = cpu_to_le32(val); #endif } -static inline u8 aty_ld_8(volatile unsigned int regindex, +static inline u8 aty_ld_8(unsigned int regindex, const struct fb_info_aty *info) { +#ifdef __sparc_v9__ + return readb(info->ati_regbase + regindex); +#else return *(volatile u8 *)(info->ati_regbase+regindex); +#endif } -static inline void aty_st_8(volatile unsigned int regindex, u8 val, +static inline void aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty *info) { +#ifdef __sparc_v9__ + writeb(val, info->ati_regbase + regindex); +#else *(volatile u8 *)(info->ati_regbase+regindex) = val; +#endif } @@ -941,8 +1031,10 @@ atyfb_cursor(struct display *p, int mode, int x, int y) } } -__initfunc(static struct aty_cursor * -aty_init_cursor(struct fb_info_aty *fb)) +static struct fb_info_aty *fb_list = NULL; + +static struct aty_cursor * __init +aty_init_cursor(struct fb_info_aty *fb) { struct aty_cursor *cursor; unsigned long addr; @@ -1169,6 +1261,124 @@ static int aty_var_to_crtc(const struct fb_info_aty *info, return 0; } + +static int aty_set_dac_ATI68860_B(const struct fb_info_aty *info, u32 bpp, + u32 AccelMode) +{ + u32 gModeReg, devSetupRegA, temp, mask; + + gModeReg = 0; + devSetupRegA = 0; + + switch (bpp) { + case 8: + gModeReg = 0x83; + devSetupRegA = 0x60 | 0x00 /*(info->mach64DAC8Bit ? 0x00 : 0x01) */; + break; + case 15: + gModeReg = 0xA0; + devSetupRegA = 0x60; + break; + case 16: + gModeReg = 0xA1; + devSetupRegA = 0x60; + break; + case 24: + gModeReg = 0xC0; + devSetupRegA = 0x60; + break; + case 32: + gModeReg = 0xE3; + devSetupRegA = 0x60; + break; + } + + if (!AccelMode) { + gModeReg = 0x80; + devSetupRegA = 0x61; + } + + temp = aty_ld_8(DAC_CNTL, info); + aty_st_8(DAC_CNTL, (temp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); + + aty_st_8(DAC_REGS + 2, 0x1D, info); + aty_st_8(DAC_REGS + 3, gModeReg, info); + aty_st_8(DAC_REGS, 0x02, info); + + temp = aty_ld_8(DAC_CNTL, info); + aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); + + if (info->total_vram < MEM_SIZE_1M) + mask = 0x04; + else if (info->total_vram == MEM_SIZE_1M) + mask = 0x08; + else + mask = 0x0C; + + /* The following assumes that the BIOS has correctly set R7 of the + * Device Setup Register A at boot time. + */ +#define A860_DELAY_L 0x80 + + temp = aty_ld_8(DAC_REGS, info); + aty_st_8(DAC_REGS, (devSetupRegA | mask) | (temp & A860_DELAY_L), info); + temp = aty_ld_8(DAC_CNTL, info); + aty_st_8(DAC_CNTL, (temp & ~(DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3)), info); + + return 0; +} + +static int aty_set_dac_ATT21C498(const struct fb_info_aty *info, + const struct pll_18818 *pll, u32 bpp) +{ + u32 dotClock; + int muxmode = 0; + int DACMask = 0; + + dotClock = 100000000 / pll->period_in_ps; + + switch (bpp) { + case 8: + if (dotClock > 8000) { + DACMask = 0x24; + muxmode = 1; + } else + DACMask = 0x04; + break; + case 15: + DACMask = 0x16; + break; + case 16: + DACMask = 0x36; + break; + case 24: + DACMask = 0xE6; + break; + case 32: + DACMask = 0xE6; + break; + } + + if (1 /* info->mach64DAC8Bit */) + DACMask |= 0x02; + + aty_dac_waste4(info); + aty_st_8(DAC_REGS + 2, DACMask, info); + + return muxmode; +} + +void aty_dac_waste4(const struct fb_info_aty *info) +{ + (void)aty_ld_8(DAC_REGS, info); + + (void)aty_ld_8(DAC_REGS + 2, info); + (void)aty_ld_8(DAC_REGS + 2, info); + (void)aty_ld_8(DAC_REGS + 2, info); + (void)aty_ld_8(DAC_REGS + 2, info); +} + + static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp) { static struct { @@ -1366,60 +1576,477 @@ static void aty_set_pll_gx(const struct fb_info_aty *info, } } -static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll) + +static int aty_var_to_pll_18818(u32 period_in_ps, struct pll_18818 *pll) { - /* - * FIXME: use real calculations instead of using fixed values from the old - * driver - */ - static struct { - u32 ps_lim; /* pixclock period rounding limit (arbitrary) */ - u8 mode; /* (prescsaler << 4) | Select */ - u8 prog; /* ref_div_count */ - } ATI18818_clocks[] = { - { 7500, 0x0B, 1 }, /* 7407.4 ps = 135.00 MHz */ - { 9000, 0x0A, 1 }, /* 7936.5 ps = 126.00 MHz */ - { 11000, 0x09, 1 }, /* 10000.0 ps = 100.00 MHz */ - { 12800, 0x0D, 1 }, /* 12500.0 ps = 80.00 MHz */ - { 13500, 0x0E, 1 }, /* 13333.3 ps = 75.00 MHz */ -/* { 14000, 0x03, 2 },*/ /* 13888.8 ps = 72.00 MHz */ - { 15000, 0x1B, 1 }, /* 14814.8 ps = 67.50 MHz */ - { 15500, 0x0F, 1 }, /* 15384.6 ps = 65.00 MHz */ - { 16000, 0x1A, 1 }, /* 15873.0 ps = 63.00 MHz */ -/* { 16000, 0x02, 2 },*/ /* 15873.0 ps = 63.00 MHz */ -/* { 18000, 0x01, 2 },*/ /* 17655.4 ps = 56.64 MHz */ -/* { 19900, 0x00, 2 },*/ /* 19860.9 ps = 50.35 MHz */ - { 20000, 0x07, 1 }, /* 20000.0 ps = 50.00 MHz */ - { 20300, 0x06, 1 }, /* 20202.0 ps = 49.50 MHz */ - { 22500, 0x05, 1 }, /* 22271.2 ps = 44.90 MHz */ - { 25000, 0x04, 1 }, /* 25000.0 ps = 40.00 MHz */ -/* { 28000, 0x03, 1 },*/ /* 27777.8 ps = 36.00 MHz */ - { 30000, 0x2B, 1 }, /* 29629,6 ps = 33.75 MHz */ - { 31000, 0x1F, 1 }, /* 30769.2 ps = 32.50 MHz */ - { 32000, 0x2A, 1 }, /* 31746.0 ps = 31.50 MHz */ -/* { 32000, 0x02, 1 },*/ /* 31746.0 ps = 31.50 MHz */ -/* { 36000, 0x01, 1 },*/ /* 35310.7 ps = 28.32 MHz */ -/* { 39900, 0x00, 1 },*/ /* 39714.1 ps = 25.18 MHz */ - { 40000, 0x17, 1 }, /* 40000.0 ps = 25.00 MHz */ - { 40600, 0x16, 1 }, /* 40404.0 ps = 24.75 MHz */ - { 45000, 0x15, 1 }, /* 44543.4 ps = 22.45 MHz */ - { 50000, 0x14, 1 }, /* 50000.0 ps = 20.00 MHz */ -/* { 56000, 0x13, 1 },*/ /* 55555.5 ps = 18.00 MHz */ - { 62000, 0x2F, 1 }, /* 61538.8 ps = 16.25 MHz */ -/* { 64000, 0x12, 1 },*/ /* 63492.0 ps = 15.75 MHz */ - }; - int set; + u32 MHz100; /* in 0.01 MHz */ + u32 program_bits; + u32 post_divider; - for (set = 0; set < sizeof(ATI18818_clocks)/sizeof(*ATI18818_clocks); - set++) - if (vclk_per <= ATI18818_clocks[set].ps_lim) { - pll->m = ATI18818_clocks[set].mode; - pll->n = ATI18818_clocks[set].prog; - return 0; + /* Calculate the programming word */ + MHz100 = 100000000 / period_in_ps; + + program_bits = -1; + post_divider = 1; + + if (MHz100 > MAX_FREQ_2595) { + MHz100 = MAX_FREQ_2595; + return -EINVAL; + } else if (MHz100 < ABS_MIN_FREQ_2595) { + program_bits = 0; /* MHz100 = 257 */ + return -EINVAL; + } else { + while (MHz100 < MIN_FREQ_2595) { + MHz100 *= 2; + post_divider *= 2; } - return -EINVAL; + } + MHz100 *= 1000; + MHz100 = (REF_DIV_2595 * MHz100) / REF_FREQ_2595; + + MHz100 += 500; /* + 0.5 round */ + MHz100 /= 1000; + + if (program_bits == -1) { + program_bits = MHz100 - N_ADJ_2595; + switch (post_divider) { + case 1: + program_bits |= 0x0600; + break; + case 2: + program_bits |= 0x0400; + break; + case 4: + program_bits |= 0x0200; + break; + case 8: + default: + break; + } + } + + program_bits |= STOP_BITS_2595; + + pll->program_bits = program_bits; + pll->locationAddr = 0; + pll->post_divider = post_divider; + pll->period_in_ps = period_in_ps; + + return 0; +} + +static u32 aty_pll_18818_to_var(const struct pll_18818 *pll) +{ + return(pll->period_in_ps); /* default for now */ +} + +static void aty_set_pll18818(const struct fb_info_aty *info, + const struct pll_18818 *pll) +{ + u32 program_bits; + u32 locationAddr; + + u32 i; + + u8 old_clock_cntl; + u8 old_crtc_ext_disp; + + old_clock_cntl = aty_ld_8(CLOCK_CNTL, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); + + old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), + info); + + udelay(15000); /* delay for 50 (15) ms */ + + program_bits = pll->program_bits; + locationAddr = pll->locationAddr; + + /* Program the clock chip */ + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); /* Strobe = 0 */ + aty_StrobeClock(info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 1, info); /* Strobe = 0 */ + aty_StrobeClock(info); + + aty_ICS2595_put1bit(1, info); /* Send start bits */ + aty_ICS2595_put1bit(0, info); /* Start bit */ + aty_ICS2595_put1bit(0, info); /* Read / ~Write */ + + for (i = 0; i < 5; i++) { /* Location 0..4 */ + aty_ICS2595_put1bit(locationAddr & 1, info); + locationAddr >>= 1; + } + + for (i = 0; i < 8 + 1 + 2 + 2; i++) { + aty_ICS2595_put1bit(program_bits & 1, info); + program_bits >>= 1; + } + + udelay(1000); /* delay for 1 ms */ + + (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, old_clock_cntl | CLOCK_STROBE, + info); + + udelay(50000); /* delay for 50 (15) ms */ + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, + ((pll->locationAddr & 0x0F) | CLOCK_STROBE), info); + + return; +} + + +static int aty_var_to_pll_408(u32 period_in_ps, struct pll_18818 *pll) +{ + u32 mhz100; /* in 0.01 MHz */ + u32 program_bits; + /* u32 post_divider; */ + u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; + u32 temp, tempB; + u16 remainder, preRemainder; + short divider = 0, tempA; + + /* Calculate the programming word */ + mhz100 = 100000000 / period_in_ps; + mach64MinFreq = MIN_FREQ_2595; + mach64MaxFreq = MAX_FREQ_2595; + mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ + + /* Calculate program word */ + if (mhz100 == 0) + program_bits = 0xFF; + else { + if (mhz100 < mach64MinFreq) + mhz100 = mach64MinFreq; + if (mhz100 > mach64MaxFreq) + mhz100 = mach64MaxFreq; + + while (mhz100 < (mach64MinFreq << 3)) { + mhz100 <<= 1; + divider += 0x40; + } + + temp = (unsigned int)mhz100; + temp = (unsigned int)(temp * (MIN_N_408 + 2)); + temp -= ((short)(mach64RefFreq << 1)); + + tempA = MIN_N_408; + preRemainder = 0xFFFF; + + do { + tempB = temp; + remainder = tempB % mach64RefFreq; + tempB = tempB / mach64RefFreq; + if (((tempB & 0xFFFF) <= 255) && (remainder <= preRemainder)) { + preRemainder = remainder; + divider &= ~0x3f; + divider |= tempA; + divider = (divider & 0x00FF) + ((tempB & 0xFF) << 8); + } + temp += mhz100; + tempA++; + } while(tempA <= 32); + + program_bits = divider; + } + + pll->program_bits = program_bits; + pll->locationAddr = 0; + pll->post_divider = divider; /* fuer nix */ + pll->period_in_ps = period_in_ps; + + return 0; +} + +static u32 aty_pll_408_to_var(const struct pll_18818 *pll) +{ + return(pll->period_in_ps); /* default for now */ +} + +static void aty_set_pll_408(const struct fb_info_aty *info, + const struct pll_18818 *pll) +{ + u32 program_bits; + u32 locationAddr; + + u8 tmpA, tmpB, tmpC; + char old_crtc_ext_disp; + + old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), + info); + + program_bits = pll->program_bits; + locationAddr = pll->locationAddr; + + /* Program clock */ + aty_dac_waste4(info); + tmpB = aty_ld_8(DAC_REGS + 2, info) | 1; + aty_dac_waste4(info); + aty_st_8(DAC_REGS + 2, tmpB, info); + + tmpA = tmpB; + tmpC = tmpA; + tmpA |= 8; + tmpB = 1; + + aty_st_8(DAC_REGS, tmpB, info); + aty_st_8(DAC_REGS + 2, tmpA, info); + + udelay(400); /* delay for 400 us */ + + locationAddr = (locationAddr << 2) + 0x40; + tmpB = locationAddr; + tmpA = program_bits >> 8; + + aty_st_8(DAC_REGS, tmpB, info); + aty_st_8(DAC_REGS + 2, tmpA, info); + + tmpB = locationAddr + 1; + tmpA = (u8)program_bits; + + aty_st_8(DAC_REGS, tmpB, info); + aty_st_8(DAC_REGS + 2, tmpA, info); + + tmpB = locationAddr + 2; + tmpA = 0x77; + + aty_st_8(DAC_REGS, tmpB, info); + aty_st_8(DAC_REGS + 2, tmpA, info); + + udelay(400); /* delay for 400 us */ + tmpA = tmpC & (~(1 | 8)); + tmpB = 1; + + aty_st_8(DAC_REGS, tmpB, info); + aty_st_8(DAC_REGS + 2, tmpA, info); + + (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); + + return; +} + + +static int aty_var_to_pll_1703(u32 period_in_ps, struct pll_18818 *pll) +{ + u32 mhz100; /* in 0.01 MHz */ + u32 program_bits; + /* u32 post_divider; */ + u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; + u32 temp, tempB; + u16 remainder, preRemainder; + short divider = 0, tempA; + + /* Calculate the programming word */ + mhz100 = 100000000 / period_in_ps; + mach64MinFreq = MIN_FREQ_2595; + mach64MaxFreq = MAX_FREQ_2595; + mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ + + /* Calculate program word */ + if (mhz100 == 0) + program_bits = 0xE0; + else { + if (mhz100 < mach64MinFreq) + mhz100 = mach64MinFreq; + if (mhz100 > mach64MaxFreq) + mhz100 = mach64MaxFreq; + + divider = 0; + while (mhz100 < (mach64MinFreq << 3)) { + mhz100 <<= 1; + divider += 0x20; + } + + temp = (unsigned int)(mhz100); + temp = (unsigned int)(temp * (MIN_N_1703 + 2)); + temp -= (short)(mach64RefFreq << 1); + + tempA = MIN_N_1703; + preRemainder = 0xffff; + + do { + tempB = temp; + remainder = tempB % mach64RefFreq; + tempB = tempB / mach64RefFreq; + + if ((tempB & 0xffff) <= 127 && (remainder <= preRemainder)) { + preRemainder = remainder; + divider &= ~0x1f; + divider |= tempA; + divider = (divider & 0x00ff) + ((tempB & 0xff) << 8); + } + + temp += mhz100; + tempA++; + } while (tempA <= (MIN_N_1703 << 1)); + + program_bits = divider; + } + + pll->program_bits = program_bits; + pll->locationAddr = 0; + pll->post_divider = divider; /* fuer nix */ + pll->period_in_ps = period_in_ps; + + return 0; +} + +static u32 aty_pll_1703_to_var(const struct pll_18818 *pll) +{ + return(pll->period_in_ps); /* default for now */ +} + +static void aty_set_pll_1703(const struct fb_info_aty *info, + const struct pll_18818 *pll) +{ + u32 program_bits; + u32 locationAddr; + + char old_crtc_ext_disp; + + old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), + info); + + program_bits = pll->program_bits; + locationAddr = pll->locationAddr; + + /* Program clock */ + aty_dac_waste4(info); + + (void)aty_ld_8(DAC_REGS + 2, info); + aty_st_8(DAC_REGS+2, (locationAddr << 1) + 0x20, info); + aty_st_8(DAC_REGS+2, 0, info); + aty_st_8(DAC_REGS+2, (program_bits & 0xFF00) >> 8, info); + aty_st_8(DAC_REGS+2, (program_bits & 0xFF), info); + + (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); + + return; +} + + +static int aty_var_to_pll_8398(u32 period_in_ps, struct pll_18818 *pll) +{ + + u32 tempA, tempB, fOut, longMHz100, diff, preDiff; + + u32 mhz100; /* in 0.01 MHz */ + u32 program_bits; + /* u32 post_divider; */ + u32 mach64MinFreq, mach64MaxFreq, mach64RefFreq; + u16 m, n, k=0, save_m, save_n, twoToKth; + + /* Calculate the programming word */ + mhz100 = 100000000 / period_in_ps; + mach64MinFreq = MIN_FREQ_2595; + mach64MaxFreq = MAX_FREQ_2595; + mach64RefFreq = REF_FREQ_2595; /* 14.32 MHz */ + + save_m = 0; + save_n = 0; + + /* Calculate program word */ + if (mhz100 == 0) + program_bits = 0xE0; + else + { + if (mhz100 < mach64MinFreq) + mhz100 = mach64MinFreq; + if (mhz100 > mach64MaxFreq) + mhz100 = mach64MaxFreq; + + longMHz100 = mhz100 * 256 / 100; /* 8 bit scale this */ + + while (mhz100 < (mach64MinFreq << 3)) + { + mhz100 <<= 1; + k++; + } + + twoToKth = 1 << k; + diff = 0; + preDiff = 0xFFFFFFFF; + + for (m = MIN_M; m <= MAX_M; m++) + { + for (n = MIN_N; n <= MAX_N; n++) + { + tempA = (14.31818 * 65536); + tempA *= (n + 8); /* 43..256 */ + tempB = twoToKth * 256; + tempB *= (m + 2); /* 4..32 */ + fOut = tempA / tempB; /* 8 bit scale */ + + if (longMHz100 > fOut) + diff = longMHz100 - fOut; + else + diff = fOut - longMHz100; + + if (diff < preDiff) + { + save_m = m; + save_n = n; + preDiff = diff; + } + } + } + + program_bits = (k << 6) + (save_m) + (save_n << 8); + } + + pll->program_bits = program_bits; + pll->locationAddr = 0; + pll->post_divider = 0; + pll->period_in_ps = period_in_ps; + + return 0; +} + +static u32 aty_pll_8398_to_var(const struct pll_18818 *pll) +{ + return(pll->period_in_ps); /* default for now */ +} + +static void aty_set_pll_8398(const struct fb_info_aty *info, + const struct pll_18818 *pll) +{ + u32 program_bits; + u32 locationAddr; + + char old_crtc_ext_disp; + char tmp; + + old_crtc_ext_disp = aty_ld_8(CRTC_GEN_CNTL + 3, info); + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp | (CRTC_EXT_DISP_EN >> 24), + info); + + program_bits = pll->program_bits; + locationAddr = pll->locationAddr; + + /* Program clock */ + tmp = aty_ld_8(DAC_CNTL, info); + aty_st_8(DAC_CNTL, tmp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, info); + + aty_st_8(DAC_REGS, locationAddr, info); + aty_st_8(DAC_REGS+1, (program_bits & 0xff00) >> 8, info); + aty_st_8(DAC_REGS+1, (program_bits & 0xff), info); + + tmp = aty_ld_8(DAC_CNTL, info); + aty_st_8(DAC_CNTL, (tmp & ~DAC_EXT_SEL_RS2) | DAC_EXT_SEL_RS3, info); + + (void)aty_ld_8(DAC_REGS, info); /* Clear DAC Counter */ + aty_st_8(CRTC_GEN_CNTL + 3, old_crtc_ext_disp, info); + + return; } + static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll) { /* @@ -1450,9 +2077,44 @@ static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll) return -EINVAL; } - /* FIXME: ATI18818?? */ -static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per, +static void aty_StrobeClock(const struct fb_info_aty *info) +{ + u8 tmp; + + udelay(26); + + tmp = aty_ld_8(CLOCK_CNTL, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, tmp | CLOCK_STROBE, info); + + return; +} + + +static void aty_ICS2595_put1bit(u8 data, const struct fb_info_aty *info) +{ + u8 tmp; + + data &= 0x01; + tmp = aty_ld_8(CLOCK_CNTL, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x04) | (data << 2), + info); + + tmp = aty_ld_8(CLOCK_CNTL, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (0 << 3), info); + + aty_StrobeClock(info); + + tmp = aty_ld_8(CLOCK_CNTL, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, (tmp & ~0x08) | (1 << 3), info); + + aty_StrobeClock(info); + + return; +} + + +static u32 aty_pll_gx_to_var(const struct pll_gx *pll, const struct fb_info_aty *info) { u8 df, vco_div_count, ref_div_count; @@ -1461,9 +2123,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per, vco_div_count = pll->m & 0x3f; ref_div_count = pll->n; - *vclk_per = ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); - - return 0; + return ((info->ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65); } @@ -1495,16 +2155,15 @@ static void aty_set_pll_ct(const struct fb_info_aty *info, } } -static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, - u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div, - u8 bpp, struct pll_ct *pll) +static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp, + struct pll_ct *pll) { u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on; u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size; /* xclocks_per_row<<11 */ - xclks_per_row = (mclk_fb_div*vclk_post_div*64<<11)/ - (vclk_fb_div*mclk_post_div*bpp); + xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/ + (pll->vclk_fb_div*pll->mclk_post_div_real*bpp); if (xclks_per_row < (1<<11)) FAIL("Dotclock to high"); if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID || @@ -1564,63 +2223,59 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, return 0; } -static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, - u8 bpp, struct pll_ct *pll) +static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per, + struct pll_ct *pll) { u32 q, x; /* x is a workaround for sparc64-linux-gcc */ - u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl; - u8 mclk_fb_div, mclk_post_div, mpostdiv = 0; - u8 vclk_fb_div, vclk_post_div, vpostdiv = 0; - int err; - x = x; /* x is a workaround for sparc64-linux-gcc */ - pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ - - pll_ref_div = info->pll_per*2*255/info->ref_clk_per; + pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per; /* FIXME: use the VTB/GTB /3 post divider if it's better suited */ - q = info->ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */ + q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per; /* actually 8*q */ if (q < 16*8 || q > 255*8) FAIL("mclk out of range"); else if (q < 32*8) - mclk_post_div = 8; + pll->mclk_post_div_real = 8; else if (q < 64*8) - mclk_post_div = 4; + pll->mclk_post_div_real = 4; else if (q < 128*8) - mclk_post_div = 2; + pll->mclk_post_div_real = 2; else - mclk_post_div = 1; - mclk_fb_div = q*mclk_post_div/8; + pll->mclk_post_div_real = 1; + pll->mclk_fb_div = q*pll->mclk_post_div_real/8; /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */ - q = info->ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */ + q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per; /* actually 8*q */ if (q < 16*8 || q > 255*8) FAIL("vclk out of range"); else if (q < 32*8) - vclk_post_div = 8; + pll->vclk_post_div_real = 8; else if (q < 64*8) - vclk_post_div = 4; + pll->vclk_post_div_real = 4; else if (q < 128*8) - vclk_post_div = 2; + pll->vclk_post_div_real = 2; else - vclk_post_div = 1; - vclk_fb_div = q*vclk_post_div/8; + pll->vclk_post_div_real = 1; + pll->vclk_fb_div = q*pll->vclk_post_div_real/8; + return 0; +} - if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div, - vclk_post_div, bpp, pll))) - return err; +static void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll) +{ + u8 mpostdiv = 0; + u8 vpostdiv = 0; if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) || (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) || (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) || (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM)) - pll_gen_cntl = 0x04; + pll->pll_gen_cntl = 0x04; else - pll_gen_cntl = 0x84; + pll->pll_gen_cntl = 0x84; - switch (mclk_post_div) { + switch (pll->mclk_post_div_real) { case 1: mpostdiv = 0; break; @@ -1637,61 +2292,64 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, mpostdiv = 3; break; } - pll_gen_cntl |= mpostdiv<<4; /* mclk */ + pll->pll_gen_cntl |= mpostdiv<<4; /* mclk */ if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)) - pll_ext_cntl = 0; + pll->pll_ext_cntl = 0; else - pll_ext_cntl = mpostdiv; /* xclk == mclk */ + pll->pll_ext_cntl = mpostdiv; /* xclk == mclk */ - switch (vclk_post_div) { + switch (pll->vclk_post_div_real) { case 2: vpostdiv = 1; break; case 3: - pll_ext_cntl |= 0x10; + pll->pll_ext_cntl |= 0x10; case 1: vpostdiv = 0; break; case 6: - pll_ext_cntl |= 0x10; + pll->pll_ext_cntl |= 0x10; case 4: vpostdiv = 2; break; case 12: - pll_ext_cntl |= 0x10; + pll->pll_ext_cntl |= 0x10; case 8: vpostdiv = 3; break; } - vclk_post_div = vpostdiv; - - pll->pll_ref_div = pll_ref_div; - pll->pll_gen_cntl = pll_gen_cntl; - pll->mclk_fb_div = mclk_fb_div; - pll->vclk_post_div = vclk_post_div; - pll->vclk_fb_div = vclk_fb_div; - pll->pll_ext_cntl = pll_ext_cntl; + + pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ + pll->vclk_post_div = vpostdiv; +} + +static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, + u8 bpp, struct pll_ct *pll) +{ + int err; + + if ((err = aty_valid_pll_ct(info, vclk_per, pll))) + return err; + if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID || + Gx == ET_CHIP_ID || + ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) { + if ((err = aty_dsp_gt(info, bpp, pll))) + return err; + } + aty_calc_pll_ct(info, pll); return 0; } -static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per, +static u32 aty_pll_ct_to_var(const struct pll_ct *pll, const struct fb_info_aty *info) { + u32 ref_clk_per = info->ref_clk_per; u8 pll_ref_div = pll->pll_ref_div; u8 vclk_fb_div = pll->vclk_fb_div; - u8 vclk_post_div = pll->vclk_post_div; - u8 pll_ext_cntl = pll->pll_ext_cntl; - static u8 vclk_post_div_tab[] = { - 1, 2, 4, 8, - 3, 0, 6, 12 - }; - u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 2) | - (vclk_post_div & 3)]; - if (vpostdiv == 0) - return -EINVAL; - *vclk_per = pll_ref_div*vpostdiv*info->ref_clk_per/vclk_fb_div/2; - return 0; + u8 vclk_post_div = pll->vclk_post_div_real; + + return ref_clk_per*pll_ref_div*vclk_post_div/vclk_fb_div/2; } /* ------------------------------------------------------------------------- */ @@ -1700,27 +2358,76 @@ static void atyfb_set_par(const struct atyfb_par *par, struct fb_info_aty *info) { u32 i; + int accelmode; + int muxmode; + u8 tmp; + + accelmode = par->accel_flags; /* hack */ info->current_par = *par; if (info->blitter_may_be_busy) wait_for_idle(info); + tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info); aty_set_crtc(info, &par->crtc); - aty_st_8(CLOCK_CNTL, 0, info); - aty_st_8(CLOCK_CNTL, CLOCK_STROBE, info); + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info); + /* better call aty_StrobeClock ?? */ + aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info); if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) { - switch (info->dac_type) { + switch (info->dac_subtype) { case DAC_IBMRGB514: aty_set_dac_514(info, par->crtc.bpp); break; case DAC_ATI68860_B: - /* FIXME */ + case DAC_ATI68860_C: + muxmode = aty_set_dac_ATI68860_B(info, par->crtc.bpp, + accelmode); + aty_st_le32(BUS_CNTL, 0x890e20f1, info); + aty_st_le32(DAC_CNTL, 0x47052100, info); break; - } - aty_set_pll_gx(info, &par->pll.gx); + case DAC_ATT20C408: + muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595, + par->crtc.bpp); + aty_st_le32(BUS_CNTL, 0x890e20f1, info); + aty_st_le32(DAC_CNTL, 0x00072000, info); + break; + case DAC_ATT21C498: + muxmode = aty_set_dac_ATT21C498(info, &par->pll.ics2595, + par->crtc.bpp); + aty_st_le32(BUS_CNTL, 0x890e20f1, info); + aty_st_le32(DAC_CNTL, 0x00072000, info); + break; + default: + printk(" atyfb_set_par: DAC type not implemented yet!\n"); + aty_st_le32(BUS_CNTL, 0x890e20f1, info); + aty_st_le32(DAC_CNTL, 0x47052100, info); + /* new in 2.2.3p1 from Geert. ???????? */ aty_st_le32(BUS_CNTL, 0x590e10ff, info); aty_st_le32(DAC_CNTL, 0x47012100, info); + break; + } + + switch (info->clk_type) { + case CLK_ATI18818_1: + aty_set_pll18818(info, &par->pll.ics2595); + break; + case CLK_STG1703: + aty_set_pll_1703(info, &par->pll.ics2595); + break; + case CLK_CH8398: + aty_set_pll_8398(info, &par->pll.ics2595); + break; + case CLK_ATT20C408: + aty_set_pll_408(info, &par->pll.ics2595); + break; + case CLK_IBMRGB514: + aty_set_pll_gx(info, &par->pll.gx); + break; + default: + printk(" atyfb_set_par: CLK type not implemented yet!"); + break; + } /* Don't forget MEM_CNTL */ i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff; @@ -1739,7 +2446,7 @@ static void atyfb_set_par(const struct atyfb_par *par, } else { aty_set_pll_ct(info, &par->pll.ct); - i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff; + i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff; if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))) i |= info->mem_refresh_rate << 20; switch (par->crtc.bpp) { @@ -1808,7 +2515,16 @@ static int atyfb_decode_var(const struct fb_var_screeninfo *var, if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) switch (info->clk_type) { case CLK_ATI18818_1: - err = aty_var_to_pll_18818(var->pixclock, &par->pll.gx); + err = aty_var_to_pll_18818(var->pixclock, &par->pll.ics2595); + break; + case CLK_STG1703: + err = aty_var_to_pll_1703(var->pixclock, &par->pll.ics2595); + break; + case CLK_CH8398: + err = aty_var_to_pll_8398(var->pixclock, &par->pll.ics2595); + break; + case CLK_ATT20C408: + err = aty_var_to_pll_408(var->pixclock, &par->pll.ics2595); break; case CLK_IBMRGB514: err = aty_var_to_pll_514(var->pixclock, &par->pll.gx); @@ -1844,11 +2560,25 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var, if ((err = aty_crtc_to_var(&par->crtc, var))) return err; if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) - err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock, info); + switch (info->clk_type) { + case CLK_ATI18818_1: + var->pixclock = aty_pll_18818_to_var(&par->pll.ics2595); + break; + case CLK_STG1703: + var->pixclock = aty_pll_1703_to_var(&par->pll.ics2595); + break; + case CLK_CH8398: + var->pixclock = aty_pll_8398_to_var(&par->pll.ics2595); + break; + case CLK_ATT20C408: + var->pixclock = aty_pll_408_to_var(&par->pll.ics2595); + break; + case CLK_IBMRGB514: + var->pixclock = aty_pll_gx_to_var(&par->pll.gx, info); + break; + } else - err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock, info); - if (err) - return err; + var->pixclock = aty_pll_ct_to_var(&par->pll.ct, info); var->height = -1; var->width = -1; @@ -1923,7 +2653,7 @@ static int encode_fix(struct fb_fix_screeninfo *fix, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, atyfb_name); - fix->smem_start = (char *)info->frame_buffer_phys; + fix->smem_start = info->frame_buffer_phys; fix->smem_len = (u32)info->total_vram; #ifdef __LITTLE_ENDIAN @@ -1940,19 +2670,19 @@ static int encode_fix(struct fb_fix_screeninfo *fix, * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400 */ if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) { - fix->mmio_start = (char *)info->ati_regbase_phys; + fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64GX; } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) { - fix->mmio_start = (char *)info->ati_regbase_phys; + fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64CT; } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) { - fix->mmio_start = (char *)(info->ati_regbase_phys-0x400); + fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64VT; } else { - fix->mmio_start = (char *)(info->ati_regbase_phys-0x400); + fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64GT; } @@ -2194,36 +2924,112 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, } +#ifdef DEBUG +#define ATYIO_CLKR 0x41545900 /* ATY\00 */ +#define ATYIO_CLKW 0x41545901 /* ATY\01 */ + +struct atyclk { + u32 ref_clk_per; + u8 pll_ref_div; + u8 mclk_fb_div; + u8 mclk_post_div; /* 1,2,3,4,8 */ + u8 vclk_fb_div; + u8 vclk_post_div; /* 1,2,3,4,6,8,12 */ + u32 dsp_xclks_per_row; /* 0-16383 */ + u32 dsp_loop_latency; /* 0-15 */ + u32 dsp_precision; /* 0-7 */ + u32 dsp_on; /* 0-2047 */ + u32 dsp_off; /* 0-2047 */ +}; +#endif + static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con, struct fb_info *info) + u_long arg, int con, struct fb_info *info2) { +#if defined(__sparc__) || defined(DEBUG) + struct fb_info_aty *info = (struct fb_info_aty *)info2; +#endif /* __sparc__ || DEBUG */ #ifdef __sparc__ - struct fb_info_aty *fb = (struct fb_info_aty *)info; struct fbtype fbtyp; struct display *disp; if (con >= 0) disp = &fb_display[con]; else - disp = info->disp; + disp = info2->disp; +#endif switch (cmd) { +#ifdef __sparc__ case FBIOGTYPE: fbtyp.fb_type = FBTYPE_PCI_GENERIC; - fbtyp.fb_width = fb->current_par.crtc.vxres; - fbtyp.fb_height = fb->current_par.crtc.vyres; - fbtyp.fb_depth = fb->current_par.crtc.bpp; + fbtyp.fb_width = info->current_par.crtc.vxres; + fbtyp.fb_height = info->current_par.crtc.vyres; + fbtyp.fb_depth = info->current_par.crtc.bpp; fbtyp.fb_cmsize = disp->cmap.len; - fbtyp.fb_size = fb->total_vram; + fbtyp.fb_size = info->total_vram; copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT); break; +#endif /* __sparc__ */ +#ifdef DEBUG + case ATYIO_CLKR: + if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { + struct atyclk clk; + struct pll_ct *pll = &info->current_par.pll.ct; + u32 dsp_config = pll->dsp_config; + u32 dsp_on_off = pll->dsp_on_off; + clk.ref_clk_per = info->ref_clk_per; + clk.pll_ref_div = pll->pll_ref_div; + clk.mclk_fb_div = pll->mclk_fb_div; + clk.mclk_post_div = pll->mclk_post_div_real; + clk.vclk_fb_div = pll->vclk_fb_div; + clk.vclk_post_div = pll->vclk_post_div_real; + clk.dsp_xclks_per_row = dsp_config & 0x3fff; + clk.dsp_loop_latency = (dsp_config>>16) & 0xf; + clk.dsp_precision = (dsp_config>>20) & 7; + clk.dsp_on = dsp_on_off & 0x7ff; + clk.dsp_off = (dsp_on_off>>16) & 0x7ff; + copy_to_user_ret((struct atyclk *)arg, &clk, sizeof(clk), + -EFAULT); + } else + return -EINVAL; + break; + case ATYIO_CLKW: + if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { + struct atyclk clk; + struct pll_ct *pll = &info->current_par.pll.ct; + copy_from_user_ret(&clk, (struct atyclk *)arg, sizeof(clk), + -EFAULT); + info->ref_clk_per = clk.ref_clk_per; + pll->pll_ref_div = clk.pll_ref_div; + pll->mclk_fb_div = clk.mclk_fb_div; + pll->mclk_post_div_real = clk.mclk_post_div; + pll->vclk_fb_div = clk.vclk_fb_div; + pll->vclk_post_div_real = clk.vclk_post_div; + pll->dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | + ((clk.dsp_loop_latency & 0xf)<<16) | + ((clk.dsp_precision & 7)<<20); + pll->dsp_on_off = (clk.dsp_on & 0x7ff) | + ((clk.dsp_off & 0x7ff)<<16); + aty_calc_pll_ct(info, pll); + aty_set_pll_ct(info, pll); + } else + return -EINVAL; + break; +#endif /* DEBUG */ default: return -EINVAL; } return 0; -#else - return -EINVAL; -#endif +} + +static int atyfb_rasterimg(struct fb_info *info, int start) +{ + struct fb_info_aty *fb = (struct fb_info_aty *)info; + + if (fb->blitter_may_be_busy) + wait_for_idle(fb); + return 0; } #ifdef __sparc__ @@ -2424,7 +3230,7 @@ static void atyfb_palette(int enter) * Initialisation */ -__initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) +static int __init aty_init(struct fb_info_aty *info, const char *name) { u32 chip_id; u32 i; @@ -2439,12 +3245,16 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) u8 pll_ref_div; info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0); +#ifdef __sparc_v9__ + info->aty_cmap_regs = __va(info->aty_cmap_regs); +#endif chip_id = aty_ld_le32(CONFIG_CHIP_ID, info); Gx = chip_id & CFG_CHIP_TYPE; Rev = (chip_id & CFG_CHIP_REV)>>24; for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++) if (aty_features[j].chip_type == Gx) { chipname = aty_features[j].name; + info->dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07; break; } if (!chipname) { @@ -2458,10 +3268,16 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) ramname = aty_gx_ram[info->ram_type]; /* FIXME: clockchip/RAMDAC probing? */ #ifdef CONFIG_ATARI - info->dac_type = DAC_ATI68860_B; info->clk_type = CLK_ATI18818_1; + info->dac_type = (aty_ld_le32(CONFIG_STAT0, info) >> 9) & 0x07; + if (info->dac_type == 0x07) + info->dac_subtype = DAC_ATT20C408; + else + info->dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) | + info->dac_type; #else info->dac_type = DAC_IBMRGB514; + info->dac_subtype = DAC_IBMRGB514; info->clk_type = CLK_IBMRGB514; #endif /* FIXME */ @@ -2472,6 +3288,7 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07); ramname = aty_ct_ram[info->ram_type]; info->dac_type = DAC_INTERNAL; + info->dac_subtype = DAC_INTERNAL; info->clk_type = CLK_INTERNAL; if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) { pll = 135; @@ -2667,32 +3484,64 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) info->total_vram -= GUI_RESERVE; } + disp = &info->disp; + + strcpy(info->fb_info.modename, atyfb_name); + info->fb_info.node = -1; + info->fb_info.fbops = &atyfb_ops; + info->fb_info.disp = disp; + strcpy(info->fb_info.fontname, fontname); + info->fb_info.changevar = NULL; + info->fb_info.switch_con = &atyfbcon_switch; + info->fb_info.updatevar = &atyfbcon_updatevar; + info->fb_info.blank = &atyfbcon_blank; + info->fb_info.flags = FBINFO_FLAG_DEFAULT; + +#ifdef MODULE + var = default_var; +#else /* !MODULE */ + memset(&var, 0, sizeof(var)); #if defined(CONFIG_PPC) - if (default_vmode == VMODE_NVRAM) { - default_vmode = nvram_read_byte(NV_VMODE); - if (default_vmode <= 0 || default_vmode > VMODE_MAX) - default_vmode = VMODE_CHOOSE; - } - if (default_vmode == VMODE_CHOOSE) { - if (Gx == LG_CHIP_ID) - /* G3 PowerBook with 1024x768 LCD */ - default_vmode = VMODE_1024_768_60; - else { - sense = read_aty_sense(info); - default_vmode = mac_map_monitor_sense(sense); + if (mode_option) { + if (!mac_find_mode(&var, &info->fb_info, mode_option, 8)) + var = default_var; + } else { + if (default_vmode == VMODE_NVRAM) { + default_vmode = nvram_read_byte(NV_VMODE); + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_CHOOSE; + } + if (default_vmode == VMODE_CHOOSE) { + if (Gx == LG_CHIP_ID) + /* G3 PowerBook with 1024x768 LCD */ + default_vmode = VMODE_1024_768_60; + else { + sense = read_aty_sense(info); + default_vmode = mac_map_monitor_sense(sense); + } } + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_640_480_60; + if (default_cmode == CMODE_NVRAM) + default_cmode = nvram_read_byte(NV_CMODE); + if (default_cmode < CMODE_8 || default_cmode > CMODE_32) + default_cmode = CMODE_8; + if (mac_vmode_to_var(default_vmode, default_cmode, &var)) + var = default_var; } - if (default_vmode <= 0 || default_vmode > VMODE_MAX) - default_vmode = VMODE_640_480_60; - if (default_cmode == CMODE_NVRAM) - default_cmode = nvram_read_byte(NV_CMODE); - if (default_cmode < CMODE_8 || default_cmode > CMODE_32) - default_cmode = CMODE_8; - if (mac_vmode_to_var(default_vmode, default_cmode, &var)) - var = default_var; #else /* !CONFIG_PPC */ - var = default_var; +#ifdef __sparc__ + if (mode_option) { + if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8)) + var = default_var; + } else + var = default_var; +#else + if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8)) + var = default_var; +#endif /* !__sparc__ */ #endif /* !CONFIG_PPC */ +#endif /* !MODULE */ if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; else @@ -2710,19 +3559,6 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) return 0; } - disp = &info->disp; - - strcpy(info->fb_info.modename, atyfb_name); - info->fb_info.node = -1; - info->fb_info.fbops = &atyfb_ops; - info->fb_info.disp = disp; - strcpy(info->fb_info.fontname, fontname); - info->fb_info.changevar = NULL; - info->fb_info.switch_con = &atyfbcon_switch; - info->fb_info.updatevar = &atyfbcon_updatevar; - info->fb_info.blank = &atyfbcon_blank; - info->fb_info.flags = FBINFO_FLAG_DEFAULT; - #ifdef __sparc__ atyfb_save_palette(&info->fb_info, 0); #endif @@ -2746,12 +3582,15 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) if (register_framebuffer(&info->fb_info) < 0) return 0; + info->next = fb_list; + fb_list = info; + printk("fb%d: %s frame buffer device on %s\n", GET_FB_IDX(info->fb_info.node), atyfb_name, name); return 1; } -__initfunc(void atyfb_init(void)) +int __init atyfb_init(void) { #if defined(CONFIG_FB_OF) /* We don't want to be called like this. */ @@ -2771,7 +3610,7 @@ __initfunc(void atyfb_init(void)) /* Do not attach when we have a serial console. */ if (!con_is_present()) - return; + return -ENXIO; #else u16 tmp; #endif @@ -2779,39 +3618,40 @@ __initfunc(void atyfb_init(void)) for (pdev = pci_devices; pdev; pdev = pdev->next) { if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && (pdev->vendor == PCI_VENDOR_ID_ATI)) { + struct resource *rp; info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); if (!info) { printk("atyfb_init: can't alloc fb_info_aty\n"); - return; + return -ENXIO; } memset(info, 0, sizeof(struct fb_info_aty)); - addr = pdev->base_address[0]; - if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) - addr = pdev->base_address[1]; + rp = &pdev->resource[0]; + if (rp->flags & IORESOURCE_IO) + rp = &pdev->resource[1]; + addr = rp->start; if (!addr) continue; - addr &= PCI_BASE_ADDRESS_MEM_MASK; #ifdef __sparc__ /* * Map memory-mapped registers. */ - info->ati_regbase = addr + 0x7ffc00; - info->ati_regbase_phys = __pa(addr + 0x7ffc00); + info->ati_regbase = addr + 0x7ffc00UL; + info->ati_regbase_phys = addr + 0x7ffc00UL; /* * Map in big-endian aperture. */ - info->frame_buffer = (unsigned long)(addr + 0x800000); - info->frame_buffer_phys = __pa(addr + 0x800000); + info->frame_buffer = (unsigned long) __va(addr + 0x800000UL); + info->frame_buffer_phys = addr + 0x800000UL; /* * Figure mmap addresses from PCI config space. * Split Framebuffer in big- and little-endian halfs. */ - for (i = 0; i < 6 && pdev->base_address[i]; i++) + for (i = 0; i < 6 && pdev->resource[i].start; i++) /* nothing */; j = i + 4; @@ -2819,27 +3659,26 @@ __initfunc(void atyfb_init(void)) if (!info->mmap_map) { printk("atyfb_init: can't alloc mmap_map\n"); kfree(info); - return; + return -ENXIO; } memset(info->mmap_map, 0, j * sizeof(*info->mmap_map)); - for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) { + for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) { + struct resource *rp = &pdev->resource[i]; int io, breg = PCI_BASE_ADDRESS_0 + (i << 2); unsigned long base; u32 size, pbase; - base = pdev->base_address[i]; + base = rp->start; - io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; + io = (rp->flags & IORESOURCE_IO); + size = rp->end - base + 1; + pci_read_config_dword(pdev, breg, &pbase); - pci_write_config_dword(pdev, breg, 0xffffffff); - pci_read_config_dword(pdev, breg, &size); - pci_write_config_dword(pdev, breg, pbase); if (io) size &= ~1; - size = ~(size) + 1; /* * Map the framebuffer a second time, this time without @@ -2849,7 +3688,7 @@ __initfunc(void atyfb_init(void)) */ if (base == addr) { info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK; - info->mmap_map[j].poff = __pa(base & PAGE_MASK); + info->mmap_map[j].poff = base & PAGE_MASK; info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; info->mmap_map[j].prot_mask = _PAGE_CACHE; info->mmap_map[j].prot_flag = _PAGE_E; @@ -2862,7 +3701,7 @@ __initfunc(void atyfb_init(void)) */ if (base == addr) { info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK; - info->mmap_map[j].poff = __pa((base+0x800000) & PAGE_MASK); + info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK; info->mmap_map[j].size = 0x800000; info->mmap_map[j].prot_mask = _PAGE_CACHE; info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; @@ -2871,7 +3710,7 @@ __initfunc(void atyfb_init(void)) } info->mmap_map[j].voff = pbase & PAGE_MASK; - info->mmap_map[j].poff = __pa(base & PAGE_MASK); + info->mmap_map[j].poff = base & PAGE_MASK; info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; info->mmap_map[j].prot_mask = _PAGE_CACHE; info->mmap_map[j].prot_flag = _PAGE_E; @@ -2999,7 +3838,7 @@ __initfunc(void atyfb_init(void)) if(!info->ati_regbase) { kfree(info); - return; + return -ENOMEM; } info->ati_regbase_phys += 0xc00; @@ -3026,7 +3865,7 @@ __initfunc(void atyfb_init(void)) if(!info->frame_buffer) { kfree(info); - return; + return -ENXIO; } #endif /* __sparc__ */ @@ -3035,7 +3874,7 @@ __initfunc(void atyfb_init(void)) if (info->mmap_map) kfree(info->mmap_map); kfree(info); - return; + return -ENXIO; } #ifdef __sparc__ @@ -3051,14 +3890,16 @@ __initfunc(void atyfb_init(void)) info->mmap_map[0].prot_mask = _PAGE_CACHE; info->mmap_map[0].prot_flag = _PAGE_E; info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram; - info->mmap_map[1].poff = __pa(info->ati_regbase & PAGE_MASK); + info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK; info->mmap_map[1].size = PAGE_SIZE; info->mmap_map[1].prot_mask = _PAGE_CACHE; info->mmap_map[1].prot_flag = _PAGE_E; #endif /* __sparc__ */ } } + #elif defined(CONFIG_ATARI) + u32 clock_r; int m64_num; struct fb_info_aty *info; @@ -3073,7 +3914,7 @@ __initfunc(void atyfb_init(void)) info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); if (!info) { printk("atyfb_init: can't alloc fb_info_aty\n"); - return; + return -ENOMEM; } memset(info, 0, sizeof(struct fb_info_aty)); @@ -3082,21 +3923,40 @@ __initfunc(void atyfb_init(void)) * kernel address space. */ info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]); - info->frame_buffer_phys = info->frame_buffer; + info->frame_buffer_phys = info->frame_buffer; /* Fake! */ info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul; - info->ati_regbase_phys = info->ati_regbase; + info->ati_regbase_phys = info->ati_regbase; /* Fake! */ + + aty_st_le32(CLOCK_CNTL, 0x12345678, info); + clock_r = aty_ld_le32(CLOCK_CNTL, info); + + switch (clock_r & 0x003F) { + case 0x12: + info->clk_wr_offset = 3; /* */ + break; + case 0x34: + info->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */ + break; + case 0x16: + info->clk_wr_offset = 1; /* */ + break; + case 0x38: + info->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */ + break; + } if (!aty_init(info, "ISA bus")) { kfree(info); /* This is insufficient! kernel_map has added two large chunks!! */ - return; + return -ENXIO; } } -#endif +#endif /* CONFIG_ATARI */ + return 0; } #ifdef CONFIG_FB_OF -__initfunc(void atyfb_of_init(struct device_node *dp)) +void __init atyfb_of_init(struct device_node *dp) { unsigned long addr; u8 bus, devfn; @@ -3135,7 +3995,7 @@ __initfunc(void atyfb_of_init(struct device_node *dp)) 0x1000); if(! info->ati_regbase) { - printk("atyfb_init: ioremap() returned NULL\n"); + printk("atyfb_of_init: ioremap() returned NULL\n"); kfree(info); return; } @@ -3162,7 +4022,7 @@ __initfunc(void atyfb_of_init(struct device_node *dp)) info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); if(! info->frame_buffer) { - printk("atyfb_init: ioremap() returned NULL\n"); + printk("atyfb_of_init: ioremap() returned NULL\n"); kfree(info); return; } @@ -3180,12 +4040,13 @@ __initfunc(void atyfb_of_init(struct device_node *dp)) #endif /* CONFIG_FB_OF */ -__initfunc(void atyfb_setup(char *options, int *ints)) +#ifndef MODULE +int __init atyfb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -3247,11 +4108,15 @@ __initfunc(void atyfb_setup(char *options, int *ints)) } } #endif + else + mode_option = this_opt; } + return 0; } +#endif /* !MODULE */ #ifdef CONFIG_ATARI -__initfunc(static int store_video_par(char *video_str, unsigned char m64_num)) +static int __init store_video_par(char *video_str, unsigned char m64_num) { char *p; unsigned long vmembase, size, guiregbase; @@ -3280,7 +4145,7 @@ mach64_invalid: return -1; } -__initfunc(static char *strtoke(char *s, const char *ct)) +static char __init *strtoke(char *s, const char *ct) { static char *ssave = NULL; char *sbegin, *send; @@ -3870,3 +4735,44 @@ static struct display_switch fbcon_aty32 = { FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif + +#ifdef MODULE +int __init init_module(void) +{ + atyfb_init(); + return fb_list ? 0 : -ENXIO; +} + +void cleanup_module(void) +{ + while (fb_list) { + struct fb_info_aty *info = fb_list; + fb_list = info->next; + + unregister_framebuffer(&info->fb_info); + +#ifndef __sparc__ + if (info->ati_regbase) + iounmap((void *)info->ati_regbase); + if (info->frame_buffer) + iounmap((void *)info->frame_buffer); +#ifdef __BIG_ENDIAN + if (info->cursor && info->cursor->ram) + iounmap(info->cursor->ram); +#endif +#endif + + if (info->cursor) { + if (info->cursor->timer) + kfree(info->cursor->timer); + kfree(info->cursor); + } +#ifdef __sparc__ + if (info->mmap_map) + kfree(info->mmap_map); +#endif + kfree(info); + } +} + +#endif diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c index 0735ca1b3..25a223600 100644 --- a/drivers/video/bwtwofb.c +++ b/drivers/video/bwtwofb.c @@ -1,4 +1,4 @@ -/* $Id: bwtwofb.c,v 1.7 1999/01/26 10:55:02 jj Exp $ +/* $Id: bwtwofb.c,v 1.8 1999/08/26 05:13:09 shadow Exp $ * bwtwofb.c: BWtwo frame buffer driver * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -216,7 +216,7 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) #endif fb->margins = bw2_margins; - fb->physbase = phys; + fb->physbase = __get_phys(fb->sbdp->sbus_vaddrs[0]); fb->mmap_map = bw2_mmap_map; #ifdef __sparc_v9__ diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c index c5dfaad6e..0e1f095c6 100644 --- a/drivers/video/cgfourteenfb.c +++ b/drivers/video/cgfourteenfb.c @@ -1,4 +1,4 @@ -/* $Id: cgfourteenfb.c,v 1.4 1999/01/26 10:55:03 jj Exp $ +/* $Id: cgfourteenfb.c,v 1.5 1999/08/10 15:56:02 davem Exp $ * cgfourteenfb.c: CGfourteen frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -288,19 +288,19 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon return 0; } -__initfunc(static unsigned long get_phys(unsigned long addr)) +static unsigned long __init get_phys(unsigned long addr) { return __get_phys(addr); } -__initfunc(static int get_iospace(unsigned long addr)) +static int __init get_iospace(unsigned long addr) { return __get_iospace(addr); } static char idstring[60] __initdata = { 0 }; -__initfunc(char *cgfourteenfb_init(struct fb_info_sbusfb *fb)) +char __init *cgfourteenfb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index 1973ba92b..5921e232b 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.17 1999/05/25 01:00:31 davem Exp $ +/* $Id: cgsixfb.c,v 1.19 1999/08/10 15:56:03 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -588,9 +588,21 @@ static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); } +static int __init cg6_rasterimg (struct fb_info *info, int start) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + register struct cg6_fbc *fbc = fb->s.cg6.fbc; + int i; + + do { + i = fbc->s; + } while (i & 0x10000000); + return 0; +} + static char idstring[70] __initdata = { 0 }; -__initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) +char __init *cgsixfb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; @@ -601,10 +613,20 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) char *p; char *cardtype; struct bt_regs *bt; + struct fb_ops *fbops; + + fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); + if (!fbops) return NULL; + + *fbops = *fb->info.fbops; + fbops->fb_rasterimg = cg6_rasterimg; + fb->info.fbops = fbops; + + if (prom_getbool (fb->prom_node, "dblbuf")) { + type->fb_size *= 4; + fix->smem_len *= 4; + } - strcpy(fb->info.modename, "CGsix"); - - strcpy(fix->id, "CGsix"); fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_CGSIX; @@ -660,9 +682,9 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { if (fix->smem_len <= 0x100000) { - cardtype = "TurboGX"; + cardtype = "TGX"; } else { - cardtype = "TurboGX+"; + cardtype = "TGX+"; } } else { if (fix->smem_len <= 0x100000) { @@ -680,6 +702,9 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) #endif (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype); + + sprintf(fb->info.modename, "CGsix [%s]", cardtype); + sprintf(fix->id, "CGsix [%s]", cardtype); cg6_reset(fb); diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c index 91611c674..e8cb95e59 100644 --- a/drivers/video/cgthreefb.c +++ b/drivers/video/cgthreefb.c @@ -1,4 +1,4 @@ -/* $Id: cgthreefb.c,v 1.4 1999/01/26 10:55:01 jj Exp $ +/* $Id: cgthreefb.c,v 1.5 1999/08/10 15:56:04 davem Exp $ * cgthreefb.c: CGthree frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -145,7 +145,7 @@ static u_char cg3_dacvals[] __initdata = { static char idstring[60] __initdata = { 0 }; -__initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb)) +char __init *cgthreefb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index eb5d8931c..79df3aa98 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -112,7 +112,7 @@ static struct notifier_block chips_sleep_notifier = { /* * Exported functions */ -void chips_init(void); +int chips_init(void); void chips_of_init(struct device_node *dp); static int chips_open(struct fb_info *info, int user); @@ -525,7 +525,7 @@ static struct chips_init_reg chips_init_xr[] = { { 0xa8, 0x00 } }; -__initfunc(static void chips_hw_init(struct fb_info_chips *p)) +static void __init chips_hw_init(struct fb_info_chips *p) { int i; @@ -544,12 +544,12 @@ __initfunc(static void chips_hw_init(struct fb_info_chips *p)) write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); } -__initfunc(static void init_chips(struct fb_info_chips *p)) +static void __init init_chips(struct fb_info_chips *p) { int i; strcpy(p->fix.id, "C&T 65550"); - p->fix.smem_start = (char *) p->frame_buffer_phys; + p->fix.smem_start = p->frame_buffer_phys; // FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB. // * "3500" PowerBook G3 (the original PB G3) has 2MB. @@ -559,7 +559,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p)) // * 3400 has 1MB (I think). Don't know if it's expandable. // -- Tim Seufert p->fix.smem_len = 0x100000; // 1MB - p->fix.mmio_start = (char *) p->io_base_phys; + p->fix.mmio_start = p->io_base_phys; p->fix.type = FB_TYPE_PACKED_PIXELS; p->fix.visual = FB_VISUAL_PSEUDOCOLOR; p->fix.line_length = 800; @@ -645,7 +645,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p)) all_chips = p; } -__initfunc(void chips_init(void)) +int __init chips_init(void) { #ifndef CONFIG_FB_OF struct device_node *dp; @@ -654,9 +654,10 @@ __initfunc(void chips_init(void)) if (dp != 0) chips_of_init(dp); #endif /* CONFIG_FB_OF */ + return 0; } -__initfunc(void chips_of_init(struct device_node *dp)) +void __init chips_of_init(struct device_node *dp) { struct fb_info_chips *p; unsigned long addr; diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index 3f95ae58c..23e0f64dc 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -1,7 +1,39 @@ /* - * Based on retz3fb.c and clgen.c + * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets + * + * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * + * Contributors (thanks, all!) + * + * Jeff Rugen: + * Major contributions; Motorola PowerStack (PPC and PCI) support, + * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. + * + * Geert Uytterhoeven: + * Excellent code review. + * + * Lars Hecking: + * Amiga updates and testing. + * + * Original clgenfb author: Frank Neumann + * + * Based on retz3fb.c and clgen.c: + * Copyright (C) 1997 Jes Sorensen + * Copyright (C) 1996 Frank Neumann + * + *************************************************************** + * + * Format this code with GNU indent '-kr -i8 -pcs' options. + * + * 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. + * */ - + +#define CLGEN_VERSION "1.9.4.4" + +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -11,12 +43,23 @@ #include <linux/malloc.h> #include <linux/delay.h> #include <linux/fb.h> -#include <linux/zorro.h> #include <linux/init.h> -#include <asm/amigahw.h> +#include <linux/selection.h> #include <asm/pgtable.h> #include <asm/delay.h> #include <asm/io.h> +#ifdef CONFIG_ZORRO +#include <linux/zorro.h> +#endif +#ifdef CONFIG_PCI +#include <linux/pci.h> +#endif +#ifdef CONFIG_AMIGA +#include <asm/amigahw.h> +#endif +#ifdef CONFIG_FB_OF +#include <asm/prom.h> +#endif #include <video/fbcon.h> #include <video/fbcon-mfb.h> @@ -26,125 +69,415 @@ #include <video/fbcon-cfb32.h> #include "clgenfb.h" +#include "vga.h" -#define CLGEN_VERSION "1.4 ?" -/* #define DEBUG if(1) */ -#define DEBUG if(0) + +/***************************************************************** + * + * compatibility with older kernel versions + * + */ + +#ifndef LINUX_VERSION_CODE +#include <linux/version.h> +#endif + +#ifndef KERNEL_VERSION +#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) +#endif + +#ifndef PCI_DEVICE_ID_CIRRUS_5462 +#define PCI_DEVICE_ID_CIRRUS_5462 0x00d0 +#endif + + + + +/***************************************************************** + * + * debugging and utility macros + * + */ + +/* enable debug output? */ +/* #define CLGEN_DEBUG 1 */ + +/* disable runtime assertions? */ +/* #define CLGEN_NDEBUG */ + + +/* debug output */ +#ifdef CLGEN_DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +/* debugging assertions */ +#ifndef CLGEN_NDEBUG +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n",\ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#else +#define assert(expr) +#endif #define arraysize(x) (sizeof(x)/sizeof(*(x))) -/* board types */ -#define BT_NONE 0 -#define BT_SD64 1 -#define BT_PICCOLO 2 -#define BT_PICASSO 3 -#define BT_SPECTRUM 4 -#define BT_PICASSO4 5 +#ifdef TRUE +#undef TRUE +#endif +#ifdef FALSE +#undef FALSE +#endif +#define TRUE 1 +#define FALSE 0 + +#define MB_ (1024*1024) #define MAX_NUM_BOARDS 7 -#define TRUE 1 -#define FALSE 0 -struct clgenfb_par -{ - struct fb_var_screeninfo var; - - __u32 line_length; /* in BYTES! */ - __u32 visual; - __u32 type; - - long freq; - long nom; - long den; - long div; - - long HorizRes; /* The x resolution in pixel */ - long HorizTotal; - long HorizDispEnd; - long HorizBlankStart; - long HorizBlankEnd; - long HorizSyncStart; - long HorizSyncEnd; - - long VertRes; /* the physical y resolution in scanlines */ - long VertTotal; - long VertDispEnd; - long VertSyncStart; - long VertSyncEnd; - long VertBlankStart; - long VertBlankEnd; + + +/***************************************************************** + * + * chipset information + * + */ + +/* board types */ +typedef enum { + BT_NONE = 0, + BT_SD64, + BT_PICCOLO, + BT_PICASSO, + BT_SPECTRUM, + BT_PICASSO4, /* GD5446 */ + BT_ALPINE, /* GD543x/4x */ + BT_GD5480, + BT_LAGUNA, /* GD546x */ +} clgen_board_t; + + + +/* + * per-board-type information, used for enumerating and abstracting + * chip-specific information + * NOTE: MUST be in the same order as clgen_board_t in order to + * use direct indexing on this array + * NOTE: '__initdata' cannot be used as some of this info + * is required at runtime. Maybe separate into an init-only and + * a run-time table? + */ +static const struct clgen_board_info_rec { + clgen_board_t btype; /* chipset enum, not strictly necessary, as + * clgen_board_info[] is directly indexed + * by this value */ + char *name; /* ASCII name of chipset */ + long maxclock; /* maximum video clock */ + unsigned init_sr07 : 1; /* init SR07 during init_vgachip() */ + unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */ + unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */ + + /* initial SR07 value, then for each mode */ + unsigned char sr07; + unsigned char sr07_1bpp; + unsigned char sr07_1bpp_mux; + unsigned char sr07_8bpp; + unsigned char sr07_8bpp_mux; + + unsigned char sr1f; /* SR1F VGA initial register value */ +} clgen_board_info[] = { + { BT_NONE, }, /* dummy record */ + { BT_SD64, + "CL SD64", + 140000, /* the SD64/P4 have a higher max. videoclock */ + TRUE, + TRUE, + TRUE, + 0xF0, + 0xF0, + 0, /* unused, does not multiplex */ + 0xF1, + 0, /* unused, does not multiplex */ + 0x20 }, + { BT_PICCOLO, + "CL Piccolo", + 90000, + TRUE, + TRUE, + FALSE, + 0x80, + 0x80, + 0, /* unused, does not multiplex */ + 0x81, + 0, /* unused, does not multiplex */ + 0x22 }, + { BT_PICASSO, + "CL Picasso", + 90000, + TRUE, + TRUE, + FALSE, + 0x20, + 0x20, + 0, /* unused, does not multiplex */ + 0x21, + 0, /* unused, does not multiplex */ + 0x22 }, + { BT_SPECTRUM, + "CL Spectrum", + 90000, + TRUE, + TRUE, + FALSE, + 0x80, + 0x80, + 0, /* unused, does not multiplex */ + 0x81, + 0, /* unused, does not multiplex */ + 0x22 }, + { BT_PICASSO4, + "CL Picasso4", + 140000, /* the SD64/P4 have a higher max. videoclock */ + TRUE, + FALSE, + TRUE, + 0x20, + 0x20, + 0, /* unused, does not multiplex */ + 0x21, + 0, /* unused, does not multiplex */ + 0 }, + { BT_ALPINE, + "CL Alpine", + 110000, /* 135100 for some, 85500 for others */ + TRUE, + TRUE, + TRUE, + 0xA0, + 0xA1, + 0xA7, + 0xA1, + 0xA7, + 0x1C }, + { BT_GD5480, + "CL GD5480", + 90000, + TRUE, + TRUE, + TRUE, + 0x10, + 0x11, + 0, /* unused, does not multiplex */ + 0x11, + 0, /* unused, does not multiplex */ + 0x1C }, + { BT_LAGUNA, + "CL Laguna", + 135100, + FALSE, + FALSE, + TRUE, + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0 }, /* unused */ +}; + + +#ifdef CONFIG_PCI +/* the list of PCI devices for which we probe, and the + * order in which we do it */ +static const struct { + clgen_board_t btype; + const char *nameOverride; /* XXX unused... for now */ + unsigned short device; +} clgen_pci_probe_list[] __initdata = { + { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5436 }, + { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 }, + { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 }, + { BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */ + { BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */ + { BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */ + { BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 }, + { BT_LAGUNA, "CL Laguna 3D", PCI_DEVICE_ID_CIRRUS_5464 }, + { BT_LAGUNA, "CL Laguna 3DA", PCI_DEVICE_ID_CIRRUS_5465 }, +}; +#endif /* CONFIG_PCI */ + + + +#ifdef CONFIG_ZORRO +static const struct { + clgen_board_t btype; + int key, key2; +} clgen_zorro_probe_list[] __initdata = { + { BT_SD64, + ZORRO_PROD_HELFRICH_SD64_RAM, + ZORRO_PROD_HELFRICH_SD64_REG }, + { BT_PICCOLO, + ZORRO_PROD_HELFRICH_PICCOLO_RAM, + ZORRO_PROD_HELFRICH_PICCOLO_REG }, + { BT_PICASSO, + ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, + ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG }, + { BT_SPECTRUM, + ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, + ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG }, + { BT_PICASSO4, + ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, + 0 }, +}; +#endif /* CONFIG_ZORRO */ + + + +struct clgenfb_par { + struct fb_var_screeninfo var; + + __u32 line_length; /* in BYTES! */ + __u32 visual; + __u32 type; + + long freq; + long nom; + long den; + long div; + long multiplexing; + long mclk; + long divMCLK; + + long HorizRes; /* The x resolution in pixel */ + long HorizTotal; + long HorizDispEnd; + long HorizBlankStart; + long HorizBlankEnd; + long HorizSyncStart; + long HorizSyncEnd; + + long VertRes; /* the physical y resolution in scanlines */ + long VertTotal; + long VertDispEnd; + long VertSyncStart; + long VertSyncEnd; + long VertBlankStart; + long VertBlankEnd; }; + + +#ifdef CLGEN_DEBUG +typedef enum { + CRT, + SEQ +} clgen_dbg_reg_class_t; +#endif /* CLGEN_DEBUG */ + + + + /* info about board */ -struct clgenfb_info -{ - struct fb_info_gen gen; - - int keyRAM; /* RAM, REG zorro board keys */ - int keyREG; - unsigned long fbmem; - volatile unsigned char *regs; - unsigned long mem; - unsigned long size; - int btype; - int smallboard; - unsigned char SFR; /* Shadow of special function register */ - - unsigned long fbmem_phys; - unsigned long fbregs_phys; - - struct clgenfb_par currentmode; - union { +struct clgenfb_info { + struct fb_info_gen gen; + + caddr_t fbmem; + caddr_t regs; + caddr_t mem; + unsigned long size; + clgen_board_t btype; + int smallboard; + unsigned char SFR; /* Shadow of special function register */ + + unsigned long fbmem_phys; + unsigned long fbregs_phys; + + struct clgenfb_par currentmode; + + struct { u8 red, green, blue, pad; } palette[256]; + + union { #ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; + u16 cfb16[16]; #endif #ifdef FBCON_HAS_CFB24 - u32 cfb24[16]; + u32 cfb24[16]; #endif #ifdef FBCON_HAS_CFB32 - u32 cfb32[16]; + u32 cfb32[16]; +#endif + } fbcon_cmap; + +#ifdef CONFIG_ZORRO + int keyRAM; /* RAM, REG zorro board keys */ + int keyREG; + unsigned long board_addr, + board_size; +#endif + +#ifdef CONFIG_PCI + struct pci_dev *pdev; #endif - } fbcon_cmap; }; + + + static struct display disp; -static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */ -static struct clgenfb_info *fb_info=NULL; /* pointer to current board */ +static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */ + +static unsigned clgen_def_mode = 1; + +static int release_io_ports = 0; + + /* * Predefined Video Modes */ -static struct fb_videomode clgenfb_predefined[] __initdata = +static const struct { + const char *name; + struct fb_var_screeninfo var; +} clgenfb_predefined[] __initdata = + { - { "Autodetect", /* autodetect mode */ - { 0 } + {"Autodetect", /* autodetect mode */ + {0} }, - { "640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ - { - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - } + {"640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ + { + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } }, - /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ /* - Modeline from XF86Config: - Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 - */ - { - "1024x768", - { - 1024, 768, 1024, 768, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - } + Modeline from XF86Config: + Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 + */ + {"1024x768", /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ + { + 1024, 768, 1024, 768, 0, 0, 8, 0, + {0, 8, 0}, + {0, 8, 0}, + {0, 8, 0}, + {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } } }; @@ -155,135 +488,189 @@ static struct fb_var_screeninfo clgenfb_default; * Frame Buffer Name */ -static char clgenfb_name[16] = "CLgen"; +static const char *clgenfb_name = "CLgen"; /****************************************************************************/ /**** BEGIN PROTOTYPES ******************************************************/ + /*--- Interface used by the world ------------------------------------------*/ -void clgenfb_init(void); -void clgenfb_setup(char *options, int *ints); -int clgenfb_open(struct fb_info *info, int user); -int clgenfb_release(struct fb_info *info, int user); -int clgenfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con, - struct fb_info *info); +int clgenfb_init (void); +int clgenfb_setup (char *options); + +#ifdef MODULE +static void clgenfb_cleanup (struct clgenfb_info *info); +#endif + +static int clgenfb_open (struct fb_info *info, int user); +static int clgenfb_release (struct fb_info *info, int user); +static int clgenfb_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); +#if defined(CONFIG_FB_OF) +int clgen_of_init (struct device_node *dp); +#endif /* function table of the above functions */ static struct fb_ops clgenfb_ops = { - clgenfb_open, - clgenfb_release, - fbgen_get_fix, /* using the generic functions */ - fbgen_get_var, /* makes things much easier... */ - fbgen_set_var, - fbgen_get_cmap, - fbgen_set_cmap, - fbgen_pan_display, - clgenfb_ioctl, - NULL + clgenfb_open, + clgenfb_release, + fbgen_get_fix, /* using the generic functions */ + fbgen_get_var, /* makes things much easier... */ + fbgen_set_var, + fbgen_get_cmap, + fbgen_set_cmap, + fbgen_pan_display, + clgenfb_ioctl, + NULL }; /*--- Hardware Specific Routines -------------------------------------------*/ -static void clgen_detect(void); -static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par, +static void clgen_detect (void); +static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info); -static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par, +static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info); -static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par, +static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info); -static void clgen_get_par(void *par, struct fb_info_gen *info); -static void clgen_set_par(const void *par, struct fb_info_gen *info); -static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info); -static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green, +static void clgen_get_par (void *par, struct fb_info_gen *info); +static void clgen_set_par (const void *par, struct fb_info_gen *info); +static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info); +static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); -static int clgen_pan_display(const struct fb_var_screeninfo *var, +static int clgen_pan_display (const struct fb_var_screeninfo *var, struct fb_info_gen *info); -static int clgen_blank(int blank_mode, struct fb_info_gen *info); +static int clgen_blank (int blank_mode, struct fb_info_gen *info); -static void clgen_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info); +static void clgen_set_disp (const void *par, struct display *disp, + struct fb_info_gen *info); /* function table of the above functions */ -static struct fbgen_hwswitch clgen_hwswitch = +static struct fbgen_hwswitch clgen_hwswitch = { - clgen_detect, - clgen_encode_fix, - clgen_decode_var, - clgen_encode_var, - clgen_get_par, - clgen_set_par, - clgen_getcolreg, - clgen_setcolreg, - clgen_pan_display, - clgen_blank, - clgen_set_disp + clgen_detect, + clgen_encode_fix, + clgen_decode_var, + clgen_encode_var, + clgen_get_par, + clgen_set_par, + clgen_getcolreg, + clgen_setcolreg, + clgen_pan_display, + clgen_blank, + clgen_set_disp }; /* Text console acceleration */ #ifdef FBCON_HAS_CFB8 -static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, +static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width); -static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, +static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width); -static struct display_switch fbcon_clgen_8 = { - fbcon_cfb8_setup, - fbcon_clgen8_bmove, - fbcon_clgen8_clear, - fbcon_cfb8_putc, - fbcon_cfb8_putcs, - fbcon_cfb8_revc, - NULL, - NULL, - fbcon_cfb8_clear_margins, - FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +static struct display_switch fbcon_clgen_8 = +{ + fbcon_cfb8_setup, + fbcon_clgen8_bmove, + fbcon_clgen8_clear, + fbcon_cfb8_putc, + fbcon_cfb8_putcs, + fbcon_cfb8_revc, + NULL, + NULL, + fbcon_cfb8_clear_margins, + FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) +}; +#endif +#ifdef FBCON_HAS_CFB16 +static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, + int dy, int dx, int height, int width); +static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); +static struct display_switch fbcon_clgen_16 = +{ + fbcon_cfb16_setup, + fbcon_clgen16_bmove, + fbcon_clgen16_clear, + fbcon_cfb16_putc, + fbcon_cfb16_putcs, + fbcon_cfb16_revc, + NULL, + NULL, + fbcon_cfb16_clear_margins, + FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) +}; +#endif +#ifdef FBCON_HAS_CFB32 +static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, + int dy, int dx, int height, int width); +static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); +static struct display_switch fbcon_clgen_32 = +{ + fbcon_cfb32_setup, + fbcon_clgen32_bmove, + fbcon_clgen32_clear, + fbcon_cfb32_putc, + fbcon_cfb32_putcs, + fbcon_cfb32_revc, + NULL, + NULL, + fbcon_cfb32_clear_margins, + FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif /*--- Internal routines ----------------------------------------------------*/ -static void init_vgachip(void); -static void switch_monitor(int on); - -static void WGen( int regnum, unsigned char val ); -static unsigned char RGen( int regnum ); -static void WSeq( unsigned char regnum, unsigned char val ); -static unsigned char RSeq( unsigned char regnum ); -static void WCrt( unsigned char regnum, unsigned char val ); -static unsigned char RCrt( unsigned char regnum ); -static void WGfx( unsigned char regnum, unsigned char val ); -static unsigned char RGfx( unsigned char regnum ); -static void WAttr( unsigned char regnum, unsigned char val ); -static void AttrOn( void ); -static unsigned char RAttr( unsigned char regnum ); -static void WHDR( unsigned char val ); -static unsigned char RHDR( void ); -static void WSFR( unsigned char val ); -static void WSFR2( unsigned char val ); -static void WClut( unsigned char regnum, unsigned char red, - unsigned char green, - unsigned char blue ); -static void RClut( unsigned char regnum, unsigned char *red, - unsigned char *green, - unsigned char *blue ); -static void clgen_WaitBLT( void ); -static void clgen_BitBLT (u_short curx, u_short cury, - u_short destx, u_short desty, - u_short width, u_short height, - u_short line_length); -static void clgen_RectFill (u_short x, u_short y, - u_short width, u_short height, - u_char color, u_short line_length); - -static void bestclock(long freq, long *best, - long *nom, long *den, - long *div, long maxfreq); +static void init_vgachip (struct clgenfb_info *fb_info); +static void switch_monitor (struct clgenfb_info *fb_info, int on); +static void WGen (const struct clgenfb_info *fb_info, + int regnum, unsigned char val); +static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum); +static void AttrOn (const struct clgenfb_info *fb_info); +static void WHDR (const struct clgenfb_info *fb_info, unsigned char val); +static void WSFR (struct clgenfb_info *fb_info, unsigned char val); +static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val); +static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red, + unsigned char green, + unsigned char blue); +#if 0 +static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red, + unsigned char *green, + unsigned char *blue); +#endif +static void clgen_WaitBLT (caddr_t regbase); +static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, + u_short destx, u_short desty, + u_short width, u_short height, + u_short line_length); +static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y, + u_short width, u_short height, + u_char color, u_short line_length); + +static void bestclock (long freq, long *best, + long *nom, long *den, + long *div, long maxfreq); + +#ifdef CONFIG_PCI +static struct pci_dev *clgen_pci_dev_get (clgen_board_t *btype); +static unsigned int clgen_get_memsize (caddr_t regbase); +static int clgen_pci_setup (struct clgenfb_info *fb_info, clgen_board_t *btype); +#endif /* CONFIG_PCI */ + +#ifdef CLGEN_DEBUG +static void clgen_dump (void); +static void clgen_dbg_reg_dump (caddr_t regbase); +static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...); +static void clgen_dbg_print_byte (const char *name, unsigned char val); +#endif /* CLGEN_DEBUG */ /*** END PROTOTYPES ********************************************************/ /*****************************************************************************/ @@ -292,302 +679,478 @@ static void bestclock(long freq, long *best, static int opencount = 0; /*--- Open /dev/fbx ---------------------------------------------------------*/ -int clgenfb_open(struct fb_info *info, int user) +static int clgenfb_open (struct fb_info *info, int user) { - MOD_INC_USE_COUNT; - if (opencount++ == 0) switch_monitor(1); - return 0; + MOD_INC_USE_COUNT; + if (opencount++ == 0) + switch_monitor ((struct clgenfb_info *) info, 1); + return 0; } /*--- Close /dev/fbx --------------------------------------------------------*/ -int clgenfb_release(struct fb_info *info, int user) +static int clgenfb_release (struct fb_info *info, int user) { - if (--opencount == 0) switch_monitor(0); - MOD_DEC_USE_COUNT; - return 0; + if (--opencount == 0) + switch_monitor ((struct clgenfb_info *) info, 0); + MOD_DEC_USE_COUNT; + return 0; } /*--- handle /dev/fbx ioctl calls ------------------------------------------*/ -int clgenfb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con, - struct fb_info *info) +static int clgenfb_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) { - printk(">clgenfb_ioctl()\n"); - /* Nothing exciting here... */ - printk("<clgenfb_ioctl()\n"); - return -EINVAL; + DPRINTK ("ENTER\n"); + /* Nothing exciting here... */ + DPRINTK ("EXIT\n"); + return -EINVAL; } - /**** END Interface used by the World *************************************/ /****************************************************************************/ /**** BEGIN Hardware specific Routines **************************************/ -static void clgen_detect(void) +static void clgen_detect (void) { - printk(">clgen_detect()\n"); - printk("<clgen_detect()\n"); + DPRINTK ("ENTER\n"); + DPRINTK ("EXIT\n"); } -static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par, - struct fb_info_gen *info) +static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, + struct fb_info_gen *info) { - struct clgenfb_par *_par = (struct clgenfb_par*) par; - struct clgenfb_info *_info = (struct clgenfb_info*)info; - - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, clgenfb_name); - - fix->smem_start = (char*)_info->fbmem_phys; - - /* monochrome: only 1 memory plane */ - /* 8 bit and above: Use whole memory area */ - fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4 - : _info->size; - fix->type = _par->type; - fix->type_aux = 0; - fix->visual = _par->visual; - fix->xpanstep = 1; - fix->ypanstep = 1; - fix->ywrapstep = 0; - fix->line_length = _par->line_length; - fix->mmio_start = (char *)_info->fbregs_phys; - fix->mmio_len = 0x10000; - fix->accel = FB_ACCEL_NONE; + struct clgenfb_par *_par = (struct clgenfb_par *) par; + struct clgenfb_info *_info = (struct clgenfb_info *) info; + + DPRINTK ("ENTER\n"); + + memset (fix, 0, sizeof (struct fb_fix_screeninfo)); + strcpy (fix->id, clgenfb_name); + + if (_info->btype == BT_GD5480) { + /* Select proper byte-swapping aperture */ + switch (_par->var.bits_per_pixel) { + case 1: + case 8: + fix->smem_start = _info->fbmem_phys; + break; + case 16: + fix->smem_start = _info->fbmem_phys + 1 * MB_; + break; + case 24: + case 32: + fix->smem_start = _info->fbmem_phys + 2 * MB_; + break; + } + } else { + fix->smem_start = _info->fbmem_phys; + } - return 0; + /* monochrome: only 1 memory plane */ + /* 8 bit and above: Use whole memory area */ + fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4 + : _info->size; + fix->type = _par->type; + fix->type_aux = 0; + fix->visual = _par->visual; + fix->xpanstep = 1; + fix->ypanstep = 1; + fix->ywrapstep = 0; + fix->line_length = _par->line_length; + + /* FIXME: map region at 0xB8000 if available, fill in here */ + fix->mmio_start = 0; + fix->mmio_len = 0; + fix->accel = FB_ACCEL_NONE; + + DPRINTK ("EXIT\n"); + return 0; } -static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par, - struct fb_info_gen *info) + + +/* Get a good MCLK value */ +static long clgen_get_mclk (long freq, int bpp, long *div) { - long freq; - int xres, hfront, hsync, hback; - int yres, vfront, vsync, vback; - int nom,den; /* translyting from pixels->bytes */ - int i; - static struct - { - int xres,yres; - } - modes[] = { {1600,1280}, {1280,1024}, {1024,768}, - {800,600}, {640,480}, {-1,-1} }; - - struct clgenfb_par *_par = (struct clgenfb_par *)par; - - fb_info = (struct clgenfb_info*)info; - printk("clgen_decode_var()\n"); - - printk("Requested: %dx%dx%d\n", var->xres,var->yres,var->bits_per_pixel); - printk(" virtual: %dx%d\n", var->xres_virtual,var->yres_virtual); - printk(" offset: (%d,%d)\n", var->xoffset, var->yoffset); - printk("grayscale: %d\n", var->grayscale); -#if 0 - printk(" activate: 0x%x\n", var->activate); - printk(" pixclock: %d\n", var->pixclock); - printk(" htiming: %d;%d %d\n", var->left_margin,var->right_margin,var->hsync_len); - printk(" vtiming: %d;%d %d\n", var->upper_margin,var->lower_margin,var->vsync_len); - printk(" sync: 0x%x\n", var->sync); - printk(" vmode: 0x%x\n", var->vmode); -#endif + long mclk; + + assert (div != NULL); + + /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. + * Assume a 64-bit data path for now. The formula is: + * ((B * PCLK * 2)/W) * 1.2 + * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ + mclk = ((bpp / 8) * freq * 2) / 4; + mclk = (mclk * 12) / 10; + if (mclk < 50000) + mclk = 50000; + DPRINTK ("Use MCLK of %ld kHz\n", mclk); + + /* Calculate value for SR1F. Multiply by 2 so we can round up. */ + mclk = ((mclk * 16) / 14318); + mclk = (mclk + 1) / 2; + DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk); + + /* Determine if we should use MCLK instead of VCLK, and if so, what we + * should divide it by to get VCLK */ + switch (freq) { + case 24751 ... 25249: + *div = 2; + DPRINTK ("Using VCLK = MCLK/2\n"); + break; + case 49501 ... 50499: + *div = 1; + DPRINTK ("Using VCLK = MCLK\n"); + break; + default: + *div = 0; + break; + } - _par->var = *var; - - switch (var->bits_per_pixel) - { - case 1: nom = 4; den = 8; break; /* 8 pixel per byte, only 1/4th of mem usable */ - case 8: nom = 1; den = 1; break; /* 1 pixel == 1 byte */ - case 16: nom = 2; den = 1; break; /* 2 bytes per pixel */ - case 24: nom = 3; den = 1; break; /* 3 bytes per pixel */ - case 32: nom = 4; den = 1; break; /* 4 bytes per pixel */ - default: - printk("clgen: mode %dx%dx%d rejected...color depth not supported.\n", - var->xres, var->yres, var->bits_per_pixel); - return -EINVAL; - } + return mclk; +} - if (_par->var.xres*nom/den * _par->var.yres > fb_info->size) - { - printk("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", - var->xres, var->yres, var->bits_per_pixel); - return -EINVAL; - } - - /* use highest possible virtual resolution */ - if (_par->var.xres_virtual == -1 && - _par->var.yres_virtual == -1) - { - printk("clgen: using maximum available virtual resolution\n"); - for (i=0; modes[i].xres != -1; i++) +static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, + struct fb_info_gen *info) +{ + long freq; + long maxclock; + int xres, hfront, hsync, hback; + int yres, vfront, vsync, vback; + int nom, den; /* translyting from pixels->bytes */ + int i; + static struct { + int xres, yres; + } modes[] = { { + 1600, 1280 + }, { + 1280, 1024 + }, { + 1024, 768 + }, { - if (modes[i].xres*nom/den * modes[i].yres < fb_info->size/2) + 800, 600 + }, { + 640, 480 + }, { + -1, -1 + } + }; + + struct clgenfb_par *_par = (struct clgenfb_par *) par; + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; + + assert (var != NULL); + assert (par != NULL); + assert (info != NULL); + + DPRINTK ("ENTER\n"); + + DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); + DPRINTK (" virtual: %dx%d\n", var->xres_virtual, var->yres_virtual); + DPRINTK (" offset: (%d,%d)\n", var->xoffset, var->yoffset); + DPRINTK ("grayscale: %d\n", var->grayscale); + + memset (par, 0, sizeof (struct clgenfb_par)); + + _par->var = *var; + + switch (var->bits_per_pixel) { + case 1: + nom = 4; + den = 8; + break; /* 8 pixel per byte, only 1/4th of mem usable */ + case 2 ... 8: + _par->var.bits_per_pixel = 8; + nom = 1; + den = 1; + break; /* 1 pixel == 1 byte */ + case 9 ... 16: + _par->var.bits_per_pixel = 16; + nom = 2; + den = 1; + break; /* 2 bytes per pixel */ + case 17 ... 24: + _par->var.bits_per_pixel = 24; + nom = 3; + den = 1; + break; /* 3 bytes per pixel */ + case 25 ... 32: + _par->var.bits_per_pixel = 32; + nom = 4; + den = 1; + break; /* 4 bytes per pixel */ + default: + printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n", + var->xres, var->yres, var->bits_per_pixel); + DPRINTK ("EXIT - EINVAL error\n"); + return -EINVAL; + } + + if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) { + printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", + var->xres, var->yres, var->bits_per_pixel); + DPRINTK ("EXIT - EINVAL error\n"); + return -EINVAL; + } + /* use highest possible virtual resolution */ + if (_par->var.xres_virtual == -1 && + _par->var.yres_virtual == -1) { + printk ("clgen: using maximum available virtual resolution\n"); + for (i = 0; modes[i].xres != -1; i++) { + if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2) + break; + } + if (modes[i].xres == -1) { + printk ("clgen: could not find a virtual resolution that fits into video memory!!\n"); + DPRINTK ("EXIT - EINVAL error\n"); + return -EINVAL; + } + _par->var.xres_virtual = modes[i].xres; + _par->var.yres_virtual = modes[i].yres; + + printk ("clgen: virtual resolution set to maximum of %dx%d\n", + _par->var.xres_virtual, _par->var.yres_virtual); + } else if (_par->var.xres_virtual == -1) { + /* FIXME: maximize X virtual resolution only */ + } else if (_par->var.yres_virtual == -1) { + /* FIXME: maximize Y virtual resolution only */ + } + if (_par->var.xoffset < 0) + _par->var.xoffset = 0; + if (_par->var.yoffset < 0) + _par->var.yoffset = 0; + + /* truncate xoffset and yoffset to maximum if too high */ + if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres) + _par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1; + + if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres) + _par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1; + + switch (_par->var.bits_per_pixel) { + case 1: + _par->line_length = _par->var.xres_virtual / 8; + _par->visual = FB_VISUAL_MONO10; + break; + + case 8: + _par->line_length = _par->var.xres_virtual; + _par->visual = FB_VISUAL_PSEUDOCOLOR; + _par->var.red.offset = 0; + _par->var.red.length = 6; + _par->var.green.offset = 0; + _par->var.green.length = 6; + _par->var.blue.offset = 0; + _par->var.blue.length = 6; + break; + + case 16: + _par->line_length = _par->var.xres_virtual * 2; + _par->visual = FB_VISUAL_DIRECTCOLOR; +#ifdef CONFIG_PREP + _par->var.red.offset = 2; + _par->var.green.offset = -3; + _par->var.blue.offset = 8; +#else + _par->var.red.offset = 10; + _par->var.green.offset = 5; + _par->var.blue.offset = 0; +#endif + _par->var.red.length = 5; + _par->var.green.length = 5; + _par->var.blue.length = 5; + break; + + case 24: + _par->line_length = _par->var.xres_virtual * 3; + _par->visual = FB_VISUAL_DIRECTCOLOR; +#ifdef CONFIG_PREP + _par->var.red.offset = 8; + _par->var.green.offset = 16; + _par->var.blue.offset = 24; +#else + _par->var.red.offset = 16; + _par->var.green.offset = 8; + _par->var.blue.offset = 0; +#endif + _par->var.red.length = 8; + _par->var.green.length = 8; + _par->var.blue.length = 8; + break; + + case 32: + _par->line_length = _par->var.xres_virtual * 4; + _par->visual = FB_VISUAL_DIRECTCOLOR; +#ifdef CONFIG_PREP + _par->var.red.offset = 8; + _par->var.green.offset = 16; + _par->var.blue.offset = 24; +#else + _par->var.red.offset = 16; + _par->var.green.offset = 8; + _par->var.blue.offset = 0; +#endif + _par->var.red.length = 8; + _par->var.green.length = 8; + _par->var.blue.length = 8; + break; + + default: + DPRINTK("Unsupported bpp size: %d\n", _par->var.bits_per_pixel); + assert (FALSE); + /* should never occur */ break; } - if (modes[i].xres == -1) - { - printk("clgen: could not find a virtual resolution that fits into video memory!!\n"); - return -EINVAL; - } - _par->var.xres_virtual = modes[i].xres; - _par->var.yres_virtual = modes[i].yres; - - printk("clgen: virtual resolution set to maximum of %dx%d\n", - _par->var.xres_virtual, _par->var.yres_virtual); - } - else if (_par->var.xres_virtual == -1) - { - } - else if (_par->var.yres_virtual == -1) - { - } - - if (_par->var.xoffset < 0) _par->var.xoffset = 0; - if (_par->var.yoffset < 0) _par->var.yoffset = 0; - - /* truncate xoffset and yoffset to maximum if too high */ - if (_par->var.xoffset > _par->var.xres_virtual-_par->var.xres) - _par->var.xoffset = _par->var.xres_virtual-_par->var.xres -1; - - if (_par->var.yoffset > _par->var.yres_virtual-_par->var.yres) - _par->var.yoffset = _par->var.yres_virtual-_par->var.yres -1; - - switch (var->bits_per_pixel) - { - case 1: - _par->line_length = _par->var.xres_virtual / 8; - _par->visual = FB_VISUAL_MONO10; - break; - - case 8: - _par->line_length = _par->var.xres_virtual; - _par->visual = FB_VISUAL_PSEUDOCOLOR; - _par->var.red.offset = 0; - _par->var.red.length = 6; - _par->var.green.offset = 0; - _par->var.green.length = 6; - _par->var.blue.offset = 0; - _par->var.blue.length = 6; - break; - - case 16: - _par->line_length = _par->var.xres_virtual * 2; - _par->visual = FB_VISUAL_DIRECTCOLOR; - _par->var.red.offset = 10; - _par->var.red.length = 5; - _par->var.green.offset = 5; - _par->var.green.length = 5; - _par->var.blue.offset = 0; - _par->var.blue.length = 5; - break; - - case 24: - _par->line_length = _par->var.xres_virtual * 3; - _par->visual = FB_VISUAL_DIRECTCOLOR; - _par->var.red.offset = 16; - _par->var.red.length = 8; - _par->var.green.offset = 8; - _par->var.green.length = 8; - _par->var.blue.offset = 0; - _par->var.blue.length = 8; - break; - - case 32: - _par->line_length = _par->var.xres_virtual * 4; - _par->visual = FB_VISUAL_DIRECTCOLOR; - _par->var.red.offset = 16; - _par->var.red.length = 8; - _par->var.green.offset = 8; - _par->var.green.length = 8; - _par->var.blue.offset = 0; - _par->var.blue.length = 8; - break; - } - _par->var.red.msb_right = 0; - _par->var.green.msb_right = 0; - _par->var.blue.msb_right = 0; - _par->var.transp.offset = 0; - _par->var.transp.length = 0; - _par->var.transp.msb_right = 0; - - _par->type = FB_TYPE_PACKED_PIXELS; - - /* convert from ps to kHz */ - freq = 1000000000 / var->pixclock; - - DEBUG printk("desired pixclock: %ld kHz\n", freq); - - /* the SD64/P4 have a higher max. videoclock */ - bestclock(freq, &_par->freq, &_par->nom, &_par->den, &_par->div, - fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4 - ? 140000 : 90000); - - DEBUG printk("Best possible values for given frequency: best: %ld kHz nom: %ld den: %ld div: %ld\n", - _par->freq, _par->nom, _par->den, _par->div); - - xres = _par->var.xres; - hfront = _par->var.right_margin; - hsync = _par->var.hsync_len; - hback = _par->var.left_margin; - - yres = _par->var.yres; - vfront = _par->var.lower_margin; - vsync = _par->var.vsync_len; - vback = _par->var.upper_margin; - - if (_par->var.vmode & FB_VMODE_DOUBLE) - { - yres *= 2; - vfront *= 2; - vsync *= 2; - vback *= 2; - } - else if (_par->var.vmode & FB_VMODE_INTERLACED) - { - yres = ++yres / 2; - vfront = ++vfront / 2; - vsync = ++vsync / 2; - vback = ++vback / 2; - } - - _par->HorizRes = xres; - _par->HorizTotal = (xres + hfront + hsync + hback)/8 - 5; - _par->HorizDispEnd = xres/8 - 1; - _par->HorizBlankStart = xres/8; - _par->HorizBlankEnd = _par->HorizTotal+5; /* does not count with "-5" */ - _par->HorizSyncStart = (xres + hfront)/8 + 1; - _par->HorizSyncEnd = (xres + hfront + hsync)/8 + 1; - - _par->VertRes = yres; - _par->VertTotal = yres + vfront + vsync + vback -2; - _par->VertDispEnd = yres - 1; - _par->VertBlankStart = yres; - _par->VertBlankEnd = _par->VertTotal; - _par->VertSyncStart = yres + vfront - 1; - _par->VertSyncEnd = yres + vfront + vsync - 1; - - if (_par->VertTotal >= 1024) - { - printk(KERN_WARNING "clgen: ERROR: VerticalTotal >= 1024; special treatment required! (TODO)\n"); - return -EINVAL; - } - return 0; + _par->var.red.msb_right = + _par->var.green.msb_right = + _par->var.blue.msb_right = + _par->var.transp.offset = + _par->var.transp.length = + _par->var.transp.msb_right = 0; + + _par->type = FB_TYPE_PACKED_PIXELS; + + /* convert from ps to kHz */ + freq = 1000000000 / var->pixclock; + + DPRINTK ("desired pixclock: %ld kHz\n", freq); + + maxclock = clgen_board_info[fb_info->btype].maxclock; + _par->multiplexing = 0; + + /* If the frequency is greater than we can support, we might be able + * to use multiplexing for the video mode */ + if (freq > maxclock) { + switch (fb_info->btype) { + case BT_ALPINE: + case BT_GD5480: + _par->multiplexing = 1; + break; + + default: + printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock); + DPRINTK ("EXIT - return -EINVAL\n"); + return -EINVAL; + } + } +#if 0 + /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where + * the VCLK is double the pixel clock. */ + switch (var->bits_per_pixel) { + case 16: + case 32: + if (_par->HorizRes <= 800) + freq /= 2; /* Xbh has this type of clock for 32-bit */ + break; + } +#endif + + bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div, + maxclock); + _par->mclk = clgen_get_mclk (freq, _par->var.bits_per_pixel, &_par->divMCLK); + + xres = _par->var.xres; + hfront = _par->var.right_margin; + hsync = _par->var.hsync_len; + hback = _par->var.left_margin; + + yres = _par->var.yres; + vfront = _par->var.lower_margin; + vsync = _par->var.vsync_len; + vback = _par->var.upper_margin; + + if (_par->var.vmode & FB_VMODE_DOUBLE) { + yres *= 2; + vfront *= 2; + vsync *= 2; + vback *= 2; + } else if (_par->var.vmode & FB_VMODE_INTERLACED) { + yres = ++yres / 2; + vfront = ++vfront / 2; + vsync = ++vsync / 2; + vback = ++vback / 2; + } + _par->HorizRes = xres; + _par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5; + _par->HorizDispEnd = xres / 8 - 1; + _par->HorizBlankStart = xres / 8; + _par->HorizBlankEnd = _par->HorizTotal + 5; /* does not count with "-5" */ + _par->HorizSyncStart = (xres + hfront) / 8 + 1; + _par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1; + + _par->VertRes = yres; + _par->VertTotal = yres + vfront + vsync + vback - 2; + _par->VertDispEnd = yres - 1; + _par->VertBlankStart = yres; + _par->VertBlankEnd = _par->VertTotal; + _par->VertSyncStart = yres + vfront - 1; + _par->VertSyncEnd = yres + vfront + vsync - 1; + + if (_par->VertRes >= 1024) { + _par->VertTotal /= 2; + _par->VertSyncStart /= 2; + _par->VertSyncEnd /= 2; + _par->VertDispEnd /= 2; + } + if (_par->multiplexing) { + _par->HorizTotal /= 2; + _par->HorizSyncStart /= 2; + _par->HorizSyncEnd /= 2; + _par->HorizDispEnd /= 2; + } + if (_par->VertRes >= 1280) { + printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n"); + DPRINTK ("EXIT - EINVAL error\n"); + return -EINVAL; + } + DPRINTK ("EXIT\n"); + return 0; } -static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par, - struct fb_info_gen *info) +static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par, + struct fb_info_gen *info) { - *var = ((struct clgenfb_par*)par)->var; - return 0; + DPRINTK ("ENTER\n"); + + *var = ((struct clgenfb_par *) par)->var; + + DPRINTK ("EXIT\n"); + return 0; } /* get current video mode */ -static void clgen_get_par(void *par, struct fb_info_gen *info) +static void clgen_get_par (void *par, struct fb_info_gen *info) { - struct clgenfb_par *_par = (struct clgenfb_par*)par; - struct clgenfb_info*_info = (struct clgenfb_info*)fb_info; + struct clgenfb_par *_par = (struct clgenfb_par *) par; + struct clgenfb_info *_info = (struct clgenfb_info *) info; + + DPRINTK ("ENTER\n"); - *_par = _info->currentmode; + *_par = _info->currentmode; + + DPRINTK ("EXIT\n"); +} + +static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div) +{ + assert (fb_info != NULL); + + if (div == 2) { + /* VCLK = MCLK/2 */ + unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E); + vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1); + vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f)); + } else if (div == 1) { + /* VCLK = MCLK */ + unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E); + vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1); + vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f)); + } else { + vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f); + } } /************************************************************************* @@ -595,1340 +1158,2081 @@ static void clgen_get_par(void *par, struct fb_info_gen *info) actually writes the values for a new video mode into the hardware, **************************************************************************/ -static void clgen_set_par(const void *par, struct fb_info_gen *info) +static void clgen_set_par (const void *par, struct fb_info_gen *info) { - unsigned char tmp; - int offset = 0; - struct clgenfb_par *_par = (struct clgenfb_par*)par; - - printk(KERN_INFO">clgen_set_par()\n"); - printk(KERN_INFO"Requested mode: %dx%dx%d\n", - _par->var.xres, _par->var.yres, _par->var.bits_per_pixel); - printk(KERN_INFO"pixclock: %d\n", _par->var.pixclock); - - fb_info = (struct clgenfb_info *)info; - - /* unlock register CRT0..CRT7 */ - WCrt(CRT11, 0x20); /* previously: 0x00) */ - - /* if DEBUG is set, all parameters get output before writing */ - DEBUG printk("CRT0: %ld\n", _par->HorizTotal); - WCrt(CRT0, _par->HorizTotal); - - DEBUG printk("CRT1: %ld\n", _par->HorizDispEnd); - WCrt(CRT1, _par->HorizDispEnd); - - DEBUG printk("CRT2: %ld\n", _par->HorizBlankStart); - WCrt(CRT2, _par->HorizBlankStart); - - DEBUG printk("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /* + 128: Compatible read */ - WCrt(CRT3, 128 + (_par->HorizBlankEnd % 32)); - - DEBUG printk("CRT4: %ld\n", _par->HorizSyncStart); - WCrt(CRT4, _par->HorizSyncStart); - - tmp = _par->HorizSyncEnd % 32; - if (_par->HorizBlankEnd & 32) - tmp += 128; - DEBUG printk("CRT5: %d\n", tmp); - WCrt(CRT5, tmp); - - DEBUG printk("CRT6: %ld\n", _par->VertTotal & 0xff); - WCrt(CRT6, (_par->VertTotal & 0xff)); - - tmp = 16; /* LineCompare bit #9 */ - if (_par->VertTotal & 256) tmp |= 1; - if (_par->VertDispEnd & 256) tmp |= 2; - if (_par->VertSyncStart & 256) tmp |= 4; - if (_par->VertBlankStart & 256) tmp |= 8; - if (_par->VertTotal & 512) tmp |= 32; - if (_par->VertDispEnd & 512) tmp |= 64; - if (_par->VertSyncStart & 512) tmp |= 128; - DEBUG printk("CRT7: %d\n", tmp); - WCrt(CRT7, tmp); - - tmp = 0x40; /* LineCompare bit #8 */ - if (_par->VertBlankStart & 512) tmp |= 0x20; - if (_par->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; - DEBUG printk("CRT9: %d\n", tmp); - WCrt(CRT9, tmp); - - DEBUG printk("CRT10: %ld\n", _par->VertSyncStart & 0xff); - WCrt(CRT10, (_par->VertSyncStart & 0xff)); - - DEBUG printk("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16); - WCrt(CRT11, (_par->VertSyncEnd % 16 + 64 + 32)); - - DEBUG printk("CRT12: %ld\n", _par->VertDispEnd & 0xff); - WCrt(CRT12, (_par->VertDispEnd & 0xff)); - - DEBUG printk("CRT15: %ld\n", _par->VertBlankStart & 0xff); - WCrt(CRT15, (_par->VertBlankStart & 0xff)); - - DEBUG printk("CRT16: %ld\n", _par->VertBlankEnd & 0xff); - WCrt(CRT16, (_par->VertBlankEnd & 0xff)); - - DEBUG printk("CRT18: 0xff\n"); - WCrt(CRT18, 0xff); - - tmp = 0; - if (_par->var.vmode & FB_VMODE_INTERLACED) tmp |= 1; - if (_par->HorizBlankEnd & 64) tmp |= 16; - if (_par->HorizBlankEnd & 128) tmp |= 32; - if (_par->VertBlankEnd & 256) tmp |= 64; - if (_par->VertBlankEnd & 512) tmp |= 128; - - DEBUG printk("CRT1a: %d\n", tmp); - WCrt(CRT1A, tmp); - - /* set VCLK0 */ - /* hardware RefClock: 14.31818 MHz */ - /* formula: VClk = (OSC * N) / (D * (1+P)) */ - /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ - - WSeq(SEQRB, _par->nom); - tmp = _par->den<<1; - if (_par->div != 0) tmp |= 1; - - if (fb_info->btype == BT_SD64) - tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ - - WSeq(SEQR1B, tmp); - - WCrt(CRT17, 0xc3); /* mode control: CRTC enable, ROTATE(?), 16bit address wrap, no compat. */ - -/* HAEH? WCrt(CRT11, 0x20); * previously: 0x00 unlock CRT0..CRT7 */ - - /* don't know if it would hurt to also program this if no interlaced */ - /* mode is used, but I feel better this way.. :-) */ - if (_par->var.vmode & FB_VMODE_INTERLACED) - WCrt(CRT19, _par->HorizTotal / 2); - else - WCrt(CRT19, 0x00); /* interlace control */ - - WSeq(SEQR3, 0); - - /* adjust horizontal/vertical sync type (low/high) */ - tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */ - if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT) tmp |= 0x40; - if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) tmp |= 0x80; - WGen(MISC_W, tmp); - - WCrt(CRT8, 0); /* Screen A Preset Row-Scan register */ - WCrt(CRTA, 0); /* text cursor on and start line */ - WCrt(CRTB, 31); /* text cursor end line */ - - /* programming for different color depths */ - if (_par->var.bits_per_pixel == 1) - { - DEBUG printk(KERN_INFO "clgen: preparing for 1 bit deep display\n"); -#if 0 - /* restore first 2 color registers for mono mode */ - WClut( 0, 0x00, 0x00, 0x00); /* background: black */ - WClut( 1, 0x3f, 0x3f, 0x3f); /* foreground: white */ -#endif - WGfx(GR5, 0); /* mode register */ - - /* Extended Sequencer Mode */ - switch(fb_info->btype) - { - case BT_SD64: - /* setting the SEQRF on SD64 is not necessary (only during init) */ - DEBUG printk(KERN_INFO "(for SD64)\n"); - WSeq(SEQR7, 0xf0); - WSeq(SEQR1F, 0x1a); /* MCLK select */ - break; + unsigned char tmp; + int offset = 0; + struct clgenfb_par *_par = (struct clgenfb_par *) par; + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; + const struct clgen_board_info_rec *bi; + + DPRINTK ("ENTER\n"); + DPRINTK ("Requested mode: %dx%dx%d\n", + _par->var.xres, _par->var.yres, _par->var.bits_per_pixel); + DPRINTK ("pixclock: %d\n", _par->var.pixclock); + + bi = &clgen_board_info[fb_info->btype]; + + + /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ + vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ + + /* if debugging is enabled, all parameters get output before writing */ + DPRINTK ("CRT0: %ld\n", _par->HorizTotal); + vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal); + + DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd); + vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd); + + DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart); + vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart); + + DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /* + 128: Compatible read */ + vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32)); + + DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart); + vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart); + + tmp = _par->HorizSyncEnd % 32; + if (_par->HorizBlankEnd & 32) + tmp += 128; + DPRINTK ("CRT5: %d\n", tmp); + vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp); + + DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff); + vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff)); + + tmp = 16; /* LineCompare bit #9 */ + if (_par->VertTotal & 256) + tmp |= 1; + if (_par->VertDispEnd & 256) + tmp |= 2; + if (_par->VertSyncStart & 256) + tmp |= 4; + if (_par->VertBlankStart & 256) + tmp |= 8; + if (_par->VertTotal & 512) + tmp |= 32; + if (_par->VertDispEnd & 512) + tmp |= 64; + if (_par->VertSyncStart & 512) + tmp |= 128; + DPRINTK ("CRT7: %d\n", tmp); + vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp); + + tmp = 0x40; /* LineCompare bit #8 */ + if (_par->VertBlankStart & 512) + tmp |= 0x20; + if (_par->var.vmode & FB_VMODE_DOUBLE) + tmp |= 0x80; + DPRINTK ("CRT9: %d\n", tmp); + vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp); + + DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff); + vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff)); + + DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16); + vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32)); + + DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff); + vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff)); + + DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff); + vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff)); + + DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff); + vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff)); + + DPRINTK ("CRT18: 0xff\n"); + vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff); + + tmp = 0; + if (_par->var.vmode & FB_VMODE_INTERLACED) + tmp |= 1; + if (_par->HorizBlankEnd & 64) + tmp |= 16; + if (_par->HorizBlankEnd & 128) + tmp |= 32; + if (_par->VertBlankEnd & 256) + tmp |= 64; + if (_par->VertBlankEnd & 512) + tmp |= 128; + + DPRINTK ("CRT1a: %d\n", tmp); + vga_wcrt (fb_info->regs, CL_CRT1A, tmp); + + /* set VCLK0 */ + /* hardware RefClock: 14.31818 MHz */ + /* formula: VClk = (OSC * N) / (D * (1+P)) */ + /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ + + vga_wseq (fb_info->regs, CL_SEQRB, _par->nom); + tmp = _par->den << 1; + if (_par->div != 0) + tmp |= 1; + + if ((fb_info->btype == BT_SD64) || + (fb_info->btype == BT_ALPINE) || + (fb_info->btype == BT_GD5480)) + tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ + + DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp); + vga_wseq (fb_info->regs, CL_SEQR1B, tmp); + + if (_par->VertRes >= 1024) + /* 1280x1024 */ + vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7); + else + /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit + * address wrap, no compat. */ + vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); - case BT_PICCOLO: - DEBUG printk(KERN_INFO "(for Piccolo)\n"); - WSeq(SEQR7, 0x80); -/* ### ueberall 0x22? */ - WSeq(SEQR1F, 0x22); /* ##vorher 1c MCLK select */ - WSeq(SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ - break; +/* HAEH? vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20); * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */ - case BT_PICASSO: - DEBUG printk(KERN_INFO "(for Picasso)\n"); - WSeq(SEQR7, 0x20); - WSeq(SEQR1F, 0x22); /* ##vorher 22 MCLK select */ - WSeq(SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */ - break; + /* don't know if it would hurt to also program this if no interlaced */ + /* mode is used, but I feel better this way.. :-) */ + if (_par->var.vmode & FB_VMODE_INTERLACED) + vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2); + else + vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00); /* interlace control */ + + vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0); + + /* adjust horizontal/vertical sync type (low/high) */ + tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */ + if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT) + tmp |= 0x40; + if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) + tmp |= 0x80; + WGen (fb_info, VGA_MIS_W, tmp); + + vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0); /* Screen A Preset Row-Scan register */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0); /* text cursor on and start line */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31); /* text cursor end line */ + + /****************************************************** + * + * 1 bpp + * + */ + + /* programming for different color depths */ + if (_par->var.bits_per_pixel == 1) { + DPRINTK ("clgen: preparing for 1 bit deep display\n"); + vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0); /* mode register */ + + /* SR07 */ + switch (fb_info->btype) { + case BT_SD64: + case BT_PICCOLO: + case BT_PICASSO: + case BT_SPECTRUM: + case BT_PICASSO4: + case BT_ALPINE: + case BT_GD5480: + DPRINTK (" (for GD54xx)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + _par->multiplexing ? + bi->sr07_1bpp_mux : bi->sr07_1bpp); + break; + + case BT_LAGUNA: + DPRINTK (" (for GD546x)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); + break; + + default: + printk (KERN_WARNING "clgen: unknown Board\n"); + break; + } - case BT_SPECTRUM: - DEBUG printk(KERN_INFO "(for Spectrum)\n"); - WSeq(SEQR7, 0x80); + /* Extended Sequencer Mode */ + switch (fb_info->btype) { + case BT_SD64: + /* setting the SEQRF on SD64 is not necessary (only during init) */ + DPRINTK ("(for SD64)\n"); + vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a); /* MCLK select */ + break; + + case BT_PICCOLO: + DPRINTK ("(for Piccolo)\n"); +/* ### ueberall 0x22? */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ + break; + + case BT_PICASSO: + DPRINTK ("(for Picasso)\n"); + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 22 MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */ + break; + + case BT_SPECTRUM: + DPRINTK ("(for Spectrum)\n"); /* ### ueberall 0x22? */ - WSeq(SEQR1F, 0x22); /* ##vorher 1c MCLK select */ - WSeq(SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */ - break; + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ##vorher 1c MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */ + break; + + case BT_PICASSO4: + case BT_ALPINE: + case BT_GD5480: + case BT_LAGUNA: + DPRINTK (" (for GD54xx)\n"); + /* do nothing */ + break; + + default: + printk (KERN_WARNING "clgen: unknown Board\n"); + break; + } - case BT_PICASSO4: - DEBUG printk(KERN_INFO "(for Picasso 4)\n"); - WSeq(SEQR7, 0x20); -/* WSeq(SEQR1F, 0x1c); */ -/* SEQRF not being set here... WSeq(SEQRF, 0xd0); */ - break; + WGen (fb_info, VGA_PEL_MSK, 0x01); /* pixel mask: pass-through for first plane */ + if (_par->multiplexing) + WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */ + else + WHDR (fb_info, 0); /* hidden dac: nothing */ + vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06); /* memory mode: odd/even, ext. memory */ + vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01); /* plane mask: only write to first plane */ + offset = _par->var.xres_virtual / 16; + } + + /****************************************************** + * + * 8 bpp + * + */ + + else if (_par->var.bits_per_pixel == 8) { + DPRINTK ("clgen: preparing for 8 bit deep display\n"); + switch (fb_info->btype) { + case BT_SD64: + case BT_PICCOLO: + case BT_PICASSO: + case BT_SPECTRUM: + case BT_PICASSO4: + case BT_ALPINE: + case BT_GD5480: + DPRINTK (" (for GD54xx)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + _par->multiplexing ? + bi->sr07_8bpp_mux : bi->sr07_8bpp); + break; + + case BT_LAGUNA: + DPRINTK (" (for GD546x)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + vga_rseq (fb_info->regs, CL_SEQR7) | 0x01); + break; + + default: + printk (KERN_WARNING "clgen: unknown Board\n"); + break; + } - default: - printk(KERN_WARNING "clgen: unknown Board\n"); - break; - } - - WGen(M_3C6,0x01); /* pixel mask: pass-through for first plane */ - WHDR(0); /* hidden dac reg: nothing special */ - WSeq(SEQR4, 0x06); /* memory mode: odd/even, ext. memory */ - WSeq(SEQR2, 0x01); /* plane mask: only write to first plane */ - offset = _par->var.xres_virtual / 16; - } - else if (_par->var.bits_per_pixel == 8) - { - DEBUG printk(KERN_INFO "clgen: preparing for 8 bit deep display\n"); - switch(fb_info->btype) - { - case BT_SD64: - WSeq(SEQR7, 0xf1); /* Extended Sequencer Mode: 256c col. mode */ - WSeq(SEQR1F, 0x1d); /* MCLK select */ - break; + switch (fb_info->btype) { + case BT_SD64: + vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d); /* MCLK select */ + break; + + case BT_PICCOLO: + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_PICASSO: + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_SPECTRUM: + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_PICASSO4: + vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); /* ### INCOMPLETE!! */ +/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ + break; + + case BT_ALPINE: + DPRINTK (" (for GD543x)\n"); + clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); + /* We already set SRF and SR1F */ + break; + + case BT_GD5480: + case BT_LAGUNA: + DPRINTK (" (for GD54xx)\n"); + /* do nothing */ + break; + + default: + printk (KERN_WARNING "clgen: unknown Board\n"); + break; + } - case BT_PICCOLO: - WSeq(SEQR7, 0x81); - WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - break; + vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ + WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ + if (_par->multiplexing) + WHDR (fb_info, 0x4a); /* hidden dac reg: 1280x1024 */ + else + WHDR (fb_info, 0); /* hidden dac: nothing */ + vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ + vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 8; + } + + /****************************************************** + * + * 16 bpp + * + */ + + else if (_par->var.bits_per_pixel == 16) { + DPRINTK ("clgen: preparing for 16 bit deep display\n"); + switch (fb_info->btype) { + case BT_SD64: + vga_wseq (fb_info->regs, CL_SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */ + break; + + case BT_PICCOLO: + vga_wseq (fb_info->regs, CL_SEQR7, 0x87); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO: + vga_wseq (fb_info->regs, CL_SEQR7, 0x27); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_SPECTRUM: + vga_wseq (fb_info->regs, CL_SEQR7, 0x87); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO4: + vga_wseq (fb_info->regs, CL_SEQR7, 0x27); +/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ + break; + + case BT_ALPINE: + DPRINTK (" (for GD543x)\n"); + if (_par->HorizRes >= 1024) + vga_wseq (fb_info->regs, CL_SEQR7, 0xa7); + else + vga_wseq (fb_info->regs, CL_SEQR7, 0xa3); + clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); + break; + + case BT_GD5480: + DPRINTK (" (for GD5480)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, 0x17); + /* We already set SRF and SR1F */ + break; + + case BT_LAGUNA: + DPRINTK (" (for GD546x)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); + break; + + default: + printk (KERN_WARNING "CLGEN: unknown Board\n"); + break; + } - case BT_PICASSO: - WSeq(SEQR7, 0x21); - WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - break; + vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ + WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ +#ifdef CONFIG_PCI + WHDR (fb_info, 0xc0); /* Copy Xbh */ +#elif CONFIG_ZORRO + WHDR (fb_info, 0xa0); /* hidden dac reg: nothing special */ +#endif + vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ + vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 4; + } + + /****************************************************** + * + * 32 bpp + * + */ + + else if (_par->var.bits_per_pixel == 32) { + DPRINTK ("clgen: preparing for 24/32 bit deep display\n"); + switch (fb_info->btype) { + case BT_SD64: + vga_wseq (fb_info->regs, CL_SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e); /* MCLK select */ + break; + + case BT_PICCOLO: + vga_wseq (fb_info->regs, CL_SEQR7, 0x85); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO: + vga_wseq (fb_info->regs, CL_SEQR7, 0x25); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_SPECTRUM: + vga_wseq (fb_info->regs, CL_SEQR7, 0x85); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); /* Fast Page-Mode writes */ + vga_wseq (fb_info->regs, CL_SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO4: + vga_wseq (fb_info->regs, CL_SEQR7, 0x25); +/* vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */ + break; + + case BT_ALPINE: + DPRINTK (" (for GD543x)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, 0xa9); + clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK); + break; + + case BT_GD5480: + DPRINTK (" (for GD5480)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, 0x19); + /* We already set SRF and SR1F */ + break; + + case BT_LAGUNA: + DPRINTK (" (for GD546x)\n"); + vga_wseq (fb_info->regs, CL_SEQR7, + vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01); + break; + + default: + printk (KERN_WARNING "clgen: unknown Board\n"); + break; + } - case BT_SPECTRUM: - WSeq(SEQR7, 0x81); - WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - break; + vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64); /* mode register: 256 color mode */ + WGen (fb_info, VGA_PEL_MSK, 0xff); /* pixel mask: pass-through all planes */ + WHDR (fb_info, 0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */ + vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a); /* memory mode: chain4, ext. memory */ + vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 4; + } + + /****************************************************** + * + * unknown/unsupported bpp + * + */ + + else { + printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n", + _par->var.bits_per_pixel); + } + + vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff); + tmp = 0x22; + if (offset & 0x100) + tmp |= 0x10; /* offset overflow bit */ + + vga_wcrt (fb_info->regs, CL_CRT1B, tmp); /* screen start addr #16-18, fastpagemode cycles */ + + if (fb_info->btype == BT_SD64 || + fb_info->btype == BT_PICASSO4 || + fb_info->btype == BT_ALPINE || + fb_info->btype == BT_GD5480) + vga_wcrt (fb_info->regs, CL_CRT1D, 0x00); /* screen start address bit 19 */ + + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0); /* text cursor location high */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0); /* text cursor location low */ + vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0); /* underline row scanline = at very bottom */ + + vga_wattr (fb_info->regs, VGA_ATC_MODE, 1); /* controller mode */ + vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0); /* overscan (border) color */ + vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15); /* color plane enable */ + vga_wattr (fb_info->regs, CL_AR33, 0); /* pixel panning */ + vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0); /* color select */ + + /* [ EGS: SetOffset(); ] */ + /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ + AttrOn (fb_info); + + vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0); /* set/reset register */ + vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0); /* set/reset enable */ + vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0); /* color compare */ + vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0); /* data rotate */ + vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0); /* read map select */ + vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1); /* miscellaneous register */ + vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15); /* color don't care */ + vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255); /* bit mask */ + + vga_wseq (fb_info->regs, CL_SEQR12, 0x0); /* graphics cursor attributes: nothing special */ + + /* finally, turn on everything - turn off "FullBandwidth" bit */ + /* also, set "DotClock%2" bit where requested */ + tmp = 0x01; - case BT_PICASSO4: - WSeq(SEQR7, 0x21); - WSeq(SEQRF, 0xb8); /* ### INCOMPLETE!! */ -/* WSeq(SEQR1F, 0x1c); */ - break; +/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? + if (var->vmode & FB_VMODE_CLOCK_HALVE) + tmp |= 0x08; +*/ - default: - printk(KERN_WARNING "clgen: unknown Board\n"); - break; - } - - WGfx(GR5, 64); /* mode register: 256 color mode */ - WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ - WHDR(0); /* hidden dac reg: nothing special */ - WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ - WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ - offset = _par->var.xres_virtual / 8; - } - else if (_par->var.bits_per_pixel == 16) - { - DEBUG printk(KERN_INFO "clgen: preparing for 16 bit deep display\n"); - switch(fb_info->btype) - { - case BT_SD64: - WSeq(SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */ - WSeq(SEQR1F, 0x1e); /* MCLK select */ - break; + vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp); + DPRINTK ("CL_SEQR1: %d\n", tmp); - case BT_PICCOLO: - WSeq(SEQR7, 0x87); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; + fb_info->currentmode = *_par; - case BT_PICASSO: - WSeq(SEQR7, 0x27); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; + DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset); + /* pan to requested offset */ + clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info); - case BT_SPECTRUM: - WSeq(SEQR7, 0x87); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; +#ifdef CLGEN_DEBUG + clgen_dump (); +#endif - case BT_PICASSO4: - WSeq(SEQR7, 0x27); -/* WSeq(SEQR1F, 0x1c); */ - break; + DPRINTK ("EXIT\n"); + return; +} - default: - printk(KERN_WARNING "CLGEN: unknown Board\n"); - break; - } - - WGfx(GR5, 64); /* mode register: 256 color mode */ - WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ - WHDR(0xa0); /* hidden dac reg: nothing special */ - WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ - WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ - offset = _par->var.xres_virtual / 4; - } - else if (_par->var.bits_per_pixel == 32) - { - DEBUG printk(KERN_INFO "clgen: preparing for 24/32 bit deep display\n"); - switch(fb_info->btype) - { - case BT_SD64: - WSeq(SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */ - WSeq(SEQR1F, 0x1e); /* MCLK select */ - break; - case BT_PICCOLO: - WSeq(SEQR7, 0x85); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; +static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info) +{ + struct clgenfb_info *fb_info = (struct clgenfb_info *)info; - case BT_PICASSO: - WSeq(SEQR7, 0x25); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; + if (regno > 255) + return 1; + *red = fb_info->palette[regno].red; + *green = fb_info->palette[regno].green; + *blue = fb_info->palette[regno].blue; + *transp = 0; + return 0; +} - case BT_SPECTRUM: - WSeq(SEQR7, 0x85); - WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ - WSeq(SEQR1F, 0x22); /* MCLK select */ - break; - case BT_PICASSO4: - WSeq(SEQR7, 0x25); -/* WSeq(SEQR1F, 0x1c); */ - break; +static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; + + if (regno > 255) + return -EINVAL; +#ifdef FBCON_HAS_CFB8 + switch (fb_info->currentmode.var.bits_per_pixel) { + case 8: + /* "transparent" stuff is completely ignored. */ + WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10); + break; default: - printk(KERN_WARNING "clgen: unknown Board\n"); - break; - } - - WGfx(GR5, 64); /* mode register: 256 color mode */ - WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ - WHDR(0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */ - WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ - WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ - offset = _par->var.xres_virtual / 4; - } - else - printk(KERN_ERR "clgen: What's this?? requested color depth == %d.\n", - _par->var.bits_per_pixel); - - WCrt(CRT13, offset & 0xff); - tmp = 0x22; - if (offset & 0x100) tmp |= 0x10; /* offset overflow bit */ - - WCrt(CRT1B,tmp); /* screen start addr #16-18, fastpagemode cycles */ - - if (fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4) - WCrt(CRT1D, 0x00); /* screen start address bit 19 */ - - WCrt(CRTE, 0); /* text cursor location high */ - WCrt(CRTF, 0); /* text cursor location low */ - WCrt(CRT14, 0); /* underline row scanline = at very bottom */ - - WAttr(AR10, 1); /* controller mode */ - WAttr(AR11, 0); /* overscan (border) color */ - WAttr(AR12, 15); /* color plane enable */ - WAttr(AR33, 0); /* pixel panning */ - WAttr(AR14, 0); /* color select */ - - /* [ EGS: SetOffset(); ] */ - /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ - AttrOn(); - - WGfx(GR0, 0); /* set/reset register */ - WGfx(GR1, 0); /* set/reset enable */ - WGfx(GR2, 0); /* color compare */ - WGfx(GR3, 0); /* data rotate */ - WGfx(GR4, 0); /* read map select */ - WGfx(GR6, 1); /* miscellaneous register */ - WGfx(GR7, 15); /* color don't care */ - WGfx(GR8, 255); /* bit mask */ - - WSeq(SEQR12, 0x0); /* graphics cursor attributes: nothing special */ - - /* finally, turn on everything - turn off "FullBandwidth" bit */ - /* also, set "DotClock%2" bit where requested */ - tmp = 0x01; + /* do nothing */ + break; + } +#endif /* FBCON_HAS_CFB8 */ -/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? - if (var->vmode & FB_VMODE_CLOCK_HALVE) - tmp |= 0x08; -*/ + fb_info->palette[regno].red = red; + fb_info->palette[regno].green = green; + fb_info->palette[regno].blue = blue; - WSeq(SEQR1, tmp); - DEBUG printk("SEQR1: %d\n", tmp); + if (regno >= 16) + return 0; + + switch (fb_info->currentmode.var.bits_per_pixel) { -#if 0 - DEBUG printk(KERN_INFO "clgen: clearing display..."); - clgen_RectFill(0, 0, _par->HorizRes, _par->VertRes, 0, _par->line_length); - clgen_WaitBLT(); - DEBUG printk("done.\n"); +#ifdef FBCON_HAS_CFB16 + case 16: + assert (regno < 16); +#ifdef CONFIG_PREP + fb_info->fbcon_cmap.cfb16[regno] = + ((red & 0xf800) >> 9) | + ((green & 0xf800) >> 14) | + ((green & 0xf800) << 2) | + ((blue & 0xf800) >> 3); +#else + fb_info->fbcon_cmap.cfb16[regno] = + ((red & 0xf800) >> 1) | + ((green & 0xf800) >> 6) | + ((blue & 0xf800) >> 11); #endif +#endif /* FBCON_HAS_CFB16 */ - fb_info->currentmode = *_par; +#ifdef FBCON_HAS_CFB24 + case 24: + assert (regno < 16); + fb_info->fbcon_cmap.cfb24[regno] = + (red << fb_info->currentmode.var.red.offset) | + (green << fb_info->currentmode.var.green.offset) | + (blue << fb_info->currentmode.var.blue.offset); + break; +#endif /* FBCON_HAS_CFB24 */ - printk("virtual offset: (%d,%d)\n", _par->var.xoffset,_par->var.yoffset); - /* pan to requested offset */ - clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen*)fb_info); +#ifdef FBCON_HAS_CFB32 + case 32: + assert (regno < 16); +#ifdef CONFIG_PREP + fb_info->fbcon_cmap.cfb32[regno] = + ((red & 0xff00)) | + ((green & 0xff00) << 8) | + ((blue & 0xff00) << 16); +#else + fb_info->fbcon_cmap.cfb32[regno] = + ((red & 0xff00) << 8) | + ((green & 0xff00)) | + ((blue & 0xff00) >> 8); +#endif + break; +#endif /* FBCON_HAS_CFB32 */ + default: + /* do nothing */ + break; + } - DEBUG printk("<clgen_set_par()\n"); - return; + return 0; } -static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green, - unsigned *blue, unsigned *transp, - struct fb_info *info) +/************************************************************************* + clgen_pan_display() + + performs display panning - provided hardware permits this +**************************************************************************/ +static int clgen_pan_display (const struct fb_var_screeninfo *var, + struct fb_info_gen *info) { - unsigned char bred, bgreen, bblue; + int xoffset = 0; + int yoffset = 0; + unsigned long base; + unsigned char tmp = 0, tmp2 = 0, xpix; + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; - if (regno > 255) - return (1); + DPRINTK ("ENTER\n"); - fb_info = (struct clgenfb_info *)info; + /* no range checks for xoffset and yoffset, */ + /* as fbgen_pan_display has already done this */ - RClut(regno, &bred, &bgreen, &bblue); + fb_info->currentmode.var.xoffset = var->xoffset; + fb_info->currentmode.var.yoffset = var->yoffset; - *red = (bred<<10) | (bred<<4) | (bred>>2); - *green = (bgreen<<10) | (bgreen<<4) | (bgreen>>2); - *blue = (bblue<<10) | (bblue<<4) | (bblue>>2); - *transp = 0; - return (0); -} + xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8; + yoffset = var->yoffset; -static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - if (regno > 255) - return (1); + base = yoffset * fb_info->currentmode.line_length + xoffset; - fb_info = (struct clgenfb_info *)info; - - /* "transparent" stuff is completely ignored. */ - WClut(regno, red>>10, green>>10, blue>>10); + if (fb_info->currentmode.var.bits_per_pixel == 1) { + /* base is already correct */ + xpix = (unsigned char) (var->xoffset % 8); + } else { + base /= 4; + xpix = (unsigned char) ((xoffset % 4) * 2); + } - return (0); -} + /* lower 8 + 8 bits of screen start address */ + vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff)); + vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8)); + + /* construct bits 16, 17 and 18 of screen start address */ + if (base & 0x10000) + tmp |= 0x01; + if (base & 0x20000) + tmp |= 0x04; + if (base & 0x40000) + tmp |= 0x08; + + tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */ + vga_wcrt (fb_info->regs, CL_CRT1B, tmp2); + + /* construct bit 19 of screen start address */ + if (clgen_board_info[fb_info->btype].scrn_start_bit19) { + tmp2 = 0; + if (base & 0x80000) + tmp2 = 0x80; + vga_wcrt (fb_info->regs, CL_CRT1D, tmp2); + } -/************************************************************************* - clgen_pan_display() + /* write pixel panning value to AR33; this does not quite work in 8bpp */ + /* ### Piccolo..? Will this work? */ + if (fb_info->currentmode.var.bits_per_pixel == 1) + vga_wattr (fb_info->regs, CL_AR33, xpix); - performs display panning - provided hardware permits this -**************************************************************************/ -static int clgen_pan_display(const struct fb_var_screeninfo *var, - struct fb_info_gen *info) -{ - int xoffset = 0; - int yoffset = 0; - unsigned long base; - unsigned char tmp = 0, tmp2 = 0, xpix; - - fb_info = (struct clgenfb_info*)fb_info; - - /* no range checks for xoffset and yoffset, */ - /* as fbgen_pan_display has already done this */ - - fb_info->currentmode.var.xoffset = var->xoffset; - fb_info->currentmode.var.yoffset = var->yoffset; - - xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8; - yoffset = var->yoffset; - - base = yoffset * fb_info->currentmode.line_length + xoffset; - - if (fb_info->currentmode.var.bits_per_pixel == 1) - { - /* base is already correct */ - xpix = (unsigned char)(var->xoffset % 8); - } - else - { - base /= 4; - xpix = (unsigned char)((xoffset % 4) * 2); - } - - /* lower 8 + 8 bits of screen start address */ - WCrt(CRTD, (unsigned char)(base & 0xff)); - WCrt(CRTC, (unsigned char)(base >> 8)); - - /* construct bits 16, 17 and 18 of screen start address */ - if (base & 0x10000) tmp |= 0x01; - if (base & 0x20000) tmp |= 0x04; - if (base & 0x40000) tmp |= 0x08; - - tmp2 = (RCrt(CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */ - WCrt(CRT1B, tmp2); - /* construct bit 19 of screen start address (only on SD64) */ - if (fb_info->btype == BT_SD64 || - fb_info->btype == BT_PICASSO4) - { - tmp2 = 0; - if (base & 0x80000) tmp2 = 0x80; - WCrt(CRT1D, tmp2); - } - - /* write pixel panning value to AR33; this does not quite work in 8bpp */ - /* ### Piccolo..? Will this work? */ - if (fb_info->currentmode.var.bits_per_pixel == 1) - WAttr(AR33, xpix); - - return(0); + + DPRINTK ("EXIT\n"); + return (0); } -static int clgen_blank(int blank_mode, struct fb_info_gen *info) +static int clgen_blank (int blank_mode, struct fb_info_gen *info) { - unsigned char val; - printk(">clgen_blank(%d)\n",blank_mode); + /* + * Blank the screen if blank_mode != 0, else unblank. If blank == NULL + * then the caller blanks by setting the CLUT (Color Look Up Table) to all + * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due + * to e.g. a video mode which doesn't support it. Implements VESA suspend + * and powerdown modes on hardware that supports disabling hsync/vsync: + * blank_mode == 2: suspend vsync + * blank_mode == 3: suspend hsync + * blank_mode == 4: powerdown + */ + unsigned char val; + static int current_mode = 0; + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; + + DPRINTK ("ENTER, blank mode = %d\n", blank_mode); + + if (current_mode == blank_mode) { + DPRINTK ("EXIT, returning 0\n"); + return 0; + } - fb_info = (struct clgenfb_info *)info; + /* Undo current */ + switch (current_mode) { + case 0: /* Screen is normal */ + break; + case 1: /* Screen is blanked */ + val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE); + vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf); /* clear "FullBandwidth" bit */ + break; + case 2: /* vsync suspended */ + case 3: /* hsync suspended */ + case 4: /* sceen is powered down */ + vga_wgfx (fb_info->regs, CL_GRE, 0x00); + break; + default: + DPRINTK ("EXIT, returning 1\n"); + return 1; + } - val = RSeq(SEQR1); - if (blank_mode) - WSeq(SEQR1, val | 0x20); /* set "FullBandwidth" bit */ - else - WSeq(SEQR1, val & 0xdf); /* clear "FullBandwidth" bit */ + /* set new */ + switch (blank_mode) { + case 0: /* Unblank screen */ + break; + case 1: /* Blank screen */ + val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE); + vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20); /* set "FullBandwidth" bit */ + break; + case 2: /* suspend vsync */ + vga_wgfx (fb_info->regs, CL_GRE, 0x04); + break; + case 3: /* suspend hsync */ + vga_wgfx (fb_info->regs, CL_GRE, 0x02); + break; + case 4: /* powerdown */ + vga_wgfx (fb_info->regs, CL_GRE, 0x06); + break; + default: + DPRINTK ("EXIT, returning 1\n"); + return 1; + } - printk("<clgen_blank()\n"); - return 0; + current_mode = blank_mode; + DPRINTK ("EXIT, returning 0\n"); + return 0; } - /**** END Hardware specific Routines **************************************/ /****************************************************************************/ /**** BEGIN Internal Routines ***********************************************/ -static void init_vgachip(void) +static void __init init_vgachip (struct clgenfb_info *fb_info) { - printk(">init_vgachip()\n"); - - /* reset board globally */ - switch(fb_info->btype) - { - case BT_SD64: WSFR(0x1f); udelay(500); WSFR(0x4f); udelay(500); break; - case BT_PICCOLO: WSFR(0x01); udelay(500); WSFR(0x51); udelay(500); break; - case BT_PICASSO: WSFR2(0xff); udelay(500); break; - case BT_SPECTRUM: WSFR(0x1f); udelay(500); WSFR(0x4f); udelay(500); break; - case BT_PICASSO4: - WCrt(CRT51, 0x00); /* disable flickerfixer */ - udelay(100000); - WGfx(GR2F, 0x00); /* from Klaus' NetBSD driver: */ - WGfx(GR33, 0x00); /* put blitter into 542x compat */ - WGfx(GR31, 0x00); /* mode */ - break; - - default: - printk(KERN_ERR "clgen: Warning: Unknown board type\n"); - break; - } - - /* "pre-set" a RAMsize; if the test succeeds, double it */ - if (fb_info->btype == BT_SD64 || - fb_info->btype == BT_PICASSO4) - fb_info->size = 0x400000; - else - fb_info->size = 0x200000; - - /* assume it's a "large memory" board (2/4 MB) */ - fb_info->smallboard = FALSE; - - /* the P4 is not fully initialized here; I rely on it having been */ - /* inited under AmigaOS already, which seems to work just fine */ - /* (Klaus advised to do it this way) */ - - if (fb_info->btype != BT_PICASSO4) - { - WGen(VSSM, 0x10); /* EGS: 0x16 */ - WGen(POS102, 0x01); - WGen(VSSM, 0x08); /* EGS: 0x0e */ - - if(fb_info->btype != BT_SD64) - WGen(VSSM2, 0x01); - - WSeq(SEQR0, 0x03); /* reset sequencer logic */ - - WSeq(SEQR1, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */ - WGen(MISC_W, 0xc1); /* polarity (-/-), disable access to display memory, CRTC base address: color */ - -/* WGfx(GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */ - WSeq(SEQR6, 0x12); /* unlock all extension registers */ - - WGfx(GR31, 0x04); /* reset blitter */ - - if (fb_info->btype == BT_SD64) - { - WSeq(SEQRF, 0xb8); /* 4 MB Ram SD64, disable CRT fifo(!), 64 bit bus */ + const struct clgen_board_info_rec *bi; + + DPRINTK ("ENTER\n"); + + assert (fb_info != NULL); + + bi = &clgen_board_info[fb_info->btype]; + + /* reset board globally */ + switch (fb_info->btype) { + case BT_PICCOLO: + WSFR (fb_info, 0x01); + udelay (500); + WSFR (fb_info, 0x51); + udelay (500); + break; + case BT_PICASSO: + WSFR2 (fb_info, 0xff); + udelay (500); + break; + case BT_SD64: + case BT_SPECTRUM: + WSFR (fb_info, 0x1f); + udelay (500); + WSFR (fb_info, 0x4f); + udelay (500); + break; + case BT_PICASSO4: + vga_wcrt (fb_info->regs, CL_CRT51, 0x00); /* disable flickerfixer */ + udelay (100000); + vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ + vga_wgfx (fb_info->regs, CL_GR33, 0x00); /* put blitter into 542x compat */ + vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* mode */ + break; + + case BT_GD5480: + vga_wgfx (fb_info->regs, CL_GR2F, 0x00); /* from Klaus' NetBSD driver: */ + break; + + case BT_ALPINE: + /* Nothing to do to reset the board. */ + break; + + default: + printk (KERN_ERR "clgen: Warning: Unknown board type\n"); + break; } + +#ifdef CLGEN_USE_HARDCODED_RAM_SETTINGS + /* "pre-set" a RAMsize; if the test succeeds, double it */ + if (fb_info->btype == BT_SD64 || + fb_info->btype == BT_PICASSO4) + fb_info->size = 0x400000; else - { - WSeq(SEQR16, 0x0f); /* Perf. Tuning: Fix value..(?) */ - WSeq(SEQRF, 0xb0); /* 2 MB DRAM, 8level write buffer, 32bit bus */ - } - } - - WSeq(SEQR2, 0xff); /* plane mask: nothing */ - WSeq(SEQR3, 0x00); /* character map select: doesn't even matter in gx mode */ - WSeq(SEQR4, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */ - - /* controller-internal base address of video memory */ - switch(fb_info->btype) - { - case BT_SD64: WSeq(SEQR7, 0xf0); break; - case BT_PICCOLO: WSeq(SEQR7, 0x80); break; - case BT_SPECTRUM: WSeq(SEQR7, 0x80); break; - case BT_PICASSO: WSeq(SEQR7, 0x20); break; - case BT_PICASSO4: WSeq(SEQR7, 0x20); break; - } - -/* WSeq(SEQR8, 0x00);*/ /* EEPROM control: shouldn't be necessary to write to this at all.. */ - - WSeq(SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */ - WSeq(SEQR11, 0x00); /* graphics cursor Y position (..."... ) */ - WSeq(SEQR12, 0x00); /* graphics cursor attributes */ - WSeq(SEQR13, 0x00); /* graphics cursor pattern address */ - - /* writing these on a P4 might give problems.. */ - if (fb_info->btype != BT_PICASSO4) - { - WSeq(SEQR17, 0x00); /* configuration readback and ext. color */ - WSeq(SEQR18, 0x02); /* signature generator */ - } - - /* MCLK select etc. */ - switch(fb_info->btype) - { - case BT_PICCOLO: - case BT_PICASSO: - case BT_SPECTRUM: WSeq(SEQR1F, 0x22); break; - case BT_SD64: WSeq(SEQR1F, 0x20); break; - case BT_PICASSO4:/*WSeq(SEQR1F, 0x1c); */ break; - } - - WCrt(CRT8, 0x00); /* Screen A preset row scan: none */ - WCrt(CRTA, 0x20); /* Text cursor start: disable text cursor */ - WCrt(CRTB, 0x00); /* Text cursor end: - */ - WCrt(CRTC, 0x00); /* Screen start address high: 0 */ - WCrt(CRTD, 0x00); /* Screen start address low: 0 */ - WCrt(CRTE, 0x00); /* text cursor location high: 0 */ - WCrt(CRTF, 0x00); /* text cursor location low: 0 */ - - WCrt(CRT14, 0x00); /* Underline Row scanline: - */ - WCrt(CRT17, 0xc3); /* mode control: timing enable, byte mode, no compat modes */ - WCrt(CRT18, 0x00); /* Line Compare: not needed */ - /* ### add 0x40 for text modes with > 30 MHz pixclock */ - WCrt(CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */ - - WGfx(GR0, 0x00); /* Set/Reset registes: - */ - WGfx(GR1, 0x00); /* Set/Reset enable: - */ - WGfx(GR2, 0x00); /* Color Compare: - */ - WGfx(GR3, 0x00); /* Data Rotate: - */ - WGfx(GR4, 0x00); /* Read Map Select: - */ - WGfx(GR5, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ - WGfx(GR6, 0x01); /* Miscellaneous: memory map base address, graphics mode */ - WGfx(GR7, 0x0f); /* Color Don't care: involve all planes */ - WGfx(GR8, 0xff); /* Bit Mask: no mask at all */ - WGfx(GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */ - - WGfx(GRC, 0xff); /* Color Key compare: - */ - WGfx(GRD, 0x00); /* Color Key compare mask: - */ - WGfx(GRE, 0x00); /* Miscellaneous control: - */ -/* WGfx(GR10, 0x00);*/ /* Background color byte 1: - */ -/* WGfx(GR11, 0x00); */ - - WAttr(AR0, 0x00); /* Attribute Controller palette registers: "identity mapping" */ - WAttr(AR1, 0x01); - WAttr(AR2, 0x02); - WAttr(AR3, 0x03); - WAttr(AR4, 0x04); - WAttr(AR5, 0x05); - WAttr(AR6, 0x06); - WAttr(AR7, 0x07); - WAttr(AR8, 0x08); - WAttr(AR9, 0x09); - WAttr(ARA, 0x0a); - WAttr(ARB, 0x0b); - WAttr(ARC, 0x0c); - WAttr(ARD, 0x0d); - WAttr(ARE, 0x0e); - WAttr(ARF, 0x0f); - - WAttr(AR10, 0x01); /* Attribute Controller mode: graphics mode */ - WAttr(AR11, 0x00); /* Overscan color reg.: reg. 0 */ - WAttr(AR12, 0x0f); /* Color Plane enable: Enable all 4 planes */ -/* ### WAttr(AR33, 0x00); * Pixel Panning: - */ - WAttr(AR14, 0x00); /* Color Select: - */ - - WGen(M_3C6, 0xff); /* Pixel mask: no mask */ - - WGen(MISC_W, 0xc3); /* polarity (-/-), enable display mem, CRTC i/o base = color */ - - WGfx(GR31, 0x04); /* BLT Start/status: Blitter reset */ - WGfx(GR31, 0x00); /* - " - : "end-of-reset" */ - - /* CLUT setup */ - WClut( 0, 0x00, 0x00, 0x00); /* background: black */ - WClut( 1, 0x3f, 0x3f, 0x3f); /* foreground: white */ - WClut( 2, 0x00, 0x20, 0x00); - WClut( 3, 0x00, 0x20, 0x20); - WClut( 4, 0x20, 0x00, 0x00); - WClut( 5, 0x20, 0x00, 0x20); - WClut( 6, 0x20, 0x10, 0x00); - WClut( 7, 0x20, 0x20, 0x20); - WClut( 8, 0x10, 0x10, 0x10); - WClut( 9, 0x10, 0x10, 0x30); - WClut(10, 0x10, 0x30, 0x10); - WClut(11, 0x10, 0x30, 0x30); - WClut(12, 0x30, 0x10, 0x10); - WClut(13, 0x30, 0x10, 0x30); - WClut(14, 0x30, 0x30, 0x10); - WClut(15, 0x30, 0x30, 0x30); - - /* the rest a grey ramp */ - { - int i; + fb_info->size = 0x200000; +#else + assert (fb_info->size > 0); /* make sure RAM size set by this point */ +#endif - for (i = 16; i < 256; i++) - WClut(i, i>>2, i>>2, i>>2); - } + /* assume it's a "large memory" board (2/4 MB) */ + fb_info->smallboard = FALSE; + /* the P4 is not fully initialized here; I rely on it having been */ + /* inited under AmigaOS already, which seems to work just fine */ + /* (Klaus advised to do it this way) */ - /* misc... */ - WHDR(0); /* Hidden DAC register: - */ + if (fb_info->btype != BT_PICASSO4) { + WGen (fb_info, CL_VSSM, 0x10); /* EGS: 0x16 */ + WGen (fb_info, CL_POS102, 0x01); + WGen (fb_info, CL_VSSM, 0x08); /* EGS: 0x0e */ -#if 0 - /* check for 1/2 MB Piccolo/Picasso/Spectrum resp. 2/4 MB SD64 */ - /* DRAM register has already been pre-set for "large", so it is*/ - /* only modified if we find that this is a "small" version */ - { - unsigned volatile char *ram = fb_info->fbmem; - int i, flag = 0; + if (fb_info->btype != BT_SD64) + WGen (fb_info, CL_VSSM2, 0x01); - ram += (fb_info->size >> 1); + vga_wseq (fb_info->regs, CL_SEQR0, 0x03); /* reset sequencer logic */ - for (i = 0; i < 256; i++) - ram[i] = (unsigned char)i; + vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */ + WGen (fb_info, VGA_MIS_W, 0xc1); /* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */ - for (i = 0; i < 256; i++) - { - if (ram[i] != i) - flag = 1; +/* vga_wgfx (fb_info->regs, CL_GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */ + vga_wseq (fb_info->regs, CL_SEQR6, 0x12); /* unlock all extension registers */ + + vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* reset blitter */ + + switch (fb_info->btype) { + case BT_GD5480: + vga_wseq (fb_info->regs, CL_SEQRF, 0x98); + break; + case BT_ALPINE: + break; + case BT_SD64: + vga_wseq (fb_info->regs, CL_SEQRF, 0xb8); + break; + default: + vga_wseq (fb_info->regs, CL_SEQR16, 0x0f); + vga_wseq (fb_info->regs, CL_SEQRF, 0xb0); + break; + } } + vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff); /* plane mask: nothing */ + vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00); /* character map select: doesn't even matter in gx mode */ + vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */ - /* if the DRAM test failed, halve RAM value */ - if (flag) + /* controller-internal base address of video memory */ + if (bi->init_sr07) + vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07); + + /* vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */ + + vga_wseq (fb_info->regs, CL_SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */ + vga_wseq (fb_info->regs, CL_SEQR11, 0x00); /* graphics cursor Y position (..."... ) */ + vga_wseq (fb_info->regs, CL_SEQR12, 0x00); /* graphics cursor attributes */ + vga_wseq (fb_info->regs, CL_SEQR13, 0x00); /* graphics cursor pattern address */ + + /* writing these on a P4 might give problems.. */ + if (fb_info->btype != BT_PICASSO4) { + vga_wseq (fb_info->regs, CL_SEQR17, 0x00); /* configuration readback and ext. color */ + vga_wseq (fb_info->regs, CL_SEQR18, 0x02); /* signature generator */ + } + + /* MCLK select etc. */ + if (bi->init_sr1f) + vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f); + + vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00); /* Screen A preset row scan: none */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor start: disable text cursor */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00); /* Text cursor end: - */ + vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00); /* Screen start address high: 0 */ + vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00); /* Screen start address low: 0 */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location high: 0 */ + vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00); /* text cursor location low: 0 */ + + vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00); /* Underline Row scanline: - */ + vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3); /* mode control: timing enable, byte mode, no compat modes */ + vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00); /* Line Compare: not needed */ + /* ### add 0x40 for text modes with > 30 MHz pixclock */ + vga_wcrt (fb_info->regs, CL_CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */ + + vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00); /* Set/Reset registes: - */ + vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00); /* Set/Reset enable: - */ + vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00); /* Color Compare: - */ + vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00); /* Data Rotate: - */ + vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00); /* Read Map Select: - */ + vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ + vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01); /* Miscellaneous: memory map base address, graphics mode */ + vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f); /* Color Don't care: involve all planes */ + vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff); /* Bit Mask: no mask at all */ + if (fb_info->btype == BT_ALPINE) + vga_wgfx (fb_info->regs, CL_GRB, 0x20); /* (5434 can't have bit 3 set for bitblt) */ + else + vga_wgfx (fb_info->regs, CL_GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */ + + vga_wgfx (fb_info->regs, CL_GRC, 0xff); /* Color Key compare: - */ + vga_wgfx (fb_info->regs, CL_GRD, 0x00); /* Color Key compare mask: - */ + vga_wgfx (fb_info->regs, CL_GRE, 0x00); /* Miscellaneous control: - */ + /* vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */ +/* vga_wgfx (fb_info->regs, CL_GR11, 0x00); */ + + vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00); /* Attribute Controller palette registers: "identity mapping" */ + vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08); + vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09); + vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a); + vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b); + vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c); + vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d); + vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e); + vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f); + + vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01); /* Attribute Controller mode: graphics mode */ + vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00); /* Overscan color reg.: reg. 0 */ + vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f); /* Color Plane enable: Enable all 4 planes */ +/* ### vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */ + vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00); /* Color Select: - */ + + WGen (fb_info, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ + + if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480) + WGen (fb_info, VGA_MIS_W, 0xc3); /* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */ + + vga_wgfx (fb_info->regs, CL_GR31, 0x04); /* BLT Start/status: Blitter reset */ + vga_wgfx (fb_info->regs, CL_GR31, 0x00); /* - " - : "end-of-reset" */ + + /* CLUT setup */ + WClut (fb_info, 0, 0x00, 0x00, 0x00); /* background: black */ + WClut (fb_info, 1, 0x3f, 0x3f, 0x3f); /* foreground: white */ + WClut (fb_info, 2, 0x00, 0x20, 0x00); + WClut (fb_info, 3, 0x00, 0x20, 0x20); + WClut (fb_info, 4, 0x20, 0x00, 0x00); + WClut (fb_info, 5, 0x20, 0x00, 0x20); + WClut (fb_info, 6, 0x20, 0x10, 0x00); + WClut (fb_info, 7, 0x20, 0x20, 0x20); + WClut (fb_info, 8, 0x10, 0x10, 0x10); + WClut (fb_info, 9, 0x10, 0x10, 0x30); + WClut (fb_info, 10, 0x10, 0x30, 0x10); + WClut (fb_info, 11, 0x10, 0x30, 0x30); + WClut (fb_info, 12, 0x30, 0x10, 0x10); + WClut (fb_info, 13, 0x30, 0x10, 0x30); + WClut (fb_info, 14, 0x30, 0x30, 0x10); + WClut (fb_info, 15, 0x30, 0x30, 0x30); + + /* the rest a grey ramp */ { - fb_info->size /= 2; - fb_info->smallboard = TRUE; - switch(fb_info->btype) - { - case BT_SD64: WSeq(SEQRF, 0x38); break; /* 2 MB Ram SD64 */ - case BT_PICASSO4: WSeq(SEQRF, 0x38); break; /* ### like SD64? */ - case BT_PICCOLO: - case BT_PICASSO: - case BT_SPECTRUM: WSeq(SEQRF, 0x30); break; /* 1 MB DRAM */ - default: - printk(KERN_WARNING "clgen: Uuhh..could not determine RAM size!\n"); - } - } - - } -#endif - printk(KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size); - printk("<init_vgachip()\n"); - return; -} + int i; + + for (i = 16; i < 256; i++) + WClut (fb_info, i, i >> 2, i >> 2, i >> 2); + } -static void switch_monitor(int on) -{ - static int IsOn = 0; /* XXX not ok for multiple boards */ - if (fb_info->btype == BT_PICASSO4) return; /* nothing to switch */ - if (fb_info->btype == BT_PICASSO) - { - if ((on && !IsOn) || (!on && IsOn)) - WSFR(0xff); + /* misc... */ + WHDR (fb_info, 0); /* Hidden DAC register: - */ + + printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size); + DPRINTK ("EXIT\n"); return; - } - if (on) - switch(fb_info->btype) - { - case BT_SD64: WSFR(fb_info->SFR | 0x21); break; - case BT_PICCOLO: WSFR(fb_info->SFR | 0x28); break; - case BT_SPECTRUM: WSFR(0x6f); break; +} + +static void switch_monitor (struct clgenfb_info *fb_info, int on) +{ +#ifdef CONFIG_ZORRO /* only works on Zorro boards */ + static int IsOn = 0; /* XXX not ok for multiple boards */ + + DPRINTK ("ENTER\n"); + + if (fb_info->btype == BT_PICASSO4) + return; /* nothing to switch */ + if (fb_info->btype == BT_ALPINE) + return; /* nothing to switch */ + if (fb_info->btype == BT_GD5480) + return; /* nothing to switch */ + if (fb_info->btype == BT_PICASSO) { + if ((on && !IsOn) || (!on && IsOn)) + WSFR (fb_info, 0xff); + + DPRINTK ("EXIT\n"); + return; } - else - switch(fb_info->btype) - { - case BT_SD64: WSFR(fb_info->SFR & 0xde); break; - case BT_PICCOLO: WSFR(fb_info->SFR & 0xd7); break; - case BT_SPECTRUM: WSFR(0x4f); break; + if (on) { + switch (fb_info->btype) { + case BT_SD64: + WSFR (fb_info, fb_info->SFR | 0x21); + break; + case BT_PICCOLO: + WSFR (fb_info, fb_info->SFR | 0x28); + break; + case BT_SPECTRUM: + WSFR (fb_info, 0x6f); + break; + default: /* do nothing */ break; + } + } else { + switch (fb_info->btype) { + case BT_SD64: + WSFR (fb_info, fb_info->SFR & 0xde); + break; + case BT_PICCOLO: + WSFR (fb_info, fb_info->SFR & 0xd7); + break; + case BT_SPECTRUM: + WSFR (fb_info, 0x4f); + break; + default: /* do nothing */ break; + } } + + DPRINTK ("EXIT\n"); +#endif /* CONFIG_ZORRO */ } -static void clgen_set_disp(const void *par, struct display *disp, - struct fb_info_gen *info) +static void clgen_set_disp (const void *par, struct display *disp, + struct fb_info_gen *info) { - struct clgenfb_par *_par = (struct clgenfb_par*) par; - struct clgenfb_info *info2 = (struct clgenfb_info *)info; + struct clgenfb_par *_par = (struct clgenfb_par *) par; + struct clgenfb_info *fb_info = (struct clgenfb_info *) info; + int accel_text; + + DPRINTK ("ENTER\n"); + + assert (_par != NULL); + assert (fb_info != NULL); + + accel_text = _par->var.accel_flags & FB_ACCELF_TEXT; - printk("clgen_set_disp(): "); - disp->screen_base = info2->fbmem; - switch (_par->var.bits_per_pixel) - { + printk ("Cirrus Logic video mode: "); + disp->screen_base = (char *) fb_info->fbmem; + switch (_par->var.bits_per_pixel) { #ifdef FBCON_HAS_MFB - case 1: - printk("monochrome\n"); - disp->dispsw = &fbcon_mfb; - break; + case 1: + printk ("monochrome\n"); + if (fb_info->btype == BT_GD5480) + disp->screen_base = (char *) fb_info->fbmem; + disp->dispsw = &fbcon_mfb; + break; #endif #ifdef FBCON_HAS_CFB8 - case 8: - printk("8 bit color depth\n"); - disp->dispsw = &fbcon_clgen_8; - break; + case 8: + printk ("8 bit color depth\n"); + if (fb_info->btype == BT_GD5480) + disp->screen_base = (char *) fb_info->fbmem; + if (accel_text) + disp->dispsw = &fbcon_clgen_8; + else + disp->dispsw = &fbcon_cfb8; + break; #endif #ifdef FBCON_HAS_CFB16 - case 16: - printk("16 bit color depth\n"); - disp->dispsw = &fbcon_cfb16; - disp->dispsw_data = info2->fbcon_cmap.cfb16; - break; + case 16: + printk ("16 bit color depth\n"); + if (accel_text) + disp->dispsw = &fbcon_clgen_16; + else + disp->dispsw = &fbcon_cfb16; + if (fb_info->btype == BT_GD5480) + disp->screen_base = (char *) fb_info->fbmem + 1 * MB_; + disp->dispsw_data = fb_info->fbcon_cmap.cfb16; + break; #endif #ifdef FBCON_HAS_CFB24 - case 24: - printk("24 bit color depth\n"); - disp->dispsw = &fbcon_cfb24; - disp->dispsw_data = info2->fbcon_cmap.cfb24; - break; + case 24: + printk ("24 bit color depth\n"); + disp->dispsw = &fbcon_cfb24; + if (fb_info->btype == BT_GD5480) + disp->screen_base = (char *) fb_info->fbmem + 2 * MB_; + disp->dispsw_data = fb_info->fbcon_cmap.cfb24; + break; #endif #ifdef FBCON_HAS_CFB32 - case 32: - printk("32 bit color depth\n"); - disp->dispsw = &fbcon_cfb32; - disp->dispsw_data = info2->fbcon_cmap.cfb32; - break; + case 32: + printk ("32 bit color depth\n"); + if (accel_text) + disp->dispsw = &fbcon_clgen_32; + else + disp->dispsw = &fbcon_cfb32; + if (fb_info->btype == BT_GD5480) + disp->screen_base = (char *) fb_info->fbmem + 2 * MB_; + disp->dispsw_data = fb_info->fbcon_cmap.cfb32; + break; #endif - default: - printk("unsupported color depth\n"); - disp->dispsw = &fbcon_dummy; - break; - } + default: + printk ("unsupported color depth\n"); + disp->dispsw = &fbcon_dummy; + disp->dispsw_data = NULL; + break; + } + + DPRINTK ("EXIT\n"); } -static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, +#ifdef FBCON_HAS_CFB8 +static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width) { - sx *= fontwidth(p); - sy *= fontheight(p); - dx *= fontwidth(p); - dy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - fb_info = (struct clgenfb_info*)p->fb_info; - - clgen_BitBLT((unsigned short)sx, (unsigned short)sy, - (unsigned short)dx, (unsigned short)dy, - (unsigned short)width, (unsigned short)height, - fb_info->currentmode.line_length); - clgen_WaitBLT(); + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; + + DPRINTK ("ENTER\n"); + + sx *= fontwidth (p); + sy *= fontheight (p); + dx *= fontwidth (p); + dy *= fontheight (p); + width *= fontwidth (p); + height *= fontheight (p); + + clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, + (unsigned short) dx, (unsigned short) dy, + (unsigned short) width, (unsigned short) height, + fb_info->currentmode.line_length); + + DPRINTK ("EXIT\n"); } -static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, +static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { - unsigned short col; - - fb_info = (struct clgenfb_info*)p->fb_info; - - sx *= fontwidth(p); - sy *= fontheight(p); - width *= fontwidth(p); - height *= fontheight(p); - - col = attr_bgcol_ec(p, conp); - col &= 0xff; - - clgen_RectFill((unsigned short)sx, (unsigned short)sy, - (unsigned short)width,(unsigned short)height, - col, fb_info->currentmode.line_length); - clgen_WaitBLT(); + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; + unsigned short col; + + DPRINTK ("ENTER\n"); + + sx *= fontwidth (p); + sy *= fontheight (p); + width *= fontwidth (p); + height *= fontheight (p); + + col = attr_bgcol_ec (p, conp); + col &= 0xff; + + clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, + (unsigned short) width, (unsigned short) height, + col, fb_info->currentmode.line_length); + + DPRINTK ("EXIT\n"); } +#endif -/********************************************************************/ -/* clgenfb_init() - master initialization function */ -/********************************************************************/ -__initfunc(void clgenfb_init(void)) +#ifdef FBCON_HAS_CFB16 +static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, + int dy, int dx, int height, int width) { - const struct ConfigDev *cd = NULL; - const struct ConfigDev *cd2 = NULL; - int err; - int btype; - int key,key2; - unsigned long board_addr,board_size; - - printk(">clgenfb_init()\n"); - printk(KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n"); - - btype = -1; - - if ((key = zorro_find(ZORRO_PROD_HELFRICH_SD64_RAM, 0, 0))) - { - key2 = zorro_find(ZORRO_PROD_HELFRICH_SD64_REG, 0, 0); - btype = BT_SD64; - printk(KERN_INFO "clgen: SD64 board detected; "); - } - else if ((key = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_RAM, 0, 0))) - { - key2 = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_REG, 0, 0); - btype = BT_PICCOLO; - printk(KERN_INFO "clgen: Piccolo board detected; "); - } - else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 0, 0))) - { - key2 = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 0, 0); - btype = BT_PICASSO; - printk(KERN_INFO "clgen: Picasso II board detected; "); - } - else if ((key = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 0, 0))) - { - key2 = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 0, 0); - btype = BT_SPECTRUM; - printk(KERN_INFO "clgen: Spectrum board detected; "); - } - else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 0, 0))) - { - btype = BT_PICASSO4; - printk(KERN_INFO "clgen: Picasso 4 board detected; "); - } - else - { - printk(KERN_NOTICE "clgen: no supported board found.\n"); - return; - } - - fb_info = &boards[0]; /* FIXME support multiple boards ...*/ - - fb_info->keyRAM = key; - fb_info->keyREG = key2; - fb_info->btype = btype; - - cd = zorro_get_board(key); - board_addr = (unsigned long)cd->cd_BoardAddr; - board_size = (unsigned long)cd->cd_BoardSize; - printk(" RAM (%lu MB) at $%lx, ", board_size/0x100000, board_addr); - - if (btype == BT_PICASSO4) - { - printk(" REG at $%lx\n", board_addr + 0x600000); - - /* To be precise, for the P4 this is not the */ - /* begin of the board, but the begin of RAM. */ - /* for P4, map in its address space in 2 chunks (### TEST! ) */ - /* (note the ugly hardcoded 16M number) */ - fb_info->regs = ioremap(board_addr, 16777216); - DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs); - fb_info->regs += 0x600000; - fb_info->fbregs_phys = board_addr + 0x600000; - - fb_info->fbmem_phys = board_addr + 16777216; - fb_info->fbmem = ioremap(fb_info->fbmem_phys, 16777216); - DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem); - } - else - { - cd2 = zorro_get_board(key2); - printk(" REG at $%lx\n", (unsigned long)cd2->cd_BoardAddr); - - fb_info->fbmem_phys = board_addr; - if (board_addr > 0x01000000) - fb_info->fbmem = ioremap(board_addr, board_size); - else - fb_info->fbmem = ZTWO_VADDR(board_addr); - - /* set address for REG area of board */ - fb_info->regs = (unsigned char *)ZTWO_VADDR(cd2->cd_BoardAddr); - fb_info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr; - - DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs); - DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem); - } - - init_vgachip(); - - /* set up a few more things, register framebuffer driver etc */ - fb_info->gen.parsize = sizeof(struct clgenfb_par); - fb_info->gen.fbhw = &clgen_hwswitch; - strcpy (fb_info->gen.info.modename, clgenfb_name); - fb_info->gen.info.node = -1; - fb_info->gen.info.fbops = &clgenfb_ops; - fb_info->gen.info.disp = &disp; - fb_info->gen.info.changevar = NULL; - fb_info->gen.info.switch_con = &fbgen_switch; - fb_info->gen.info.updatevar = &fbgen_update_var; - fb_info->gen.info.blank = &fbgen_blank; - fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; - - /* mark this board as "autoconfigured" */ - zorro_config_board(key, 0); - if (btype != BT_PICASSO4) - zorro_config_board(key2, 0); - - /* now that we know the board has been registered n' stuff, we */ - /* can finally initialize it to a default mode (640x480) */ - clgenfb_default = clgenfb_predefined[1].var; - clgenfb_default.activate = FB_ACTIVATE_NOW; - clgenfb_default.yres_virtual = 480*3; /* for fast scrolling (YPAN-Mode) */ - err = fbgen_do_set_var(&clgenfb_default, 1, &fb_info->gen); - - if (err) - return; + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; - disp.var = clgenfb_default; - fbgen_set_disp(-1, &fb_info->gen); - fbgen_install_cmap(0, &fb_info->gen); + DPRINTK ("ENTER\n"); - err = register_framebuffer(&fb_info->gen.info); - if (err) - { - printk(KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err); - return; - } + sx *= fontwidth (p) * 2; /* 2 bytes/pixel */ + sy *= fontheight (p); + dx *= fontwidth (p) * 2; /* 2 bytes/pixel */ + dy *= fontheight (p); + width *= fontwidth (p) * 2; /* 2 bytes/pixel */ + height *= fontheight (p); + + clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, + (unsigned short) dx, (unsigned short) dy, + (unsigned short) width, (unsigned short) height, + fb_info->currentmode.line_length); - printk("<clgenfb_init()\n"); - return; + DPRINTK ("EXIT\n"); } - /* - * Cleanup - */ +static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width) +{ + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; + unsigned short col; + + DPRINTK ("ENTER\n"); + + sx *= fontwidth (p) * 2; /* 2 bytes/pixel */ + sy *= fontheight (p); + width *= fontwidth (p) * 2; /* 2 bytes/pixel? */ + height *= fontheight (p); + + col = attr_bgcol_ec (p, conp); + col &= 0xff; + + clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, + (unsigned short) width, (unsigned short) height, + col, fb_info->currentmode.line_length); + + DPRINTK ("EXIT\n"); +} + +#endif -void clgenfb_cleanup(struct clgenfb_info *info) +#ifdef FBCON_HAS_CFB32 +static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, + int dy, int dx, int height, int width) +{ + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; + + DPRINTK ("ENTER\n"); + + sx *= fontwidth (p) * 4; /* 4 bytes/pixel */ + sy *= fontheight (p); + dx *= fontwidth (p) * 4; /* 4 bytes/pixel */ + dy *= fontheight (p); + width *= fontwidth (p) * 4; /* 4 bytes/pixel */ + height *= fontheight (p); + + clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy, + (unsigned short) dx, (unsigned short) dy, + (unsigned short) width, (unsigned short) height, + fb_info->currentmode.line_length); + + DPRINTK ("EXIT\n"); +} + +static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width) { - printk(">clgenfb_cleanup()\n"); + struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info; + + unsigned short col; - fb_info = info; + DPRINTK ("ENTER\n"); - switch_monitor(0); + sx *= fontwidth (p) * 4; /* 4 bytes/pixel */ + sy *= fontheight (p); + width *= fontwidth (p) * 4; /* 4 bytes/pixel? */ + height *= fontheight (p); - zorro_unconfig_board(info->keyRAM, 0); - if (fb_info->btype != BT_PICASSO4) - zorro_unconfig_board(info->keyREG, 0); + col = attr_bgcol_ec (p, conp); + col &= 0xff; - unregister_framebuffer(&info->gen.info); - printk("Framebuffer unregistered\n"); - printk("<clgenfb_cleanup()\n"); + clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy, + (unsigned short) width, (unsigned short) height, + col, fb_info->currentmode.line_length); + + DPRINTK ("EXIT\n"); } +#endif /* FBCON_HAS_CFB32 */ + + -/* A strtok which returns empty strings, too */ -static char *strtoke(char *s,const char *ct) + +#ifdef CONFIG_PREP +#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000) +#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) +static void __init get_prep_addrs (unsigned long *display, unsigned long *registers) { - char *sbegin, *send; - static char *ssave = NULL; - - sbegin = s ? s : ssave; - if (!sbegin) - return NULL; - if (*sbegin == '\0') { - ssave = NULL; - return NULL; - } - send = strpbrk(sbegin, ct); - if (send && *send != '\0') - *send++ = '\0'; - ssave = send; - return sbegin; + DPRINTK ("ENTER\n"); + + *display = PREP_VIDEO_BASE; + *registers = (unsigned long) PREP_IO_BASE; + + DPRINTK ("EXIT\n"); } -/*****************************************************************/ -/* clgenfb_setup() might be used later for parsing possible */ -/* arguments to the video= bootstrap parameter. Right now, there */ -/* is nothing I do here. */ -/*****************************************************************/ -__initfunc(void clgenfb_setup(char *options, int *ints)) +#endif /* CONFIG_PREP */ + + + + +#ifdef CONFIG_FB_OF +static void __init get_of_addrs (const struct device_node *dp, + unsigned long *display, unsigned long *registers) { -// char *this_opt; + int i; + + DPRINTK ("ENTER\n"); + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + unsigned long addr = dp->addrs[i].address; + unsigned long size = dp->addrs[i].size; + printk ("dp->addrs[%d].address = $lx, dp->addrs[%d].size = %lx\n", + i, addr, i, size); + if (size >= 0x800000) { + *display = addr; + } else { + *registers = addr; + } + } -// printk("clgenfb_setup(): options: %s\n", options); + DPRINTK ("EXIT\n"); } +#endif /* CONFIG_FB_OF */ - /* - * Modularization - */ -#ifdef MODULE -int init_module(void) + +#ifdef CONFIG_PCI +/* Pulled the logic from XFree86 Cirrus driver to get the memory size, + * based on the DRAM bandwidth bit and DRAM bank switching bit. This + * works with 1MB, 2MB and 4MB configurations (which the Motorola boards + * seem to have. */ +static unsigned int __init clgen_get_memsize (caddr_t regbase) { - printk("init_module()\n"); - clgenfb_init(); - return 0; + unsigned long mem = 1 * MB_; + unsigned char SRF; + + DPRINTK ("ENTER\n"); + + SRF = vga_rseq (regbase, CL_SEQRF); + if ((SRF & 0x18) == 0x18) { + /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory + * on the 5430. */ + mem *= 2; + } + if (SRF & 0x80) { + /* If DRAM bank switching is enabled, there must be twice as much + * memory installed. (4MB on the 5434) */ + mem *= 2; + } + return mem; + + DPRINTK ("EXIT\n"); } -void cleanup_module(void) + + +static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype) { - printk("module_cleanup()\n"); - clgenfb_cleanup(fb_info); + struct pci_dev *pdev = NULL; + int i; + + DPRINTK ("ENTER\n"); + + for (i = 0; i < arraysize(clgen_pci_probe_list) && !pdev; i++) + pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, + clgen_pci_probe_list[i].device, NULL); + + if (pdev) + *btype = clgen_pci_probe_list[i - 1].btype; + + DPRINTK ("EXIT, returning %p\n", pdev); + return pdev; } -#endif /* MODULE */ -/**********************************************************************/ -/* about the following functions - I have used the same names for the */ -/* functions as Markus Wild did in his Retina driver for NetBSD as */ -/* they just made sense for this purpose. Apart from that, I wrote */ -/* these functions myself. */ -/**********************************************************************/ -/*** WGen() - write into one of the external/general registers ***/ -void WGen(int regnum, unsigned char val) +static void __init get_pci_addrs (const struct pci_dev *pdev, + unsigned long *display, unsigned long *registers) { - unsigned volatile char *reg = fb_info->regs + regnum; + assert (pdev != NULL); + assert (display != NULL); + assert (registers != NULL); - if(fb_info->btype == BT_PICASSO) - { - /* Picasso II specific hack */ -/* if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */ - if (regnum == M_3C7_W || regnum == M_3C9) - reg += 0xfff; + DPRINTK ("ENTER\n"); + + *display = 0; + *registers = 0; + + /* This is a best-guess for now */ + + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) + + *display = pdev->base_address[0]; + if ((*display & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { + *registers = *display; + *display = pdev->base_address[1]; + } else { + *registers = pdev->base_address[1]; } - *reg = val; +#else + + if (pdev->resource[0].flags & IORESOURCE_IO) { + *display = pdev->resource[1].start; + *registers = pdev->resource[0].start; + } else { + *display = pdev->resource[0].start; + *registers = pdev->resource[1].start; + } + +#endif /* kernel older than 2.3.13 */ + + assert (*display != 0); + + DPRINTK ("EXIT\n"); } -/*** RGen() - read out one of the external/general registers ***/ -unsigned char RGen(int regnum) + + + +/* clgen_pci_unmap only used in modules */ +#ifdef MODULE +static void clgen_pci_unmap (struct clgenfb_info *info) { - unsigned volatile char *reg = fb_info->regs + regnum; + iounmap (info->fbmem); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) + __release_region (&iomem_resource, info->fbmem_phys, info->size); + __release_region (&iomem_resource, 0xA0000, 65535); + if (release_io_ports) + __release_region (&ioport_resource, 0x3C0, 32); +#endif +} +#endif /* MODULE */ + + +static int __init clgen_pci_setup (struct clgenfb_info *info, + clgen_board_t *btype) +{ +#ifdef CONFIG_FB_OF + struct device_node *dp; +#endif /* CONFIG_FB_OF */ + struct pci_dev *pdev; + unsigned long board_addr, board_size; + u16 tmp16; + + DPRINTK ("ENTER\n"); + + pdev = clgen_pci_dev_get (btype); + if (!pdev) { + printk (KERN_ERR " Couldn't find PCI device\n"); + DPRINTK ("EXIT, returning 1\n"); + return 1; + } + DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n", + pdev->resource[0].start, *btype); + DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start); + + info->pdev = pdev; - if(fb_info->btype == BT_PICASSO) +#ifdef CONFIG_PREP + /* Xbh does this, though 0 seems to be the init value */ + pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000); +#endif + + pci_read_config_word (pdev, PCI_COMMAND, &tmp16); + if (!(tmp16 & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) { + u16 tmp16_o = tmp16 | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + pci_write_config_word (pdev, PCI_COMMAND, tmp16_o); + } + +#ifdef CONFIG_FB_OF + /* Ok, so its an ugly hack, since we could have passed it down from + * clgen_of_init() if we'd done it right. */ + DPRINTK ("Attempt to get OF info for MacPicasso\n"); + dp = find_devices ("MacPicasso"); + if (dp != 0) { + if (dp->n_addrs != 2) { + printk (KERN_ERR "expecting 2 address for clgen (got %d)\n", dp->n_addrs); + DPRINTK ("EXIT, returning 1\n"); + return 1; + } + get_of_addrs (dp, &board_addr, &info->fbregs_phys); + } else +#endif { - /* Picasso II specific hack */ -/* if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */ - if (regnum == M_3C7_W || regnum == M_3C9) - reg += 0xfff; + +#ifdef CONFIG_PREP + get_prep_addrs (&board_addr, &info->fbregs_phys); +#else /* CONFIG_PREP */ + DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n"); + get_pci_addrs (pdev, &board_addr, &info->fbregs_phys); +#endif /* CONFIG_PREP */ + } + + DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys); + +#ifdef CONFIG_PREP + /* PReP dies if we ioremap the IO registers, but it works w/out... */ + info->regs = (char *) info->fbregs_phys; +#else + info->regs = 0; /* FIXME: this forces VGA. alternatives? */ +#endif + + if (*btype == BT_GD5480) { + board_size = 32 * MB_; + } else { + board_size = clgen_get_memsize (info->regs); + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) + + if (!__request_region (&iomem_resource, board_addr, + board_size, "clgenfb")) { + pci_write_config_word (pdev, PCI_COMMAND, tmp16); + printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", + board_addr); + return -1; } + if (!__request_region (&iomem_resource, 0xA0000, 65535, "clgenfb")) { + pci_write_config_word (pdev, PCI_COMMAND, tmp16); + printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", + 0xA0000L); + __release_region(&iomem_resource, board_addr, board_size); + return -1; + } + if (__request_region(&ioport_resource, 0x3C0, 32, "clgenfb")) + release_io_ports = 1; + +#endif /* kernel > 2.3.13 */ + + info->fbmem = ioremap (board_addr, board_size); + info->fbmem_phys = board_addr; + info->size = board_size; - return *reg; + printk (" RAM (%lu MB) at 0x%lx, ", info->size / MB_, board_addr); + + printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n"); + + DPRINTK ("EXIT, returning 0\n"); + return 0; } +#endif /* CONFIG_PCI */ + + + + +#ifdef CONFIG_ZORRO +static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btype) +{ + int i, key = 0; + + assert (key_o != NULL); + assert (btype != NULL); + + for (i = 0; i < arraysize(clgen_zorro_probe_list) && !key; i++) + key = zorro_find (clgen_zorro_probe_list[i].key, 0, 0); + + if (key) { + *key_o = key; + if (clgen_zorro_probe_list[i].key2) + *key2_o = zorro_find (clgen_zorro_probe_list[i].key2, 0, 0); + else + *key2_o = 0; + *btype = clgen_zorro_probe_list[i - 1].btype; + + printk (KERN_INFO "clgen: %s board detected; ", + clgen_board_info[*btype].name); + + return 0; + } + + printk (KERN_NOTICE "clgen: no supported board found.\n"); + return -1; +} + + + +/* clgen_zorro_unmap only used in modules */ +#ifdef MODULE +static void clgen_zorro_unmap (struct clgenfb_info *info) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13) + __release_region(&iomem_resource, info->board_addr, info->board_size); +#endif + if (info->btype == BT_PICASSO4) { + iounmap (info->board_addr); + iounmap (info->fbmem_phys); + } else { + if (info->board_addr > 0x01000000) + iounmap (info->board_addr); + } +} +#endif /* MODULE */ + + + +static int __init clgen_zorro_setup (struct clgenfb_info *info, + clgen_board_t *btype) +{ + int key = 0, key2 = 0; + const struct ConfigDev *cd = NULL; + const struct ConfigDev *cd2 = NULL; + unsigned long board_addr, board_size; + + assert (info != NULL); + assert (btype != NULL); + + if (clgen_zorro_find (&key, &key2, btype)) + return -1; + + assert (key > 0); + assert (key2 >= 0); + assert (*btype != BT_NONE); + + info->keyRAM = key; + info->keyREG = key2; + cd = zorro_get_board (key); + info->board_addr = board_addr = (unsigned long) cd->cd_BoardAddr; + info->board_size = board_size = (unsigned long) cd->cd_BoardSize; + + if (!__request_region(&iomem_resource, board_addr, + board_size, "clgenfb")) { + printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n", + board_addr); + return -1; + } + + printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); + + if (*btype == BT_PICASSO4) { + printk (" REG at $%lx\n", board_addr + 0x600000); + + /* To be precise, for the P4 this is not the */ + /* begin of the board, but the begin of RAM. */ + /* for P4, map in its address space in 2 chunks (### TEST! ) */ + /* (note the ugly hardcoded 16M number) */ + info->regs = ioremap (board_addr, 16777216); + DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs); + info->regs += 0x600000; + info->fbregs_phys = board_addr + 0x600000; + + info->fbmem_phys = board_addr + 16777216; + info->fbmem = ioremap (info->fbmem_phys, 16777216); + } else { + cd2 = zorro_get_board (key2); + printk (" REG at $%lx\n", (unsigned long) cd2->cd_BoardAddr); + + info->fbmem_phys = board_addr; + if (board_addr > 0x01000000) + info->fbmem = ioremap (board_addr, board_size); + else + info->fbmem = (caddr_t) ZTWO_VADDR (board_addr); + + /* set address for REG area of board */ + info->regs = (caddr_t) ZTWO_VADDR (cd2->cd_BoardAddr); + info->fbregs_phys = (unsigned long) cd2->cd_BoardAddr; + + DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs); + } + + /* mark this board as "autoconfigured" */ + zorro_config_board (key, 0); + if (*btype != BT_PICASSO4) + zorro_config_board (key2, 0); + + printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); + + return 0; +} +#endif /* CONFIG_ZORRO */ + -/*** WSeq() - write into a register of the sequencer ***/ -void WSeq(unsigned char regnum, unsigned char val) + +/********************************************************************/ +/* clgenfb_init() - master initialization function */ +/********************************************************************/ +int __init clgenfb_init(void) { - fb_info->regs[SEQRX] = regnum; - fb_info->regs[SEQRX+1] = val; + int err, j, k; + + clgen_board_t btype = BT_NONE; + struct clgenfb_info *fb_info = NULL; + + DPRINTK ("ENTER\n"); + + printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n"); + + fb_info = &boards[0]; /* FIXME support multiple boards ... */ + +#ifdef CONFIG_PCI + if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */ + DPRINTK ("EXIT, returning -ENXIO\n"); + return -ENXIO; + } + +#elif CONFIG_ZORRO + if (clgen_zorro_setup (fb_info, &btype)) { + DPRINTK ("EXIT, returning -ENXIO\n"); + return -ENXIO; + } + +#else +#error Unsupported bus. Supported: PCI, Zorro +#endif /* !CONFIG_PCI, !CONFIG_ZORRO */ + + /* sanity checks */ + assert (btype != BT_NONE); + assert (btype == clgen_board_info[btype].btype); + + fb_info->btype = btype; + + DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem); + + init_vgachip (fb_info); + + /* set up a few more things, register framebuffer driver etc */ + fb_info->gen.parsize = sizeof (struct clgenfb_par); + fb_info->gen.fbhw = &clgen_hwswitch; + + strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name, + sizeof (fb_info->gen.info.modename)); + fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0; + + fb_info->gen.info.node = -1; + fb_info->gen.info.fbops = &clgenfb_ops; + fb_info->gen.info.disp = &disp; + fb_info->gen.info.changevar = NULL; + fb_info->gen.info.switch_con = &fbgen_switch; + fb_info->gen.info.updatevar = &fbgen_update_var; + fb_info->gen.info.blank = &fbgen_blank; + fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT; + + for (j = 0; j < 256; j++) { + if (j < 16) { + k = color_table[j]; + fb_info->palette[j].red = default_red[k]; + fb_info->palette[j].green = default_grn[k]; + fb_info->palette[j].blue = default_blu[k]; + } else { + fb_info->palette[j].red = + fb_info->palette[j].green = + fb_info->palette[j].blue = j; + } + } + + /* now that we know the board has been registered n' stuff, we */ + /* can finally initialize it to a default mode */ + clgenfb_default = clgenfb_predefined[clgen_def_mode].var; + clgenfb_default.activate = FB_ACTIVATE_NOW; + clgenfb_default.yres_virtual = 480 * 3; /* for fast scrolling (YPAN-Mode) */ + err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen); + + if (err) { + DPRINTK ("EXIT, returning -EINVAL\n"); + return -EINVAL; + } + + disp.var = clgenfb_default; + fbgen_set_disp (-1, &fb_info->gen); + fbgen_install_cmap (0, &fb_info->gen); + + err = register_framebuffer (&fb_info->gen.info); + if (err) { + printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err); + DPRINTK ("EXIT, returning -EINVAL\n"); + return -EINVAL; + } + DPRINTK ("EXIT, returning 0\n"); + return 0; } -/*** RSeq() - read out one of the Sequencer registers ***/ -unsigned char RSeq(unsigned char regnum) + + +#if defined(CONFIG_FB_OF) +int __init clgen_of_init (struct device_node *dp) { - fb_info->regs[SEQRX] = regnum; - return fb_info->regs[SEQRX+1]; + int rc; + + DPRINTK ("ENTER\n"); + + rc = clgenfb_init (); + + DPRINTK ("EXIT, returning %d\n", rc); + + return rc; } +#endif /* CONFIG_FB_OF */ + + -/*** WCrt() - write into a register of the CRT controller ***/ -void WCrt(unsigned char regnum, unsigned char val) + /* + * Cleanup (only needed for module) + */ +#ifdef MODULE +static void clgenfb_cleanup (struct clgenfb_info *info) { - fb_info->regs[CRTX] = regnum; - fb_info->regs[CRTX+1] = val; + DPRINTK ("ENTER\n"); + +#ifdef CONFIG_ZORRO + switch_monitor (info, 0); + + clgen_zorro_unmap (info); + + zorro_unconfig_board (info->keyRAM, 0); + if (info->btype != BT_PICASSO4) + zorro_unconfig_board (info->keyREG, 0); +#else + clgen_pci_unmap (info); +#endif /* CONFIG_ZORRO */ + + unregister_framebuffer ((struct fb_info *) info); + printk ("Framebuffer unregistered\n"); + + DPRINTK ("EXIT\n"); +} +#endif + + + + +#ifndef MODULE +int __init clgenfb_setup(char *options) { + char *this_opt, s[32]; + int i; + + DPRINTK ("ENTER\n"); + + if (!options || !*options) + return 0; + + for (this_opt = strtok (options, ","); this_opt != NULL; + this_opt = strtok (NULL, ",")) { + if (!*this_opt) continue; + + DPRINTK("clgenfb_setup: option '%s'\n", this_opt); + + for (i = 0; i < NUM_TOTAL_MODES; i++) { + sprintf (s, "mode:%s", clgenfb_predefined[i].name); + if (strcmp (this_opt, s) == 0) + clgen_def_mode = i; + } + } + return 0; } +#endif + -/*** RCrt() - read out one of the CRT controller registers ***/ -unsigned char RCrt(unsigned char regnum) + + + + /* + * Modularization + */ + +#ifdef MODULE +MODULE_AUTHOR("Copyright 1999 Jeff Garzik <jgarzik@pobox.com>"); +MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); + +int init_module (void) { - fb_info->regs[CRTX] = regnum; - return fb_info->regs[CRTX+1]; +#if defined(CONFIG_FB_OF) +/* Nothing to do, must be called from offb */ + return 0; +#else + int i; + + DPRINTK ("ENTER\n"); + i = clgenfb_init (); + DPRINTK ("EXIT\n"); + return i; +#endif } -/*** WGfx() - write into a register of the Gfx controller ***/ -void WGfx(unsigned char regnum, unsigned char val) +void cleanup_module (void) { - fb_info->regs[GRX] = regnum; - fb_info->regs[GRX+1] = val; + DPRINTK ("ENTER\n"); + + clgenfb_cleanup (&boards[0]); /* FIXME: support multiple boards */ + + DPRINTK ("EXIT\n"); } -/*** RGfx() - read out one of the Gfx controller registers ***/ -unsigned char RGfx(unsigned char regnum) +#endif /* MODULE */ + + +/**********************************************************************/ +/* about the following functions - I have used the same names for the */ +/* functions as Markus Wild did in his Retina driver for NetBSD as */ +/* they just made sense for this purpose. Apart from that, I wrote */ +/* these functions myself. */ +/**********************************************************************/ + +/*** WGen() - write into one of the external/general registers ***/ +static void WGen (const struct clgenfb_info *fb_info, + int regnum, unsigned char val) { - fb_info->regs[GRX] = regnum; - return fb_info->regs[GRX+1]; + unsigned long regofs = 0; + + if (fb_info->btype == BT_PICASSO) { + /* Picasso II specific hack */ +/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ + if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) + regofs = 0xfff; + } + + vga_w (fb_info->regs, regofs + regnum, val); } -/*** WAttr() - write into a register of the Attribute controller ***/ -void WAttr(unsigned char regnum, unsigned char val) +/*** RGen() - read out one of the external/general registers ***/ +static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum) { - /* if the next access to the attribute controller is a data write access, */ - /* simply write back the information that was already there before, so that */ - /* the next write access after that will be an index write. */ - if (RCrt(CRT24) & 0x80) - /* can't use WAttr() here - we would go into a recursive loop otherwise */ - fb_info->regs[ARX] = fb_info->regs[ARX+1]; - - if (RCrt(CRT24) & 0x80) - printk(KERN_WARNING "clgen: *** AttrIdx BAD!***\n"); - - /* now, first set index and after that the value - both to the same address (!) */ - fb_info->regs[ARX] = regnum; - fb_info->regs[ARX] = val; + unsigned long regofs = 0; + + if (fb_info->btype == BT_PICASSO) { + /* Picasso II specific hack */ +/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */ + if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) + regofs = 0xfff; + } + + return vga_r (fb_info->regs, regofs + regnum); } /*** AttrOn() - turn on VideoEnable for Attribute controller ***/ -void AttrOn() +static void AttrOn (const struct clgenfb_info *fb_info) { - if (RCrt(CRT24) & 0x80) + assert (fb_info != NULL); + + DPRINTK ("ENTER\n"); + + if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) { /* if we're just in "write value" mode, write back the */ /* same value as before to not modify anything */ - fb_info->regs[ARX] = fb_info->regs[ARX+1]; - + vga_w (fb_info->regs, VGA_ATT_IW, + vga_r (fb_info->regs, VGA_ATT_R)); + } /* turn on video bit */ -/* fb_info->regs[ARX] = 0x20; */ - fb_info->regs[ARX] = 0x33; +/* vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */ + vga_w (fb_info->regs, VGA_ATT_IW, 0x33); /* dummy write on Reg0 to be on "write index" mode next time */ - fb_info->regs[ARX] = 0x00; -} - -/*** RAttr() - read out a register of the Attribute controller ***/ -unsigned char RAttr(unsigned char regnum) -{ - /* (explanation see above in WAttr() ) */ - if (RCrt(CRT24) & 0x80) - fb_info->regs[ARX] = fb_info->regs[ARX+1]; + vga_w (fb_info->regs, VGA_ATT_IW, 0x00); - fb_info->regs[ARX] = regnum; - return fb_info->regs[ARX+1]; + DPRINTK ("EXIT\n"); } - /*** WHDR() - write into the Hidden DAC register ***/ /* as the HDR is the only extension register that requires special treatment * (the other extension registers are accessible just like the "ordinary" * registers of their functional group) here is a specialized routine for * accessing the HDR */ -void WHDR(unsigned char val) +static void WHDR (const struct clgenfb_info *fb_info, unsigned char val) { unsigned char dummy; - if(fb_info->btype == BT_PICASSO) - { + if (fb_info->btype == BT_PICASSO) { /* Klaus' hint for correct access to HDR on some boards */ /* first write 0 to pixel mask (3c6) */ - WGen(M_3C6, 0x00); udelay(200); + WGen (fb_info, VGA_PEL_MSK, 0x00); + udelay (200); /* next read dummy from pixel address (3c8) */ - dummy = RGen(M_3C8); udelay(200); + dummy = RGen (fb_info, VGA_PEL_IW); + udelay (200); } - /* now do the usual stuff to access the HDR */ - dummy = RGen(M_3C6); udelay(200); - dummy = RGen(M_3C6); udelay(200); - dummy = RGen(M_3C6); udelay(200); - dummy = RGen(M_3C6); udelay(200); + dummy = RGen (fb_info, VGA_PEL_MSK); + udelay (200); + dummy = RGen (fb_info, VGA_PEL_MSK); + udelay (200); + dummy = RGen (fb_info, VGA_PEL_MSK); + udelay (200); + dummy = RGen (fb_info, VGA_PEL_MSK); + udelay (200); - WGen(M_3C6, val); udelay(200); + WGen (fb_info, VGA_PEL_MSK, val); + udelay (200); - if(fb_info->btype == BT_PICASSO) - { + if (fb_info->btype == BT_PICASSO) { /* now first reset HDR access counter */ - dummy = RGen(M_3C8); udelay(200); + dummy = RGen (fb_info, VGA_PEL_IW); + udelay (200); /* and at the end, restore the mask value */ /* ## is this mask always 0xff? */ - WGen(M_3C6, 0xff); udelay(200); + WGen (fb_info, VGA_PEL_MSK, 0xff); + udelay (200); } } -/*** RHDR() - read out the Hidden DAC register ***/ -/* I hope this does not break on the GD5428 - cannot test it. */ -/* (Is there any board for the Amiga that uses the 5428 ?) */ -unsigned char RHDR() -{ - unsigned char dummy; - - dummy = RGen(M_3C6); - dummy = RGen(M_3C6); - dummy = RGen(M_3C6); - dummy = RGen(M_3C6); - - return RGen(M_3C6); -} /*** WSFR() - write to the "special function register" (SFR) ***/ -void WSFR(unsigned char val) +static void WSFR (struct clgenfb_info *fb_info, unsigned char val) { - fb_info->SFR = val; - fb_info->regs[0x8000] = val; +#ifdef CONFIG_ZORRO + assert (fb_info->regs != NULL); + fb_info->SFR = val; + writeb (val, fb_info->regs + 0x8000); +#endif } /* The Picasso has a second register for switching the monitor bit */ -void WSFR2(unsigned char val) +static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val) { +#ifdef CONFIG_ZORRO /* writing an arbitrary value to this one causes the monitor switcher */ /* to flip to Amiga display */ - fb_info->SFR = val; - fb_info->regs[0x9000] = val; + assert (fb_info->regs != NULL); + fb_info->SFR = val; + writeb (val, fb_info->regs + 0x9000); +#endif } + /*** WClut - set CLUT entry (range: 0..63) ***/ -void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue) +static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red, + unsigned char green, unsigned char blue) { - unsigned int data = 0x3c9; + unsigned int data = VGA_PEL_D; /* address write mode register is not translated.. */ - fb_info->regs[0x3c8] = regnum; + vga_w (fb_info->regs, VGA_PEL_IW, regnum); - if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4) - { + if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 || + fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) { /* but DAC data register IS, at least for Picasso II */ - if(fb_info->btype == BT_PICASSO) + if (fb_info->btype == BT_PICASSO) data += 0xfff; - fb_info->regs[data] = red; - fb_info->regs[data] = green; - fb_info->regs[data] = blue; - } - else - { - fb_info->regs[data] = blue; - fb_info->regs[data] = green; - fb_info->regs[data] = red; + vga_w (fb_info->regs, data, red); + vga_w (fb_info->regs, data, green); + vga_w (fb_info->regs, data, blue); + } else { + vga_w (fb_info->regs, data, blue); + vga_w (fb_info->regs, data, green); + vga_w (fb_info->regs, data, red); } } + + +#if 0 /*** RClut - read CLUT entry (range 0..63) ***/ -void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue) +static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red, + unsigned char *green, unsigned char *blue) { - unsigned int data = 0x3c9; + unsigned int data = VGA_PEL_D; - fb_info->regs[0x3c7] = regnum; + vga_w (fb_info->regs, VGA_PEL_IR, regnum); - if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4) - { - if(fb_info->btype == BT_PICASSO) + if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 || + fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) { + if (fb_info->btype == BT_PICASSO) data += 0xfff; - *red = fb_info->regs[data]; - *green = fb_info->regs[data]; - *blue = fb_info->regs[data]; - } - else - { - *blue = fb_info->regs[data]; - *green = fb_info->regs[data]; - *red = fb_info->regs[data]; + *red = vga_r (fb_info->regs, data); + *green = vga_r (fb_info->regs, data); + *blue = vga_r (fb_info->regs, data); + } else { + *blue = vga_r (fb_info->regs, data); + *green = vga_r (fb_info->regs, data); + *red = vga_r (fb_info->regs, data); } } +#endif /******************************************************************* @@ -1937,11 +3241,12 @@ void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsig Wait for the BitBLT engine to complete a possible earlier job *********************************************************************/ -void clgen_WaitBLT() +/* FIXME: use interrupts instead */ +extern inline void clgen_WaitBLT (caddr_t regbase) { /* now busy-wait until we're done */ - while (RGfx(GR31) & 0x08) - ; + while (vga_rgfx (regbase, CL_GR31) & 0x08) + /* do nothing */ ; } /******************************************************************* @@ -1950,90 +3255,87 @@ void clgen_WaitBLT() perform accelerated "scrolling" ********************************************************************/ -void clgen_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, - u_short width, u_short height, u_short line_length) +static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty, + u_short width, u_short height, u_short line_length) { u_short nwidth, nheight; u_long nsrc, ndest; u_char bltmode; + DPRINTK ("ENTER\n"); + nwidth = width - 1; nheight = height - 1; bltmode = 0x00; /* if source adr < dest addr, do the Blt backwards */ - if (cury <= desty) - { - if (cury == desty) - { + if (cury <= desty) { + if (cury == desty) { /* if src and dest are on the same line, check x */ if (curx < destx) bltmode |= 0x01; - } - else + } else bltmode |= 0x01; } - - if (!bltmode) - { + if (!bltmode) { /* standard case: forward blitting */ nsrc = (cury * line_length) + curx; ndest = (desty * line_length) + destx; - } - else - { + } else { /* this means start addresses are at the end, counting backwards */ nsrc = cury * line_length + curx + nheight * line_length + nwidth; ndest = desty * line_length + destx + nheight * line_length + nwidth; } -// clgen_WaitBLT(); /* ### NOT OK for multiple boards! */ + clgen_WaitBLT(regbase); /* - run-down of registers to be programmed: - destination pitch - source pitch - BLT width/height - source start - destination start - BLT mode - BLT ROP - GR0 / GR1: "fill color" - start/stop - */ + run-down of registers to be programmed: + destination pitch + source pitch + BLT width/height + source start + destination start + BLT mode + BLT ROP + VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" + start/stop + */ /* pitch: set to line_length */ - WGfx(GR24, line_length & 0xff); /* dest pitch low */ - WGfx(GR25, (line_length >> 8)); /* dest pitch hi */ - WGfx(GR26, line_length & 0xff); /* source pitch low */ - WGfx(GR27, (line_length >> 8)); /* source pitch hi */ + vga_wgfx (regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ + vga_wgfx (regbase, CL_GR25, (line_length >> 8)); /* dest pitch hi */ + vga_wgfx (regbase, CL_GR26, line_length & 0xff); /* source pitch low */ + vga_wgfx (regbase, CL_GR27, (line_length >> 8)); /* source pitch hi */ /* BLT width: actual number of pixels - 1 */ - WGfx(GR20, nwidth & 0xff); /* BLT width low */ - WGfx(GR21, (nwidth >> 8)); /* BLT width hi */ + vga_wgfx (regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ + vga_wgfx (regbase, CL_GR21, (nwidth >> 8)); /* BLT width hi */ /* BLT height: actual number of lines -1 */ - WGfx(GR22, nheight & 0xff); /* BLT height low */ - WGfx(GR23, (nheight >> 8)); /* BLT width hi */ + vga_wgfx (regbase, CL_GR22, nheight & 0xff); /* BLT height low */ + vga_wgfx (regbase, CL_GR23, (nheight >> 8)); /* BLT width hi */ /* BLT destination */ - WGfx(GR28, (u_char)(ndest & 0xff)); /* BLT dest low */ - WGfx(GR29, (u_char)(ndest >> 8)); /* BLT dest mid */ - WGfx(GR2A, (u_char)(ndest >> 16)); /* BLT dest hi */ + vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ + vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ + vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ /* BLT source */ - WGfx(GR2C, (u_char)(nsrc & 0xff)); /* BLT src low */ - WGfx(GR2D, (u_char)(nsrc >> 8)); /* BLT src mid */ - WGfx(GR2E, (u_char)(nsrc >> 16)); /* BLT src hi */ + vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff)); /* BLT src low */ + vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8)); /* BLT src mid */ + vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16)); /* BLT src hi */ /* BLT mode */ - WGfx(GR30, bltmode); /* BLT mode */ + vga_wgfx (regbase, CL_GR30, bltmode); /* BLT mode */ /* BLT ROP: SrcCopy */ - WGfx(GR32, 0x0d); /* BLT ROP */ + vga_wgfx (regbase, CL_GR32, 0x0d); /* BLT ROP */ /* and finally: GO! */ - WGfx(GR31, 0x02); /* BLT Start/status */ + vga_wgfx (regbase, CL_GR31, 0x02); /* BLT Start/status */ + + DPRINTK ("EXIT\n"); } /******************************************************************* @@ -2042,56 +3344,78 @@ void clgen_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, perform accelerated rectangle fill ********************************************************************/ -void clgen_RectFill (u_short x, u_short y, u_short width, u_short height, - u_char color, u_short line_length) +static void clgen_RectFill (struct clgenfb_info *fb_info, + u_short x, u_short y, u_short width, u_short height, + u_char color, u_short line_length) { u_short nwidth, nheight; u_long ndest; + u_char op; + + DPRINTK ("ENTER\n"); nwidth = width - 1; nheight = height - 1; ndest = (y * line_length) + x; -// clgen_WaitBLT(); /* ### NOT OK for multiple boards! */ + clgen_WaitBLT(fb_info->regs); /* pitch: set to line_length */ - WGfx(GR24, line_length & 0xff); /* dest pitch low */ - WGfx(GR25, (line_length >> 8)); /* dest pitch hi */ - WGfx(GR26, line_length & 0xff); /* source pitch low */ - WGfx(GR27, (line_length >> 8)); /* source pitch hi */ + vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff); /* dest pitch low */ + vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8)); /* dest pitch hi */ + vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff); /* source pitch low */ + vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8)); /* source pitch hi */ /* BLT width: actual number of pixels - 1 */ - WGfx(GR20, nwidth & 0xff); /* BLT width low */ - WGfx(GR21, (nwidth >> 8)); /* BLT width hi */ + vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff); /* BLT width low */ + vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8)); /* BLT width hi */ /* BLT height: actual number of lines -1 */ - WGfx(GR22, nheight & 0xff); /* BLT height low */ - WGfx(GR23, (nheight >> 8)); /* BLT width hi */ + vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff); /* BLT height low */ + vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8)); /* BLT width hi */ /* BLT destination */ - WGfx(GR28, (u_char)(ndest & 0xff)); /* BLT dest low */ - WGfx(GR29, (u_char)(ndest >> 8)); /* BLT dest mid */ - WGfx(GR2A, (u_char)(ndest >> 16)); /* BLT dest hi */ + vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff)); /* BLT dest low */ + vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8)); /* BLT dest mid */ + vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16)); /* BLT dest hi */ /* BLT source: set to 0 (is a dummy here anyway) */ - WGfx(GR2C, 0x00); /* BLT src low */ - WGfx(GR2D, 0x00); /* BLT src mid */ - WGfx(GR2E, 0x00); /* BLT src hi */ + vga_wgfx (fb_info->regs, CL_GR2C, 0x00); /* BLT src low */ + vga_wgfx (fb_info->regs, CL_GR2D, 0x00); /* BLT src mid */ + vga_wgfx (fb_info->regs, CL_GR2E, 0x00); /* BLT src hi */ /* This is a ColorExpand Blt, using the */ /* same color for foreground and background */ - WGfx(GR0, color); /* foreground color */ - WGfx(GR1, color); /* background color */ - + vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color); /* foreground color */ + vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color); /* background color */ + + op = 0xc0; + if (fb_info->currentmode.var.bits_per_pixel == 16) { + vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */ + vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */ + op = 0x50; + op = 0xd0; + } else if (fb_info->currentmode.var.bits_per_pixel == 32) { + vga_wgfx (fb_info->regs, CL_GR10, color); /* foreground color */ + vga_wgfx (fb_info->regs, CL_GR11, color); /* background color */ + vga_wgfx (fb_info->regs, CL_GR12, color); /* foreground color */ + vga_wgfx (fb_info->regs, CL_GR13, color); /* background color */ + vga_wgfx (fb_info->regs, CL_GR14, 0); /* foreground color */ + vga_wgfx (fb_info->regs, CL_GR15, 0); /* background color */ + op = 0x50; + op = 0xf0; + } /* BLT mode: color expand, Enable 8x8 copy (faster?) */ - WGfx(GR30, 0xc0); /* BLT mode */ + vga_wgfx (fb_info->regs, CL_GR30, op); /* BLT mode */ /* BLT ROP: SrcCopy */ - WGfx(GR32, 0x0d); /* BLT ROP */ + vga_wgfx (fb_info->regs, CL_GR32, 0x0d); /* BLT ROP */ /* and finally: GO! */ - WGfx(GR31, 0x02); /* BLT Start/status */ + vga_wgfx (fb_info->regs, CL_GR31, 0x02); /* BLT Start/status */ + + DPRINTK ("EXIT\n"); } /************************************************************************** @@ -2099,70 +3423,283 @@ void clgen_RectFill (u_short x, u_short y, u_short width, u_short height, * desired pixel clock **************************************************************************/ #define abs(x) ((x)<0 ? -(x) : (x)) -static void bestclock(long freq, long *best, long *nom, - long *den, long *div, long maxfreq) +static void bestclock (long freq, long *best, long *nom, + long *den, long *div, long maxfreq) { - long n, h, d, f; - - *nom = 0; - *den = 0; - *div = 0; - - if (freq < 8000) - freq = 8000; - - if (freq > maxfreq) - freq = maxfreq; - - *best = 0; - f = freq * 10; - - for(n = 32; n < 128; n++) - { - d = (143181 * n) / f; - if ( (d >= 7) && (d <= 63) ) - { - if (d > 31) - d = (d / 2) * 2; - h = (14318 * n) / d; - if ( abs(h - freq) < abs(*best - freq) ) - { - *best = h; - *nom = n; - if (d < 32) - { - *den = d; - *div = 0; + long n, h, d, f; + + assert (best != NULL); + assert (nom != NULL); + assert (den != NULL); + assert (div != NULL); + assert (maxfreq > 0); + + *nom = 0; + *den = 0; + *div = 0; + + DPRINTK ("ENTER\n"); + + if (freq < 8000) + freq = 8000; + + if (freq > maxfreq) + freq = maxfreq; + + *best = 0; + f = freq * 10; + + for (n = 32; n < 128; n++) { + d = (143181 * n) / f; + if ((d >= 7) && (d <= 63)) { + if (d > 31) + d = (d / 2) * 2; + h = (14318 * n) / d; + if (abs (h - freq) < abs (*best - freq)) { + *best = h; + *nom = n; + if (d < 32) { + *den = d; + *div = 0; + } else { + *den = d / 2; + *div = 1; + } + } } - else - { - *den = d / 2; - *div = 1; + d = ((143181 * n) + f - 1) / f; + if ((d >= 7) && (d <= 63)) { + if (d > 31) + d = (d / 2) * 2; + h = (14318 * n) / d; + if (abs (h - freq) < abs (*best - freq)) { + *best = h; + *nom = n; + if (d < 32) { + *den = d; + *div = 0; + } else { + *den = d / 2; + *div = 1; + } + } } - } - } - d = ( (143181 * n)+f-1) / f; - if ( (d >= 7) && (d <= 63) ) - { - if (d > 31) - d = (d / 2) * 2; - h = (14318 * n) / d; - if ( abs(h - freq) < abs(*best - freq) ) - { - *best = h; - *nom = n; - if (d < 32) - { - *den = d; - *div = 0; - } - else - { - *den = d / 2; - *div = 1; - } - } - } - } + } + + DPRINTK ("Best possible values for given frequency:\n"); + DPRINTK (" best: %ld kHz nom: %ld den: %ld div: %ld\n", + freq, *nom, *den, *div); + + DPRINTK ("EXIT\n"); } + + + + + +/* ------------------------------------------------------------------------- + * + * debugging functions + * + * ------------------------------------------------------------------------- + */ + +#ifdef CLGEN_DEBUG + +/** + * clgen_dbg_print_byte + * @name: name associated with byte value to be displayed + * @val: byte value to be displayed + * + * DESCRIPTION: + * Display an indented string, along with a hexidecimal byte value, and + * its decoded bits. Bits 7 through 0 are listed in left-to-right + * order. + */ + +static +void clgen_dbg_print_byte (const char *name, unsigned char val) +{ + DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n", + name, val, + val & 0x80 ? '1' : '0', + val & 0x40 ? '1' : '0', + val & 0x20 ? '1' : '0', + val & 0x10 ? '1' : '0', + val & 0x08 ? '1' : '0', + val & 0x04 ? '1' : '0', + val & 0x02 ? '1' : '0', + val & 0x01 ? '1' : '0'); +} + + + +/** + * clgen_dbg_print_regs + * @base: If using newmmio, the newmmio base address, otherwise %NULL + * @reg_class: type of registers to read: %CRT, or %SEQ + * + * DESCRIPTION: + * Dumps the given list of VGA CRTC registers. If @base is %NULL, + * old-style I/O ports are queried for information, otherwise MMIO is + * used at the given @base address to query the information. + */ + +static +void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...) +{ + va_list list; + unsigned char val = 0; + unsigned reg; + char *name; + + va_start (list, reg_class); + + name = va_arg (list, char *); + while (name != NULL) { + reg = va_arg (list, int); + + switch (reg_class) { + case CRT: + val = vga_rcrt (regbase, (unsigned char) reg); + break; + case SEQ: + val = vga_rseq (regbase, (unsigned char) reg); + break; + default: + /* should never occur */ + assert (FALSE); + break; + } + + clgen_dbg_print_byte (name, val); + + name = va_arg (list, char *); + } + + va_end (list); +} + + + + + +/** + * clgen_dump + * @clgeninfo: + * + * DESCRIPTION: + */ + +static +void clgen_dump (void) +{ + clgen_dbg_reg_dump (NULL); +} + + + +/** + * clgen_dbg_reg_dump + * @base: If using newmmio, the newmmio base address, otherwise %NULL + * + * DESCRIPTION: + * Dumps a list of interesting VGA and CLGEN registers. If @base is %NULL, + * old-style I/O ports are queried for information, otherwise MMIO is + * used at the given @base address to query the information. + */ + +static +void clgen_dbg_reg_dump (caddr_t regbase) +{ + DPRINTK ("CLGEN VGA CRTC register dump:\n"); + + clgen_dbg_print_regs (regbase, CRT, + "CR00", 0x00, + "CR01", 0x01, + "CR02", 0x02, + "CR03", 0x03, + "CR04", 0x04, + "CR05", 0x05, + "CR06", 0x06, + "CR07", 0x07, + "CR08", 0x08, + "CR09", 0x09, + "CR0A", 0x0A, + "CR0B", 0x0B, + "CR0C", 0x0C, + "CR0D", 0x0D, + "CR0E", 0x0E, + "CR0F", 0x0F, + "CR10", 0x10, + "CR11", 0x11, + "CR12", 0x12, + "CR13", 0x13, + "CR14", 0x14, + "CR15", 0x15, + "CR16", 0x16, + "CR17", 0x17, + "CR18", 0x18, + "CR22", 0x22, + "CR24", 0x24, + "CR26", 0x26, + "CR2D", 0x2D, + "CR2E", 0x2E, + "CR2F", 0x2F, + "CR30", 0x30, + "CR31", 0x31, + "CR32", 0x32, + "CR33", 0x33, + "CR34", 0x34, + "CR35", 0x35, + "CR36", 0x36, + "CR37", 0x37, + "CR38", 0x38, + "CR39", 0x39, + "CR3A", 0x3A, + "CR3B", 0x3B, + "CR3C", 0x3C, + "CR3D", 0x3D, + "CR3E", 0x3E, + "CR3F", 0x3F, + NULL); + + DPRINTK ("\n"); + + DPRINTK ("CLGEN VGA SEQ register dump:\n"); + + clgen_dbg_print_regs (regbase, SEQ, + "SR00", 0x00, + "SR01", 0x01, + "SR02", 0x02, + "SR03", 0x03, + "SR04", 0x04, + "SR08", 0x08, + "SR09", 0x09, + "SR0A", 0x0A, + "SR0B", 0x0B, + "SR0D", 0x0D, + "SR10", 0x10, + "SR11", 0x11, + "SR12", 0x12, + "SR13", 0x13, + "SR14", 0x14, + "SR15", 0x15, + "SR16", 0x16, + "SR17", 0x17, + "SR18", 0x18, + "SR19", 0x19, + "SR1A", 0x1A, + "SR1B", 0x1B, + "SR1C", 0x1C, + "SR1D", 0x1D, + "SR1E", 0x1E, + "SR1F", 0x1F, + NULL); + + DPRINTK ("\n"); +} + + +#endif /* CLGEN_DEBUG */ diff --git a/drivers/video/clgenfb.h b/drivers/video/clgenfb.h index 3f66ec294..b2776b6c8 100644 --- a/drivers/video/clgenfb.h +++ b/drivers/video/clgenfb.h @@ -1,175 +1,122 @@ +/* + * drivers/video/clgenfb.h - Cirrus Logic chipset constants + * + * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * + * Original clgenfb author: Frank Neumann + * + * Based on retz3fb.c and clgen.c: + * Copyright (C) 1997 Jes Sorensen + * Copyright (C) 1996 Frank Neumann + * + *************************************************************** + * + * Format this code with GNU indent '-kr -i8 -pcs' options. + * + * 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. + * + */ -/* definitions for Piccolo/SD64 VGA controller chip */ -/* these definitions might most of the time also work */ -/* for other CL-GD542x/543x based boards.. */ +#ifndef __CLGENFB_H__ +#define __CLGENFB_H__ + +/* OLD COMMENT: definitions for Piccolo/SD64 VGA controller chip */ +/* OLD COMMENT: these definitions might most of the time also work */ +/* OLD COMMENT: for other CL-GD542x/543x based boards.. */ /*** External/General Registers ***/ -#define POS102 0x102 /* POS102 register */ -#define VSSM 0x46e8 /* Adapter Sleep */ -#define VSSM2 0x3c3 /* Motherboard Sleep */ -#define MISC_W 0x3c2 /* Miscellaneous Output register, write */ -#define MISC_R 0x3cc /* Miscellaneous Output register, read */ -#define FC_W 0x3da /* Feature Control Register, write (color) */ -#define FC_R 0x3ca /* Feature Control Register, read */ -#define FEAT 0x3c2 /* Input Status Register 0 */ -#define STAT 0x3da /* Input Status Register 1, read-only */ -#define M_3C6 0x3c6 /* Pixel Mask */ -#define M_3C7_W 0x3c7 /* Pixel Address Read Mode (write) */ -#define M_3C7_R 0x3c7 /* DAC State (read-only */ -#define M_3C8 0x3c8 /* Pixel Address Write Mode */ -#define M_3C9 0x3c9 /* Pixel Data */ +#define CL_POS102 0x102 /* POS102 register */ +#define CL_VSSM 0x46e8 /* Adapter Sleep */ +#define CL_VSSM2 0x3c3 /* Motherboard Sleep */ /*** VGA Sequencer Registers ***/ -#define SEQRX 0x3c4 /* Sequencer Index */ -#define SEQR0 0x0 /* Reset */ -#define SEQR1 0x1 /* Clocking Mode */ -#define SEQR2 0x2 /* Plane Mask / Write Pixel Extension */ -#define SEQR3 0x3 /* Character Map Select */ -#define SEQR4 0x4 /* Memory Mode */ +#define CL_SEQR0 0x0 /* Reset */ /* the following are from the "extension registers" group */ -#define SEQR6 0x6 /* Unlock ALL Extensions */ -#define SEQR7 0x7 /* Extended Sequencer Mode */ -#define SEQR8 0x8 /* EEPROM Control */ -#define SEQR9 0x9 /* Scratch Pad 0 (do not access!) */ -#define SEQRA 0xa /* Scratch Pad 1 (do not access!) */ -#define SEQRB 0xb /* VCLK0 Numerator */ -#define SEQRC 0xc /* VCLK1 Numerator */ -#define SEQRD 0xd /* VCLK2 Numerator */ -#define SEQRE 0xe /* VCLK3 Numerator */ -#define SEQRF 0xf /* DRAM Control */ -#define SEQR10 0x10 /* Graphics Cursor X Position */ -#define SEQR11 0x11 /* Graphics Cursor Y Position */ -#define SEQR12 0x12 /* Graphics Cursor Attributes */ -#define SEQR13 0x13 /* Graphics Cursor Pattern Address Offset */ -#define SEQR14 0x14 /* Scratch Pad 2 (CL-GD5426/'28 Only) (do not access!) */ -#define SEQR15 0x15 /* Scratch Pad 3 (CL-GD5426/'28 Only) (do not access!) */ -#define SEQR16 0x16 /* Performance Tuning (CL-GD5424/'26/'28 Only) */ -#define SEQR17 0x17 /* Configuration ReadBack and Extended Control (CL-GF5428 Only) */ -#define SEQR18 0x18 /* Signature Generator Control (Not CL-GD5420) */ -#define SEQR19 0x19 /* Signature Generator Result Low Byte (Not CL-GD5420) */ -#define SEQR1A 0x1a /* Signature Generator Result High Byte (Not CL-GD5420) */ -#define SEQR1B 0x1b /* VCLK0 Denominator and Post-Scalar Value */ -#define SEQR1C 0x1c /* VCLK1 Denominator and Post-Scalar Value */ -#define SEQR1D 0x1d /* VCLK2 Denominator and Post-Scalar Value */ -#define SEQR1E 0x1e /* VCLK3 Denominator and Post-Scalar Value */ -#define SEQR1F 0x1f /* BIOS ROM write enable and MCLK Select */ +#define CL_SEQR6 0x6 /* Unlock ALL Extensions */ +#define CL_SEQR7 0x7 /* Extended Sequencer Mode */ +#define CL_SEQR8 0x8 /* EEPROM Control */ +#define CL_SEQR9 0x9 /* Scratch Pad 0 (do not access!) */ +#define CL_SEQRA 0xa /* Scratch Pad 1 (do not access!) */ +#define CL_SEQRB 0xb /* VCLK0 Numerator */ +#define CL_SEQRC 0xc /* VCLK1 Numerator */ +#define CL_SEQRD 0xd /* VCLK2 Numerator */ +#define CL_SEQRE 0xe /* VCLK3 Numerator */ +#define CL_SEQRF 0xf /* DRAM Control */ +#define CL_SEQR10 0x10 /* Graphics Cursor X Position */ +#define CL_SEQR11 0x11 /* Graphics Cursor Y Position */ +#define CL_SEQR12 0x12 /* Graphics Cursor Attributes */ +#define CL_SEQR13 0x13 /* Graphics Cursor Pattern Address Offset */ +#define CL_SEQR14 0x14 /* Scratch Pad 2 (CL-GD5426/'28 Only) (do not access!) */ +#define CL_SEQR15 0x15 /* Scratch Pad 3 (CL-GD5426/'28 Only) (do not access!) */ +#define CL_SEQR16 0x16 /* Performance Tuning (CL-GD5424/'26/'28 Only) */ +#define CL_SEQR17 0x17 /* Configuration ReadBack and Extended Control (CL-GF5428 Only) */ +#define CL_SEQR18 0x18 /* Signature Generator Control (Not CL-GD5420) */ +#define CL_SEQR19 0x19 /* Signature Generator Result Low Byte (Not CL-GD5420) */ +#define CL_SEQR1A 0x1a /* Signature Generator Result High Byte (Not CL-GD5420) */ +#define CL_SEQR1B 0x1b /* VCLK0 Denominator and Post-Scalar Value */ +#define CL_SEQR1C 0x1c /* VCLK1 Denominator and Post-Scalar Value */ +#define CL_SEQR1D 0x1d /* VCLK2 Denominator and Post-Scalar Value */ +#define CL_SEQR1E 0x1e /* VCLK3 Denominator and Post-Scalar Value */ +#define CL_SEQR1F 0x1f /* BIOS ROM write enable and MCLK Select */ /*** CRT Controller Registers ***/ -#define CRTX 0x3d4 /* CRTC Index */ -#define CRT0 0x0 /* Horizontal Total */ -#define CRT1 0x1 /* Horizontal Display End */ -#define CRT2 0x2 /* Horizontal Blanking Start */ -#define CRT3 0x3 /* Horizontal Blabking End */ -#define CRT4 0x4 /* Horizontal Sync Start */ -#define CRT5 0x5 /* Horizontal Sync End */ -#define CRT6 0x6 /* Vertical Total */ -#define CRT7 0x7 /* Overflow */ -#define CRT8 0x8 /* Screen A Preset Row Scan */ -#define CRT9 0x9 /* Character Cell Height */ -#define CRTA 0xa /* Text Cursor Start */ -#define CRTB 0xb /* Text Cursor End */ -#define CRTC 0xc /* Screen Start Address High */ -#define CRTD 0xd /* Screen Start Address Low */ -#define CRTE 0xe /* Text Cursor Location High */ -#define CRTF 0xf /* Text Cursor Location Low */ -#define CRT10 0x10 /* Vertical Sync Start */ -#define CRT11 0x11 /* Vertical Sync End */ -#define CRT12 0x12 /* Vertical Display End */ -#define CRT13 0x13 /* Offset */ -#define CRT14 0x14 /* Underline Row Scan */ -#define CRT15 0x15 /* Vertical Blanking Start */ -#define CRT16 0x16 /* Vertical Blanking End */ -#define CRT17 0x17 /* Mode Control */ -#define CRT18 0x18 /* Line Compare */ -#define CRT22 0x22 /* Graphics Data Latches ReadBack */ -#define CRT24 0x24 /* Attribute Controller Toggle ReadBack */ -#define CRT26 0x26 /* Attribute Controller Index ReadBack */ +#define CL_CRT22 0x22 /* Graphics Data Latches ReadBack */ +#define CL_CRT24 0x24 /* Attribute Controller Toggle ReadBack */ +#define CL_CRT26 0x26 /* Attribute Controller Index ReadBack */ /* the following are from the "extension registers" group */ -#define CRT19 0x19 /* Interlace End */ -#define CRT1A 0x1a /* Interlace Control */ -#define CRT1B 0x1b /* Extended Display Controls */ -#define CRT1C 0x1c /* Sync adjust and genlock register */ -#define CRT1D 0x1d /* Overlay Extended Control register */ -#define CRT25 0x25 /* Part Status Register */ -#define CRT27 0x27 /* ID Register */ -#define CRT51 0x51 /* P4 disable "flicker fixer" */ +#define CL_CRT19 0x19 /* Interlace End */ +#define CL_CRT1A 0x1a /* Interlace Control */ +#define CL_CRT1B 0x1b /* Extended Display Controls */ +#define CL_CRT1C 0x1c /* Sync adjust and genlock register */ +#define CL_CRT1D 0x1d /* Overlay Extended Control register */ +#define CL_CRT25 0x25 /* Part Status Register */ +#define CL_CRT27 0x27 /* ID Register */ +#define CL_CRT51 0x51 /* P4 disable "flicker fixer" */ /*** Graphics Controller Registers ***/ -#define GRX 0x3ce /* Graphics Controller Index */ -#define GR0 0x0 /* Set/Reset, Write Mode 5 Background Extension */ -#define GR1 0x1 /* Set/Reset Enable, Write Mode 4, 5 Foreground Ext. */ -#define GR2 0x2 /* Color Compare */ -#define GR3 0x3 /* Data Rotate */ -#define GR4 0x4 /* Read Map Select */ -#define GR5 0x5 /* Mode */ -#define GR6 0x6 /* Miscellaneous */ -#define GR7 0x7 /* Color Don't Care */ -#define GR8 0x8 /* Bit Mask */ /* the following are from the "extension registers" group */ -#define GR9 0x9 /* Offset Register 0 */ -#define GRA 0xa /* Offset Register 1 */ -#define GRB 0xb /* Graphics Controller Mode Extensions */ -#define GRC 0xc /* Color Key (CL-GD5424/'26/'28 Only) */ -#define GRD 0xd /* Color Key Mask (CL-GD5424/'26/'28 Only) */ -#define GRE 0xe /* Miscellaneous Control (Cl-GD5428 Only) */ -#define GRF 0xf /* Display Compression Control register */ -#define GR10 0x10 /* 16-bit Pixel BG Color High Byte (Not CL-GD5420) */ -#define GR11 0x11 /* 16-bit Pixel FG Color High Byte (Not CL-GD5420) */ -#define GR12 0x12 /* Background Color Byte 2 Register */ -#define GR13 0x13 /* Foreground Color Byte 2 Register */ -#define GR14 0x14 /* Background Color Byte 3 Register */ -#define GR15 0x15 /* Foreground Color Byte 3 Register */ +#define CL_GR9 0x9 /* Offset Register 0 */ +#define CL_GRA 0xa /* Offset Register 1 */ +#define CL_GRB 0xb /* Graphics Controller Mode Extensions */ +#define CL_GRC 0xc /* Color Key (CL-GD5424/'26/'28 Only) */ +#define CL_GRD 0xd /* Color Key Mask (CL-GD5424/'26/'28 Only) */ +#define CL_GRE 0xe /* Miscellaneous Control (Cl-GD5428 Only) */ +#define CL_GRF 0xf /* Display Compression Control register */ +#define CL_GR10 0x10 /* 16-bit Pixel BG Color High Byte (Not CL-GD5420) */ +#define CL_GR11 0x11 /* 16-bit Pixel FG Color High Byte (Not CL-GD5420) */ +#define CL_GR12 0x12 /* Background Color Byte 2 Register */ +#define CL_GR13 0x13 /* Foreground Color Byte 2 Register */ +#define CL_GR14 0x14 /* Background Color Byte 3 Register */ +#define CL_GR15 0x15 /* Foreground Color Byte 3 Register */ /* the following are CL-GD5426/'28 specific blitter registers */ -#define GR20 0x20 /* BLT Width Low */ -#define GR21 0x21 /* BLT Width High */ -#define GR22 0x22 /* BLT Height Low */ -#define GR23 0x23 /* BLT Height High */ -#define GR24 0x24 /* BLT Destination Pitch Low */ -#define GR25 0x25 /* BLT Destination Pitch High */ -#define GR26 0x26 /* BLT Source Pitch Low */ -#define GR27 0x27 /* BLT Source Pitch High */ -#define GR28 0x28 /* BLT Destination Start Low */ -#define GR29 0x29 /* BLT Destination Start Mid */ -#define GR2A 0x2a /* BLT Destination Start High */ -#define GR2C 0x2c /* BLT Source Start Low */ -#define GR2D 0x2d /* BLT Source Start Mid */ -#define GR2E 0x2e /* BLT Source Start High */ -#define GR2F 0x2f /* Picasso IV Blitter compat mode..? */ -#define GR30 0x30 /* BLT Mode */ -#define GR31 0x31 /* BLT Start/Status */ -#define GR32 0x32 /* BLT Raster Operation */ -#define GR33 0x33 /* another P4 "compat" register.. */ -#define GR34 0x34 /* Transparent Color Select Low */ -#define GR35 0x35 /* Transparent Color Select High */ -#define GR38 0x38 /* Source Transparent Color Mask Low */ -#define GR39 0x39 /* Source Transparent Color Mask High */ +#define CL_GR20 0x20 /* BLT Width Low */ +#define CL_GR21 0x21 /* BLT Width High */ +#define CL_GR22 0x22 /* BLT Height Low */ +#define CL_GR23 0x23 /* BLT Height High */ +#define CL_GR24 0x24 /* BLT Destination Pitch Low */ +#define CL_GR25 0x25 /* BLT Destination Pitch High */ +#define CL_GR26 0x26 /* BLT Source Pitch Low */ +#define CL_GR27 0x27 /* BLT Source Pitch High */ +#define CL_GR28 0x28 /* BLT Destination Start Low */ +#define CL_GR29 0x29 /* BLT Destination Start Mid */ +#define CL_GR2A 0x2a /* BLT Destination Start High */ +#define CL_GR2C 0x2c /* BLT Source Start Low */ +#define CL_GR2D 0x2d /* BLT Source Start Mid */ +#define CL_GR2E 0x2e /* BLT Source Start High */ +#define CL_GR2F 0x2f /* Picasso IV Blitter compat mode..? */ +#define CL_GR30 0x30 /* BLT Mode */ +#define CL_GR31 0x31 /* BLT Start/Status */ +#define CL_GR32 0x32 /* BLT Raster Operation */ +#define CL_GR33 0x33 /* another P4 "compat" register.. */ +#define CL_GR34 0x34 /* Transparent Color Select Low */ +#define CL_GR35 0x35 /* Transparent Color Select High */ +#define CL_GR38 0x38 /* Source Transparent Color Mask Low */ +#define CL_GR39 0x39 /* Source Transparent Color Mask High */ /*** Attribute Controller Registers ***/ -#define ARX 0x3c0 /* Attribute Controller Index */ -#define AR0 0x0 /* Attribute Controller Palette Register 0 */ -#define AR1 0x1 /* Attribute Controller Palette Register 1 */ -#define AR2 0x2 /* Attribute Controller Palette Register 2 */ -#define AR3 0x3 /* Attribute Controller Palette Register 3 */ -#define AR4 0x4 /* Attribute Controller Palette Register 4 */ -#define AR5 0x5 /* Attribute Controller Palette Register 5 */ -#define AR6 0x6 /* Attribute Controller Palette Register 6 */ -#define AR7 0x7 /* Attribute Controller Palette Register 7 */ -#define AR8 0x8 /* Attribute Controller Palette Register 8 */ -#define AR9 0x9 /* Attribute Controller Palette Register 9 */ -#define ARA 0xa /* Attribute Controller Palette Register 10 */ -#define ARB 0xb /* Attribute Controller Palette Register 11 */ -#define ARC 0xc /* Attribute Controller Palette Register 12 */ -#define ARD 0xd /* Attribute Controller Palette Register 13 */ -#define ARE 0xe /* Attribute Controller Palette Register 14 */ -#define ARF 0xf /* Attribute Controller Palette Register 15 */ -#define AR10 0x10 /* Attribute Controller Mode Register */ -#define AR11 0x11 /* Overscan (Border) Color Register */ -#define AR12 0x12 /* Color Plane Enable Register */ -#define AR13 0x13 /* Pixel Panning Register */ -#define AR14 0x14 /* Color Select Register */ -#define AR33 0x33 /* The "real" Pixel Panning register (?) */ -#define AR34 0x34 /* *TEST* */ - -/*** Extension Registers ***/ -#define HDR 0x3c6 /* Hidden DAC Register (Not CL-GD5420) */ +#define CL_AR33 0x33 /* The "real" Pixel Panning register (?) */ +#define CL_AR34 0x34 /* TEST */ +#endif /* __CLGENFB_H__ */ diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 2a783fc9b..6893afbef 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -149,11 +149,11 @@ static int default_cmode = CMODE_NVRAM; /* * Exported functions */ -void control_init(void); +int control_init(void); #ifdef CONFIG_FB_OF void control_of_init(struct device_node *dp); #endif -void control_setup(char *options, int *ints); +void control_setup(char *); static int read_control_sense(struct fb_info_control *p); static inline int control_vram_reqd(int video_mode, int color_mode); @@ -185,13 +185,9 @@ static struct fb_ops controlfb_ops = { /******************** The functions for controlfb_ops ********************/ -#ifndef MODULE -__openfirmware -#endif - /********** Dummies for loading control as a module **********/ -static int control_open(struct fb_info *info, int user) +int control_open(struct fb_info *info, int user) { MOD_INC_USE_COUNT; return 0; @@ -523,7 +519,7 @@ static void set_control_clock(unsigned char *params) } -__initfunc(static void init_control(struct fb_info_control *p)) +static void __init init_control(struct fb_info_control *p) { struct fb_par_control parstruct; struct fb_par_control *par = &parstruct; @@ -660,7 +656,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro #endif /* CONFIG_FB_COMPAT_XPMAC */ } -__initfunc(void control_init(void)) +int __init control_init(void) { #ifndef CONFIG_FB_OF struct device_node *dp; @@ -669,9 +665,10 @@ __initfunc(void control_init(void)) if (dp != 0) control_of_init(dp); #endif /* CONFIG_FB_OF */ + return 0; } -__initfunc(void control_of_init(struct device_node *dp)) +void __init control_of_init(struct device_node *dp) { struct fb_info_control *p; unsigned long addr, size; @@ -720,9 +717,11 @@ __initfunc(void control_of_init(struct device_node *dp)) p->total_vram = (bank1 + bank2) * 0x200000; /* If we don't have bank 1 installed, we hope we have bank 2 :-) */ p->control_use_bank2 = !bank1; - if (p->control_use_bank2) + if (p->control_use_bank2) { p->frame_buffer += 0x600000; - + p->frame_buffer_phys += 0x600000; + } + init_control(p); } @@ -998,7 +997,7 @@ static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeni { memset(fix, 0, sizeof(*fix)); strcpy(fix->id, "control"); - fix->mmio_start = (char *)p->control_regs_phys; + fix->mmio_start = p->control_regs_phys; fix->mmio_len = sizeof(struct control_regs); fix->type = FB_TYPE_PACKED_PIXELS; @@ -1010,7 +1009,7 @@ static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeni fix->xpanstep = 0; */ - fix->smem_start = (void *)(p->frame_buffer_phys + fix->smem_start = (p->frame_buffer_phys + control_reg_init[par->vmode-1]->offset[par->cmode]); fix->smem_len = p->total_vram - control_reg_init[par->vmode-1]->offset[par->cmode]; fix->visual = (par->cmode == CMODE_8) ? @@ -1152,7 +1151,7 @@ static void control_init_info(struct fb_info *info, struct fb_info_control *p) } /* Parse user speficied options (`video=controlfb:') */ -__initfunc(void control_setup(char *options, int *ints)) +void __init control_setup(char *options) { char *this_opt; diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c index 81421a7ff..e2fefe0f4 100644 --- a/drivers/video/creatorfb.c +++ b/drivers/video/creatorfb.c @@ -1,4 +1,4 @@ -/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $ +/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -633,11 +633,17 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb) fbc->fg = fb->s.ffb.fg_cache; fbc->bg = fb->s.ffb.bg_cache; FFBWait(fbc); -} +} + +static int __init ffb_rasterimg (struct fb_info *info, int start) +{ + ffb_switch_from_graph (sbusfbinfo(info)); + return 0; +} static char idstring[60] __initdata = { 0 }; -__initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) +char __init *creatorfb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; @@ -647,6 +653,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) int i, afb = 0; unsigned int btype; char name[64]; + struct fb_ops *fbops; if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0) return NULL; @@ -656,6 +663,13 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) return NULL; memset(disp->dispsw_data, 0, 16 * sizeof(u32)); + fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); + if (!fbops) return NULL; + + *fbops = *fb->info.fbops; + fbops->fb_rasterimg = ffb_rasterimg; + fb->info.fbops = fbops; + prom_getstring(fb->prom_node, "name", name, sizeof(name)); if (!strcmp(name, "SUNW,afb")) afb = 1; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index d342304a3..cedb41c2a 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -631,13 +631,15 @@ static void cyber2000fb_set_timing(struct fb_var_screeninfo *var) cyber2000_outw(width, 0xbf218); cyber2000_outb(b, 0xbf01c); -{ int j; +#if 0 +{ int j; i = 0; printk(KERN_DEBUG); for (j = 0; j < 19; j++) printk("%2d ", j); printk("\n"KERN_DEBUG); for (j = 0; j < 19; j++) printk("%02X ", crtc[j]); printk("\n"KERN_DEBUG); for (j = 0; j < 18; j++) printk("%02X ", cyber2000_res[i].crtc_regs[j]); printk("%02X\n", cyber2000_res[i].crtc_ofl); } +#endif } static inline void @@ -765,9 +767,9 @@ cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con, else display = &global_disp; - fix->smem_start = (char *)current_par.screen_base_p; + fix->smem_start = current_par.screen_base_p; fix->smem_len = current_par.screen_size; - fix->mmio_start = (char *)current_par.regs_base_p; + fix->mmio_start = current_par.regs_base_p; fix->mmio_len = 0x000c0000; fix->type = display->type; fix->type_aux = display->type_aux; @@ -1018,8 +1020,9 @@ static void cyber2000fb_blank(int blank, struct fb_info *fb_info) } } -__initfunc(void cyber2000fb_setup(char *options, int *ints)) +int __init cyber2000fb_setup(char *options) { + return 0; } static struct fb_ops cyber2000fb_ops = @@ -1035,8 +1038,8 @@ static struct fb_ops cyber2000fb_ops = cyber2000fb_ioctl }; -__initfunc(static void -cyber2000fb_init_fbinfo(void)) +static void __init +cyber2000fb_init_fbinfo(void) { static int first = 1; @@ -1138,16 +1141,28 @@ cyber2000fb_init_fbinfo(void)) /* * Initialization */ -__initfunc(void cyber2000fb_init(void)) +int __init cyber2000fb_init(void) { struct pci_dev *dev; u_int h_sync, v_sync; + u_long base_p, base_v; dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL); if (!dev) - return; + return -ENXIO; + + /* this should be done by PCI generic code */ + base_p = 0x80000000 + dev->resource[0].start; + + /* + * This should be ioremap'd, thus: + * + * base_v = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1); + */ + base_v = (u_long)bus_to_virt(dev->resource[0].start); - CyberRegs = bus_to_virt(dev->base_address[0]) + 0x00800000;/*FIXME*/ + /*FIXME*/ + CyberRegs = base_v + 0x00800000; cyber2000_outb(0x18, 0x46e8); cyber2000_outb(0x01, 0x102); @@ -1156,10 +1171,10 @@ __initfunc(void cyber2000fb_init(void)) cyber2000fb_init_fbinfo(); current_par.currcon = -1; - current_par.screen_base_p = 0x80000000 + dev->base_address[0]; - current_par.screen_base = (u_int)bus_to_virt(dev->base_address[0]); + current_par.screen_base_p = base_p; + current_par.screen_base = base_v; current_par.screen_size = 0x00200000; - current_par.regs_base_p = 0x80800000 + dev->base_address[0]; + current_par.regs_base_p = base_p + 0x00800000; cyber2000fb_set_var(&init_var, -1, &fb_info); @@ -1175,18 +1190,18 @@ __initfunc(void cyber2000fb_init(void)) h_sync / 1000, h_sync % 1000, v_sync); if (register_framebuffer(&fb_info) < 0) - return; + return -EINVAL; MOD_INC_USE_COUNT; /* TODO: This driver cannot be unloaded yet */ + return 0; } #ifdef MODULE -int init_module(void) +int __init init_module(void) { - cyber2000fb_init(); - return 0; + return cyber2000fb_init(); } void cleanup_module(void) diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index 6882ebfb0..7e4aea83f 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -109,7 +109,10 @@ static void cv64_dump(void); #define arraysize(x) (sizeof(x)/sizeof(*(x))) -#define wb_64(reg,dat) (*((unsigned char volatile *)CyberRegs + reg) = dat) +#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) +#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) + +#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat) struct cyberfb_par { struct fb_var_screeninfo var; @@ -129,60 +132,32 @@ static struct fb_info fb_info; /* -* Switch for Chipset Independency -*/ - -static struct fb_hwswitch { - -/* Initialisation */ - -int (*init)(void); - -/* Display Control */ - -int (*encode_fix)(struct fb_fix_screeninfo *fix, struct cyberfb_par *par); -int (*decode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par); -int (*encode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par); -int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *info); -int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); -void (*blank)(int blank); -} *fbhw; - - -/* -* Frame Buffer Name -*/ + * Frame Buffer Name + */ static char cyberfb_name[16] = "Cybervision"; /* -* Cybervision Graphics Board -*/ + * CyberVision Graphics Board + */ static unsigned char Cyber_colour_table [256][3]; -static unsigned long CyberMem; static unsigned long CyberSize; -static volatile char *CyberRegs; +static volatile unsigned char *CyberBase; +static volatile unsigned char *CyberMem; +static volatile unsigned char *CyberRegs; static unsigned long CyberMem_phys; static unsigned long CyberRegs_phys; -/* From cvision.c for cvision_core.c */ -static unsigned long cv64_mem; -static unsigned long cv64_fbmem; -static volatile char *cv64_regs; -static unsigned long cv64_size; -#if 0 -static int cvision_custom_mode = 0; -static int hbs, hbe, hss, hse, ht, vbs, vbe, vss, vse, vt; -#endif /* -* Predefined Video Modes -*/ + * Predefined Video Modes + */ -static struct fb_videomode cyberfb_predefined[] __initdata = { +static struct { + const char *name; + struct fb_var_screeninfo var; +} cyberfb_predefined[] __initdata = { { "640x480-8", { /* Default 8 BPP mode (cyber8) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, @@ -251,19 +226,20 @@ static struct fb_videomode cyberfb_predefined[] __initdata = { static int Cyberfb_inverse = 0; /* -* Some default modes -*/ + * Some default modes + */ #define CYBER8_DEFMODE (0) #define CYBER16_DEFMODE (1) static struct fb_var_screeninfo cyberfb_default; +static int cyberfb_usermode __initdata = 0; /* -* Interface used by the world -*/ + * Interface used by the world + */ -void cyberfb_setup(char *options, int *ints); +int cyberfb_setup(char *options); static int cyberfb_open(struct fb_info *info, int user); static int cyberfb_release(struct fb_info *info, int user); @@ -283,25 +259,25 @@ static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info); /* -* Interface to the low level console driver -*/ + * Interface to the low level console driver + */ -void cyberfb_init(void); +int cyberfb_init(void); static int Cyberfb_switch(int con, struct fb_info *info); static int Cyberfb_updatevar(int con, struct fb_info *info); static void Cyberfb_blank(int blank, struct fb_info *info); /* -* Text console acceleration -*/ + * Text console acceleration + */ #ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_cyber8; #endif /* -* Accelerated Functions used by the low level console driver -*/ + * Accelerated Functions used by the low level console driver + */ static void Cyber_WaitQueue(u_short fifo); static void Cyber_WaitBlit(void); @@ -310,11 +286,13 @@ static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, u_short mode); static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height, u_short mode, u_short color); +#if 0 static void Cyber_MoveCursor(u_short x, u_short y); +#endif /* -* Hardware Specific Routines -*/ + * Hardware Specific Routines + */ static int Cyber_init(void); static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, @@ -327,11 +305,10 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info); static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); -static void Cyber_blank(int blank); /* -* Internal routines -*/ + * Internal routines + */ static void cyberfb_get_par(struct cyberfb_par *par); static void cyberfb_set_par(struct cyberfb_par *par); @@ -342,7 +319,7 @@ static int get_video_mode(const char *name); /* For cvision_core.c */ static unsigned short cv64_compute_clock(unsigned long); -static int cv_has_4mb (volatile caddr_t); +static int cv_has_4mb (volatile unsigned char *); static void cv64_board_init (void); static void cv64_load_video_mode (struct fb_var_screeninfo *); @@ -351,16 +328,17 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *); /* -* Initialization -* -* Set the default video mode for this chipset. If a video mode was -* specified on the command line, it will override the default mode. -*/ + * Initialization + * + * Set the default video mode for this chipset. If a video mode was + * specified on the command line, it will override the default mode. + */ static int Cyber_init(void) { + volatile unsigned char *regs = CyberRegs; + volatile unsigned long *CursorBase; int i; - volatile u_long *CursorBase; DPRINTK("ENTER\n"); /* Init local cmap as greyscale levels */ @@ -371,27 +349,25 @@ static int Cyber_init(void) } /* Initialize the board and determine fbmem size */ - cv64_board_init (); + cv64_board_init(); #ifdef CYBERFBDEBUG DPRINTK("Register state after initing board\n"); cv64_dump(); #endif /* Clear framebuffer memory */ DPRINTK("Clear framebuffer memory\n"); - memset ((char *) cv64_fbmem, 0, cv64_size); + memset ((char *)CyberMem, 0, CyberSize); /* Disable hardware cursor */ DPRINTK("Disable HW cursor\n"); - wb_64(S3_CRTC_ADR, S3_REG_LOCK2); - wb_64(S3_CRTC_DATA, 0xa0); - wb_64(S3_CRTC_ADR, S3_HGC_MODE); - wb_64(S3_CRTC_DATA, 0x00); - wb_64(S3_CRTC_ADR, S3_HWGC_DX); - wb_64(S3_CRTC_DATA, 0x00); - wb_64(S3_CRTC_ADR, S3_HWGC_DY); - wb_64(S3_CRTC_DATA, 0x00); - - CyberSize = cv64_size; + wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2); + wb_64(regs, S3_CRTC_DATA, 0xa0); + wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE); + wb_64(regs, S3_CRTC_DATA, 0x00); + wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX); + wb_64(regs, S3_CRTC_DATA, 0x00); + wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY); + wb_64(regs, S3_CRTC_DATA, 0x00); /* Initialize hardware cursor */ DPRINTK("Init HW cursor\n"); @@ -420,9 +396,9 @@ static int Cyber_init(void) /* -* This function should fill in the `fix' structure based on the -* values in the `par' structure. -*/ + * This function should fill in the `fix' structure based on the + * values in the `par' structure. + */ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, struct cyberfb_par *par) @@ -430,9 +406,9 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, DPRINTK("ENTER\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, cyberfb_name); - fix->smem_start = (char*) CyberMem_phys; + fix->smem_start = CyberMem_phys; fix->smem_len = CyberSize; - fix->mmio_start = (char*) CyberRegs_phys; + fix->mmio_start = CyberRegs_phys; fix->mmio_len = 0x10000; fix->type = FB_TYPE_PACKED_PIXELS; @@ -546,19 +522,21 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, /* -* Set a single color register. Return != 0 for invalid regno. -*/ + * Set a single color register. Return != 0 for invalid regno. + */ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { + volatile unsigned char *regs = CyberRegs; + /*DPRINTK("ENTER\n");*/ if (regno > 255) { DPRINTK("EXIT - Register # > 255\n"); return (1); } - wb_64(0x3c8, (unsigned char) regno); + wb_64(regs, 0x3c8, (unsigned char) regno); red >>= 10; green >>= 10; @@ -568,9 +546,9 @@ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, Cyber_colour_table [regno][1] = green; Cyber_colour_table [regno][2] = blue; - wb_64(0x3c9, red); - wb_64(0x3c9, green); - wb_64(0x3c9, blue); + wb_64(regs, 0x3c9, red); + wb_64(regs, 0x3c9, green); + wb_64(regs, 0x3c9, blue); /*DPRINTK("EXIT\n");*/ return (0); @@ -611,29 +589,30 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, * 0 = restore fb cmap from local cmap */ -void Cyber_blank(int blank) +void Cyberfb_blank(int blank, struct fb_info *info) { + volatile unsigned char *regs = CyberRegs; int i; DPRINTK("ENTER\n"); #if 0 /* Blank by turning gfx off */ - gfx_on_off (1, cv64_regs); + gfx_on_off (1, regs); #else if (blank) { for (i = 0; i < 256; i++) { - wb_64(0x3c8, (unsigned char) i); + wb_64(regs, 0x3c8, (unsigned char) i); /* ARB Pale red to detect this blanking method */ - wb_64(0x3c9, 48); - wb_64(0x3c9, 0); - wb_64(0x3c9, 0); + wb_64(regs, 0x3c9, 48); + wb_64(regs, 0x3c9, 0); + wb_64(regs, 0x3c9, 0); } } else { for (i = 0; i < 256; i++) { - wb_64(0x3c8, (unsigned char) i); - wb_64(0x3c9, Cyber_colour_table[i][0]); - wb_64(0x3c9, Cyber_colour_table[i][1]); - wb_64(0x3c9, Cyber_colour_table[i][2]); + wb_64(regs, 0x3c8, (unsigned char) i); + wb_64(regs, 0x3c9, Cyber_colour_table[i][0]); + wb_64(regs, 0x3c9, Cyber_colour_table[i][1]); + wb_64(regs, 0x3c9, Cyber_colour_table[i][2]); } } #endif @@ -646,13 +625,12 @@ void Cyber_blank(int blank) */ static void Cyber_WaitQueue (u_short fifo) { - u_short status; + unsigned short status; DPRINTK("ENTER\n"); do { status = *((u_short volatile *)(CyberRegs + S3_GP_STAT)); - } - while (status & fifo); + } while (status & fifo); DPRINTK("EXIT\n"); } @@ -661,13 +639,12 @@ static void Cyber_WaitQueue (u_short fifo) */ static void Cyber_WaitBlit (void) { - u_short status; + unsigned short status; DPRINTK("ENTER\n"); do { status = *((u_short volatile *)(CyberRegs + S3_GP_STAT)); - } - while (status & S3_HDW_BUSY); + } while (status & S3_HDW_BUSY); DPRINTK("EXIT\n"); } @@ -678,6 +655,7 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, u_short width, u_short height, u_short mode) { + volatile unsigned char *regs = CyberRegs; u_short blitcmd = S3_BITBLT; DPRINTK("ENTER\n"); @@ -699,19 +677,19 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, Cyber_WaitQueue (0x8000); - *((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000; - *((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0060 | mode); + *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000; + *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode); - *((u_short volatile *)(CyberRegs + S3_CUR_X)) = curx; - *((u_short volatile *)(CyberRegs + S3_CUR_Y)) = cury; + *((u_short volatile *)(regs + S3_CUR_X)) = curx; + *((u_short volatile *)(regs + S3_CUR_Y)) = cury; - *((u_short volatile *)(CyberRegs + S3_DESTX_DIASTP)) = destx; - *((u_short volatile *)(CyberRegs + S3_DESTY_AXSTP)) = desty; + *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx; + *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty; - *((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1; - *((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width - 1; + *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1; + *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1; - *((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd; + *((u_short volatile *)(regs + S3_CMD)) = blitcmd; DPRINTK("EXIT\n"); } @@ -721,56 +699,52 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, static void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height, u_short mode, u_short color) { + volatile unsigned char *regs = CyberRegs; u_short blitcmd = S3_FILLEDRECT; DPRINTK("ENTER\n"); Cyber_WaitQueue (0x8000); - *((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000; - *((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0020 | mode); + *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000; + *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode); - *((u_short volatile *)(CyberRegs + S3_MULT_MISC)) = 0xe000; - *((u_short volatile *)(CyberRegs + S3_FRGD_COLOR)) = color; + *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000; + *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color; - *((u_short volatile *)(CyberRegs + S3_CUR_X)) = x; - *((u_short volatile *)(CyberRegs + S3_CUR_Y)) = y; + *((u_short volatile *)(regs + S3_CUR_X)) = x; + *((u_short volatile *)(regs + S3_CUR_Y)) = y; - *((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1; - *((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width - 1; + *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1; + *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width - 1; - *((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd; + *((u_short volatile *)(regs + S3_CMD)) = blitcmd; DPRINTK("EXIT\n"); } + +#if 0 /************************************************************** * Move cursor to x, y */ static void Cyber_MoveCursor (u_short x, u_short y) { + volatile unsigned char *regs = CyberRegs; DPRINTK("ENTER\n"); - *(CyberRegs + S3_CRTC_ADR) = 0x39; - *(CyberRegs + S3_CRTC_DATA) = 0xa0; - - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_ORGX_H; - *(CyberRegs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8); - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_ORGX_L; - *(CyberRegs + S3_CRTC_DATA) = (char)(x & 0x00ff); - - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_ORGY_H; - *(CyberRegs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8); - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_ORGY_L; - *(CyberRegs + S3_CRTC_DATA) = (char)(y & 0x00ff); + *(regs + S3_CRTC_ADR) = 0x39; + *(regs + S3_CRTC_DATA) = 0xa0; + + *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H; + *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8); + *(regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L; + *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff); + + *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H; + *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8); + *(regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L; + *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff); DPRINTK("EXIT\n"); } - - -/* -------------------- Interfaces to hardware functions -------------------- */ - - -static struct fb_hwswitch Cyber_switch = { - Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var, - Cyber_getcolreg, Cyber_setcolreg, Cyber_blank -}; +#endif /* -------------------- Generic routines ---------------------------------- */ @@ -786,7 +760,7 @@ static void cyberfb_get_par(struct cyberfb_par *par) if (current_par_valid) { *par = current_par; } else { - fbhw->decode_var(&cyberfb_default, par); + Cyber_decode_var(&cyberfb_default, par); } DPRINTK("EXIT\n"); } @@ -819,14 +793,14 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) struct cyberfb_par par; DPRINTK("ENTER\n"); - if ((err = fbhw->decode_var(var, &par))) { + if ((err = Cyber_decode_var(var, &par))) { DPRINTK("EXIT - decode_var failed\n"); return(err); } activate = var->activate; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) cyberfb_set_par(&par); - fbhw->encode_var(var, &par); + Cyber_encode_var(var, &par); var->activate = activate; cyber_set_video(var); @@ -844,11 +818,11 @@ static void do_install_cmap(int con, struct fb_info *info) } if (fb_display[con].cmap.len) { DPRINTK("Use console cmap\n"); - fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info); + fb_set_cmap(&fb_display[con].cmap, 1, Cyber_setcolreg, info); } else { DPRINTK("Use default cmap\n"); fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), - 1, fbhw->setcolreg, info); + 1, Cyber_setcolreg, info); } DPRINTK("EXIT\n"); } @@ -889,10 +863,10 @@ static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con, if (con == -1) { cyberfb_get_par(&par); } else { - error = fbhw->decode_var(&fb_display[con].var, &par); + error = Cyber_decode_var(&fb_display[con].var, &par); } DPRINTK("EXIT\n"); - return(error ? error : fbhw->encode_fix(fix, &par)); + return(error ? error : Cyber_encode_fix(fix, &par)); } @@ -909,7 +883,7 @@ static int cyberfb_get_var(struct fb_var_screeninfo *var, int con, DPRINTK("ENTER\n"); if (con == -1) { cyberfb_get_par(&par); - error = fbhw->encode_var(var, &par); + error = Cyber_encode_var(var, &par); disp.var = *var; /* ++Andre: don't know if this is the right place */ } else { *var = fb_display[con].var; @@ -934,7 +908,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info) cyberfb_get_fix(&fix, con, info); if (con == -1) con = 0; - display->screen_base = phys_to_virt ((unsigned long) fix.smem_start); + display->screen_base = (unsigned char *)CyberMem; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1014,7 +988,7 @@ static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, DPRINTK("ENTER\n"); if (con == currcon) { /* current console? */ DPRINTK("EXIT - console is current console\n"); - return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info)); + return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info)); } else if (fb_display[con].cmap.len) { /* non default colormap? */ DPRINTK("Use console cmap\n"); fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -1048,7 +1022,7 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, } if (con == currcon) { /* current console? */ DPRINTK("EXIT - Current console\n"); - return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info)); + return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info)); } else { fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); } @@ -1066,7 +1040,7 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - return(-EINVAL); + return -EINVAL; } @@ -1077,7 +1051,7 @@ static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con, static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info) { - return(-EINVAL); + return -EINVAL; } @@ -1088,7 +1062,7 @@ static struct fb_ops cyberfb_ops = { }; -__initfunc(void cyberfb_setup(char *options, int *ints)) +int __init cyberfb_setup(char *options) { char *this_opt; DPRINTK("ENTER\n"); @@ -1097,7 +1071,7 @@ __initfunc(void cyberfb_setup(char *options, int *ints)) if (!options || !*options) { DPRINTK("EXIT - no options\n"); - return; + return 0; } for (this_opt = strtok(options, ","); this_opt; @@ -1109,8 +1083,10 @@ __initfunc(void cyberfb_setup(char *options, int *ints)) strcpy(fb_info.fontname, this_opt+5); } else if (!strcmp (this_opt, "cyber8")) { cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var; + cyberfb_usermode = 1; } else if (!strcmp (this_opt, "cyber16")) { cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var; + cyberfb_usermode = 1; } else get_video_mode(this_opt); } @@ -1119,13 +1095,14 @@ __initfunc(void cyberfb_setup(char *options, int *ints)) cyberfb_default.yres, cyberfb_default.bits_per_pixel); DPRINTK("EXIT\n"); + return 0; } /* * Initialization */ -__initfunc(void cyberfb_init(void)) +int __init cyberfb_init(void) { struct cyberfb_par par; unsigned long board_addr; @@ -1136,7 +1113,7 @@ __initfunc(void cyberfb_init(void)) if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0))) { DPRINTK("EXIT - zorro_find failed\n"); - return; + return -ENXIO; } cd = zorro_get_board (CyberKey); @@ -1146,14 +1123,12 @@ __initfunc(void cyberfb_init(void)) DPRINTK("board_addr=%08lx\n", board_addr); DPRINTK("board_size=%08lx\n", board_size); - cv64_mem = ioremap(board_addr, board_size); - cv64_regs = (volatile char *)(cv64_mem + 0x02000000); - cv64_fbmem = cv64_mem + 0x01400000; - DPRINTK("cv64_mem=%08lx cv64_regs=%08lx cv64_fbmem=%08lx\n", - cv64_mem, (long unsigned int)cv64_regs, cv64_fbmem); + CyberBase = ioremap(board_addr, board_size); + CyberRegs = CyberBase + 0x02000000; + CyberMem = CyberBase + 0x01400000; + DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n", + CyberBase, (long unsigned int)CyberRegs, CyberMem); - CyberMem = cv64_fbmem; - CyberRegs = cv64_regs; CyberMem_phys = board_addr + 0x01400000; CyberRegs_phys = CyberMem_phys + 0x00c00000; DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem, @@ -1164,8 +1139,6 @@ __initfunc(void cyberfb_init(void)) cv64_dump(); #endif - fbhw = &Cyber_switch; - strcpy(fb_info.modename, cyberfb_name); fb_info.changevar = NULL; fb_info.node = -1; @@ -1175,9 +1148,14 @@ __initfunc(void cyberfb_init(void)) fb_info.updatevar = &Cyberfb_updatevar; fb_info.blank = &Cyberfb_blank; - fbhw->init(); - fbhw->decode_var(&cyberfb_default, &par); - fbhw->encode_var(&cyberfb_default, &par); + Cyber_init(); + /* ++Andre: set cyberfb default mode */ + if (!cyberfb_usermode) { + cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var; + DPRINTK("Use default cyber8 mode\n"); + } + Cyber_decode_var(&cyberfb_default, &par); + Cyber_encode_var(&cyberfb_default, &par); do_fb_set_var(&cyberfb_default, 1); cyberfb_get_var(&fb_display[0].var, -1, &fb_info); @@ -1186,7 +1164,7 @@ __initfunc(void cyberfb_init(void)) if (register_framebuffer(&fb_info) < 0) { DPRINTK("EXIT - register_framebuffer failed\n"); - return; + return -EINVAL; } printk("fb%d: %s frame buffer device, using %ldK of video memory\n", @@ -1195,6 +1173,7 @@ __initfunc(void cyberfb_init(void)) /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; DPRINTK("EXIT\n"); + return 0; } @@ -1203,7 +1182,7 @@ static int Cyberfb_switch(int con, struct fb_info *info) DPRINTK("ENTER\n"); /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) { - fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg, + fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg, info); } @@ -1231,22 +1210,10 @@ static int Cyberfb_updatevar(int con, struct fb_info *info) /* - * Blank the display. - */ - -static void Cyberfb_blank(int blank, struct fb_info *info) -{ - DPRINTK("Enter\n"); - fbhw->blank(blank); - DPRINTK("Exit\n"); -} - - -/* * Get a Video Mode */ -__initfunc(static int get_video_mode(const char *name)) +static int __init get_video_mode(const char *name) { int i; @@ -1254,13 +1221,11 @@ __initfunc(static int get_video_mode(const char *name)) for (i = 0; i < NUM_TOTAL_MODES; i++) { if (!strcmp(name, cyberfb_predefined[i].name)) { cyberfb_default = cyberfb_predefined[i].var; + cyberfb_usermode = 1; DPRINTK("EXIT - Matched predefined mode\n"); return(i); } } - /* ++Andre: set cyberfb default mode */ - cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var; - DPRINTK("EXIT - Use default cyber8 mode\n"); return(0); } @@ -1336,8 +1301,7 @@ static struct display_switch fbcon_cyber8 = { #ifdef MODULE int init_module(void) { - cyberfb_init(); - return 0; + return cyberfb_init(); } void cleanup_module(void) @@ -1454,71 +1418,38 @@ unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */ }; /* -------------------- Hardware specific routines ------------------------- */ -#if 0 -/* ARB Generates 100 usec delay */ -inline void __cv_delay (unsigned long usecs) -{ - int k; - - for (k = 0; k < 1000; k++) { - asm volatile ("nop"); - } -} -#endif - -/* Wait while Graphics Engine is busy */ -inline void GfxBusyWait (volatile caddr_t board) -{ - int test; - DPRINTK("ENTER\n"); - - do { - test = vgar16 (board, ECR_GP_STAT); - asm volatile ("nop"); - } while (test & (1 << 9)); - DPRINTK("EXIT\n"); -} - -/* Wait for any of the 8 Trio32 FIFOs to be free */ -inline void GfxFifoWait (volatile caddr_t board) -{ - int test; - DPRINTK("ENTER\n"); - - do { - test = vgar16 (board, ECR_GP_STAT); - } while (test & 0x0f); - DPRINTK("EXIT\n"); -} /* Read Attribute Controller Register=idx */ -inline unsigned char RAttr (volatile caddr_t board, short idx) +inline unsigned char RAttr (volatile unsigned char *regs, short idx) { - vgaw (board, ACT_ADDRESS_W, idx); + wb_64 (regs, ACT_ADDRESS_W, idx); + mb(); udelay(100); - /* __cv_delay (0); */ - return (vgar (board, ACT_ADDRESS_R)); + return (rb_64(regs, ACT_ADDRESS_R)); } /* Read Sequencer Register=idx */ -inline unsigned char RSeq (volatile caddr_t board, short idx) +inline unsigned char RSeq (volatile unsigned char *regs, short idx) { - vgaw (board, SEQ_ADDRESS, idx); - return (vgar (board, SEQ_ADDRESS_R)); + wb_64 (regs, SEQ_ADDRESS, idx); + mb(); + return (rb_64(regs, SEQ_ADDRESS_R)); } /* Read CRT Controller Register=idx */ -inline unsigned char RCrt (volatile caddr_t board, short idx) +inline unsigned char RCrt (volatile unsigned char *regs, short idx) { - vgaw (board, CRT_ADDRESS, idx); - return (vgar (board, CRT_ADDRESS_R)); + wb_64 (regs, CRT_ADDRESS, idx); + mb(); + return (rb_64(regs, CRT_ADDRESS_R)); } /* Read Graphics Controller Register=idx */ -inline unsigned char RGfx (volatile caddr_t board, short idx) +inline unsigned char RGfx (volatile unsigned char *regs, short idx) { - vgaw (board, GCT_ADDRESS, idx); - return (vgar (board, GCT_ADDRESS_R)); + wb_64 (regs, GCT_ADDRESS, idx); + mb(); + return (rb_64(regs, GCT_ADDRESS_R)); } /* @@ -1526,13 +1457,13 @@ inline unsigned char RGfx (volatile caddr_t board, short idx) */ inline void cv64_write_port (unsigned short bits, - volatile unsigned char *board) + volatile unsigned char *base) { volatile unsigned char *addr; static unsigned char cvportbits = 0; /* Mirror port bits here */ DPRINTK("ENTER\n"); - addr = board + 0x40001; + addr = base + 0x40001; if (bits & 0x8000) { cvportbits |= bits & 0xff; /* Set bits */ DPRINTK("Set bits: %04x\n", bits); @@ -1542,7 +1473,7 @@ inline void cv64_write_port (unsigned short bits, cvportbits &= bits; /* Clear bits */ DPRINTK("Clear bits: %04x\n", bits); } - + *addr = cvportbits; DPRINTK("EXIT\n"); } @@ -1572,7 +1503,7 @@ inline void cvscreen (int toggle, volatile unsigned char *board) /* Control screen display */ /* toggle: 0 = on, 1 = off */ /* board = registerbase */ -inline void gfx_on_off (int toggle, volatile unsigned char *board) +inline void gfx_on_off(int toggle, volatile unsigned char *regs) { int r; DPRINTK("ENTER\n"); @@ -1581,10 +1512,10 @@ inline void gfx_on_off (int toggle, volatile unsigned char *board) toggle = toggle << 5; DPRINTK("Turn display %s\n", (toggle ? "off" : "on")); - r = (int) RSeq ((volatile caddr_t) board, SEQ_ID_CLOCKING_MODE); + r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE); r &= 0xdf; /* Set bit 5 to 0 */ - WSeq (board, SEQ_ID_CLOCKING_MODE, r | toggle); + WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle); DPRINTK("EXIT\n"); } @@ -1640,11 +1571,11 @@ static unsigned short cv64_compute_clock(unsigned long freq) return (erg); } -static int cv_has_4mb (volatile caddr_t fb) +static int cv_has_4mb (volatile unsigned char *fb) { volatile unsigned long *tr, *tw; DPRINTK("ENTER\n"); - + /* write patterns in memory and test if they can be read */ tw = (volatile unsigned long *) fb; tr = (volatile unsigned long *) (fb + 0x02000000); @@ -1655,41 +1586,42 @@ static int cv_has_4mb (volatile caddr_t fb) DPRINTK("EXIT - <4MB\n"); return (0); } - + /* upper memory region */ tw = (volatile unsigned long *) (fb + 0x00200000); tr = (volatile unsigned long *) (fb + 0x02200000); - + *tw = 0x87654321; - + if (*tr != 0x87654321) { DPRINTK("EXIT - <4MB\n"); return (0); } - + *tw = 0xAAAAAAAA; - + if (*tr != 0xAAAAAAAA) { DPRINTK("EXIT - <4MB\n"); return (0); } - + *tw = 0x55555555; - + if (*tr != 0x55555555) { DPRINTK("EXIT - <4MB\n"); return (0); } - + DPRINTK("EXIT\n"); return (1); } static void cv64_board_init (void) { + volatile unsigned char *regs = CyberRegs; int i; - unsigned char test; unsigned int clockpar; + unsigned char test; DPRINTK("ENTER\n"); @@ -1698,259 +1630,252 @@ static void cv64_board_init (void) */ /* Reset board */ for (i = 0; i < 6; i++) { - cv64_write_port (0xff, (volatile unsigned char *) cv64_mem); + cv64_write_port (0xff, CyberBase); } /* Return to operational mode */ - cv64_write_port (0x8004, (volatile unsigned char *) cv64_mem); + cv64_write_port (0x8004, CyberBase); - /* - * Generic (?) S3 chip wakeup - */ - /* Disable I/O & memory decoders, video in setup mode */ - vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x10); - /* Video responds to cmds, addrs & data */ - vgaw (cv64_regs, SREG_OPTION_SELECT, 0x1); - /* Enable I/O & memory decoders, video in operational mode */ - vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x8); - /* VGA color emulation, enable cpu access to display mem */ - vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x03); - /* Unlock S3 VGA regs */ - WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_1, 0x48); - /* Unlock system control & extension registers */ - WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_2, 0xA5); + /* + * Generic (?) S3 chip wakeup + */ + /* Disable I/O & memory decoders, video in setup mode */ + wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10); + /* Video responds to cmds, addrs & data */ + wb_64 (regs, SREG_OPTION_SELECT, 0x1); + /* Enable I/O & memory decoders, video in operational mode */ + wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8); + /* VGA color emulation, enable cpu access to display mem */ + wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03); + /* Unlock S3 VGA regs */ + WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); + /* Unlock system control & extension registers */ + WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5); /* GRF - Enable interrupts */ - /* Enable enhanced regs access, Ready cntl 0 wait states */ - test = RCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG); - test = test | 0x01; /* enable enhaced register access */ - test = test & 0xEF; /* clear bit 4, 0 wait state */ - WCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG, test); - /* - * bit 0=1: Enable enhaced mode functions - * bit 2=0: Enhanced mode 8+ bits/pixel - * bit 4=1: Enable linear addressing - * bit 5=1: Enable MMIO - */ - vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, 0x31); - /* - * bit 0=1: Color emulation - * bit 1=1: Enable CPU access to display memory - * bit 5=1: Select high 64K memory page - */ + /* Enable enhanced regs access, Ready cntl 0 wait states */ + test = RCrt (regs, CRT_ID_SYSTEM_CONFIG); + test = test | 0x01; /* enable enhanced register access */ + test = test & 0xEF; /* clear bit 4, 0 wait state */ + WCrt (regs, CRT_ID_SYSTEM_CONFIG, test); + /* + * bit 0=1: Enable enhaced mode functions + * bit 2=0: Enhanced mode 8+ bits/pixel + * bit 4=1: Enable linear addressing + * bit 5=1: Enable MMIO + */ + wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31); + /* + * bit 0=1: Color emulation + * bit 1=1: Enable CPU access to display memory + * bit 5=1: Select high 64K memory page + */ /* GRF - 0xE3 */ - vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x23); - - /* Cpu base addr */ - WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_4, 0x0); - - /* Reset. This does nothing on Trio, but standard VGA practice */ - /* WSeq (cv64_regs, SEQ_ID_RESET, 0x03); */ - /* Character clocks 8 dots wide */ - WSeq (cv64_regs, SEQ_ID_CLOCKING_MODE, 0x01); - /* Enable cpu write to all color planes */ - WSeq (cv64_regs, SEQ_ID_MAP_MASK, 0x0F); - /* Font table in 1st 8k of plane 2, font A=B disables swtich */ - WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x0); - /* Allow mem access to 256kb */ - WSeq (cv64_regs, SEQ_ID_MEMORY_MODE, 0x2); - /* Unlock S3 extensions to VGA Sequencer regs */ - WSeq (cv64_regs, SEQ_ID_UNLOCK_EXT, 0x6); - - /* Enable 4MB fast page mode */ - test = RSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL); - test = test | 1 << 6; - WSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL, test); - - /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */ - WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, 0xC0); - - /* Clear immediate clock load bit */ - test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2); - test = test & 0xDF; - /* If > 55MHz, enable 2 cycle memory write */ - if (cv64_memclk >= 55000000) { - test |= 0x80; - } - WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test); - - /* Set MCLK value */ - clockpar = cv64_compute_clock (cv64_memclk); - test = (clockpar & 0xFF00) >> 8; - WSeq (cv64_regs, SEQ_ID_MCLK_HI, test); - test = clockpar & 0xFF; - WSeq (cv64_regs, SEQ_ID_MCLK_LO, test); - - /* Chip rev specific: Not in my Trio manual!!! */ - if (RCrt (cv64_regs, CRT_ID_REVISION) == 0x10) - WSeq (cv64_regs, SEQ_ID_MORE_MAGIC, test); - - /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */ - - /* Set DCLK value */ - WSeq (cv64_regs, SEQ_ID_DCLK_HI, 0x13); - WSeq (cv64_regs, SEQ_ID_DCLK_LO, 0x41); - - /* Load DCLK (and MCLK?) immediately */ - test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2); - test = test | 0x22; - WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test); - - /* Enable loading of DCLK */ - test = vgar (cv64_regs, GREG_MISC_OUTPUT_R); - test = test | 0x0C; - vgaw (cv64_regs, GREG_MISC_OUTPUT_W, test); - - /* Turn off immediate xCLK load */ - WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, 0x2); - - /* Horizontal character clock counts */ - /* 8 LSB of 9 bits = total line - 5 */ - WCrt (cv64_regs, CRT_ID_HOR_TOTAL, 0x5F); - /* Active display line */ - WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, 0x4F); - /* Blank assertion start */ - WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, 0x50); - /* Blank assertion end */ - WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, 0x82); - /* HSYNC assertion start */ - WCrt (cv64_regs, CRT_ID_START_HOR_RETR, 0x54); - /* HSYNC assertion end */ - WCrt (cv64_regs, CRT_ID_END_HOR_RETR, 0x80); - WCrt (cv64_regs, CRT_ID_VER_TOTAL, 0xBF); - WCrt (cv64_regs, CRT_ID_OVERFLOW, 0x1F); - WCrt (cv64_regs, CRT_ID_PRESET_ROW_SCAN, 0x0); - WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE, 0x40); - WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00); - WCrt (cv64_regs, CRT_ID_CURSOR_END, 0x00); - WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00); - WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00); - WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00); - WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00); - WCrt (cv64_regs, CRT_ID_START_VER_RETR, 0x9C); - WCrt (cv64_regs, CRT_ID_END_VER_RETR, 0x0E); - WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, 0x8F); - WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, 0x50); - WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, 0x00); - WCrt (cv64_regs, CRT_ID_START_VER_BLANK, 0x96); - WCrt (cv64_regs, CRT_ID_END_VER_BLANK, 0xB9); - WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3); - WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF); - WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ - WCrt (cv64_regs, CRT_ID_MISC_1, 0x35); - WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, 0x5A); - WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, 0x70); - WCrt (cv64_regs, CRT_ID_LAW_POS_LO, 0x40); - WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF); - - WGfx (cv64_regs, GCT_ID_SET_RESET, 0x0); - WGfx (cv64_regs, GCT_ID_ENABLE_SET_RESET, 0x0); - WGfx (cv64_regs, GCT_ID_COLOR_COMPARE, 0x0); - WGfx (cv64_regs, GCT_ID_DATA_ROTATE, 0x0); - WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x0); - WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE, 0x40); - WGfx (cv64_regs, GCT_ID_MISC, 0x01); - WGfx (cv64_regs, GCT_ID_COLOR_XCARE, 0x0F); - WGfx (cv64_regs, GCT_ID_BITMASK, 0xFF); - - /* Colors for text mode */ - for (i = 0; i < 0xf; i++) - WAttr (cv64_regs, i, i); - - WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, 0x41); - WAttr (cv64_regs, ACT_ID_OVERSCAN_COLOR, 0x01); - WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA, 0x0F); - WAttr (cv64_regs, ACT_ID_HOR_PEL_PANNING, 0x0); - WAttr (cv64_regs, ACT_ID_COLOR_SELECT, 0x0); - - vgaw (cv64_regs, VDAC_MASK, 0xFF); - - *((unsigned long *) (cv64_regs + ECR_FRGD_COLOR)) = 0xFF; - *((unsigned long *) (cv64_regs + ECR_BKGD_COLOR)) = 0; - - /* Colors initially set to grayscale */ - - vgaw (cv64_regs, VDAC_ADDRESS_W, 0); - for (i = 255; i >= 0; i--) { - vgaw (cv64_regs, VDAC_DATA, i); - vgaw (cv64_regs, VDAC_DATA, i); - vgaw (cv64_regs, VDAC_DATA, i); - } + wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23); + + /* Cpu base addr */ + WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0); + + /* Reset. This does nothing on Trio, but standard VGA practice */ + /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */ + /* Character clocks 8 dots wide */ + WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01); + /* Enable cpu write to all color planes */ + WSeq (regs, SEQ_ID_MAP_MASK, 0x0F); + /* Font table in 1st 8k of plane 2, font A=B disables swtich */ + WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0); + /* Allow mem access to 256kb */ + WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2); + /* Unlock S3 extensions to VGA Sequencer regs */ + WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6); + + /* Enable 4MB fast page mode */ + test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL); + test = test | 1 << 6; + WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test); + + /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */ + WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0); + + /* Clear immediate clock load bit */ + test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2); + test = test & 0xDF; + /* If > 55MHz, enable 2 cycle memory write */ + if (cv64_memclk >= 55000000) { + test |= 0x80; + } + WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test); + + /* Set MCLK value */ + clockpar = cv64_compute_clock (cv64_memclk); + test = (clockpar & 0xFF00) >> 8; + WSeq (regs, SEQ_ID_MCLK_HI, test); + test = clockpar & 0xFF; + WSeq (regs, SEQ_ID_MCLK_LO, test); + + /* Chip rev specific: Not in my Trio manual!!! */ + if (RCrt (regs, CRT_ID_REVISION) == 0x10) + WSeq (regs, SEQ_ID_MORE_MAGIC, test); + + /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */ + + /* Set DCLK value */ + WSeq (regs, SEQ_ID_DCLK_HI, 0x13); + WSeq (regs, SEQ_ID_DCLK_LO, 0x41); + + /* Load DCLK (and MCLK?) immediately */ + test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2); + test = test | 0x22; + WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test); + + /* Enable loading of DCLK */ + test = rb_64(regs, GREG_MISC_OUTPUT_R); + test = test | 0x0C; + wb_64 (regs, GREG_MISC_OUTPUT_W, test); + + /* Turn off immediate xCLK load */ + WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2); + + /* Horizontal character clock counts */ + /* 8 LSB of 9 bits = total line - 5 */ + WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F); + /* Active display line */ + WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F); + /* Blank assertion start */ + WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50); + /* Blank assertion end */ + WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82); + /* HSYNC assertion start */ + WCrt (regs, CRT_ID_START_HOR_RETR, 0x54); + /* HSYNC assertion end */ + WCrt (regs, CRT_ID_END_HOR_RETR, 0x80); + WCrt (regs, CRT_ID_VER_TOTAL, 0xBF); + WCrt (regs, CRT_ID_OVERFLOW, 0x1F); + WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0); + WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40); + WCrt (regs, CRT_ID_CURSOR_START, 0x00); + WCrt (regs, CRT_ID_CURSOR_END, 0x00); + WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00); + WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00); + WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00); + WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00); + WCrt (regs, CRT_ID_START_VER_RETR, 0x9C); + WCrt (regs, CRT_ID_END_VER_RETR, 0x0E); + WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F); + WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50); + WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00); + WCrt (regs, CRT_ID_START_VER_BLANK, 0x96); + WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9); + WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3); + WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF); + WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */ + WCrt (regs, CRT_ID_MISC_1, 0x35); + WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A); + WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70); + WCrt (regs, CRT_ID_LAW_POS_LO, 0x40); + WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF); + + WGfx (regs, GCT_ID_SET_RESET, 0x0); + WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0); + WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0); + WGfx (regs, GCT_ID_DATA_ROTATE, 0x0); + WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0); + WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40); + WGfx (regs, GCT_ID_MISC, 0x01); + WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F); + WGfx (regs, GCT_ID_BITMASK, 0xFF); + + /* Colors for text mode */ + for (i = 0; i < 0xf; i++) + WAttr (regs, i, i); + + WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41); + WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01); + WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F); + WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0); + WAttr (regs, ACT_ID_COLOR_SELECT, 0x0); + + wb_64 (regs, VDAC_MASK, 0xFF); + + *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF; + *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0; + + /* Colors initially set to grayscale */ + + wb_64 (regs, VDAC_ADDRESS_W, 0); + for (i = 255; i >= 0; i--) { + wb_64(regs, VDAC_DATA, i); + wb_64(regs, VDAC_DATA, i); + wb_64(regs, VDAC_DATA, i); + } - /* GFx hardware cursor off */ - WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00); + /* GFx hardware cursor off */ + WCrt (regs, CRT_ID_HWGC_MODE, 0x00); - /* Set first to 4MB, so test will work */ - WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13); - /* Find "correct" size of fbmem of Z3 board */ - if (cv_has_4mb ((volatile caddr_t) cv64_fbmem)) { - cv64_size = 1024 * 1024 * 4; - WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13); - DPRINTK("4MB board\n"); - } else { - cv64_size = 1024 * 1024 * 2; - WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x12); - DPRINTK("2MB board\n"); - } - - /* Initialize graphics engine */ - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x27); - vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07); - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000); - udelay(200); - /* __cv_delay (200000); */ - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000); - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x3FFF); - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - udelay(200); - /* __cv_delay (200000); */ - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF); - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, ~0); - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xE000); - vgaw16 (cv64_regs, ECR_CURRENT_Y_POS2, 0x00); - vgaw16 (cv64_regs, ECR_CURRENT_X_POS2, 0x00); - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000); - vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, 0x00); - vgaw16 (cv64_regs, ECR_DEST_Y2__AX_STEP2, 0x00); - vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, 0x00); - vgaw16 (cv64_regs, ECR_DEST_X2__DIA_STEP2, 0x00); - vgaw16 (cv64_regs, ECR_SHORT_STROKE, 0x00); - vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x01); - - Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF); - vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x01); - vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x00); - - - /* Enable video display (set bit 5) */ + /* Set first to 4MB, so test will work */ + WCrt (regs, CRT_ID_LAW_CNTL, 0x13); + /* Find "correct" size of fbmem of Z3 board */ + if (cv_has_4mb (CyberMem)) { + CyberSize = 1024 * 1024 * 4; + WCrt (regs, CRT_ID_LAW_CNTL, 0x13); + DPRINTK("4MB board\n"); + } else { + CyberSize = 1024 * 1024 * 2; + WCrt (regs, CRT_ID_LAW_CNTL, 0x12); + DPRINTK("2MB board\n"); + } + + /* Initialize graphics engine */ + Cyber_WaitBlit(); + vgaw16 (regs, ECR_FRGD_MIX, 0x27); + vgaw16 (regs, ECR_BKGD_MIX, 0x07); + vgaw16 (regs, ECR_READ_REG_DATA, 0x1000); + udelay(200); + vgaw16 (regs, ECR_READ_REG_DATA, 0x2000); + Cyber_WaitBlit(); + vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF); + Cyber_WaitBlit(); + udelay(200); + vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF); + Cyber_WaitBlit(); + vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0); + Cyber_WaitBlit(); + vgaw16 (regs, ECR_READ_REG_DATA, 0xE000); + vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00); + vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00); + vgaw16 (regs, ECR_READ_REG_DATA, 0xA000); + vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00); + vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00); + vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00); + vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00); + vgaw16 (regs, ECR_SHORT_STROKE, 0x00); + vgaw16 (regs, ECR_DRAW_CMD, 0x01); + + Cyber_WaitBlit(); + + vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF); + vgaw16 (regs, ECR_BKGD_COLOR, 0x01); + vgaw16 (regs, ECR_FRGD_COLOR, 0x00); + + + /* Enable video display (set bit 5) */ /* ARB - Would also seem to write to AR13. * May want to use parts of WAttr to set JUST bit 5 */ - WAttr (cv64_regs, 0x33, 0); + WAttr (regs, 0x33, 0); /* GRF - function code ended here */ - /* Turn gfx on again */ - gfx_on_off (0, cv64_regs); - - /* Pass-through */ - cvscreen (0, (volatile unsigned char *) cv64_mem); + /* Turn gfx on again */ + gfx_on_off (0, regs); + + /* Pass-through */ + cvscreen (0, CyberBase); - DPRINTK("EXIT\n"); + DPRINTK("EXIT\n"); } static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) { + volatile unsigned char *regs = CyberRegs; int fx, fy; unsigned short mnr; unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT; @@ -1977,7 +1902,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) /* GRF - Disable interrupts */ - gfx_on_off (1, cv64_regs); + gfx_on_off (1, regs); switch (video_mode->bits_per_pixel) { case 15: @@ -2049,7 +1974,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) VT = yres + vfront + vsync + vback - 2; } - vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31)); + wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31)); if (TEXT) HDE = ((video_mode->xres + fx - 1) / fx) - 1; @@ -2058,15 +1983,15 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) VDE = video_mode->yres - 1; - WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00); - WCrt (cv64_regs, CRT_ID_EXT_DAC_CNTL, 0x00); + WCrt (regs, CRT_ID_HWGC_MODE, 0x00); + WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00); - WSeq (cv64_regs, SEQ_ID_MEMORY_MODE, + WSeq (regs, SEQ_ID_MEMORY_MODE, (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e); - WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x00); - WSeq (cv64_regs, SEQ_ID_MAP_MASK, + WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00); + WSeq (regs, SEQ_ID_MAP_MASK, (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF); - WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x00); + WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00); /* cv64_compute_clock accepts arguments in Hz */ /* pixclock is in ps ... convert to Hz */ @@ -2081,11 +2006,11 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) #endif mnr = cv64_compute_clock (freq); - WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); - WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF)); + WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8)); + WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF)); /* Load display parameters into board */ - WCrt (cv64_regs, CRT_ID_EXT_HOR_OVF, + WCrt (regs, CRT_ID_EXT_HOR_OVF, ((HT & 0x100) ? 0x01 : 0x00) | ((HDE & 0x100) ? 0x02 : 0x00) | ((HBS & 0x100) ? 0x04 : 0x00) | @@ -2095,7 +2020,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) (((HT-5) & 0x100) ? 0x40 : 0x00) ); - WCrt (cv64_regs, CRT_ID_EXT_VER_OVF, + WCrt (regs, CRT_ID_EXT_VER_OVF, 0x40 | ((VT & 0x400) ? 0x01 : 0x00) | ((VDE & 0x400) ? 0x02 : 0x00) | @@ -2103,18 +2028,18 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) ((VSS & 0x400) ? 0x10 : 0x00) ); - WCrt (cv64_regs, CRT_ID_HOR_TOTAL, HT); - WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, HT - 5); - WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); - WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, HBS); - WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80)); - WCrt (cv64_regs, CRT_ID_START_HOR_RETR, HSS); - WCrt (cv64_regs, CRT_ID_END_HOR_RETR, + WCrt (regs, CRT_ID_HOR_TOTAL, HT); + WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5); + WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE)); + WCrt (regs, CRT_ID_START_HOR_BLANK, HBS); + WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80)); + WCrt (regs, CRT_ID_START_HOR_RETR, HSS); + WCrt (regs, CRT_ID_END_HOR_RETR, (HSE & 0x1F) | ((HBE & 0x20) ? 0x80 : 0x00) ); - WCrt (cv64_regs, CRT_ID_VER_TOTAL, VT); - WCrt (cv64_regs, CRT_ID_OVERFLOW, + WCrt (regs, CRT_ID_VER_TOTAL, VT); + WCrt (regs, CRT_ID_OVERFLOW, 0x10 | ((VT & 0x100) ? 0x01 : 0x00) | ((VDE & 0x100) ? 0x02 : 0x00) | @@ -2124,65 +2049,65 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) ((VDE & 0x200) ? 0x40 : 0x00) | ((VSS & 0x200) ? 0x80 : 0x00) ); - WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE, + WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40 | (DBLSCAN ? 0x80 : 0x00) | ((VBS & 0x200) ? 0x20 : 0x00) | (TEXT ? ((fy - 1) & 0x1F) : 0x00) ); - WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3); + WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3); /* Text cursor */ if (TEXT) { #if 1 - WCrt (cv64_regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2); - WCrt (cv64_regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1); + WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2); + WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1); #else - WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00); - WCrt (cv64_regs, CRT_ID_CURSOR_END, fy & 0x1F); + WCrt (regs, CRT_ID_CURSOR_START, 0x00); + WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F); #endif - WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F); - WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00); - WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00); + WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F); + WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00); + WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00); } - WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00); - WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00); - WCrt (cv64_regs, CRT_ID_START_VER_RETR, VSS); - WCrt (cv64_regs, CRT_ID_END_VER_RETR, (VSE & 0x0F)); - WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, VDE); - WCrt (cv64_regs, CRT_ID_START_VER_BLANK, VBS); - WCrt (cv64_regs, CRT_ID_END_VER_BLANK, VBE); - WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF); - WCrt (cv64_regs, CRT_ID_LACE_RETR_START, HT / 2); - WCrt (cv64_regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); - WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE, + WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00); + WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00); + WCrt (regs, CRT_ID_START_VER_RETR, VSS); + WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F)); + WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE); + WCrt (regs, CRT_ID_START_VER_BLANK, VBS); + WCrt (regs, CRT_ID_END_VER_BLANK, VBE); + WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF); + WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2); + WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00)); + WGfx (regs, GCT_ID_GRAPHICS_MODE, ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40)); - WGfx (cv64_regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); - WSeq (cv64_regs, SEQ_ID_MEMORY_MODE, + WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01)); + WSeq (regs, SEQ_ID_MEMORY_MODE, ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02)); - vgaw (cv64_regs, VDAC_MASK, 0xFF); + wb_64 (regs, VDAC_MASK, 0xFF); /* Blank border */ - test = RCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2); - WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); + test = RCrt (regs, CRT_ID_BACKWAD_COMP_2); + WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20)); - sr15 = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2); + sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2); sr15 &= 0xEF; - sr18 = RSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL); + sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL); sr18 &= 0x7F; clock_mode = 0x00; cr50 = 0x00; - test = RCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2); + test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2); test &= 0xD; /* Clear roxxler byte-swapping... */ - cv64_write_port (0x0040, (volatile unsigned char *) cv64_mem); - cv64_write_port (0x0020, (volatile unsigned char *) cv64_mem); + cv64_write_port (0x0040, CyberBase); + cv64_write_port (0x0020, CyberBase); switch (video_mode->bits_per_pixel) { case 1: @@ -2201,14 +2126,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) break; case 15: - cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem); + cv64_write_port (0x8020, CyberBase); clock_mode = 0x30; HDE = video_mode->xres / 4; cr50 |= 0x10; break; case 16: - cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem); + cv64_write_port (0x8020, CyberBase); clock_mode = 0x50; HDE = video_mode->xres / 4; cr50 |= 0x10; @@ -2216,24 +2141,24 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) case 24: case 32: - cv64_write_port (0x8040, (volatile unsigned char *) cv64_mem); + cv64_write_port (0x8040, CyberBase); clock_mode = 0xD0; HDE = video_mode->xres / 2; cr50 |= 0x30; break; } - - WCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test); - WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, sr15); - WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, sr18); - WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, HDE); - WCrt (cv64_regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35)); + WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test); + WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15); + WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18); + WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE); + + WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35)); - test = RCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2); + test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2); test &= ~0x30; test |= (HDE >> 4) & 0x30; - WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2, test); + WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test); /* Set up graphics engine */ switch (video_mode->xres) { @@ -2265,17 +2190,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) break; } - WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50); + WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50); udelay(100); - /* __cv_delay (100000); */ - WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); + WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41)); udelay(100); - /* __cv_delay (100000); */ - WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA, + WAttr (regs, ACT_ID_COLOR_PLANE_ENA, (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F); udelay(100); - /* __cv_delay (100000); */ tfillm = (96 * (cv64_memclk / 1000)) / 240000; @@ -2304,10 +2226,9 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) m = 0x18; n = 0xFF; - WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m); - WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n); + WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m); + WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n); udelay(10); - /* __cv_delay (10000); */ /* Text initialization */ @@ -2317,21 +2238,21 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode) if (CONSOLE) { int i; - vgaw (cv64_regs, VDAC_ADDRESS_W, 0); + wb_64 (regs, VDAC_ADDRESS_W, 0); for (i = 0; i < 4; i++) { - vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][0]); - vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][1]); - vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][2]); + wb_64 (regs, VDAC_DATA, cvconscolors [i][0]); + wb_64 (regs, VDAC_DATA, cvconscolors [i][1]); + wb_64 (regs, VDAC_DATA, cvconscolors [i][2]); } } - WAttr (cv64_regs, 0x33, 0); + WAttr (regs, 0x33, 0); /* Turn gfx on again */ - gfx_on_off (0, (volatile unsigned char *) cv64_regs); + gfx_on_off (0, (volatile unsigned char *) regs); /* Pass-through */ - cvscreen (0, (volatile unsigned char *) cv64_mem); + cvscreen (0, CyberBase); DPRINTK("EXIT\n"); } @@ -2339,6 +2260,7 @@ DPRINTK("EXIT\n"); void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy, u_short w, u_short h) { + volatile unsigned char *regs = CyberRegs; unsigned short drawdir = 0; DPRINTK("ENTER\n"); @@ -2357,37 +2279,36 @@ void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy, } Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000); - vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x7); - vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x67); - vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x0); - vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x1); - vgaw16 (cv64_regs, ECR_BITPLANE_READ_MASK, 0x1); - vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, 0xFFF); - vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, sy); - vgaw16 (cv64_regs, ECR_CURRENT_X_POS, sx); - vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, dy); - vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, dx); - vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1); - vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1); - vgaw16 (cv64_regs, ECR_DRAW_CMD, 0xC051 | drawdir); + vgaw16 (regs, ECR_READ_REG_DATA, 0xA000); + vgaw16 (regs, ECR_BKGD_MIX, 0x7); + vgaw16 (regs, ECR_FRGD_MIX, 0x67); + vgaw16 (regs, ECR_BKGD_COLOR, 0x0); + vgaw16 (regs, ECR_FRGD_COLOR, 0x1); + vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1); + vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF); + vgaw16 (regs, ECR_CURRENT_Y_POS, sy); + vgaw16 (regs, ECR_CURRENT_X_POS, sx); + vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy); + vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx); + vgaw16 (regs, ECR_READ_REG_DATA, h - 1); + vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1); + vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir); DPRINTK("EXIT\n"); } void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg) { + volatile unsigned char *regs = CyberRegs; DPRINTK("ENTER\n"); Cyber_WaitBlit(); - /* GfxBusyWait (cv64_regs); */ - vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x0027); - vgaw16 (cv64_regs, ECR_FRGD_COLOR, bg); - vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000); - vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, dy); - vgaw16 (cv64_regs, ECR_CURRENT_X_POS, dx); - vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1); - vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1); - vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x40B1); + vgaw16 (regs, ECR_FRGD_MIX, 0x0027); + vgaw16 (regs, ECR_FRGD_COLOR, bg); + vgaw16 (regs, ECR_READ_REG_DATA, 0xA000); + vgaw16 (regs, ECR_CURRENT_Y_POS, dy); + vgaw16 (regs, ECR_CURRENT_X_POS, dx); + vgaw16 (regs, ECR_READ_REG_DATA, h - 1); + vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1); + vgaw16 (regs, ECR_DRAW_CMD, 0x40B1); DPRINTK("EXIT\n"); } @@ -2397,83 +2318,84 @@ void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg) */ static void cv64_dump (void) { + volatile unsigned char *regs = CyberRegs; DPRINTK("ENTER\n"); /* Dump the VGA setup values */ - *(CyberRegs + S3_CRTC_ADR) = 0x00; - DPRINTK("CR00 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x01; - DPRINTK("CR01 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x02; - DPRINTK("CR02 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x03; - DPRINTK("CR03 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x04; - DPRINTK("CR04 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x05; - DPRINTK("CR05 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x06; - DPRINTK("CR06 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x07; - DPRINTK("CR07 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x08; - DPRINTK("CR08 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x09; - DPRINTK("CR09 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x10; - DPRINTK("CR10 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x11; - DPRINTK("CR11 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x12; - DPRINTK("CR12 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x13; - DPRINTK("CR13 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x15; - DPRINTK("CR15 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x16; - DPRINTK("CR16 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x36; - DPRINTK("CR36 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x37; - DPRINTK("CR37 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x42; - DPRINTK("CR42 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x43; - DPRINTK("CR43 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x50; - DPRINTK("CR50 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x51; - DPRINTK("CR51 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x53; - DPRINTK("CR53 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x58; - DPRINTK("CR58 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x59; - DPRINTK("CR59 = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x5A; - DPRINTK("CR5A = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x5D; - DPRINTK("CR5D = %x\n", *(CyberRegs + S3_CRTC_DATA)); - *(CyberRegs + S3_CRTC_ADR) = 0x5E; - DPRINTK("CR5E = %x\n", *(CyberRegs + S3_CRTC_DATA)); - DPRINTK("MISC = %x\n", *(CyberRegs + GREG_MISC_OUTPUT_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x01; - DPRINTK("SR01 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x02; - DPRINTK("SR02 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x03; - DPRINTK("SR03 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x09; - DPRINTK("SR09 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x10; - DPRINTK("SR10 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x11; - DPRINTK("SR11 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x12; - DPRINTK("SR12 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x13; - DPRINTK("SR13 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); - *(CyberRegs + SEQ_ADDRESS) = 0x15; - DPRINTK("SR15 = %x\n", *(CyberRegs + SEQ_ADDRESS_R)); + *(regs + S3_CRTC_ADR) = 0x00; + DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x01; + DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x02; + DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x03; + DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x04; + DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x05; + DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x06; + DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x07; + DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x08; + DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x09; + DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x10; + DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x11; + DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x12; + DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x13; + DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x15; + DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x16; + DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x36; + DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x37; + DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x42; + DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x43; + DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x50; + DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x51; + DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x53; + DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x58; + DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x59; + DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x5A; + DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x5D; + DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA)); + *(regs + S3_CRTC_ADR) = 0x5E; + DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA)); + DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R)); + *(regs + SEQ_ADDRESS) = 0x01; + DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x02; + DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x03; + DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x09; + DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x10; + DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x11; + DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x12; + DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x13; + DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R)); + *(regs + SEQ_ADDRESS) = 0x15; + DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R)); return; } diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h index bce02a462..2acff941a 100644 --- a/drivers/video/cyberfb.h +++ b/drivers/video/cyberfb.h @@ -128,26 +128,9 @@ #define GRFBBOPset 0xf /* 1 */ -/* Read VGA register */ -#define vgar(ba, reg) (*(((volatile caddr_t)ba)+reg)) - -/* Write VGA register */ -#define vgaw(ba, reg, val) \ -*(((volatile caddr_t)ba)+reg) = ((val) & 0xff) - -/* Read 16 Bit VGA register */ -#define vgar16(ba, reg) ( *((unsigned short *) (((volatile caddr_t)ba)+reg)) ) - /* Write 16 Bit VGA register */ #define vgaw16(ba, reg, val) \ -*((unsigned short *) (((volatile caddr_t)ba)+reg)) = val - -/* Read 32 Bit VGA register */ -#define vgar32(ba, reg) ( *((unsigned long *) (((volatile caddr_t)ba)+reg)) ) - -/* Write 32 Bit VGA register */ -#define vgaw32(ba, reg, val) \ - *((unsigned long *) (((volatile caddr_t)ba)+reg)) = val +*((unsigned short *) (((volatile unsigned char *)ba)+reg)) = val /* * Defines for the used register addresses (mw) @@ -394,20 +377,20 @@ #define WGfx(ba, idx, val) \ -do { vgaw(ba, GCT_ADDRESS, idx); vgaw(ba, GCT_ADDRESS_W , val); } while (0) +do { wb_64(ba, GCT_ADDRESS, idx); wb_64(ba, GCT_ADDRESS_W , val); } while (0) #define WSeq(ba, idx, val) \ -do { vgaw(ba, SEQ_ADDRESS, idx); vgaw(ba, SEQ_ADDRESS_W , val); } while (0) +do { wb_64(ba, SEQ_ADDRESS, idx); wb_64(ba, SEQ_ADDRESS_W , val); } while (0) #define WCrt(ba, idx, val) \ -do { vgaw(ba, CRT_ADDRESS, idx); vgaw(ba, CRT_ADDRESS_W , val); } while (0) +do { wb_64(ba, CRT_ADDRESS, idx); wb_64(ba, CRT_ADDRESS_W , val); } while (0) #define WAttr(ba, idx, val) \ do { \ unsigned char tmp;\ - tmp = vgar(ba, ACT_ADDRESS_RESET);\ - vgaw(ba, ACT_ADDRESS_W, idx);\ - vgaw(ba, ACT_ADDRESS_W, val);\ + tmp = rb_64(ba, ACT_ADDRESS_RESET);\ + wb_64(ba, ACT_ADDRESS_W, idx);\ + wb_64(ba, ACT_ADDRESS_W, val);\ } while (0) #define SetTextPlane(ba, m) \ @@ -420,21 +403,17 @@ do { \ /* prototypes */ /* --------------------------------- */ -/* in cvision_core.c */ -inline void __cv_delay(unsigned long usecs); -inline void GfxBusyWait(volatile caddr_t board); -inline void GfxFifoWait(volatile caddr_t board); -inline unsigned char RAttr(volatile caddr_t board, short idx); -inline unsigned char RSeq(volatile caddr_t board, short idx); -inline unsigned char RCrt(volatile caddr_t board, short idx); -inline unsigned char RGfx(volatile caddr_t board, short idx); +inline unsigned char RAttr(volatile unsigned char * board, short idx); +inline unsigned char RSeq(volatile unsigned char * board, short idx); +inline unsigned char RCrt(volatile unsigned char * board, short idx); +inline unsigned char RGfx(volatile unsigned char * board, short idx); inline void cv64_write_port(unsigned short bits, volatile unsigned char *board); inline void cvscreen(int toggle, volatile unsigned char *board); inline void gfx_on_off(int toggle, volatile unsigned char *board); #if 0 unsigned short cv64_compute_clock(unsigned long freq); -int cv_has_4mb(volatile caddr_t fb); +int cv_has_4mb(volatile unsigned char * fb); void cv64_board_init(void); void cv64_load_video_mode(struct fb_var_screeninfo *video_mode); #endif diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index e0da396bf..c8a550eb8 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -169,7 +169,7 @@ static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"Apollo Mono"); - fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE); + fix->smem_start=FRAME_BUFFER_START+IO_BASE; fix->smem_len=FRAME_BUFFER_LEN; fix->type=FB_TYPE_PACKED_PIXELS; fix->type_aux=0; @@ -310,7 +310,7 @@ static void dnfb_set_disp(int con, struct fb_info *info) #endif } -void dnfb_init(void) +int dnfb_init(void) { fb_info.changevar=NULL; strcpy(&fb_info.modename[0],dnfb_name); @@ -333,11 +333,14 @@ void dnfb_init(void) dnfb_get_var(&disp[0].var, 0, &fb_info); dnfb_set_disp(-1, &fb_info); - if (register_framebuffer(&fb_info) < 0) - panic("unable to register apollo frame buffer\n"); + if (register_framebuffer(&fb_info) < 0) { + printk(KERN_ERR "unable to register apollo frame buffer\n"); + return -EINVAL; + } printk("fb%d: apollo frame buffer alive and kicking !\n", GET_FB_IDX(fb_info.node)); + return 0; } diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c index ea8743495..ecabee5e5 100644 --- a/drivers/video/dummycon.c +++ b/drivers/video/dummycon.c @@ -25,7 +25,7 @@ #define DUMMY_ROWS 25 #endif -__initfunc(static const char *dummycon_startup(void)) +static const char __init *dummycon_startup(void) { return "dummy device"; } diff --git a/drivers/video/fbcon-vga-planes.c b/drivers/video/fbcon-vga-planes.c index 391ceb22e..3f500e694 100644 --- a/drivers/video/fbcon-vga-planes.c +++ b/drivers/video/fbcon-vga-planes.c @@ -44,7 +44,8 @@ OR. */ static inline void rmw(volatile char *p) { - *p |= 1; + readb(p); + writeb(1, p); } /* Set the Graphics Mode Register. Bits 0-1 are write mode, bit 3 is @@ -122,8 +123,12 @@ void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx, dest = p->screen_base + dx + dy * p->line_length; src = p->screen_base + sx + sy * p->line_length; while (height--) { - for (x = 0; x < width; x++) - *dest++ = *src++; + for (x = 0; x < width; x++) { + readb(src); + writeb(0, dest); + dest++; + src++; + } src += line_ofs; dest += line_ofs; } @@ -132,8 +137,12 @@ void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx, dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length; src = p->screen_base + sx + width + (sy + height - 1) * p->line_length; while (height--) { - for (x = 0; x < width; x++) - *--dest = *--src; + for (x = 0; x < width; x++) { + dest--; + src--; + readb(src); + writeb(0, dest); + } src -= line_ofs; dest -= line_ofs; } @@ -160,8 +169,10 @@ void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int where = p->screen_base + sx + sy * p->line_length; while (height--) { - for (x = 0; x < width; x++) - *where++ = 0; + for (x = 0; x < width; x++) { + writeb(0, where); + where++; + } where += line_ofs; } } @@ -211,13 +222,13 @@ void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int y selectmask(); setmask(0xff); - *where = bg; + writeb(bg, where); rmb(); - *(volatile char*)where; /* fill latches */ + readb(where); /* fill latches */ setmode(3); wmb(); for (y = 0; y < fontheight(p); y++, where += p->line_length) - *where = cdat[y]; + writeb(cdat[y], where); wmb(); } @@ -237,9 +248,9 @@ void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsig setmask(0xff); where = p->screen_base + xx + yy * p->line_length * fontheight(p); - *where = bg; + writeb(bg, where); rmb(); - *(volatile char*)where; + readb(where); /* fill latches */ wmb(); selectmask(); for (n = 0; n < count; n++) { @@ -250,7 +261,7 @@ void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsig while (cdat < end) { outb(*cdat++, GRAPHICS_DATA_REG); wmb(); - *where = fg; + writeb(fg, where); where += p->line_length; } where += 1 - p->line_length * fontheight(p); @@ -277,9 +288,9 @@ void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsig setmask(0xff); where = p->screen_base + xx + yy * p->line_length * fontheight(p); - *where = bg; + writeb(bg, where); rmb(); - *(volatile char*)where; /* fill latches with background */ + readb(where); /* fill latches */ setmode(3); wmb(); for (n = 0; n < count; n++) { @@ -288,7 +299,7 @@ void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsig u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p); for (y = 0; y < fontheight(p); y++, cdat++) { - *where = *cdat; + writeb (*cdat, where); where += p->line_length; } where += 1 - p->line_length * fontheight(p); diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 12ab76c65..b54d0b5a4 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -215,7 +215,7 @@ static int fbcon_show_logo(void); #ifdef CONFIG_MAC /* - * On the Macintoy, there may or may not be a working VBL int. We need to prob + * On the Macintoy, there may or may not be a working VBL int. We need to probe */ static int vbl_detected = 0; @@ -246,7 +246,7 @@ static void cursor_timer_handler(unsigned long dev_addr) struct display_switch fbcon_dummy; -/* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */ +/* NOTE: fbcon cannot be __init: it may be called from take_over_console later */ static const char *fbcon_startup(void) { @@ -1951,7 +1951,7 @@ static inline unsigned safe_shift(unsigned d,int n) return n<0 ? d>>-n : d<<n; } -__initfunc(static int fbcon_show_logo( void )) +static int __init fbcon_show_logo( void ) { struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */ int depth = p->var.bits_per_pixel; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 24e7ad742..a02920395 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -44,65 +44,67 @@ * Frame buffer device initialization and setup routines */ -extern void acornfb_init(void); -extern void acornfb_setup(char *options, int *ints); -extern void amifb_init(void); -extern void amifb_setup(char *options, int *ints); -extern void atafb_init(void); -extern void atafb_setup(char *options, int *ints); -extern void macfb_init(void); -extern void macfb_setup(char *options, int *ints); -extern void cyberfb_init(void); -extern void cyberfb_setup(char *options, int *ints); -extern void pm2fb_init(void); -extern void pm2fb_setup(char *options, int *ints); -extern void cyber2000fb_init(void); -extern void cyber2000fb_setup(char *options, int *ints); -extern void retz3fb_init(void); -extern void retz3fb_setup(char *options, int *ints); -extern void clgenfb_init(void); -extern void clgenfb_setup(char *options, int *ints); -extern void vfb_init(void); -extern void vfb_setup(char *options, int *ints); -extern void offb_init(void); -extern void offb_setup(char *options, int *ints); -extern void atyfb_init(void); -extern void atyfb_setup(char *options, int *ints); -extern void igafb_init(void); -extern void igafb_setup(char *options, int *ints); -extern void imsttfb_init(void); -extern void imsttfb_setup(char *options, int *ints); -extern void dnfb_init(void); -extern void tgafb_init(void); -extern void tgafb_setup(char *options, int *ints); -extern void virgefb_init(void); -extern void virgefb_setup(char *options, int *ints); -extern void resolver_video_setup(char *options, int *ints); -extern void s3triofb_init(void); -extern void s3triofb_setup(char *options, int *ints); -extern void vesafb_init(void); -extern void vesafb_setup(char *options, int *ints); -extern void vga16fb_init(void); -extern void vga16fb_setup(char *options, int *ints); -extern void matroxfb_init(void); -extern void matroxfb_setup(char* options, int *ints); -extern void hpfb_init(void); -extern void hpfb_setup(char *options, int *ints); -extern void sbusfb_init(void); -extern void sbusfb_setup(char *options, int *ints); -extern void valkyriefb_init(void); -extern void valkyriefb_setup(char *options, int *ints); -extern void g364fb_init(void); -extern void fm2fb_init(void); -extern void fm2fb_setup(char *options, int *ints); -extern void q40fb_init(void); -extern void sgivwfb_init(void); -extern void sgivwfb_setup(char* options, int *ints); +extern int acornfb_init(void); +extern int acornfb_setup(char*); +extern int amifb_init(void); +extern int amifb_setup(char*); +extern int atafb_init(void); +extern int atafb_setup(char*); +extern int macfb_init(void); +extern int macfb_setup(char*); +extern int cyberfb_init(void); +extern int cyberfb_setup(char*); +extern int pm2fb_init(void); +extern int pm2fb_setup(char*); +extern int cyber2000fb_init(void); +extern int cyber2000fb_setup(char*); +extern int retz3fb_init(void); +extern int retz3fb_setup(char*); +extern int clgenfb_init(void); +extern int clgenfb_setup(char*); +extern int vfb_init(void); +extern int vfb_setup(char*); +extern int offb_init(void); +extern int offb_setup(char*); +extern int atyfb_init(void); +extern int atyfb_setup(char*); +extern int igafb_init(void); +extern int igafb_setup(char*); +extern int imsttfb_init(void); +extern int imsttfb_setup(char*); +extern int dnfb_init(void); +extern int tgafb_init(void); +extern int tgafb_setup(char*); +extern int virgefb_init(void); +extern int virgefb_setup(char*); +extern int resolver_video_setup(char*); +extern int s3triofb_init(void); +extern int s3triofb_setup(char*); +extern int vesafb_init(void); +extern int vesafb_setup(char*); +extern int vga16fb_init(void); +extern int vga16fb_setup(char*); +extern int matroxfb_init(void); +extern int matroxfb_setup(char*); +extern int hpfb_init(void); +extern int hpfb_setup(char*); +extern int sbusfb_init(void); +extern int sbusfb_setup(char*); +extern int valkyriefb_init(void); +extern int valkyriefb_setup(char*); +extern int control_init(void); +extern int control_setup(char*); +extern int g364fb_init(void); +extern int fm2fb_init(void); +extern int fm2fb_setup(char*); +extern int q40fb_init(void); +extern int sgivwfb_init(void); +extern int sgivwfb_setup(char*); static struct { const char *name; - void (*init)(void); - void (*setup)(char *options, int *ints); + int (*init)(void); + int (*setup)(char*); } fb_drivers[] __initdata = { #ifdef CONFIG_FB_SGIVW { "sgivw", sgivwfb_init, sgivwfb_setup }, @@ -176,6 +178,9 @@ static struct { #ifdef CONFIG_FB_HP300 { "hpfb", hpfb_init, hpfb_setup }, #endif +#ifdef CONFIG_FB_CONTROL + { "controlfb", control_init, control_setup }, +#endif #ifdef CONFIG_FB_VALKYRIE { "valkyriefb", valkyriefb_init, valkyriefb_setup }, #endif @@ -197,7 +202,9 @@ static struct { #define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers)) -static void (*pref_init_funcs[FB_MAX])(void); +extern const char *global_mode_option; + +static initcall_t pref_init_funcs[FB_MAX]; static int num_pref_init_funcs __initdata = 0; @@ -214,7 +221,7 @@ static int first_fb_vc = 0; static int last_fb_vc = MAX_NR_CONSOLES-1; static int fbcon_is_default = 1; -static int PROC_CONSOLE(struct fb_info *info) +static int PROC_CONSOLE(const struct fb_info *info) { int fgc; @@ -468,10 +475,18 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) return -ENODEV; if (fb->fb_mmap) return fb->fb_mmap(info, file, vma); + +#if defined(__sparc__) + /* Should never get here, all fb drivers should have their own + mmap routines */ + return -EINVAL; +#else + /* non-SPARC... */ + fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); /* frame buffer memory */ - start = (unsigned long)fix.smem_start; + start = fix.smem_start; len = (start & ~PAGE_MASK)+fix.smem_len; start &= PAGE_MASK; len = (len+~PAGE_MASK) & PAGE_MASK; @@ -481,7 +496,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) fb->fb_get_var(&var, PROC_CONSOLE(info), info); if (var.accel_flags) return -EINVAL; - start = (unsigned long)fix.mmio_start; + start = fix.mmio_start; len = (start & ~PAGE_MASK)+fix.mmio_len; start &= PAGE_MASK; len = (len+~PAGE_MASK) & PAGE_MASK; @@ -503,9 +518,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED; #elif defined(__alpha__) /* Caching is off in the I/O space quadrant by design. */ -#elif defined(__sparc__) - /* Should never get here, all fb drivers should have their own - mmap routines */ #elif defined(__i386__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; @@ -522,10 +534,12 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) #else #warning What do we have to do here?? #endif - if (remap_page_range(vma->vm_start, vma->vm_offset, + if (io_remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; + +#endif /* defined(__sparc__) */ } static int @@ -619,8 +633,8 @@ unregister_framebuffer(const struct fb_info *fb_info) static struct proc_dir_entry *proc_fbmem; -__initfunc(void -fbmem_init(void)) +void __init +fbmem_init(void) { int i; @@ -679,12 +693,12 @@ int fbmon_dpms(const struct fb_info *fb_info) * Command line options */ -__initfunc(void video_setup(char *options, int *ints)) +int __init video_setup(char *options) { int i, j; if (!options || !*options) - return; + return 0; if (!strncmp(options, "scrollback:", 11)) { options += 11; @@ -695,10 +709,10 @@ __initfunc(void video_setup(char *options, int *ints)) options++; } if (*options != ',') - return; + return 0; options++; } else - return; + return 0; } if (!strncmp(options, "map:", 4)) { @@ -709,7 +723,7 @@ __initfunc(void video_setup(char *options, int *ints)) j = 0; con2fb_map[i] = (options[j++]-'0') % FB_MAX; } - return; + return 0; } if (!strncmp(options, "vc:", 3)) { @@ -724,7 +738,7 @@ __initfunc(void video_setup(char *options, int *ints)) } if (num_pref_init_funcs == FB_MAX) - return; + return 0; for (i = 0; i < NUM_FB_DRIVERS; i++) { j = strlen(fb_drivers[i].name); @@ -739,28 +753,21 @@ __initfunc(void video_setup(char *options, int *ints)) fb_drivers[i].init = NULL; } if (fb_drivers[i].setup) - fb_drivers[i].setup(options+j+1, ints); + fb_drivers[i].setup(options+j+1); } - return; + return 0; } } + /* - * If we get here no fb was specified and we default to pass the - * options to the first frame buffer that has an init and a setup - * function. + * If we get here no fb was specified. + * We consider the argument to be a global video mode option. */ - for (i = 0; i < NUM_FB_DRIVERS; i++) { - if (fb_drivers[i].init && fb_drivers[i].setup) { - pref_init_funcs[num_pref_init_funcs++] = - fb_drivers[i].init; - fb_drivers[i].init = NULL; - - fb_drivers[i].setup(options, ints); - return; - } - } + global_mode_option = options; + return 0; } +__setup("video=", video_setup); /* * Visible symbols for modules diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index e5ab75e08..97f4e9ba8 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -205,7 +205,7 @@ static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -void fm2fb_init(void); +int fm2fb_init(void); static int fm2fbcon_switch(int con, struct fb_info *info); static int fm2fbcon_updatevar(int con, struct fb_info *info); static void fm2fbcon_blank(int blank, struct fb_info *info); @@ -374,7 +374,7 @@ static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Initialisation */ -__initfunc(void fm2fb_init(void)) +int __init fm2fb_init(void) { int key, is_fm; const struct ConfigDev *cd = NULL; @@ -383,10 +383,10 @@ __initfunc(void fm2fb_init(void)) if (!(key = is_fm = zorro_find(ZORRO_PROD_BSC_FRAMEMASTER_II, 0, 0)) && !(key = zorro_find(ZORRO_PROD_HELFRICH_RAINBOW_II, 0, 0))) - return; + return -ENXIO; cd = zorro_get_board(key); if (!(board = (u_long)cd->cd_BoardAddr)) - return; + return -ENXIO; zorro_config_board(key, 0); /* assigning memory to kernel space */ @@ -415,13 +415,13 @@ __initfunc(void fm2fb_init(void)) fb_var = fb_var_modes[fm2fb_mode]; strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II"); - fb_fix.smem_start = (char *)fm2fb_mem_phys; + fb_fix.smem_start = fm2fb_mem_phys; fb_fix.smem_len = FRAMEMASTER_REG; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; fb_fix.visual = FB_VISUAL_TRUECOLOR; fb_fix.line_length = 768<<2; - fb_fix.mmio_start = (char *)fm2fb_reg_phys; + fb_fix.mmio_start = fm2fb_reg_phys; fb_fix.mmio_len = 8; fb_fix.accel = FB_ACCEL_NONE; @@ -460,18 +460,19 @@ __initfunc(void fm2fb_init(void)) fm2fb_set_var(&fb_var, -1, &fb_info); if (register_framebuffer(&fb_info) < 0) - return; + return -EINVAL; printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_fix.id); + return 0; } -__initfunc(void fm2fb_setup(char *options, int *ints)) +int __init fm2fb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -480,6 +481,7 @@ __initfunc(void fm2fb_setup(char *options, int *ints)) else if (!strncmp(this_opt, "ntsc", 4)) fm2fb_mode = FM2FB_MODE_NTSC; } + return 0; } diff --git a/drivers/video/font_6x11.c b/drivers/video/font_6x11.c index 362529c2b..aa95f8863 100644 --- a/drivers/video/font_6x11.c +++ b/drivers/video/font_6x11.c @@ -1207,6 +1207,8 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { 0x00, /* 00000000 */ /* 92 0x5c '\' */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ 0x20, /* 00 00000 */ 0x20, /* 00 00000 */ 0x10, /* 000 0000 */ @@ -1215,8 +1217,6 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { 0x08, /* 0000 000 */ 0x04, /* 00000 00 */ 0x04, /* 00000 00 */ - 0x02, /* 000000 0 */ - 0x02, /* 000000 0 */ 0x00, /* 00000000 */ /* 93 0x5d ']' */ @@ -1253,7 +1253,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ + 0xfc, /* 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ @@ -2222,9 +2222,9 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { /* 170 0xaa '\252' */ 0x00, /* 00000000 */ - 0x7a, /* 0 0 0 */ - 0x2e, /* 00 0 0 */ - 0x2e, /* 00 0 0 */ + 0xf4, /* 0 00 */ + 0x5c, /* 0 0 00 */ + 0x5c, /* 0 0 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ @@ -2732,7 +2732,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ + 0xfc, /* 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ @@ -2834,11 +2834,11 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { /* 217 0xd9 '\331' */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ + 0xfc, /* 00 */ 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ + 0xfc, /* 00 */ 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ + 0xfc, /* 00 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ 0x00, /* 00000000 */ diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index fe57a7558..b74d12d93 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -112,7 +112,7 @@ static int g364fb_ioctl(struct inode *inode, struct file *file, u_int cmd, /* * Interface to the low level console driver */ -void g364fb_init(void); +int g364fb_init(void); static int g364fbcon_switch(int con, struct fb_info *info); static int g364fbcon_updatevar(int con, struct fb_info *info); static void g364fbcon_blank(int blank, struct fb_info *info); @@ -297,7 +297,7 @@ static int g364fb_ioctl(struct inode *inode, struct file *file, u_int cmd, /* * Initialisation */ -__initfunc(void g364fb_init(void)) +int __init g364fb_init(void) { int i,j; volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG; @@ -345,7 +345,7 @@ __initfunc(void g364fb_init(void)) fb_var.yres = yres; fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel; - fb_fix.smem_start = (char *)0x40000000; /* physical address */ + fb_fix.smem_start = 0x40000000; /* physical address */ /* get size of video memory; this is special for the JAZZ hardware */ mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3; fb_fix.smem_len = (1 << (mem*2)) * 512 * 1024; @@ -355,7 +355,7 @@ __initfunc(void g364fb_init(void)) fb_fix.xpanstep = 0; fb_fix.ypanstep = 1; fb_fix.ywrapstep = 0; - fb_fix.mmio_start = NULL; + fb_fix.mmio_start = 0; fb_fix.mmio_len = 0; fb_fix.accel = FB_ACCEL_NONE; @@ -413,10 +413,11 @@ __initfunc(void g364fb_init(void)) g364fb_set_var(&fb_var, -1, &fb_info); if (register_framebuffer(&fb_info) < 0) - return; + return -EINVAL; printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_fix.id); + return 0; } diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index 11689b150..27a383ece 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -192,7 +192,7 @@ static void hpfb_encode_fix(struct fb_fix_screeninfo *fix, /* * X works, but screen wraps ... */ - fix->smem_start=(char *)fb_start; + fix->smem_start=fb_start; fix->smem_len=fb_size; fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_PSEUDOCOLOR; @@ -301,7 +301,7 @@ static struct fb_ops hpfb_ops = { #define TOPCAT_FBOMSB 0x5d #define TOPCAT_FBOLSB 0x5f -__initfunc(int hpfb_init_one(unsigned long base)) +int __init hpfb_init_one(unsigned long base) { unsigned long fboff; @@ -384,7 +384,7 @@ __initfunc(int hpfb_init_one(unsigned long base)) * Initialise the framebuffer */ -__initfunc(unsigned long hpfb_init(unsigned long mem_start)) +int __init hpfb_init(void) { unsigned int sid; @@ -421,9 +421,10 @@ __initfunc(unsigned long hpfb_init(unsigned long mem_start)) } } - return mem_start; + return 0; } -__initfunc(void hpfb_setup(char *options, int *ints)) +int __init hpfb_setup(char *options) { + return 0; } diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index dbf56108c..5ed528af2 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -217,7 +217,7 @@ static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, igafb_name); - fix->smem_start = (char *)fb->frame_buffer; + fix->smem_start = fb->frame_buffer; fix->smem_len = fb->total_vram; fix->xpanstep = 0; fix->ypanstep = 0; @@ -559,7 +559,7 @@ static void igafb_blank(int blank, struct fb_info *info) } -__initfunc(static int iga_init(struct fb_info_iga *info)) +static int __init iga_init(struct fb_info_iga *info) { char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) & MEM_SIZE_ALIAS; @@ -624,7 +624,7 @@ __initfunc(static int iga_init(struct fb_info_iga *info)) } -__initfunc(void igafb_init(void)) +int __init igafb_init(void) { struct pci_dev *pdev; struct fb_info_iga *info; @@ -634,7 +634,7 @@ __initfunc(void igafb_init(void)) /* Do not attach when we have a serial console. */ if (!con_is_present()) - return; + return -ENXIO; pdev = pci_find_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); @@ -642,28 +642,28 @@ __initfunc(void igafb_init(void)) pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); if(pdev == NULL) - return; + return -ENXIO; iga2000 = 1; } info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC); if (!info) { printk("igafb_init: can't alloc fb_info_iga\n"); - return; + return -ENOMEM; } memset(info, 0, sizeof(struct fb_info_iga)); - info->frame_buffer = pdev->base_address[0]; + info->frame_buffer = pdev->resource[0].start; if (!info->frame_buffer) { kfree(info); - return; + return -ENXIO; } pcibios_read_config_dword(0, pdev->devfn, PCI_BASE_ADDRESS_0, (unsigned int*)&addr); if (!addr) - return; + return -ENXIO; info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK; #ifdef __sparc__ @@ -684,7 +684,7 @@ __initfunc(void igafb_init(void)) } if (!info->io_base) { kfree(info); - return; + return -ENXIO; } /* @@ -700,7 +700,7 @@ __initfunc(void igafb_init(void)) printk("igafb_init: can't alloc mmap_map\n"); /* XXX Here we left I/O allocated */ kfree(info); - return; + return -ENOMEM; } memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map)); @@ -775,14 +775,16 @@ __initfunc(void igafb_init(void)) info->mmap_map[1].prot_mask = SRMMU_CACHE; info->mmap_map[1].prot_flag = SRMMU_WRITE; #endif /* __sparc__ */ + + return 0; } -__initfunc(void igafb_setup(char *options, int *ints)) +int __init igafb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -798,4 +800,5 @@ __initfunc(void igafb_setup(char *options, int *ints)) fontname[i] = 0; } } + return 0; } diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 99ebadf4b..398e8e500 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -380,9 +380,7 @@ static char noaccel __initdata = 0; #if defined(CONFIG_PPC) static signed char init_vmode __initdata = -1, init_cmode __initdata = -1; #endif -#ifdef MODULE static struct fb_info_imstt *fb_info_imstt_p[FB_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -#endif static struct imstt_regvals tvp_reg_init_2 = { 512, @@ -967,8 +965,8 @@ out: add_timer(&c->timer); } -__initfunc(static void -imstt_cursor_init (struct fb_info_imstt *p)) +static void __init +imstt_cursor_init (struct fb_info_imstt *p) { struct imstt_cursor *c = &p->cursor; @@ -1728,8 +1726,8 @@ imsttfbcon_blank (int blank, struct fb_info *info) out_le32(&p->dc_regs[STGCTL], ctrl); } -__initfunc(static void -init_imstt(struct fb_info_imstt *p)) +static void __init +init_imstt(struct fb_info_imstt *p) { __u32 i, tmp; __u32 *ip, *end; @@ -1799,10 +1797,10 @@ init_imstt(struct fb_info_imstt *p)) } sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP"); - p->fix.smem_start = (__u8 *)p->frame_buffer_phys; + p->fix.smem_start = p->frame_buffer_phys; p->fix.smem_len = p->total_vram; - p->fix.mmio_start = (__u8 *)p->dc_regs_phys; - p->fix.mmio_len = 0x40000; + p->fix.mmio_start = p->dc_regs_phys; + p->fix.mmio_len = 0x1000; p->fix.accel = FB_ACCEL_IMS_TWINTURBO; p->fix.type = FB_TYPE_PACKED_PIXELS; p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR @@ -1853,9 +1851,7 @@ init_imstt(struct fb_info_imstt *p)) printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n", i, p->fix.id, p->total_vram >> 20, tmp); -#ifdef MODULE fb_info_imstt_p[i] = p; -#endif #ifdef CONFIG_FB_COMPAT_XPMAC strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name)); display_info.fb_address = (__u32)p->frame_buffer_phys; @@ -1868,8 +1864,8 @@ init_imstt(struct fb_info_imstt *p)) } #if defined(CONFIG_FB_OF) && !defined(MODULE) -__initfunc(void -imsttfb_of_init(struct device_node *dp)) +void __init +imsttfb_of_init(struct device_node *dp) { struct fb_info_imstt *p; int i; @@ -1912,9 +1908,10 @@ imsttfb_of_init(struct device_node *dp)) } #endif -__initfunc(void -imsttfb_init(void)) +int __init +imsttfb_init(void) { + int i; #if defined(CONFIG_FB_OF) && !defined(MODULE) /* We don't want to be called like this. */ /* We rely on Open Firmware (offb) instead. */ @@ -1935,13 +1932,13 @@ imsttfb_init(void)) pci_write_config_word(pdev, PCI_COMMAND, cmd); } - addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; + addr = pdev->resource[0].start; if (!addr) continue; p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC); if (!p) - return; + continue; memset(p, 0, sizeof(struct fb_info_imstt)); printk("imsttfb: device=%04x\n", pdev->device); @@ -1966,16 +1963,21 @@ imsttfb_init(void)) init_imstt(p); } #endif /* CONFIG_PCI */ + for (i = 0; i < FB_MAX; i++) { + if (fb_info_imstt_p[i]) + return 0; + } + return -ENXIO; } #ifndef MODULE -__initfunc(void -imsttfb_setup(char *options, int *ints)) +int __init +imsttfb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -2020,25 +2022,16 @@ imsttfb_setup(char *options, int *ints)) } #endif } + return 0; } #else /* MODULE */ -int +int __init init_module (void) { - struct fb_info_imstt *p; - __u32 i; - - imsttfb_init(); - - for (i = 0; i < FB_MAX; i++) { - p = fb_info_imstt_p[i]; - if (p) - return 0; - } - return -ENXIO; + return imsttfb_init(); } void diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c index 0a273fe43..9daa66421 100644 --- a/drivers/video/leofb.c +++ b/drivers/video/leofb.c @@ -1,4 +1,4 @@ -/* $Id: leofb.c,v 1.6 1999/04/01 13:03:25 jj Exp $ +/* $Id: leofb.c,v 1.7 1999/08/09 11:06:52 jj Exp $ * leofb.c: Leo (ZX) 24/8bit frame buffer driver * * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) @@ -505,8 +505,9 @@ static void leo_switch_from_graph (struct fb_info_sbusfb *fb) us->fontt = 0; } -static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start) +static int __init leo_rasterimg (struct fb_info *info, int start) { + struct fb_info_sbusfb *fb = sbusfbinfo(info); register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; register struct leo_ld *ss = fb->s.leo.ld_ss0; @@ -521,6 +522,7 @@ static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start) ss->rop = 0x310850; us->addrspace = 4; } + return 0; } static char idstring[40] __initdata = { 0 }; diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 0f964f60a..282c47739 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -157,7 +157,7 @@ static void macfb_encode_fix(struct fb_fix_screeninfo *fix, /* * fbmem.c accepts non page aligned mappings now! */ - fix->smem_start=(char *)mac_videobase; + fix->smem_start=mac_videobase; fix->smem_len=mac_videosize; fix->type = FB_TYPE_PACKED_PIXELS; if (mac_depth == 1) @@ -459,14 +459,14 @@ static struct fb_ops macfb_ops = { macfb_ioctl }; -void macfb_setup(char *options, int *ints) +int __init macfb_setup(char *options) { char *this_opt; fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; @@ -478,6 +478,7 @@ void macfb_setup(char *options, int *ints) printk("macfb_setup: option %s\n", this_opt); } } + return 0; } static int macfb_switch(int con, struct fb_info *info) @@ -512,12 +513,12 @@ static struct nubus_device_specifier nb_video={ NULL }; -__initfunc(void macfb_init(void)) +int __init macfb_init(void) { /* nubus_remap the video .. */ if (!MACH_IS_MAC) - return; + return -ENXIO; mac_xres=mac_bi_data.dimensions&0xFFFF; mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16; @@ -572,11 +573,12 @@ __initfunc(void macfb_init(void)) if (register_framebuffer(&fb_info) < 0) { - return; + return -EINVAL; } printk("fb%d: %s frame buffer device using %ldK of video memory\n", GET_FB_IDX(fb_info.node), fb_info.modename, mac_videosize>>10); + return 0; } #if 0 diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index 0fbe917d3..e71f36e50 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -14,240 +14,151 @@ #include <video/macmodes.h> -struct mac_mode { - int number; - u32 xres; - u32 yres; - u32 pixclock; - u32 left_margin; - u32 right_margin; - u32 upper_margin; - u32 lower_margin; - u32 hsync_len; - u32 vsync_len; - u32 sync; - u32 vmode; -}; - - - /* 512x384, 60Hz, Interlaced (NTSC) */ - -#if 0 -static const struct mac_mode mac_mode_1 = { - VMODE_512_384_60I, 512, 384, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_INTERLACED -}; -#endif - - /* 512x384, 60Hz, Non-Interlaced */ - -#if 0 -static const struct mac_mode mac_mode_2 = { - VMODE_512_384_60, 512, 384, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_NONINTERLACED -}; -#endif - - /* 640x480, 50Hz, Interlaced (PAL) */ - -#if 0 -static const struct mac_mode mac_mode_3 = { - VMODE_640_480_50I, 640, 480, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_INTERLACED -}; -#endif - - /* 640x480, 60Hz, Interlaced (NTSC) */ - -#if 0 -static const struct mac_mode mac_mode_4 = { - VMODE_640_480_60I, 640, 480, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_INTERLACED -}; -#endif - /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ - -static const struct mac_mode mac_mode_5 = { - VMODE_640_480_60, 640, 480, - 39722, 32, 32, 33, 10, 96, 2, - 0, FB_VMODE_NONINTERLACED -}; - - /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */ - -static const struct mac_mode mac_mode_6 = { - VMODE_640_480_67, 640, 480, - 33334, 80, 80, 39, 3, 64, 3, - 0, FB_VMODE_NONINTERLACED -}; - - /* 640x870, 75Hz (portrait), Non-Interlaced */ - -#if 0 -static const struct mac_mode mac_mode_7 = { - VMODE_640_870_75P, 640, 870, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_NONINTERLACED -}; -#endif + /* + * MacOS video mode definitions + * + * Order IS important! If you change these, don't forget to update + * mac_modes[] below! + */ - /* 768x576, 50Hz (PAL full frame), Interlaced */ +#define DEFAULT_MODEDB_INDEX 0 + +static const struct fb_videomode mac_modedb[] = { + { + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + "mac5", 60, 640, 480, 39722, 32, 32, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED + }, { + /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */ + "mac6", 67, 640, 480, 33334, 80, 80, 39, 3, 64, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */ + "mac9", 56, 800, 600, 27778, 112, 40, 22, 1, 72, 2, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */ + "mac10", 60, 800, 600, 25000, 72, 56, 23, 1, 128, 4, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */ + "mac11", 72, 800, 600, 20000, 48, 72, 23, 37, 120, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */ + "mac12", 75, 800, 600, 20203, 144, 32, 21, 1, 80, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 832x624, 75Hz, Non-Interlaced (57.6 MHz dotclock) */ + "mac13", 75, 832, 624, 17362, 208, 48, 39, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */ + "mac14", 60, 1024, 768, 15385, 144, 40, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */ + "mac15", 72, 1024, 768, 13334, 128, 40, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ + "mac16", 75, 1024, 768, 12699, 176, 16, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ + "mac17", 75, 1024, 768, 12699, 160, 32, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */ + "mac18", 75, 1152, 870, 10000, 128, 48, 39, 3, 128, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */ + "mac19", 75, 1280, 960, 7937, 224, 32, 36, 1, 144, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ + "mac20", 75, 1280, 1024, 7408, 232, 64, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, #if 0 -static const struct mac_mode mac_mode_8 = { - VMODE_768_576_50I, 768, 576, - pixclock, left, right, upper, lower, hslen, vslen, - sync, FB_VMODE_INTERLACED -}; + /* Anyone who has timings for these? */ + { + /* VMODE_512_384_60I: 512x384, 60Hz, Interlaced (NTSC) */ + "mac1", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED + }, { + /* VMODE_512_384_60: 512x384, 60Hz, Non-Interlaced */ + "mac2", 60, 512, 384, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_NONINTERLACED + }, { + /* VMODE_640_480_50I: 640x480, 50Hz, Interlaced (PAL) */ + "mac3", 50, 640, 480, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED + }, { + /* VMODE_640_480_60I: 640x480, 60Hz, Interlaced (NTSC) */ + "mac4", 60, 640, 480, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED + }, { + /* VMODE_640_870_75P: 640x870, 75Hz (portrait), Non-Interlaced */ + "mac7", 75, 640, 870, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_NONINTERLACED + }, { + /* VMODE_768_576_50I: 768x576, 50Hz (PAL full frame), Interlaced */ + "mac8", 50, 768, 576, pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED + }, #endif - - /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_9 = { - VMODE_800_600_56, 800, 600, - 27778, 112, 40, 22, 1, 72, 2, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_10 = { - VMODE_800_600_60, 800, 600, - 25000, 72, 56, 23, 1, 128, 4, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_11 = { - VMODE_800_600_72, 800, 600, - 20000, 48, 72, 23, 37, 120, 6, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }; - /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */ - -static const struct mac_mode mac_mode_12 = { - VMODE_800_600_75, 800, 600, - 20203, 144, 32, 21, 1, 80, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 832x624, 75Hz, Non-Interlaced (57.6 MHz */ - -static const struct mac_mode mac_mode_13 = { - VMODE_832_624_75, 832, 624, - 17362, 208, 48, 39, 1, 64, 3, - 0, FB_VMODE_NONINTERLACED -}; - - /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_14 = { - VMODE_1024_768_60, 1024, 768, - 15385, 144, 40, 29, 3, 136, 6, - 0, FB_VMODE_NONINTERLACED -}; - - /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_15 = { - VMODE_1024_768_70, 1024, 768, - 13334, 128, 40, 29, 3, 136, 6, - 0, FB_VMODE_NONINTERLACED -}; - - /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ - -static const struct mac_mode mac_mode_16 = { - VMODE_1024_768_75V, 1024, 768, - 12699, 176, 16, 28, 1, 96, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ - -static const struct mac_mode mac_mode_17 = { - VMODE_1024_768_75, 1024, 768, - 12699, 160, 32, 28, 1, 96, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */ - -static const struct mac_mode mac_mode_18 = { - VMODE_1152_870_75, 1152, 870, - 10000, 128, 48, 39, 3, 128, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; - - /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_19 = { - VMODE_1280_960_75, 1280, 960, - 7937, 224, 32, 36, 1, 144, 3, - 0, FB_VMODE_NONINTERLACED -}; - - /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ - -static const struct mac_mode mac_mode_20 = { - VMODE_1280_1024_75, 1280, 1024, - 7408, 232, 64, 38, 1, 112, 3, - FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED -}; + /* + * Mapping between MacOS video mode numbers and video mode definitions + * + * These MUST be ordered in + * - increasing resolution + * - decreasing refresh rate + */ -static const struct mac_mode *mac_modes[20] = { - NULL, /* 512x384, 60Hz interlaced (NTSC) */ - NULL, /* 512x384, 60Hz */ - NULL, /* 640x480, 50Hz interlaced (PAL) */ - NULL, /* 640x480, 60Hz interlaced (NTSC) */ - &mac_mode_5, /* 640x480, 60Hz (VGA) */ - &mac_mode_6, /* 640x480, 67Hz */ - NULL, /* 640x870, 75Hz (portrait) */ - NULL, /* 768x576, 50Hz (PAL full frame) */ - &mac_mode_9, /* 800x600, 56Hz */ - &mac_mode_10, /* 800x600, 60Hz */ - &mac_mode_11, /* 800x600, 72Hz */ - &mac_mode_12, /* 800x600, 75Hz */ - &mac_mode_13, /* 832x624, 75Hz */ - &mac_mode_14, /* 1024x768, 60Hz */ - &mac_mode_15, /* 1024x768, 70Hz (or 72Hz?) */ - &mac_mode_16, /* 1024x768, 75Hz (VESA) */ - &mac_mode_17, /* 1024x768, 75Hz */ - &mac_mode_18, /* 1152x870, 75Hz */ - &mac_mode_19, /* 1280x960, 75Hz */ - &mac_mode_20, /* 1280x1024, 75Hz */ +static const struct mode_map { + int vmode; + const struct fb_videomode *mode; +} mac_modes[] = { + /* 640x480 */ + { VMODE_640_480_67, &mac_modedb[1] }, + { VMODE_640_480_60, &mac_modedb[0] }, + /* 800x600 */ + { VMODE_800_600_75, &mac_modedb[5] }, + { VMODE_800_600_72, &mac_modedb[4] }, + { VMODE_800_600_60, &mac_modedb[3] }, + { VMODE_800_600_56, &mac_modedb[2] }, + /* 832x624 */ + { VMODE_832_624_75, &mac_modedb[6] }, + /* 1024x768 */ + { VMODE_1024_768_75, &mac_modedb[10] }, + { VMODE_1024_768_75V, &mac_modedb[9] }, + { VMODE_1024_768_70, &mac_modedb[8] }, + { VMODE_1024_768_60, &mac_modedb[7] }, + /* 1152x870 */ + { VMODE_1152_870_75, &mac_modedb[11] }, + /* 1280x960 */ + { VMODE_1280_960_75, &mac_modedb[12] }, + /* 1280x1024 */ + { VMODE_1280_1024_75, &mac_modedb[13] }, + { -1, NULL } }; -static const struct mac_mode *mac_modes_inv[] = { - &mac_mode_6, /* 640x480, 67Hz */ - &mac_mode_5, /* 640x480, 60Hz (VGA) */ - &mac_mode_12, /* 800x600, 75Hz */ - &mac_mode_11, /* 800x600, 72Hz */ - &mac_mode_10, /* 800x600, 60Hz */ - &mac_mode_9, /* 800x600, 56Hz */ - &mac_mode_13, /* 832x624, 75Hz */ - &mac_mode_17, /* 1024x768, 75Hz */ - &mac_mode_16, /* 1024x768, 75Hz (VESA) */ - &mac_mode_15, /* 1024x768, 70Hz (or 72Hz?) */ - &mac_mode_14, /* 1024x768, 60Hz */ - &mac_mode_18, /* 1152x870, 75Hz */ - &mac_mode_19, /* 1280x960, 75Hz */ - &mac_mode_20, /* 1280x1024, 75Hz */ -}; + /* + * Mapping between monitor sense values and MacOS video mode numbers + */ -static struct mon_map { +static const struct monitor_map { int sense; int vmode; -} monitor_map[] = { +} mac_monitors[] = { { 0x000, VMODE_1280_1024_75 }, /* 21" RGB */ { 0x114, VMODE_640_870_75P }, /* Portrait Monochrome */ { 0x221, VMODE_512_384_60 }, /* 12" RGB*/ @@ -277,11 +188,14 @@ static struct mon_map { int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var) { - const struct mac_mode *mode = NULL; - - if (vmode > 0 && vmode <= VMODE_MAX) - mode = mac_modes[vmode-1]; + const struct fb_videomode *mode = NULL; + const struct mode_map *map; + for (map = mac_modes; map->vmode != -1; map++) + if (map->vmode == vmode) { + mode = map->mode; + break; + } if (!mode) return -EINVAL; @@ -348,7 +262,8 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var) int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, int *cmode) { - unsigned int i; + const struct fb_videomode *mode = NULL; + const struct mode_map *map; if (var->bits_per_pixel <= 8) *cmode = CMODE_8; @@ -359,8 +274,8 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, else return -EINVAL; - for (i = 0; i < sizeof(mac_modes_inv)/sizeof(*mac_modes_inv); i++) { - const struct mac_mode *mode = mac_modes_inv[i]; + for (map = mac_modes; map->vmode != -1; map++) { + mode = map->mode; if (var->xres > mode->xres || var->yres > mode->yres) continue; if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres) @@ -369,7 +284,7 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, continue; if ((var->vmode & FB_VMODE_MASK) != mode->vmode) continue; - *vmode = mode->number; + *vmode = map->vmode; return 0; } return -EINVAL; @@ -382,10 +297,32 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, int mac_map_monitor_sense(int sense) { - struct mon_map *map; + const struct monitor_map *map; - for (map = monitor_map; map->sense >= 0; ++map) + for (map = mac_monitors; map->sense != -1; map++) if (map->sense == sense) break; return map->vmode; } + + + /* + * Find a suitable video mode + * + * If the name of the wanted mode begins with `mac', use the Mac video + * mode database, else fall back to the standard video mode database. + */ + +int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, + const char *mode_option, unsigned int default_bpp) +{ + const struct fb_videomode *db = NULL; + unsigned int dbsize = 0; + + if (mode_option && !strncmp(mode_option, "mac", 3)) { + db = mac_modedb; + dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb); + } + return fb_find_mode(var, info, mode_option, db, dbsize, + &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); +} diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c index eb6126965..4b0ffb0ad 100644 --- a/drivers/video/matroxfb.c +++ b/drivers/video/matroxfb.c @@ -1,10 +1,10 @@ /* * - * Hardware accelerated Matrox Millennium I, II, Mystique and G200 + * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.15 1999/04/19 + * Version: 1.19 1999/08/05 * * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net> * @@ -14,8 +14,8 @@ * "Kurt Garloff" <garloff@kg1.ping.de> * Betatesting, fixes, ideas, videomodes, videomodes timmings * - * "Tom Rini" <tmrini@ntplx.net> - * MTRR stuff, betatesting, fixes, ideas + * "Tom Rini" <trini@disparity.net> + * MTRR stuff, PPC cleanups, betatesting, fixes, ideas * * "Bibek Sahu" <scorpio@dodds.net> * Access device through readb|w|l and write b|w|l @@ -60,6 +60,9 @@ * "Cort Dougan" <cort@cs.nmt.edu> * CHRP fixes and PReP cleanup * + * "Mark Vojkovich" <mvojkovi@ucsd.edu> + * G400 support + * * (following author is not in any relation with this code, but his code * is included in this driver) * @@ -87,6 +90,11 @@ /* Debug register calls, too? */ #undef MATROXFB_DEBUG_REG +/* Log reentrancy attempts - you must have printstate() patch applied */ +#undef MATROXFB_DEBUG_REENTER +/* you must define DEBUG_REENTER to get debugged CONSOLEBH... */ +#undef MATROXFB_DEBUG_CONSOLEBH + #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> @@ -103,9 +111,9 @@ #include <linux/init.h> #include <linux/timer.h> #include <linux/pci.h> +#include <linux/spinlock.h> #include <asm/io.h> -#include <asm/spinlock.h> #include <asm/unaligned.h> #ifdef CONFIG_MTRR #include <asm/mtrr.h> @@ -127,12 +135,15 @@ #include <video/macmodes.h> #endif +/* always compile support for 32MB... It cost almost nothing */ +#define CONFIG_FB_MATROX_32MB + #define FBCON_HAS_VGATEXT #ifdef MATROXFB_DEBUG #define DEBUG -#define DBG(x) printk("matroxfb: %s\n", (x)); +#define DBG(x) printk(KERN_DEBUG "matroxfb: %s\n", (x)); #ifdef MATROXFB_DEBUG_HEAVY #define DBG_HEAVY(x) DBG(x) @@ -217,6 +228,9 @@ #ifndef PCI_DEVICE_ID_MATROX_G100_AGP #define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001 #endif +#ifndef PCI_DEVICE_ID_MATROX_G400_AGP +#define PCI_DEVICE_ID_MATROX_G400_AGP 0x0525 +#endif #ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP #define PCI_SS_ID_MATROX_GENERIC 0xFF00 @@ -422,7 +436,7 @@ struct matrox_hw_state { unsigned char MiscOutReg; unsigned char DACpal[768]; unsigned char CRTC[25]; - unsigned char CRTCEXT[6]; + unsigned char CRTCEXT[9]; unsigned char SEQ[5]; /* unused for MGA mode, but who knows... */ unsigned char GCTL[9]; @@ -453,7 +467,8 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) { } #define PMXINFO(p) mxinfo(p), -#define MINFO_FROM_DISP(x) struct matrox_fb_info* minfo = mxinfo(x) +#define MINFO_FROM(x) struct matrox_fb_info* minfo = x +#define MINFO_FROM_DISP(x) MINFO_FROM(mxinfo(x)) #else @@ -476,6 +491,7 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) { #endif #define PMXINFO(p) +#define MINFO_FROM(x) #define MINFO_FROM_DISP(x) #endif @@ -563,6 +579,9 @@ struct matrox_fb_info { int hwcursor; int blink; int sgram; +#ifdef CONFIG_FB_MATROX_32MB + int support32MB; +#endif int accelerator; int text_type_aux; @@ -609,6 +628,8 @@ struct matrox_fb_info { #if defined(CONFIG_FB_OF) unsigned char nvram_read_byte(int); int matrox_of_init(struct device_node *dp); +static int default_vmode = VMODE_NVRAM; +static int default_cmode = CMODE_NVRAM; #endif #define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels) @@ -678,6 +699,8 @@ int matrox_of_init(struct device_node *dp); #define M_RESET 0x1E40 +#define M_AGP2PLL 0x1E4C + #define M_OPMODE 0x1E54 #define M_OPMODE_DMA_GEN_WRITE 0x00 #define M_OPMODE_DMA_BLIT 0x04 @@ -713,6 +736,9 @@ int matrox_of_init(struct device_node *dp); #define M_EXTVGA_INDEX 0x1FDE #define M_EXTVGA_DATA 0x1FDF +/* G200 only */ +#define M_SRCORG 0x2CB4 + #define M_RAMDAC_BASE 0x3C00 /* fortunately, same on TVP3026 and MGA1064 */ @@ -723,6 +749,9 @@ int matrox_of_init(struct device_node *dp); #define M_X_INDEX 0x00 #define M_X_DATAREG 0x0A +#define DAC_XGENIOCTRL 0x2A +#define DAC_XGENIODATA 0x2B + #ifdef CONFIG_FB_MATROX_MILLENIUM #define TVP3026_INDEX 0x00 #define TVP3026_PALWRADD 0x00 @@ -1054,6 +1083,48 @@ int matrox_of_init(struct device_node *dp); #define isMilleniumII(x) (0) #endif +#ifdef MATROXFB_DEBUG_REENTER +static atomic_t guard_counter = ATOMIC_INIT(1); +static atomic_t guard_printing = ATOMIC_INIT(1); +static void guard_start(void) { + if (atomic_dec_and_test(&guard_counter)) { /* first level */ + if (!(bh_mask & (1 << CONSOLE_BH))) /* and CONSOLE_BH disabled */ + return; /* is OK */ + /* otherwise it is first level with CONSOLE_BH enabled - + - if we are __sti or SMP, reentering from console_bh possible */ + atomic_dec(&guard_printing); /* disable reentrancy warning */ + printk(KERN_DEBUG "matroxfb entered without CONSOLE_BH disabled\n"); +#ifdef printstate + printstate(); +#endif + atomic_inc(&guard_printing); + return; + } + /* real reentering... You should be already warned by code above */ + if (atomic_dec_and_test(&guard_printing)) { +#ifdef printstate + printstate(); +#endif + } + atomic_inc(&guard_printing); +} + +static inline void guard_end(void) { + atomic_inc(&guard_counter); +} + +#define CRITBEGIN guard_start(); +#define CRITEND guard_end(); + +#else + +#define CRITBEGIN +#define CRITEND + +#endif + +#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l)) + static void matrox_cfbX_init(WPMINFO struct display* p) { u_int32_t maccess; u_int32_t mpitch; @@ -1101,7 +1172,7 @@ static void matrox_cfbX_init(WPMINFO struct display* p) { mga_outl(M_OPMODE, mopmode); mga_outl(M_CXBNDRY, 0xFFFF0000); mga_outl(M_YTOP, 0); - mga_outl(M_YBOT, 0x007FFFFF); + mga_outl(M_YBOT, 0x01FFFFFF); mga_outl(M_MACCESS, maccess); ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO; if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC; @@ -1113,7 +1184,9 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, MINFO_FROM_DISP(p); DBG("matrox_cfbX_bmove") - + + CRITBEGIN + sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p); @@ -1142,8 +1215,10 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, mga_outl(M_AR0, end); mga_outl(M_AR3, start); mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx); - mga_outl(M_YDSTLEN | M_EXEC, ((dy)<<16) | height); + mga_ydstlen(dy, height); WaitTillIdle(); + + CRITEND } #ifdef FBCON_HAS_CFB4 @@ -1154,7 +1229,9 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx, also odd, that means that we cannot use acceleration */ DBG("matrox_cfb4_bmove") - + + CRITBEGIN + if ((sx | dx | width) & fontwidth(p) & 1) { fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width); return; @@ -1194,6 +1271,8 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx, mga_outl(M_YDST, dy*pixx >> 5); mga_outl(M_LEN | M_EXEC, height); WaitTillIdle(); + + CRITEND } #endif @@ -1201,13 +1280,17 @@ static void matroxfb_accel_clear(CPMINFO u_int32_t color, int sy, int sx, int he int width) { DBG("matroxfb_accel_clear") - - mga_fifo(4); + + CRITBEGIN + + mga_fifo(5); mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE); mga_outl(M_FCOL, color); mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx); - mga_outl(M_YDSTLEN | M_EXEC, (sy << 16) | height); + mga_ydstlen(sy, height); WaitTillIdle(); + + CRITEND } static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) { @@ -1225,7 +1308,9 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i MINFO_FROM_DISP(p); DBG("matrox_cfb4_clear") - + + CRITBEGIN + whattodo = 0; bgx = attr_bgcol_ec(p, conp); bgx |= bgx << 4; @@ -1277,6 +1362,8 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i } } } + + CRITEND } #endif @@ -1323,7 +1410,10 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p charcell = fontwidth(p) * fontheight(p); yy *= fontheight(p); xx *= fontwidth(p); - mga_fifo(7); + + CRITBEGIN + + mga_fifo(8); mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE); mga_outl(M_FCOL, fgx); @@ -1332,8 +1422,10 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell; mga_outl(M_AR3, ar3); mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF); - mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); WaitTillIdle(); + + CRITEND } static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) { @@ -1345,6 +1437,9 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in yy *= fontheight(p); xx *= fontwidth(p); + + CRITBEGIN + #ifdef __BIG_ENDIAN WaitTillIdle(); mga_outl(M_OPMODE, M_OPMODE_8BPP); @@ -1367,7 +1462,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in mga_outl(M_BCOL, bgx); mga_outl(M_AR3, 0); mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1); - mga_outl(M_YDSTLEN | M_EXEC, (yy<<16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell); } else { u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step; @@ -1379,7 +1474,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in mga_outl(M_AR5, 0); mga_outl(M_AR3, 0); mga_outl(M_AR0, ar0); - mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); switch (step) { case 1: @@ -1410,6 +1505,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in #ifdef __BIG_ENDIAN mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); #endif + CRITEND } #ifdef FBCON_HAS_CFB8 @@ -1464,6 +1560,9 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* yy *= fontheight(p); xx *= fontwidth(p); charcell = fontwidth(p) * fontheight(p); + + CRITBEGIN + mga_fifo(3); mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE); mga_outl(M_FCOL, fgx); @@ -1475,10 +1574,12 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx); mga_outl(M_AR3, ar3); mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF); - mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); xx += fontwidth(p); } WaitTillIdle(); + + CRITEND } static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) { @@ -1504,7 +1605,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c step = 4; charcell = fontheight(p)*step; xlen = (charcell + 3) & ~3; - ydstlen = (yy<<16) | fontheight(p); + ydstlen = (yy << 16) | fontheight(p); if (fontwidth(p) == step << 3) { ar0 = fontheight(p)*fontwidth(p) - 1; easy = 1; @@ -1512,6 +1613,9 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c ar0 = fontwidth(p) - 1; easy = 0; } + + CRITBEGIN + #ifdef __BIG_ENDIAN WaitTillIdle(); mga_outl(M_OPMODE, M_OPMODE_8BPP); @@ -1529,7 +1633,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c while (count--) { u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell; - mga_fifo(5); + mga_fifo(6); mga_writel(mmio, M_FXBNDRY, fxbndry); mga_writel(mmio, M_AR0, ar0); mga_writel(mmio, M_AR3, 0); @@ -1573,6 +1677,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c #ifdef __BIG_ENDIAN mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); #endif + CRITEND } #ifdef FBCON_HAS_CFB8 @@ -1635,6 +1740,8 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) { xx |= (xx + fontwidth(p)) << 16; xx >>= 1; + CRITBEGIN + mga_fifo(5); mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR); mga_outl(M_FCOL, 0xFFFFFFFF); @@ -1642,6 +1749,8 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) { mga_outl(M_YDST, yy * p->var.xres_virtual >> 6); mga_outl(M_LEN | M_EXEC, fontheight(p)); WaitTillIdle(); + + CRITEND } #endif @@ -1654,12 +1763,16 @@ static void matrox_cfb8_revc(struct display* p, int xx, int yy) { yy *= fontheight(p); xx *= fontwidth(p); + CRITBEGIN + mga_fifo(4); mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR); mga_outl(M_FCOL, 0x0F0F0F0F); mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx); - mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); WaitTillIdle(); + + CRITEND } #endif @@ -1671,12 +1784,16 @@ static void matrox_cfbX_revc(struct display* p, int xx, int yy) { yy *= fontheight(p); xx *= fontwidth(p); + CRITBEGIN + mga_fifo(4); mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR); mga_outl(M_FCOL, 0xFFFFFFFF); mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx); - mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p)); + mga_ydstlen(yy, fontheight(p)); WaitTillIdle(); + + CRITEND } static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) { @@ -1840,6 +1957,9 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) { DBG("matroxfb_ti3026_cursor") + if (ACCESS_FBINFO(currcon_display) != p) + return; + if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags); @@ -1914,6 +2034,9 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) { xline = (~0) << (32 - ACCESS_FBINFO(cursor.w)); cursorbase = ACCESS_FBINFO(video.vbase); h = ACCESS_FBINFO(features.DAC1064.cursorimage); + + CRITBEGIN + #ifdef __BIG_ENDIAN WaitTillIdle(); mga_outl(M_OPMODE, M_OPMODE_32BPP); @@ -1944,12 +2067,17 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) { #ifdef __BIG_ENDIAN mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); #endif + + CRITEND } static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) { unsigned long flags; MINFO_FROM_DISP(p); + if (ACCESS_FBINFO(currcon_display) != p) + return; + if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags); @@ -2010,6 +2138,9 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) { fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p); if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size)) return 0; + + CRITBEGIN + mga_outl(M_OPMODE, M_OPMODE_8BPP); if (width <= 8) { if (width == 8) @@ -2100,6 +2231,9 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) { } } mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); + + CRITEND + return 1; } @@ -2117,6 +2251,8 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx, unsigned int step; MINFO_FROM_DISP(p); + CRITBEGIN + step = ACCESS_FBINFO(devflags.textstep); srcoff = (sy * p->next_line) + (sx * step); dstoff = (dy * p->next_line) + (dx * step); @@ -2144,6 +2280,7 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx, height--; } } + CRITEND } static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx, @@ -2156,6 +2293,9 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i step = ACCESS_FBINFO(devflags.textstep); offs = sy * p->next_line + sx * step; val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8)); + + CRITBEGIN + while (height > 0) { int i; for (i = width; i > 0; offs += step, i--) @@ -2163,6 +2303,7 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i offs += p->next_line - width * step; height--; } + CRITEND } static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) { @@ -2175,7 +2316,12 @@ static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int offs = yy * p->next_line + xx * step; chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8); if (chr & 0x10000) chr |= 0x08; + + CRITBEGIN + mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr)); + + CRITEND } static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, @@ -2188,12 +2334,17 @@ static void matrox_text_putcs(struct vc_data* conp, struct display* p, const uns step = ACCESS_FBINFO(devflags.textstep); offs = yy * p->next_line + xx * step; attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4); + + CRITBEGIN + while (count-- > 0) { unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8; if (chr & 0x10000) chr ^= 0x10008; mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr)); offs += step; } + + CRITEND } static void matrox_text_revc(struct display* p, int xx, int yy) { @@ -2203,7 +2354,12 @@ static void matrox_text_revc(struct display* p, int xx, int yy) { step = ACCESS_FBINFO(devflags.textstep); offs = yy * p->next_line + xx * step + 1; + + CRITBEGIN + mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77); + + CRITEND } static int matrox_text_loadfont(WPMINFO struct display* p) { @@ -2221,6 +2377,9 @@ static int matrox_text_loadfont(WPMINFO struct display* p) { dst = ACCESS_FBINFO(video.vbase); i = 2; font = (u_int8_t*)p->fontdata; + + CRITBEGIN + mga_setr(M_SEQ_INDEX, 0x02, 0x04); while (fsize--) { int l; @@ -2233,6 +2392,9 @@ static int matrox_text_loadfont(WPMINFO struct display* p) { i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep); } mga_setr(M_SEQ_INDEX, 0x02, 0x03); + + CRITEND + return 1; } @@ -2242,17 +2404,31 @@ static void matrox_text_createcursor(WPMINFO struct display* p) { return; matroxfb_createcursorshape(PMINFO p, 0); + + CRITBEGIN + mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u)); mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1); + + CRITEND } static void matrox_text_cursor(struct display* p, int mode, int x, int y) { unsigned int pos; MINFO_FROM_DISP(p); + if (ACCESS_FBINFO(currcon_display) != p) + return; + if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { + + CRITBEGIN + mga_setr(M_CRTC_INDEX, 0x0A, 0x20); + + CRITEND + ACCESS_FBINFO(cursor.state) = CM_ERASE; } return; @@ -2264,10 +2440,16 @@ static void matrox_text_cursor(struct display* p, int mode, int x, int y) { ACCESS_FBINFO(cursor.x) = x; ACCESS_FBINFO(cursor.y) = y; pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x; + + CRITBEGIN + mga_setr(M_CRTC_INDEX, 0x0F, pos); mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8); mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u)); + + CRITEND + ACCESS_FBINFO(cursor.state) = CM_DRAW; } @@ -2498,7 +2680,7 @@ static void initMatrox(WPMINFO struct display* p) { /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo vesafb_defined __initdata = { - 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/ + 640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/ 0,0, /* virtual -> visible no offset */ 8, /* depth -> load bits_per_pixel */ 0, /* greyscale ? */ @@ -2510,8 +2692,8 @@ static struct fb_var_screeninfo vesafb_defined __initdata = { FB_ACTIVATE_NOW, -1,-1, FB_ACCELF_TEXT, /* accel flags */ - 0L,0L,0L,0L,0L, - 0L,0L,0, /* No sync info */ + 39721L,48L,16L,33L,10L, + 96L,2L,~0, /* No sync info */ FB_VMODE_NONINTERLACED, {0,0,0,0,0,0} }; @@ -2523,6 +2705,9 @@ static struct fb_var_screeninfo vesafb_defined __initdata = { static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { unsigned int pos; unsigned short p0, p1, p2; +#ifdef CONFIG_FB_MATROX_32MB + unsigned int p3; +#endif struct display *disp; DBG("matrox_pan_var") @@ -2536,10 +2721,22 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { } p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF; p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8; - p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F); + p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); +#ifdef CONFIG_FB_MATROX_32MB + p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21; +#endif + + CRITBEGIN + mga_setr(M_CRTC_INDEX, 0x0D, p0); mga_setr(M_CRTC_INDEX, 0x0C, p1); +#ifdef CONFIG_FB_MATROX_32MB + if (ACCESS_FBINFO(devflags.support32MB)) + mga_setr(M_EXTVGA_INDEX, 0x08, p3); +#endif mga_setr(M_EXTVGA_INDEX, 0x00, p2); + + CRITEND } /* @@ -2627,13 +2824,16 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { case 0: return xres; case 4: rounding = 128; break; - case 8: rounding = 64; + case 8: rounding = 64; /* doc says 64; 32 is OK for G400 */ break; case 16: rounding = 32; break; - case 24: rounding = 64; + case 24: rounding = 64; /* doc says 64; 32 is OK for G400 */ break; default: rounding = 16; + /* on G400, 16 really does not work */ + if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) + rounding = 32; break; } if (isInterleave(MINFO)) { @@ -3140,7 +3340,7 @@ static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, unsigned long fo hw->DACclk[2] = p; } -__initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem)) { +static void __init DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem){ u_int32_t mx; DBG("DAC1064_setmclk") @@ -3288,6 +3488,8 @@ static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) { DBG("DAC1064_restore_1") + + CRITBEGIN outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); @@ -3298,6 +3500,8 @@ static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const st for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]); } + + CRITEND } static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) { @@ -3305,6 +3509,8 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st unsigned int tmout; DBG("DAC1064_restore_2") + + CRITBEGIN for (i = 0; i < 3; i++) outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]); @@ -3313,6 +3519,9 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st break; udelay(10); }; + + CRITEND + if (!tmout) printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); @@ -3585,7 +3794,9 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin var->pixclock = 15000; /* limit for "normal" gclk & mclk */ #endif } - + /* YDSTLEN contains only signed 16bit value */ + if (var->yres_virtual > 32767) + var->yres_virtual = 32767; if (var->yres_virtual < var->yres) var->yres = var->yres_virtual; if (var->xres_virtual < var->xres) @@ -3684,7 +3895,7 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin } #ifdef CONFIG_FB_MATROX_MILLENIUM -__initfunc(static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout)) { +static void __init ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){ unsigned int f_pll; unsigned int pclk_m, pclk_n, pclk_p; unsigned int mclk_m, mclk_n, mclk_p; @@ -3783,7 +3994,7 @@ __initfunc(static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fo printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); } -__initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) { +static void __init ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){ DBG("ti3026_ramdac_init") @@ -3800,7 +4011,7 @@ __initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) { } #endif -__initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) { +static void matroxfb_fastfont_init(struct matrox_fb_info* minfo){ unsigned int size; size = ACCESS_FBINFO(fastfont.size); @@ -3824,7 +4035,7 @@ __initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) { } #ifdef CONFIG_FB_MATROX_MYSTIQUE -__initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw)) { +static void __init MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){ DBG("MGA1064_ramdac_init"); @@ -3841,7 +4052,7 @@ __initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw)) DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); } -__initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) { +static int __init MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){ static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; @@ -3873,7 +4084,7 @@ __initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) { return 0; } -__initfunc(static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw)) { +static void __init MGA1064_reset(WPMINFO struct matrox_hw_state* hw){ DBG("MGA1064_reset"); @@ -3893,7 +4104,7 @@ static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */ static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ #endif -__initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p)) { +static void __init MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){ int reg; int selClk; int clk; @@ -3937,7 +4148,7 @@ __initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); } -__initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) { +static void __init MGAG100_setPixClock(CPMINFO int flags, int freq){ unsigned int m, n, p; DBG("MGAG100_setPixClock") @@ -3946,7 +4157,7 @@ __initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) { MGAG100_progPixClock(PMINFO flags, m, n, p); } -__initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) { +static int __init MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; @@ -4036,7 +4247,7 @@ __initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) { return 0; } -__initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) { +static void __init MGAG100_reset(WPMINFO struct matrox_hw_state* hw){ u_int8_t b; DBG("MGAG100_reset") @@ -4104,6 +4315,8 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st dprintk("%02X:", hw->ATTR[i]); dprintk("\n"); + CRITBEGIN + mga_inb(M_ATTR_RESET); mga_outb(M_ATTR_INDEX, 0); mga_outb(M_MISC_REG, hw->MiscOutReg); @@ -4125,6 +4338,8 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st mga_outb(M_DAC_VAL, hw->DACpal[i]); mga_inb(M_ATTR_RESET); mga_outb(M_ATTR_INDEX, 0x20); + + CRITEND } static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -4227,10 +4442,15 @@ static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw int i; DBG("MGA1064_restore") + + CRITBEGIN pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); mga_outb(M_IEN, 0x00); mga_outb(M_CACHEFLUSH, 0x00); + + CRITEND + DAC1064_restore_1(PMINFO hw, oldhw); vgaHWrestore(PMINFO hw, oldhw); for (i = 0; i < 6; i++) @@ -4244,10 +4464,18 @@ static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw int i; DBG("MGAG100_restore") - + + CRITBEGIN + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + CRITEND + DAC1064_restore_1(PMINFO hw, oldhw); vgaHWrestore(PMINFO hw, oldhw); +#ifdef CONFIG_FB_MATROX_32MB + if (ACCESS_FBINFO(devflags.support32MB)) + mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]); +#endif for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); DAC1064_restore_2(PMINFO hw, oldhw, p); @@ -4265,9 +4493,16 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ dprintk("%02X:", hw->CRTCEXT[i]); dprintk("\n"); + CRITBEGIN + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + CRITEND + vgaHWrestore(PMINFO hw, oldhw); + + CRITBEGIN + for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); @@ -4285,11 +4520,13 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); } + CRITEND if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) { /* agrhh... setting up PLL is very slow on Millenium... */ /* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */ /* Maybe even we should call schedule() ? */ + CRITBEGIN outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]); outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0); @@ -4307,24 +4544,31 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ break; udelay(10); } + + CRITEND + if (!tmout) printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); else dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout); + CRITBEGIN } outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]); outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); for (i = 3; i < 6; i++) outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]); + CRITEND if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) { int tmout; + CRITBEGIN outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F); for (tmout = 500000; tmout; --tmout) { if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40) break; udelay(10); } + CRITEND if (!tmout) printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n"); else @@ -4378,8 +4622,8 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"MATROX"); - fix->smem_start = (void*)ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); - fix->smem_len = ACCESS_FBINFO(video.len) - ACCESS_FBINFO(curr.ydstorg.bytes); + fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); + fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); fix->type = p->type; fix->type_aux = p->type_aux; fix->visual = p->visual; @@ -4387,7 +4631,7 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, fix->ypanstep = 1; fix->ywrapstep = 0; fix->line_length = p->line_length; - fix->mmio_start = (void*)ACCESS_FBINFO(mmio.base); + fix->mmio_start = ACCESS_FBINFO(mmio.base); fix->mmio_len = ACCESS_FBINFO(mmio.len); fix->accel = ACCESS_FBINFO(devflags.accelerator); return 0; @@ -4531,7 +4775,8 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, hw->CRTC[0x0D] = pos & 0xFF; hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; - hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F); + hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); + hw->CRTCEXT[8] = pos >> 21; ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display)); ACCESS_FBINFO(cursor.redraw) = 1; ACCESS_FBINFO(currenthw) = hw; @@ -4717,10 +4962,16 @@ static void matroxfb_blank(int blank, struct fb_info *info) case 4: seq = 0x20; crtc = 0x30; break; default: seq = 0x00; crtc = 0x00; break; } + + CRITBEGIN + mga_outb(M_SEQ_INDEX, 1); mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq); mga_outb(M_EXTVGA_INDEX, 1); mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc); + + CRITEND + #undef minfo } @@ -4739,7 +4990,8 @@ static void matroxfb_blank(int blank, struct fb_info *info) #define RS1056x344 12 /* 132 x 43 text */ #define RS1056x400 13 /* 132 x 50 text */ #define RS1056x480 14 /* 132 x 60 text */ -/* 0F-FF */ +#define RSNoxNo 15 +/* 10-FF */ static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = { { 640, 400, 48, 16, 39, 8, 96, 2, 70 }, { 640, 480, 48, 16, 33, 10, 96, 2, 60 }, @@ -4754,7 +5006,8 @@ static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; { 640, 350, 48, 16, 39, 8, 96, 2, 70 }, { 1056, 344, 96, 24, 59, 44, 160, 2, 70 }, { 1056, 400, 96, 24, 39, 8, 160, 2, 70 }, - { 1056, 480, 96, 24, 36, 12, 160, 3, 60 } + { 1056, 480, 96, 24, 36, 12, 160, 3, 60 }, + { 0, 0, ~0, ~0, ~0, ~0, 0, 0, 0 } }; #define RSDepth(X) (((X) >> 8) & 0x0F) @@ -4775,13 +5028,14 @@ static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 }, { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 }, { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode with (default) VGA8x16 */ - { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 } /* textmode hardwired to VGA8x8 */ + { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode hardwired to VGA8x8 */ }; #define RSCreate(X,Y) ((X) | ((Y) << 8)) static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = { /* default must be first */ #ifdef FBCON_HAS_CFB8 + { ~0, RSCreate(RSNoxNo, RS8bpp ) }, { 0x101, RSCreate(RS640x480, RS8bpp ) }, { 0x100, RSCreate(RS640x400, RS8bpp ) }, { 0x180, RSCreate(RS768x576, RS8bpp ) }, @@ -4793,14 +5047,8 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init { 0x198, RSCreate(RS1408x1056, RS8bpp ) }, { 0x11C, RSCreate(RS1600x1200, RS8bpp ) }, #endif -#ifdef FBCON_HAS_CFB4 - { 0x010, RSCreate(RS640x350, RS4bpp ) }, - { 0x012, RSCreate(RS640x480, RS4bpp ) }, - { 0x102, RSCreate(RS800x600, RS4bpp ) }, - { 0x104, RSCreate(RS1024x768, RS4bpp ) }, - { 0x106, RSCreate(RS1280x1024, RS4bpp ) }, -#endif #ifdef FBCON_HAS_CFB16 + { ~0, RSCreate(RSNoxNo, RS15bpp) }, { 0x110, RSCreate(RS640x480, RS15bpp) }, { 0x181, RSCreate(RS768x576, RS15bpp) }, { 0x113, RSCreate(RS800x600, RS15bpp) }, @@ -4821,6 +5069,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init { 0x11E, RSCreate(RS1600x1200, RS16bpp) }, #endif #ifdef FBCON_HAS_CFB24 + { ~0, RSCreate(RSNoxNo, RS24bpp) }, { 0x1B2, RSCreate(RS640x480, RS24bpp) }, { 0x184, RSCreate(RS768x576, RS24bpp) }, { 0x1B5, RSCreate(RS800x600, RS24bpp) }, @@ -4832,6 +5081,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init { 0x1BF, RSCreate(RS1600x1200, RS24bpp) }, #endif #ifdef FBCON_HAS_CFB32 + { ~0, RSCreate(RSNoxNo, RS32bpp) }, { 0x112, RSCreate(RS640x480, RS32bpp) }, { 0x183, RSCreate(RS768x576, RS32bpp) }, { 0x115, RSCreate(RS800x600, RS32bpp) }, @@ -4843,6 +5093,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init { 0x11F, RSCreate(RS1600x1200, RS32bpp) }, #endif #ifdef FBCON_HAS_VGATEXT + { ~0, RSCreate(RSNoxNo, RSText) }, { 0x002, RSCreate(RS640x400, RSText) }, /* 80x25 */ { 0x003, RSCreate(RS640x400, RSText) }, /* 80x25 */ { 0x007, RSCreate(RS640x400, RSText) }, /* 80x25 */ @@ -4853,6 +5104,14 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init { 0x10B, RSCreate(RS1056x400, RSText8) }, /* 132x50 */ { 0x10C, RSCreate(RS1056x480, RSText8) }, /* 132x60 */ #endif +#ifdef FBCON_HAS_CFB4 + { ~0, RSCreate(RSNoxNo, RS4bpp ) }, + { 0x010, RSCreate(RS640x350, RS4bpp ) }, + { 0x012, RSCreate(RS640x480, RS4bpp ) }, + { 0x102, RSCreate(RS800x600, RS4bpp ) }, + { 0x104, RSCreate(RS1024x768, RS4bpp ) }, + { 0x106, RSCreate(RS1280x1024, RS4bpp ) }, +#endif { 0, 0 }}; /* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */ @@ -4871,19 +5130,21 @@ static int inverse = 0; /* "matrox:inverse" */ static int hwcursor = 1; /* "matrox:nohwcursor" */ static int blink = 1; /* "matrox:noblink" */ static int sgram = 0; /* "matrox:sgram" */ +#ifdef CONFIG_MTRR static int mtrr = 1; /* "matrox:nomtrr" */ +#endif static int grayscale = 0; /* "matrox:grayscale" */ static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */ static int dev = -1; /* "matrox:dev:xxxxx" */ -static unsigned int vesa = 0x101; /* "matrox:vesa:xxxxx" */ +static unsigned int vesa = ~0; /* "matrox:vesa:xxxxx" */ static int depth = -1; /* "matrox:depth:xxxxx" */ static unsigned int xres = 0; /* "matrox:xres:xxxxx" */ static unsigned int yres = 0; /* "matrox:yres:xxxxx" */ -static unsigned int upper = 0; /* "matrox:upper:xxxxx" */ -static unsigned int lower = 0; /* "matrox:lower:xxxxx" */ +static unsigned int upper = ~0; /* "matrox:upper:xxxxx" */ +static unsigned int lower = ~0; /* "matrox:lower:xxxxx" */ static unsigned int vslen = 0; /* "matrox:vslen:xxxxx" */ -static unsigned int left = 0; /* "matrox:left:xxxxx" */ -static unsigned int right = 0; /* "matrox:right:xxxxx" */ +static unsigned int left = ~0; /* "matrox:left:xxxxx" */ +static unsigned int right = ~0; /* "matrox:right:xxxxx" */ static unsigned int hslen = 0; /* "matrox:hslen:xxxxx" */ static unsigned int pixclock = 0; /* "matrox:pixclock:xxxxx" */ static int sync = -1; /* "matrox:sync:xxxxx" */ @@ -4893,7 +5154,11 @@ static unsigned int maxclk = 0; /* "matrox:maxclk:xxxxM" */ static char fontname[64]; /* "matrox:font:xxxxx" */ #ifndef MODULE -__initfunc(void matroxfb_setup(char *options, int *ints)) { +static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ +#endif + +#ifndef MODULE +int __init matroxfb_setup(char *options) { char *this_opt; DBG("matroxfb_setup") @@ -4901,7 +5166,7 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) { fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; @@ -4945,7 +5210,7 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) { else if (!strncmp(this_opt, "vesa:", 5)) vesa = simple_strtoul(this_opt+5, NULL, 0); else if (!strncmp(this_opt, "font:", 5)) - strcpy(fontname, this_opt+5); + strncpy(fontname, this_opt+5, sizeof(fontname)-1); else if (!strncmp(this_opt, "maxclk:", 7)) maxclk = simple_strtoul(this_opt+7, NULL, 0); else if (!strncmp(this_opt, "fh:", 3)) @@ -4954,6 +5219,31 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) { fv = simple_strtoul(this_opt+3, NULL, 0); else if (!strncmp(this_opt, "mem:", 4)) mem = simple_strtoul(this_opt+4, NULL, 0); + else if (!strncmp(this_opt, "mode:", 5)) + strncpy(videomode, this_opt+5, sizeof(videomode)-1); +#ifdef CONFIG_FB_OF + else if (!strncmp(this_opt, "vmode:", 6)) { + unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0); + if (vmode > 0 && vmode <= VMODE_MAX) + default_vmode = vmode; + } else if (!strncmp(this_opt, "cmode:", 6)) { + unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0); + switch (cmode) { + case 0: + case 8: + default_cmode = CMODE_8; + break; + case 15: + case 16: + default_cmode = CMODE_16; + break; + case 24: + case 32: + default_cmode = CMODE_32; + break; + } + } +#endif else if (!strncmp(this_opt, "fastfont:", 9)) fastfont = simple_strtoul(this_opt+9, NULL, 0); else if (!strcmp(this_opt, "nofastfont")) /* fastfont:N and nofastfont (nofastfont = fastfont:0) */ @@ -4987,8 +5277,10 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) { nobios = !value; else if (!strcmp(this_opt, "init")) noinit = !value; +#ifdef CONFIG_MTRR else if (!strcmp(this_opt, "mtrr")) mtrr = value; +#endif else if (!strcmp(this_opt, "inv24")) inv24 = value; else if (!strcmp(this_opt, "cross4MB")) @@ -5000,19 +5292,20 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) { else if (!strcmp(this_opt, "grayscale")) grayscale = value; else { - printk(KERN_ERR "matroxfb: unknown parameter %s%s\n", value?"":"no", this_opt); + strncpy(videomode, this_opt, sizeof(videomode)-1); } } } + return 0; } -#endif +#endif /* !MODULE */ -__initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize)) { +static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize){ vaddr_t vm; unsigned int offs; unsigned int offs2; unsigned char store; - unsigned char bytes[16]; + unsigned char bytes[32]; unsigned char* tmp; unsigned long cbase; unsigned long mbase; @@ -5025,7 +5318,7 @@ __initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */ /* at least 2MB */ if (maxSize < 0x0200000) return 0; - if (maxSize > 0x1000000) maxSize = 0x1000000; + if (maxSize > 0x2000000) maxSize = 0x2000000; mga_outb(M_EXTVGA_INDEX, 0x03); mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80); @@ -5080,7 +5373,7 @@ __initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned } #ifdef CONFIG_FB_MATROX_MILLENIUM -__initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) { +static int __init Ti3026_preinit(WPMINFO struct matrox_hw_state* hw){ static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; @@ -5133,7 +5426,7 @@ __initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) { return 0; } -__initfunc(static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw)) { +static void __init Ti3026_reset(WPMINFO struct matrox_hw_state* hw){ DBG("Ti3026_reset") @@ -5163,20 +5456,28 @@ static struct matrox_switch matrox_G100 = { struct video_board { int maxvram; + int maxdisplayable; int accelID; struct matrox_switch* lowlevel; }; #ifdef CONFIG_FB_MATROX_MILLENIUM -static struct video_board vbMillenium __initdata = {0x0800000, FB_ACCEL_MATROX_MGA2064W, &matrox_millenium}; -static struct video_board vbMillenium2 __initdata = {0x1000000, FB_ACCEL_MATROX_MGA2164W, &matrox_millenium}; -static struct video_board vbMillenium2A __initdata = {0x1000000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millenium}; +static struct video_board vbMillenium __initdata = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W, &matrox_millenium}; +static struct video_board vbMillenium2 __initdata = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W, &matrox_millenium}; +static struct video_board vbMillenium2A __initdata = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millenium}; #endif /* CONFIG_FB_MATROX_MILLENIUM */ #ifdef CONFIG_FB_MATROX_MYSTIQUE -static struct video_board vbMystique __initdata = {0x0800000, FB_ACCEL_MATROX_MGA1064SG, &matrox_mystique}; +static struct video_board vbMystique __initdata = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG, &matrox_mystique}; #endif /* CONFIG_FB_MATROX_MYSTIQUE */ #ifdef CONFIG_FB_MATROX_G100 -static struct video_board vbG100 __initdata = {0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100}; -static struct video_board vbG200 __initdata = {0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100}; +static struct video_board vbG100 __initdata = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100}; +static struct video_board vbG200 __initdata = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100}; +#ifdef CONFIG_FB_MATROX_32MB +/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for + whole 32MB */ +static struct video_board vbG400 __initdata = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100}; +#else +static struct video_board vbG400 __initdata = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100}; +#endif #endif #define DEVF_VIDEO64BIT 0x01 @@ -5185,6 +5486,15 @@ static struct video_board vbG200 __initdata = {0x1000000, FB_ACCEL_MATROX_MGAG2 #define DEVF_MILLENIUM2 0x08 #define DEVF_CROSS4MB 0x10 #define DEVF_TEXT4B 0x20 +#define DEVF_DDC_8_2 0x40 +#define DEVF_DMA 0x80 +#define DEVF_SUPPORT32MB 0x100 +#define DEVF_ANY_VXRES 0x200 + +#define DEVF_G100 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2) /* no doc, no vxres... */ +#define DEVF_G200 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES) +#define DEVF_G400 (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES | DEVF_SUPPORT32MB) + static struct board { unsigned short vendor, device, rev, svid, sid; unsigned int flags; @@ -5229,88 +5539,94 @@ static struct board { #ifdef CONFIG_FB_MATROX_G100 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "MGA-G100 (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "unknown G100 (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "MGA-G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "MGA-G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G100_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "MGA-G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "Productiva G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G100, 230000, &vbG100, "unknown G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 250000, &vbG200, "unknown G200 (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 220000, &vbG200, "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 230000, &vbG200, "Mystique G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 250000, &vbG200, "Millennium G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 230000, &vbG200, "Marvel G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 230000, &vbG200, "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + DEVF_G200, 230000, &vbG200, "unknown G200 (AGP)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400_AGP, 0xFF, + 0, 0, + DEVF_G400, + 360000, + &vbG400, + "unknown G400 (AGP)"}, #endif {0, 0, 0xFF, 0, 0, @@ -5319,7 +5635,17 @@ static struct board { NULL, NULL}}; -__initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { +#ifndef MODULE + /* it cannot be static const struct due to __initdata + marker */ + static struct fb_videomode defaultmode __initdata = { + /* 640x480 @ 60Hz, 31.5 kHz */ + NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, + 0, FB_VMODE_NONINTERLACED + }; +#endif /* !MODULE */ + +static int __init initMatrox2(WPMINFO struct display* d, struct board* b){ unsigned long ctrlptr_phys = 0; unsigned long video_base_phys = 0; unsigned int memsize; @@ -5348,17 +5674,21 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { ACCESS_FBINFO(devflags.vgastepdisp) = 64; ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8; } +#ifdef CONFIG_FB_MATROX_32MB + ACCESS_FBINFO(devflags.support32MB) = b->flags & DEVF_SUPPORT32MB; +#endif + ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES); ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); if (ACCESS_FBINFO(capable.cross4MB) < 0) ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB; if (b->flags & DEVF_SWAPS) { - ctrlptr_phys = ACCESS_FBINFO(pcidev)->base_address[1] & ~0x3FFF; - video_base_phys = ACCESS_FBINFO(pcidev)->base_address[0] & ~0x7FFFFF; /* aligned at 8MB (or 16 for Mill 2) */ + ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[1].start; + video_base_phys = ACCESS_FBINFO(pcidev)->resource[0].start; } else { - ctrlptr_phys = ACCESS_FBINFO(pcidev)->base_address[0] & ~0x3FFF; - video_base_phys = ACCESS_FBINFO(pcidev)->base_address[1] & ~0x7FFFFF; /* aligned at 8MB */ + ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[0].start; + video_base_phys = ACCESS_FBINFO(pcidev)->resource[1].start; } if (!ctrlptr_phys) { printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n"); @@ -5472,8 +5802,8 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { return -ENOMEM; } ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len); - if (ACCESS_FBINFO(video.len_usable) > 0x08000000) - ACCESS_FBINFO(video.len_usable) = 0x08000000; + if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable) + ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable; #ifdef CONFIG_MTRR if (mtrr) { ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1); @@ -5482,11 +5812,16 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { } #endif /* CONFIG_MTRR */ + if (!ACCESS_FBINFO(devflags.novga)) + request_region(0x3C0, 32, "matrox"); + ACCESS_FBINFO(hw_switch->reset(PMINFO hw)); + /* validate params, autodetect k, M */ if (fh < 1000) fh *= 1000; /* 1kHz minimum */ if (maxclk < 1000) maxclk *= 1000; /* kHz -> Hz, MHz -> kHz */ if (maxclk < 1000000) maxclk *= 1000; /* kHz -> Hz, 1MHz minimum */ - vesa &= 0x1DFF; /* mask out clearscreen, acceleration and so on */ + if (vesa != ~0) + vesa &= 0x1DFF; /* mask out clearscreen, acceleration and so on */ ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0; ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh; @@ -5504,19 +5839,19 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { } { int res = RSResolution(RSptr->info)-1; - if (!left) + if (left == ~0) left = timmings[res].left; if (!xres) xres = timmings[res].xres; - if (!right) + if (right == ~0) right = timmings[res].right; if (!hslen) hslen = timmings[res].hslen; - if (!upper) + if (upper == ~0) upper = timmings[res].upper; if (!yres) yres = timmings[res].yres; - if (!lower) + if (lower == ~0) lower = timmings[res].lower; if (!vslen) vslen = timmings[res].vslen; @@ -5525,38 +5860,6 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { if (depth == -1) depth = RSDepth(RSptr->info); } - if (sync == -1) { - sync = 0; - if (yres < 400) - sync |= FB_SYNC_HOR_HIGH_ACT; - else if (yres < 480) - sync |= FB_SYNC_VERT_HIGH_ACT; - } - if (xres < 320) - xres = 320; - if (xres > 2048) - xres = 2048; - if (yres < 200) - yres = 200; - if (yres > 2048) - yres = 2048; - { - unsigned int tmp; - - if (fv) { - tmp = fv * (upper + yres + lower + vslen); - if ((tmp < fh) || (fh == 0)) fh = tmp; - } - if (fh) { - tmp = fh * (left + xres + right + hslen); - if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp; - } - maxclk = (maxclk + 499) / 500; - if (maxclk) { - tmp = (2000000000 + maxclk) / maxclk; - if (tmp > pixclock) pixclock = tmp; - } - } if ((depth == RSText8) && (!*ACCESS_FBINFO(fbcon.fontname))) { strcpy(ACCESS_FBINFO(fbcon.fontname), "VGA8x8"); } @@ -5564,27 +5867,8 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { vesafb_defined.green = colors[depth-1].green; vesafb_defined.blue = colors[depth-1].blue; vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel; - if (pixclock < 2000) /* > 500MHz */ - pixclock = 4000; /* 250MHz */ - if (pixclock > 1000000) - pixclock = 1000000; /* 1MHz */ - vesafb_defined.xres = xres; - vesafb_defined.yres = yres; - vesafb_defined.xoffset = 0; - vesafb_defined.yoffset = 0; vesafb_defined.grayscale = grayscale; - vesafb_defined.pixclock = pixclock; - vesafb_defined.left_margin = left; - vesafb_defined.right_margin = right; - vesafb_defined.hsync_len = hslen; - vesafb_defined.upper_margin = upper; - vesafb_defined.lower_margin = lower; - vesafb_defined.vsync_len = vslen; - vesafb_defined.sync = sync; vesafb_defined.vmode = 0; - - if (!ACCESS_FBINFO(devflags.novga)) - request_region(0x3C0, 32, "matrox"); if (noaccel) vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT; @@ -5597,8 +5881,72 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { ACCESS_FBINFO(fbcon.updatevar) = &matroxfb_updatevar; ACCESS_FBINFO(fbcon.blank) = &matroxfb_blank; ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT; - ACCESS_FBINFO(hw_switch->reset(PMINFO hw)); ACCESS_FBINFO(video.len_usable) &= PAGE_MASK; + +#ifndef MODULE + /* mode database is marked __init ... */ + { + fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL, + NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel); + } +#endif /* !MODULE */ + + /* mode modifiers */ + if (hslen) + vesafb_defined.hsync_len = hslen; + if (vslen) + vesafb_defined.vsync_len = vslen; + if (left != ~0) + vesafb_defined.left_margin = left; + if (right != ~0) + vesafb_defined.right_margin = right; + if (upper != ~0) + vesafb_defined.upper_margin = upper; + if (lower != ~0) + vesafb_defined.lower_margin = lower; + if (xres) + vesafb_defined.xres = xres; + if (yres) + vesafb_defined.yres = yres; + if (sync != -1) + vesafb_defined.sync = sync; + else if (vesafb_defined.sync == ~0) { + vesafb_defined.sync = 0; + if (yres < 400) + vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT; + else if (yres < 480) + vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT; + } + + /* fv, fh, maxclk limits was specified */ + { + unsigned int tmp; + + if (fv) { + tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres + + vesafb_defined.lower_margin + vesafb_defined.vsync_len); + if ((tmp < fh) || (fh == 0)) fh = tmp; + } + if (fh) { + tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres + + vesafb_defined.right_margin + vesafb_defined.hsync_len); + if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp; + } + maxclk = (maxclk + 499) / 500; + if (maxclk) { + tmp = (2000000000 + maxclk) / maxclk; + if (tmp > pixclock) pixclock = tmp; + } + } + if (pixclock) { + if (pixclock < 2000) /* > 500MHz */ + pixclock = 4000; /* 250MHz */ + if (pixclock > 1000000) + pixclock = 1000000; /* 1MHz */ + vesafb_defined.pixclock = pixclock; + } + + /* FIXME: Where to move this?! */ #if defined(CONFIG_FB_OF) #if defined(CONFIG_FB_COMPAT_XPMAC) strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */ @@ -5608,30 +5956,30 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { #endif if ((xres <= 640) && (yres <= 480)) { struct fb_var_screeninfo var; - int default_vmode = nvram_read_byte(NV_VMODE); - int default_cmode = nvram_read_byte(NV_CMODE); - - if ((default_vmode <= 0) || (default_vmode > VMODE_MAX)) + if (default_vmode == VMODE_NVRAM) { + default_vmode = nvram_read_byte(NV_VMODE); + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_CHOOSE; + } + if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_640_480_60; - if ((default_cmode < CMODE_8) || (default_cmode > CMODE_32)) + if (default_cmode == CMODE_NVRAM) + default_cmode = nvram_read_byte(NV_CMODE); + if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) { var.accel_flags = vesafb_defined.accel_flags; var.xoffset = var.yoffset = 0; vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */ - } + } } #endif - { - int pixel_size = vesafb_defined.bits_per_pixel; - - vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO vesafb_defined.xres, pixel_size); - if (nopan) { - vesafb_defined.yres_virtual = vesafb_defined.yres; - } else { - vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough - to yres_virtual * xres_virtual < 2^32 */ - } + vesafb_defined.xres_virtual = vesafb_defined.xres; + if (nopan) { + vesafb_defined.yres_virtual = vesafb_defined.yres; + } else { + vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough + to yres_virtual * xres_virtual < 2^32 */ } if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) { printk(KERN_ERR "matroxfb: cannot set required parameters\n"); @@ -5647,8 +5995,9 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { /* We do not have to set currcon to 0... register_framebuffer do it for us on first console * and we do not want currcon == 0 for subsequent framebuffers */ - if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) + if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) { return -EINVAL; + } printk("fb%d: %s frame buffer device\n", GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), ACCESS_FBINFO(fbcon.modename)); if (ACCESS_FBINFO(currcon) < 0) { @@ -5663,7 +6012,7 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) { static struct matrox_fb_info* fb_list = NULL; -__initfunc(static int matrox_init(void)) { +static int __init matrox_init(void){ struct pci_dev* pdev = NULL; DBG("matrox_init") @@ -5756,7 +6105,7 @@ leave:; #ifndef MODULE static int __init initialized = 0; -__initfunc(void matroxfb_init(void)) +int __init matroxfb_init(void) { DBG("matroxfb_init") @@ -5764,10 +6113,12 @@ __initfunc(void matroxfb_init(void)) initialized = 1; matrox_init(); } + if (!fb_list) return -ENXIO; + return 0; } #if defined(CONFIG_FB_OF) -__initfunc(int matrox_of_init(struct device_node *dp)) { +int __init matrox_of_init(struct device_node *dp){ DBG("matrox_of_init"); if (!initialized) { @@ -5781,8 +6132,8 @@ __initfunc(int matrox_of_init(struct device_node *dp)) { #else -MODULE_AUTHOR("(c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>"); -MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200"); +MODULE_AUTHOR("(c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>"); +MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400"); MODULE_PARM(mem, "i"); MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)"); MODULE_PARM(disabled, "i"); @@ -5802,7 +6153,7 @@ MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization MODULE_PARM(mtrr, "i"); MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)"); MODULE_PARM(sgram, "i"); -MODULE_PARM_DESC(sgram, "Indicates that G200 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)"); +MODULE_PARM_DESC(sgram, "Indicates that G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)"); MODULE_PARM(inv24, "i"); MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)"); MODULE_PARM(inverse, "i"); @@ -5855,14 +6206,20 @@ MODULE_PARM(grayscale, "i"); MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)"); MODULE_PARM(cross4MB, "i"); MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)"); +#ifdef CONFIG_FB_OF +MODULE_PARM(vmode, "i"); +MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)"); +MODULE_PARM(cmode, "i"); +MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)"); +#endif -__initfunc(int init_module(void)) { +int __init init_module(void){ DBG("init_module") #ifdef DEBUG if( disabled ) - return 0; + return -ENXIO; #endif /* DEBUG */ if (depth == 0) diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c index ae32da083..0c45722fe 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/mdacon.c @@ -182,7 +182,7 @@ static inline void mda_set_cursor_size(int from, int to) #ifndef MODULE -__initfunc(void mdacon_setup(char *str, int *ints)) +void __init mdacon_setup(char *str, int *ints) { /* command line format: mdacon=<first>,<last> */ @@ -201,7 +201,7 @@ __initfunc(void mdacon_setup(char *str, int *ints)) #ifdef MODULE static int mda_detect(void) #else -__initfunc(static int mda_detect(void)) +static int __init mda_detect(void) #endif { int count=0; @@ -283,7 +283,7 @@ __initfunc(static int mda_detect(void)) #ifdef MODULE static void mda_initialize(void) #else -__initfunc(static void mda_initialize(void)) +static void __init mda_initialize(void) #endif { write_mda_b(97, 0x00); /* horizontal total */ @@ -312,7 +312,7 @@ __initfunc(static void mda_initialize(void)) #ifdef MODULE static const char *mdacon_startup(void) #else -__initfunc(static const char *mdacon_startup(void)) +static const char __init *mdacon_startup(void) #endif { mda_num_columns = 80; @@ -591,7 +591,7 @@ struct consw mda_con = { #ifdef MODULE void mda_console_init(void) #else -__initfunc(void mda_console_init(void)) +void __init mda_console_init(void) #endif { if (mda_first_vc > mda_last_vc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c new file mode 100644 index 000000000..af58b457a --- /dev/null +++ b/drivers/video/modedb.c @@ -0,0 +1,410 @@ +/* + * linux/drivers/video/modedb.c -- Standard video mode database management + * + * Copyright (C) 1999 Geert Uytterhoeven + * + * 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/tty.h> +#include <linux/fb.h> +#include <linux/console_struct.h> +#include <linux/sched.h> + + +#define DEBUG + +#define name_matches(v, s, l) \ + ((v).name && !strncmp((s), (v).name, (l)) && strlen((v).name) == (l)) +#define res_matches(v, x, y) \ + ((v).xres == (x) && (v).yres == (y)) + +#ifdef DEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + + +const char *global_mode_option = NULL; + + + /* + * Standard video mode definitions (taken from XFree86) + */ + +#define DEFAULT_MODEDB_INDEX 0 + +static const struct fb_videomode modedb[] __initdata = { + { + /* 640x400 @ 70 Hz, 31.5 kHz hsync */ + NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, + 0, FB_VMODE_NONINTERLACED + }, { + /* 640x480 @ 60 Hz, 31.5 kHz hsync */ + NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600 @ 56 Hz, 35.15 kHz hsync */ + NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ + NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, + 0, FB_VMODE_INTERLACED + }, { + /* 640x400 @ 85 Hz, 37.86 kHz hsync */ + NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 640x480 @ 72 Hz, 36.5 kHz hsync */ + NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 640x480 @ 75 Hz, 37.50 kHz hsync */ + NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600 @ 60 Hz, 37.8 kHz hsync */ + NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 640x480 @ 85 Hz, 43.27 kHz hsync */ + NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ + NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, + 0, FB_VMODE_INTERLACED + }, { + /* 800x600 @ 72 Hz, 48.0 kHz hsync */ + NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ + NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 640x480 @ 100 Hz, 53.01 kHz hsync */ + NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ + NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, + 0, FB_VMODE_NONINTERLACED + }, { + /* 800x600 @ 85 Hz, 55.84 kHz hsync */ + NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ + NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ + NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, + 0, FB_VMODE_INTERLACED + }, { + /* 800x600 @ 100 Hz, 64.02 kHz hsync */ + NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ + NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ + NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ + NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ + NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ + NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ + NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ + NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ + NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ + NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1024x768 @ 100Hz, 80.21 kHz hsync */ + NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ + NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ + NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ + NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ + NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ + NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ + NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ + NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, + 0, FB_VMODE_NONINTERLACED + }, { + /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ + NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ + NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + }, { + /* 512x384 @ 78 Hz, 31.50 kHz hsync */ + NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 512x384 @ 85 Hz, 34.38 kHz hsync */ + NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED + }, { + /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ + NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, + 0, FB_VMODE_DOUBLE + }, { + /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ + NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, + 0, FB_VMODE_DOUBLE + }, { + /* 320x240 @ 72 Hz, 36.5 kHz hsync */ + NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, + 0, FB_VMODE_DOUBLE + }, { + /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ + NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, + 0, FB_VMODE_DOUBLE + }, { + /* 400x300 @ 60 Hz, 37.8 kHz hsync */ + NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, + 0, FB_VMODE_DOUBLE + }, { + /* 400x300 @ 72 Hz, 48.0 kHz hsync */ + NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, + 0, FB_VMODE_DOUBLE + }, { + /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ + NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, + 0, FB_VMODE_DOUBLE + }, { + /* 480x300 @ 60 Hz, 37.8 kHz hsync */ + NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, + 0, FB_VMODE_DOUBLE + }, { + /* 480x300 @ 63 Hz, 39.6 kHz hsync */ + NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, + 0, FB_VMODE_DOUBLE + }, { + /* 480x300 @ 72 Hz, 48.0 kHz hsync */ + NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, + 0, FB_VMODE_DOUBLE + }, +}; + + +static int __init my_atoi(const char *name) +{ + int val = 0; + + for (;; name++) { + switch (*name) { + case '0'...'9': + val = 10*val+(*name-'0'); + break; + default: + return val; + } + } +} + +static int __init PROC_CONSOLE(const struct fb_info *info) +{ + int fgc; + + if (info->display_fg != NULL) + fgc = info->display_fg->vc_num; + else + return -1; + + if (!current->tty) + return fgc; + + if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) + /* XXX Should report error here? */ + return fgc; + + if (MINOR(current->tty->device) < 1) + return fgc; + + return MINOR(current->tty->device) - 1; +} + +static int __init try_mode(struct fb_var_screeninfo *var, struct fb_info *info, + const struct fb_videomode *mode, unsigned int bpp) +{ + int err; + + DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname", + mode->xres, mode->yres, bpp, mode->refresh); + var->xres = mode->xres; + var->yres = mode->yres; + var->xres_virtual = mode->xres; + var->yres_virtual = mode->yres; + var->xoffset = 0; + var->yoffset = 0; + var->bits_per_pixel = bpp; + var->activate |= FB_ACTIVATE_TEST; + var->pixclock = mode->pixclock; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->hsync_len = mode->hsync_len; + var->vsync_len = mode->vsync_len; + var->sync = mode->sync; + var->vmode = mode->vmode; + err = info->fbops->fb_set_var(var, PROC_CONSOLE(info), info); + var->activate &= ~FB_ACTIVATE_TEST; + return !err; +} + + + /* + * + * Find a suitable video mode + * + * Valid mode specifiers (mode_option): + * + * <xres>x<yres>[-<bpp>][@<refresh>] + * <name>[-<bpp>][@<refresh>] + * + * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a + * string + * + * The passed struct fb_var_screeninfo is _not_ cleared! This allows you + * to supply values for e.g. the grayscale and accel_flags fields. + */ + +int __init fb_find_mode(struct fb_var_screeninfo *var, + struct fb_info *info, const char *mode_option, + const struct fb_videomode *db, unsigned int dbsize, + const struct fb_videomode *default_mode, + unsigned int default_bpp) +{ + int i, j; + + /* Set up defaults */ + if (!db) { + db = modedb; + dbsize = sizeof(modedb)/sizeof(*modedb); + } + if (!default_mode) + default_mode = &modedb[DEFAULT_MODEDB_INDEX]; + if (!default_bpp) + default_bpp = 8; + + /* Did the user specify a video mode? */ + if (mode_option || (mode_option = global_mode_option)) { + const char *name = mode_option; + unsigned int namelen = strlen(name); + int res_specified = 0, bpp_specified = 0, refresh_specified = 0; + unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; + int yres_specified = 0; + + for (i = namelen-1; i >= 0; i--) { + switch (name[i]) { + case '@': + namelen = i; + if (!refresh_specified && !bpp_specified && + !yres_specified) { + refresh = my_atoi(&name[i+1]); + refresh_specified = 1; + } else + goto done; + break; + case '-': + namelen = i; + if (!bpp_specified && !yres_specified) { + bpp = my_atoi(&name[i+1]); + bpp_specified = 1; + } else + goto done; + break; + case 'x': + if (!yres_specified) { + yres = my_atoi(&name[i+1]); + yres_specified = 1; + } else + goto done; + break; + case '0'...'9': + break; + default: + goto done; + } + } + if (i < 0 && yres_specified) { + xres = my_atoi(name); + res_specified = 1; + } +done: + for (i = refresh_specified; i >= 0; i--) { + DPRINTK("Trying specified video mode%s\n", + i ? "" : " (ignoring refresh rate)"); + for (j = 0; j < dbsize; j++) + if ((name_matches(db[j], name, namelen) || + (res_specified && res_matches(db[j], xres, yres))) && + (!i || db[j].refresh == refresh) && + try_mode(var, info, &db[j], bpp)) + return 2-i; + } + } + + DPRINTK("Trying default video mode\n"); + if (try_mode(var, info, default_mode, default_bpp)) + return 3; + + DPRINTK("Trying all modes\n"); + for (i = 0; i < dbsize; i++) + if (try_mode(var, info, &db[i], default_bpp)) + return 4; + + DPRINTK("No valid mode found\n"); + return 0; +} diff --git a/drivers/video/newport_con.c b/drivers/video/newport_con.c index f47cb6c1c..3d461df5d 100644 --- a/drivers/video/newport_con.c +++ b/drivers/video/newport_con.c @@ -272,7 +272,7 @@ static void newport_get_revisions(void) #ifdef MODULE static const char *newport_startup(void) #else -__initfunc(static const char *newport_startup(void)) +static const char * __init newport_startup(void) #endif { struct newport_regs *p; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index a769e9454..068282244 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -72,8 +72,8 @@ static int ofonly = 0; * Interface used by the world */ -void offb_init(void); -void offb_setup(char *options, int *ints); +int offb_init(void); +int offb_setup(char*); static int offb_open(struct fb_info *info, int user); static int offb_release(struct fb_info *info, int user); @@ -314,13 +314,16 @@ extern void valkyrie_of_init(struct device_node *dp); #ifdef CONFIG_FB_PLATINUM extern void platinum_of_init(struct device_node *dp); #endif /* CONFIG_FB_PLATINUM */ +#ifdef CONFIG_FB_CLGEN +extern void clgen_of_init(struct device_node *dp); +#endif /* CONFIG_FB_CLGEN */ /* * Initialisation */ -__initfunc(void offb_init(void)) +int __init offb_init(void) { struct device_node *dp; unsigned int dpy; @@ -389,9 +392,10 @@ __initfunc(void offb_init(void)) offb_init_driver(dp); } } + return 0; } -__initfunc(static int offb_init_driver(struct device_node *dp)) +static int __init offb_init_driver(struct device_node *dp) { #ifdef CONFIG_FB_ATY if (!strncmp(dp->name, "ATY", 3)) { @@ -441,10 +445,17 @@ __initfunc(static int offb_init_driver(struct device_node *dp)) return 1; } #endif /* CONFIG_FB_PLATINUM */ +#ifdef CONFIG_FB_CLGEN + if ((!strncmp(dp->name, "MacPicasso",10) || + (!strncmp(dp->name, "54m30",5)) { + clgen_of_init(dp); + return 1; + } +#endif /* CONFIG_FB_CLGEN */ return 0; } -__initfunc(static void offb_init_nodriver(struct device_node *dp)) +static void __init offb_init_nodriver(struct device_node *dp) { int *pp, i; unsigned int len; @@ -473,7 +484,7 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp)) if (dp->addrs[i].size >= len) break; if (i >= dp->n_addrs) { - printk("no framebuffer address found for %s\n", dp->full_name); + printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name); return; } @@ -488,9 +499,9 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp)) } -__initfunc(static void offb_init_fb(const char *name, const char *full_name, +static void offb_init_fb(const char *name, const char *full_name, int width, int height, int depth, - int pitch, unsigned long address)) + int pitch, unsigned long address) { int i; struct fb_fix_screeninfo *fix; @@ -501,7 +512,7 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name, printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n", width, height, name, address, depth, pitch); if (depth != 8 && depth != 16 && depth != 32) { - printk("%s: can't use depth = %d\n", full_name, depth); + printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth); return; } @@ -522,7 +533,7 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name, var->yres = var->yres_virtual = height; fix->line_length = pitch; - fix->smem_start = (char *)address; + fix->smem_start = address; fix->smem_len = pitch * height; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -674,7 +685,7 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name, return; } - printk("fb%d: Open Firmware frame buffer device on %s\n", + printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", GET_FB_IDX(info->info.node), full_name); #ifdef CONFIG_FB_COMPAT_XPMAC @@ -706,13 +717,14 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name, * Setup: parse used options */ -void offb_setup(char *options, int *ints) +int offb_setup(char *options) { if (!options || !*options) - return; + return 0; if (!strcmp(options, "ofonly")) ofonly = 1; + return 0; } diff --git a/drivers/video/p9100.h b/drivers/video/p9100.h new file mode 100644 index 000000000..152b41769 --- /dev/null +++ b/drivers/video/p9100.h @@ -0,0 +1,87 @@ +/* + * Register information for the Weitek P9100 as found + * on the Tadpole Sparcbook 3 laptops. + * + * From the technical specification document provided by Tadpole. + * + * Derrick J Brashear (shadow@dementia.org) + */ + +#ifndef _P9100_H_ +#define _P9100_H_ + +/* P9100 control registers */ +#define P9100_SYSCTL_OFF 0x0 +#define P9100_VIDEOCTL_OFF 0x100 +#define P9100_VRAMCTL_OFF 0x180 +#define P9100_RAMDAC_OFF 0x200 +#define P9100_VIDEOCOPROC_OFF 0x400 + +/* P9100 command registers */ +#define P9100_CMD_OFF 0x0 + +/* P9100 framebuffer memory */ +#define P9100_FB_OFF 0x0 + + +/* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */ +#define SYS_CONFIG_PIXELSIZE_SHIFT 26 + +#define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */ + +struct p9100_ctrl { + /* Registers for the system control */ + __volatile__ __u32 sys_base; + __volatile__ __u32 sys_config; + __volatile__ __u32 sys_intr; + __volatile__ __u32 sys_int_ena; + __volatile__ __u32 sys_alt_rd; + __volatile__ __u32 sys_alt_wr; + __volatile__ __u32 sys_xxx[58]; + /* Registers for the video control */ + __volatile__ __u32 vid_base; + __volatile__ __u32 vid_hcnt; + __volatile__ __u32 vid_htotal; + __volatile__ __u32 vid_hsync_rise; + __volatile__ __u32 vid_hblank_rise; + __volatile__ __u32 vid_hblank_fall; + __volatile__ __u32 vid_hcnt_preload; + __volatile__ __u32 vid_vcnt; + __volatile__ __u32 vid_vlen; + __volatile__ __u32 vid_vsync_rise; + __volatile__ __u32 vid_vblank_rise; + __volatile__ __u32 vid_vblank_fall; + __volatile__ __u32 vid_vcnt_preload; + __volatile__ __u32 vid_screenpaint_addr; + __volatile__ __u32 vid_screenpaint_timectl1; + __volatile__ __u32 vid_screenpaint_qsfcnt; + __volatile__ __u32 vid_screenpaint_timectl2; + __volatile__ __u32 vid_xxx[15]; + /* Registers for the video control */ + __volatile__ __u32 vram_base; + __volatile__ __u32 vram_memcfg; + __volatile__ __u32 vram_refresh_pd; + __volatile__ __u32 vram_refresh_cnt; + __volatile__ __u32 vram_raslo_max; + __volatile__ __u32 vram_raslo_cur; + __volatile__ __u32 pwrup_cfg; + __volatile__ __u32 vram_xxx[25]; + /* Registers for IBM RGB528 Palette */ + __volatile__ __u32 ramdac_cmap_wridx; + __volatile__ __u32 ramdac_palette_data; + __volatile__ __u32 ramdac_pixel_mask; + __volatile__ __u32 ramdac_palette_rdaddr; + __volatile__ __u32 ramdac_idx_lo; + __volatile__ __u32 ramdac_idx_hi; + __volatile__ __u32 ramdac_idx_data; + __volatile__ __u32 ramdac_idx_ctl; + __volatile__ __u32 ramdac_xxx[1784]; +}; + +struct p9100_cmd_parameng { + __volatile__ __u32 parameng_status; + __volatile__ __u32 parameng_bltcmd; + __volatile__ __u32 parameng_quadcmd; +}; + +#endif /* _P9100_H_ */ diff --git a/drivers/video/p9100fb.c b/drivers/video/p9100fb.c new file mode 100644 index 000000000..cbecb5e4f --- /dev/null +++ b/drivers/video/p9100fb.c @@ -0,0 +1,178 @@ +/* $id: p9100fb.c,v 1.4 1999/08/18 10:55:01 shadow Exp $ + * p9100fb.c: P9100 frame buffer driver + * + * Copyright 1999 Derrick J Brashear (shadow@dementia.org) + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/selection.h> + +#include <video/sbusfb.h> +#include <asm/io.h> + +#include <video/fbcon-cfb8.h> + +#include "p9100.h" + +static struct sbus_mmap_map p9100_mmap_map[] = { +#if 0 /* For now, play we're a dumb color fb */ + { P9100_CTL_OFF, 0x38000000, 0x2000 }, + { P9100_CMD_OFF, 0x38002000, 0x2000 }, + { P9100_FB_OFF, 0x38800000, 0x200000 }, + { CG3_MMAP_OFFSET, 0x38800000, SBUS_MMAP_FBSIZE(1) }, +#else + { CG3_MMAP_OFFSET, 0x0, SBUS_MMAP_FBSIZE(1) }, +#endif + { 0, 0, 0 } +}; + +#define _READCTL(member, out) \ +{ \ + struct p9100_ctrl *actual; \ + actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ + out = actual-> ## member ; \ +} + +#define READCTL(member, out) \ +{ \ + struct p9100_ctrl *enab, *actual; \ + actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ + enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \ + out = enab-> ## member ; \ + out = actual-> ## member ; \ +} + +#define WRITECTL(member, val) \ +{ \ + u32 __writetmp; \ + struct p9100_ctrl *enab, *actual; \ + actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \ + enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \ + __writetmp = enab-> ## member ; \ + actual-> ## member = val; \ +} + +static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count) +{ + int i; + u32 tmp; + + _READCTL(pwrup_cfg, tmp); + WRITECTL(ramdac_cmap_wridx, (index << 16)); + + for (i = index; count--; i++){ + _READCTL(pwrup_cfg, tmp); + WRITECTL(ramdac_palette_data, (fb->color_map CM(i,0) << 16)); + _READCTL(pwrup_cfg, tmp); + WRITECTL(ramdac_palette_data, (fb->color_map CM(i,1) << 16)); + _READCTL(pwrup_cfg, tmp); + WRITECTL(ramdac_palette_data, (fb->color_map CM(i,2) << 16)); + } +} + +static void p9100_blank (struct fb_info_sbusfb *fb) +{ + u32 val; + READCTL(vid_screenpaint_timectl1, val); + val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO; + WRITECTL(vid_screenpaint_timectl1, val); +} + +static void p9100_unblank (struct fb_info_sbusfb *fb) +{ + u32 val; + READCTL(vid_screenpaint_timectl1, val); + val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO; + WRITECTL(vid_screenpaint_timectl1, val); +} + +static void p9100_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + p->screen_base += (y_margin - fb->y_margin) * p->line_length + + (x_margin - fb->x_margin); +} + +static char idstring[60] __initdata = { 0 }; + +char * __init p9100fb_init(struct fb_info_sbusfb *fb) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; + unsigned long phys = fb->sbdp->reg_addrs[2].phys_addr; + int tmp; + +#ifndef FBCON_HAS_CFB8 + return NULL; +#endif + + /* Control regs: fb->sbdp->reg_addrs[0].phys_addr + * Command regs: fb->sbdp->reg_addrs[1].phys_addr + * Frame buffer: fb->sbdp->reg_addrs[2].phys_addr + */ + + if (!fb->s.p9100.ctrl) { + fb->s.p9100.ctrl = (struct p9100_ctrl *) + sparc_alloc_io(fb->sbdp->reg_addrs[0].phys_addr, 0, + fb->sbdp->reg_addrs[1].reg_size, "p9100_ctrl", fb->iospace, 0); + } + + strcpy(fb->info.modename, "p9100"); + strcpy(fix->id, "p9100"); + fix->accel = FB_ACCEL_SUN_CGTHREE; + fix->line_length = fb->var.xres_virtual; + + disp->scrollmode = SCROLL_YREDRAW; + if (!disp->screen_base) + disp->screen_base = + (char *)sparc_alloc_io(phys, 0, type->fb_size, "p9100_ram", + fb->iospace, 0); + fb->s.p9100.fbmem = disp->screen_base; + disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; + + READCTL(sys_config, tmp); + switch ((tmp >> SYS_CONFIG_PIXELSIZE_SHIFT) & 7) { + case 7: + type->fb_depth = 24; + break; + case 5: + type->fb_depth = 32; + break; + case 3: + type->fb_depth = 16; + break; + case 2: + type->fb_depth = 8; + break; + default: + printk("p9100: screen depth unknown: 0x%x", tmp); + return NULL; + } + + fb->dispsw = fbcon_cfb8; + + fb->margins = p9100_margins; + fb->loadcmap = p9100_loadcmap; + fb->blank = p9100_blank; + fb->unblank = p9100_unblank; + + fb->physbase = phys; + fb->mmap_map = p9100_mmap_map; + + sprintf(idstring, "%s at 0x%x", "p9100", disp->screen_base); + + return idstring; +} + diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 89f6860f2..cf7fe3418 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -156,11 +156,11 @@ static void do_install_cmap(int con, struct fb_info *info); * Interface used by the world */ -void platinum_init(void); +int platinum_init(void); #ifdef CONFIG_FB_OF void platinum_of_init(struct device_node *dp); #endif -void platinum_setup(char *options, int *ints); +int platinum_setup(char*); static struct fb_ops platinumfb_ops = { @@ -581,7 +581,7 @@ static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_p } -__initfunc(static int init_platinum(struct fb_info_platinum *info)) +static int __init init_platinum(struct fb_info_platinum *info) { struct fb_var_screeninfo var; struct display *disp; @@ -651,7 +651,7 @@ __initfunc(static int init_platinum(struct fb_info_platinum *info)) return 1; } -__initfunc(void platinum_init(void)) +int __init platinum_init(void) { #ifndef CONFIG_FB_OF struct device_node *dp; @@ -660,6 +660,7 @@ __initfunc(void platinum_init(void)) if (dp != 0) platinum_of_init(dp); #endif /* CONFIG_FB_OF */ + return 0; } #ifdef __powerpc__ @@ -670,14 +671,16 @@ __initfunc(void platinum_init(void)) #define invalidate_cache(addr) #endif -__initfunc(void platinum_of_init(struct device_node *dp)) +void __init platinum_of_init(struct device_node *dp) { struct fb_info_platinum *info; unsigned long addr, size; int i, bank0, bank1, bank2, bank3; - if(dp->n_addrs != 2) - panic("expecting 2 address for platinum (got %d)", dp->n_addrs); + if(dp->n_addrs != 2) { + printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs); + return; + } info = kmalloc(sizeof(*info), GFP_ATOMIC); if (info == 0) @@ -834,9 +837,9 @@ static int platinum_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(*fix)); strcpy(fix->id, "platinum"); - fix->smem_start = (void *) (info->frame_buffer_phys + 0x1000); + fix->smem_start = (info->frame_buffer_phys + 0x1000); fix->smem_len = (u32) info->total_vram - 0x1000; - fix->mmio_start = (char *) (info->platinum_regs_phys); + fix->mmio_start = (info->platinum_regs_phys); fix->mmio_len = 0x1000; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -854,12 +857,12 @@ static int platinum_encode_fix(struct fb_fix_screeninfo *fix, /* * Parse user speficied options (`video=platinumfb:') */ -__initfunc(void platinum_setup(char *options, int *ints)) +int __init platinum_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -895,4 +898,5 @@ __initfunc(void platinum_setup(char *options, int *ints)) } } } + return 0; } diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index dfb0f8ae8..343ad3f52 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -50,7 +50,7 @@ #define PM2FB_MASTER_DEBUG #ifdef PM2FB_MASTER_DEBUG -#define DPRINTK(a,b...) printk("pm2fb: %s: " a, __FUNCTION__ , ## b) +#define DPRINTK(a,b...) printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b) #else #define DPRINTK(a,b...) #endif @@ -192,12 +192,12 @@ static struct pm2fb_info { int board; /* Permedia2 board index (see board_table[] below) */ struct { - unsigned char* fb_base; /* framebuffer memory base */ + unsigned long fb_base; /* physical framebuffer memory base */ u32 fb_size; /* framebuffer memory size */ - unsigned char* rg_base; /* register memory base */ - unsigned char* p_fb; /* physical address of frame buffer */ + unsigned long rg_base; /* physical register memory base */ + unsigned long p_fb; /* physical address of frame buffer */ unsigned char* v_fb; /* virtual address of frame buffer */ - unsigned char* p_regs; /* physical address of registers + unsigned long p_regs; /* physical address of registers region, must be rg_base or rg_base+PM2_REGS_SIZE depending on the host endianness */ @@ -741,7 +741,7 @@ static void pm2fb_reset(struct pm2fb_info* p) { set_memclock(p, p->memclock); } -__initfunc(static int pm2fb_conf(struct pm2fb_info* p)) { +static int __init pm2fb_conf(struct pm2fb_info* p){ for (p->board=0; board_table[p->board].detect && !(board_table[p->board].detect(p)); p->board++); @@ -750,13 +750,26 @@ __initfunc(static int pm2fb_conf(struct pm2fb_info* p)) { return 0; } DPRINTK("found board: %s\n", board_table[p->board].name); + p->regions.p_fb=p->regions.fb_base; + if (!__request_region(&iomem_resource, p->regions.p_fb, + p->regions.fb_size, "pm2fb")) { + printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n"); + return 0; + } p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size); + #ifdef __LITTLE_ENDIAN p->regions.p_regs=p->regions.rg_base; #else p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE; #endif + if (!__request_region(&iomem_resource, p->regions.p_regs, + PM2_REGS_SIZE, "pm2fb")) { + printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n"); + UNMAP(p->regions.v_fb, p->regions.fb_size); + return 0; + } p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE); return 1; } @@ -809,9 +822,9 @@ static int cvppc_detect(struct pm2fb_info* p) { if (!cvppc_PCI_init(&p->board_par.cvppc)) return 0; - p->regions.fb_base=(unsigned char* )CVPPC_FB_APERTURE_ONE; + p->regions.fb_base=CVPPC_FB_APERTURE_ONE; p->regions.fb_size=CVPPC_FB_SIZE; - p->regions.rg_base=(unsigned char* )CVPPC_REGS_REGION; + p->regions.rg_base=CVPPC_REGS_REGION; p->memclock=CVPPC_MEMCLOCK; return 1; } @@ -852,27 +865,21 @@ static int pm2pci_detect(struct pm2fb_info* p) { return 0; } DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n", - pci->dev->base_address[0], - pci->dev->base_address[1], - pci->dev->base_address[2], - pci->dev->rom_address); + pci->dev->resource[0].start, + pci->dev->resource[1].start, + pci->dev->resource[2].start, + pci->dev->resource[PCI_ROM_RESOURCE].start); #ifdef __sparc__ - p->regions.rg_base=(unsigned char* ) - __pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK); - p->regions.fb_base=(unsigned char* ) - __pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK); + p->regions.rg_base= __pa(pci->dev->resource[0].start); + p->regions.fb_base= __pa(pci->dev->resource[1].start); #else if (pm2fb_options.flags & OPTF_VIRTUAL) { - p->regions.rg_base=(unsigned char* ) - __pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK); - p->regions.fb_base=(unsigned char* ) - __pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK); + p->regions.rg_base= __pa(pci->dev->resource[0].start); + p->regions.fb_base= __pa(pci->dev->resource[1].start); } else { - p->regions.rg_base=(unsigned char* ) - (pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK); - p->regions.fb_base=(unsigned char* ) - (pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK); + p->regions.rg_base= (pci->dev->resource[0].start); + p->regions.fb_base= (pci->dev->resource[0].start); } #endif #ifdef __BIG_ENDIAN @@ -1526,14 +1533,14 @@ static int pm2fb_setcolreg(unsigned regno, } static void pm2fb_set_disp(const void* par, struct display* disp, - struct fb_info_gen* info) { + struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; - u32 flags; - u32 depth; + unsigned long flags; + unsigned long depth; save_flags(flags); cli(); - disp->screen_base=i->regions.v_fb; + disp->screen_base = i->regions.v_fb; switch (depth=((struct pm2fb_par* )par)->depth) { #ifdef FBCON_HAS_CFB8 case 8: @@ -1581,21 +1588,29 @@ static int pm2fb_release(struct fb_info* info, int user) { * Begin of public functions ***************************************************************************/ -void pm2fb_cleanup(struct fb_info* info) { - struct pm2fb_info* i=(struct pm2fb_info* )info; +#ifdef MODULE +static void pm2fb_cleanup(void) { + struct pm2fb_info* i = &fb_info; - unregister_framebuffer(info); + unregister_framebuffer((struct fb_info *)i); pm2fb_reset(i); - /* FIXME UNMAP()??? */ + + UNMAP(i->regions.v_fb, i->regions.fb_size); + __release_region(&iomem_resource, i->regions.p_fb, i->regions.fb_size); + + UNMAP(i->regions.v_regs, PM2_REGS_SIZE); + __release_region(&iomem_resource, i->regions.p_regs, PM2_REGS_SIZE); + if (board_table[i->board].cleanup) board_table[i->board].cleanup(i); } +#endif /* MODULE */ -__initfunc(void pm2fb_init(void)) { +int __init pm2fb_init(void){ memset(&fb_info, 0, sizeof(fb_info)); if (!pm2fb_conf(&fb_info)) - return; + return -ENXIO; pm2fb_reset(&fb_info); fb_info.disp.scrollmode=SCROLL_YNOMOVE; fb_info.gen.parsize=sizeof(struct pm2fb_par); @@ -1613,18 +1628,19 @@ __initfunc(void pm2fb_init(void)) { fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info)<0) { - printk("pm2fb: unable to register.\n"); - return; + printk(KERN_ERR "pm2fb: unable to register.\n"); + return -EINVAL; } - printk("fb%d: %s (%s), using %uK of video memory.\n", + printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n", GET_FB_IDX(fb_info.gen.info.node), board_table[fb_info.board].name, permedia2_name, (u32 )(fb_info.regions.fb_size>>10)); MOD_INC_USE_COUNT; + return 0; } -__initfunc(void pm2fb_mode_setup(char* options)) { +void __init pm2fb_mode_setup(char* options){ int i; for (i=0; user_mode[i].name[0] && @@ -1634,13 +1650,13 @@ __initfunc(void pm2fb_mode_setup(char* options)) { sizeof(pm2fb_options.user_mode)); } -__initfunc(void pm2fb_font_setup(char* options)) { +void __init pm2fb_font_setup(char* options){ strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font)); pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0'; } -__initfunc(void pm2fb_setup(char* options, int* ints)) { +int __init pm2fb_setup(char* options){ char* next; while (options) { @@ -1658,6 +1674,7 @@ __initfunc(void pm2fb_setup(char* options, int* ints)) { pm2fb_options.flags |= OPTF_VIRTUAL; options=next; } + return 0; } /*************************************************************************** @@ -1665,9 +1682,9 @@ __initfunc(void pm2fb_setup(char* options, int* ints)) { ***************************************************************************/ #ifdef MODULE -int init_module(void) { +int __init init_module(void) { - pm2fb_init(); + return pm2fb_init(); } void cleanup_module(void) { diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c index 984edab98..e58d32ed1 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/promcon.c @@ -1,4 +1,4 @@ -/* $Id: promcon.c,v 1.15 1999/04/22 06:35:32 davem Exp $ +/* $Id: promcon.c,v 1.16 1999/08/10 15:56:22 davem Exp $ * Console driver utilizing PROM sun terminal emulation * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) @@ -104,7 +104,7 @@ promcon_end(struct vc_data *conp, char *b) return b - p; } -__initfunc(const char *promcon_startup(void)) +const char __init *promcon_startup(void) { const char *display_desc = "PROM"; int node; @@ -128,8 +128,8 @@ __initfunc(const char *promcon_startup(void)) return display_desc; } -__initfunc(static void -promcon_init_unimap(struct vc_data *conp)) +static void __init +promcon_init_unimap(struct vc_data *conp) { mm_segment_t old_fs = get_fs(); struct unipair *p, *p1; @@ -591,7 +591,7 @@ struct consw prom_con = { con_invert_region: NULL, }; -__initfunc(void prom_con_init(void)) +void __init prom_con_init(void) { #ifdef CONFIG_DUMMY_CONSOLE if (conswitchp == &dummy_con) diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 8cacf5966..8f1e2eb88 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -6,6 +6,8 @@ #include <linux/malloc.h> #include <linux/delay.h> #include <linux/interrupt.h> + +#include <asm/uaccess.h> #include <asm/setup.h> #include <asm/segment.h> #include <asm/system.h> @@ -15,8 +17,10 @@ #include <linux/module.h> #include <asm/pgtable.h> +#include <video/fbcon.h> #include <video/fbcon-cfb16.h> +#define FBIOSETSCROLLMODE 0x4611 #define Q40_PHYS_SCREEN_ADDR 0xFE800000 static unsigned long q40_screen_addr; @@ -82,7 +86,7 @@ static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"Q40"); - fix->smem_start=(char*)q40_screen_addr; + fix->smem_start=q40_screen_addr; fix->smem_len=1024*1024; fix->type=FB_TYPE_PACKED_PIXELS; fix->type_aux=0; @@ -212,7 +216,7 @@ static int q40_setcolreg(unsigned regno, unsigned red, unsigned green, blue>>=10; if (regno < 16) { - fbcon_cmap_cfb16[regno] = ((red & 31) <<5) | + fbcon_cmap_cfb16[regno] = ((red & 31) <<6) | ((green & 31) << 11) | (blue & 63); } @@ -232,7 +236,7 @@ static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, cmap, kspc ? 0 : 2); return 0; #else - printk("get cmap not supported\n"); + printk(KERN_ERR "get cmap not supported\n"); return -EINVAL; #endif @@ -256,7 +260,7 @@ static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; #else - printk("set cmap not supported\n"); + printk(KERN_ERR "set cmap not supported\n"); return -EINVAL; #endif @@ -265,7 +269,7 @@ static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int q40fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - printk("panning not supported\n"); + printk(KERN_ERR "panning not supported\n"); return -EINVAL; @@ -275,6 +279,27 @@ static int q40fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info) { +#if 0 + unsigned long i; + struct display *display; + + if (con>=0) + display = &fb_display[con]; + else + display = &disp[0]; + + if (cmd == FBIOSETSCROLLMODE) + { + i = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long)); + if (!i) + { + copy_from_user(&i, (void *)arg, sizeof(unsigned long)); + display->scrollmode = i; + } + q40_updatescrollmode(display); + return i; + } +#endif return -EINVAL; } @@ -302,6 +327,8 @@ static void q40fb_set_disp(int con, struct fb_info *info) display->inverse = 0; display->line_length = fix.line_length; + display->scrollmode = SCROLL_YREDRAW; + #ifdef FBCON_HAS_CFB16 display->dispsw = &fbcon_cfb16; disp->dispsw_data = fbcon_cmap_cfb16; @@ -310,8 +337,11 @@ static void q40fb_set_disp(int con, struct fb_info *info) #endif } -void q40fb_init(void) +int q40fb_init(void) { + + if ( !MACH_IS_Q40) + return -ENXIO; #if 0 q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024, KERNELMAP_NO_COPYBACK, NULL); @@ -335,12 +365,14 @@ void q40fb_init(void) q40fb_get_var(&disp[0].var, 0, &fb_info); q40fb_set_disp(-1, &fb_info); - if (register_framebuffer(&fb_info) < 0) - panic("unable to register Q40 frame buffer\n"); - + if (register_framebuffer(&fb_info) < 0) { + printk(KERN_ERR "unable to register Q40 frame buffer\n"); + return -EINVAL; + } - printk("fb%d: Q40 frame buffer alive and kicking !\n", + printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !\n", GET_FB_IDX(fb_info.node)); + return 0; } diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index 1ee42692f..dbc6eb022 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -109,6 +109,7 @@ struct retz3_fb_info { unsigned long physregs; int currcon; int current_par_valid; /* set to 0 by memset */ + int blitbusy; struct display disp; struct retz3fb_par current_par; unsigned char color_table [256][3]; @@ -169,7 +170,10 @@ under "programs/Xserver/hw/xfree86/doc/modeDB.txt". * Predefined Video Modes */ -static struct fb_videomode retz3fb_predefined[] __initdata = { +static struct { + const char *name; + struct fb_var_screeninfo var; +} retz3fb_predefined[] __initdata = { /* * NB: it is very important to adjust the pixel-clock to the color-depth. */ @@ -178,11 +182,7 @@ static struct fb_videomode retz3fb_predefined[] __initdata = { "640x480", { /* 640x480, 8 bpp */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, -#if 1 0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2, -#else - 0, 0, -1, -1, FB_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2, -#endif FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED } }, @@ -265,7 +265,7 @@ static int z3fb_mode __initdata = 0; * Interface used by the world */ -void retz3fb_setup(char *options, int *ints); +int retz3fb_setup(char *options); static int retz3fb_open(struct fb_info *info, int user); static int retz3fb_release(struct fb_info *info, int user); @@ -290,7 +290,7 @@ static int retz3fb_ioctl(struct inode *inode, struct file *file, * Interface to the low level console driver */ -void retz3fb_init(void); +int retz3fb_init(void); static int z3fb_switch(int con, struct fb_info *info); static int z3fb_updatevar(int con, struct fb_info *info); static void z3fb_blank(int blank, struct fb_info *info); @@ -346,7 +346,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info); static int get_video_mode(const char *name); -/* -------------------- Hardware specific routines -------------------------- */ +/* -------------------- Hardware specific routines ------------------------- */ static unsigned short find_fq(unsigned int freq) { @@ -490,7 +490,7 @@ static int retz3_set_video(struct fb_info *info, #endif if (data.v_total >= 1024) - printk("MAYDAY: v_total >= 1024; bailing out!\n"); + printk(KERN_ERR "MAYDAY: v_total >= 1024; bailing out!\n"); reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04)); reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00); @@ -770,7 +770,7 @@ static int retz3_set_video(struct fb_info *info, reg_w(regs, 0x83c6, 0xe0); break; default: - printk("Illegal color-depth: %i\n", bpp); + printk(KERN_INFO "Illegal color-depth: %i\n", bpp); } reg_w(regs, VDAC_ADDRESS, 0x00); @@ -794,9 +794,9 @@ static int retz3_encode_fix(struct fb_info *info, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, retz3fb_name); - fix->smem_start = (char *)(zinfo->physfbmem); + fix->smem_start = zinfo->physfbmem; fix->smem_len = zinfo->fbsize; - fix->mmio_start = (char *)(zinfo->physregs); + fix->mmio_start = zinfo->physregs; fix->mmio_len = 0x00c00000; fix->type = FB_TYPE_PACKED_PIXELS; @@ -959,6 +959,21 @@ static int retz3_getcolreg(unsigned int regno, unsigned int *red, } +static inline void retz3_busy(struct display *p) +{ + struct retz3_fb_info *zinfo = retz3info(p->fb_info); + volatile unsigned char *acm = zinfo->base + ACM_OFFSET; + unsigned char blt_status; + + if (zinfo->blitbusy) { + do{ + blt_status = *((acm) + (ACM_START_STATUS + 2)); + }while ((blt_status & 1) == 0); + zinfo->blitbusy = 0; + } +} + + static void retz3_bitblt (struct display *p, unsigned short srcx, unsigned short srcy, unsigned short destx, unsigned short desty, @@ -973,7 +988,6 @@ static void retz3_bitblt (struct display *p, unsigned short mod; unsigned long tmp; unsigned long pat, src, dst; - unsigned char blt_status; int i, xres_virtual = var->xres_virtual; short bpp = (var->bits_per_pixel & 0xff); @@ -983,16 +997,7 @@ static void retz3_bitblt (struct display *p, tmp = mask | (mask << 16); -#if 0 - /* - * Check for blitter finished before we start messing with the - * pattern. - */ - do{ - blt_status = *(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)); - }while ((blt_status & 1) == 0); -#endif + retz3_busy(p); i = 0; do{ @@ -1042,23 +1047,7 @@ static void retz3_bitblt (struct display *p, *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01; - - /* - * No reason to wait for the blitter to finish, it is better - * just to check if it has finished before we use it again. - */ -#if 1 -#if 0 - while ((*(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)) & 1) == 0); -#else - do{ - blt_status = *(((volatile unsigned char *)acm) + - (ACM_START_STATUS + 2)); - } - while ((blt_status & 1) == 0); -#endif -#endif + zinfo->blitbusy = 1; } #if 0 @@ -1192,7 +1181,6 @@ static int retz3fb_get_var(struct fb_var_screeninfo *var, int con, } -#if 1 static void retz3fb_set_disp(int con, struct fb_info *info) { struct fb_fix_screeninfo fix; @@ -1243,7 +1231,6 @@ static void retz3fb_set_disp(int con, struct fb_info *info) break; } } -#endif /* @@ -1407,12 +1394,12 @@ static struct fb_ops retz3fb_ops = { }; -__initfunc(void retz3fb_setup(char *options, int *ints)) +int __init retz3fb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")){ @@ -1422,9 +1409,10 @@ __initfunc(void retz3fb_setup(char *options, int *ints)) } else if (!strncmp(this_opt, "font:", 5)) { strncpy(fontname, this_opt+5, 39); fontname[39] = '\0'; - }else + } else z3fb_mode = get_video_mode(this_opt); } + return 0; } @@ -1432,7 +1420,7 @@ __initfunc(void retz3fb_setup(char *options, int *ints)) * Initialization */ -__initfunc(void retz3fb_init(void)) +int __init retz3fb_init(void) { unsigned long board_addr, board_size; unsigned int key; @@ -1444,10 +1432,10 @@ __initfunc(void retz3fb_init(void)) short i; if (!(key = zorro_find(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, 0, 0))) - return; + return -ENXIO; if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info), GFP_KERNEL))) - return; + return -ENOMEM; memset(zinfo, 0, sizeof(struct retz3_fb_info)); cd = zorro_get_board (key); @@ -1505,13 +1493,15 @@ __initfunc(void retz3fb_init(void)) do_install_cmap(0, fb_info); if (register_framebuffer(fb_info) < 0) - return; + return -EINVAL; - printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info->node), fb_info->modename,zinfo->fbsize>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; + + return 0; } @@ -1576,11 +1566,11 @@ static void z3fb_blank(int blank, struct fb_info *info) * Get a Video Mode */ -__initfunc(static int get_video_mode(const char *name)) +static int __init get_video_mode(const char *name) { short i; - for (i = 0; i <= NUM_TOTAL_MODES; i++) + for (i = 0; i < NUM_TOTAL_MODES; i++) if (!strcmp(name, retz3fb_predefined[i].name)){ retz3fb_default = retz3fb_predefined[i].var; return i; @@ -1592,8 +1582,7 @@ __initfunc(static int get_video_mode(const char *name)) #ifdef MODULE int init_module(void) { - retz3fb_init(); - return 0; + return retz3fb_init(); } void cleanup_module(void) @@ -1613,8 +1602,8 @@ void cleanup_module(void) */ #ifdef FBCON_HAS_CFB8 -static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx, - int dy, int dx, int height, int width) +static void retz3_8_bmove(struct display *p, int sy, int sx, + int dy, int dx, int height, int width) { int fontwidth = fontwidth(p); @@ -1633,8 +1622,8 @@ static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx, 0xffff); } -static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, - int sy, int sx, int height, int width) +static void retz3_8_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width) { unsigned short col; int fontwidth = fontwidth(p); @@ -1657,9 +1646,42 @@ static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, col); } + +static void retz3_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ + retz3_busy(p); + fbcon_cfb8_putc(conp, p, c, yy, xx); +} + + +static void retz3_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, + int yy, int xx) +{ + retz3_busy(p); + fbcon_cfb8_putcs(conp, p, s, count, yy, xx); +} + + +static void retz3_revc(struct display *p, int xx, int yy) +{ + retz3_busy(p); + fbcon_cfb8_revc(p, xx, yy); +} + + +static void retz3_clear_margins(struct vc_data* conp, struct display* p, + int bottom_only) +{ + retz3_busy(p); + fbcon_cfb8_clear_margins(conp, p, bottom_only); +} + + static struct display_switch fbcon_retz3_8 = { - fbcon_cfb8_setup, fbcon_retz3_8_bmove, fbcon_retz3_8_clear, - fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, - fbcon_cfb8_clear_margins, FONTWIDTH(8) + fbcon_cfb8_setup, retz3_8_bmove, retz3_8_clear, + retz3_putc, retz3_putcs, retz3_revc, NULL, NULL, + retz3_clear_margins, FONTWIDTH(8) }; #endif diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index 7e17bf1d6..aafa04542 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -53,8 +53,8 @@ * Interface used by the world */ -void sbusfb_init(void); -void sbusfb_setup(char *options, int *ints); +int sbusfb_init(void); +int sbusfb_setup(char*); static int currcon; static int defx_margin = -1, defy_margin = -1; @@ -743,7 +743,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Setup: parse used options */ -__initfunc(void sbusfb_setup(char *options, int *ints)) +int __init sbusfb_setup(char *options) { char *p; @@ -775,6 +775,7 @@ __initfunc(void sbusfb_setup(char *options, int *ints)) if (*p != ',') break; p++; } + return 0; } static int sbusfbcon_switch(int con, struct fb_info *info) @@ -960,8 +961,8 @@ void sbusfb_palette(int enter) extern void (*prom_palette)(int); -__initfunc(static void sbusfb_init_fb(int node, int parent, int fbtype, - struct linux_sbus_device *sbdp)) +static void __init sbusfb_init_fb(int node, int parent, int fbtype, + struct linux_sbus_device *sbdp) { struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; @@ -1085,6 +1086,11 @@ sizechange: case FBTYPE_MDICOLOR: p = cgfourteenfb_init(fb); break; #endif +#ifdef CONFIG_FB_P9100 + case FBTYPE_P9100COLOR: + /* Temporary crock. For now we are a cg3 */ + p = p9100fb_init(fb); type->fb_type = FBTYPE_SUN3COLOR; break; +#endif } if (!p) { @@ -1128,7 +1134,7 @@ sizechange: kfree(fb); return; } - printk("fb%d: %s\n", GET_FB_IDX(fb->info.node), p); + printk(KERN_INFO "fb%d: %s\n", GET_FB_IDX(fb->info.node), p); } static inline int known_card(char *name) @@ -1148,10 +1154,12 @@ static inline int known_card(char *name) return FBTYPE_SUN2BW; if (!strcmp(name, "tcx")) return FBTYPE_TCXCOLOR; + if (!strcmp(name, "p9100")) + return FBTYPE_P9100COLOR; return FBTYPE_NOTYPE; } -__initfunc(void sbusfb_init(void)) +int __init sbusfb_init(void) { int type; struct linux_sbus_device *sbdp; @@ -1159,7 +1167,7 @@ __initfunc(void sbusfb_init(void)) char prom_name[40]; extern int con_is_present(void); - if (!con_is_present()) return; + if (!con_is_present()) return -ENXIO; #ifdef CONFIG_FB_CREATOR { @@ -1187,7 +1195,7 @@ __initfunc(void sbusfb_init(void)) } } #endif - if (!SBus_chain) return; + if (!SBus_chain) return 0; for_all_sbusdev(sbdp, sbus) { type = known_card(sbdp->prom_name); if (type == FBTYPE_NOTYPE) continue; @@ -1199,4 +1207,5 @@ __initfunc(void sbusfb_init(void)) sbdp->num_registers, sbdp); sbusfb_init_fb(sbdp->prom_node, sbdp->my_bus->prom_node, type, sbdp); } + return 0; } diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 71aafc340..ce02149cf 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -89,7 +89,7 @@ static struct sgivwfb_par par_current = { /* * Interface used by the world */ -void sgivwfb_setup(char *options, int *ints); +int sgivwfb_setup(char*); static int sgivwfb_open(struct fb_info *info, int user); static int sgivwfb_release(struct fb_info *info, int user); @@ -126,7 +126,7 @@ static struct fb_ops sgivwfb_ops = { /* * Interface to the low level console driver */ -void sgivwfb_init(void); +int sgivwfb_init(void); static int sgivwfbcon_switch(int con, struct fb_info *info); static int sgivwfbcon_updatevar(int con, struct fb_info *info); static void sgivwfbcon_blank(int blank, struct fb_info *info); @@ -165,7 +165,7 @@ static unsigned long bytes_per_pixel(int bpp) length = 4; break; default: - printk("sgivwfb: unsupported bpp=%d\n", bpp); + printk(KERN_INFO "sgivwfb: unsupported bpp=%d\n", bpp); length = 0; break; } @@ -271,7 +271,7 @@ static void activate_par(struct sgivwfb_par *par) if (wholeTilesX*maxPixelsPerTileX < xpmax) wholeTilesX++; - printk("sgivwfb: pixPerTile=%d wholeTilesX=%d\n", + printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n", maxPixelsPerTileX, wholeTilesX); /* dbe_InitGammaMap(); */ @@ -465,7 +465,7 @@ static void activate_par(struct sgivwfb_par *par) } if (i==100000) - printk("sgivwfb: timeout waiting for frame DMA enable.\n"); + printk(KERN_INFO "sgivwfb: timeout waiting for frame DMA enable.\n"); outputVal = 0; htmp = currentTiming->hblank_end - 19; @@ -501,7 +501,7 @@ static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, sgivwfb_name); - fix->smem_start = (char *) sgivwfb_mem_phys; + fix->smem_start = sgivwfb_mem_phys; fix->smem_len = sgivwfb_mem_size; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -517,7 +517,7 @@ static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix, fix->xpanstep = 0; fix->ypanstep = ypan; fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); - fix->mmio_start = (char *) DBE_REG_PHYS; + fix->mmio_start = DBE_REG_PHYS; fix->mmio_len = DBE_REG_SIZE; } @@ -688,7 +688,7 @@ static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con, /* XXX FIXME - should try to pick best refresh rate */ /* for now, pick closest dot-clock within 3MHz*/ req_dot = (int)((1.0e3/1.0e6) / (1.0e-12 * (float)var->pixclock)); - printk("sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock, + printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock, req_dot); test_mode=min_mode; while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) { @@ -700,7 +700,7 @@ static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con, test_mode--; min_mode = test_mode; timing = &dbeVTimings[min_mode]; - printk("sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq); + printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq); /* Adjust virtual resolution, if necessary */ if (var->xres > var->xres_virtual || (!ywrap && !ypan)) @@ -775,9 +775,9 @@ static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con, oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel || !par_current.valid) { struct fb_fix_screeninfo fix; - printk("sgivwfb: new video mode xres=%d yres=%d bpp=%d\n", + printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%d\n", var->xres, var->yres, var->bits_per_pixel); - printk(" vxres=%d vyres=%d\n", + printk(KERN_INFO " vxres=%d vyres=%d\n", var->xres_virtual, var->yres_virtual); activate_par(&par_current); sgivwfb_encode_fix(&fix, var); @@ -915,37 +915,38 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file, if (remap_page_range(vma->vm_start, offset, size, vma->vm_page_prot)) return -EAGAIN; vma->vm_file = file; - printk("sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start); + printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start); return 0; } -__initfunc(void sgivwfb_setup(char *options, int *ints)) +int __init sgivwfb_setup(char *options) { char *this_opt; fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { if (!strncmp(this_opt, "font:", 5)) strcpy(fb_info.fontname, this_opt+5); } + return 0; } /* * Initialisation */ -__initfunc(void sgivwfb_init(void)) +int __init sgivwfb_init(void) { - printk("sgivwfb: framebuffer at 0x%lx, size %ldk\n", + printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldk\n", sgivwfb_mem_phys, sgivwfb_mem_size/1024); regs = (asregs*)ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE); if (!regs) { - printk("sgivwfb: couldn't ioremap registers\n"); + printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n"); goto fail_ioremap_regs; } @@ -965,7 +966,7 @@ __initfunc(void sgivwfb_init(void)) fbmem = ioremap_nocache((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size); if (!fbmem) { - printk("sgivwfb: couldn't ioremap fbmem\n"); + printk(KERN_ERR "sgivwfb: couldn't ioremap fbmem\n"); goto fail_ioremap_fbmem; } @@ -973,21 +974,21 @@ __initfunc(void sgivwfb_init(void)) sgivwfb_set_var(&par_current.var, -1, &fb_info); if (register_framebuffer(&fb_info) < 0) { - printk("sgivwfb: couldn't register framebuffer\n"); + printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n"); goto fail_register_framebuffer; } - printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n", + printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), sgivwfb_mem_size>>10); - return; + return 0; fail_register_framebuffer: iounmap((char*)fbmem); fail_ioremap_fbmem: iounmap(regs); fail_ioremap_regs: - return; + return -ENXIO; } static int sgivwfbcon_switch(int con, struct fb_info *info) @@ -1022,8 +1023,7 @@ static void sgivwfbcon_blank(int blank, struct fb_info *info) #ifdef MODULE int init_module(void) { - sgivwfb_init(); - return 0; + return sgivwfb_init(); } void cleanup_module(void) diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 59a2da716..2eb7962f8 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -73,6 +73,8 @@ static struct fb_var_screeninfo default_var; static int currcon = 0; static int inverse = 0; +int xxxfb_init(void); +int xxxfb_setup(char*); /* ------------------- chipset specific functions -------------------------- */ @@ -297,7 +299,7 @@ struct fbgen_hwswitch xxx_switch = { * Initialization */ -__initfunc(void xxxfb_init(void)) +int __init xxxfb_init(void) { fb_info.gen.fbhw = &xxx_switch; fb_info.gen.fbhw->detect(); @@ -316,12 +318,13 @@ __initfunc(void xxxfb_init(void)) fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) - return; - printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), + return -EINVAL; + printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename); /* uncomment this if your driver cannot be unloaded */ /* MOD_INC_USE_COUNT; */ + return 0; } @@ -345,7 +348,7 @@ void xxxfb_cleanup(struct fb_info *info) * Setup */ -__initfunc(void xxxfb_setup(char *options, int *ints)) +int __init xxxfb_setup(char *options) { /* Parse user speficied options (`video=xxxfb:') */ } @@ -393,8 +396,7 @@ static struct fb_ops xxxfb_ops = { #ifdef MODULE int init_module(void) { - xxxfb_init(); - return 0; + return xxxfb_init(); } void cleanup_module(void) diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c index 8e9d2fc41..c56894a4a 100644 --- a/drivers/video/tcxfb.c +++ b/drivers/video/tcxfb.c @@ -1,4 +1,4 @@ -/* $Id: tcxfb.c,v 1.7 1999/01/26 10:55:03 jj Exp $ +/* $Id: tcxfb.c,v 1.8 1999/08/10 15:56:26 davem Exp $ * tcxfb.c: TCX 24/8bit frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -206,7 +206,7 @@ static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar static char idstring[60] __initdata = { 0 }; -__initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb)) +char __init *tcxfb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct display *disp = &fb->disp; diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 59902a57a..a8c985035 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -125,7 +125,10 @@ const unsigned int bt463_cursor_source[4] = { * fbcon should provide a general mechanism for doing something like this. */ -static struct fb_videomode tgafb_predefined[] __initdata = { +static struct { + const char *name; + struct fb_var_screeninfo var; +} tgafb_predefined[] __initdata = { { "640x480-60", { 640, 480, 640, 480, 0, 0, 0, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, @@ -287,8 +290,8 @@ static void tgafb_set_disp(const void *fb_par, struct display *disp, static int tgafb_open(struct fb_info *info, int user); static int tgafb_release(struct fb_info *info, int user); -void tgafb_setup(char *options, int *ints); -void tgafb_init(void); +int tgafb_setup(char*); +int tgafb_init(void); void tgafb_cleanup(struct fb_info *info); static void tgafb_set_pll(int f); @@ -325,9 +328,9 @@ static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par, fix->visual = FB_VISUAL_TRUECOLOR; fix->line_length = par->xres * (par->bits_per_pixel >> 3); - fix->smem_start = (char *)__pa(fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base)); + fix->smem_start = fb_info.tga_fb_base; fix->smem_len = fix->line_length * par->yres; - fix->mmio_start = (char *)__pa(fb_info.tga_regs_base); + fix->mmio_start = fb_info.tga_regs_base; fix->mmio_len = 0x1000; /* Is this sufficient? */ fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0; fix->accel = FB_ACCEL_DEC_TGA; @@ -934,7 +937,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info) static void tgafb_set_disp(const void *fb_par, struct display *disp, struct fb_info_gen *info) { - disp->screen_base = (char *)fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base); + disp->screen_base = ioremap(fb_info.tga_fb_base); switch (fb_info.tga_type) { #ifdef FBCON_HAS_CFB8 case 0: /* 8-plane */ @@ -996,7 +999,7 @@ static struct fb_ops tgafb_ops = { * Setup */ -__initfunc(void tgafb_setup(char *options, int *ints)) { +int __init tgafb_setup(char *options) { char *this_opt; int i; @@ -1016,6 +1019,7 @@ __initfunc(void tgafb_setup(char *options, int *ints)) { printk(KERN_ERR "tgafb: unknown parameter %s\n", this_opt); } } + return 0; } @@ -1023,16 +1027,16 @@ __initfunc(void tgafb_setup(char *options, int *ints)) { * Initialisation */ -__initfunc(void tgafb_init(void)) +int __init tgafb_init(void) { struct pci_dev *pdev; pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL); if (!pdev) - return; - fb_info.tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; + return -ENXIO; + fb_info.tga_mem_base = pdev->resource[0].start; #ifdef DEBUG - printk("tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base); + printk(KERN_DEBUG "tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base); #endif /* DEBUG */ fb_info.tga_type = (readl((unsigned long)fb_info.tga_mem_base) >> 12) & 0x0f; @@ -1078,9 +1082,10 @@ __initfunc(void tgafb_init(void)) fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) - return; - printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), + return -EINVAL; + printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename); + return 0; } @@ -1101,8 +1106,7 @@ void tgafb_cleanup(struct fb_info *info) #ifdef MODULE int init_module(void) { - tgafb_init(); - return 0; + return tgafb_init(); } void cleanup_module(void) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index d7f2131de..2541d14a4 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -113,9 +113,9 @@ struct fb_info_valkyrie { /* * Exported functions */ -void valkyriefb_init(void); +int valkyriefb_init(void); void valkyrie_of_init(struct device_node *dp); -void valkyriefb_setup(char *options, int *ints); +int valkyriefb_setup(char*); static int valkyrie_open(struct fb_info *info, int user); static int valkyrie_release(struct fb_info *info, int user); @@ -218,7 +218,7 @@ static int valkyrie_set_var(struct fb_var_screeninfo *var, int con, } if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) { - /* printk("Not activating, in valkyrie_set_var.\n"); */ + /* printk(KERN_ERR "Not activating, in valkyrie_set_var.\n"); */ valkyrie_par_to_var(&par, var); return 0; } @@ -471,14 +471,14 @@ static void set_valkyrie_clock(unsigned char *params) } } -__initfunc(static void init_valkyrie(struct fb_info_valkyrie *p)) +static void __init init_valkyrie(struct fb_info_valkyrie *p) { struct fb_par_valkyrie *par = &p->par; struct fb_var_screeninfo var; int j, k; p->sense = read_valkyrie_sense(p); - printk("Monitor sense value = 0x%x, ", p->sense); + printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense); /* Try to pick a video mode out of NVRAM if we have one. */ if (default_vmode == VMODE_NVRAM) { @@ -504,7 +504,7 @@ __initfunc(static void init_valkyrie(struct fb_info_valkyrie *p)) || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram) default_cmode = CMODE_8; - printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode); + printk(KERN_INFO "using video mode %d and color mode %d.\n", default_vmode, default_cmode); mac_vmode_to_var(default_vmode, default_cmode, &var); if (valkyrie_var_to_par(&var, par, &p->info)) { @@ -534,7 +534,7 @@ __initfunc(static void init_valkyrie(struct fb_info_valkyrie *p)) return; } - printk("fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node)); + printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node)); } static void valkyrie_set_par(const struct fb_par_valkyrie *par, @@ -584,7 +584,7 @@ static void valkyrie_set_par(const struct fb_par_valkyrie *par, #endif /* CONFIG_FB_COMPAT_XPMAC */ } -__initfunc(void valkyriefb_init(void)) +int __init valkyriefb_init(void) { #ifndef CONFIG_FB_OF struct device_node *dp; @@ -593,15 +593,18 @@ __initfunc(void valkyriefb_init(void)) if (dp != 0) valkyrie_of_init(dp); #endif /* CONFIG_FB_OF */ + return 0; } -__initfunc(void valkyrie_of_init(struct device_node *dp)) +void __init valkyrie_of_init(struct device_node *dp) { struct fb_info_valkyrie *p; unsigned long addr, size; - if(dp->n_addrs != 1) - panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs); + if(dp->n_addrs != 1) { + printk(KERN_ERR "expecting 1 address for valkyrie (got %d)", dp->n_addrs); + return; + } p = kmalloc(sizeof(*p), GFP_ATOMIC); if (p == 0) @@ -764,7 +767,7 @@ static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valk { memset(fix, 0, sizeof(*fix)); strcpy(fix->id, "valkyrie"); - fix->mmio_start = (char *)p->valkyrie_regs_phys; + fix->mmio_start = p->valkyrie_regs_phys; fix->mmio_len = sizeof(struct valkyrie_regs); fix->type = FB_TYPE_PACKED_PIXELS; @@ -780,7 +783,7 @@ static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p) { - fix->smem_start = (void *)(p->frame_buffer_phys + 0x1000); + fix->smem_start = p->frame_buffer_phys + 0x1000; #if 1 fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode); #else @@ -848,12 +851,12 @@ static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valky /* * Parse user speficied options (`video=valkyriefb:') */ -__initfunc(void valkyriefb_setup(char *options, int *ints)) +int __init valkyriefb_setup(char *options) { char *this_opt; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { @@ -893,4 +896,5 @@ __initfunc(void valkyriefb_setup(char *options, int *ints)) can_soft_blank = 1; } } + return 0; } diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 78af83ef0..bb98bd8c7 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -41,7 +41,7 @@ */ /* card */ -char *video_base; +unsigned long video_base; /* physical addr */ int video_size; char *video_vbase; /* mapped */ @@ -96,8 +96,7 @@ static int mtrr = 0; static int currcon = 0; static int pmi_setpal = 0; /* pmi for palette changes ??? */ -static int ypan = 0; -static int ywrap = 0; +static int ypan = 0; /* 0..nothing, 1..ypan, 2..ywrap */ static unsigned short *pmi_base = 0; static void (*pmi_start)(void); static void (*pmi_pal)(void); @@ -130,13 +129,13 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con, { int offset; - if (!ypan && !ywrap) + if (!ypan) return -EINVAL; if (var->xoffset) return -EINVAL; - if (ypan && var->yoffset+var->yres > var->yres_virtual) + if (var->yoffset > var->yres_virtual) return -EINVAL; - if (ywrap && var->yoffset > var->yres_virtual) + if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual) return -EINVAL; offset = (var->yoffset * video_linelength + var->xoffset) / 4; @@ -154,7 +153,7 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con, static int vesafb_update_var(int con, struct fb_info *info) { - if (con == currcon && (ywrap || ypan)) { + if (con == currcon && ypan) { struct fb_var_screeninfo *var = &fb_display[currcon].var; return vesafb_pan_display(var,con,info); } @@ -167,13 +166,13 @@ static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"VESA VGA"); - fix->smem_start=(char *) video_base; + fix->smem_start=video_base; fix->smem_len=video_size; fix->type = video_type; fix->visual = video_visual; fix->xpanstep = 0; - fix->ypanstep = (ywrap || ypan) ? 1 : 0; - fix->ywrapstep = ywrap ? 1 : 0; + fix->ypanstep = ypan ? 1 : 0; + fix->ywrapstep = (ypan>1) ? 1 : 0; fix->line_length=video_linelength; return 0; } @@ -245,7 +244,7 @@ static void vesafb_set_disp(int con) } memcpy(&vesafb_sw, sw, sizeof(*sw)); display->dispsw = &vesafb_sw; - if (!ypan && !ywrap) { + if (!ypan) { display->scrollmode = SCROLL_YREDRAW; vesafb_sw.bmove = fbcon_redraw_bmove; } @@ -265,7 +264,7 @@ static int vesafb_set_var(struct fb_var_screeninfo *var, int con, var->bits_per_pixel != vesafb_defined.bits_per_pixel || var->nonstd) { if (first) { - printk("Vesafb does not support changing the video mode\n"); + printk(KERN_ERR "Vesafb does not support changing the video mode\n"); first = 0; } return -EINVAL; @@ -274,7 +273,7 @@ static int vesafb_set_var(struct fb_var_screeninfo *var, int con, if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; - if (ypan || ywrap) { + if (ypan) { if (vesafb_defined.yres_virtual != var->yres_virtual) { vesafb_defined.yres_virtual = var->yres_virtual; if (con != -1) { @@ -471,14 +470,14 @@ static struct fb_ops vesafb_ops = { vesafb_ioctl }; -void vesafb_setup(char *options, int *ints) +int vesafb_setup(char *options) { char *this_opt; fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; @@ -486,11 +485,11 @@ void vesafb_setup(char *options, int *ints) if (! strcmp(this_opt, "inverse")) inverse=1; else if (! strcmp(this_opt, "redraw")) - ywrap=0,ypan=0; + ypan=0; else if (! strcmp(this_opt, "ypan")) - ywrap=0,ypan=1; + ypan=1; else if (! strcmp(this_opt, "ywrap")) - ywrap=1,ypan=0; + ypan=2; else if (! strcmp(this_opt, "vgapal")) pmi_setpal=0; else if (! strcmp(this_opt, "pmipal")) @@ -500,6 +499,7 @@ void vesafb_setup(char *options, int *ints) else if (!strncmp(this_opt, "font:", 5)) strcpy(fb_info.fontname, this_opt+5); } + return 0; } static int vesafb_switch(int con, struct fb_info *info) @@ -523,14 +523,14 @@ static void vesafb_blank(int blank, struct fb_info *info) /* Not supported */ } -__initfunc(void vesafb_init(void)) +int __init vesafb_init(void) { int i,j; if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) - return; + return -ENXIO; - video_base = (char*)screen_info.lfb_base; + video_base = screen_info.lfb_base; video_bpp = screen_info.lfb_depth; video_width = screen_info.lfb_width; video_height = screen_info.lfb_height; @@ -538,28 +538,37 @@ __initfunc(void vesafb_init(void)) video_size = screen_info.lfb_size * 65536; video_visual = (video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - video_vbase = ioremap((unsigned long)video_base, video_size); - printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n", + if (!__request_region(&iomem_resource, video_base, video_size, + "vesafb")) { + printk(KERN_ERR + "vesafb: abort, cannot reserve video memory at 0x%lu\n", + video_base); + return -1; + } + + video_vbase = ioremap(video_base, video_size); + + printk(KERN_INFO "vesafb: framebuffer at 0x%lu, mapped to 0x%p, size %dk\n", video_base, video_vbase, video_size/1024); - printk("vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", + printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", video_width, video_height, video_bpp, video_linelength, screen_info.pages); if (screen_info.vesapm_seg) { - printk("vesafb: protected mode interface info at %04x:%04x\n", + printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", screen_info.vesapm_seg,screen_info.vesapm_off); } if (screen_info.vesapm_seg < 0xc000) - ywrap = ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */ + ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */ - if (ypan || ywrap || pmi_setpal) { - pmi_base = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); + if (ypan || pmi_setpal) { + pmi_base = (unsigned short*)bus_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); pmi_start = (void*)((char*)pmi_base + pmi_base[1]); pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); - printk("vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal); + printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal); if (pmi_base[3]) { - printk("vesafb: pmi: ports = "); + printk(KERN_INFO "vesafb: pmi: ports = "); for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++) printk("%x ",pmi_base[i]); printk("\n"); @@ -570,8 +579,8 @@ __initfunc(void vesafb_init(void)) * Rules are: we have to set up a descriptor for the requested * memory area and pass it in the ES register to the BIOS function. */ - printk("vesafb: can't handle memory requests, pmi disabled\n"); - ywrap = ypan = pmi_setpal = 0; + printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n"); + ypan = pmi_setpal = 0; } } } @@ -582,13 +591,13 @@ __initfunc(void vesafb_init(void)) vesafb_defined.yres_virtual=video_size / video_linelength; vesafb_defined.bits_per_pixel=video_bpp; - if ((ypan || ywrap) && vesafb_defined.yres_virtual > video_height) { - printk("vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n", - ywrap ? "ywrap" : "ypan",vesafb_defined.yres_virtual); + if (ypan && vesafb_defined.yres_virtual > video_height) { + printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n", + (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual); } else { - printk("vesafb: scrolling: redraw\n"); + printk(KERN_INFO "vesafb: scrolling: redraw\n"); vesafb_defined.yres_virtual = video_height; - ypan = ywrap = 0; + ypan = 0; } video_height_virtual = vesafb_defined.yres_virtual; @@ -610,7 +619,7 @@ __initfunc(void vesafb_init(void)) vesafb_defined.blue.length = screen_info.blue_size; vesafb_defined.transp.offset = screen_info.rsvd_pos; vesafb_defined.transp.length = screen_info.rsvd_size; - printk("vesafb: directcolor: " + printk(KERN_INFO "vesafb: directcolor: " "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", screen_info.rsvd_size, screen_info.red_size, @@ -633,9 +642,13 @@ __initfunc(void vesafb_init(void)) } video_cmap_len = 256; } - request_region(0x3c0, 32, "vga+"); + + /* request failure does not faze us, as vgacon probably has this + * region already (FIXME) */ + __request_region(&ioport_resource, 0x3c0, 32, "vesafb"); + if (mtrr) - mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1); + mtrr_add(video_base, video_size, MTRR_TYPE_WRCOMB, 1); strcpy(fb_info.modename, "VESA VGA"); fb_info.changevar = NULL; @@ -649,10 +662,11 @@ __initfunc(void vesafb_init(void)) vesafb_set_disp(-1); if (register_framebuffer(&fb_info)<0) - return; + return -EINVAL; - printk("fb%d: %s frame buffer device\n", + printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_info.modename); + return 0; } /* diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index ccc5e2a27..165b03077 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -78,7 +78,7 @@ static int vfb_enable = 0; /* disabled by default */ * Interface used by the world */ -void vfb_setup(char *options, int *ints); +int vfb_setup(char*); static int vfb_open(struct fb_info *info, int user); static int vfb_release(struct fb_info *info, int user); @@ -102,7 +102,7 @@ static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -void vfb_init(void); +int vfb_init(void); static int vfbcon_switch(int con, struct fb_info *info); static int vfbcon_updatevar(int con, struct fb_info *info); static void vfbcon_blank(int blank, struct fb_info *info); @@ -406,7 +406,7 @@ static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd, } -__initfunc(void vfb_setup(char *options, int *ints)) +int __init vfb_setup(char *options) { char *this_opt; @@ -415,13 +415,14 @@ __initfunc(void vfb_setup(char *options, int *ints)) vfb_enable = 1; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { if (!strncmp(this_opt, "font:", 5)) strcpy(fb_info.fontname, this_opt+5); } + return 0; } @@ -429,13 +430,13 @@ __initfunc(void vfb_setup(char *options, int *ints)) * Initialisation */ -__initfunc(void vfb_init(void)) +int __init vfb_init(void) { if (!vfb_enable) - return; + return -ENXIO; if (!(videomemory = (u_long)vmalloc(videomemorysize))) - return; + return -ENOMEM; strcpy(fb_info.modename, vfb_name); fb_info.changevar = NULL; @@ -451,11 +452,12 @@ __initfunc(void vfb_init(void)) if (register_framebuffer(&fb_info) < 0) { vfree((void *)videomemory); - return; + return -EINVAL; } - printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n", + printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), videomemorysize>>10); + return 0; } @@ -505,7 +507,7 @@ static void vfb_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, vfb_name); - fix->smem_start = (char *)videomemory; + fix->smem_start = videomemory; fix->smem_len = videomemorysize; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -636,8 +638,7 @@ static void do_install_cmap(int con, struct fb_info *info) #ifdef MODULE int init_module(void) { - vfb_init(); - return 0; + return vfb_init(); } void cleanup_module(void) diff --git a/drivers/video/vga.h b/drivers/video/vga.h new file mode 100644 index 000000000..7c05ba331 --- /dev/null +++ b/drivers/video/vga.h @@ -0,0 +1,444 @@ +/* + * linux/include/video/vga.h -- standard VGA chipset interaction + * + * Copyright 1999 Jeff Garzik <jgarzik@pobox.com> + * + * Copyright history from vga16fb.c: + * Copyright 1999 Ben Pfaff and Petr Vandrovec + * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm + * Based on VESA framebuffer (c) 1998 Gerd Knorr + * + * 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. + * + */ + +#ifndef __linux_video_vga_h__ +#define __linux_video_vga_h__ + +#include <linux/config.h> +#include <linux/types.h> +#include <asm/io.h> +#ifndef CONFIG_AMIGA +#include <asm/vga.h> +#endif +#include <asm/byteorder.h> + + +/* Some of the code below is taken from SVGAlib. The original, + unmodified copyright notice for that code is below. */ +/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it without any restrictions. This library is distributed */ +/* in the hope that it will be useful, but without any warranty. */ + +/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ +/* partially copyrighted (C) 1993 by Hartmut Schirmer */ + +/* VGA data register ports */ +#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ +#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ +#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */ +#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */ +#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */ +#define VGA_MIS_R 0x3CC /* Misc Output Read Register */ +#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */ +#define VGA_FTC_R 0x3CA /* Feature Control Read Register */ +#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ +#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ +#define VGA_PEL_D 0x3C9 /* PEL Data Register */ +#define VGA_PEL_MSK 0x3C6 /* PEL mask register */ + +/* EGA-specific registers */ +#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */ +#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */ + +/* VGA index register ports */ +#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ +#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ +#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define VGA_GFX_I 0x3CE /* Graphics Controller Index */ +#define VGA_SEQ_I 0x3C4 /* Sequencer Index */ +#define VGA_PEL_IW 0x3C8 /* PEL Write Index */ +#define VGA_PEL_IR 0x3C7 /* PEL Read Index */ + +/* standard VGA indexes max counts */ +#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */ +#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */ +#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */ +#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */ +#define VGA_MIS_C 0x01 /* Number of Misc Output Register */ + +/* VGA misc register bit masks */ +#define VGA_MIS_COLOR 0x01 +#define VGA_MIS_ENB_MEM_ACCESS 0x02 +#define VGA_MIS_DCLK_28322_720 0x04 +#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08) +#define VGA_MIS_SEL_HIGH_PAGE 0x20 + +/* VGA CRT controller register indices */ +#define VGA_CRTC_H_TOTAL 0 +#define VGA_CRTC_H_DISP 1 +#define VGA_CRTC_H_BLANK_START 2 +#define VGA_CRTC_H_BLANK_END 3 +#define VGA_CRTC_H_SYNC_START 4 +#define VGA_CRTC_H_SYNC_END 5 +#define VGA_CRTC_V_TOTAL 6 +#define VGA_CRTC_OVERFLOW 7 +#define VGA_CRTC_PRESET_ROW 8 +#define VGA_CRTC_MAX_SCAN 9 +#define VGA_CRTC_CURSOR_START 0x0A +#define VGA_CRTC_CURSOR_END 0x0B +#define VGA_CRTC_START_HI 0x0C +#define VGA_CRTC_START_LO 0x0D +#define VGA_CRTC_CURSOR_HI 0x0E +#define VGA_CRTC_CURSOR_LO 0x0F +#define VGA_CRTC_V_SYNC_START 0x10 +#define VGA_CRTC_V_SYNC_END 0x11 +#define VGA_CRTC_V_DISP_END 0x12 +#define VGA_CRTC_OFFSET 0x13 +#define VGA_CRTC_UNDERLINE 0x14 +#define VGA_CRTC_V_BLANK_START 0x15 +#define VGA_CRTC_V_BLANK_END 0x16 +#define VGA_CRTC_MODE 0x17 +#define VGA_CRTC_LINE_COMPARE 0x18 +#define VGA_CRTC_REGS VGA_CRT_C + +/* VGA CRT controller bit masks */ +#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ +#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 + +/* VGA attribute controller register indices */ +#define VGA_ATC_PALETTE0 0x00 +#define VGA_ATC_PALETTE1 0x01 +#define VGA_ATC_PALETTE2 0x02 +#define VGA_ATC_PALETTE3 0x03 +#define VGA_ATC_PALETTE4 0x04 +#define VGA_ATC_PALETTE5 0x05 +#define VGA_ATC_PALETTE6 0x06 +#define VGA_ATC_PALETTE7 0x07 +#define VGA_ATC_PALETTE8 0x08 +#define VGA_ATC_PALETTE9 0x09 +#define VGA_ATC_PALETTEA 0x0A +#define VGA_ATC_PALETTEB 0x0B +#define VGA_ATC_PALETTEC 0x0C +#define VGA_ATC_PALETTED 0x0D +#define VGA_ATC_PALETTEE 0x0E +#define VGA_ATC_PALETTEF 0x0F +#define VGA_ATC_MODE 0x10 +#define VGA_ATC_OVERSCAN 0x11 +#define VGA_ATC_PLANE_ENABLE 0x12 +#define VGA_ATC_PEL 0x13 +#define VGA_ATC_COLOR_PAGE 0x14 + +#define VGA_AR_ENABLE_DISPLAY 0x20 + +/* VGA sequencer register indices */ +#define VGA_SEQ_RESET 0x00 +#define VGA_SEQ_CLOCK_MODE 0x01 +#define VGA_SEQ_PLANE_WRITE 0x02 +#define VGA_SEQ_CHARACTER_MAP 0x03 +#define VGA_SEQ_MEMORY_MODE 0x04 + +/* VGA sequencer register bit masks */ +#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */ +#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */ +#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */ +#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */ +#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */ +#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */ + +/* VGA graphics controller register indices */ +#define VGA_GFX_SR_VALUE 0x00 +#define VGA_GFX_SR_ENABLE 0x01 +#define VGA_GFX_COMPARE_VALUE 0x02 +#define VGA_GFX_DATA_ROTATE 0x03 +#define VGA_GFX_PLANE_READ 0x04 +#define VGA_GFX_MODE 0x05 +#define VGA_GFX_MISC 0x06 +#define VGA_GFX_COMPARE_MASK 0x07 +#define VGA_GFX_BIT_MASK 0x08 + +/* VGA graphics controller bit masks */ +#define VGA_GR06_GRAPHICS_MODE 0x01 + +/* macro for composing an 8-bit VGA register index and value + * into a single 16-bit quantity */ +#define VGA_OUT16VAL(v, r) (((v) << 8) | (r)) + +/* decide whether we should enable the faster 16-bit VGA register writes */ +#ifdef __LITTLE_ENDIAN +#define VGA_OUTW_WRITE +#endif + + +/* + * generic VGA port read/write + */ + +extern inline unsigned char vga_io_r (unsigned short port) +{ + return inb (port); +} + +extern inline void vga_io_w (unsigned short port, unsigned char val) +{ + outb (val, port); +} + +extern inline void vga_io_w_fast (unsigned short port, unsigned char reg, + unsigned char val) +{ + outw (VGA_OUT16VAL (val, reg), port); +} + +extern inline unsigned char vga_mm_r (caddr_t regbase, unsigned short port) +{ + return readb (regbase + port); +} + +extern inline void vga_mm_w (caddr_t regbase, unsigned short port, unsigned char val) +{ + writeb (val, regbase + port); +} + +extern inline void vga_mm_w_fast (caddr_t regbase, unsigned short port, + unsigned char reg, unsigned char val) +{ + writew (VGA_OUT16VAL (val, reg), regbase + port); +} + +extern inline unsigned char vga_r (caddr_t regbase, unsigned short port) +{ + if (regbase) + return vga_mm_r (regbase, port); + else + return vga_io_r (port); +} + +extern inline void vga_w (caddr_t regbase, unsigned short port, unsigned char val) +{ + if (regbase) + vga_mm_w (regbase, port, val); + else + vga_io_w (port, val); +} + + +extern inline void vga_w_fast (caddr_t regbase, unsigned short port, + unsigned char reg, unsigned char val) +{ + if (regbase) + vga_mm_w_fast (regbase, port, reg, val); + else + vga_io_w_fast (port, reg, val); +} + + +/* + * VGA CRTC register read/write + */ + +extern inline unsigned char vga_rcrt (caddr_t regbase, unsigned char reg) +{ + vga_w (regbase, VGA_CRT_IC, reg); + return vga_r (regbase, VGA_CRT_DC); +} + +extern inline void vga_wcrt (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_w_fast (regbase, VGA_CRT_IC, reg, val); +#else + vga_w (regbase, VGA_CRT_IC, reg); + vga_w (regbase, VGA_CRT_DC, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_io_rcrt (unsigned char reg) +{ + vga_io_w (VGA_CRT_IC, reg); + return vga_io_r (VGA_CRT_DC); +} + +extern inline void vga_io_wcrt (unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_io_w_fast (VGA_CRT_IC, reg, val); +#else + vga_io_w (VGA_CRT_IC, reg); + vga_io_w (VGA_CRT_DC, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_mm_rcrt (caddr_t regbase, unsigned char reg) +{ + vga_mm_w (regbase, VGA_CRT_IC, reg); + return vga_mm_r (regbase, VGA_CRT_DC); +} + +extern inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_mm_w_fast (regbase, VGA_CRT_IC, reg, val); +#else + vga_mm_w (regbase, VGA_CRT_IC, reg); + vga_mm_w (regbase, VGA_CRT_DC, val); +#endif /* VGA_OUTW_WRITE */ +} + + +/* + * VGA sequencer register read/write + */ + +extern inline unsigned char vga_rseq (caddr_t regbase, unsigned char reg) +{ + vga_w (regbase, VGA_SEQ_I, reg); + return vga_r (regbase, VGA_SEQ_D); +} + +extern inline void vga_wseq (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_w_fast (regbase, VGA_SEQ_I, reg, val); +#else + vga_w (regbase, VGA_SEQ_I, reg); + vga_w (regbase, VGA_SEQ_D, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_io_rseq (unsigned char reg) +{ + vga_io_w (VGA_SEQ_I, reg); + return vga_io_r (VGA_SEQ_D); +} + +extern inline void vga_io_wseq (unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_io_w_fast (VGA_SEQ_I, reg, val); +#else + vga_io_w (VGA_SEQ_I, reg); + vga_io_w (VGA_SEQ_D, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_mm_rseq (caddr_t regbase, unsigned char reg) +{ + vga_mm_w (regbase, VGA_SEQ_I, reg); + return vga_mm_r (regbase, VGA_SEQ_D); +} + +extern inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_mm_w_fast (regbase, VGA_SEQ_I, reg, val); +#else + vga_mm_w (regbase, VGA_SEQ_I, reg); + vga_mm_w (regbase, VGA_SEQ_D, val); +#endif /* VGA_OUTW_WRITE */ +} + + + +/* + * VGA graphics controller register read/write + */ + +extern inline unsigned char vga_rgfx (caddr_t regbase, unsigned char reg) +{ + vga_w (regbase, VGA_GFX_I, reg); + return vga_r (regbase, VGA_GFX_D); +} + +extern inline void vga_wgfx (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_w_fast (regbase, VGA_GFX_I, reg, val); +#else + vga_w (regbase, VGA_GFX_I, reg); + vga_w (regbase, VGA_GFX_D, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_io_rgfx (unsigned char reg) +{ + vga_io_w (VGA_GFX_I, reg); + return vga_io_r (VGA_GFX_D); +} + +extern inline void vga_io_wgfx (unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_io_w_fast (VGA_GFX_I, reg, val); +#else + vga_io_w (VGA_GFX_I, reg); + vga_io_w (VGA_GFX_D, val); +#endif /* VGA_OUTW_WRITE */ +} + +extern inline unsigned char vga_mm_rgfx (caddr_t regbase, unsigned char reg) +{ + vga_mm_w (regbase, VGA_GFX_I, reg); + return vga_mm_r (regbase, VGA_GFX_D); +} + +extern inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned char val) +{ +#ifdef VGA_OUTW_WRITE + vga_mm_w_fast (regbase, VGA_GFX_I, reg, val); +#else + vga_mm_w (regbase, VGA_GFX_I, reg); + vga_mm_w (regbase, VGA_GFX_D, val); +#endif /* VGA_OUTW_WRITE */ +} + + +/* + * VGA attribute controller register read/write + */ + +extern inline unsigned char vga_rattr (caddr_t regbase, unsigned char reg) +{ + vga_w (regbase, VGA_ATT_IW, reg); + return vga_r (regbase, VGA_ATT_R); +} + +extern inline void vga_wattr (caddr_t regbase, unsigned char reg, unsigned char val) +{ + vga_w (regbase, VGA_ATT_IW, reg); + vga_w (regbase, VGA_ATT_W, val); +} + +extern inline unsigned char vga_io_rattr (unsigned char reg) +{ + vga_io_w (VGA_ATT_IW, reg); + return vga_io_r (VGA_ATT_R); +} + +extern inline void vga_io_wattr (unsigned char reg, unsigned char val) +{ + vga_io_w (VGA_ATT_IW, reg); + vga_io_w (VGA_ATT_W, val); +} + +extern inline unsigned char vga_mm_rattr (caddr_t regbase, unsigned char reg) +{ + vga_mm_w (regbase, VGA_ATT_IW, reg); + return vga_mm_r (regbase, VGA_ATT_R); +} + +extern inline void vga_mm_wattr (caddr_t regbase, unsigned char reg, unsigned char val) +{ + vga_mm_w (regbase, VGA_ATT_IW, reg); + vga_mm_w (regbase, VGA_ATT_W, val); +} + + + + +#endif /* __linux_video_vga_h__ */ diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 7f7b1af4d..9b014c45e 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -27,10 +27,14 @@ #include <video/fbcon.h> #include <video/fbcon-vga-planes.h> +#include "vga.h" #define dac_reg (0x3c8) #define dac_val (0x3c9) +#define VGA_FB_PHYS 0xA0000 +#define VGA_FB_PHYS_LEN 65535 + /* --------------------------------------------------------------------- */ /* @@ -63,104 +67,12 @@ static struct vga16fb_info { int vesa_blanked; } vga16fb; -/* Some of the code below is taken from SVGAlib. The original, - unmodified copyright notice for that code is below. */ -/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it without any restrictions. This library is distributed */ -/* in the hope that it will be useful, but without any warranty. */ - -/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ -/* partially copyrighted (C) 1993 by Hartmut Schirmer */ - -/* VGA data register ports */ -#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ -#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ -#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ -#define GRA_D 0x3CF /* Graphics Controller Data Register */ -#define SEQ_D 0x3C5 /* Sequencer Data Register */ -#define MIS_R 0x3CC /* Misc Output Read Register */ -#define MIS_W 0x3C2 /* Misc Output Write Register */ -#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ -#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ -#define PEL_D 0x3C9 /* PEL Data Register */ -#define PEL_MSK 0x3C6 /* PEL mask register */ - -/* EGA-specific registers */ -#define GRA_E0 0x3CC /* Graphics enable processor 0 */ -#define GRA_E1 0x3CA /* Graphics enable processor 1 */ - - -/* VGA index register ports */ -#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ -#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ -#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ -#define GRA_I 0x3CE /* Graphics Controller Index */ -#define SEQ_I 0x3C4 /* Sequencer Index */ -#define PEL_IW 0x3C8 /* PEL Write Index */ -#define PEL_IR 0x3C7 /* PEL Read Index */ - -/* standard VGA indexes max counts */ -#define CRT_C 24 /* 24 CRT Controller Registers */ -#define ATT_C 21 /* 21 Attribute Controller Registers */ -#define GRA_C 9 /* 9 Graphics Controller Registers */ -#define SEQ_C 5 /* 5 Sequencer Registers */ -#define MIS_C 1 /* 1 Misc Output Register */ - -#define CRTC_H_TOTAL 0 -#define CRTC_H_DISP 1 -#define CRTC_H_BLANK_START 2 -#define CRTC_H_BLANK_END 3 -#define CRTC_H_SYNC_START 4 -#define CRTC_H_SYNC_END 5 -#define CRTC_V_TOTAL 6 -#define CRTC_OVERFLOW 7 -#define CRTC_PRESET_ROW 8 -#define CRTC_MAX_SCAN 9 -#define CRTC_CURSOR_START 0x0A -#define CRTC_CURSOR_END 0x0B -#define CRTC_START_HI 0x0C -#define CRTC_START_LO 0x0D -#define CRTC_CURSOR_HI 0x0E -#define CRTC_CURSOR_LO 0x0F -#define CRTC_V_SYNC_START 0x10 -#define CRTC_V_SYNC_END 0x11 -#define CRTC_V_DISP_END 0x12 -#define CRTC_OFFSET 0x13 -#define CRTC_UNDERLINE 0x14 -#define CRTC_V_BLANK_START 0x15 -#define CRTC_V_BLANK_END 0x16 -#define CRTC_MODE 0x17 -#define CRTC_LINE_COMPARE 0x18 -#define CRTC_REGS 0x19 - -#define ATC_MODE 0x10 -#define ATC_OVERSCAN 0x11 -#define ATC_PLANE_ENABLE 0x12 -#define ATC_PEL 0x13 -#define ATC_COLOR_PAGE 0x14 - -#define SEQ_CLOCK_MODE 0x01 -#define SEQ_PLANE_WRITE 0x02 -#define SEQ_CHARACTER_MAP 0x03 -#define SEQ_MEMORY_MODE 0x04 - -#define GDC_SR_VALUE 0x00 -#define GDC_SR_ENABLE 0x01 -#define GDC_COMPARE_VALUE 0x02 -#define GDC_DATA_ROTATE 0x03 -#define GDC_PLANE_READ 0x04 -#define GDC_MODE 0x05 -#define GDC_MISC 0x06 -#define GDC_COMPARE_MASK 0x07 -#define GDC_BIT_MASK 0x08 struct vga16fb_par { - u8 crtc[CRTC_REGS]; - u8 atc[ATT_C]; - u8 gdc[GRA_C]; - u8 seq[SEQ_C]; + u8 crtc[VGA_CRT_C]; + u8 atc[VGA_ATT_C]; + u8 gdc[VGA_GFX_C]; + u8 seq[VGA_SEQ_C]; u8 misc; u8 vss; struct fb_var_screeninfo var; @@ -192,6 +104,8 @@ static struct { u_short blue, green, red, pad; } palette[256]; static int currcon = 0; +static int release_io_ports = 0; + /* --------------------------------------------------------------------- */ /* @@ -216,17 +130,17 @@ static int vga16fb_release(struct fb_info *info, int user) static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var) { u32 pos = (var->xres_virtual * var->yoffset + var->xoffset) >> 3; - outb(CRTC_START_HI, CRT_IC); - outb(pos >> 8, CRT_DC); - outb(CRTC_START_LO, CRT_IC); - outb(pos & 0xFF, CRT_DC); + outb(VGA_CRTC_START_HI, VGA_CRT_IC); + outb(pos >> 8, VGA_CRT_DC); + outb(VGA_CRTC_START_LO, VGA_CRT_IC); + outb(pos & 0xFF, VGA_CRT_DC); #if 0 /* if someone supports xoffset in bit resolution */ - inb(IS1_RC); /* reset flip-flop */ - outb(ATC_PEL, ATT_IW); - outb(xoffset & 7, ATT_IW); - inb(IS1_RC); - outb(0x20, ATT_IW); + inb(VGA_IS1_RC); /* reset flip-flop */ + outb(VGA_ATC_PEL, VGA_ATT_IW); + outb(xoffset & 7, VGA_ATT_IW); + inb(VGA_IS1_RC); + outb(0x20, VGA_ATT_IW); #endif } @@ -249,8 +163,8 @@ static int vga16fb_get_fix(struct fb_fix_screeninfo *fix, int con, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"VGA16 VGA"); - fix->smem_start = (char *) 0xa0000; - fix->smem_len = 65536; + fix->smem_start = VGA_FB_PHYS; + fix->smem_len = VGA_FB_PHYS_LEN; fix->type = FB_TYPE_VGA_PLANES; fix->visual = FB_VISUAL_PSEUDOCOLOR; fix->xpanstep = 8; @@ -338,7 +252,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, } } par->misc |= best->misc; - par->seq[SEQ_CLOCK_MODE] |= best->seq_clock_mode; + par->seq[VGA_SEQ_CLOCK_MODE] |= best->seq_clock_mode; par->var.pixclock = best->pixclock; } @@ -388,17 +302,17 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, FAIL("hslen too big"); if (right + hslen + left > 64) FAIL("hblank too big"); - par->crtc[CRTC_H_TOTAL] = xtotal - 5; - par->crtc[CRTC_H_BLANK_START] = xres - 1; - par->crtc[CRTC_H_DISP] = xres - 1; + par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5; + par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1; + par->crtc[VGA_CRTC_H_DISP] = xres - 1; pos = xres + right; - par->crtc[CRTC_H_SYNC_START] = pos; + par->crtc[VGA_CRTC_H_SYNC_START] = pos; pos += hslen; - par->crtc[CRTC_H_SYNC_END] = pos & 0x1F; + par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F; pos += left - 2; /* blank_end + 2 <= total + 5 */ - par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; + par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; if (pos & 0x20) - par->crtc[CRTC_H_SYNC_END] |= 0x80; + par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80; yres = var->yres; lower = var->lower_margin; @@ -443,59 +357,59 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, FAIL("ytotal too big"); if (vslen > 16) FAIL("vslen too big"); - par->crtc[CRTC_V_TOTAL] = ytotal - 2; + par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2; r7 = 0x10; /* disable linecompare */ if (ytotal & 0x100) r7 |= 0x01; if (ytotal & 0x200) r7 |= 0x20; - par->crtc[CRTC_PRESET_ROW] = 0; - par->crtc[CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */ + par->crtc[VGA_CRTC_PRESET_ROW] = 0; + par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */ par->var.vmode = var->vmode; if (var->vmode & FB_VMODE_DOUBLE) - par->crtc[CRTC_MAX_SCAN] |= 0x80; - par->crtc[CRTC_CURSOR_START] = 0x20; - par->crtc[CRTC_CURSOR_END] = 0x00; + par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80; + par->crtc[VGA_CRTC_CURSOR_START] = 0x20; + par->crtc[VGA_CRTC_CURSOR_END] = 0x00; pos = yoffset * vxres + (xoffset >> 3); - par->crtc[CRTC_START_HI] = pos >> 8; - par->crtc[CRTC_START_LO] = pos & 0xFF; - par->crtc[CRTC_CURSOR_HI] = 0x00; - par->crtc[CRTC_CURSOR_LO] = 0x00; + par->crtc[VGA_CRTC_START_HI] = pos >> 8; + par->crtc[VGA_CRTC_START_LO] = pos & 0xFF; + par->crtc[VGA_CRTC_CURSOR_HI] = 0x00; + par->crtc[VGA_CRTC_CURSOR_LO] = 0x00; pos = yres - 1; - par->crtc[CRTC_V_DISP_END] = pos & 0xFF; - par->crtc[CRTC_V_BLANK_START] = pos & 0xFF; + par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF; + par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF; if (pos & 0x100) r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */ if (pos & 0x200) { r7 |= 0x40; /* 0x40 -> DISP_END */ - par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ + par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ } pos += lower; - par->crtc[CRTC_V_SYNC_START] = pos & 0xFF; + par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF; if (pos & 0x100) r7 |= 0x04; if (pos & 0x200) r7 |= 0x80; pos += vslen; - par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */ + par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */ pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ - par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, + par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, but some SVGA chips requires all 8 bits to set */ if (vxres >= 512) FAIL("vxres too long"); - par->crtc[CRTC_OFFSET] = vxres >> 1; - par->crtc[CRTC_UNDERLINE] = 0x1F; - par->crtc[CRTC_MODE] = rMode | 0xE3; - par->crtc[CRTC_LINE_COMPARE] = 0xFF; - par->crtc[CRTC_OVERFLOW] = r7; + par->crtc[VGA_CRTC_OFFSET] = vxres >> 1; + par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; + par->crtc[VGA_CRTC_MODE] = rMode | 0xE3; + par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF; + par->crtc[VGA_CRTC_OVERFLOW] = r7; par->vss = 0x00; /* 3DA */ for (i = 0x00; i < 0x10; i++) par->atc[i] = i; - par->atc[ATC_MODE] = 0x81; - par->atc[ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ - par->atc[ATC_PLANE_ENABLE] = 0x0F; - par->atc[ATC_PEL] = xoffset & 7; - par->atc[ATC_COLOR_PAGE] = 0x00; + par->atc[VGA_ATC_MODE] = 0x81; + par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ + par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F; + par->atc[VGA_ATC_PEL] = xoffset & 7; + par->atc[VGA_ATC_COLOR_PAGE] = 0x00; par->misc = 0xC3; /* enable CPU, ports 0x3Dx, positive sync */ par->var.sync = var->sync; @@ -504,20 +418,20 @@ static int vga16fb_decode_var(const struct fb_var_screeninfo *var, if (var->sync & FB_SYNC_VERT_HIGH_ACT) par->misc &= ~0x80; - par->seq[SEQ_CLOCK_MODE] = 0x01; - par->seq[SEQ_PLANE_WRITE] = 0x0F; - par->seq[SEQ_CHARACTER_MAP] = 0x00; - par->seq[SEQ_MEMORY_MODE] = 0x06; + par->seq[VGA_SEQ_CLOCK_MODE] = 0x01; + par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F; + par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00; + par->seq[VGA_SEQ_MEMORY_MODE] = 0x06; - par->gdc[GDC_SR_VALUE] = 0x00; - par->gdc[GDC_SR_ENABLE] = 0x0F; - par->gdc[GDC_COMPARE_VALUE] = 0x00; - par->gdc[GDC_DATA_ROTATE] = 0x20; - par->gdc[GDC_PLANE_READ] = 0; - par->gdc[GDC_MODE] = 0x00; - par->gdc[GDC_MISC] = 0x05; - par->gdc[GDC_COMPARE_MASK] = 0x0F; - par->gdc[GDC_BIT_MASK] = 0xFF; + par->gdc[VGA_GFX_SR_VALUE] = 0x00; + par->gdc[VGA_GFX_SR_ENABLE] = 0x0F; + par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00; + par->gdc[VGA_GFX_DATA_ROTATE] = 0x20; + par->gdc[VGA_GFX_PLANE_READ] = 0; + par->gdc[VGA_GFX_MODE] = 0x00; + par->gdc[VGA_GFX_MISC] = 0x05; + par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F; + par->gdc[VGA_GFX_BIT_MASK] = 0xFF; vga16fb_clock_chip(par, var->pixclock, info); @@ -543,64 +457,64 @@ static int vga16fb_set_par(const struct vga16fb_par *par, { int i; - outb(inb(MIS_R) | 0x01, MIS_W); + outb(inb(VGA_MIS_R) | 0x01, VGA_MIS_W); /* Enable graphics register modification */ if (!info->isVGA) { - outb(0x00, GRA_E0); - outb(0x01, GRA_E1); + outb(0x00, EGA_GFX_E0); + outb(0x01, EGA_GFX_E1); } /* update misc output register */ - outb(par->misc, MIS_W); + outb(par->misc, VGA_MIS_W); /* synchronous reset on */ - outb(0x00, SEQ_I); - outb(0x01, SEQ_D); + outb(0x00, VGA_SEQ_I); + outb(0x01, VGA_SEQ_D); /* write sequencer registers */ - outb(1, SEQ_I); - outb(par->seq[1] | 0x20, SEQ_D); - for (i = 2; i < SEQ_C; i++) { - outb(i, SEQ_I); - outb(par->seq[i], SEQ_D); + outb(1, VGA_SEQ_I); + outb(par->seq[1] | 0x20, VGA_SEQ_D); + for (i = 2; i < VGA_SEQ_C; i++) { + outb(i, VGA_SEQ_I); + outb(par->seq[i], VGA_SEQ_D); } /* synchronous reset off */ - outb(0x00, SEQ_I); - outb(0x03, SEQ_D); + outb(0x00, VGA_SEQ_I); + outb(0x03, VGA_SEQ_D); /* deprotect CRT registers 0-7 */ - outb(0x11, CRT_IC); - outb(par->crtc[0x11], CRT_DC); + outb(0x11, VGA_CRT_IC); + outb(par->crtc[0x11], VGA_CRT_DC); /* write CRT registers */ - for (i = 0; i < CRTC_REGS; i++) { - outb(i, CRT_IC); - outb(par->crtc[i], CRT_DC); + for (i = 0; i < VGA_CRT_C; i++) { + outb(i, VGA_CRT_IC); + outb(par->crtc[i], VGA_CRT_DC); } /* write graphics controller registers */ - for (i = 0; i < GRA_C; i++) { - outb(i, GRA_I); - outb(par->gdc[i], GRA_D); + for (i = 0; i < VGA_GFX_C; i++) { + outb(i, VGA_GFX_I); + outb(par->gdc[i], VGA_GFX_D); } /* write attribute controller registers */ - for (i = 0; i < ATT_C; i++) { - inb_p(IS1_RC); /* reset flip-flop */ - outb_p(i, ATT_IW); - outb_p(par->atc[i], ATT_IW); + for (i = 0; i < VGA_ATT_C; i++) { + inb_p(VGA_IS1_RC); /* reset flip-flop */ + outb_p(i, VGA_ATT_IW); + outb_p(par->atc[i], VGA_ATT_IW); } /* Wait for screen to stabilize. */ mdelay(50); - outb(0x01, SEQ_I); - outb(par->seq[1], SEQ_D); + outb(0x01, VGA_SEQ_I); + outb(par->seq[1], VGA_SEQ_D); - inb(IS1_RC); - outb(0x20, ATT_IW); + inb(VGA_IS1_RC); + outb(0x20, VGA_ATT_IW); return 0; } @@ -799,14 +713,14 @@ static struct fb_ops vga16fb_ops = { vga16fb_ioctl }; -void vga16fb_setup(char *options, int *ints) +int vga16fb_setup(char *options) { char *this_opt; vga16fb.fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { if (!*this_opt) continue; @@ -814,6 +728,7 @@ void vga16fb_setup(char *options, int *ints) if (!strncmp(this_opt, "font:", 5)) strcpy(vga16fb.fb_info.fontname, this_opt+5); } + return 0; } static int vga16fb_switch(int con, struct fb_info *fb) @@ -1003,14 +918,20 @@ static void vga16fb_blank(int blank, struct fb_info *fb_info) } } -__initfunc(void vga16fb_init(void)) +int __init vga16_init(void) { int i,j; - printk("vga16fb: initializing\n"); + printk(KERN_DEBUG "vga16fb: initializing\n"); + + if (!__request_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN, + "vga16fb")) { + printk (KERN_ERR "vga16fb: unable to reserve VGA memory, exiting\n"); + return -1; + } - vga16fb.video_vbase = ioremap((unsigned long)0xa0000, 65536); - printk("vga16fb: mapped to 0x%p\n", vga16fb.video_vbase); + vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN); + printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.video_vbase); vga16fb.isVGA = ORIG_VIDEO_ISVGA; vga16fb.palette_blanked = 0; @@ -1027,10 +948,11 @@ __initfunc(void vga16fb_init(void)) palette[i].green = default_grn[j]; palette[i].blue = default_blu[j]; } - if (vga16fb.isVGA) - request_region(0x3c0, 32, "vga+"); - else - request_region(0x3C0, 32, "ega"); + + /* note - does not cause failure, b/c vgacon probably still owns this + * region (FIXME) */ + if (__request_region(&ioport_resource, 0x3C0, 32, "vga16fb")) + release_io_ports = 1; disp.var = vga16fb_defined; @@ -1047,12 +969,37 @@ __initfunc(void vga16fb_init(void)) vga16fb_set_disp(-1, &vga16fb); if (register_framebuffer(&vga16fb.fb_info)<0) - return; + return -EINVAL; - printk("fb%d: %s frame buffer device\n", + printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename); + + return 0; +} + +#ifndef MODULE +int __init vga16fb_init(void) +{ + return vga16_init(); +} + +#else /* MODULE */ + +int init_module(void) +{ + return vga16_init(); +} + +void cleanup_module(void) +{ + unregister_framebuffer(&vga16fb.fb_info); + iounmap(vga16fb.video_vbase); + __release_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN); + if (release_io_ports) + __release_region(&ioport_resource, 0x3c0, 32); } +#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/video/vga_font.c b/drivers/video/vga_font.c new file mode 100644 index 000000000..d6683ee4b --- /dev/null +++ b/drivers/video/vga_font.c @@ -0,0 +1,352 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/modversions.h> + + +#define cmapsz 8192 + +unsigned char vga_font[cmapsz] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index 95a758dd1..696845f8a 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -116,7 +116,7 @@ static int vga_video_font_height; static unsigned int vga_rolled_over = 0; -void no_scroll(char *str, int *ints) +static int __init no_scroll(char *str) { /* * Disabling scrollback is required for the Braillex ib80-piezo @@ -124,8 +124,11 @@ void no_scroll(char *str, int *ints) * Use the "no-scroll" bootflag. */ vga_hardscroll_user_enable = vga_hardscroll_enabled = 0; + return 1; } +__setup("no-scroll", no_scroll); + /* * By replacing the four outb_p with two back to back outw, we can reduce * the window of opportunity to see text mislocated to the RHS of the @@ -159,11 +162,11 @@ static inline void write_vga(unsigned char reg, unsigned int val) restore_flags(flags); } -__initfunc(static const char *vgacon_startup(void)) +static const char __init *vgacon_startup(void) { const char *display_desc = NULL; u16 saved1, saved2; - u16 *p; + volatile u16 *p; if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) { no_vga: @@ -186,18 +189,21 @@ __initfunc(static const char *vgacon_startup(void)) vga_video_port_val = 0x3b5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + static struct resource ega_console_resource = { "ega", 0x3B0, 0x3BF }; vga_video_type = VIDEO_TYPE_EGAM; vga_vram_end = 0xb8000; display_desc = "EGA+"; - request_region(0x3b0,16,"ega"); + request_resource(&ioport_resource, &ega_console_resource); } else { + static struct resource mda1_console_resource = { "mda", 0x3B0, 0x3BB }; + static struct resource mda2_console_resource = { "mda", 0x3BF, 0x3BF }; vga_video_type = VIDEO_TYPE_MDA; vga_vram_end = 0xb2000; display_desc = "*MDA"; - request_region(0x3b0,12,"mda"); - request_region(0x3bf, 1,"mda"); + request_resource(&ioport_resource, &mda1_console_resource); + request_resource(&ioport_resource, &mda2_console_resource); vga_video_font_height = 14; } } @@ -214,13 +220,15 @@ __initfunc(static const char *vgacon_startup(void)) vga_vram_end = 0xc0000; if (!ORIG_VIDEO_ISVGA) { + static struct resource ega_console_resource = { "ega", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_EGAC; display_desc = "EGA"; - request_region(0x3c0,32,"ega"); + request_resource(&ioport_resource, &ega_console_resource); } else { + static struct resource vga_console_resource = { "vga+", 0x3C0, 0x3DF }; vga_video_type = VIDEO_TYPE_VGAC; display_desc = "VGA+"; - request_region(0x3c0,32,"vga+"); + request_resource(&ioport_resource, &vga_console_resource); #ifdef VGA_CAN_DO_64KB /* @@ -261,13 +269,15 @@ __initfunc(static const char *vgacon_startup(void)) } else { + static struct resource cga_console_resource = { "cga", 0x3D4, 0x3D5 }; vga_video_type = VIDEO_TYPE_CGA; vga_vram_end = 0xba000; display_desc = "*CGA"; - request_region(0x3d4,2,"cga"); + request_resource(&ioport_resource, &cga_console_resource); vga_video_font_height = 8; } } + vga_vram_base = VGA_MAP_MEM(vga_vram_base); vga_vram_end = VGA_MAP_MEM(vga_vram_end); @@ -275,7 +285,7 @@ __initfunc(static const char *vgacon_startup(void)) * Find out if there is a graphics card present. * Are there smarter methods around? */ - p = (u16 *)vga_vram_base; + p = (volatile u16 *)vga_vram_base; saved1 = scr_readw(p); saved2 = scr_readw(p + 1); scr_writew(0xAA55, p); diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index a19c1c9e5..1e9abfe3d 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -85,10 +85,21 @@ (*((unsigned word volatile *)(CyberRegs + reg)) = dat) #define wl_3d(reg,dat) \ (*((unsigned long volatile *)(CyberRegs + reg)) = dat) - #define rl_3d(reg) \ (*((unsigned long volatile *)(CyberRegs + reg))) +#define Select_Zorro2_FrameBuffer(flag) \ + do { \ + *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x08)) = \ + ((flag * 0x40) & 0xffff); asm volatile ("nop"); \ + } while (0) +/* + * may be needed when we initialize the board? + * 8bit: flag = 2, 16 bit: flag = 1, 24/32bit: flag = 0 + * _when_ the board is initialized, depth doesnt matter, we allways write + * to the same address, aperture seems not to matter on Z2. + */ + struct virgefb_par { int xres; int yres; @@ -175,7 +186,10 @@ static unsigned char cv3d_on_zorro2; * Predefined Video Modes */ -static struct fb_videomode virgefb_predefined[] __initdata = { +static struct { + const char *name; + struct fb_var_screeninfo var; +} virgefb_predefined[] __initdata = { { "640x480-8", { /* Cybervision 8 bpp */ 640, 480, 640, 480, 0, 0, 8, 0, @@ -236,28 +250,28 @@ static struct fb_videomode virgefb_predefined[] __initdata = { "1024x768-16", { /* Cybervision 16 bpp */ 1024, 768, 1024, 768, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, { "1152x886-16", { /* Cybervision 16 bpp */ 1152, 886, 1152, 886, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, { "1280x1024-16", { /* Cybervision 16 bpp */ 1280, 1024, 1280, 1024, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, { "1600x1200-16", { /* Cybervision 16 bpp */ 1600, 1200, 1600, 1200, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } } @@ -268,10 +282,6 @@ static struct fb_videomode virgefb_predefined[] __initdata = { static int Cyberfb_inverse = 0; -#if 0 -static int Cyberfb_Cyber8 = 0; /* Use Cybervision board */ -static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */ -#endif /* * Some default modes @@ -287,7 +297,7 @@ static struct fb_var_screeninfo virgefb_default; * Interface used by the world */ -void virgefb_setup(char *options, int *ints); +int virgefb_setup(char*); static int virgefb_open(struct fb_info *info, int user); static int virgefb_release(struct fb_info *info, int user); @@ -311,7 +321,7 @@ static int virgefb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -void virgefb_init(void); +int virgefb_init(void); static int Cyberfb_switch(int con, struct fb_info *info); static int Cyberfb_updatevar(int con, struct fb_info *info); static void Cyberfb_blank(int blank, struct fb_info *info); @@ -392,6 +402,7 @@ static int Cyber_init(void) } else { CyberSize = 0x00400000; /* 4 MB */ } + memset ((char*)CyberMem, 0, CyberSize); /* Disable hardware cursor */ @@ -430,19 +441,19 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, virgefb_name); if (cv3d_on_zorro2) { - fix->smem_start = (char*) CyberMem_phys; + fix->smem_start = CyberMem_phys; } else { switch (par->bpp) { case 8: - fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_8); + fix->smem_start = (CyberMem_phys + CYBMEM_OFFSET_8); break; case 16: - fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_16); + fix->smem_start = (CyberMem_phys + CYBMEM_OFFSET_16); break; } } fix->smem_len = CyberSize; - fix->mmio_start = (char*) CyberRegs_phys; + fix->mmio_start = CyberRegs_phys; fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */ fix->type = FB_TYPE_PACKED_PIXELS; @@ -667,7 +678,13 @@ void Cyber_blank(int blank) * CV3D low-level support */ -#define Cyber3D_WaitQueue(v) { do { while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); } while (0); } +#define Cyber3D_WaitQueue(v) \ +{ \ + do { \ + while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); \ + } \ + while (0); \ +} static inline void Cyber3D_WaitBusy(void) { @@ -699,11 +716,22 @@ unsigned long status; */ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx, - u_short desty, u_short width, u_short height) + u_short desty, u_short width, u_short height, u_short depth) { - unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_DST_8BPP; + unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY; - blitcmd |= S3V_BLT_COPY; + switch (depth) { +#ifdef FBCON_HAS_CFB8 + case 8 : + blitcmd |= S3V_DST_8BPP; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16 : + blitcmd |= S3V_DST_16BPP; + break; +#endif + } /* Set drawing direction */ /* -Y, X maj, -X (default) */ @@ -748,16 +776,29 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx, */ static void Cyber3D_RectFill(u_short x, u_short y, u_short width, - u_short height, u_short color) + u_short height, u_short color, u_short depth) { unsigned int tmp; - unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP | + unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25); if (blit_maybe_busy) Cyber3D_WaitBusy(); blit_maybe_busy = 1; + switch (depth) { +#ifdef FBCON_HAS_CFB8 + case 8 : + blitcmd |= S3V_DST_8BPP; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16 : + blitcmd |= S3V_DST_16BPP; + break; +#endif + } + tmp = color & 0xff; wl_3d(0xa4f4, tmp); @@ -775,7 +816,7 @@ static void Cyber3D_RectFill(u_short x, u_short y, u_short width, #if 0 static void Cyber_MoveCursor (u_short x, u_short y) { - printk("Yuck .... MoveCursor on a 3D\n"); + printk(KERN_DEBUG "Yuck .... MoveCursor on a 3D\n"); return; } #endif @@ -1087,14 +1128,14 @@ static struct fb_ops virgefb_ops = { }; -__initfunc(void virgefb_setup(char *options, int *ints)) +int __init virgefb_setup(char *options) { char *this_opt; fb_info.fontname[0] = '\0'; if (!options || !*options) - return; + return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) if (!strcmp(this_opt, "inverse")) { @@ -1114,6 +1155,7 @@ __initfunc(void virgefb_setup(char *options, int *ints)) DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",virgefb_default.xres, virgefb_default.yres, virgefb_default.bits_per_pixel); + return 0; } @@ -1121,14 +1163,14 @@ __initfunc(void virgefb_setup(char *options, int *ints)) * Initialization */ -__initfunc(void virgefb_init(void)) +void __init virgefb_init(void) { struct virgefb_par par; unsigned long board_addr; const struct ConfigDev *cd; if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64_3D, 0, 0))) - return; + return -ENXIO; cd = zorro_get_board (CyberKey); zorro_config_board (CyberKey, 0); @@ -1152,18 +1194,17 @@ __initfunc(void virgefb_init(void)) Cyber_vcode_switch_base = (unsigned long) \ ZTWO_VADDR(board_addr + 0x003a0000); cv3d_on_zorro2 = 1; - printk("CV3D detected running in Z2 mode.\n"); + printk(KERN_INFO "CV3D detected running in Z2 mode.\n"); } else { CyberVGARegs = (unsigned long)ioremap(board_addr +0x0c000000, 0x00010000); - CyberRegs_phys = board_addr + 0x05000000; CyberMem_phys = board_addr + 0x04000000; /* was 0x04800000 */ CyberRegs = ioremap(CyberRegs_phys, 0x00010000); CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000); /* was 0x00400000 */ cv3d_on_zorro2 = 0; - printk("CV3D detected running in Z3 mode\n"); + printk(KERN_INFO "CV3D detected running in Z3 mode.\n"); } fbhw = &Cyber_switch; @@ -1188,15 +1229,16 @@ __initfunc(void virgefb_init(void)) do_install_cmap(0, &fb_info); if (register_framebuffer(&fb_info) < 0) { - printk("virgefb.c: register_framebuffer failed\n"); - return; + printk(KERN_ERR "virgefb.c: register_framebuffer failed\n"); + return -EINVAL; } - printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; + return 0; } @@ -1242,7 +1284,7 @@ static void Cyberfb_blank(int blank, struct fb_info *info) * Get a Video Mode */ -__initfunc(static int get_video_mode(const char *name)) +static int __init get_video_mode(const char *name) { int i; @@ -1269,7 +1311,7 @@ static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy, sx *= 8; dx *= 8; width *= 8; Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx, (u_short)(dy*fontheight(p)), (u_short)width, - (u_short)(height*fontheight(p))); + (u_short)(height*fontheight(p)), 8); } static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy, @@ -1281,7 +1323,7 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy, bg = attr_bgcol_ec(p,conp); Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)width, (u_short)(height*fontheight(p)), - (u_short)bg); + (u_short)bg, 8); } static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy, @@ -1326,10 +1368,10 @@ static struct display_switch fbcon_virge8 = { static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { - sx *= 16; dx *= 16; width *= 16; + sx *= 8; dx *= 8; width *= 8; Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx, (u_short)(dy*fontheight(p)), (u_short)width, - (u_short)(height*fontheight(p))); + (u_short)(height*fontheight(p)), 16); } static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy, @@ -1337,11 +1379,11 @@ static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy, { unsigned char bg; - sx *= 16; width *= 16; + sx *= 8; width *= 8; bg = attr_bgcol_ec(p,conp); Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)width, (u_short)(height*fontheight(p)), - (u_short)bg); + (u_short)bg, 16); } static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy, @@ -1385,8 +1427,7 @@ static struct display_switch fbcon_virge16 = { #ifdef MODULE int init_module(void) { - virgefb_init(); - return 0; + return virgefb_init(); } void cleanup_module(void) |