diff options
Diffstat (limited to 'drivers/video')
47 files changed, 4442 insertions, 815 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index cb04cf0c0..3cbc22762 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -4,12 +4,17 @@ if [ "$CONFIG_FB" = "y" ]; then define_bool CONFIG_DUMMY_CONSOLE y - if [ "$CONFIG_APUS" = "y" ]; then - bool 'Permedia2 support' CONFIG_FB_PM2 - if [ "$CONFIG_FB_PM2" = "y" ]; then - bool ' enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT - if [ "$CONFIG_APUS" = "y" ]; then - bool ' Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then + bool '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 + bool ' generic Permedia2 PCI board support' CONFIG_FB_PM2_PCI + fi + if [ "$CONFIG_AMIGA" = "y" ]; then + bool ' Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC + fi fi fi fi @@ -19,6 +24,9 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_APOLLO" = "y" ]; then define_bool CONFIG_FB_APOLLO y fi + if [ "$CONFIG_Q40" = "y" ]; then + define_bool CONFIG_FB_Q40 y + fi if [ "$CONFIG_AMIGA" = "y" ]; then bool 'Amiga native chipset support' CONFIG_FB_AMIGA if [ "$CONFIG_FB_AMIGA" != "n" ]; then @@ -33,6 +41,7 @@ if [ "$CONFIG_FB" = "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 @@ -64,6 +73,9 @@ if [ "$CONFIG_FB" = "y" ]; then bool 'VESA VGA graphics console' CONFIG_FB_VESA define_bool CONFIG_VIDEO_SELECT y fi + if [ "$CONFIG_VISWS" = "y" ]; then + tristate 'SGI Visual Workstation framebuffer support' CONFIG_FB_SGIVW + fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then if [ "$CONFIG_PCI" != "n" ]; then tristate 'Matrox acceleration' CONFIG_FB_MATROX @@ -166,7 +178,8 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$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" ]; then + "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o + "$CONFIG_FB_SGIVW = "y" ]; then define_bool CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ @@ -179,28 +192,31 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$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" ]; then + "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ + "$CONFIG_FB_SGIVW = "m" ]; then define_bool CONFIG_FBCON_CFB8 m fi fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ + "$CONFIG_FB_Q40" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \ - "$CONFIG_FB_PM2" = "y" ]; then + "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then define_bool CONFIG_FBCON_CFB16 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \ "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ + "$CONFIG_FB_Q40" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ - "$CONFIG_FB_PM2" = "m" ]; then + "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" ]; then define_bool CONFIG_FBCON_CFB16 m fi fi @@ -219,14 +235,16 @@ if [ "$CONFIG_FB" = "y" ]; then "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \ - "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then + "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \ + "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then define_bool CONFIG_FBCON_CFB32 y else if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \ - "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then + "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ + "$CONFIG_FB_SGIVW" = "m" ]; then define_bool CONFIG_FBCON_CFB32 m fi fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5c049664a..25b78efb9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -88,6 +88,10 @@ ifeq ($(CONFIG_FB_APOLLO),y) L_OBJS += dnfb.o endif +ifeq ($(CONFIG_FB_Q40),y) +L_OBJS += q40fb.o +endif + ifeq ($(CONFIG_FB_ATARI),y) L_OBJS += atafb.o else @@ -128,6 +132,14 @@ else endif endif +ifeq ($(CONFIG_FB_SGIVW),y) +L_OBJS += sgivwfb.o +else + ifeq ($(CONFIG_FB_SGIVW),m) + M_OBJS += sgivwfb.o + endif +endif + ifeq ($(CONFIG_FB_MAC),y) L_OBJS += macfb.o endif @@ -198,6 +210,10 @@ ifdef CONFIG_FB_G364 L_OBJS := $(L_OBJS) g364fb.o endif +ifdef CONFIG_FB_FM2 +L_OBJS := $(L_OBJS) fm2fb.o +endif + ifeq ($(CONFIG_FB_SBUS),y) L_OBJS += sbusfb.o ifeq ($(CONFIG_FB_CREATOR),y) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index f33d118b7..e35a79e0b 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -103,7 +103,7 @@ static int sttt_xres_virtual=640,sttt_yres_virtual=400; static int ovsc_offset=0, ovsc_addlen=0; static struct atafb_par { - unsigned long screen_base; + void *screen_base; int yres_virtual; #if defined ATAFB_TT || defined ATAFB_STE union { @@ -167,8 +167,8 @@ static int DontCalcRes = 0; static struct fb_info fb_info; -static unsigned long screen_base; /* base address of screen */ -static unsigned long real_screen_base; /* (only for Overscan) */ +static void *screen_base; /* base address of screen */ +static void *real_screen_base; /* (only for Overscan) */ static int screen_len; @@ -193,7 +193,7 @@ static unsigned external_yres; static unsigned external_depth; static int external_pmode; -static unsigned long external_addr = 0; +static void *external_addr = 0; static unsigned long external_len; static unsigned long external_vgaiobase = 0; static unsigned int external_bitspercol = 6; @@ -299,7 +299,7 @@ extern unsigned char fontdata_8x16[]; * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. * - * void (*set_screen_base)( unsigned long s_base ) + * void (*set_screen_base)(void *s_base) * Set the base address of the displayed frame buffer. Only called * if yres_virtual > yres or xres_virtual > xres. * @@ -328,7 +328,7 @@ static struct fb_hwswitch { int (*setcolreg)( unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info ); - void (*set_screen_base)( unsigned long s_base ); + void (*set_screen_base)(void *s_base); int (*blank)( int blank_mode ); int (*pan_display)( struct fb_var_screeninfo *var, struct atafb_par *par); @@ -464,7 +464,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix, int mode; strcpy(fix->id,"Atari Builtin"); - fix->smem_start = (char *)real_screen_base; + fix->smem_start = real_screen_base; fix->smem_len = screen_len; fix->type=FB_TYPE_INTERLEAVED_PLANES; fix->type_aux=2; @@ -797,7 +797,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, struct atafb_par *par ) { strcpy(fix->id, "Atari Builtin"); - fix->smem_start = (char *)real_screen_base; + fix->smem_start = real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; @@ -1760,7 +1760,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, int mode; strcpy(fix->id,"Atari Builtin"); - fix->smem_start = (char *)real_screen_base; + fix->smem_start = real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; @@ -2024,7 +2024,7 @@ static int stste_detect( void ) return 1; } -static void stste_set_screen_base(unsigned long s_base) +static void stste_set_screen_base(void *s_base) { unsigned long addr; addr= virt_to_phys(s_base); @@ -2104,8 +2104,8 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, { strcpy(fix->id,"Unknown Extern"); - fix->smem_start=(char *)external_addr; - fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK; + fix->smem_start=external_addr; + fix->smem_len = PAGE_ALIGN(external_len); if (external_depth == 1) { fix->type = FB_TYPE_PACKED_PIXELS; /* The letters 'n' and 'i' in the "atavideo=external:" stand @@ -2295,7 +2295,7 @@ static int ext_detect( void ) /* ------ This is the same for most hardware types -------- */ -static void set_screen_base(unsigned long s_base) +static void set_screen_base(void *s_base) { unsigned long addr; addr= virt_to_phys(s_base); @@ -2804,15 +2804,13 @@ __initfunc(void atafb_init(void)) #ifdef ATAFB_EXT if (!external_addr) { #endif /* ATAFB_EXT */ - mem_req = default_mem_req + ovsc_offset + - ovsc_addlen; - mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE; - screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL, - "atafb"); + mem_req = default_mem_req + ovsc_offset + ovsc_addlen; + mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; + screen_base = atari_stram_alloc(mem_req, NULL, "atafb"); if (!screen_base) panic("Cannot allocate screen memory"); - memset((char *) screen_base, 0, mem_req); - pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base; + memset(screen_base, 0, mem_req); + pad = -(unsigned long)screen_base & (PAGE_SIZE-1); screen_base+=pad; real_screen_base=screen_base+ovsc_offset; screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; @@ -2820,9 +2818,9 @@ __initfunc(void atafb_init(void)) if (CPU_IS_040_OR_060) { /* On a '040+, the cache mode of video RAM must be set to * write-through also for internal video hardware! */ - cache_push( virt_to_phys(screen_base), screen_len ); - kernel_set_cachemode( screen_base, screen_len, - IOMAP_WRITETHROUGH ); + cache_push(virt_to_phys(screen_base), screen_len); + kernel_set_cachemode(screen_base, screen_len, + IOMAP_WRITETHROUGH); } #ifdef ATAFB_EXT } @@ -2836,7 +2834,7 @@ __initfunc(void atafb_init(void)) screen_base = real_screen_base = external_addr; screen_len = external_len & PAGE_MASK; - memset ((char *) screen_base, 0, external_len); + memset (screen_base, 0, external_len); } #endif /* ATAFB_EXT */ diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index 6a3625d23..1f9e41ac8 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,4 +1,4 @@ -/* $Id: atyfb.c,v 1.98 1999/01/14 08:50:53 geert Exp $ +/* $Id: atyfb.c,v 1.106 1999/04/16 11:20:49 geert Exp $ * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * * Copyright (C) 1997-1998 Geert Uytterhoeven @@ -66,6 +66,8 @@ #include <asm/prom.h> #include <asm/pci-bridge.h> #include <video/macmodes.h> +#include <asm/adb.h> +#include <asm/pmu.h> #endif #ifdef __sparc__ #include <asm/pbm.h> @@ -383,7 +385,6 @@ void atyfb_of_init(struct device_node *dp); #endif void atyfb_setup(char *options, int *ints); - static int currcon = 0; static struct fb_ops atyfb_ops = { @@ -439,10 +440,10 @@ static struct aty_features { /* mach64CT family / mach64GT (3D RAGE) class */ { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" }, - { 0x4c42, 0x4c44, "3D RAGE LT PRO" }, - { 0x4c42, 0x4c47, "3D RAGE LT PRO" }, - { 0x4c42, 0x4c49, "3D RAGE LT PRO" }, - { 0x4c42, 0x4c50, "3D RAGE LT PRO" }, + { 0x4c44, 0x4c44, "3D RAGE LT PRO" }, + { 0x4c47, 0x4c47, "3D RAGE LT PRO" }, + { 0x4c49, 0x4c49, "3D RAGE LT PRO" }, + { 0x4c50, 0x4c50, "3D RAGE LT PRO" }, { 0x4c54, 0x4c54, "3D RAGE LT" }, { 0x4754, 0x4754, "3D RAGE (GT)" }, { 0x4755, 0x4755, "3D RAGE II+ (GTB)" }, @@ -777,7 +778,8 @@ aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel, return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -804,7 +806,8 @@ aty_set_cursor_shape(struct fb_info_aty *fb) return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -838,7 +841,8 @@ aty_set_cursor(struct fb_info_aty *fb, int on) return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -908,7 +912,8 @@ atyfb_cursor(struct display *p, int mode, int x, int y) return; #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -1282,7 +1287,7 @@ static int aty_crtc_to_var(const struct crtc *crtc, bpp = 16; var->red.offset = 11; var->red.length = 5; - var->green.offset = 6; + var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; @@ -1642,30 +1647,24 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per, pll_ext_cntl = mpostdiv; /* xclk == mclk */ switch (vclk_post_div) { - case 1: - vpostdiv = 0; - break; case 2: vpostdiv = 1; break; case 3: - vpostdiv = 0; pll_ext_cntl |= 0x10; + case 1: + vpostdiv = 0; break; + case 6: + pll_ext_cntl |= 0x10; case 4: vpostdiv = 2; break; - case 6: - vpostdiv = 2; + case 12: pll_ext_cntl |= 0x10; - break; case 8: vpostdiv = 3; break; - case 12: - vpostdiv = 3; - pll_ext_cntl |= 0x10; - break; } vclk_post_div = vpostdiv; @@ -1688,7 +1687,7 @@ static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per) 1, 2, 4, 8, 3, 0, 6, 12 }; - u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 1) | + u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 2) | (vclk_post_div & 3)]; if (vpostdiv == 0) return -EINVAL; @@ -2112,7 +2111,8 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con, if (info->fb_info.changevar) (*info->fb_info.changevar)(con); } - if (con == currcon) + if (!info->fb_info.display_fg || + info->fb_info.display_fg->vc_num == con) atyfb_set_par(&par, info); if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) @@ -2157,7 +2157,7 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -2176,16 +2176,21 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { int err; + struct display *disp; - if (!fb_display[con].cmap.len) { /* no colormap allocated? */ - int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; - if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) + if (con >= 0) + disp = &fb_display[con]; + else + disp = info->disp; + if (!disp->cmap.len) { /* no colormap allocated? */ + int size = disp->var.bits_per_pixel == 16 ? 32 : 256; + if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info); else - fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; } @@ -2196,6 +2201,12 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, #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; switch (cmd) { case FBIOGTYPE: @@ -2203,7 +2214,7 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, 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_cmsize = fb_display[con].cmap.len; + fbtyp.fb_cmsize = disp->cmap.len; fbtyp.fb_size = fb->total_vram; copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT); break; @@ -2321,8 +2332,6 @@ static int atyfb_mmap(struct fb_info *info, struct file *file, if (!map_size) return -EINVAL; - vma->vm_file = file; - file->f_count++; vma->vm_flags |= VM_IO; if (!fb->mmaped) { @@ -2353,10 +2362,10 @@ static void atyfb_save_palette(struct fb_info *fb, int enter) for (i = 0; i < 256; i++) { tmp = aty_ld_8(DAC_CNTL, info) & 0xfc; - if ((Gx == GT_CHIP_ID) || (Gx == GU_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)) + if (Gx == GT_CHIP_ID || 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) tmp |= 0x2; aty_st_8(DAC_CNTL, tmp, info); aty_st_8(DAC_MASK, 0xff, info); @@ -2785,7 +2794,7 @@ __initfunc(void atyfb_init(void)) */ for (i = 0; i < 6 && pdev->base_address[i]; i++) /* nothing */; - j = i + 3; + j = i + 4; info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC); if (!info->mmap_map) { @@ -2813,15 +2822,33 @@ __initfunc(void atyfb_init(void)) size &= ~1; size = ~(size) + 1; + /* + * Map the framebuffer a second time, this time without + * the braindead _PAGE_IE setting. This is used by the + * fixed Xserver, but we need to maintain the old mapping + * to stay compatible with older ones... + */ 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].size = 0x800000; - info->mmap_map[j].prot_mask = _PAGE_CACHE; - info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; - size -= 0x800000; - j++; + info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK; + info->mmap_map[j].poff = __pa(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; + j++; + } + + /* + * Here comes the old framebuffer mapping with _PAGE_IE + * set for the big endian half of the framebuffer... + */ + 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].size = 0x800000; + info->mmap_map[j].prot_mask = _PAGE_CACHE; + info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; + size -= 0x800000; + j++; } info->mmap_map[j].voff = pbase & PAGE_MASK; @@ -3296,6 +3323,11 @@ static void atyfbcon_blank(int blank, struct fb_info *fb) struct fb_info_aty *info = (struct fb_info_aty *)fb; u8 gen_cntl; +#if defined(CONFIG_PPC) + if ((_machine == _MACH_Pmac) && blank) + pmu_enable_backlight(0); +#endif + gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info); if (blank > 0) switch (blank-1) { @@ -3315,6 +3347,11 @@ static void atyfbcon_blank(int blank, struct fb_info *fb) else gen_cntl &= ~(0x4c); aty_st_8(CRTC_GEN_CNTL, gen_cntl, info); + +#if defined(CONFIG_PPC) + if ((_machine == _MACH_Pmac) && !blank) + pmu_enable_backlight(1); +#endif } @@ -3359,9 +3396,10 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, info->palette[regno].green = green; info->palette[regno].blue = blue; i = aty_ld_8(DAC_CNTL, info) & 0xfc; - if ((Gx == GT_CHIP_ID) || (Gx == GU_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)) + if (Gx == GT_CHIP_ID || 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) i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ aty_st_8(DAC_CNTL, i, info); aty_st_8(DAC_MASK, 0xff, info); @@ -3545,7 +3583,8 @@ static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3567,7 +3606,8 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, #ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3591,7 +3631,8 @@ static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3607,7 +3648,8 @@ static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3622,7 +3664,8 @@ static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3645,7 +3688,8 @@ static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3661,7 +3705,8 @@ static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3676,7 +3721,8 @@ static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3699,7 +3745,8 @@ static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3715,7 +3762,8 @@ static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3730,7 +3778,8 @@ static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3753,7 +3802,8 @@ static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3769,7 +3819,8 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif @@ -3784,7 +3835,8 @@ static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p, struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); #ifdef __sparc__ - if (fb->mmaped && currcon == fb->vtconsole) + if (fb->mmaped && (!fb->fb_info.display_fg + || fb->fb_info.display_fg->vc_num == fb->vtconsole)) return; #endif diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c index 00db47d10..0735ca1b3 100644 --- a/drivers/video/bwtwofb.c +++ b/drivers/video/bwtwofb.c @@ -1,4 +1,4 @@ -/* $Id: bwtwofb.c,v 1.6 1998/09/15 15:45:35 jj Exp $ +/* $Id: bwtwofb.c,v 1.7 1999/01/26 10:55:02 jj Exp $ * bwtwofb.c: BWtwo frame buffer driver * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -199,6 +199,7 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb) strcpy(fb->info.modename, "BWtwo"); strcpy(fix->id, "BWtwo"); fix->line_length = fb->var.xres_virtual>>3; + fix->accel = FB_ACCEL_SUN_BWTWO; disp->scrollmode = SCROLL_YREDRAW; disp->inverse = 1; diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c index f22389921..c5dfaad6e 100644 --- a/drivers/video/cgfourteenfb.c +++ b/drivers/video/cgfourteenfb.c @@ -1,4 +1,4 @@ -/* $Id: cgfourteenfb.c,v 1.3 1998/09/04 15:43:41 jj Exp $ +/* $Id: cgfourteenfb.c,v 1.4 1999/01/26 10:55:03 jj Exp $ * cgfourteenfb.c: CGfourteen frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -355,6 +355,7 @@ __initfunc(char *cgfourteenfb_init(struct fb_info_sbusfb *fb)) strcpy(fb->info.modename, "CGfourteen"); strcpy(fix->id, "CGfourteen"); fix->line_length = fb->var.xres_virtual; + fix->accel = FB_ACCEL_SUN_CG14; disp->scrollmode = SCROLL_YREDRAW; disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index 2891b4877..a62fd12ad 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $ +/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -352,8 +352,8 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh do { i = fbc->s; } while (i & 0x10000000); - fbc->fg = attr_fgcol(p,*s); - fbc->bg = attr_bgcol(p,*s); + fbc->fg = attr_fgcol(p, scr_readw(s)); + fbc->bg = attr_bgcol(p, scr_readw(s)); fbc->mode = 0x140000; fbc->alu = 0xe880fc30; fbc->pixelm = ~(0); @@ -379,15 +379,15 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh fbc->x1 = (x += 4 * fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { - fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) @@ -408,11 +408,11 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh fbc->x1 = (x += 2 * fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); - fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { - fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); - fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); + fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); + fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); @@ -428,9 +428,9 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh fbc->x1 = (x += fontwidth(p)) - 1; fbc->y0 = y; if (fontheightlog(p)) - i = ((*s++ & p->charmask) << fontheightlog(p)); + i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else - i = ((*s++ & p->charmask) * fontheight(p)); + i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) @@ -535,6 +535,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb) struct cg6_tec *tec = fb->s.cg6.tec; struct cg6_fbc *fbc = fb->s.cg6.fbc; u32 mode; + int i; /* Turn off stuff in the Transform Engine. */ tec->tec_matrix = 0; @@ -557,6 +558,9 @@ static void cg6_reset (struct fb_info_sbusfb *fb) * back to back store/loads on the mode register, so copy it * out instead. */ mode = fbc->mode; + do { + i = fbc->s; + } while (i & 0x10000000); mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c index 882669d8f..91611c674 100644 --- a/drivers/video/cgthreefb.c +++ b/drivers/video/cgthreefb.c @@ -1,4 +1,4 @@ -/* $Id: cgthreefb.c,v 1.3 1998/09/04 15:43:43 jj Exp $ +/* $Id: cgthreefb.c,v 1.4 1999/01/26 10:55:01 jj Exp $ * cgthreefb.c: CGthree frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -186,6 +186,7 @@ __initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb)) strcpy(fb->info.modename, "CGthree"); strcpy(fix->id, "CGthree"); fix->line_length = fb->var.xres_virtual; + fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c index 6e09ae666..3f95ae58c 100644 --- a/drivers/video/clgenfb.c +++ b/drivers/video/clgenfb.c @@ -204,8 +204,8 @@ 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 void clgen_set_dispsw(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 = @@ -220,7 +220,7 @@ static struct fbgen_hwswitch clgen_hwswitch = clgen_setcolreg, clgen_pan_display, clgen_blank, - clgen_set_dispsw + clgen_set_disp }; /* Text console acceleration */ @@ -1372,13 +1372,14 @@ static void switch_monitor(int on) } } -static void clgen_set_dispsw(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; - printk("clgen_get_dispsw(): "); + printk("clgen_set_disp(): "); + disp->screen_base = info2->fbmem; switch (_par->var.bits_per_pixel) { #ifdef FBCON_HAS_MFB @@ -1670,7 +1671,7 @@ __initfunc(void clgenfb_setup(char *options, int *ints)) int init_module(void) { printk("init_module()\n"); - clgenfb_init(0); + clgenfb_init(); return 0; } diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 129c4e396..2a783fc9b 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -377,7 +377,7 @@ static int controlfb_switch(int con, struct fb_info *info) control_set_hardware(p, &par); control_set_dispsw(&fb_display[con], par.cmode, p); - if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset); + if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset) controlfb_updatevar(con, info); do_install_cmap(con, info); @@ -447,21 +447,24 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { struct fb_info_control *p = (struct fb_info_control *) info; - int i; + u_int i; + __u8 r, g, b; if (regno > 255) return 1; - red >>= 8; - green >>= 8; - blue >>= 8; - p->palette[regno].red = red; - p->palette[regno].green = green; - p->palette[regno].blue = blue; + + r = red >> 8; + g = green >> 8; + b = blue >> 8; + + p->palette[regno].red = r; + p->palette[regno].green = g; + p->palette[regno].blue = b; out_8(&p->cmap_regs->addr, regno); /* tell clut what addr to fill */ - out_8(&p->cmap_regs->lut, red); /* send one color channel at */ - out_8(&p->cmap_regs->lut, green); /* a time... */ - out_8(&p->cmap_regs->lut, blue); + out_8(&p->cmap_regs->lut, r); /* send one color channel at */ + out_8(&p->cmap_regs->lut, g); /* a time... */ + out_8(&p->cmap_regs->lut, b); if (regno < 16) switch (p->par.cmode) { @@ -501,8 +504,9 @@ extern struct fb_info *console_fb_info; static inline int control_vram_reqd(int video_mode, int color_mode) { - return control_reg_init[video_mode-1]->vres - * control_reg_init[video_mode-1]->hres << color_mode; + return (control_reg_init[video_mode-1]->vres + * control_reg_init[video_mode-1]->hres << color_mode) + + control_reg_init[video_mode-1]->offset[color_mode]; } static void set_control_clock(unsigned char *params) @@ -557,6 +561,7 @@ __initfunc(static void init_control(struct fb_info_control *p)) par_set = 1; /* Debug */ control_par_to_var(par, &var); + var.activate = FB_ACTIVATE_NOW; control_set_var(&var, -1, &p->info); p->info.flags = FBINFO_FLAG_DEFAULT; @@ -616,11 +621,11 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro for (i = 0; i < 16; ++i, ++rp) out_le32(&rp->r, init->regs[i]); - out_le32(&p->control_regs->pitch.r, init->hres << cmode); + out_le32(&p->control_regs->pitch.r, par->vxres << cmode); out_le32(&p->control_regs->mode.r, init->mode[cmode]); out_le32(&p->control_regs->flags.r, flags); out_le32(&p->control_regs->start_addr.r, - par->yoffset * (par->vxres << par->cmode)); + par->yoffset * (par->vxres << cmode)); out_le32(&p->control_regs->reg18.r, 0x1e5); out_le32(&p->control_regs->reg19.r, 0); @@ -762,8 +767,6 @@ static int control_var_to_par(struct fb_var_screeninfo *var, int xres = var->xres; int yres = var->yres; int bpp = var->bits_per_pixel; - - struct control_regvals *init; struct fb_info_control *p = (struct fb_info_control *) fb_info; /* @@ -776,7 +779,7 @@ static int control_var_to_par(struct fb_var_screeninfo *var, */ /* swiped by jonh from atyfb.c */ if (xres <= 512 && yres <= 384) - par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */ + par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */ else if (xres <= 640 && yres <= 480) par->vmode = VMODE_640_480_67; /* 640x480, 67Hz */ else if (xres <= 640 && yres <= 870) @@ -844,8 +847,7 @@ static int control_var_to_par(struct fb_var_screeninfo *var, } /* Check if we know about the wanted video mode */ - init = control_reg_init[par->vmode-1]; - if (init == NULL) { + if (control_reg_init[par->vmode - 1] == NULL) { printk(KERN_ERR "init is null in control_var_to_par().\n"); /* I'm not sure if control has any specific requirements -- */ /* if we have a regvals struct, we're good to go? */ @@ -1010,7 +1012,7 @@ static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeni fix->smem_start = (void *)(p->frame_buffer_phys + control_reg_init[par->vmode-1]->offset[par->cmode]); - fix->smem_len = p->total_vram; + fix->smem_len = p->total_vram - control_reg_init[par->vmode-1]->offset[par->cmode]; fix->visual = (par->cmode == CMODE_8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; fix->line_length = par->vxres << par->cmode; @@ -1046,6 +1048,70 @@ static void control_par_to_display(struct fb_par_control *par, control_set_dispsw(disp, par->cmode, p); } +static void control_cfb16_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes = p->next_line, rows; + + dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2; + for (rows = fontheight(p); rows--; dest += bytes) { + switch (fontwidth(p)) { + case 16: + ((u32 *)dest)[6] ^= 0x3def3def; ((u32 *)dest)[7] ^= 0x3def3def; + /* FALL THROUGH */ + case 12: + ((u32 *)dest)[4] ^= 0x3def3def; ((u32 *)dest)[5] ^= 0x3def3def; + /* FALL THROUGH */ + case 8: + ((u32 *)dest)[2] ^= 0x3def3def; ((u32 *)dest)[3] ^= 0x3def3def; + /* FALL THROUGH */ + case 4: + ((u32 *)dest)[0] ^= 0x3def3def; ((u32 *)dest)[1] ^= 0x3def3def; + } + } +} + +static void control_cfb32_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes = p->next_line, rows; + + dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; + for (rows = fontheight(p); rows--; dest += bytes) { + switch (fontwidth(p)) { + case 16: + ((u32 *)dest)[12] ^= 0x0f0f0f0f; ((u32 *)dest)[13] ^= 0x0f0f0f0f; + ((u32 *)dest)[14] ^= 0x0f0f0f0f; ((u32 *)dest)[15] ^= 0x0f0f0f0f; + /* FALL THROUGH */ + case 12: + ((u32 *)dest)[8] ^= 0x0f0f0f0f; ((u32 *)dest)[9] ^= 0x0f0f0f0f; + ((u32 *)dest)[10] ^= 0x0f0f0f0f; ((u32 *)dest)[11] ^= 0x0f0f0f0f; + /* FALL THROUGH */ + case 8: + ((u32 *)dest)[4] ^= 0x0f0f0f0f; ((u32 *)dest)[5] ^= 0x0f0f0f0f; + ((u32 *)dest)[6] ^= 0x0f0f0f0f; ((u32 *)dest)[7] ^= 0x0f0f0f0f; + /* FALL THROUGH */ + case 4: + ((u32 *)dest)[0] ^= 0x0f0f0f0f; ((u32 *)dest)[1] ^= 0x0f0f0f0f; + ((u32 *)dest)[2] ^= 0x0f0f0f0f; ((u32 *)dest)[3] ^= 0x0f0f0f0f; + /* FALL THROUGH */ + } + } +} + +static struct display_switch control_cfb16 = { + fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc, + fbcon_cfb16_putcs, control_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; + +static struct display_switch control_cfb32 = { + fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc, + fbcon_cfb32_putcs, control_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; + + static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p) { switch (cmode) { @@ -1056,13 +1122,13 @@ static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_c #endif #ifdef FBCON_HAS_CFB16 case CMODE_16: - disp->dispsw = &fbcon_cfb16; + disp->dispsw = &control_cfb16; disp->dispsw_data = p->fbcon_cmap.cfb16; break; #endif #ifdef FBCON_HAS_CFB32 case CMODE_32: - disp->dispsw = &fbcon_cfb32; + disp->dispsw = &control_cfb32; disp->dispsw_data = p->fbcon_cmap.cfb32; break; #endif diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c index 69242992d..81421a7ff 100644 --- a/drivers/video/creatorfb.c +++ b/drivers/video/creatorfb.c @@ -1,7 +1,7 @@ -/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $ +/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $ * creatorfb.c: Creator/Creator3D frame buffer driver * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz) */ #include <linux/module.h> @@ -132,18 +132,10 @@ struct ffb_fbc { /* Next vertex registers */ - u32 xxx1[3]; - volatile u32 alpha; - volatile u32 red; - volatile u32 green; - volatile u32 blue; - volatile u32 depth; - volatile u32 y; - volatile u32 x; - u32 xxx2[2]; - volatile u32 ryf; - volatile u32 rxf; - u32 xxx3[2]; + u32 xxx1[3]; volatile u32 alpha; volatile u32 red; + volatile u32 green; volatile u32 blue; volatile u32 depth; volatile + u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32 + rxf; u32 xxx3[2]; volatile u32 dmyf; volatile u32 dmxf; @@ -276,16 +268,17 @@ struct ffb_fbc { volatile u32 mer; }; -static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n) +static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n) { - int limit = 10000; + struct ffb_fbc *fbc; + int cache = fb->s.ffb.fifo_cache; - do { - if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4)) - break; - if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0) - ffb->ucsr = FFB_UCSR_ALL_ERRORS; - } while(--limit > 0); + if (cache - n < 0) { + fbc = fb->s.ffb.fbc; + do { cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8; + } while (cache - n < 0); + } + fb->s.ffb.fifo_cache = cache - n; } static __inline__ void FFBWait(struct ffb_fbc *ffb) @@ -340,40 +333,45 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; - int x, y, w, h; + u64 yx, hw; + int fg; - FFBWait(fbc); - FFBFifo(fbc, 6); - fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)]; - fbc->drawop = FFB_DRAWOP_RECTANGLE; + fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)]; + if (fg != fb->s.ffb.fg_cache) { + FFBFifo(fb, 5); + fbc->fg = fg; + fb->s.ffb.fg_cache = fg; + } else + FFBFifo(fb, 4); if (fontheightlog(p)) { - y = sy << fontheightlog(p); h = height << fontheightlog(p); + yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32); } else { - y = sy * fontheight(p); h = height * fontheight(p); + yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32; } if (fontwidthlog(p)) { - x = sx << fontwidthlog(p); w = width << fontwidthlog(p); + yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p); } else { - x = sx * fontwidth(p); w = width * fontwidth(p); + yx += sx * fontwidth(p); hw += width * fontwidth(p); } - fbc->by = y + fb->y_margin; - fbc->bx = x + fb->x_margin; - fbc->bh = h; - fbc->bw = w; + *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin; + *(volatile u64 *)&fbc->bh = hw; } static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes) { register struct ffb_fbc *fbc = fb->s.ffb.fbc; + int fg; - FFBWait(fbc); - FFBFifo(fbc, 2); - fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)]; - fbc->drawop = FFB_DRAWOP_RECTANGLE; + fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)]; + if (fg != fb->s.ffb.fg_cache) { + FFBFifo(fb, 1); + fbc->fg = fg; + fb->s.ffb.fg_cache = fg; + } while (count-- > 0) { - FFBFifo(fbc, 4); + FFBFifo(fb, 4); fbc->by = boxes[1]; fbc->bx = boxes[0]; fbc->bh = boxes[3] - boxes[1]; @@ -388,6 +386,7 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int register struct ffb_fbc *fbc = fb->s.ffb.fbc; int i, xy; u8 *fd; + u64 fgbg; if (fontheightlog(p)) { xy = (yy << (16 + fontheightlog(p))); @@ -404,14 +403,16 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin; else xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin; - FFBWait(fbc); - FFBFifo(fbc, 5); - fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)]; - fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)]; - fbc->fontw = fontwidth(p); - fbc->fontinc = 0x10000; + fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) | + ((u32 *)p->dispsw_data)[attr_bgcol(p,c)]; + if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { + FFBFifo(fb, 2); + *(volatile u64 *)&fbc->fg = fgbg; + *(u64 *)&fb->s.ffb.fg_cache = fgbg; + } + FFBFifo(fb, 2 + fontheight(p)); fbc->fontxy = xy; - FFBFifo(fbc, fontheight(p)); + fbc->fontw = fontwidth(p); if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++) fbc->font = *fd++ << 24; @@ -430,11 +431,15 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh register struct ffb_fbc *fbc = fb->s.ffb.fbc; int i, xy; u8 *fd1, *fd2, *fd3, *fd4; - - FFBWait(fbc); - FFBFifo(fbc, 2); - fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)]; - fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)]; + u64 fgbg; + + fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) | + ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))]; + if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { + FFBFifo(fb, 2); + *(volatile u64 *)&fbc->fg = fgbg; + *(u64 *)&fb->s.ffb.fg_cache = fgbg; + } xy = fb->s.ffb.xy_margin; if (fontwidthlog(p)) xy += (xx << fontwidthlog(p)); @@ -447,22 +452,20 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; - FFBFifo(fbc, 3); + FFBFifo(fb, 2 + fontheight(p)); fbc->fontw = 4 * fontwidth(p); - fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { - fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } - FFBFifo(fbc, fontheight(p)); if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) @@ -478,18 +481,16 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh } else { while (count >= 2) { count -= 2; - FFBFifo(fbc, 3); + FFBFifo(fb, 2 + fontheight(p)); fbc->fontw = 2 * fontwidth(p); - fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); - fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { - fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); - fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); + fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); + fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } - FFBFifo(fbc, fontheight(p)); for (i = 0; i < fontheight(p); i++) { fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); fd1 += 2; fd2 += 2; @@ -499,15 +500,13 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh } while (count) { count--; - FFBFifo(fbc, 3); + FFBFifo(fb, 2 + fontheight(p)); fbc->fontw = fontwidth(p); - fbc->fontinc = 0x10000; fbc->fontxy = xy; if (fontheightlog(p)) - i = ((*s++ & p->charmask) << fontheightlog(p)); + i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else - i = ((*s++ & p->charmask) * fontheight(p)); - FFBFifo(fbc, fontheight(p)); + i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) @@ -554,8 +553,12 @@ static struct display_switch ffb_dispsw __initdata = { static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { + register struct ffb_fbc *fbc = fb->s.ffb.fbc; + fb->s.ffb.xy_margin = (y_margin << 16) + x_margin; + fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin; p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); + FFBWait(fbc); } static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) @@ -619,11 +622,16 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb) register struct ffb_fbc *fbc = fb->s.ffb.fbc; FFBWait(fbc); - FFBFifo(fbc, 4); + fb->s.ffb.fifo_cache = 0; + FFBFifo(fb, 8); fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST; fbc->fbc = 0x2000707f; fbc->rop = FFB_ROP_NEW; + fbc->drawop = FFB_DRAWOP_RECTANGLE; fbc->pmask = 0xffffffff; + fbc->fontinc = 0x10000; + fbc->fg = fb->s.ffb.fg_cache; + fbc->bg = fb->s.ffb.bg_cache; FFBWait(fbc); } @@ -675,6 +683,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) disp->scrollmode = SCROLL_YREDRAW; disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin; fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin; + fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin; fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF); fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF); fb->dispsw = ffb_dispsw; @@ -710,5 +719,10 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev); + /* Elite3D has different DAC revision numbering, and no DAC revisions + have the reversed meaning of cursor enable */ + if (afb) + fb->s.ffb.dac_rev = 10; + return idstring; } diff --git a/drivers/video/cvisionppc.h b/drivers/video/cvisionppc.h index 4a137548f..0afc0d04e 100644 --- a/drivers/video/cvisionppc.h +++ b/drivers/video/cvisionppc.h @@ -4,7 +4,7 @@ * * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * -------------------------------------------------------------------------- - * $Id: cvisionppc.h,v 1.1.2.1 1999/01/12 19:52:59 geert Exp $ + * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $ * -------------------------------------------------------------------------- * This file is subject to the terms and conditions of the GNU General Public * License. See the file README.legal in the main directory of this archive @@ -21,7 +21,7 @@ struct cvppc_par { unsigned char* pci_config; unsigned char* pci_bridge; - unsigned long user_flags; + u32 user_flags; }; #define CSPPC_PCI_BRIDGE 0xfffe0000 diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c index 205c1347d..3b9d4bb93 100644 --- a/drivers/video/fbcon-afb.c +++ b/drivers/video/fbcon-afb.c @@ -290,12 +290,12 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p, int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx; - fg0 = attr_fgcol(p,*s); - bg0 = attr_bgcol(p,*s); + fg0 = attr_fgcol(p, scr_readw(s)); + bg0 = attr_bgcol(p, scr_readw(s)); while (count--) if (xx&3 || count < 3) { /* Slow version */ - c1 = *s++ & p->charmask; + c1 = scr_readw(s++) & p->charmask; dest1 = dest0++; xx++; @@ -322,10 +322,10 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p, dest1 += p->next_plane; } while (--i); } else { /* Fast version */ - c1 = s[0] & p->charmask; - c2 = s[1] & p->charmask; - c3 = s[2] & p->charmask; - c4 = s[3] & p->charmask; + c1 = scr_readw(&s[0]) & p->charmask; + c2 = scr_readw(&s[1]) & p->charmask; + c3 = scr_readw(&s[2]) & p->charmask; + c4 = scr_readw(&s[3]) & p->charmask; dest1 = dest0; cdat10 = p->fontdata+c1*fontheight(p); diff --git a/drivers/video/fbcon-cfb16.c b/drivers/video/fbcon-cfb16.c index a05848f5b..9fef8171e 100644 --- a/drivers/video/fbcon-cfb16.c +++ b/drivers/video/fbcon-cfb16.c @@ -177,8 +177,8 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; - fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, *s)]; - bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, *s)]; + fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))]; + bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))]; fgx |= (fgx << 16); bgx |= (bgx << 16); eorx = fgx ^ bgx; @@ -187,7 +187,7 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, case 4: case 8: while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { u8 bits = *cdat++; @@ -204,7 +204,7 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, case 12: case 16: while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + (c * fontheight(p) << 1); for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) { u8 bits = *cdat++; diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c index e25fadaae..5b339a4fa 100644 --- a/drivers/video/fbcon-cfb2.c +++ b/drivers/video/fbcon-cfb2.c @@ -50,7 +50,7 @@ static u_char nibbletab_cfb2[]={ void fbcon_cfb2_setup(struct display *p) { - p->next_line = p->var.xres_virtual>>2; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>2; p->next_plane = 0; } @@ -156,15 +156,15 @@ void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned sh u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 2; - fgx=3/*attr_fgcol(p,*s)*/; - bgx=attr_bgcol(p,*s); + fgx=3/*attr_fgcol(p,scr_readw(s))*/; + bgx=attr_bgcol(p,scr_readw(s)); fgx |= (fgx << 2); fgx |= (fgx << 4); bgx |= (bgx << 2); bgx |= (bgx << 4); eorx = fgx ^ bgx; while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { diff --git a/drivers/video/fbcon-cfb24.c b/drivers/video/fbcon-cfb24.c index 488aac290..17e8ee08a 100644 --- a/drivers/video/fbcon-cfb24.c +++ b/drivers/video/fbcon-cfb24.c @@ -187,11 +187,11 @@ void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, u32 eorx, fgx, bgx, d1, d2, d3, d4; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3; - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)]; + fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))]; + bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))]; eorx = fgx ^ bgx; while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; if (fontwidth(p) <= 8) cdat = p->fontdata + c * fontheight(p); diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c index cd1e80a7d..b66ec2bad 100644 --- a/drivers/video/fbcon-cfb32.c +++ b/drivers/video/fbcon-cfb32.c @@ -163,11 +163,11 @@ void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4; - fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)]; - bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)]; + fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))]; + bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))]; eorx = fgx ^ bgx; while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; if (fontwidth(p) <= 8) cdat = p->fontdata + c * fontheight(p); else diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c index 78b87ffe7..6248c28ee 100644 --- a/drivers/video/fbcon-cfb4.c +++ b/drivers/video/fbcon-cfb4.c @@ -50,7 +50,7 @@ static u16 nibbletab_cfb4[] = { void fbcon_cfb4_setup(struct display *p) { - p->next_line = p->var.xres_virtual>>1; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>1; p->next_plane = 0; } @@ -158,8 +158,8 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4; - fgx=attr_fgcol(p,*s); - bgx=attr_bgcol(p,*s); + fgx=attr_fgcol(p,scr_readw(s)); + bgx=attr_bgcol(p,scr_readw(s)); fgx |= (fgx << 4); fgx |= (fgx << 8); fgx |= (fgx << 16); @@ -168,7 +168,7 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, bgx |= (bgx << 16); eorx = fgx ^ bgx; while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c index bfa98c719..0acf7c989 100644 --- a/drivers/video/fbcon-cfb8.c +++ b/drivers/video/fbcon-cfb8.c @@ -163,8 +163,8 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p); - fgx=attr_fgcol(p,*s); - bgx=attr_bgcol(p,*s); + fgx=attr_fgcol(p,scr_readw(s)); + bgx=attr_bgcol(p,scr_readw(s)); fgx |= (fgx << 8); fgx |= (fgx << 16); bgx |= (bgx << 8); @@ -173,7 +173,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, switch (fontwidth(p)) { case 4: while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) @@ -183,7 +183,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, break; case 8: while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { @@ -196,7 +196,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, case 12: case 16: while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; cdat = p->fontdata + (c * fontheight(p) << 1); for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) { diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c index 183f05a46..fbba519d9 100644 --- a/drivers/video/fbcon-ilbm.c +++ b/drivers/video/fbcon-ilbm.c @@ -154,12 +154,12 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx; - fg0 = attr_fgcol(p,*s); - bg0 = attr_bgcol(p,*s); + fg0 = attr_fgcol(p,scr_readw(s)); + bg0 = attr_bgcol(p,scr_readw(s)); while (count--) if (xx&3 || count < 3) { /* Slow version */ - c1 = *s++ & p->charmask; + c1 = scr_readw(s++) & p->charmask; dest = dest0++; xx++; @@ -185,10 +185,10 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, } } } else { /* Fast version */ - c1 = s[0] & p->charmask; - c2 = s[1] & p->charmask; - c3 = s[2] & p->charmask; - c4 = s[3] & p->charmask; + c1 = scr_readw(&s[0]) & p->charmask; + c2 = scr_readw(&s[1]) & p->charmask; + c3 = scr_readw(&s[2]) & p->charmask; + c4 = scr_readw(&s[3]) & p->charmask; dest = dest0; cdat1 = p->fontdata+c1*fontheight(p); diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c index 0c0bfa21f..0dfdc6107 100644 --- a/drivers/video/fbcon-iplan2p2.c +++ b/drivers/video/fbcon-iplan2p2.c @@ -361,12 +361,12 @@ void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, else dest0 = (p->screen_base + yy * bytes * fontheight(p) + (xx>>1)*4 + (xx & 1)); - fgx = expand2w(COLOR_2P(attr_fgcol(p,*s))); - bgx = expand2w(COLOR_2P(attr_bgcol(p,*s))); + fgx = expand2w(COLOR_2P(attr_fgcol(p,scr_readw(s)))); + bgx = expand2w(COLOR_2P(attr_bgcol(p,scr_readw(s)))); eorx = fgx ^ bgx; while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; if (fontheightlog(p)) cdat = p->fontdata + (c << fontheightlog(p)); else diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c index 2c1d67a77..805c9170b 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/fbcon-iplan2p4.c @@ -371,8 +371,8 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, else dest0 = (p->screen_base + yy * bytes * fontheight(p) + (xx>>1)*8 + (xx & 1)); - fgx = expand4l(attr_fgcol(p,*s)); - bgx = expand4l(attr_bgcol(p,*s)); + fgx = expand4l(attr_fgcol(p,scr_readw(s))); + bgx = expand4l(attr_bgcol(p,scr_readw(s))); eorx = fgx ^ bgx; while (count--) { @@ -383,7 +383,7 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, * cache :-( */ - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; if (fontheightlog(p)) cdat = p->fontdata + (c << fontheightlog(p)); else diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c index c730eb39c..411dc5ae9 100644 --- a/drivers/video/fbcon-iplan2p8.c +++ b/drivers/video/fbcon-iplan2p8.c @@ -404,8 +404,8 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, dest0 = (p->screen_base + yy * bytes * fontheight(p) + (xx>>1)*16 + (xx & 1)); - expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2); - expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2); + expand8dl(attr_fgcol(p,scr_readw(s)), &fgx1, &fgx2); + expand8dl(attr_bgcol(p,scr_readw(s)), &bgx1, &bgx2); eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2; while (count--) { @@ -417,7 +417,7 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, * cache :-( */ - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; if (fontheightlog(p)) cdat = p->fontdata + (c << fontheightlog(p)); else diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c index f2508e4cb..2c6486c41 100644 --- a/drivers/video/fbcon-mac.c +++ b/drivers/video/fbcon-mac.c @@ -301,7 +301,7 @@ void fbcon_mac_putcs(struct vc_data *conp, struct display *p, u16 c; while (count--) { - c = *s++; + c = scr_readw(s++); fbcon_mac_putc(conp, p, c, yy, xx++); } } diff --git a/drivers/video/fbcon-mfb.c b/drivers/video/fbcon-mfb.c index 32f1ea8d4..76caf5cc9 100644 --- a/drivers/video/fbcon-mfb.c +++ b/drivers/video/fbcon-mfb.c @@ -117,12 +117,12 @@ void fbcon_mfb_putcs(struct vc_data *conp, struct display *p, u16 c; dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx; - bold = attr_bold(p,*s); - revs = attr_reverse(p,*s); - underl = attr_underline(p,*s); + bold = attr_bold(p,scr_readw(s)); + revs = attr_reverse(p,scr_readw(s)); + underl = attr_underline(p,scr_readw(s)); while (count--) { - c = *s++ & p->charmask; + c = scr_readw(s++) & p->charmask; dest = dest0++; cdat = p->fontdata+c*fontheight(p); for (rows = fontheight(p); rows--; dest += p->next_line) { diff --git a/drivers/video/fbcon-vga.c b/drivers/video/fbcon-vga.c index fa4d387b8..05f843d25 100644 --- a/drivers/video/fbcon-vga.c +++ b/drivers/video/fbcon-vga.c @@ -155,11 +155,11 @@ void fbcon_vga_putcs(struct vc_data *conp, struct display *p, u16 sattr; if (conp->vc_can_do_color) while (count--) - vga_writew(*s++, dst++); + vga_writew(scr_readw(s++), dst++); else { - sattr = fbcon_vga_attr(p, *s); + sattr = fbcon_vga_attr(p, scr_readw(s)); while (count--) - vga_writew(sattr | ((int) (*s++) & 0xff), dst++); + vga_writew(sattr | ((int) (scr_readw(s++)) & 0xff), dst++); } } diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 033118f61..b3e56f322 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -26,7 +26,7 @@ * * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) * Smart redraw scrolling, arbitrary font width support, 512char font support - * added by + * and software scrollback added by * Jakub Jelinek (jj@ultra.linux.cz) * * Random hacking by Martin Mares <mj@ucw.cz> @@ -111,6 +111,12 @@ struct display fb_display[MAX_NR_CONSOLES]; static int logo_lines; static int logo_shown = -1; +/* Software scrollback */ +extern int fbcon_softback_size; +static unsigned long softback_buf, softback_curr; +static unsigned long softback_in; +static unsigned long softback_top, softback_end; +static int softback_lines; #define REFCOUNT(fd) (((int *)(fd))[-1]) #define FNTSIZE(fd) (((int *)(fd))[-2]) @@ -118,7 +124,12 @@ static int logo_shown = -1; #define FNTSUM(fd) (((int *)(fd))[-4]) #define FONT_EXTRA_WORDS 4 -static void fbcon_free_font(struct display *p); +#define CM_SOFTBACK (8) + +#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row) + +static void fbcon_free_font(struct display *); +static int fbcon_set_origin(struct vc_data *); /* * Emmanuel: fbcon will now use a hardware cursor if the @@ -422,6 +433,27 @@ static void fbcon_setup(int con, int init, int logo) logo = 0; p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ + + if (con == fg_console && p->type != FB_TYPE_TEXT) { + if (fbcon_softback_size) { + if (!softback_buf) { + softback_buf = (unsigned long)kmalloc(fbcon_softback_size, GFP_KERNEL); + if (!softback_buf) { + fbcon_softback_size = 0; + softback_top = 0; + } + } + } else { + if (softback_buf) { + kfree((void *)softback_buf); + softback_buf = 0; + softback_top = 0; + } + } + if (softback_buf) + softback_in = softback_top = softback_curr = softback_buf; + softback_lines = 0; + } for (i = 0; i < MAX_NR_CONSOLES; i++) if (i != con && fb_display[i].fb_info == p->fb_info && @@ -579,6 +611,17 @@ static void fbcon_setup(int con, int init, int logo) logo_shown = -2; conp->vc_top = logo_lines; } + + if (con == fg_console && softback_buf) { + int l = fbcon_softback_size / conp->vc_size_row; + if (l > 5) + softback_end = softback_buf + l * conp->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } } @@ -703,17 +746,29 @@ static void fbcon_cursor(struct vc_data *conp, int mode) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; + int y = conp->vc_y; + + if (mode & CM_SOFTBACK) { + mode &= ~CM_SOFTBACK; + if (softback_lines) { + if (y + softback_lines >= conp->vc_rows) + mode = CM_ERASE; + else + y += softback_lines; + } + } else if (softback_lines) + fbcon_set_origin(conp); /* do we have a hardware cursor ? */ if (p->dispsw->cursor) { p->cursor_x = conp->vc_x; - p->cursor_y = conp->vc_y; + p->cursor_y = y; p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y)); return; } /* Avoid flickering if there's no real change. */ - if (p->cursor_x == conp->vc_x && p->cursor_y == conp->vc_y && + if (p->cursor_x == conp->vc_x && p->cursor_y == y && (mode == CM_ERASE) == !cursor_on) return; @@ -722,7 +777,7 @@ static void fbcon_cursor(struct vc_data *conp, int mode) p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); p->cursor_x = conp->vc_x; - p->cursor_y = conp->vc_y; + p->cursor_y = y; switch (mode) { case CM_ERASE: @@ -836,6 +891,94 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp, scrollback_current = 0; } +static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta) +{ + unsigned short *d, *s; + unsigned long n; + int line = 0; + int count = conp->vc_rows; + + d = (u16 *)softback_curr; + if (d == (u16 *)softback_in) + d = (u16 *)conp->vc_origin; + n = softback_curr + delta * conp->vc_size_row; + softback_lines -= delta; + if (delta < 0) { + if (softback_curr < softback_top && n < softback_buf) { + n += softback_end - softback_buf; + if (n < softback_top) { + softback_lines -= (softback_top - n) / conp->vc_size_row; + n = softback_top; + } + } else if (softback_curr >= softback_top && n < softback_top) { + softback_lines -= (softback_top - n) / conp->vc_size_row; + n = softback_top; + } + } else { + if (softback_curr > softback_in && n >= softback_end) { + n += softback_buf - softback_end; + if (n > softback_in) { + n = softback_in; + softback_lines = 0; + } + } else if (softback_curr <= softback_in && n > softback_in) { + n = softback_in; + softback_lines = 0; + } + } + if (n == softback_curr) + return; + softback_curr = n; + s = (u16 *)softback_curr; + if (s == (u16 *)softback_in) + s = (u16 *)conp->vc_origin; + while (count--) { + unsigned short *start; + unsigned short *le; + unsigned short c; + int x = 0; + unsigned short attr = 1; + + start = s; + le = advance_row(s, 1); + do { + c = scr_readw(s); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (s > start) { + p->dispsw->putcs(conp, p, start, s - start, + real_y(p, line), x); + x += s - start; + start = s; + } + } + if (c == scr_readw(d)) { + if (s > start) { + p->dispsw->putcs(conp, p, start, s - start, + real_y(p, line), x); + x += s - start + 1; + start = s + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (s < le); + if (s > start) + p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x); + line++; + if (d == (u16 *)softback_end) + d = (u16 *)softback_buf; + if (d == (u16 *)softback_in) + d = (u16 *)conp->vc_origin; + if (s == (u16 *)softback_end) + s = (u16 *)softback_buf; + if (s == (u16 *)softback_in) + s = (u16 *)conp->vc_origin; + } +} static void fbcon_redraw(struct vc_data *conp, struct display *p, int line, int count, int offset) @@ -846,8 +989,7 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p, while (count--) { unsigned short *start = s; - unsigned short *le = (unsigned short *) - ((unsigned long)s + conp->vc_size_row); + unsigned short *le = advance_row(s, 1); unsigned short c; int x = 0; unsigned short attr = 1; @@ -940,13 +1082,32 @@ void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h } } +static inline void fbcon_softback_note(struct vc_data *conp, int t, int count) +{ + unsigned short *p = (unsigned short *) + (conp->vc_origin + t * conp->vc_size_row); + while (count) { + scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row); + count--; + p = advance_row(p, 1); + softback_in += conp->vc_size_row; + if (softback_in == softback_end) + softback_in = softback_buf; + if (softback_in == softback_top) { + softback_top += conp->vc_size_row; + if (softback_top == softback_end) + softback_top = softback_buf; + } + } + softback_curr = softback_in; +} + static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL); - int logos_left = 0; int logos_width = conp->vc_cols; if (!p->can_soft_blank && console_blanked) return 0; @@ -955,7 +1116,7 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, return 0; fbcon_cursor(conp, CM_ERASE); - + /* * ++Geert: Only use ywrap/ypan if the console is in text mode * ++Andrew: Only use ypan on hardware text mode when scrolling the @@ -964,34 +1125,25 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, switch (dir) { case SM_UP: - /* K.Garloff@ping.de, 98/10/21: If logo is diplayed, only save logo - * and not the hole top region. In combination with the logo being - * displayed on the right side, this allows scrollback feature - * when bootlogo is displayed. */ - if (t != 0 && logo_shown == fg_console) { - struct display *p = &fb_display[unit]; - int lw = (smp_num_cpus * (LOGO_W + 8) - 7) / fontwidth(p) + 1; - logos_left = conp->vc_cols - lw; - while (logos_left < 0) logos_left += (LOGO_W + 8 - 7) / fontwidth(p); - logos_width = conp->vc_cols - logos_left; - } if (count > conp->vc_rows) /* Maximum realistic size */ count = conp->vc_rows; + if (softback_top) + fbcon_softback_note(conp, t, count); + if (logo_shown >= 0) goto redraw_up; switch (p->scrollmode & __SCROLL_YMASK) { case __SCROLL_YMOVE: - if (t > 0) p->dispsw->bmove(p, 0, logos_left, count, - logos_left, t, logos_width); - p->dispsw->bmove(p, count, 0, 0, 0, b-count, + p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count, conp->vc_cols); - p->dispsw->clear(conp, p, b-count, 0, count, + p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols); break; case __SCROLL_YWRAP: - if (b-t-count > 2*conp->vc_rows/3) { + if (b-t-count > 3*conp->vc_rows>>2) { if (t > 0) - fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width); - ywrap_up(unit, conp, p, count); + fbcon_bmove(conp, 0, 0, count, 0, t, + conp->vc_cols); + ywrap_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); @@ -1004,11 +1156,12 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case __SCROLL_YPAN: - if (( !scroll_partial && (b-t == conp->vc_rows)) || - ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) { + if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) && + (( !scroll_partial && (b-t == conp->vc_rows)) || + ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { if (t > 0) - fbcon_bmove(conp, 0, logos_left, count, logos_left, t, - logos_width); + fbcon_bmove(conp, 0, 0, count, 0, t, + conp->vc_cols); ypan_up(unit, conp, p, count); if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, @@ -1063,8 +1216,9 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case __SCROLL_YPAN: - if (( !scroll_partial && (b-t == conp->vc_rows)) || - ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) { + if (( count-p->yscroll <= p->vrows-conp->vc_rows) && + (( !scroll_partial && (b-t == conp->vc_rows)) || + ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) { if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); @@ -1112,7 +1266,7 @@ static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, (sx <= p->cursor_x) && (p->cursor_x < sx+width)) || ((dy <= p->cursor_y) && (p->cursor_y < dy+height) && (dx <= p->cursor_x) && (p->cursor_x < dx+width))) - fbcon_cursor(conp, CM_ERASE); + fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); /* Split blits that cross physical y_wrap case. * Pathological case involves 4 blits, better to use recursive @@ -1162,6 +1316,21 @@ static int fbcon_switch(struct vc_data *conp) struct display *p = &fb_display[unit]; struct fb_info *info = p->fb_info; + if (softback_top) { + int l = fbcon_softback_size / conp->vc_size_row; + if (softback_lines) + fbcon_set_origin(conp); + softback_top = softback_curr = softback_in = softback_buf; + softback_lines = 0; + + if (l > 5) + softback_end = softback_buf + l * conp->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } if (logo_shown >= 0) { struct vc_data *conp2 = vc_cons[logo_shown].d; @@ -1227,8 +1396,22 @@ static int fbcon_blank(struct vc_data *conp, int blank) mymemset(p->screen_base, p->var.xres_virtual*p->var.yres_virtual* p->var.bits_per_pixel>>3); - } else - p->dispsw->clear(conp, p, 0, 0, conp->vc_rows, conp->vc_cols); + } else { + unsigned short oldc; + u_int height; + u_int y_break; + + oldc = conp->vc_video_erase_char; + conp->vc_video_erase_char &= p->charmask; + height = conp->vc_rows; + y_break = p->vrows-p->yscroll; + if (height > y_break) { + p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols); + p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols); + } else + p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols); + conp->vc_video_erase_char = oldc; + } return 0; } else { /* Tell console.c that it has to restore the screen itself */ @@ -1320,6 +1503,9 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int return -ENXIO; } + if (CON_IS_VISIBLE(p->conp) && softback_lines) + fbcon_set_origin(p->conp); + resize = (w != fontwidth(p)) || (h != fontheight(p)); if (p->userfont) old_data = p->fontdata; @@ -1390,6 +1576,7 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int fbcon_font_widths(p); if (resize) { + struct vc_data *conp = p->conp; /* reset wrap/pan */ p->var.xoffset = p->var.yoffset = p->yscroll = 0; p->vrows = p->var.yres_virtual/h; @@ -1397,6 +1584,16 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int p->vrows--; updatescrollmode(p); vc_resize_con( p->var.yres/h, p->var.xres/w, unit ); + if (CON_IS_VISIBLE(conp) && softback_buf) { + int l = fbcon_softback_size / conp->vc_size_row; + if (l > 5) + softback_end = softback_buf + l * conp->vc_size_row; + else { + /* Smaller scrollback makes no sense, and 0 would screw + the operation totally */ + softback_top = 0; + } + } } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) { if (p->dispsw->clear_margins) p->dispsw->clear_margins(p->conp, p, 0); @@ -1432,9 +1629,6 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op) int h = op->height; int size = h; int i, k; -#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY - int j; -#endif u8 *new_data, *data = op->data, *p; #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY @@ -1476,6 +1670,7 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op) } } else if (w <= 24) { for (i = 0; i < op->charcount; i++) { + int j; for (j = 0; j < h; j++) { memcpy(p, data, 3); p[3] = 0; @@ -1505,6 +1700,7 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op) fb_display[i].fontdata && FNTSUM(fb_display[i].fontdata) == k && FNTSIZE(fb_display[i].fontdata) == size && + fontwidth(&fb_display[i]) == w && !memcmp(fb_display[i].fontdata, new_data, size)) { kfree(new_data - FONT_EXTRA_WORDS*sizeof(int)); new_data = fb_display[i].fontdata; @@ -1586,10 +1782,119 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info); } +static u16 *fbcon_screen_pos(struct vc_data *conp, int offset) +{ + int line; + unsigned long p; + + if (conp->vc_num != fg_console || !softback_lines) + return (u16 *)(conp->vc_origin + offset); + line = offset / conp->vc_size_row; + if (line >= softback_lines) + return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row); + p = softback_curr + offset; + if (p >= softback_end) + p += softback_buf - softback_end; + return (u16 *)p; +} + +static unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py) +{ + int x, y; + unsigned long ret; + if (pos >= conp->vc_origin && pos < conp->vc_scr_end) { + unsigned long offset = (pos - conp->vc_origin) / 2; + + x = offset % conp->vc_cols; + y = offset / conp->vc_cols; + if (conp->vc_num == fg_console) + y += softback_lines; + ret = pos + (conp->vc_cols - x) * 2; + } else if (conp->vc_num == fg_console && softback_lines) { + unsigned long offset = (pos - softback_curr) / 2; + + x = offset % conp->vc_cols; + y = offset / conp->vc_cols; + if (pos < softback_curr) + y += (softback_end - softback_buf) / conp->vc_size_row; + ret = pos + (conp->vc_cols - x) * 2; + if (ret == softback_end) + ret = softback_buf; + if (ret == softback_in) + ret = conp->vc_origin; + } else { + /* Should not happen */ + x = y = 0; + ret = conp->vc_origin; + } + if (px) *px = x; + if (py) *py = y; + return ret; +} + +/* As we might be inside of softback, we may work with non-contiguous buffer, + that's why we have to use a separate routine. */ +static void fbcon_invert_region(struct vc_data *conp, u16 *p, int cnt) +{ + while (cnt--) { + if (!conp->vc_can_do_color) + *p++ ^= 0x0800; + else if (conp->vc_hi_font_mask == 0x100) { + u16 a = *p; + a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4); + *p++ = a; + } else { + u16 a = *p; + a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); + *p++ = a; + } + if (p == (u16 *)softback_end) + p = (u16 *)softback_buf; + if (p == (u16 *)softback_in) + p = (u16 *)conp->vc_origin; + } +} + static int fbcon_scrolldelta(struct vc_data *conp, int lines) { int unit, offset, limit, scrollback_old; struct display *p; + + unit = fg_console; + p = &fb_display[unit]; + if (softback_top) { + if (conp->vc_num != unit) + return 0; + if (vt_cons[unit]->vc_mode != KD_TEXT || !lines) + return 0; + if (logo_shown >= 0) { + struct vc_data *conp2 = vc_cons[logo_shown].d; + + if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) + conp2->vc_top = 0; + if (logo_shown == unit) { + unsigned long p, q; + int i; + + p = softback_in; + q = conp->vc_origin + logo_lines * conp->vc_size_row; + for (i = 0; i < logo_lines; i++) { + if (p == softback_top) break; + if (p == softback_buf) p = softback_end; + p -= conp->vc_size_row; + q -= conp->vc_size_row; + scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row); + } + softback_in = p; + update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols); + } + logo_shown = -1; + } + fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK); + fbcon_redraw_softback(conp, p, lines); + fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK); + return 0; + } if (!scrollback_phys_max) return -ENOSYS; @@ -1603,8 +1908,6 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines) if (scrollback_current == scrollback_old) return 0; - unit = fg_console; - p = &fb_display[unit]; if (!p->can_soft_blank && (console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines)) return 0; @@ -1633,6 +1936,13 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines) return 0; } +static int fbcon_set_origin(struct vc_data *conp) +{ + if (softback_lines && !console_blanked) + fbcon_scrolldelta(conp, softback_lines); + return 0; +} + static inline unsigned safe_shift(unsigned d,int n) { return n<0 ? d>>-n : d<<n; @@ -1652,7 +1962,7 @@ __initfunc(static int fbcon_show_logo( void )) /* Return if the frame buffer is not mapped */ if (!fb) return 0; - + /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for * DIRECTCOLOR */ if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) || @@ -1704,9 +2014,12 @@ __initfunc(static int fbcon_show_logo( void )) logo = linux_logo_bw; logo_depth = 1; } + + if (p->fb_info->fbops->fb_rasterimg) + p->fb_info->fbops->fb_rasterimg(p->fb_info, 1); - for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres - - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) { + for (x = 0; x < smp_num_cpus * (LOGO_W + 8) && + x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) { #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) @@ -1730,12 +2043,18 @@ __initfunc(static int fbcon_show_logo( void )) val = (*src << redshift) | (*src << greenshift) | (*src << blueshift); + if (bdepth == 4 && !((long)dst & 3)) { + /* Some cards require 32bit access */ + *(u32 *)dst = val; + dst += 4; + } else { #ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) + for( i = 0; i < bdepth; ++i ) #else - for( i = bdepth-1; i >= 0; --i ) + for( i = bdepth-1; i >= 0; --i ) #endif - *dst++ = val >> (i*8); + *dst++ = val >> (i*8); + } } } } @@ -1798,12 +2117,18 @@ __initfunc(static int fbcon_show_logo( void )) val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) | safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) | safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift); + if (bdepth == 4 && !((long)dst & 3)) { + /* Some cards require 32bit access */ + *(u32 *)dst = val; + dst += 4; + } else { #ifdef __LITTLE_ENDIAN - for( i = 0; i < bdepth; ++i ) + for( i = 0; i < bdepth; ++i ) #else - for( i = bdepth-1; i >= 0; --i ) + for( i = bdepth-1; i >= 0; --i ) #endif - *dst++ = val >> (i*8); + *dst++ = val >> (i*8); + } } } done = 1; @@ -1914,6 +2239,9 @@ __initfunc(static int fbcon_show_logo( void )) #endif } + if (p->fb_info->fbops->fb_rasterimg) + p->fb_info->fbops->fb_rasterimg(p->fb_info, 0); + /* Modes not yet supported: packed pixels with depth != 8 (does such a * thing exist in reality?) */ @@ -1939,10 +2267,12 @@ struct consw fb_con = { con_font_op: fbcon_font_op, con_set_palette: fbcon_set_palette, con_scrolldelta: fbcon_scrolldelta, - con_set_origin: NULL, + con_set_origin: fbcon_set_origin, con_save_screen: NULL, con_build_attr: NULL, - con_invert_region: NULL, + con_invert_region: fbcon_invert_region, + con_screen_pos: fbcon_screen_pos, + con_getxy: fbcon_getxy, }; diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c index c3c42ed5e..ff14807a0 100644 --- a/drivers/video/fbgen.c +++ b/drivers/video/fbgen.c @@ -244,7 +244,6 @@ void fbgen_set_disp(int con, struct fb_info_gen *info) memset(&fix, 0, sizeof(struct fb_fix_screeninfo)); fbhw->encode_fix(&fix, &par, info); - display->screen_base = phys_to_virt((unsigned long)fix.smem_start); display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -256,7 +255,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info) display->can_soft_blank = 1; else display->can_soft_blank = 0; - fbhw->set_dispsw(&par, display, info); + fbhw->set_disp(&par, display, info); #if 0 /* FIXME: generic inverse is not supported yet */ display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); #else diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d8e6b0829..34c57ddb5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -88,12 +88,20 @@ 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); static struct { const char *name; void (*init)(void); void (*setup)(char *options, int *ints); } fb_drivers[] __initdata = { +#ifdef CONFIG_FB_SGIVW + { "sgivw", sgivwfb_init, sgivwfb_setup }, +#endif #ifdef CONFIG_FB_RETINAZ3 { "retz3", retz3fb_init, retz3fb_setup }, #endif @@ -136,6 +144,9 @@ static struct { #ifdef CONFIG_APOLLO { "apollo", dnfb_init, NULL }, #endif +#ifdef CONFIG_FB_Q40 + { "q40fb", q40fb_init, NULL }, +#endif #ifdef CONFIG_FB_S3TRIO { "s3trio", s3triofb_init, s3triofb_setup }, #endif @@ -160,6 +171,9 @@ static struct { #ifdef CONFIG_FB_G364 { "g364", g364fb_init, NULL }, #endif +#ifdef CONFIG_FB_FM2 + { "fm2fb", fm2fb_init, fm2fb_setup }, +#endif #ifdef CONFIG_GSP_RESOLVER /* Not a real frame buffer device... */ { "resolver", NULL, resolver_video_setup }, @@ -181,6 +195,7 @@ static int num_pref_init_funcs __initdata = 0; struct fb_info *registered_fb[FB_MAX]; int num_registered_fb = 0; +int fbcon_softback_size = 32768; char con2fb_map[MAX_NR_CONSOLES]; @@ -188,17 +203,24 @@ static int first_fb_vc = 0; static int last_fb_vc = MAX_NR_CONSOLES-1; static int fbcon_is_default = 1; -static inline int PROC_CONSOLE(void) +static int PROC_CONSOLE(struct fb_info *info) { + int fgc; + + if (info->display_fg != NULL) + fgc = info->display_fg->vc_num; + else + return -1; + if (!current->tty) - return fg_console; + return fgc; if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) /* XXX Should report error here? */ - return fg_console; + return fgc; if (MINOR(current->tty->device) < 1) - return fg_console; + return fgc; return MINOR(current->tty->device) - 1; } @@ -233,7 +255,7 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos) if (! fb || ! info->disp) return -ENODEV; - fb->fb_get_fix(&fix,PROC_CONSOLE(), info); + fb->fb_get_fix(&fix,PROC_CONSOLE(info), info); base_addr=info->disp->screen_base; copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); if (copy_to_user(buf, base_addr+p, copy_size)) @@ -257,7 +279,7 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) if (! fb || ! info->disp) return -ENODEV; - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); + fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); base_addr=info->disp->screen_base; copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p); if (copy_from_user(base_addr+p, buf, copy_size)) @@ -273,7 +295,7 @@ static int set_all_vcs(int fbidx, struct fb_ops *fb, int unit, err; var->activate |= FB_ACTIVATE_TEST; - err = fb->fb_set_var(var, PROC_CONSOLE(), info); + err = fb->fb_set_var(var, PROC_CONSOLE(info), info); var->activate &= ~FB_ACTIVATE_TEST; if (err) return err; @@ -350,7 +372,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -ENODEV; switch (cmd) { case FBIOGET_VSCREENINFO: - if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info))) + if ((i = fb->fb_get_var(&var, PROC_CONSOLE(info), info))) return i; return copy_to_user((void *) arg, &var, sizeof(var)) ? -EFAULT : 0; @@ -359,29 +381,29 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EFAULT; i = var.activate & FB_ACTIVATE_ALL ? set_all_vcs(fbidx, fb, &var, info) - : fb->fb_set_var(&var, PROC_CONSOLE(), info); + : fb->fb_set_var(&var, PROC_CONSOLE(info), info); if (i) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; return 0; case FBIOGET_FSCREENINFO: - if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info))) + if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(info), info))) return i; return copy_to_user((void *) arg, &fix, sizeof(fix)) ? -EFAULT : 0; case FBIOPUTCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info)); + return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(info), info)); case FBIOGETCMAP: if (copy_from_user(&cmap, (void *) arg, sizeof(cmap))) return -EFAULT; - return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info)); + return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(info), info)); case FBIOPAN_DISPLAY: if (copy_from_user(&var, (void *) arg, sizeof(var))) return -EFAULT; - if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info))) + if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(info), info))) return i; if (copy_to_user((void *) arg, &var, sizeof(var))) return -EFAULT; @@ -415,7 +437,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, set_con2fb_map(i, con2fb.framebuffer); return 0; default: - return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(), + return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info), info); } } @@ -435,7 +457,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) return -ENODEV; if (fb->fb_mmap) return fb->fb_mmap(info, file, vma); - fb->fb_get_fix(&fix, PROC_CONSOLE(), info); + fb->fb_get_fix(&fix, PROC_CONSOLE(info), info); /* frame buffer memory */ start = (unsigned long)fix.smem_start; @@ -445,7 +467,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (vma->vm_offset >= len) { /* memory mapped io */ vma->vm_offset -= len; - fb->fb_get_var(&var, PROC_CONSOLE(), info); + fb->fb_get_var(&var, PROC_CONSOLE(info), info); if (var.accel_flags) return -EINVAL; start = (unsigned long)fix.mmio_start; @@ -485,8 +507,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (remap_page_range(vma->vm_start, vma->vm_offset, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; - vma->vm_file = file; - file->f_count++; return 0; } @@ -648,6 +668,21 @@ __initfunc(void video_setup(char *options, int *ints)) if (!options || !*options) return; + if (!strncmp(options, "scrollback:", 11)) { + options += 11; + if (*options) { + fbcon_softback_size = simple_strtoul(options, &options, 0); + if (*options == 'k' || *options == 'K') { + fbcon_softback_size *= 1024; + options++; + } + if (*options != ',') + return; + options++; + } else + return; + } + if (!strncmp(options, "map:", 4)) { options += 4; if (*options) @@ -658,7 +693,7 @@ __initfunc(void video_setup(char *options, int *ints)) } return; } - + if (!strncmp(options, "vc:", 3)) { options += 3; if (*options) diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c new file mode 100644 index 000000000..e5ab75e08 --- /dev/null +++ b/drivers/video/fm2fb.c @@ -0,0 +1,572 @@ +/* + * linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer + * device + * + * Copyright (C) 1998 Steffen A. Mork (mork@ls7.cs.uni-dortmund.de) + * Copyright (C) 1999 Geert Uytterhoeven + * + * Written for 2.0.x by Steffen A. Mork + * Ported to 2.1.x by 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/module.h> +#include <linux/mm.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/zorro.h> + +#include <asm/io.h> + +#include <video/fbcon.h> +#include <video/fbcon-cfb32.h> + + +/* + * Some technical notes: + * + * The BSC FrameMaster II (or Rainbow II) is a simple very dumb + * frame buffer which allows to display 24 bit true color images. + * Each pixel is 32 bit width so it's very easy to maintain the + * frame buffer. One long word has the following layout: + * AARRGGBB which means: AA the alpha channel byte, RR the red + * channel, GG the green channel and BB the blue channel. + * + * The FrameMaster II supports the following video modes. + * - PAL/NTSC + * - interlaced/non interlaced + * - composite sync/sync/sync over green + * + * The resolution is to the following both ones: + * - 768x576 (PAL) + * - 768x480 (NTSC) + * + * This means that pixel access per line is fixed due to the + * fixed line width. In case of maximal resolution the frame + * buffer needs an amount of memory of 1.769.472 bytes which + * is near to 2 MByte (the allocated address space of Zorro2). + * The memory is channel interleaved. That means every channel + * owns four VRAMs. Unfortunatly most FrameMasters II are + * not assembled with memory for the alpha channel. In this + * case it could be possible to add the frame buffer into the + * normal memory pool. + * + * At relative address 0x1ffff8 of the frame buffers base address + * there exists a control register with the number of + * four control bits. They have the following meaning: + * bit value meaning + * + * 0 1 0=interlaced/1=non interlaced + * 1 2 0=video out disabled/1=video out enabled + * 2 4 0=normal mode as jumpered via JP8/1=complement mode + * 3 8 0=read onboard ROM/1 normal operation (required) + * + * As mentioned above there are several jumper. I think there + * is not very much information about the FrameMaster II in + * the world so I add these information for completeness. + * + * JP1 interlace selection (1-2 non interlaced/2-3 interlaced) + * JP2 wait state creation (leave as is!) + * JP3 wait state creation (leave as is!) + * JP4 modulate composite sync on green output (1-2 composite + * sync on green channel/2-3 normal composite sync) + * JP5 create test signal, shorting this jumper will create + * a white screen + * JP6 sync creation (1-2 composite sync/2-3 H-sync output) + * JP8 video mode (1-2 PAL/2-3 NTSC) + * + * With the following jumpering table you can connect the + * FrameMaster II to a normal TV via SCART connector: + * JP1: 2-3 + * JP4: 2-3 + * JP6: 2-3 + * JP8: 1-2 (means PAL for Europe) + * + * NOTE: + * There is no other possibility to change the video timings + * except the interlaced/non interlaced, sync control and the + * video mode PAL (50 Hz)/NTSC (60 Hz). Inside this + * FrameMaster II driver are assumed values to avoid anomalies + * to a future X server. Except the pixel clock is really + * constant at 30 MHz. + * + * 9 pin female video connector: + * + * 1 analog red 0.7 Vss + * 2 analog green 0.7 Vss + * 3 analog blue 0.7 Vss + * 4 H-sync TTL + * 5 V-sync TTL + * 6 ground + * 7 ground + * 8 ground + * 9 ground + * + * Some performance notes: + * The FrameMaster II was not designed to display a console + * this driver would do! It was designed to display still true + * color images. Imagine: When scroll up a text line there + * must copied ca. 1.7 MBytes to another place inside this + * frame buffer. This means 1.7 MByte read and 1.7 MByte write + * over the slow 16 bit wide Zorro2 bus! A scroll of one + * line needs 1 second so do not expect to much from this + * driver - he is at the limit! + * + */ + + +/* + * definitions + */ + +#define FRAMEMASTER_SIZE 0x200000 +#define FRAMEMASTER_REG 0x1ffff8 + +#define FRAMEMASTER_NOLACE 1 +#define FRAMEMASTER_ENABLE 2 +#define FRAMEMASTER_COMPL 4 +#define FRAMEMASTER_ROM 8 + + +struct FrameMaster_fb_par +{ + int xres; + int yres; + int bpp; + int pixclock; +}; + +static unsigned long fm2fb_mem_phys; +static void *fm2fb_mem; +static unsigned long fm2fb_reg_phys; +static volatile unsigned char *fm2fb_reg; + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +static int currcon = 0; +static struct display disp; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[16]; +#ifdef FBCON_HAS_CFB32 +static u32 fbcon_cfb32_cmap[16]; +#endif + +static struct fb_fix_screeninfo fb_fix; +static struct fb_var_screeninfo fb_var; + +static int fm2fb_mode __initdata = -1; + +#define FM2FB_MODE_PAL 0 +#define FM2FB_MODE_NTSC 1 + +static struct fb_var_screeninfo fb_var_modes[] __initdata = { + { + /* 768 x 576, 32 bpp (PAL) */ + 768, 576, 768, 576, 0, 0, 32, 0, + { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 }, + 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE, + 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0 + }, { + /* 768 x 480, 32 bpp (NTSC - not supported yet */ + 768, 480, 768, 480, 0, 0, 32, 0, + { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 }, + 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE, + 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0 + } +}; + + + /* + * Interface used by the world + */ + +static int fm2fb_open(struct fb_info *info, int user); +static int fm2fb_release(struct fb_info *info, int user); +static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int fm2fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int fm2fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int fm2fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int fm2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int fm2fb_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 + */ + +void 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); + + + /* + * Internal routines + */ + +static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static void do_install_cmap(int con, struct fb_info *info); + + +static struct fb_ops fm2fb_ops = { + fm2fb_open, fm2fb_release, fm2fb_get_fix, fm2fb_get_var, fm2fb_set_var, + fm2fb_get_cmap, fm2fb_set_cmap, fm2fb_pan_display, fm2fb_ioctl +}; + + + /* + * Open/Release the frame buffer device + */ + +static int fm2fb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int fm2fb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + + + /* + * Get the Fixed Part of the Display + */ + +static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + memcpy(fix, &fb_fix, sizeof(fb_fix)); + return 0; +} + + + /* + * Get the User Defined Part of the Display + */ + +static int fm2fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + memcpy(var, &fb_var, sizeof(fb_var)); + return 0; +} + + + /* + * Set the User Defined Part of the Display + */ + +static int fm2fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct display *display; + int oldbpp = -1, err; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + if (var->xres > fb_var.xres || var->yres > fb_var.yres || + var->xres_virtual > fb_var.xres_virtual || + var->yres_virtual > fb_var.yres_virtual || + var->bits_per_pixel > fb_var.bits_per_pixel || + var->nonstd || + (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; + memcpy(var, &fb_var, sizeof(fb_var)); + + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldbpp = display->var.bits_per_pixel; + display->var = *var; + } + if (oldbpp != var->bits_per_pixel) { + if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) + return err; + do_install_cmap(con, info); + } + return 0; +} + + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int fm2fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset) + return -EINVAL; + else + return 0; +} + + /* + * Get the Colormap + */ + +static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, kspc, fm2fb_getcolreg, info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2); + return 0; +} + + /* + * Set the Colormap + */ + +static int fm2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0))) + return err; + } + if (con == currcon) { /* current console? */ + err = fb_set_cmap(cmap, kspc, fm2fb_setcolreg, info); + return err; + } else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + + +static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + + /* + * Initialisation + */ + +__initfunc(void fm2fb_init(void)) +{ + int key, is_fm; + const struct ConfigDev *cd = NULL; + unsigned long board, *ptr; + int x, y; + + if (!(key = is_fm = zorro_find(ZORRO_PROD_BSC_FRAMEMASTER_II, 0, 0)) && + !(key = zorro_find(ZORRO_PROD_HELFRICH_RAINBOW_II, 0, 0))) + return; + cd = zorro_get_board(key); + if (!(board = (u_long)cd->cd_BoardAddr)) + return; + zorro_config_board(key, 0); + + /* assigning memory to kernel space */ + fm2fb_mem_phys = board; + fm2fb_mem = ioremap(board, FRAMEMASTER_SIZE); + fm2fb_reg_phys = fm2fb_mem_phys+FRAMEMASTER_REG; + fm2fb_reg = (unsigned char *)(fm2fb_mem+FRAMEMASTER_REG); + + /* make EBU color bars on display */ + ptr = (unsigned long *)fm2fb_mem; + for (y = 0; y < 576; y++) { + for (x = 0; x < 96; x++) *ptr++ = 0xffffff; /* white */ + for (x = 0; x < 96; x++) *ptr++ = 0xffff00; /* yellow */ + for (x = 0; x < 96; x++) *ptr++ = 0x00ffff; /* cyan */ + for (x = 0; x < 96; x++) *ptr++ = 0x00ff00; /* green */ + for (x = 0; x < 96; x++) *ptr++ = 0xff00ff; /* magenta */ + for (x = 0; x < 96; x++) *ptr++ = 0xff0000; /* red */ + for (x = 0; x < 96; x++) *ptr++ = 0x0000ff; /* blue */ + for (x = 0; x < 96; x++) *ptr++ = 0x000000; /* black */ + } + fm2fbcon_blank(0, NULL); + + if (fm2fb_mode == -1) + fm2fb_mode = FM2FB_MODE_PAL; + + 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_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_len = 8; + fb_fix.accel = FB_ACCEL_NONE; + + disp.var = fb_var; + disp.cmap.start = 0; + disp.cmap.len = 0; + disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL; + disp.screen_base = (char *)fm2fb_mem; + disp.visual = fb_fix.visual; + disp.type = fb_fix.type; + disp.type_aux = fb_fix.type_aux; + disp.ypanstep = 0; + disp.ywrapstep = 0; + disp.line_length = fb_fix.line_length; + disp.can_soft_blank = 1; + disp.inverse = 0; +#ifdef FBCON_HAS_CFB32 + disp.dispsw = &fbcon_cfb32; + disp.dispsw_data = &fbcon_cfb32_cmap; +#else + disp.dispsw = &fbcon_dummy; +#endif + disp.scrollmode = SCROLL_YREDRAW; + + strcpy(fb_info.modename, fb_fix.id); + fb_info.node = -1; + fb_info.fbops = &fm2fb_ops; + fb_info.disp = &disp; + fb_info.fontname[0] = '\0'; + fb_info.changevar = NULL; + fb_info.switch_con = &fm2fbcon_switch; + fb_info.updatevar = &fm2fbcon_updatevar; + fb_info.blank = &fm2fbcon_blank; + fb_info.flags = FBINFO_FLAG_DEFAULT; + + fm2fb_set_var(&fb_var, -1, &fb_info); + + if (register_framebuffer(&fb_info) < 0) + return; + + printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), + fb_fix.id); +} + +__initfunc(void fm2fb_setup(char *options, int *ints)) +{ + char *this_opt; + + if (!options || !*options) + return; + + for (this_opt = strtok(options, ","); this_opt; + this_opt = strtok(NULL, ",")) { + if (!strncmp(this_opt, "pal", 3)) + fm2fb_mode = FM2FB_MODE_PAL; + else if (!strncmp(this_opt, "ntsc", 4)) + fm2fb_mode = FM2FB_MODE_NTSC; + } +} + + +static int fm2fbcon_switch(int con, struct fb_info *info) +{ + /* Do we have to save the colormap? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, 1, fm2fb_getcolreg, info); + + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + return 0; +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int fm2fbcon_updatevar(int con, struct fb_info *info) +{ + /* Nothing */ + return 0; +} + + /* + * Blank the display. + */ + +static void fm2fbcon_blank(int blank, struct fb_info *info) +{ + unsigned char t = FRAMEMASTER_ROM; + + if (!blank) + t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE; + fm2fb_reg[0] = t; +} + + /* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno > 15) + return 1; + *red = (palette[regno].red<<8) | palette[regno].red; + *green = (palette[regno].green<<8) | palette[regno].green; + *blue = (palette[regno].blue<<8) | palette[regno].blue; + *transp = 0; + return 0; +} + + + /* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 15) + return 1; + red >>= 8; + green >>= 8; + blue >>= 8; + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue; +#endif + return 0; +} + + +static void do_install_cmap(int con, struct fb_info *info) +{ + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, 1, fm2fb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(256), 1, fm2fb_setcolreg, info); +} diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index e3a86c868..d6173e77e 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -304,8 +304,6 @@ static int igafb_mmap(struct fb_info *info, struct file *file, if (!map_size) return -EINVAL; - vma->vm_file = file; - file->f_count++; vma->vm_flags |= VM_IO; if (!fb->mmaped) { diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c index 6bfd09fd8..0a273fe43 100644 --- a/drivers/video/leofb.c +++ b/drivers/video/leofb.c @@ -1,7 +1,7 @@ -/* $Id: leofb.c,v 1.4 1998/09/04 15:43:45 jj Exp $ +/* $Id: leofb.c,v 1.6 1999/04/01 13:03:25 jj Exp $ * leofb.c: Leo (ZX) 24/8bit frame buffer driver * - * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) */ @@ -80,12 +80,12 @@ struct leo_lc_ss0_krn { struct leo_lc_ss0_usr { volatile u32 csr; - volatile u32 attrs; - volatile u32 fontc; - volatile u32 fontc2; + volatile u32 addrspace; + volatile u32 fontmsk; + volatile u32 fontt; volatile u32 extent; volatile u32 src; - u32 xxx1[1]; + u32 dst; volatile u32 copy; volatile u32 fill; }; @@ -98,19 +98,42 @@ struct leo_lc_ss1_usr { u8 unknown; }; -struct leo_ld_ss0 { +struct leo_ld { u8 xxx0[0xe00]; - u32 xxx1[2]; - volatile u32 unk; - u32 xxx2[1]; - volatile u32 unk2; - volatile u32 unk3; - u32 xxx3[2]; + volatile u32 csr; + volatile u32 wid; + volatile u32 wmask; + volatile u32 widclip; + volatile u32 vclipmin; + volatile u32 vclipmax; + volatile u32 pickmin; /* SS1 only */ + volatile u32 pickmax; /* SS1 only */ volatile u32 fg; volatile u32 bg; - u8 xxx4[0x05c]; + volatile u32 src; /* Copy/Scroll (SS0 only) */ + volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ + volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ + u32 xxx1[3]; + volatile u32 setsem; /* SS1 only */ + volatile u32 clrsem; /* SS1 only */ + volatile u32 clrpick; /* SS1 only */ + volatile u32 clrdat; /* SS1 only */ + volatile u32 alpha; /* SS1 only */ + u8 xxx2[0x2c]; + volatile u32 winbg; volatile u32 planemask; volatile u32 rop; + volatile u32 z; + volatile u32 dczf; /* SS1 only */ + volatile u32 dczb; /* SS1 only */ + volatile u32 dcs; /* SS1 only */ + volatile u32 dczs; /* SS1 only */ + volatile u32 pickfb; /* SS1 only */ + volatile u32 pickbb; /* SS1 only */ + volatile u32 dcfc; /* SS1 only */ + volatile u32 forcecol; /* SS1 only */ + volatile u32 door[8]; /* SS1 only */ + volatile u32 pick[5]; /* SS1 only */ }; #define LEO_SS1_MISC_ENABLE 0x00000001 @@ -126,17 +149,17 @@ struct leo_ld_gbl { static struct sbus_mmap_map leo_mmap_map[] = { { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 }, - { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, PAGE_SIZE }, - { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, PAGE_SIZE }, - { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, PAGE_SIZE }, + { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 }, + { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 }, + { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 }, { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 }, - { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, PAGE_SIZE }, - { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, PAGE_SIZE }, - { LEO_UNK_MAP, LEO_OFF_UNK, PAGE_SIZE }, - { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, PAGE_SIZE }, - { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, PAGE_SIZE }, - { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, PAGE_SIZE }, - { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, PAGE_SIZE }, + { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 }, + { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 }, + { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 }, + { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 }, + { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 }, + { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 }, + { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 }, { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 }, { 0, 0, 0 } }; @@ -152,19 +175,14 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx, { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int x, y, w, h; int i; do { i = us->csr; } while (i & 0x20000000); - ss->unk = 0xffff; - ss->unk2 = 0; - ss->unk3 = fb->s.leo.extent; - ss->fg = (attr_bgcol_ec(p,conp)<<24) | 0x030703; - ss->planemask = 0xff000000; - ss->rop = 0xd0840; + ss->fg = (attr_bgcol_ec(p,conp)<<24); if (fontheightlog(p)) { y = sy << fontheightlog(p); h = height << fontheightlog(p); } else { @@ -176,9 +194,8 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx, x = sx * fontwidth(p); w = width * fontwidth(p); } us->extent = (w - 1) | ((h - 1) << 11); - i = us->attrs; us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) | - ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + 0x80000000; } static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, @@ -186,23 +203,17 @@ static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s, { int i; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; - do { - i = us->csr; - } while (i & 0x20000000); - ss->unk = 0xffff; - ss->unk2 = 0; - ss->unk3 = fb->s.leo.extent; - ss->fg = (attr_bgcol(p,s)<<24) | 0x030703; - ss->planemask = 0xff000000; - ss->rop = 0xd0840; + ss->fg = (attr_bgcol(p,s)<<24); while (count-- > 0) { + do { + i = us->csr; + } while (i & 0x20000000); us->extent = (boxes[2] - boxes[0] - 1) | ((boxes[3] - boxes[1] - 1) << 11); - i = us->attrs; - us->fill = boxes[0] | (boxes[1] << 11) | - ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000; + boxes += 4; } } @@ -210,7 +221,7 @@ static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int i, x, y; u8 *fd; u32 *u; @@ -235,11 +246,7 @@ static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int } while (i & 0x20000000); ss->fg = attr_fgcol(p,c) << 24; ss->bg = attr_bgcol(p,c) << 24; - ss->rop = 0x310040; - ss->planemask = 0xff000000; - us->fontc2 = 0xFFFFFFFE; - us->attrs = 4; - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { for (i = 0; i < fontheight(p); i++, u += 2048) @@ -257,7 +264,7 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; - register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0; + register struct leo_ld *ss = fb->s.leo.ld_ss0; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; u32 *u; @@ -265,13 +272,9 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh do { i = us->csr; } while (i & 0x20000000); - ss->fg = attr_fgcol(p,*s) << 24; - ss->bg = attr_bgcol(p,*s) << 24; - ss->rop = 0x310040; - ss->planemask = 0xff000000; - us->fontc2 = 0xFFFFFFFE; - us->attrs = 4; - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + ss->fg = attr_fgcol(p,scr_readw(s)) << 24; + ss->bg = attr_bgcol(p,scr_readw(s)) << 24; + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); if (fontwidthlog(p)) x = (xx << fontwidthlog(p)); else @@ -282,20 +285,20 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh y = (yy * fontheight(p)) << 11; u = ((u32 *)p->screen_base) + y + x; if (fontwidth(p) <= 8) { - us->fontc = 0xFFFFFFFF<<(32-4*fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-4*fontwidth(p)); x = 4*fontwidth(p) - fontheight(p)*2048; while (count >= 4) { count -= 4; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { - fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); - fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); + fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++, u += 2048) @@ -310,16 +313,16 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh } } } else { - us->fontc = 0xFFFFFFFF<<(32-2*fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-2*fontwidth(p)); x = 2*fontwidth(p) - fontheight(p)*2048; while (count >= 2) { count -= 2; if (fontheightlog(p)) { - fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); - fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1)); + fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); + fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { - fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); - fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1); + fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); + fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++, u += 2048) { *u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); @@ -328,14 +331,14 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh u += x; } } - us->fontc = 0xFFFFFFFF<<(32-fontwidth(p)); + us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p)); x = fontwidth(p) - fontheight(p)*2048; while (count) { count--; if (fontheightlog(p)) - i = ((*s++ & p->charmask) << fontheightlog(p)); + i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else - i = ((*s++ & p->charmask) * fontheight(p)); + i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++, u += 2048) @@ -457,8 +460,8 @@ static void leo_unblank (struct fb_info_sbusfb *fb) fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE; } -__initfunc(static int -leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)) +static int __init +leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl) { struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn; struct fb_wid_item *wi; @@ -476,6 +479,8 @@ leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)) lx_krn->krn_type = 0x5800 + j; lx_krn->krn_value = wi->wi_values[0]; } + lx_krn->krn_type = LEO_KRN_TYPE_WID; + lx_krn->krn_csr = 3; return 0; } @@ -484,9 +489,43 @@ static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); } +static void leo_switch_from_graph (struct fb_info_sbusfb *fb) +{ + register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; + register struct leo_ld *ss = fb->s.leo.ld_ss0; + + ss->wid = 0xffffffff; + ss->wmask = 0xffff; + ss->vclipmin = 0; + ss->vclipmax = fb->s.leo.extent; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + ss->widclip = 0; + us->addrspace = 4; + us->fontt = 0; +} + +static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start) +{ + register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr; + register struct leo_ld *ss = fb->s.leo.ld_ss0; + + if (start) { + ss->wid = 1; + ss->planemask = 0xffffff; + ss->rop = 0x310b90; + us->addrspace = 0; + } else { + ss->wid = 0xffffffff; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + us->addrspace = 4; + } +} + static char idstring[40] __initdata = { 0 }; -__initfunc(char *leofb_init(struct fb_info_sbusfb *fb)) +char * __init leofb_init(struct fb_info_sbusfb *fb) { struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; @@ -496,44 +535,53 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb)) struct fb_wid_item wi; struct fb_wid_list wl; int i; + register struct leo_lc_ss0_usr *us; + register struct leo_ld *ss; + struct fb_ops *fbops; strcpy(fb->info.modename, "Leo"); strcpy(fix->id, "Leo"); - fix->visual = 0xff; /* We only know how to do acceleration and know nothing - about the actual memory layout */ + fix->visual = FB_VISUAL_TRUECOLOR; fix->line_length = 8192; fix->accel = FB_ACCEL_SUN_LEO; + var->bits_per_pixel = 32; + var->green.offset = 8; + var->blue.offset = 16; var->accel_flags = FB_ACCELF_TEXT; + fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); + if (!fbops) return NULL; + + *fbops = *fb->info.fbops; + fbops->fb_rasterimg = leo_rasterimg; + fb->info.fbops = fbops; + disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0, 0x800000, "leo_ram", fb->iospace, 0); disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin; - fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) + us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *) sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, - PAGE_SIZE, "leo_lc_ss0_usr", fb->iospace, 0); - fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *) + 0x1000, "leo_lc_ss0_usr", fb->iospace, 0); + ss = fb->s.leo.ld_ss0 = (struct leo_ld *) sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, - PAGE_SIZE, "leo_ld_ss0", fb->iospace, 0); + 0x1000, "leo_ld_ss0", fb->iospace, 0); fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *) sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, - PAGE_SIZE, "leo_ld_ss1", fb->iospace, 0); + 0x1000, "leo_ld_ss1", fb->iospace, 0); fb->s.leo.lx_krn = (struct leo_lx_krn *) sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0, - PAGE_SIZE, "leo_lx_krn", fb->iospace, 0); + 0x1000, "leo_lx_krn", fb->iospace, 0); fb->s.leo.cursor = (struct leo_cursor *) sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0, sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0); fb->dispsw = leo_dispsw; - + fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16); - fb->s.leo.ld_ss0->unk = 0xffff; - fb->s.leo.ld_ss0->unk2 = 0; - fb->s.leo.ld_ss0->unk3 = fb->s.leo.extent; wl.wl_count = 1; wl.wl_list = &wi; wi.wi_type = FB_WID_DBL_8; @@ -546,17 +594,27 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb)) wi.wi_index = 2; wi.wi_values [0] = 0x20; leo_wid_put (fb, &wl); + wi.wi_type = FB_WID_DBL_24; + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put (fb, &wl); fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE; - fb->s.leo.ld_ss0->fg = 0x30703; - fb->s.leo.ld_ss0->planemask = 0xff000000; - fb->s.leo.ld_ss0->rop = 0xd0840; - fb->s.leo.lc_ss0_usr->extent = (type->fb_width-1) | ((type->fb_height-1) << 11); - i = fb->s.leo.lc_ss0_usr->attrs; - fb->s.leo.lc_ss0_usr->fill = (0) | ((0) << 11) | ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0); + ss->wid = 0xffffffff; + ss->wmask = 0xffff; + ss->vclipmin = 0; + ss->vclipmax = fb->s.leo.extent; + ss->fg = 0; + ss->planemask = 0xff000000; + ss->rop = 0x310850; + ss->widclip = 0; + us->extent = (type->fb_width-1) | ((type->fb_height-1) << 11); + us->addrspace = 4; + us->fill = 0x80000000; + us->fontt = 0; do { - i = fb->s.leo.lc_ss0_usr->csr; + i = us->csr; } while (i & 0x20000000); fb->margins = leo_margins; @@ -565,6 +623,7 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb)) fb->setcursormap = leo_setcursormap; fb->setcurshape = leo_setcurshape; fb->restore_palette = leo_restore_palette; + fb->switch_from_graph = leo_switch_from_graph; fb->fill = leo_fill; fb->blank = leo_blank; fb->unblank = leo_unblank; diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c index 5cfb98f52..eb6126965 100644 --- a/drivers/video/matroxfb.c +++ b/drivers/video/matroxfb.c @@ -4,7 +4,7 @@ * * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.9 1999/01/04 + * Version: 1.15 1999/04/19 * * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net> * @@ -24,6 +24,9 @@ * "Daniel Haun" <haund@usa.net> * Testing, hardware cursor fixes * + * "Scott Wood" <sawst46+@pitt.edu> + * Fixes + * * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> * Betatesting * @@ -54,6 +57,9 @@ * "H. Peter Arvin" <hpa@transmeta.com> * Ideas * + * "Cort Dougan" <cort@cs.nmt.edu> + * CHRP fixes and PReP cleanup + * * (following author is not in any relation with this code, but his code * is included in this driver) * @@ -184,14 +190,8 @@ #if defined(__m68k__) #define MAP_BUSTOVIRT #else -#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE) -/* do not tell me that PPC is not broken... if ioremap() oops with - invalid value written to msr... */ -#define MAP_ISAMEMBASE -#else #define MAP_IOREMAP #endif -#endif #ifdef DEBUG #define dprintk(X...) printk(X) @@ -351,13 +351,9 @@ static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, #ifdef MAP_BUSTOVIRT virt->vaddr = bus_to_virt(phys); #else -#ifdef MAP_ISAMEMBASE - virt->vaddr = (void*)(phys + _ISA_MEM_BASE); -#else #error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up" #endif #endif -#endif return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */ } @@ -452,7 +448,7 @@ struct matrox_accel_data { #define CPMINFO const struct matrox_fb_info* minfo, #define PMINFO minfo, -static inline struct matrox_fb_info* mxinfo(struct display* p) { +static inline struct matrox_fb_info* mxinfo(const struct display* p) { return (struct matrox_fb_info*)p->fb_info; } @@ -474,7 +470,7 @@ struct display global_disp; #define PMINFO #if 0 -static inline struct matrox_fb_info* mxinfo(struct display* p) { +static inline struct matrox_fb_info* mxinfo(const struct display* p) { return &global_mxinfo; } #endif @@ -1473,7 +1469,7 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* mga_outl(M_FCOL, fgx); mga_outl(M_BCOL, bgx); while (count--) { - u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (*s++ & p->charmask)*charcell; + u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (scr_readw(s++) & p->charmask)*charcell; mga_fifo(4); mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx); @@ -1531,7 +1527,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx; mmio = ACCESS_FBINFO(mmio.vbase); while (count--) { - u_int8_t* chardata = p->fontdata + (*s++ & p->charmask)*charcell; + u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell; mga_fifo(5); mga_writel(mmio, M_FXBNDRY, fxbndry); @@ -1586,8 +1582,8 @@ static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const uns DBG_HEAVY("matroxfb_cfb8_putcs"); - fgx = attr_fgcol(p, *s); - bgx = attr_bgcol(p, *s); + fgx = attr_fgcol(p, scr_readw(s)); + bgx = attr_bgcol(p, scr_readw(s)); fgx |= (fgx << 8); fgx |= (fgx << 16); bgx |= (bgx << 8); @@ -1603,8 +1599,8 @@ static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const un DBG_HEAVY("matroxfb_cfb16_putcs"); - fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, *s)]; - bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, *s)]; + fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))]; + bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))]; fgx |= (fgx << 16); bgx |= (bgx << 16); ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx); @@ -1618,8 +1614,8 @@ static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const un DBG_HEAVY("matroxfb_cfb32_putcs"); - fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, *s)]; - bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, *s)]; + fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))]; + bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))]; ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx); } #endif @@ -2191,9 +2187,9 @@ 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,*s) | (attr_bgcol(p,*s) << 4); + attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4); while (count-- > 0) { - unsigned int chr = ((*s++) & p->charmask) << 8; + 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; @@ -2395,6 +2391,10 @@ static void initMatrox(WPMINFO struct display* p) { DBG("initMatrox") + if (ACCESS_FBINFO(currcon_display) != p) + return; + if (p->dispsw && p->conp) + fb_con.con_cursor(p->conp, CM_ERASE); p->dispsw_data = NULL; if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) { if (p->type == FB_TYPE_TEXT) { @@ -4274,6 +4274,17 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ for (i = 0; i < 21; i++) { outTi3026(PMINFO DACseq[i], hw->DACreg[i]); } + if (oldhw) { + outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); + oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); + oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); + oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + } 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... */ @@ -5296,7 +5307,7 @@ static struct board { "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, 0, 0, - DEVF_VIDEO64BIT | DEVF_SWAPS, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, 230000, &vbG200, "unknown G200 (AGP)"}, @@ -5743,20 +5754,26 @@ leave:; } #ifndef MODULE +static int __init initialized = 0; + __initfunc(void matroxfb_init(void)) { DBG("matroxfb_init") -#if defined(CONFIG_FB_OF) -/* Nothing to do, must be called from offb */ -#else - matrox_init(); -#endif + + if (!initialized) { + initialized = 1; + matrox_init(); + } } #if defined(CONFIG_FB_OF) __initfunc(int matrox_of_init(struct device_node *dp)) { DBG("matrox_of_init"); - matrox_init(); + + if (!initialized) { + initialized = 1; + matrox_init(); + } if (!fb_list) return -ENXIO; return 0; } diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c index 177493d68..90dc85685 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/mdacon.c @@ -429,7 +429,7 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s, u16 *dest = MDA_ADDR(x, y); for (; count > 0; count--) { - scr_writew(mda_convert_attr(*s++), dest++); + scr_writew(mda_convert_attr(scr_readw(s++)), dest++); } } diff --git a/drivers/video/offb.c b/drivers/video/offb.c index f74486863..a769e9454 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -476,6 +476,7 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp)) printk("no framebuffer address found for %s\n", dp->full_name); return; } + address = (u_long)dp->addrs[i].address; /* kludge for valkyrie */ @@ -484,6 +485,7 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp)) } offb_init_fb(dp->name, dp->full_name, width, height, depth, pitch, address); + } __initfunc(static void offb_init_fb(const char *name, const char *full_name, diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index c26958e7b..dfb0f8ae8 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -3,7 +3,9 @@ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. * -------------------------------------------------------------------------- - * $Id: pm2fb.c,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $ + * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $ + * -------------------------------------------------------------------------- + * TODO multiple boards support * -------------------------------------------------------------------------- * This file is subject to the terms and conditions of the GNU General Public * License. See the file README.legal in the main directory of this archive @@ -26,23 +28,27 @@ #include <linux/console.h> #include <linux/init.h> #include <linux/pci.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/uaccess.h> #include <video/fbcon.h> #include <video/fbcon-cfb8.h> #include <video/fbcon-cfb16.h> #include <video/fbcon-cfb24.h> #include <video/fbcon-cfb32.h> -#include <asm/io.h> -#include <asm/uaccess.h> #include "pm2fb.h" -#ifdef CONFIG_FB_PM2_CVPPC #include "cvisionppc.h" -#endif #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) #error "The endianness of the target host has not been defined." #endif -#undef PM2FB_MASTER_DEBUG +#if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI) +#undef CONFIG_FB_PM2_PCI +#warning "support for Permedia2 PCI boards with no generic PCI support!" +#endif + +#define PM2FB_MASTER_DEBUG #ifdef PM2FB_MASTER_DEBUG #define DPRINTK(a,b...) printk("pm2fb: %s: " a, __FUNCTION__ , ## b) #else @@ -52,12 +58,20 @@ #define PICOS2KHZ(a) (1000000000UL/(a)) #define KHZ2PICOS(a) (1000000000UL/(a)) -#ifdef CONFIG_APUS -#define MMAP(a,b) (unsigned char* )kernel_map((unsigned long )(a), \ - b, KERNELMAP_NOCACHE_SER, NULL) -#else -#define MMAP(a,b) ioremap(a, b) -#endif +/* + * The _DEFINITIVE_ memory mapping/unmapping functions. + * This is due to the fact that they're changing soooo often... + */ +#define MMAP(a,b) ioremap((unsigned long )(a), b) +#define UNMAP(a,b) iounmap(a) + +/* + * The _DEFINITIVE_ memory i/o barrier functions. + * This is due to the fact that they're changing soooo often... + */ +#define DEFW() wmb() +#define DEFR() rmb() +#define DEFRW() mb() #ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) @@ -67,35 +81,33 @@ #define MAX(a,b) ((a)>(b)?(a):(b)) #endif -#ifndef __powerpc__ -#define eieio() -#endif - struct pm2fb_par { - unsigned long pixclock; /* pixclock in KHz */ - unsigned long width; /* width of virtual screen */ - unsigned long height; /* height of virtual screen */ - unsigned long hsstart; /* horiz. sync start */ - unsigned long hsend; /* horiz. sync end */ - unsigned long hbend; /* horiz. blank end (also gate end) */ - unsigned long htotal; /* total width (w/ sync & blank) */ - unsigned long vsstart; /* vert. sync start */ - unsigned long vsend; /* vert. sync end */ - unsigned long vbend; /* vert. blank end */ - unsigned long vtotal; /* total height (w/ sync & blank) */ - unsigned long stride; /* screen stride */ - unsigned long base; /* screen base (xoffset+yoffset) */ - unsigned long depth; /* screen depth (8, 16, 24 or 32) */ - unsigned long video; /* video control (hsync,vsync) */ + u32 pixclock; /* pixclock in KHz */ + u32 width; /* width of virtual screen */ + u32 height; /* height of virtual screen */ + u32 hsstart; /* horiz. sync start */ + u32 hsend; /* horiz. sync end */ + u32 hbend; /* horiz. blank end (also gate end) */ + u32 htotal; /* total width (w/ sync & blank) */ + u32 vsstart; /* vert. sync start */ + u32 vsend; /* vert. sync end */ + u32 vbend; /* vert. blank end */ + u32 vtotal; /* total height (w/ sync & blank) */ + u32 stride; /* screen stride */ + u32 base; /* screen base (xoffset+yoffset) */ + u32 depth; /* screen depth (8, 16, 24 or 32) */ + u32 video; /* video control (hsync,vsync) */ }; -#define OPTF_OLD_MEM 0x00000001 -#define OPTF_YPAN 0x00000002 +#define OPTF_OLD_MEM (1L<<0) +#define OPTF_YPAN (1L<<1) +#define OPTF_VIRTUAL (1L<<2) static struct { char font[40]; - unsigned long flags; + u32 flags; struct pm2fb_par user_mode; -} pm2fb_options; +} pm2fb_options = + {"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}}; static const struct { char name[16]; @@ -164,6 +176,15 @@ static const struct { {"\0", }, }; +#ifdef CONFIG_FB_PM2_PCI +struct pm2pci_par { + u32 mem_config; + u32 mem_control; + u32 boot_address; + struct pci_dev* dev; +}; +#endif + static const char permedia2_name[16]="Permedia2"; static struct pm2fb_info { @@ -172,7 +193,7 @@ static struct pm2fb_info { board_table[] below) */ struct { unsigned char* fb_base; /* framebuffer memory base */ - unsigned long fb_size; /* framebuffer memory size */ + u32 fb_size; /* framebuffer memory size */ unsigned char* rg_base; /* register memory base */ unsigned char* p_fb; /* physical address of frame buffer */ unsigned char* v_fb; /* virtual address of frame buffer */ @@ -186,10 +207,13 @@ static struct pm2fb_info { #ifdef CONFIG_FB_PM2_CVPPC struct cvppc_par cvppc; /* CVisionPPC data */ #endif +#ifdef CONFIG_FB_PM2_PCI + struct pm2pci_par pci; /* Permedia2 PCI boards data */ +#endif } board_par; struct pm2fb_par current_par; /* displayed screen */ int current_par_valid; - unsigned long memclock; /* memclock (set by the per-board + u32 memclock; /* memclock (set by the per-board init routine) */ struct display disp; struct { @@ -216,6 +240,11 @@ static int cvppc_detect(struct pm2fb_info*); static void cvppc_init(struct pm2fb_info*); #endif +#ifdef CONFIG_FB_PM2_PCI +static int pm2pci_detect(struct pm2fb_info*); +static void pm2pci_init(struct pm2fb_info*); +#endif + /* * Table of the supported Permedia2 based boards. * Three hooks are defined for each board: @@ -236,6 +265,9 @@ static const struct { void (*cleanup)(struct pm2fb_info*); char name[32]; } board_table[] = { +#ifdef CONFIG_FB_PM2_PCI + { pm2pci_detect, pm2pci_init, NULL, "Permedia2 PCI board" }, +#endif #ifdef CONFIG_FB_PM2_CVPPC { cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" }, #endif @@ -247,8 +279,8 @@ static const struct { */ #define PACKPP(p0,p1,p2) (((p2)<<6)|((p1)<<3)|(p0)) static const struct { - unsigned short width; - unsigned short pp; + u16 width; + u16 pp; } pp_table[] = { { 32, PACKPP(1, 0, 0) }, { 64, PACKPP(1, 1, 0) }, { 96, PACKPP(1, 1, 1) }, { 128, PACKPP(2, 1, 1) }, @@ -286,14 +318,14 @@ static int pm2fb_setcolreg(unsigned regno, static int pm2fb_blank(int blank_mode, struct fb_info_gen* info); static int pm2fb_pan_display(const struct fb_var_screeninfo* var, struct fb_info_gen* info); -static void pm2fb_dispsw(const void* par, struct display* disp, +static void pm2fb_set_disp(const void* par, struct display* disp, struct fb_info_gen* info); static struct fbgen_hwswitch pm2fb_hwswitch={ pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var, pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par, pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display, - pm2fb_blank, pm2fb_dispsw + pm2fb_blank, pm2fb_set_disp }; static int pm2fb_open(struct fb_info* info, int user); @@ -309,61 +341,61 @@ static struct fb_ops pm2fb_ops={ * Begin of Permedia2 specific functions ***************************************************************************/ -inline static unsigned long RD32(unsigned char* base, long off) { +inline static u32 RD32(unsigned char* base, s32 off) { - return *((volatile unsigned long* )(base+off)); + return readl(base+off); } -inline static void WR32(unsigned char* base, long off, unsigned long v) { +inline static void WR32(unsigned char* base, s32 off, u32 v) { - *((volatile unsigned long* )(base+off))=v; + writel(v, base+off); } -inline static unsigned long pm2_RD(struct pm2fb_info* p, long off) { +inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) { return RD32(p->regions.v_regs, off); } -inline static void pm2_WR(struct pm2fb_info* p, long off, unsigned long v) { +inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) { WR32(p->regions.v_regs, off, v); } -inline static unsigned long pm2_RDAC_RD(struct pm2fb_info* p, long idx) { +inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) { pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); - eieio(); + DEFRW(); return pm2_RD(p, PM2R_RD_INDEXED_DATA); } -inline static void pm2_RDAC_WR(struct pm2fb_info* p, long idx, - unsigned long v) { +inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx, + u32 v) { pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx); - eieio(); + DEFW(); pm2_WR(p, PM2R_RD_INDEXED_DATA, v); } #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT #define WAIT_FIFO(p,a) #else -inline static void WAIT_FIFO(struct pm2fb_info* p, unsigned long a) { +inline static void WAIT_FIFO(struct pm2fb_info* p, u32 a) { while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a); - eieio(); + DEFRW(); } #endif -static unsigned long partprod(unsigned long xres) { +static u32 partprod(u32 xres) { int i; for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++); if (!pp_table[i].width) - DPRINTK("invalid width %lu\n", xres); + DPRINTK("invalid width %u\n", xres); return pp_table[i].pp; } -static unsigned long to3264(unsigned long timing, int bpp, int is64) { +static u32 to3264(u32 timing, int bpp, int is64) { switch (bpp) { case 8: @@ -383,7 +415,7 @@ static unsigned long to3264(unsigned long timing, int bpp, int is64) { return timing; } -static unsigned long from3264(unsigned long timing, int bpp, int is64) { +static u32 from3264(u32 timing, int bpp, int is64) { switch (bpp) { case 8: @@ -403,14 +435,14 @@ static unsigned long from3264(unsigned long timing, int bpp, int is64) { return timing; } -static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn, +static void mnp(u32 clk, unsigned char* mm, unsigned char* nn, unsigned char* pp) { unsigned char m; unsigned char n; unsigned char p; - unsigned long f; - long current; - long delta=100000; + u32 f; + s32 curr; + s32 delta=100000; *mm=*nn=*pp=0; for (n=2; n<15; n++) { @@ -418,9 +450,9 @@ static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn, f=PM2_REFERENCE_CLOCK*m/n; if (f>=150000 && f<=300000) { for (p=0; p<5; p++, f>>=1) { - current=clk>f?clk-f:f-clk; - if (current<delta) { - delta=current; + curr=clk>f?clk-f:f-clk; + if (curr<delta) { + delta=curr; *mm=m; *nn=n; *pp=p; @@ -435,62 +467,75 @@ static void wait_pm2(struct pm2fb_info* i) { WAIT_FIFO(i, 1); pm2_WR(i, PM2R_SYNC, 0); - eieio(); + DEFRW(); do { while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0); - eieio(); + DEFR(); } while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC)); } -static void set_memclock(struct pm2fb_info* info, unsigned long clk) { +static void set_memclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; mnp(clk, &m, &n, &p); WAIT_FIFO(info, 5); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6); - eieio(); + DEFW(); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n); - eieio(); + DEFW(); pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p); - eieio(); + DEFW(); pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS); - eieio(); + DEFR(); for (i=256; i && !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); } -static void set_pixclock(struct pm2fb_info* info, unsigned long clk) { +static void set_pixclock(struct pm2fb_info* info, u32 clk) { int i; unsigned char m, n, p; mnp(clk, &m, &n, &p); WAIT_FIFO(info, 5); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0); - eieio(); + DEFW(); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n); - eieio(); + DEFW(); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p); - eieio(); + DEFW(); pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS); - eieio(); + DEFR(); for (i=256; i && !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); } +static void clear_palette(struct pm2fb_info* p) { + int i=256; + + WAIT_FIFO(p, 1); + pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0); + DEFW(); + while (i--) { + WAIT_FIFO(p, 3); + pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); + pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); + pm2_WR(p, PM2R_RD_PALETTE_DATA, 0); + } +} + static void set_color(struct pm2fb_info* p, unsigned char regno, unsigned char r, unsigned char g, unsigned char b) { WAIT_FIFO(p, 4); - eieio(); pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno); - eieio(); + DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, r); - eieio(); + DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, g); - eieio(); + DEFW(); pm2_WR(p, PM2R_RD_PALETTE_DATA, b); } @@ -520,12 +565,13 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { } static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { - unsigned long clrmode=0; - unsigned long txtmap=0; - unsigned long xres; + u32 clrmode=0; + u32 txtmap=0; + u32 xres; xres=(p->width+31)&~31; set_aperture(i, p); + DEFRW(); WAIT_FIFO(i, 22); pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0: PM2F_COLOR_KEY_TEST_OFF); @@ -565,7 +611,7 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { pm2_WR(i, PM2R_VS_END, p->vsend); pm2_WR(i, PM2R_VB_END, p->vbend); pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride); - eieio(); + DEFW(); pm2_WR(i, PM2R_SCREEN_BASE, p->base); pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB| PM2F_RD_GUI_ACTIVE|clrmode); @@ -573,6 +619,63 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { set_pixclock(i, p->pixclock); }; +/* + * copy with packed pixels (8/16bpp only). + */ +static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc, + s32 x, s32 y, s32 w, s32 h) { + s32 scale=i->current_par.depth==8?2:1; + s32 offset; + + if (!w || !h) + return; + WAIT_FIFO(i, 7); + pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| + PM2F_CONFIG_FB_PACKED_DATA| + PM2F_CONFIG_FB_READ_SOURCE_ENABLE); + pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); + pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| + ((xsrc-x)&0xfff)); + offset=(x&0x3)-(xsrc&0x3); + pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale)); + pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale)); + pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w)); + DEFW(); + pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| + (x<xsrc?PM2F_INCREASE_X:0)| + (y<ysrc?PM2F_INCREASE_Y:0)); + wait_pm2(i); +} + +/* + * block operation. copy=0: rectangle fill, copy=1: rectangle copy. + */ +static void pm2fb_block_op(struct pm2fb_info* i, int copy, + s32 xsrc, s32 ysrc, + s32 x, s32 y, s32 w, s32 h, + u32 color) { + + if (!w || !h) + return; + WAIT_FIFO(i, 6); + pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| + PM2F_CONFIG_FB_READ_SOURCE_ENABLE); + pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); + if (copy) + pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| + ((xsrc-x)&0xfff)); + else + pm2_WR(i, PM2R_FB_BLOCK_COLOR, color); + pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x); + pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w); + DEFW(); + pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| + (x<xsrc?PM2F_INCREASE_X:0)| + (y<ysrc?PM2F_INCREASE_Y:0)| + (copy?0:PM2F_RENDER_FASTFILL)); + wait_pm2(i); +} + /*************************************************************************** * Begin of generic initialization functions ***************************************************************************/ @@ -580,14 +683,14 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { static void pm2fb_reset(struct pm2fb_info* p) { pm2_WR(p, PM2R_RESET_STATUS, 0); - eieio(); + DEFRW(); while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET); - eieio(); + DEFRW(); #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT DPRINTK("FIFO disconnect enabled\n"); pm2_WR(p, PM2R_FIFO_DISCON, 1); + DEFRW(); #endif - eieio(); if (board_table[p->board].init) board_table[p->board].init(p); WAIT_FIFO(p, 48); @@ -633,8 +736,9 @@ static void pm2fb_reset(struct pm2fb_info* p) { pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0); - eieio(); - set_memclock(p, p->memclock); + clear_palette(p); + if (p->memclock) + set_memclock(p, p->memclock); } __initfunc(static int pm2fb_conf(struct pm2fb_info* p)) { @@ -661,9 +765,12 @@ __initfunc(static int pm2fb_conf(struct pm2fb_info* p)) { * Begin of per-board initialization functions ***************************************************************************/ +/* + * Phase5 CvisionPPC/BVisionPPC + */ #ifdef CONFIG_FB_PM2_CVPPC static int cvppc_PCI_init(struct cvppc_par* p) { - extern unsigned long powerup_PCI_present; + extern u32 powerup_PCI_present; if (!powerup_PCI_present) { DPRINTK("no PCI bridge detected\n"); @@ -683,14 +790,14 @@ static int cvppc_PCI_init(struct cvppc_par* p) { return 0; } WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN); - eieio(); + DEFW(); if (pm2fb_options.flags & OPTF_OLD_MEM) WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00); WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION); WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE); WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO); WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS); - eieio(); + DEFW(); WR32(p->pci_config, PCI_COMMAND, 0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | @@ -714,7 +821,7 @@ static void cvppc_init(struct pm2fb_info* p) { WAIT_FIFO(p, 3); pm2_WR(p, PM2R_MEM_CONTROL, 0); pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30); - eieio(); + DEFW(); if (pm2fb_options.flags & OPTF_OLD_MEM) pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD); else @@ -722,70 +829,100 @@ static void cvppc_init(struct pm2fb_info* p) { } #endif /* CONFIG_FB_PM2_CVPPC */ -/*************************************************************************** - * Console hw acceleration - ***************************************************************************/ - /* - * copy with packed pixels (8/16bpp only). + * Generic PCI detection routines */ -static void pm2fb_pp_copy(struct pm2fb_info* i, long xsrc, long ysrc, - long x, long y, long w, long h) { - long scale=i->current_par.depth==8?2:1; - long offset; - - if (!w || !h) - return; - WAIT_FIFO(i, 7); - pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| - PM2F_CONFIG_FB_PACKED_DATA| - PM2F_CONFIG_FB_READ_SOURCE_ENABLE); - pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); - pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| - ((xsrc-x)&0xfff)); - offset=(x&0x3)-(xsrc&0x3); - pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale)); - pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale)); - pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w)); - eieio(); - pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| - (x<xsrc?PM2F_INCREASE_X:0)| - (y<ysrc?PM2F_INCREASE_Y:0)); - wait_pm2(i); +#ifdef CONFIG_FB_PM2_PCI +static int pm2pci_detect(struct pm2fb_info* p) { + struct pm2pci_par* pci=&p->board_par.pci; + unsigned char* m; + + memset(pci, 0, sizeof(struct pm2pci_par)); + if (!pci_present()) { + DPRINTK("no PCI bus found.\n"); + return 0; + } + DPRINTK("scanning PCI bus for known chipsets...\n"); + if ((pci->dev=pci_find_device(PCI_VENDOR_ID_TI, + PCI_DEVICE_ID_TI_TVP4020, NULL))) { + DPRINTK("... found Texas Instruments TVP4020\n"); + } + if (!pci->dev) { + DPRINTK("no PCI board found.\n"); + 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); +#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); +#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); + } + 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); + } +#endif +#ifdef __BIG_ENDIAN + p->regions.rg_base += PM2_REGS_SIZE; +#endif + if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) { + pci->mem_control=RD32(m, PM2R_MEM_CONTROL); + pci->boot_address=RD32(m, PM2R_BOOT_ADDRESS); + pci->mem_config=RD32(m, PM2R_MEM_CONFIG); + switch (pci->mem_config & PM2F_MEM_CONFIG_RAM_MASK) { + case PM2F_MEM_BANKS_1: + p->regions.fb_size=0x200000; + break; + case PM2F_MEM_BANKS_2: + p->regions.fb_size=0x400000; + break; + case PM2F_MEM_BANKS_3: + p->regions.fb_size=0x600000; + break; + case PM2F_MEM_BANKS_4: + p->regions.fb_size=0x800000; + break; + } + p->memclock=CVPPC_MEMCLOCK; + UNMAP(m, PM2_REGS_SIZE); + return 1; + } + DPRINTK("MMAP() failed.\n"); + return 0; } -/* - * block operation. copy=0: rectangle fill, copy=1: rectangle copy. - */ -static void pm2fb_block_op(struct pm2fb_info* i, int copy, - long xsrc, long ysrc, - long x, long y, long w, long h, - unsigned long color) { +static void pm2pci_init(struct pm2fb_info* p) { + struct pm2pci_par* pci=&p->board_par.pci; - if (!w || !h) - return; - WAIT_FIFO(i, 6); - pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| - PM2F_CONFIG_FB_READ_SOURCE_ENABLE); - pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0); - if (copy) - pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| - ((xsrc-x)&0xfff)); - else - pm2_WR(i, PM2R_FB_BLOCK_COLOR, color); - pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x); - pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w); - eieio(); - pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE| - (x<xsrc?PM2F_INCREASE_X:0)| - (y<ysrc?PM2F_INCREASE_Y:0)| - (copy?0:PM2F_RENDER_FASTFILL)); - wait_pm2(i); + WAIT_FIFO(p, 3); + pm2_WR(p, PM2R_MEM_CONTROL, pci->mem_control); + pm2_WR(p, PM2R_BOOT_ADDRESS, pci->boot_address); + DEFW(); + pm2_WR(p, PM2R_MEM_CONFIG, pci->mem_config); } +#endif /* CONFIG_FB_PM2_PCI */ + +/*************************************************************************** + * Console hw acceleration + ***************************************************************************/ + static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; - unsigned long video; + u32 video; if (!i->current_par_valid) return 1; @@ -871,7 +1008,7 @@ static void pm2fb_bmove(struct display* p, int sy, int sx, #ifdef FBCON_HAS_CFB8 static void pm2fb_clear8(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) { - unsigned long c; + u32 c; sx=sx*fontwidth(p); width=width*fontwidth(p); @@ -886,9 +1023,9 @@ static void pm2fb_clear8(struct vc_data* conp, struct display* p, static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p, int bottom_only) { - unsigned long c; - unsigned long sx; - unsigned long sy; + u32 c; + u32 sx; + u32 sy; c=attr_bgcol_ec(p, conp); c|=c<<8; @@ -913,7 +1050,7 @@ static struct display_switch pm2_cfb8 = { #ifdef FBCON_HAS_CFB16 static void pm2fb_clear16(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) { - unsigned long c; + u32 c; sx=sx*fontwidth(p); width=width*fontwidth(p); @@ -927,9 +1064,9 @@ static void pm2fb_clear16(struct vc_data* conp, struct display* p, static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p, int bottom_only) { - unsigned long c; - unsigned long sx; - unsigned long sy; + u32 c; + u32 sx; + u32 sy; c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; c|=c<<16; @@ -957,7 +1094,7 @@ static struct display_switch pm2_cfb16 = { static void pm2fb_clear24(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) { struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info; - unsigned long c; + u32 c; c=attr_bgcol_ec(p, conp); if ( i->palette[c].red==i->palette[c].green && @@ -978,9 +1115,9 @@ static void pm2fb_clear24(struct vc_data* conp, struct display* p, static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p, int bottom_only) { struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info; - unsigned long c; - unsigned long sx; - unsigned long sy; + u32 c; + u32 sx; + u32 sy; c=attr_bgcol_ec(p, conp); if ( i->palette[c].red==i->palette[c].green && @@ -1011,7 +1148,7 @@ static struct display_switch pm2_cfb24 = { #ifdef FBCON_HAS_CFB32 static void pm2fb_clear32(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) { - unsigned long c; + u32 c; sx=sx*fontwidth(p); width=width*fontwidth(p); @@ -1024,9 +1161,9 @@ static void pm2fb_clear32(struct vc_data* conp, struct display* p, static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p, int bottom_only) { - unsigned long c; - unsigned long sx; - unsigned long sy; + u32 c; + u32 sx; + u32 sy; c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; sx=conp->vc_cols*fontwidth(p); @@ -1065,18 +1202,55 @@ static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix, fix->accel=FB_ACCEL_3DLABS_PERMEDIA2; fix->type=FB_TYPE_PACKED_PIXELS; fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR; - fix->line_length=0; + if (i->current_par_valid) + fix->line_length=i->current_par.width*(i->current_par.depth/8); + else + fix->line_length=0; fix->xpanstep=p->depth==24?8:64/p->depth; fix->ypanstep=1; fix->ywrapstep=0; return 0; } +#ifdef PM2FB_MASTER_DEBUG +static void pm2fb_display_var(const struct fb_var_screeninfo* var) { + + printk( KERN_DEBUG +"- struct fb_var_screeninfo ---------------------------------------------------\n"); + printk( KERN_DEBUG + "resolution: %ux%ux%u (virtual %ux%u+%u+%u)\n", + var->xres, var->yres, var->bits_per_pixel, + var->xres_virtual, var->yres_virtual, + var->xoffset, var->yoffset); + printk( KERN_DEBUG + "color: %c%c " + "R(%u,%u,%u), G(%u,%u,%u), B(%u,%u,%u), T(%u,%u,%u)\n", + var->grayscale?'G':'C', var->nonstd?'N':'S', + var->red.offset, var->red.length, var->red.msb_right, + var->green.offset, var->green.length, var->green.msb_right, + var->blue.offset, var->blue.length, var->blue.msb_right, + var->transp.offset, var->transp.length, + var->transp.msb_right); + printk( KERN_DEBUG + "timings: %ups (%u,%u)-(%u,%u)+%u+%u\n", + var->pixclock, + var->left_margin, var->upper_margin, var->right_margin, + var->lower_margin, var->hsync_len, var->vsync_len); + printk( KERN_DEBUG + "activate %08x accel_flags %08x sync %08x vmode %08x\n", + var->activate, var->accel_flags, var->sync, var->vmode); + printk( KERN_DEBUG +"------------------------------------------------------------------------------\n"); +} + +#define pm2fb_decode_var pm2fb_wrapped_decode_var +#endif + static int pm2fb_decode_var(const struct fb_var_screeninfo* var, void* par, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_par p; - unsigned long xres; + u32 xres; int data64; memset(&p, 0, sizeof(struct pm2fb_par)); @@ -1086,39 +1260,39 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, p.depth=p.depth>32?32:p.depth; data64=p.depth>8; xres=(var->xres+31)&~31; - if (p.width==~(0L)) - p.width=xres; - if (p.height==~(0L)) - p.height=var->yres; if (p.width<xres+var->xoffset) p.width=xres+var->xoffset; if (p.height<var->yres+var->yoffset) p.height=var->yres+var->yoffset; if (!partprod(xres)) { - DPRINTK("width not supported: %lu\n", xres); + DPRINTK("width not supported: %u\n", xres); return -EINVAL; } if (p.width>2047) { - DPRINTK("virtual width not supported: %lu\n", p.width); + DPRINTK("virtual width not supported: %u\n", p.width); return -EINVAL; } if (var->yres<200) { - DPRINTK("height not supported: %lu\n", - (unsigned long )var->yres); + DPRINTK("height not supported: %u\n", + (u32 )var->yres); return -EINVAL; } if (p.height<200 || p.height>2047) { - DPRINTK("virtual height not supported: %lu\n", p.height); + DPRINTK("virtual height not supported: %u\n", p.height); + return -EINVAL; + } + if (p.depth>32) { + DPRINTK("depth not supported: %u\n", p.depth); return -EINVAL; } if (p.width*p.height*p.depth/8>i->regions.fb_size) { - DPRINTK("no memory for screen (%lux%lux%lu)\n", - xres, p.height, p.depth); + DPRINTK("no memory for screen (%ux%ux%u)\n", + p.width, p.height, p.depth); return -EINVAL; } p.pixclock=PICOS2KHZ(var->pixclock); if (p.pixclock>PM2_MAX_PIXCLOCK) { - DPRINTK("pixclock too high (%luKHz)\n", p.pixclock); + DPRINTK("pixclock too high (%uKHz)\n", p.pixclock); return -EINVAL; } p.hsstart=to3264(var->right_margin, p.depth, data64); @@ -1153,11 +1327,24 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, return 0; } +#ifdef PM2FB_MASTER_DEBUG +#undef pm2fb_decode_var + +static int pm2fb_decode_var(const struct fb_var_screeninfo* var, + void* par, struct fb_info_gen* info) { + int result; + + result=pm2fb_wrapped_decode_var(var, par, info); + pm2fb_display_var(var); + return result; +} +#endif + static int pm2fb_encode_var(struct fb_var_screeninfo* var, const void* par, struct fb_info_gen* info) { struct pm2fb_par* p=(struct pm2fb_par* )par; struct fb_var_screeninfo v; - unsigned long base; + u32 base; memset(&v, 0, sizeof(struct fb_var_screeninfo)); v.xres_virtual=p->width; @@ -1266,9 +1453,9 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info) { return; } } + set_screen(i, p); i->current_par=*p; i->current_par_valid=1; - set_screen(i, &i->current_par); } static int pm2fb_getcolreg(unsigned regno, @@ -1322,7 +1509,7 @@ static int pm2fb_setcolreg(unsigned regno, break; #endif default: - DPRINTK("bad depth %lu\n", + DPRINTK("bad depth %u\n", i->current_par.depth); break; } @@ -1338,14 +1525,15 @@ static int pm2fb_setcolreg(unsigned regno, return regno>255; } -static void pm2fb_dispsw(const void* par, struct display* disp, +static void pm2fb_set_disp(const void* par, struct display* disp, struct fb_info_gen* info) { struct pm2fb_info* i=(struct pm2fb_info* )info; - unsigned long flags; - unsigned long depth; + u32 flags; + u32 depth; save_flags(flags); cli(); + disp->screen_base=i->regions.v_fb; switch (depth=((struct pm2fb_par* )par)->depth) { #ifdef FBCON_HAS_CFB8 case 8: @@ -1408,6 +1596,7 @@ __initfunc(void pm2fb_init(void)) { memset(&fb_info, 0, sizeof(fb_info)); if (!pm2fb_conf(&fb_info)) return; + pm2fb_reset(&fb_info); fb_info.disp.scrollmode=SCROLL_YNOMOVE; fb_info.gen.parsize=sizeof(struct pm2fb_par); fb_info.gen.fbhw=&pm2fb_hwswitch; @@ -1420,19 +1609,18 @@ __initfunc(void pm2fb_init(void)) { fb_info.gen.info.updatevar=&fbgen_update_var; fb_info.gen.info.blank=&fbgen_blank; fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info); - if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0) - return; + fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen); 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("fb%d: %s (%s), using %ldK of video memory.\n", + printk("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, - (unsigned long )(fb_info.regions.fb_size>>10)); + (u32 )(fb_info.regions.fb_size>>10)); MOD_INC_USE_COUNT; } @@ -1455,9 +1643,6 @@ __initfunc(void pm2fb_font_setup(char* options)) { __initfunc(void pm2fb_setup(char* options, int* ints)) { char* next; - memset(&pm2fb_options, 0, sizeof(pm2fb_options)); - memcpy(&pm2fb_options.user_mode, &user_mode[0].par, - sizeof(pm2fb_options.user_mode)); while (options) { if ((next=strchr(options, ','))) *(next++)='\0'; @@ -1469,6 +1654,8 @@ __initfunc(void pm2fb_setup(char* options, int* ints)) { pm2fb_options.flags |= OPTF_YPAN; else if (!strcmp(options, "oldmem")) pm2fb_options.flags |= OPTF_OLD_MEM; + else if (!strcmp(options, "virtual")) + pm2fb_options.flags |= OPTF_VIRTUAL; options=next; } } diff --git a/drivers/video/pm2fb.h b/drivers/video/pm2fb.h index 94f346427..f10ab7e93 100644 --- a/drivers/video/pm2fb.h +++ b/drivers/video/pm2fb.h @@ -2,7 +2,7 @@ * Permedia2 framebuffer driver definitions. * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * -------------------------------------------------------------------------- - * $Id: pm2fb.h,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $ + * $Id: pm2fb.h,v 1.21 1999/01/28 13:18:07 illo Exp $ * -------------------------------------------------------------------------- * This file is subject to the terms and conditions of the GNU General Public * License. See the file README.legal in the main directory of this archive @@ -16,7 +16,7 @@ #define PM2_MAX_PIXCLOCK 230000 /* in KHz */ #define PM2_REGS_SIZE 0x10000 -#define PM2TAG(r) (unsigned long )(((r)-0x8000)>>3) +#define PM2TAG(r) (u32 )(((r)-0x8000)>>3) /***************************************************************************** * Permedia2 registers used in the framebuffer @@ -128,16 +128,16 @@ #define PM2I_RD_BLUE_KEY 0x44 /* Fields and flags */ -#define PM2F_RENDER_AREASTIPPLE (1<<0) -#define PM2F_RENDER_FASTFILL (1<<3) -#define PM2F_RENDER_PRIMITIVE_MASK (0x3<<6) +#define PM2F_RENDER_AREASTIPPLE (1L<<0) +#define PM2F_RENDER_FASTFILL (1L<<3) +#define PM2F_RENDER_PRIMITIVE_MASK (3L<<6) #define PM2F_RENDER_LINE 0 -#define PM2F_RENDER_TRAPEZOID (1<<6) -#define PM2F_RENDER_POINT (2<<6) -#define PM2F_RENDER_RECTANGLE (3<<6) -#define PM2F_SYNCHRONIZATION (1<<10) +#define PM2F_RENDER_TRAPEZOID (1L<<6) +#define PM2F_RENDER_POINT (2L<<6) +#define PM2F_RENDER_RECTANGLE (3L<<6) +#define PM2F_SYNCHRONIZATION (1L<<10) #define PM2F_PLL_LOCKED 0x10 -#define PM2F_BEING_RESET (1<<31) +#define PM2F_BEING_RESET (1L<<31) #define PM2F_DATATYPE_COLOR 0x8000 #define PM2F_VGA_ENABLE 0x02 #define PM2F_VGA_FIXED 0x04 @@ -166,13 +166,18 @@ #define PM2F_TEXTEL_SIZE_32 0x00100000 #define PM2F_TEXTEL_SIZE_4 0x00180000 #define PM2F_TEXTEL_SIZE_24 0x00200000 -#define PM2F_INCREASE_X (1<<21) -#define PM2F_INCREASE_Y (1<<22) -#define PM2F_CONFIG_FB_WRITE_ENABLE (1<<3) -#define PM2F_CONFIG_FB_PACKED_DATA (1<<2) -#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1<<1) -#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1<<0) -#define PM2F_COLOR_KEY_TEST_OFF (1<<4) +#define PM2F_INCREASE_X (1L<<21) +#define PM2F_INCREASE_Y (1L<<22) +#define PM2F_CONFIG_FB_WRITE_ENABLE (1L<<3) +#define PM2F_CONFIG_FB_PACKED_DATA (1L<<2) +#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1L<<1) +#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1L<<0) +#define PM2F_COLOR_KEY_TEST_OFF (1L<<4) +#define PM2F_MEM_CONFIG_RAM_MASK (3L<<29) +#define PM2F_MEM_BANKS_1 0L +#define PM2F_MEM_BANKS_2 (1L<<29) +#define PM2F_MEM_BANKS_3 (2L<<29) +#define PM2F_MEM_BANKS_4 (3L<<29) #endif /* PM2FB_H */ diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c index 9148f609e..984edab98 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/promcon.c @@ -1,10 +1,11 @@ -/* $Id: promcon.c,v 1.12 1998/08/23 20:19:01 mj Exp $ +/* $Id: promcon.c,v 1.15 1999/04/22 06:35:32 davem Exp $ * Console driver utilizing PROM sun terminal emulation * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -230,7 +231,7 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s, int count, int y, int x) { unsigned char buf[256], *b = buf; - unsigned short attr = *s; + unsigned short attr = scr_readw(s); unsigned char save; int i, last = 0; @@ -256,9 +257,9 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s, } if (inverted(attr)) - b += sprintf(b, "\033[7m%c\033[m", *s++); + b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++)); else - b += sprintf(b, "%c", *s++); + b += sprintf(b, "%c", scr_readw(s++)); strcpy(b, "\b\033[@"); b += 4; @@ -295,14 +296,14 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s, promcon_puts(buf, b - buf); b = buf; } - *b++ = *s++; + *b++ = scr_readw(s++); } px += count; if (last) { - save = *s++; - b += sprintf(b, "%c\b\033[@%c", *s++, save); + save = scr_readw(s++); + b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save); px++; } @@ -318,11 +319,12 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s, static void promcon_putc(struct vc_data *conp, int c, int y, int x) { - unsigned short s = c; + unsigned short s; if (console_blanked) return; + scr_writew(c, &s); promcon_putcs(conp, &s, 1, y, x); } @@ -591,8 +593,11 @@ struct consw prom_con = { __initfunc(void prom_con_init(void)) { +#ifdef CONFIG_DUMMY_CONSOLE if (conswitchp == &dummy_con) take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1); - else if (conswitchp == &prom_con) + else +#endif + if (conswitchp == &prom_con) promcon_init_unimap(vc_cons[fg_console].d); } diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c new file mode 100644 index 000000000..8cacf5966 --- /dev/null +++ b/drivers/video/q40fb.c @@ -0,0 +1,362 @@ +#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/delay.h> +#include <linux/interrupt.h> +#include <asm/setup.h> +#include <asm/segment.h> +#include <asm/system.h> +/*#include <asm/irq.h>*/ +#include <asm/q40_master.h> +#include <linux/fb.h> +#include <linux/module.h> +#include <asm/pgtable.h> + +#include <video/fbcon-cfb16.h> + + +#define Q40_PHYS_SCREEN_ADDR 0xFE800000 +static unsigned long q40_screen_addr; + +static u16 fbcon_cmap_cfb16[16]; + +/* frame buffer operations */ + +static int q40fb_open(struct fb_info *info, int user); +static int q40fb_release(struct fb_info *info, int user); +static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int q40fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int q40fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int q40fb_get_cmap(struct fb_cmap *cmap,int kspc,int con, + struct fb_info *info); +static int q40fb_set_cmap(struct fb_cmap *cmap,int kspc,int con, + struct fb_info *info); +static int q40fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int q40fb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); + +static int q40con_switch(int con, struct fb_info *info); +static int q40con_updatevar(int con, struct fb_info *info); +static void q40con_blank(int blank, struct fb_info *info); + +static void q40fb_set_disp(int con, struct fb_info *info); + +static struct display disp[MAX_NR_CONSOLES]; +static struct fb_info fb_info; +static struct fb_ops q40fb_ops = { + q40fb_open,q40fb_release, q40fb_get_fix, q40fb_get_var, q40fb_set_var, + q40fb_get_cmap, q40fb_set_cmap, q40fb_pan_display, q40fb_ioctl +}; + +static int currcon=0; + +static char q40fb_name[]="Q40"; + +static int q40fb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int q40fb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + +static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + + strcpy(fix->id,"Q40"); + fix->smem_start=(char*)q40_screen_addr; + fix->smem_len=1024*1024; + fix->type=FB_TYPE_PACKED_PIXELS; + fix->type_aux=0; + fix->visual=FB_VISUAL_TRUECOLOR; /* good approximation so far ..*/; + fix->xpanstep=0; + fix->ypanstep=0; + fix->ywrapstep=0; + fix->line_length=1024*2; + + /* no mmio,accel ...*/ + + return 0; + +} + +static int q40fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + memset(var, 0, sizeof(struct fb_var_screeninfo)); + + var->xres=1024; + var->yres=512; + var->xres_virtual=1024; + var->yres_virtual=512; + var->xoffset=0; + var->yoffset=0; + var->bits_per_pixel=16; + var->grayscale=0; + var->nonstd=0; + var->activate=FB_ACTIVATE_NOW; + var->height=230; /* approx for my 17" monitor, more important */ + var->width=300; /* than the absolute values is the unusual aspect ratio*/ + + var->red.offset=6; /*6*/ + var->red.length=5; + var->green.offset=11; /*11*/ + var->green.length=5; + var->blue.offset=0; + var->blue.length=6; + var->transp.length=0; + + var->pixclock=0; + var->left_margin=0; + var->right_margin=0; + var->hsync_len=0; + var->vsync_len=0; + var->sync=0; + var->vmode=FB_VMODE_NONINTERLACED; + + return 0; + +} + +static int q40fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if(var->xres!=1024) + return -EINVAL; + if(var->yres!=512) + return -EINVAL; + if(var->xres_virtual!=1024) + return -EINVAL; + if(var->yres_virtual!=512) + return -EINVAL; + if(var->xoffset!=0) + return -EINVAL; + if(var->yoffset!=0) + return -EINVAL; + if(var->bits_per_pixel!=16) + return -EINVAL; + if(var->grayscale!=0) + return -EINVAL; + if(var->nonstd!=0) + return -EINVAL; + if(var->activate!=FB_ACTIVATE_NOW) + return -EINVAL; + if(var->pixclock!=0) + return -EINVAL; + if(var->left_margin!=0) + return -EINVAL; + if(var->right_margin!=0) + return -EINVAL; + if(var->hsync_len!=0) + return -EINVAL; + if(var->vsync_len!=0) + return -EINVAL; + if(var->sync!=0) + return -EINVAL; + if(var->vmode!=FB_VMODE_NONINTERLACED) + return -EINVAL; + + return 0; + +} + +static int q40_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info) +{ + /* + * Read a single color register and split it into colors/transparent. + * The return values must have a 16 bit magnitude. + * Return != 0 for invalid regno. + */ + if (regno>=16) return 1; + + *transp=0; + *green = ((fbcon_cmap_cfb16[regno]>>11) & 31)<<11; + *red = ((fbcon_cmap_cfb16[regno]>>6) & 31)<<11; + *blue = ((fbcon_cmap_cfb16[regno]) & 63)<<10; + + return 0; +} + +static int q40_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + const struct fb_info *info) +{ + /* + * Set a single color register. The values supplied have a 16 bit + * magnitude. + * Return != 0 for invalid regno. + */ + + red>>=11; + green>>=11; + blue>>=10; + + if (regno < 16) { + fbcon_cmap_cfb16[regno] = ((red & 31) <<5) | + ((green & 31) << 11) | + (blue & 63); + } + return 0; +} + +static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ +#if 1 + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, kspc, q40_getcolreg, info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return 0; +#else + printk("get cmap not supported\n"); + + return -EINVAL; +#endif +} + +static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ +#if 1 + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, + 0))) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, kspc, q40_setcolreg, info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +#else + printk("set cmap not supported\n"); + + return -EINVAL; +#endif +} + +static int q40fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + printk("panning not supported\n"); + + return -EINVAL; + +} + +static int q40fb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + return -EINVAL; +} + +static void q40fb_set_disp(int con, struct fb_info *info) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + q40fb_get_fix(&fix, con, info); + + if (con>=0) + display = &fb_display[con]; + else + display = &disp[0]; + + if (con<0) con=0; + + display->screen_base = fix.smem_start; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->can_soft_blank = 0; + display->inverse = 0; + display->line_length = fix.line_length; + +#ifdef FBCON_HAS_CFB16 + display->dispsw = &fbcon_cfb16; + disp->dispsw_data = fbcon_cmap_cfb16; +#else + display->dispsw = &fbcon_dummy; +#endif +} + +void q40fb_init(void) +{ +#if 0 + q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024, + KERNELMAP_NO_COPYBACK, NULL); +#else + q40_screen_addr = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */ +#endif + + fb_info.changevar=NULL; + strcpy(&fb_info.modename[0],q40fb_name); + fb_info.fontname[0]=0; + fb_info.disp=disp; + fb_info.switch_con=&q40con_switch; + fb_info.updatevar=&q40con_updatevar; + fb_info.blank=&q40con_blank; + fb_info.node = -1; + fb_info.fbops = &q40fb_ops; + fb_info.flags = FBINFO_FLAG_DEFAULT; /* not as module for now */ + + master_outb(3,DISPLAY_CONTROL_REG); + + 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"); + + + printk("fb%d: Q40 frame buffer alive and kicking !\n", + GET_FB_IDX(fb_info.node)); +} + + +static int q40con_switch(int con, struct fb_info *info) +{ + currcon=con; + + return 0; + +} + +static int q40con_updatevar(int con, struct fb_info *info) +{ + return 0; +} + +static void q40con_blank(int blank, struct fb_info *info) +{ +} diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index 995e86506..1ee42692f 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -101,8 +101,8 @@ struct display_data { struct retz3_fb_info { struct fb_info info; - unsigned long base; - unsigned long fbmem; + unsigned char *base; + unsigned char *fbmem; unsigned long fbsize; volatile unsigned char *regs; unsigned long physfbmem; @@ -1209,7 +1209,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info) if (con == -1) con = 0; - display->screen_base = (char *)zinfo->fbmem; + display->screen_base = zinfo->fbmem; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1282,7 +1282,7 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_fix_screeninfo fix; retz3fb_get_fix(&fix, con, info); - display->screen_base = (char *)zinfo->fbmem; + display->screen_base = zinfo->fbmem; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1456,7 +1456,7 @@ __initfunc(void retz3fb_init(void)) board_size = (unsigned long)cd->cd_BoardSize; zinfo->base = ioremap(board_addr, board_size); - zinfo->regs = (unsigned char *)(zinfo->base); + zinfo->regs = zinfo->base; zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET; /* Get memory size - for now we asume its a 4MB board */ zinfo->fbsize = 0x00400000; /* 4 MB */ diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index 88ecf5743..ce2c89eb7 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -229,7 +229,12 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file, for (i = 0; fb->mmap_map[i].size; i++) if (fb->mmap_map[i].voff == vma->vm_offset+page) { map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size); - map_offset = (fb->physbase + fb->mmap_map[i].poff) & PAGE_MASK; +#ifdef __sparc_v9__ +#define POFF_MASK (PAGE_MASK|0x1UL) +#else +#define POFF_MASK (PAGE_MASK) +#endif + map_offset = (fb->physbase + fb->mmap_map[i].poff) & POFF_MASK; break; } if (!map_size){ @@ -244,8 +249,6 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file, page += map_size; } - vma->vm_file = file; - file->f_count++; vma->vm_flags |= VM_IO; if (!fb->mmaped) { int lastconsole = 0; @@ -517,7 +520,7 @@ static void sbusfb_cursor(struct display *p, int mode, int x, int y) static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - if (con == currcon) /* current console? */ + if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); @@ -534,9 +537,14 @@ static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { int err; + struct display *disp; - if (!fb_display[con].cmap.len) { /* no colormap allocated? */ - if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0))) + if (con >= 0) + disp = &fb_display[con]; + else + disp = info->disp; + if (!disp->cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&disp->cmap, 1<<disp->var.bits_per_pixel, 0))) return err; } if (con == currcon) { /* current console? */ @@ -549,7 +557,7 @@ static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, } return err; } else - fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0; } diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c new file mode 100644 index 000000000..71aafc340 --- /dev/null +++ b/drivers/video/sgivwfb.c @@ -0,0 +1,1037 @@ +/* + * linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device + * + * Copyright (C) 1999 Silicon Graphics, Inc. + * Jeffrey Newquist, newquist@engr.sgi.som + * + * 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/config.h> +#include <linux/module.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 <asm/uaccess.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <asm/io.h> +#include <asm/mtrr.h> + +#include <video/fbcon.h> +#include <video/fbcon-cfb8.h> +#include <video/fbcon-cfb16.h> +#include <video/fbcon-cfb32.h> + +#define INCLUDE_TIMING_TABLE_DATA +#define DBE_REG_BASE regs +#include "sgivwfb.h" + +struct sgivwfb_par { + struct fb_var_screeninfo var; + u_long timing_num; + int valid; +}; + +/* + * RAM we reserve for the frame buffer. This defines the maximum screen + * size + * + * The default can be overridden if the driver is compiled as a module + */ + +/* set by arch/i386/kernel/setup.c */ +u_long sgivwfb_mem_phys; +u_long sgivwfb_mem_size; + +static volatile char *fbmem; +static asregs *regs; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[256]; +static char sgivwfb_name[16] = "SGI Vis WS FB"; +static u32 cmap_fifo; +static int ypan = 0; +static int ywrap = 0; + +/* console related variables */ +static int currcon = 0; +static struct display disp; + +static union { +#ifdef FBCON_HAS_CFB16 + u16 cfb16[16]; +#endif +#ifdef FBCON_HAS_CFB32 + u32 cfb32[16]; +#endif +} fbcon_cmap; + +static struct sgivwfb_par par_current = { + { /* var (screeninfo) */ + /* 640x480, 8 bpp */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2, + 0, FB_VMODE_NONINTERLACED + }, + 0, /* timing_num */ + 0 /* par not activated */ +}; + +/* + * Interface used by the world + */ +void sgivwfb_setup(char *options, int *ints); + +static int sgivwfb_open(struct fb_info *info, int user); +static int sgivwfb_release(struct fb_info *info, int user); +static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sgivwfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int sgivwfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); +static int sgivwfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); + +static struct fb_ops sgivwfb_ops = { + sgivwfb_open, + sgivwfb_release, + sgivwfb_get_fix, + sgivwfb_get_var, + sgivwfb_set_var, + sgivwfb_get_cmap, + sgivwfb_set_cmap, + sgivwfb_pan_display, + sgivwfb_ioctl, + sgivwfb_mmap +}; + +/* + * Interface to the low level console driver + */ +void 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); + +/* + * Internal routines + */ +static u_long get_line_length(int xres_virtual, int bpp); +static unsigned long bytes_per_pixel(int bpp); +static void activate_par(struct sgivwfb_par *par); +static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix, + struct fb_var_screeninfo *var); +static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static void do_install_cmap(int con, struct fb_info *info); + +static unsigned long get_line_length(int xres_virtual, int bpp) +{ + return(xres_virtual * bytes_per_pixel(bpp)); +} + +static unsigned long bytes_per_pixel(int bpp) +{ + unsigned long length; + + switch (bpp) { + case 8: + length = 1; + break; + case 16: + length = 2; + break; + case 32: + length = 4; + break; + default: + printk("sgivwfb: unsupported bpp=%d\n", bpp); + length = 0; + break; + } + return(length); +} + +/* + * Function: dbe_TurnOffDma + * Parameters: (None) + * Description: This should turn off the monitor and dbe. This is used + * when switching between the serial console and the graphics + * console. + */ + +static void dbe_TurnOffDma(void) +{ + int i; + unsigned int readVal; + + // Check to see if things are already turned off: + // 1) Check to see if dbe is not using the internal dotclock. + // 2) Check to see if the xy counter in dbe is already off. + + DBE_GETREG(ctrlstat, readVal); + if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2) + return; + + DBE_GETREG(vt_xy, readVal); + if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) + return; + + // Otherwise, turn off dbe + + DBE_GETREG(ovr_control, readVal); + SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0); + DBE_SETREG(ovr_control, readVal); + udelay(1000); + DBE_GETREG(frm_control, readVal); + SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0); + DBE_SETREG(frm_control, readVal); + udelay(1000); + DBE_GETREG(did_control, readVal); + SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0); + DBE_SETREG(did_control, readVal); + udelay(1000); + + // XXX HACK: + // + // This was necessary for GBE--we had to wait through two + // vertical retrace periods before the pixel DMA was + // turned off for sure. I've left this in for now, in + // case dbe needs it. + + for (i = 0; i < 10000; i++) + { + DBE_GETREG(frm_inhwctrl, readVal); + if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) == 0) + udelay(10); + else + { + DBE_GETREG(ovr_inhwctrl, readVal); + if (GET_DBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0) + udelay(10); + else + { + DBE_GETREG(did_inhwctrl, readVal); + if (GET_DBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, readVal) == 0) + udelay(10); + else + break; + } + } + } +} + +/* + * Set the hardware according to 'par'. + */ +static void activate_par(struct sgivwfb_par *par) +{ + int i,j, htmp, temp; + u32 readVal, outputVal; + int wholeTilesX, maxPixelsPerTileX; + int frmWrite1, frmWrite2, frmWrite3b; + dbe_timing_info_t *currentTiming; /* Current Video Timing */ + int xpmax, ypmax; // Monitor resolution + int bytesPerPixel; // Bytes per pixel + + currentTiming = &dbeVTimings[par->timing_num]; + bytesPerPixel = bytes_per_pixel(par->var.bits_per_pixel); + xpmax = currentTiming->width; + ypmax = currentTiming->height; + + /* dbe_InitGraphicsBase(); */ + /* Turn on dotclock PLL */ + DBE_SETREG(ctrlstat, 0x20000000); + + dbe_TurnOffDma(); + + /* dbe_CalculateScreenParams(); */ + maxPixelsPerTileX = 512/bytesPerPixel; + wholeTilesX = xpmax/maxPixelsPerTileX; + if (wholeTilesX*maxPixelsPerTileX < xpmax) + wholeTilesX++; + + printk("sgivwfb: pixPerTile=%d wholeTilesX=%d\n", + maxPixelsPerTileX, wholeTilesX); + + /* dbe_InitGammaMap(); */ + udelay(10); + + for (i = 0; i < 256; i++) + { + DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8)); + } + + /* dbe_TurnOn(); */ + DBE_GETREG(vt_xy, readVal); + if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1) + { + DBE_SETREG(vt_xy, 0x00000000); + udelay(1); + } + else + dbe_TurnOffDma(); + + /* dbe_Initdbe(); */ + for (i = 0; i < 256; i++) + { + for (j = 0; j < 100; j++) + { + DBE_GETREG(cm_fifo, readVal); + if (readVal != 0x00000000) + break; + else + udelay(10); + } + + // DBE_ISETREG(cmap, i, 0x00000000); + DBE_ISETREG(cmap, i, (i<<8)|(i<<16)|(i<<24)); + } + + /* dbe_InitFramebuffer(); */ + frmWrite1 = 0; + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1, wholeTilesX); + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0); + + switch(bytesPerPixel) + { + case 1: + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_8); + break; + case 2: + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_16); + break; + case 4: + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_32); + break; + } + + frmWrite2 = 0; + SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax); + + // Tell dbe about the framebuffer location and type + // XXX What format is the FRM_TILE_PTR?? 64K aligned address? + frmWrite3b = 0; + SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b, sgivwfb_mem_phys>>9); + SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1); + SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1); + + /* Initialize DIDs */ + + outputVal = 0; + switch(bytesPerPixel) + { + case 1: + SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8); + break; + case 2: + SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5); + break; + case 4: + SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8); + break; + } + SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH); + + for (i = 0; i < 32; i++) + { + DBE_ISETREG(mode_regs, i, outputVal); + } + + /* dbe_InitTiming(); */ + DBE_SETREG(vt_intr01, 0xffffffff); + DBE_SETREG(vt_intr23, 0xffffffff); + + DBE_GETREG(dotclock, readVal); + DBE_SETREG(dotclock, readVal & 0xffff); + + DBE_SETREG(vt_xymax, 0x00000000); + outputVal = 0; + SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal, currentTiming->vsync_start); + SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal, currentTiming->vsync_end); + DBE_SETREG(vt_vsync, outputVal); + outputVal = 0; + SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal, currentTiming->hsync_start); + SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal, currentTiming->hsync_end); + DBE_SETREG(vt_hsync, outputVal); + outputVal = 0; + SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal, currentTiming->vblank_start); + SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal, currentTiming->vblank_end); + DBE_SETREG(vt_vblank, outputVal); + outputVal = 0; + SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal, currentTiming->hblank_start); + SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal, currentTiming->hblank_end-3); + DBE_SETREG(vt_hblank, outputVal); + outputVal = 0; + SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal, currentTiming->vblank_start); + SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal, currentTiming->vblank_end); + DBE_SETREG(vt_vcmap, outputVal); + outputVal = 0; + SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal, currentTiming->hblank_start); + SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal, currentTiming->hblank_end-3); + DBE_SETREG(vt_hcmap, outputVal); + + outputVal = 0; + temp = currentTiming->vblank_start - currentTiming->vblank_end - 1; + if (temp > 0) + temp = -temp; + + SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32)temp); + if (currentTiming->hblank_end >= 20) + SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal, + currentTiming->hblank_end - 20); + else + SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal, + currentTiming->htotal - (20 - currentTiming->hblank_end)); + DBE_SETREG(did_start_xy, outputVal); + + outputVal = 0; + SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal, (u32)(temp+1)); + if (currentTiming->hblank_end >= DBE_CRS_MAGIC) + SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal, + currentTiming->hblank_end - DBE_CRS_MAGIC); + else + SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal, + currentTiming->htotal - (DBE_CRS_MAGIC - currentTiming->hblank_end)); + DBE_SETREG(crs_start_xy, outputVal); + + outputVal = 0; + SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32)temp); + SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal, + currentTiming->hblank_end - 4); + DBE_SETREG(vc_start_xy, outputVal); + + DBE_SETREG(frm_size_tile, frmWrite1); + DBE_SETREG(frm_size_pixel, frmWrite2); + + outputVal = 0; + SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m-1); + SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n-1); + SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p); + SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1); + DBE_SETREG(dotclock, outputVal); + + udelay(11*1000); + + DBE_SETREG(vt_vpixen, 0xffffff); + DBE_SETREG(vt_hpixen, 0xffffff); + + outputVal = 0; + SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal); + SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal); + DBE_SETREG(vt_xymax, outputVal); + + outputVal = frmWrite1; + SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1); + DBE_SETREG(frm_size_tile, outputVal); + DBE_SETREG(frm_size_tile, frmWrite1); + + outputVal = 0; + SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1); + DBE_SETREG(ovr_width_tile, outputVal); + DBE_SETREG(ovr_width_tile, 0); + + DBE_SETREG(frm_control, frmWrite3b); + DBE_SETREG(did_control, 0); + + // Wait for dbe to take frame settings + for (i=0; i<100000; i++) + { + DBE_GETREG(frm_inhwctrl, readVal); + if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) != 0) + break; + else + udelay(1); + } + + if (i==100000) + printk("sgivwfb: timeout waiting for frame DMA enable.\n"); + + outputVal = 0; + htmp = currentTiming->hblank_end - 19; + if (htmp < 0) + htmp += currentTiming->htotal; /* allow blank to wrap around */ + SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp); + SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal, + ((htmp + currentTiming->width - 2) % currentTiming->htotal)); + DBE_SETREG(vt_hpixen, outputVal); + + outputVal = 0; + SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal, + currentTiming->vblank_start); + SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal, + currentTiming->vblank_end); + DBE_SETREG(vt_vpixen, outputVal); + + // Turn off mouse cursor + regs->crs_ctl = 0; + + // XXX What's this section for?? + DBE_GETREG(ctrlstat, readVal); + readVal &= 0x02000000; + + if (readVal != 0) + { + DBE_SETREG(ctrlstat, 0x30000000); + } +} + +static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix, + struct fb_var_screeninfo *var) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, sgivwfb_name); + fix->smem_start = (char *) sgivwfb_mem_phys; + fix->smem_len = sgivwfb_mem_size; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + switch (var->bits_per_pixel) { + case 8: + fix->visual = FB_VISUAL_PSEUDOCOLOR; + break; + default: + fix->visual = FB_VISUAL_TRUECOLOR; + break; + } + fix->ywrapstep = ywrap; + 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_len = DBE_REG_SIZE; +} + +/* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ +static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno > 255) + return 1; + + *red = palette[regno].red << 8; + *green = palette[regno].green << 8; + *blue = palette[regno].blue << 8; + *transp = 0; + return 0; +} + +/* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 255) + return 1; + red >>= 8; + green >>= 8; + blue >>= 8; + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + + /* wait for the color map FIFO to have a free entry */ + while (cmap_fifo == 0) + cmap_fifo = regs->cm_fifo; + + regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8); + cmap_fifo--; /* assume FIFO is filling up */ + return 0; +} + +static void do_install_cmap(int con, struct fb_info *info) +{ + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, 1, sgivwfb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1, + sgivwfb_setcolreg, info); +} + +/* ---------------------------------------------------- */ + +/* + * Open/Release the frame buffer device + */ +static int sgivwfb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return(0); +} + +static int sgivwfb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + +/* + * Get the Fixed Part of the Display + */ +static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct fb_var_screeninfo *var; + + if (con == -1) + var = &par_current.var; + else + var = &fb_display[con].var; + sgivwfb_encode_fix(fix, var); + return 0; +} + +/* + * Get the User Defined Part of the Display. If a real par get it form there + */ +static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (con == -1) + *var = par_current.var; + else + *var = fb_display[con].var; + return 0; +} + +/* + * Set the User Defined Part of the Display. Again if par use it to get + * real video mode. + */ +static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err, activate = var->activate; + int oldxres, oldyres, oldvxres, oldvyres, oldbpp; + u_long line_length; + u_long min_mode; + int req_dot; + int test_mode; + + struct dbe_timing_info *timing; + + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + /* + * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal! + * as FB_VMODE_SMOOTH_XPAN is only used internally + */ + + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = display->var.xoffset; + var->yoffset = display->var.yoffset; + } + + /* XXX FIXME - forcing var's */ + var->xoffset = 0; + var->yoffset = 0; + + /* Limit bpp to 8, 16, and 32 */ + if (var->bits_per_pixel <= 8) + var->bits_per_pixel = 8; + else if (var->bits_per_pixel <= 16) + var->bits_per_pixel = 16; + else if (var->bits_per_pixel <= 32) + var->bits_per_pixel = 32; + else + return -EINVAL; + + var->grayscale = 0; /* No grayscale for now */ + + /* determine valid resolution and timing */ + for (min_mode=0; min_mode<DBE_VT_SIZE; min_mode++) { + if (dbeVTimings[min_mode].width >= var->xres && + dbeVTimings[min_mode].height >= var->yres) + break; + } + + if (min_mode == DBE_VT_SIZE) + return -EINVAL; /* Resolution to high */ + + /* 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, + req_dot); + test_mode=min_mode; + while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) { + if (dbeVTimings[test_mode].cfreq+3000 > req_dot) + break; + test_mode++; + } + if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width) + test_mode--; + min_mode = test_mode; + timing = &dbeVTimings[min_mode]; + printk("sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq); + + /* Adjust virtual resolution, if necessary */ + if (var->xres > var->xres_virtual || (!ywrap && !ypan)) + var->xres_virtual = var->xres; + if (var->yres > var->yres_virtual || (!ywrap && !ypan)) + var->yres_virtual = var->yres; + + /* + * Memory limit + */ + line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); + if (line_length*var->yres_virtual > sgivwfb_mem_size) + return -ENOMEM; /* Virtual resolution to high */ + + switch (var->bits_per_pixel) + { + case 8: + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 16: /* RGBA 5551 */ + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 6; + var->green.length = 5; + var->blue.offset = 1; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 32: /* RGB 8888 */ + 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 = 8; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + + /* set video timing information */ + var->pixclock = (__u32)(1.0e+9/(float)timing->cfreq); + var->left_margin = timing->htotal - timing->hsync_end; + var->right_margin = timing->hsync_start - timing->width; + var->upper_margin = timing->vtotal - timing->vsync_end; + var->lower_margin = timing->vsync_start - timing->height; + var->hsync_len = timing->hsync_end - timing->hsync_start; + var->vsync_len = timing->vsync_end - timing->vsync_start; + + if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldxres = display->var.xres; + oldyres = display->var.yres; + oldvxres = display->var.xres_virtual; + oldvyres = display->var.yres_virtual; + oldbpp = display->var.bits_per_pixel; + display->var = *var; + par_current.var = *var; + par_current.timing_num = min_mode; + if (oldxres != var->xres || oldyres != var->yres || + 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", + var->xres, var->yres, var->bits_per_pixel); + printk(" vxres=%d vyres=%d\n", + var->xres_virtual, var->yres_virtual); + activate_par(&par_current); + sgivwfb_encode_fix(&fix, var); + display->screen_base = (char *)fbmem; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + display->can_soft_blank = 1; + display->inverse = 0; + if (oldbpp != var->bits_per_pixel || !par_current.valid) { + if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) + return err; + do_install_cmap(con, info); + } + switch (var->bits_per_pixel) { +#ifdef FBCON_HAS_CFB8 + case 8: + display->dispsw = &fbcon_cfb8; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + display->dispsw_data = fbcon_cmap.cfb16; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + display->dispsw = &fbcon_cfb32; + display->dispsw_data = fbcon_cmap.cfb32; + break; +#endif + default: + display->dispsw = &fbcon_dummy; + break; + } + par_current.valid = 1; + if (fb_info.changevar) + (*fb_info.changevar)(con); + } + } + return 0; +} + +/* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int sgivwfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ +#if 0 + if (var->vmode & FB_VMODE_YWRAP) { + if (var->yoffset < 0 || + var->yoffset >= fb_display[con].var.yres_virtual || + var->xoffset) + return -EINVAL; + } else { + if (var->xoffset+fb_display[con].var.xres > + fb_display[con].var.xres_virtual || + var->yoffset+fb_display[con].var.yres > + fb_display[con].var.yres_virtual) + return -EINVAL; + } + fb_display[con].var.xoffset = var->xoffset; + fb_display[con].var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + fb_display[con].var.vmode |= FB_VMODE_YWRAP; + else + fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; + return 0; +#endif + return -EINVAL; +} + +/* + * Get the Colormap + */ +static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, kspc, sgivwfb_getcolreg, info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return 0; +} + +/* + * Set the Colormap + */ +static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, 0))) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, kspc, sgivwfb_setcolreg, info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + +/* + * Virtual Frame Buffer Specific ioctls + */ +static int sgivwfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + +static int sgivwfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma) +{ + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long offset = sgivwfb_mem_phys + vma->vm_offset; + if (vma->vm_offset+size > sgivwfb_mem_size) + return -EINVAL; + pgprot_val(vma->vm_page_prot) = pgprot_val(vma->vm_page_prot) | _PAGE_PCD; + vma->vm_flags |= VM_IO; + 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); + return 0; +} + +__initfunc(void sgivwfb_setup(char *options, int *ints)) +{ + char *this_opt; + + fb_info.fontname[0] = '\0'; + + if (!options || !*options) + return; + + for (this_opt = strtok(options, ","); this_opt; + this_opt = strtok(NULL, ",")) { + if (!strncmp(this_opt, "font:", 5)) + strcpy(fb_info.fontname, this_opt+5); + } +} + +/* + * Initialisation + */ +__initfunc(void sgivwfb_init(void)) +{ + printk("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"); + goto fail_ioremap_regs; + } + +#ifdef CONFIG_MTRR + mtrr_add((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1); +#endif + + strcpy(fb_info.modename, sgivwfb_name); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &sgivwfb_ops; + fb_info.disp = &disp; + fb_info.switch_con = &sgivwfbcon_switch; + fb_info.updatevar = &sgivwfbcon_updatevar; + fb_info.blank = &sgivwfbcon_blank; + fb_info.flags = FBINFO_FLAG_DEFAULT; + + fbmem = ioremap_nocache((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size); + if (!fbmem) { + printk("sgivwfb: couldn't ioremap fbmem\n"); + goto fail_ioremap_fbmem; + } + + /* turn on default video mode */ + sgivwfb_set_var(&par_current.var, -1, &fb_info); + + if (register_framebuffer(&fb_info) < 0) { + printk("sgivwfb: couldn't register framebuffer\n"); + goto fail_register_framebuffer; + } + + printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), sgivwfb_mem_size>>10); + + return; + + fail_register_framebuffer: + iounmap((char*)fbmem); + fail_ioremap_fbmem: + iounmap(regs); + fail_ioremap_regs: + return; +} + +static int sgivwfbcon_switch(int con, struct fb_info *info) +{ + /* Do we have to save the colormap? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, 1, sgivwfb_getcolreg, info); + + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + return 0; +} + +/* + * Update the `var' structure (called by fbcon.c) + */ +static int sgivwfbcon_updatevar(int con, struct fb_info *info) +{ + /* Nothing */ + return 0; +} + +/* + * Blank the display. + */ +static void sgivwfbcon_blank(int blank, struct fb_info *info) +{ + /* Nothing */ +} + +#ifdef MODULE +int init_module(void) +{ + sgivwfb_init(); + return 0; +} + +void cleanup_module(void) +{ + unregister_framebuffer(&fb_info); + dbe_TurnOffDma(); + iounmap(regs); + iounmap(fbmem); +} + +#endif /* MODULE */ diff --git a/drivers/video/sgivwfb.h b/drivers/video/sgivwfb.h new file mode 100644 index 000000000..8ff8a77f4 --- /dev/null +++ b/drivers/video/sgivwfb.h @@ -0,0 +1,660 @@ +/* + * linux/drivers/video/sgivwfb.h -- SGI DBE frame buffer device header + * + * Copyright (C) 1999 Silicon Graphics, Inc. + * Jeffrey Newquist, newquist@engr.sgi.som + * + * 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 __SGIVWFB_H__ +#define __SGIVWFB_H__ + +#define DBE_GETREG(reg, dest) ((dest) = DBE_REG_BASE->##reg) +#define DBE_SETREG(reg, src) DBE_REG_BASE->##reg = (src) +#define DBE_IGETREG(reg, idx, dest) ((dest) = DBE_REG_BASE->##reg##[idx]) +#define DBE_ISETREG(reg, idx, src) (DBE_REG_BASE->##reg##[idx] = (src)) + +#define MASK(msb, lsb) ( (((u32)1<<((msb)-(lsb)+1))-1) << (lsb) ) +#define GET(v, msb, lsb) ( ((u32)(v) & MASK(msb,lsb)) >> (lsb) ) +#define SET(v, f, msb, lsb) ( (v) = ((v)&~MASK(msb,lsb)) | (( (u32)(f)<<(lsb) ) & MASK(msb,lsb)) ) + +#define GET_DBE_FIELD(reg, field, v) GET((v), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB) +#define SET_DBE_FIELD(reg, field, v, f) SET((v), (f), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB) + +/* NOTE: All loads/stores must be 32 bits and uncached */ + +#define DBE_REG_PHYS 0xd0000000 +#define DBE_REG_SIZE 0x01000000 + +typedef struct { + volatile u32 ctrlstat; /* 0x000000 general control */ + volatile u32 dotclock; /* 0x000004 dot clock PLL control */ + volatile u32 i2c; /* 0x000008 crt I2C control */ + volatile u32 sysclk; /* 0x00000c system clock PLL control */ + volatile u32 i2cfp; /* 0x000010 flat panel I2C control */ + volatile u32 id; /* 0x000014 device id/chip revision */ + volatile u32 config; /* 0x000018 power on configuration */ + volatile u32 bist; /* 0x00001c internal bist status */ + + char _pad0[ 0x010000 - 0x000020 ]; + + volatile u32 vt_xy; /* 0x010000 current dot coords */ + volatile u32 vt_xymax; /* 0x010004 maximum dot coords */ + volatile u32 vt_vsync; /* 0x010008 vsync on/off */ + volatile u32 vt_hsync; /* 0x01000c hsync on/off */ + volatile u32 vt_vblank; /* 0x010010 vblank on/off */ + volatile u32 vt_hblank; /* 0x010014 hblank on/off */ + volatile u32 vt_flags; /* 0x010018 polarity of vt signals */ + volatile u32 vt_f2rf_lock; /* 0x01001c f2rf & framelck y coord */ + volatile u32 vt_intr01; /* 0x010020 intr 0,1 y coords */ + volatile u32 vt_intr23; /* 0x010024 intr 2,3 y coords */ + volatile u32 fp_hdrv; /* 0x010028 flat panel hdrv on/off */ + volatile u32 fp_vdrv; /* 0x01002c flat panel vdrv on/off */ + volatile u32 fp_de; /* 0x010030 flat panel de on/off */ + volatile u32 vt_hpixen; /* 0x010034 intrnl horiz pixel on/off*/ + volatile u32 vt_vpixen; /* 0x010038 intrnl vert pixel on/off */ + volatile u32 vt_hcmap; /* 0x01003c cmap write (horiz) */ + volatile u32 vt_vcmap; /* 0x010040 cmap write (vert) */ + volatile u32 did_start_xy; /* 0x010044 eol/f did/xy reset val */ + volatile u32 crs_start_xy; /* 0x010048 eol/f crs/xy reset val */ + volatile u32 vc_start_xy; /* 0x01004c eol/f vc/xy reset val */ + + char _pad1[ 0x020000 - 0x010050 ]; + + volatile u32 ovr_width_tile; /* 0x020000 overlay plane ctrl 0 */ + volatile u32 ovr_inhwctrl; /* 0x020004 overlay plane ctrl 1 */ + volatile u32 ovr_control; /* 0x020008 overlay plane ctrl 1 */ + + char _pad2[ 0x030000 - 0x02000C ]; + + volatile u32 frm_size_tile; /* 0x030000 normal plane ctrl 0 */ + volatile u32 frm_size_pixel; /* 0x030004 normal plane ctrl 1 */ + volatile u32 frm_inhwctrl; /* 0x030008 normal plane ctrl 2 */ + volatile u32 frm_control; /* 0x03000C normal plane ctrl 3 */ + + char _pad3[ 0x040000 - 0x030010 ]; + + volatile u32 did_inhwctrl; /* 0x040000 DID control */ + volatile u32 did_control; /* 0x040004 DID shadow */ + + char _pad4[ 0x048000 - 0x040008 ]; + + volatile u32 mode_regs[32]; /* 0x048000 - 0x04807c WID table */ + + char _pad5[ 0x050000 - 0x048080 ]; + + volatile u32 cmap[6144]; /* 0x050000 - 0x055ffc color map */ + + char _pad6[ 0x058000 - 0x056000 ]; + + volatile u32 cm_fifo; /* 0x058000 color map fifo status */ + + char _pad7[ 0x060000 - 0x058004 ]; + + volatile u32 gmap[256]; /* 0x060000 - 0x0603fc gamma map */ + + char _pad8[ 0x068000 - 0x060400 ]; + + volatile u32 gmap10[1024]; /* 0x068000 - 0x068ffc gamma map */ + + char _pad9[ 0x070000 - 0x069000 ]; + + volatile u32 crs_pos; /* 0x070000 cusror control 0 */ + volatile u32 crs_ctl; /* 0x070004 cusror control 1 */ + volatile u32 crs_cmap[3]; /* 0x070008 - 0x070010 crs cmap */ + + char _pad10[ 0x078000 - 0x070014 ]; + + volatile u32 crs_glyph[64]; /* 0x078000 - 0x0780fc crs glyph */ + + char _pad11[ 0x080000 - 0x078100 ]; + + volatile u32 vc_0; /* 0x080000 video capture crtl 0 */ + volatile u32 vc_1; /* 0x080004 video capture crtl 1 */ + volatile u32 vc_2; /* 0x080008 video capture crtl 2 */ + volatile u32 vc_3; /* 0x08000c video capture crtl 3 */ + volatile u32 vc_4; /* 0x080010 video capture crtl 3 */ + volatile u32 vc_5; /* 0x080014 video capture crtl 3 */ + volatile u32 vc_6; /* 0x080018 video capture crtl 3 */ + volatile u32 vc_7; /* 0x08001c video capture crtl 3 */ + volatile u32 vc_8; /* 0x08000c video capture crtl 3 */ +} asregs; + +/* Bit mask information */ + +#define DBE_CTRLSTAT_CHIPID_MSB 3 +#define DBE_CTRLSTAT_CHIPID_LSB 0 +#define DBE_CTRLSTAT_SENSE_N_MSB 4 +#define DBE_CTRLSTAT_SENSE_N_LSB 4 +#define DBE_CTRLSTAT_PCLKSEL_MSB 29 +#define DBE_CTRLSTAT_PCLKSEL_LSB 28 + +#define DBE_DOTCLK_M_MSB 7 +#define DBE_DOTCLK_M_LSB 0 +#define DBE_DOTCLK_N_MSB 13 +#define DBE_DOTCLK_N_LSB 8 +#define DBE_DOTCLK_P_MSB 15 +#define DBE_DOTCLK_P_LSB 14 +#define DBE_DOTCLK_RUN_MSB 20 +#define DBE_DOTCLK_RUN_LSB 20 + +#define DBE_VT_XY_VT_FREEZE_MSB 31 +#define DBE_VT_XY_VT_FREEZE_LSB 31 + +#define DBE_VT_VSYNC_VT_VSYNC_ON_MSB 23 +#define DBE_VT_VSYNC_VT_VSYNC_ON_LSB 12 +#define DBE_VT_VSYNC_VT_VSYNC_OFF_MSB 11 +#define DBE_VT_VSYNC_VT_VSYNC_OFF_LSB 0 + +#define DBE_VT_HSYNC_VT_HSYNC_ON_MSB 23 +#define DBE_VT_HSYNC_VT_HSYNC_ON_LSB 12 +#define DBE_VT_HSYNC_VT_HSYNC_OFF_MSB 11 +#define DBE_VT_HSYNC_VT_HSYNC_OFF_LSB 0 + +#define DBE_VT_VBLANK_VT_VBLANK_ON_MSB 23 +#define DBE_VT_VBLANK_VT_VBLANK_ON_LSB 12 +#define DBE_VT_VBLANK_VT_VBLANK_OFF_MSB 11 +#define DBE_VT_VBLANK_VT_VBLANK_OFF_LSB 0 + +#define DBE_VT_HBLANK_VT_HBLANK_ON_MSB 23 +#define DBE_VT_HBLANK_VT_HBLANK_ON_LSB 12 +#define DBE_VT_HBLANK_VT_HBLANK_OFF_MSB 11 +#define DBE_VT_HBLANK_VT_HBLANK_OFF_LSB 0 + +#define DBE_VT_VCMAP_VT_VCMAP_ON_MSB 23 +#define DBE_VT_VCMAP_VT_VCMAP_ON_LSB 12 +#define DBE_VT_VCMAP_VT_VCMAP_OFF_MSB 11 +#define DBE_VT_VCMAP_VT_VCMAP_OFF_LSB 0 + +#define DBE_VT_HCMAP_VT_HCMAP_ON_MSB 23 +#define DBE_VT_HCMAP_VT_HCMAP_ON_LSB 12 +#define DBE_VT_HCMAP_VT_HCMAP_OFF_MSB 11 +#define DBE_VT_HCMAP_VT_HCMAP_OFF_LSB 0 + +#define DBE_VT_XYMAX_VT_MAXX_MSB 11 +#define DBE_VT_XYMAX_VT_MAXX_LSB 0 +#define DBE_VT_XYMAX_VT_MAXY_MSB 23 +#define DBE_VT_XYMAX_VT_MAXY_LSB 12 + +#define DBE_VT_HPIXEN_VT_HPIXEN_ON_MSB 23 +#define DBE_VT_HPIXEN_VT_HPIXEN_ON_LSB 12 +#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_MSB 11 +#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_LSB 0 + +#define DBE_VT_VPIXEN_VT_VPIXEN_ON_MSB 23 +#define DBE_VT_VPIXEN_VT_VPIXEN_ON_LSB 12 +#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_MSB 11 +#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_LSB 0 + +#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_MSB 0 +#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_LSB 0 + +#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_MSB 0 +#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_LSB 0 + +#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_MSB 13 +#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_LSB 13 + +#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_MSB 0 +#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_LSB 0 +#define DBE_FRM_CONTROL_FRM_TILE_PTR_MSB 31 +#define DBE_FRM_CONTROL_FRM_TILE_PTR_LSB 9 +#define DBE_FRM_CONTROL_FRM_LINEAR_MSB 1 +#define DBE_FRM_CONTROL_FRM_LINEAR_LSB 1 + +#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_MSB 0 +#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_LSB 0 + +#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_MSB 12 +#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_LSB 5 +#define DBE_FRM_SIZE_TILE_FRM_RHS_MSB 4 +#define DBE_FRM_SIZE_TILE_FRM_RHS_LSB 0 +#define DBE_FRM_SIZE_TILE_FRM_DEPTH_MSB 14 +#define DBE_FRM_SIZE_TILE_FRM_DEPTH_LSB 13 +#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_MSB 15 +#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_LSB 15 + +#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_MSB 31 +#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_LSB 16 + +#define DBE_DID_CONTROL_DID_DMA_ENABLE_MSB 0 +#define DBE_DID_CONTROL_DID_DMA_ENABLE_LSB 0 +#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_MSB 0 +#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_LSB 0 + +#define DBE_DID_START_XY_DID_STARTY_MSB 23 +#define DBE_DID_START_XY_DID_STARTY_LSB 12 +#define DBE_DID_START_XY_DID_STARTX_MSB 11 +#define DBE_DID_START_XY_DID_STARTX_LSB 0 + +#define DBE_CRS_START_XY_CRS_STARTY_MSB 23 +#define DBE_CRS_START_XY_CRS_STARTY_LSB 12 +#define DBE_CRS_START_XY_CRS_STARTX_MSB 11 +#define DBE_CRS_START_XY_CRS_STARTX_LSB 0 + +#define DBE_WID_TYP_MSB 4 +#define DBE_WID_TYP_LSB 2 +#define DBE_WID_BUF_MSB 1 +#define DBE_WID_BUF_LSB 0 + +#define DBE_VC_START_XY_VC_STARTY_MSB 23 +#define DBE_VC_START_XY_VC_STARTY_LSB 12 +#define DBE_VC_START_XY_VC_STARTX_MSB 11 +#define DBE_VC_START_XY_VC_STARTX_LSB 0 + +/* Constants */ + +#define DBE_FRM_DEPTH_8 0 +#define DBE_FRM_DEPTH_16 1 +#define DBE_FRM_DEPTH_32 2 + +#define DBE_CMODE_I8 0 +#define DBE_CMODE_I12 1 +#define DBE_CMODE_RG3B2 2 +#define DBE_CMODE_RGB4 3 +#define DBE_CMODE_ARGB5 4 +#define DBE_CMODE_RGB8 5 +#define DBE_CMODE_RGBA5 6 +#define DBE_CMODE_RGB10 7 + +#define DBE_BMODE_BOTH 3 + +#define DBE_CRS_MAGIC 54 + +/* Config Register (DBE Only) Definitions */ + +#define DBE_CONFIG_VDAC_ENABLE 0x00000001 +#define DBE_CONFIG_VDAC_GSYNC 0x00000002 +#define DBE_CONFIG_VDAC_PBLANK 0x00000004 +#define DBE_CONFIG_FPENABLE 0x00000008 +#define DBE_CONFIG_LENDIAN 0x00000020 +#define DBE_CONFIG_TILEHIST 0x00000040 +#define DBE_CONFIG_EXT_ADDR 0x00000080 + +#define DBE_CONFIG_FBDEV ( DBE_CONFIG_VDAC_ENABLE | \ + DBE_CONFIG_VDAC_GSYNC | \ + DBE_CONFIG_VDAC_PBLANK | \ + DBE_CONFIG_LENDIAN | \ + DBE_CONFIG_EXT_ADDR ) + +/* + * Available Video Timings and Corresponding Indices + */ + +typedef enum { + DBE_VT_640_480_60, + + DBE_VT_800_600_60, + DBE_VT_800_600_75, + DBE_VT_800_600_120, + + DBE_VT_1024_768_50, + DBE_VT_1024_768_60, + DBE_VT_1024_768_75, + DBE_VT_1024_768_85, + DBE_VT_1024_768_120, + + DBE_VT_1280_1024_50, + DBE_VT_1280_1024_60, + DBE_VT_1280_1024_75, + DBE_VT_1280_1024_85, + + DBE_VT_1600_1024_53, + DBE_VT_1600_1024_60, + + DBE_VT_1600_1200_50, + DBE_VT_1600_1200_60, + DBE_VT_1600_1200_75, + + DBE_VT_1920_1080_50, + DBE_VT_1920_1080_60, + DBE_VT_1920_1080_72, + + DBE_VT_1920_1200_50, + DBE_VT_1920_1200_60, + DBE_VT_1920_1200_66, + + DBE_VT_UNKNOWN +} dbe_timing_t; + + + +/* + * Crime Video Timing Data Structure + */ + +typedef struct dbe_timing_info +{ + dbe_timing_t type; + int flags; + short width; /* Monitor resolution */ + short height; + int fields_sec; /* fields/sec (Hz -3 dec. places */ + int cfreq; /* pixel clock frequency (MHz -3 dec. places) */ + short htotal; /* Horizontal total pixels */ + short hblank_start; /* Horizontal blank start */ + short hblank_end; /* Horizontal blank end */ + short hsync_start; /* Horizontal sync start */ + short hsync_end; /* Horizontal sync end */ + short vtotal; /* Vertical total lines */ + short vblank_start; /* Vertical blank start */ + short vblank_end; /* Vertical blank end */ + short vsync_start; /* Vertical sync start */ + short vsync_end; /* Vertical sync end */ + short pll_m; /* PLL M parameter */ + short pll_n; /* PLL P parameter */ + short pll_p; /* PLL N parameter */ +} dbe_timing_info_t; + +/* Defines for dbe_vof_info_t flags */ + +#define DBE_VOF_UNKNOWNMON 1 +#define DBE_VOF_STEREO 2 +#define DBE_VOF_DO_GENSYNC 4 /* enable incoming sync */ +#define DBE_VOF_SYNC_ON_GREEN 8 /* sync on green */ +#define DBE_VOF_FLATPANEL 0x1000 /* FLATPANEL Timing */ +#define DBE_VOF_MAGICKEY 0x2000 /* Backdoor key */ + +/* + * DBE Timing Tables + */ + +#ifdef INCLUDE_TIMING_TABLE_DATA +struct dbe_timing_info dbeVTimings[] = { + { + DBE_VT_640_480_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 640, 480, 59940, 25175, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 800, 640, 800, 656, 752, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 525, 480, 525, 490, 492, + /* pll_m, pll_n, pll_p */ + 15, 2, 3 + }, + + { + DBE_VT_800_600_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 800, 600, 60317, 40000, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1056, 800, 1056, 840, 968, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 628, 600, 628, 601, 605, + /* pll_m, pll_n, pll_p */ + 3, 1, 1 + }, + + { + DBE_VT_800_600_75, + /* flags, width, height, fields_sec, cfreq */ + 0, 800, 600, 75000, 49500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1056, 800, 1056, 816, 896, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 625, 600, 625, 601, 604, + /* pll_m, pll_n, pll_p */ + 11, 3, 1 + }, + + { + DBE_VT_800_600_120, + /* flags, width, height, fields_sec, cfreq */ + DBE_VOF_STEREO, 800, 600, 119800, 82978, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1040, 800, 1040, 856, 976, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 666, 600, 666, 637, 643, + /* pll_m, pll_n, pll_p */ + 31, 5, 1 + }, + + { + DBE_VT_1024_768_50, + /* flags, width, height, fields_sec, cfreq */ + 0, 1024, 768, 50000, 54163, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1344, 1024, 1344, 1048, 1184, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 806, 768, 806, 771, 777, + /* pll_m, pll_n, pll_p */ + 4, 1, 1 + }, + + { + DBE_VT_1024_768_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 1024, 768, 60004, 65000, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1344, 1024, 1344, 1048, 1184, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 806, 768, 806, 771, 777, + /* pll_m, pll_n, pll_p */ + 12, 5, 0 + }, + + { + DBE_VT_1024_768_75, + /* flags, width, height, fields_sec, cfreq */ + 0, 1024, 768, 75029, 78750, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1312, 1024, 1312, 1040, 1136, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 800, 768, 800, 769, 772, + /* pll_m, pll_n, pll_p */ + 29, 5, 1 + }, + + { + DBE_VT_1024_768_85, + /* flags, width, height, fields_sec, cfreq */ + 0, 1024, 768, 84997, 94500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1376, 1024, 1376, 1072, 1168, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 808, 768, 808, 769, 772, + /* pll_m, pll_n, pll_p */ + 7, 2, 0 + }, + + { + DBE_VT_1024_768_120, + /* flags, width, height, fields_sec, cfreq */ + DBE_VOF_STEREO, 1024, 768, 119800, 133195, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1376, 1024, 1376, 1072, 1168, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 808, 768, 808, 769, 772, + /* pll_m, pll_n, pll_p */ + 5, 1, 0 + }, + + { + DBE_VT_1280_1024_50, + /* flags, width, height, fields_sec, cfreq */ + 0, 1280, 1024, 50000, 89460, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1680, 1280, 1680, 1360, 1480, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1065, 1024, 1065, 1027, 1030, + /* pll_m, pll_n, pll_p */ + 10, 3, 0 + }, + + { + DBE_VT_1280_1024_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 1280, 1024, 60020, 108000, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1688, 1280, 1688, 1328, 1440, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1066, 1024, 1066, 1025, 1028, + /* pll_m, pll_n, pll_p */ + 4, 1, 0 + }, + + { + DBE_VT_1280_1024_75, + /* flags, width, height, fields_sec, cfreq */ + 0, 1280, 1024, 75025, 135000, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1688, 1280, 1688, 1296, 1440, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1066, 1024, 1066, 1025, 1028, + /* pll_m, pll_n, pll_p */ + 5, 1, 0 + }, + + { + DBE_VT_1280_1024_85, + /* flags, width, height, fields_sec, cfreq */ + 0, 1280, 1024, 85024, 157500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1728, 1280, 1728, 1344, 1504, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1072, 1024, 1072, 1025, 1028, + /* pll_m, pll_n, pll_p */ + 29, 5, 0 + }, + + { + DBE_VT_1600_1024_53, + /* flags, width, height, fields_sec, cfreq */ + DBE_VOF_FLATPANEL | DBE_VOF_MAGICKEY, + 1600, 1024, 53000, 107447, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1900, 1600, 1900, 1630, 1730, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1067, 1024, 1067, 1027, 1030, + /* pll_m, pll_n, pll_p */ + 4, 1, 0 + }, + + { + DBE_VT_1600_1024_60, + /* flags, width, height, fields_sec, cfreq */ + DBE_VOF_FLATPANEL, 1600, 1024, 60000, 106913, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 1670, 1600, 1670, 1630, 1650, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1067, 1024, 1067, 1027, 1030, + /* pll_m, pll_n, pll_p */ + 4, 1, 0 + }, + + { + DBE_VT_1600_1200_50, + /* flags, width, height, fields_sec, cfreq */ + 0, 1600, 1200, 50000, 130500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2088, 1600, 2088, 1644, 1764, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1205, 1211, + /* pll_m, pll_n, pll_p */ + 24, 5, 0 + }, + + { + DBE_VT_1600_1200_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 1600, 1200, 59940, 162000, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2160, 1600, 2160, 1644, 1856, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1201, 1204, + /* pll_m, pll_n, pll_p */ + 6, 1, 0 + }, + + { + DBE_VT_1600_1200_75, + /* flags, width, height, fields_sec, cfreq */ + 0, 1600, 1200, 75000, 202500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2160, 1600, 2160, 1644, 1856, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1201, 1204, + /* pll_m, pll_n, pll_p */ + 15, 2, 0 + }, + + { + DBE_VT_1920_1080_50, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1080, 50000, 133200, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2368, 1920, 2368, 1952, 2096, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1125, 1080, 1125, 1083, 1086, + /* pll_m, pll_n, pll_p */ + 5, 1, 0 + }, + + { + DBE_VT_1920_1080_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1080, 59940, 159840, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2368, 1920, 2368, 1952, 2096, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1125, 1080, 1125, 1083, 1086, + /* pll_m, pll_n, pll_p */ + 6, 1, 0 + }, + + { + DBE_VT_1920_1080_72, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1080, 72000, 216023, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2560, 1920, 2560, 1968, 2184, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1172, 1080, 1172, 1083, 1086, + /* pll_m, pll_n, pll_p */ + 8, 1, 0 + }, + + { + DBE_VT_1920_1200_50, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1200, 50000, 161500, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2584, 1920, 2584, 1984, 2240, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1203, 1206, + /* pll_m, pll_n, pll_p */ + 6, 1, 0 + }, + + { + DBE_VT_1920_1200_60, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1200, 59940, 193800, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2584, 1920, 2584, 1984, 2240, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1203, 1206, + /* pll_m, pll_n, pll_p */ + 29, 4, 0 + }, + + { + DBE_VT_1920_1200_66, + /* flags, width, height, fields_sec, cfreq */ + 0, 1920, 1200, 66000, 213180, + /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */ + 2584, 1920, 2584, 1984, 2240, + /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */ + 1250, 1200, 1250, 1203, 1206, + /* pll_m, pll_n, pll_p */ + 8, 1, 0 + } +}; + +#define DBE_VT_SIZE (sizeof(dbeVTimings)/sizeof(dbeVTimings[0])) +#endif // INCLUDE_TIMING_TABLE_DATA + +#endif // ! __SGIVWFB_H__ diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index a99a3a0cd..59a2da716 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -240,12 +240,11 @@ static int xxx_blank(int blank_mode, const struct fb_info *info) return 0; } -static void xxx_set_dispsw(const void *par, struct display *disp, - struct fb_info_gen *info) +static void xxx_set_disp(const void *par, struct display *disp, + struct fb_info_gen *info) { - unsigned long flags; - /* + * Fill in a pointer with the virtual address of the mapped frame buffer. * Fill in a pointer to appropriate low level text console operations (and * optionally a pointer to help data) for the video mode `par' of your * video hardware. These can be generic software routines, or hardware @@ -253,7 +252,7 @@ static void xxx_set_dispsw(const void *par, struct display *disp, * If you don't have any appropriate operations, you must fill in a * pointer to dummy operations, and there will be no text output. */ - save_flags(flags); cli(); + disp->screen_base = virtual_frame_buffer_address; #ifdef FBCON_HAS_CFB8 if (is_cfb8) { disp->dispsw = fbcon_cfb8; @@ -278,7 +277,6 @@ static void xxx_set_dispsw(const void *par, struct display *disp, } else #endif disp->dispsw = &fbcon_dummy; - restore_flags(flags); } diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c index 90d6152fa..8e9d2fc41 100644 --- a/drivers/video/tcxfb.c +++ b/drivers/video/tcxfb.c @@ -1,4 +1,4 @@ -/* $Id: tcxfb.c,v 1.6 1998/09/04 15:43:46 jj Exp $ +/* $Id: tcxfb.c,v 1.7 1999/01/26 10:55:03 jj Exp $ * tcxfb.c: TCX 24/8bit frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -228,6 +228,7 @@ __initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb)) strcpy(fix->id, "TCX24"); } fix->line_length = fb->var.xres_virtual; + fix->accel = FB_ACCEL_SUN_TCX; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index cbad38a82..78af83ef0 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -21,7 +21,6 @@ #include <linux/selection.h> #include <linux/ioport.h> #include <linux/init.h> -#include <linux/config.h> #include <asm/io.h> #include <asm/mtrr.h> @@ -93,6 +92,7 @@ static union { } fbcon_cmap; static int inverse = 0; +static int mtrr = 0; static int currcon = 0; static int pmi_setpal = 0; /* pmi for palette changes ??? */ @@ -254,6 +254,7 @@ static void vesafb_set_disp(int con) static int vesafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { + static int first = 1; if (var->xres != vesafb_defined.xres || var->yres != vesafb_defined.yres || @@ -262,8 +263,13 @@ static int vesafb_set_var(struct fb_var_screeninfo *var, int con, var->yres_virtual < video_height || var->xoffset || var->bits_per_pixel != vesafb_defined.bits_per_pixel || - var->nonstd) + var->nonstd) { + if (first) { + printk("Vesafb does not support changing the video mode\n"); + first = 0; + } return -EINVAL; + } if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) return 0; @@ -489,6 +495,8 @@ void vesafb_setup(char *options, int *ints) pmi_setpal=0; else if (! strcmp(this_opt, "pmipal")) pmi_setpal=1; + else if (! strcmp(this_opt, "mtrr")) + mtrr=1; else if (!strncmp(this_opt, "font:", 5)) strcpy(fb_info.fontname, this_opt+5); } @@ -626,9 +634,8 @@ __initfunc(void vesafb_init(void)) video_cmap_len = 256; } request_region(0x3c0, 32, "vga+"); -#ifdef CONFIG_MTRR - mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1); -#endif + if (mtrr) + mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1); strcpy(fb_info.modename, "VESA VGA"); fb_info.changevar = NULL; diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index ba4bf5ea0..a19c1c9e5 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -89,11 +89,6 @@ #define rl_3d(reg) \ (*((unsigned long volatile *)(CyberRegs + reg))) - - - - - struct virgefb_par { int xres; int yres; @@ -109,6 +104,11 @@ static int currcon = 0; static struct display disp; static struct fb_info fb_info; +static union { +#ifdef FBCON_HAS_CFB16 + u16 cfb16[16]; +#endif +} fbcon_cmap; /* * Switch for Chipset Independency @@ -132,6 +132,7 @@ static struct fb_hwswitch { void (*blank)(int blank); } *fbhw; +static int blit_maybe_busy = 0; /* * Frame Buffer Name @@ -148,7 +149,7 @@ static char virgefb_name[16] = "Cybervision/3D"; #define VIRGE8_HEIGHT 886 #define VIRGE8_PIXCLOCK 12500 /* ++Geert: Just a guess */ -#if 0 +#if 1 #define VIRGE16_WIDTH 800 #define VIRGE16_HEIGHT 600 #endif @@ -167,6 +168,8 @@ static unsigned long Cyber_register_base; static unsigned long Cyber_vcode_switch_base; static unsigned char cv3d_on_zorro2; +#define CYBMEM_OFFSET_8 0x800000 /* offsets from start of video - */ +#define CYBMEM_OFFSET_16 0x400000 /* ram to appropriate aperture */ /* * Predefined Video Modes @@ -216,10 +219,17 @@ static struct fb_videomode virgefb_predefined[] __initdata = { FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, { + "640x480-16", { /* Cybervision 16 bpp */ + 640, 480, 640, 480, 0, 0, 16, 0, + {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, + 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 + } + }, { "800x600-16", { /* Cybervision 16 bpp */ 800, 600, 800, 600, 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 } }, { @@ -229,6 +239,27 @@ static struct fb_videomode virgefb_predefined[] __initdata = { 0, 0, -1, -1, 0, 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, + 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, + 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, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } } }; @@ -246,8 +277,8 @@ static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */ * Some default modes */ -#define VIRGE8_DEFMODE (0) -#define VIRGE16_DEFMODE (6) +#define VIRGE8_DEFMODE (1) +#define VIRGE16_DEFMODE (7) static struct fb_var_screeninfo virgefb_default; @@ -294,6 +325,9 @@ static void Cyberfb_blank(int blank, struct fb_info *info); static struct display_switch fbcon_virge8; #endif +#ifdef FBCON_HAS_CFB16 +static struct display_switch fbcon_virge16; +#endif /* * Hardware Specific Routines @@ -353,15 +387,14 @@ static int Cyber_init(void) * (the 3D penguin might need texture memory :-) ) */ - memset ((char*)CyberMem, 0, 1600 * 1200); - - /* Disable hardware cursor */ if (cv3d_on_zorro2) { CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */ } else { CyberSize = 0x00400000; /* 4 MB */ } + memset ((char*)CyberMem, 0, CyberSize); + /* Disable hardware cursor */ vgawb_3d(0x3c8, 255); vgawb_3d(0x3c9, 56); vgawb_3d(0x3c9, 100); @@ -396,7 +429,18 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, virgefb_name); - fix->smem_start = (char*) CyberMem_phys; + if (cv3d_on_zorro2) { + fix->smem_start = (char*) CyberMem_phys; + } else { + switch (par->bpp) { + case 8: + fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_8); + break; + case 16: + fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_16); + break; + } + } fix->smem_len = CyberSize; fix->mmio_start = (char*) CyberRegs_phys; fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */ @@ -467,24 +511,27 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->bits_per_pixel = par->bpp; var->grayscale = 0; - if (par->bpp == 8) { - var->red.offset = 0; - var->red.length = 6; - var->red.msb_right = 0; - var->blue = var->green = var->red; - } else { - var->red.offset = 11; - var->red.length = 5; - var->red.msb_right = 0; - var->green.offset = 5; - var->green.length = 6; - var->green.msb_right = 0; - var->blue.offset = 0; - var->blue.length = 5; - var->blue.msb_right = 0; + switch (var->bits_per_pixel) { + case 8: /* CLUT */ + var->red.offset = 0; + var->red.length = 6; + var->red.msb_right = 0; + var->blue = var->green = var->red; + break; + case 16: /* RGB 565 */ + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; } - var->transp.offset = 0; - var->transp.length = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; var->transp.msb_right = 0; var->nonstd = 0; @@ -493,8 +540,10 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; - var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0; - DPRINTK("accel CV64/3D\n"); + var->accel_flags = (par->accel && + ((par->bpp == 8) || (par->bpp == 16))) ? FB_ACCELF_TEXT : 0; + +/* printk("CV64/3D : %s\n",(var->accel_flags ? "accel" : "no accel")); */ var->vmode = FB_VMODE_NONINTERLACED; @@ -525,28 +574,34 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { - if (regno > 255) - { - return (1); + if (((current_par.bpp==8) && (regno>255)) || + ((current_par.bpp!=8) && (regno>15))) + return (1); + + if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) &&(regno<16))) { + Cyber_colour_table [regno][0] = red >> 10; + Cyber_colour_table [regno][1] = green >> 10; + Cyber_colour_table [regno][2] = blue >> 10; } - /* - * No colors on the CV3D yet. - */ - - vgawb_3d(0x3c8, (unsigned char) regno); - red >>= 10; - green >>= 10; - blue >>= 10; - - Cyber_colour_table [regno][0] = red; - Cyber_colour_table [regno][1] = green; - Cyber_colour_table [regno][2] = blue; - - vgawb_3d(0x3c9, red); - vgawb_3d(0x3c9, green); - vgawb_3d(0x3c9, blue); - + switch (current_par.bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: + vgawb_3d(0x3c8, (unsigned char) regno); + vgawb_3d(0x3c9, ((unsigned char) (red >> 10))); + vgawb_3d(0x3c9, ((unsigned char) (green >> 10))); + vgawb_3d(0x3c9, ((unsigned char) (blue >> 10))); + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 16: + fbcon_cmap.cfb16[regno] = + ((red & 0xf800) | + ((green & 0xfc00) >> 5) | + ((blue & 0xf800) >> 11)); + break; +#endif + } return (0); } @@ -561,14 +616,18 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, { int t; - if (regno >= 256) + if (regno > 255) return (1); - t = Cyber_colour_table [regno][0]; - *red = (t<<10) | (t<<4) | (t>>2); - t = Cyber_colour_table [regno][1]; - *green = (t<<10) | (t<<4) | (t>>2); - t = Cyber_colour_table [regno][2]; - *blue = (t<<10) | (t<<4) | (t>>2); + + if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) && (regno<16))) { + + t = Cyber_colour_table [regno][0]; + *red = (t<<10) | (t<<4) | (t>>2); + t = Cyber_colour_table [regno][1]; + *green = (t<<10) | (t<<4) | (t>>2); + t = Cyber_colour_table [regno][2]; + *blue = (t<<10) | (t<<4) | (t>>2); + } *transp = 0; return (0); } @@ -615,8 +674,10 @@ static inline void Cyber3D_WaitBusy(void) unsigned long status; do { + mb(); status = rl_3d(0x8504); } while (!(status & (1 << 13))); + blit_maybe_busy = 0; } #define S3V_BITBLT (0x0 << 27) @@ -666,6 +727,10 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx, desty += (height - 1); } + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + blit_maybe_busy = 1; + wl_3d(0xa4f4, 1); /* pattern fb color */ wl_3d(0xa4e8, ~0); /* mono pat 0 */ @@ -676,8 +741,6 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx, wl_3d(0xa50c, ((destx << 16) | desty)); /* rdest_xy */ wl_3d(0xa500, blitcmd); /* GO! */ - - Cyber3D_WaitBusy(); } /* @@ -691,6 +754,10 @@ static void Cyber3D_RectFill(u_short x, u_short y, u_short width, unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP | S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25); + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + blit_maybe_busy = 1; + tmp = color & 0xff; wl_3d(0xa4f4, tmp); @@ -698,19 +765,20 @@ static void Cyber3D_RectFill(u_short x, u_short y, u_short width, wl_3d(0xa50c, ((x << 16) | y)); /* rdest_xy */ wl_3d(0xa500, blitcmd); /* GO! */ - Cyber3D_WaitBusy(); } /************************************************************** * Move cursor to x, y */ + +#if 0 static void Cyber_MoveCursor (u_short x, u_short y) { printk("Yuck .... MoveCursor on a 3D\n"); return; } - +#endif /* -------------------- Interfaces to hardware functions -------------------- */ @@ -868,7 +936,18 @@ static void virgefb_set_disp(int con, struct fb_info *info) virgefb_get_fix(&fix, con, info); if (con == -1) con = 0; - display->screen_base = (char*) CyberMem; + if (cv3d_on_zorro2) { + display->screen_base = (char*) CyberMem; + } else { + switch (display->var.bits_per_pixel) { + case 8: + display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_8); + break; + case 16: + display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_16); + break; + } + } display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -878,22 +957,26 @@ static void virgefb_set_disp(int con, struct fb_info *info) display->inverse = Cyberfb_inverse; switch (display->var.bits_per_pixel) { #ifdef FBCON_HAS_CFB8 - case 8: - if (display->var.accel_flags & FB_ACCELF_TEXT) { - display->dispsw = &fbcon_virge8; + case 8: + if (display->var.accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_virge8; #warning FIXME: We should reinit the graphics engine here - } else - display->dispsw = &fbcon_virge8; - break; + } else + display->dispsw = &fbcon_cfb8; + break; #endif #ifdef FBCON_HAS_CFB16 - case 16: - display->dispsw = &fbcon_cfb16; - break; + case 16: + if (display->var.accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_virge16; + } else + display->dispsw = &fbcon_cfb16; + display->dispsw_data = &fbcon_cmap.cfb16; + break; #endif - default: - display->dispsw = &fbcon_dummy; - break; + default: + display->dispsw = &fbcon_dummy; + break; } } @@ -962,7 +1045,7 @@ static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con, if (!fb_display[con].cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&fb_display[con].cmap, - 1<<fb_display[con].var.bits_per_pixel, 0))) + 1<<fb_display[con].var.bits_per_pixel, 0))) return(err); } if (con == currcon) /* current console? */ @@ -987,8 +1070,8 @@ static int virgefb_pan_display(struct fb_var_screeninfo *var, int con, /* - * Cybervision Frame Buffer Specific ioctls - */ + * Cybervision Frame Buffer Specific ioctls + */ static int virgefb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info) @@ -1073,12 +1156,12 @@ __initfunc(void virgefb_init(void)) } else { - CyberVGARegs = ioremap(board_addr +0x0c000000, 0x00010000); + CyberVGARegs = (unsigned long)ioremap(board_addr +0x0c000000, 0x00010000); CyberRegs_phys = board_addr + 0x05000000; - CyberMem_phys = board_addr + 0x04800000; + CyberMem_phys = board_addr + 0x04000000; /* was 0x04800000 */ CyberRegs = ioremap(CyberRegs_phys, 0x00010000); - CyberMem = ioremap(CyberMem_phys, 0x00400000); + CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000); /* was 0x00400000 */ cv3d_on_zorro2 = 0; printk("CV3D detected running in Z3 mode\n"); } @@ -1146,8 +1229,8 @@ static int Cyberfb_updatevar(int con, struct fb_info *info) /* - * Blank the display. - */ + * Blank the display. + */ static void Cyberfb_blank(int blank, struct fb_info *info) { @@ -1201,13 +1284,103 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy, (u_short)bg); } +static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb8_putc(conp, p, c, yy, xx); +} + +static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb8_putcs(conp, p, s, count, yy, xx); +} + +static void fbcon_virge8_revc(struct display *p, int xx, int yy) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb8_revc(p, xx, yy); +} + +static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p, + int bottom_only) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb8_clear_margins(conp, p, bottom_only); +} + static struct display_switch fbcon_virge8 = { - fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins, - FONTWIDTH(8) + fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_virge8_putc, + fbcon_virge8_putcs, fbcon_virge8_revc, NULL, NULL, fbcon_virge8_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; #endif +#ifdef FBCON_HAS_CFB16 +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; + 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))); +} + +static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) +{ + unsigned char bg; + + sx *= 16; width *= 16; + 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); +} + +static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb16_putc(conp, p, c, yy, xx); +} + +static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb16_putcs(conp, p, s, count, yy, xx); +} + +static void fbcon_virge16_revc(struct display *p, int xx, int yy) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb16_revc(p, xx, yy); +} + +static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p, + int bottom_only) +{ + if (blit_maybe_busy) + Cyber3D_WaitBusy(); + fbcon_cfb16_clear_margins(conp, p, bottom_only); +} + +static struct display_switch fbcon_virge16 = { + fbcon_cfb16_setup, fbcon_virge16_bmove, fbcon_virge16_clear, fbcon_virge16_putc, + fbcon_virge16_putcs, fbcon_virge16_revc, NULL, NULL, fbcon_virge16_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif #ifdef MODULE int init_module(void) |