📄 cyberfb.c
字号:
/** linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device* $Id: cyberfb.c,v 1.6 1998/09/11 04:54:58 abair Exp $** Copyright (C) 1998 Alan Bair** This file is based on two CyberVision64 frame buffer device drivers** The second CyberVision64 frame buffer device (cvision.c cvision_core.c):** Copyright (c) 1997 Antonio Santos** Released as a patch to 2.1.35, but never included in the source tree.* This is based on work from the NetBSD CyberVision64 frame buffer driver * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):* Permission to use the source of this driver was obtained from the* author Michael Teske by Alan Bair.** Copyright (c) 1995 Michael Teske** The first CyberVision64 frame buffer device (cyberfb.c):** Copyright (C) 1996 Martin Apel* Geert Uytterhoeven** Which is based on the Amiga frame buffer device (amifb.c):** Copyright (C) 1995 Geert Uytterhoeven*** History:* - 22 Dec 95: Original version by Martin Apel* - 05 Jan 96: Geert: integration into the current source tree* - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c* $Log: cyberfb.c,v $* Revision 1.6 1998/09/11 04:54:58 abair* Update for 2.1.120 change in include file location.* Clean up for public release.** Revision 1.5 1998/09/03 04:27:13 abair* Move cv64_load_video_mode to cyber_set_video so a new video mode is install* with each change of the 'var' data.** Revision 1.4 1998/09/01 00:31:17 abair* Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.* Update operations with 'par' to handle a more complete set of parameter* values for encode/decode process.** Revision 1.3 1998/08/31 21:31:33 abair* Swap 800x490 for 640x480 video mode and more cleanup.* Abandon idea to resurrect "custom" mode setting via kernel opts,* instead work on making use of fbset program to do this.** Revision 1.2 1998/08/31 06:17:08 abair* Make updates for changes in cyberfb.c released in 2.1.119* and do some cleanup of the code.** Revision 1.1 1998/08/29 18:38:31 abair* Initial revision** Revision 1.3 1998/08/17 06:21:53 abair* Remove more redundant code after merging in cvision_core.c* Set blanking by colormap to pale red to detect this vs trying to* use video blanking. More formating to Linux code style.** Revision 1.2 1998/08/15 17:51:37 abair* Added cvision_core.c code from 2.1.35 patches.* Changed to compile correctly and switch to using initialization* code. Added debugging and dropping of duplicate code.**** This file is subject to the terms and conditions of the GNU General Public* License. See the file COPYING in the main directory of this archive* for more details.*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/zorro.h>#include <linux/fb.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <asm/amigahw.h>#include <asm/io.h>#include "cyberfb.h"#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>/*#define CYBERFBDEBUG*/#ifdef CYBERFBDEBUG#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)static void cv64_dump(void);#else#define DPRINTK(fmt, args...)#endif#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)struct cyberfb_par { struct fb_var_screeninfo var; __u32 type; __u32 type_aux; __u32 visual; __u32 line_length;};static struct cyberfb_par current_par;static int current_par_valid = 0;static int currcon = 0;static struct display disp;static struct fb_info fb_info;/* * Frame Buffer Name */static char cyberfb_name[16] = "Cybervision";/* * CyberVision Graphics Board */static unsigned char Cyber_colour_table [256][3];static unsigned long CyberSize;static volatile unsigned char *CyberBase;static volatile unsigned char *CyberMem;static volatile unsigned char *CyberRegs;static unsigned long CyberMem_phys;static unsigned long CyberRegs_phys;/* * Predefined Video Modes */static struct { const char *name; struct fb_var_screeninfo var;} cyberfb_predefined[] __initdata = { { "640x480-8", { /* Default 8 BPP mode (cyber8) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "640x480-16", { /* Default 16 BPP mode (cyber16) */ 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, 39722, 40, 24, 32, 11, 96, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "640x480-24", { /* Default 24 BPP mode */ 640, 480, 640, 480, 0, 0, 24, 0, {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "800x490-8", { /* Cybervision 8 bpp */ /* NO Acceleration */ 800, 490, 800, 490, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }},/* I can't test these with my monitor, but I suspect they will * be OK, since Antonio Santos indicated he had tested them in * his system. */ { "800x600-8", { /* Cybervision 8 bpp */ 800, 600, 800, 600, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "1024x768-8", { /* Cybervision 8 bpp */ 1024, 768, 1024, 768, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "1152x886-8", { /* Cybervision 8 bpp */ 1152, 886, 1152, 886, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }}, { "1280x1024-8", { /* Cybervision 8 bpp */ 1280, 1024, 1280, 1024, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED }}};#define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined)static int Cyberfb_inverse = 0;/* * Some default modes */#define CYBER8_DEFMODE (0)#define CYBER16_DEFMODE (1)static struct fb_var_screeninfo cyberfb_default;static int cyberfb_usermode __initdata = 0;/* * Interface used by the world */int cyberfb_setup(char *options);static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int cyberfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);/* * Interface to the low level console driver */int cyberfb_init(void);static int Cyberfb_switch(int con, struct fb_info *info);static int Cyberfb_updatevar(int con, struct fb_info *info);static void Cyberfb_blank(int blank, struct fb_info *info);/* * Text console acceleration */#ifdef FBCON_HAS_CFB8static struct display_switch fbcon_cyber8;#endif/* * Accelerated Functions used by the low level console driver */static void Cyber_WaitQueue(u_short fifo);static void Cyber_WaitBlit(void);static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty, u_short width, u_short height, u_short mode);static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height, u_short mode, u_short color);#if 0static void Cyber_MoveCursor(u_short x, u_short y);#endif/* * Hardware Specific Routines */static int Cyber_init(void);static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, struct cyberfb_par *par);static int Cyber_decode_var(struct fb_var_screeninfo *var, struct cyberfb_par *par);static int Cyber_encode_var(struct fb_var_screeninfo *var, struct cyberfb_par *par);static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info);static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info);/* * Internal routines */static void cyberfb_get_par(struct cyberfb_par *par);static void cyberfb_set_par(struct cyberfb_par *par);static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);static void do_install_cmap(int con, struct fb_info *info);static void cyberfb_set_disp(int con, struct fb_info *info);static int get_video_mode(const char *name);/* For cvision_core.c */static unsigned short cv64_compute_clock(unsigned long);static int cv_has_4mb (volatile unsigned char *);static void cv64_board_init (void);static void cv64_load_video_mode (struct fb_var_screeninfo *);/* -------------------- Hardware specific routines ------------------------- *//* * Initialization * * Set the default video mode for this chipset. If a video mode was * specified on the command line, it will override the default mode. */static int Cyber_init(void){ volatile unsigned char *regs = CyberRegs; volatile unsigned long *CursorBase; int i; DPRINTK("ENTER\n");/* Init local cmap as greyscale levels */ for (i = 0; i < 256; i++) { Cyber_colour_table [i][0] = i; Cyber_colour_table [i][1] = i; Cyber_colour_table [i][2] = i; }/* Initialize the board and determine fbmem size */ cv64_board_init(); #ifdef CYBERFBDEBUG DPRINTK("Register state after initing board\n"); cv64_dump();#endif/* Clear framebuffer memory */ DPRINTK("Clear framebuffer memory\n"); memset ((char *)CyberMem, 0, CyberSize);/* Disable hardware cursor */ DPRINTK("Disable HW cursor\n"); wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2); wb_64(regs, S3_CRTC_DATA, 0xa0); wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE); wb_64(regs, S3_CRTC_DATA, 0x00); wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX); wb_64(regs, S3_CRTC_DATA, 0x00); wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY); wb_64(regs, S3_CRTC_DATA, 0x00);/* Initialize hardware cursor */ DPRINTK("Init HW cursor\n"); CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400); for (i=0; i < 8; i++) { *(CursorBase +(i*4)) = 0xffffff00; *(CursorBase+1+(i*4)) = 0xffff0000; *(CursorBase+2+(i*4)) = 0xffff0000; *(CursorBase+3+(i*4)) = 0xffff0000; } for (i=8; i < 64; i++) { *(CursorBase +(i*4)) = 0xffff0000; *(CursorBase+1+(i*4)) = 0xffff0000; *(CursorBase+2+(i*4)) = 0xffff0000; *(CursorBase+3+(i*4)) = 0xffff0000; } Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */); Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */); DPRINTK("EXIT\n"); return 0;}/* * This function should fill in the `fix' structure based on the * values in the `par' structure. */static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, struct cyberfb_par *par){ DPRINTK("ENTER\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, cyberfb_name); fix->smem_start = CyberMem_phys; fix->smem_len = CyberSize; fix->mmio_start = CyberRegs_phys; fix->mmio_len = 0x10000; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 || par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) { fix->visual = FB_VISUAL_DIRECTCOLOR; } else { fix->visual = FB_VISUAL_PSEUDOCOLOR; } fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = 0; fix->accel = FB_ACCEL_S3_TRIO64; DPRINTK("EXIT\n"); return(0);}/** Fill the `par' structure based on the values in `var'.* TODO: Verify and adjust values, return -EINVAL if bad.*/static int Cyber_decode_var(struct fb_var_screeninfo *var, struct cyberfb_par *par){ DPRINTK("ENTER\n"); par->var.xres = var->xres; par->var.yres = var->yres; par->var.xres_virtual = var->xres_virtual; par->var.yres_virtual = var->yres_virtual; par->var.xoffset = var->xoffset; par->var.yoffset = var->yoffset; par->var.bits_per_pixel = var->bits_per_pixel; par->var.grayscale = var->grayscale; par->var.red = var->red; par->var.green = var->green; par->var.blue = var->blue; par->var.transp = var->transp; par->var.nonstd = var->nonstd; par->var.activate = var->activate; par->var.height = var->height; par->var.width = var->width; if (var->accel_flags & FB_ACCELF_TEXT) { par->var.accel_flags = FB_ACCELF_TEXT; } else { par->var.accel_flags = 0; } par->var.pixclock = var->pixclock; par->var.left_margin = var->left_margin; par->var.right_margin = var->right_margin; par->var.upper_margin = var->upper_margin; par->var.lower_margin = var->lower_margin; par->var.hsync_len = var->hsync_len; par->var.vsync_len = var->vsync_len; par->var.sync = var->sync; par->var.vmode = var->vmode; DPRINTK("EXIT\n"); return(0);}/** Fill the `var' structure based on the values in `par' and maybe* other values read out of the hardware.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -