/* * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the * mc68328 LCD frame buffer device * * Copyright (C) 1998,1999 Kenneth Albanowski , * 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 * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #define arraysize(x) (sizeof(x)/sizeof(*(x))) static struct fb_info fb_info; /* * 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];*/ /* * 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,} }; static struct fb_fix_screeninfo mc68328_fix __initdata = { .id = "mc68328"; .smem_len = 160 * 160 /8; .type = FB_TYPE_PACKED_PIXELS; .accel = FB_ACCEL_NONE; }; #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 */ int mc68328_fb_init(void); static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp); static void mc68328fb_blank(int blank, struct fb_info *info); /* * 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); /* * Internal routines */ static int get_video_mode(const char *name); /* * 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 mc68328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp) { return 1; #if 0 if (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 } /* * (Un)Blank the screen */ static void mc68328fb_blank(int blank, struct fb_info *info) { #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 0 u_short blitcmd = S3_BITBLT; /* Set drawing direction */ /* -Y, X maj, -X (default) */ if (curx > destx) blitcmd |= 0x0020; /* Drawing direction +X */ else { curx += (width - 1); destx += (width - 1); } if (cury > desty) blitcmd |= 0x0080; /* Drawing direction +Y */ else { cury += (height - 1); desty += (height - 1); } mc68328_WaitQueue(0x8000); *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000; *((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) = (0x0060 | mode); *((u_short volatile *) (mc68328Regs + S3_CUR_X)) = curx; *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = cury; *((u_short volatile *) (mc68328Regs + S3_DESTX_DIASTP)) = destx; *((u_short volatile *) (mc68328Regs + S3_DESTY_AXSTP)) = desty; *((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1; *((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1; *((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd; #endif } /************************************************************** * Rectangle Fill Solid */ void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height, u_short mode, u_short color) { #if 0 u_short blitcmd = S3_FILLEDRECT; mc68328_WaitQueue(0x8000); *((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000; *((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) = (0x0020 | mode); *((u_short volatile *) (mc68328Regs + S3_MULT_MISC)) = 0xe000; *((u_short volatile *) (mc68328Regs + S3_FRGD_COLOR)) = color; *((u_short volatile *) (mc68328Regs + S3_CUR_X)) = x; *((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = y; *((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1; *((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1; *((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd; #endif } /************************************************************** * Move cursor to x, y */ void mc68328_MoveCursor(u_short x, u_short y) { (*(volatile unsigned short *) 0xFFFFFA18) = (mc68328fbCursorMode << 14) | x; (*(volatile unsigned short *) 0xFFFFFA1A) = y; #if 0 *(mc68328Regs + S3_CRTC_ADR) = 0x39; *(mc68328Regs + S3_CRTC_DATA) = 0xa0; *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H; *(mc68328Regs + S3_CRTC_DATA) = (char) ((x & 0x0700) >> 8); *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L; *(mc68328Regs + S3_CRTC_DATA) = (char) (x & 0x00ff); *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H; *(mc68328Regs + S3_CRTC_DATA) = (char) ((y & 0x0700) >> 8); *(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L; *(mc68328Regs + S3_CRTC_DATA) = (char) (y & 0x00ff); #endif } /* -------------------- Generic routines ------------------------------------ */ /* * Default Colormaps */ static u_short red16[] = { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000, 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff }; static u_short green16[] = { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff }; static u_short blue16[] = { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000, 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff }; static struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL }; static struct fb_cmap *get_default_colormap(int bpp) { return (&default_16_colors); } #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16) #define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \ ((1<<(width))-1)) : 0)) static struct fb_ops mc68328_fb_ops = { .owner = THIS_MODULE, .fb_setcolreg = mc68328fb_setcolreg, .fb_fillrect = cfbfillrect, .fb_copyarea = cfbcopyarea, .fb_imageblit = cfbimgblt, .fb_cursor = softcursor, }; /* * Initialization */ int __init mc68328_fb_init(void) { if (mc68328fb_mode == -1) mc68328fb_mode = PALM_DEFMODE; mc68328_fix.smem_start = (*(volatile unsigned long *) 0xFFFFFA00); /*kernel_map (board_addr + 0x01400000, 0x00400000, */ info->var = mc68328_fb_predefined[mc68328fb_mode]; if (info->var.bits_per_pixel == 1) fix->visual = FB_VISUAL_MONO01; else fix->visual = FB_VISUAL_DIRECTCOLOR; info->screen_base = (u_char *) mc68328_fix.smem_start; if (register_framebuffer(&fb_info) < 0) panic("Cannot register frame buffer\n"); return 0; } /* * Get a Video Mode */ static int get_video_mode(const char *name) { int i; for (i = 1; i < NUM_PREDEF_MODES; i++) if (!strcmp(name, mc68328_fb_modenames[i])) return (i); return (0); }