📄 68328fb.c
字号:
/* * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the * mc68328 LCD frame buffer device * * Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>, * The Silver Hammer Group, Ltd. * * * This file is based on the Amiga CyberVision frame buffer device (Cyberfb.c): * * Copyright (C) 1996 Martin Apel * Geert Uytterhoeven * * * This file is based on the Amiga frame buffer device (amifb.c): * * Copyright (C) 1995 Geert Uytterhoeven * * * History: * - 17 Feb 98: Original version by Kenneth Albanowski <kjahds@kjahds.com> * * * 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/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/config.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <linux/fb.h>#define arraysize(x) (sizeof(x)/sizeof(*(x)))struct mc68328_fb_par { int xres; int yres; int bpp;};static struct mc68328_fb_par current_par;static int current_par_valid = 0;static int currcon = 0;static struct display disp[MAX_NR_CONSOLES];static struct fb_info fb_info;static int node; /* node of the /dev/fb?current file */ /* * Switch for Chipset Independency */static struct fb_hwswitch { /* Initialisation */ int (*init)(void); /* Display Control */ int (*encode_fix)(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par); int (*decode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par); int (*encode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par); int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp); int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue, u_int transp); void (*blank)(int blank);} *fbhw; /* * Frame Buffer Name */static char mc68328_fb_name[16] = "mc68328"; /* * mc68328vision Graphics Board */#define CYBER8_WIDTH 1152#define CYBER8_HEIGHT 886#define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */#define CYBER16_WIDTH 800#define CYBER16_HEIGHT 600#define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */#define PALM_WIDTH 160#define PALM_HEIGHT 160/*static int mc68328Key = 0;static u_char mc68328_colour_table [256][4];*/static unsigned long mc68328Mem;static unsigned long mc68328Size;static long *memstart; /* * Predefined Video Mode Names */static char *mc68328_fb_modenames[] = { /* * Autodetect (Default) Video Mode */ "default", /* * Predefined Video Modes */ "Palm", /* Palm Pilot devices, 1.0 and higher */ "Palm Grey", /* Palm Pilot devices, 1.0 and higher */ /* * Dummy Video Modes */ "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", /* * User Defined Video Modes * * This doesn't work yet!! */ "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"}; /* * Predefined Video Mode Definitions */static struct fb_var_screeninfo mc68328_fb_predefined[] = { /* * Autodetect (Default) Video Mode */ { 0, }, /* * Predefined Video Modes */ { /* Palm */ PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, 0, 0, 1, -1, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0}, 0, 0, -1, -1, /* phys height, width */ FB_ACCEL_NONE, 0, 0, 0, 0, 0, 0, 0, /* timing */ 0, /* sync */ FB_VMODE_NONINTERLACED }, { /* Palm Grey */ PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT, 0, 0, 2, -1, {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, 0, 0, -1, -1, /* phys height, width */ FB_ACCEL_NONE, 0, 0, 0, 0, 0, 0, 0, /* timing */ 0, /* sync */ FB_VMODE_NONINTERLACED }, /* * Dummy Video Modes */ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, /* * User Defined Video Modes */ { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }};#define NUM_TOTAL_MODES arraysize(mc68328_fb_predefined)#define NUM_PREDEF_MODES (3)static int mc68328fb_inverse = 0;static int mc68328fb_mode = 0;static int mc68328fbCursorMode = 0; /* * Some default modes */#define PALM_DEFMODE (1)#define CYBER16_DEFMODE (2) /* * Interface used by the world */void mc68328_video_setup(char *options, int *ints);static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con);static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con);static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con);static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);static int mc68328_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con);static int mc68328_fb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con); /* * Interface to the low level console driver */struct fb_info *mc68328_fb_init(long *mem_start); /* Through amiga_fb_init() */static int mc68328fb_switch(int con);static int mc68328fb_updatevar(int con);static void mc68328fb_blank(int blank); /* * Accelerated Functions used by the low level console driver */void mc68328_WaitQueue(u_short fifo);void mc68328_WaitBlit(void);void mc68328_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty, u_short width, u_short height, u_short mode);void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height, u_short mode, u_short color);void mc68328_MoveCursor(u_short x, u_short y); /* * Hardware Specific Routines */static int mc68328_init(void);static int mc68328_encode_fix(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par);static int mc68328_decode_var(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);static int mc68328_encode_var(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp);static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp);static void mc68328_blank(int blank); /* * Internal routines */static void mc68328_fb_get_par(struct mc68328_fb_par *par);static void mc68328_fb_set_par(struct mc68328_fb_par *par);static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);static struct fb_cmap *get_default_colormap(int bpp);static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc);static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc);static void do_install_cmap(int con);static void memcpy_fs(int fsfromto, void *to, void *from, int len);static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);static void mc68328_fb_set_disp(int con);static int get_video_mode(const char *name);/* -------------------- 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 mc68328_init(void){ /*int i; char size; volatile u_long *CursorBase; unsigned long board_addr; struct ConfigDev *cd;*/ if (mc68328fb_mode == -1) mc68328fb_mode = PALM_DEFMODE; mc68328Mem = (*(volatile unsigned long*)0xFFFFFA00); /*kernel_map (board_addr + 0x01400000, 0x00400000,*/ mc68328Size = 160*160/8; #if 0*memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);mc68328Mem = kernel_map (board_addr + 0x01400000, 0x00400000, KERNELMAP_NOCACHE_SER, memstart);if (mc68328fb_mc683288) memset ((char*)mc68328Mem, 0, CYBER8_WIDTH * CYBER8_HEIGHT);else memset ((char*)mc68328Mem, 0, CYBER16_WIDTH * CYBER16_HEIGHT);mc68328Regs = (char*) kernel_map (board_addr + 0x02000000, 0xf000, KERNELMAP_NOCACHE_SER, memstart);/* Disable hardware cursor */*(mc68328Regs + S3_CRTC_ADR) = S3_REG_LOCK2;*(mc68328Regs + S3_CRTC_DATA) = 0xa0;*(mc68328Regs + S3_CRTC_ADR) = S3_HGC_MODE;*(mc68328Regs + S3_CRTC_DATA) = 0x00;*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_DX;*(mc68328Regs + S3_CRTC_DATA) = 0x00;*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_DY;*(mc68328Regs + S3_CRTC_DATA) = 0x00;/* Set clipping rectangle to current screen size */*((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x1000;*((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x2000;if (mc68328fb_mc683288) { *((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x3000 | (CYBER8_HEIGHT - 1); *((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x4000 | (CYBER8_WIDTH - 1); }else { *((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x3000 | (CYBER16_HEIGHT - 1); *((u_short volatile *)(mc68328Regs + 0xbee8)) = 0x4000 | (CYBER16_WIDTH - 1); }/* Get memory size (if not 2MB it is 4MB) */*(mc68328Regs + S3_CRTC_ADR) = S3_LAW_CTL;size = *(mc68328Regs + S3_CRTC_DATA);if ((size & 0x03) == 0x02) mc68328Size = 0x00200000; /* 2 MB */else mc68328Size = 0x00400000; /* 4 MB *//* Initialize hardware cursor */CursorBase = (u_long *)((char *)(mc68328Mem) + mc68328Size - 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; }mc68328_setcolreg (255, 56, 100, 160, 0);mc68328_setcolreg (254, 0, 0, 0, 0);#endifreturn (0);} /* * This function should fill in the `fix' structure based on the * values in the `par' structure. */static int mc68328_encode_fix(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par){ int i; strcpy(fix->id, mc68328_fb_name); fix->smem_start = mc68328Mem; fix->smem_len = mc68328Size; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; if (par->bpp == 1) fix->visual = FB_VISUAL_MONO01; else fix->visual = FB_VISUAL_DIRECTCOLOR; fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; for (i = 0; i < arraysize(fix->reserved); i++) fix->reserved[i] = 0; return(0);} /* * Get the video params out of `var'. If a value doesn't fit, round * it up, if it's too big, return -EINVAL. */static int mc68328_decode_var(struct fb_var_screeninfo *var, struct mc68328_fb_par *par){ par->xres = PALM_WIDTH; par->yres = PALM_HEIGHT; par->bpp = 1; return(0);} /* * Fill the `var' structure based on the values in `par' and maybe * other values read out of the hardware. */static int mc68328_encode_var(struct fb_var_screeninfo *var, struct mc68328_fb_par *par){ int i; var->xres = par->xres; var->yres = par->yres; var->xres_virtual = par->xres; var->yres_virtual = par->yres; var->xoffset = 0; var->yoffset = 0; var->bits_per_pixel = par->bpp; var->grayscale = -1; var->red.offset = 0; var->red.length = par->bpp; var->red.msb_right = 0; var->blue = var->green = var->red; var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; var->nonstd = 0; var->activate = 0; var->height = -1; var->width = -1; var->accel = FB_ACCEL_NONE; var->vmode = FB_VMODE_NONINTERLACED; /* Dummy values */ var->pixclock = 0; var->sync = 0; var->left_margin = 0; var->right_margin = 0; var->upper_margin = 0; var->lower_margin = 0; var->hsync_len = 0; var->vsync_len = 0; for (i = 0; i < arraysize(var->reserved); i++) var->reserved[i] = 0; 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 mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp){ return 1;#if 0if (regno > 255) return (1);*(mc68328Regs + 0x3c8) = (char)regno;mc68328_colour_table [regno][0] = red & 0xff;mc68328_colour_table [regno][1] = green & 0xff;mc68328_colour_table [regno][2] = blue & 0xff;mc68328_colour_table [regno][3] = transp;*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;return (0);#endif} /* * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. */static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp){ return 1;#if 0if (regno >= 256) return (1);*red = mc68328_colour_table [regno][0];*green = mc68328_colour_table [regno][1];*blue = mc68328_colour_table [regno][2];*transp = mc68328_colour_table [regno][3];return (0);#endif} /* * (Un)Blank the screen */void mc68328_blank(int blank){#if 0 if (blank) (*(volatile unsigned char*)0xFFFFFA27) &= ~128; else (*(volatile unsigned char*)0xFFFFFA27) |= 128;#endif}/************************************************************** * We are waiting for "fifo" FIFO-slots empty */void mc68328_WaitQueue (u_short fifo){}/************************************************************** * We are waiting for Hardware (Graphics Engine) not busy */void mc68328_WaitBlit (void){}/************************************************************** * BitBLT - Through the Plane */void mc68328_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, u_short width, u_short height, u_short mode){#if 0u_short blitcmd = S3_BITBLT;/* Set drawing direction *//* -Y, X maj, -X (default) */if (curx > destx) blitcmd |= 0x0020; /* Drawing direction +X */else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -