📄 dragonfb.c
字号:
/* * linux/drivers/video/dragonfb.c -- Frame Buffer driver for the 68EZ328 & 68VZ328 * * (C) 03 Dec 2001 by Khaled Hassounah <khassounah@mediumware.net> * * Contributors: * * 29 March 2002 by Daniel Haensse <daniel.haensse@alumni.ethz.ch), * added support for the 68vz328 and some minor changes * * Following are few comments about this driver, if you fix any of the issues * please remove them from this list: * * 1) Most of the components to support the standard frame buffer console * exist, but it hasn't been tested before. So probably you'll need to * do some debugging before you get working * * 2) The LCD settings (resolution, color depth, etc.) have been dealt with * as configuration settings as opposed to user settings because we are * with an LCD in which those settings are mostly constant * * 3) The driver has been tested on a 68EZ328 with a 320X240 monochrome * LCD. * * 4) No color support yet, I'll try to work on it, if you get this version * check again later (or check again ;-) and you might find it, otherwise * maybe you want to make some smiles in the open source community and do * it yourself ;-) * * 5) This is effort is much less than perfect, so have fun :) * * 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/fb.h>#include <linux/init.h>#include <video/fbcon.h>#include <video/fbcon-mfb.h>// include display controller specific stuff, be aware of the differences#if defined(CONFIG_M68EZ328)#include <asm/MC68EZ328.h>#elif defined(CONFIG_M68VZ328)#include <asm/MC68VZ328.h>#endif//#define DEBUG//const int config_xres = 0;//const int config_yres = 0;//const int config_bpp = 0;//const int config_buswidth = 0;// Define diplay type#if defined(CONFIG_UG24U01WGHT3L) // Display driving #define X_RES 240 // X-Size #define Y_RES 320 // Y-Size #define REFRATE 20 // See motorola manual LRRA #define PIXRATE 0 // See motorola manual LPXCD #define ACRATE 0x00 // See motorola manual LACDRC #define GRAYSCALE 0x73 // See motorola manual LGPMR #define POLARITY 0x00 // See motorola manual LPOLCF #define BUSWIDTH_LPICF 0x08 // LPICF: 4 bit interface, 1bit = 0x00, 2bit=0x04, 4bit= 0x08, 8bit= 0x0c (VZ only)#elif define(CONFIG_UG24U03WGHT3A) // Display driving #define X_RES 320 // X-Size #define Y_RES 240 // Y-Size #define REFRATE 20 // See motorola manual LRRA #define PIXRATE 0 // See motorola manual LPXCD #define ACRATE 0x00 // See motorola manual LACDRC #define GRAYSCALE 0x73 // See motorola manual LGPMR #define POLARITY 0x00 // See motorola manual LPOLCF #define BUSWIDTH_LPICF 0x08 // LPICF: 4 bit interface, 1bit = 0x00, 2bit=0x04, 4bit= 0x08, 8bit= 0x0c (VZ only)#elif define(CONFIG_UG32F24CMGF3A) // Display driving #define X_RES 960 // X-Size 320xRGB #define Y_RES 240 // Y-Size #define REFRATE 20 // See motorola manual LRRA #define PIXRATE 1 // See motorola manual LPXCD #define ACRATE 0x00 // See motorola manual LACDRC #define GRAYSCALE 0x73 // See motorola manual LGPMR #define POLARITY 0x00 // See motorola manual LPOLCF #define BUSWIDTH_LPICF 0x0c // LPICF: 4 bit interface, 1bit = 0x00, 2bit=0x04, 4bit= 0x08, 8bit= 0x0c (VZ only)#endif#if defined(CONFIG_FB_DRAGON_MONO) #define BPP 1 #define GRAY_LPICF 0x00#elif defined(CONFIG_FB_DRAGON_4GRAY) #define BPP 2 #define GRAY_LPICF 0x01#elif defined(CONFIG_FB_DRAGON_16GRAY) // Well 16GRAY does not mean that we can use 16 gray scales, we have a better resolution of the pixel density only #define BPP 2 #define GRAY_LPICF 0x02#endif/* few useful macros */#define LINE_LENGTH(x, bpp) (((x*bpp+31)&-32)>>3)#define LENGTH(x, y, bpp) (x * y * bpp / 8)/* The video ram, which should be declared in the linker script */extern int __vram_start;/* few structs holding default or initialization info */static struct fb_info fb_info;static struct display disp;static int display_initialized[MAX_NR_CONSOLES];static struct fb_var_screeninfo default_var = { xres: X_RES, /* until I define the mechanism for passing resolutions */ yres: Y_RES, /* ditto */ /* Dragonballs (EZ & VZ) support virtual screen, but I'm in a hurry to implement it, if you need it, check out the the LVPW register and add the support, it should be pretty easy, all you need is to modify the dragon_set_var method to allow it */ xres_virtual: X_RES, /* too early for virtual support */ yres_virtual: Y_RES, /* ditto */ xoffset: 0, /* ditto */ yoffset: 0, /* ditto */ bits_per_pixel: BPP, /* see xres */ grayscale: 0, /* now monochrome tomorrow grayscale :-) */ red: {0,1,0}, /* only length is needed (not true color) */ green: {0,1,0}, /* ditto */ blue: {0,1,0}, /* ditto */ transp: {0,0,0}, /* we don't support transparency */ activate: FB_ACTIVATE_NOW, height: -1, /* is this really important? might be */ width: -1, /* later */ accel_flags: FB_ACCEL_NONE, vmode: FB_VMODE_NONINTERLACED,};static struct fb_fix_screeninfo current_fix = { id: "Dragon", smem_start: (__u32)&__vram_start, /* initially, we'll fill it later */ smem_len: LENGTH(X_RES, Y_RES, BPP), /* initially, we'll fill it later */ type: FB_TYPE_PACKED_PIXELS, /* this should always be true for dragonballs */ visual: FB_VISUAL_MONO10, /* this should depend on LCD used */ line_length: LINE_LENGTH(X_RES, BPP), accel: FB_ACCEL_NONE, /* but still like a breeze ;-) */};static int currcon = 0;/*int dragon_fb_init(void);int dragon_fb_setup(char*);*//* ------------------- chipset specific functions -------------------------- */static void set_color_bitfields(struct fb_var_screeninfo *var){ switch (var->bits_per_pixel) { case 1: var->red.offset = 0; var->red.length = 1; var->green.offset = 0; var->green.length = 1; var->blue.offset = 0; var->blue.length = 1; var->transp.offset = 0; var->transp.length = 0; break; 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: /* RGB 565 */ var->red.offset = 0; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 11; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break; case 24: /* RGB 888 */ 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 = 0; var->transp.length = 0; break; case 32: /* RGBA 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;}static int dragon_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){#if defined(DEBUG) printk(KERN_DEBUG "fb%d: start: dragon_getcolreg\n", GET_FB_IDX(fb_info.node));#endif /* * 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. */ /* ... */ return 0;}static int dragon_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ /* * Set a single color register. The values supplied have a 16 bit * magnitude. * Return != 0 for invalid regno. */#if defined(DEBUG) printk(KERN_DEBUG "fb%d: start: dragon_setcolreg\n", GET_FB_IDX(fb_info.node));#endif#if 0 if (regno < 16) { /* * Make the first 16 colors of the palette available to fbcon */ if (is_cfb15) /* RGB 555 */ ...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); if (is_cfb16) /* RGB 565 */ ...fbcon_cmap.cfb16[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); if (is_cfb24) /* RGB 888 */ ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); if (is_cfb32) /* RGBA 8888 */ ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) | ((green & 0xff00) << 8) | (blue & 0xff00) | ((transp & 0xff00) >> 8); }#endif /* ... */ return 0;} /* * Get the Colormap */static int dragon_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, dragon_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 dragon_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, dragon_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); 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, vfb_setcolreg, info); else fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1, vfb_setcolreg, info);*/}/* ------------------- fbcon specific functions -------------------------- */static int dragoncon_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, dragon_getcolreg, info);*/ currcon = con; /* Install new colormap */ do_install_cmap(con, info); return 0;}static int dragoncon_updatevar(int con, struct fb_info *info){ /* Nothing */ return 0;}static void dragoncon_blank(int blank_mode, struct fb_info *info){#if defined(DEBUG) printk(KERN_DEBUG "fb%d: start: dragon_blank\n", GET_FB_IDX(fb_info.node));#endif /* * Blank the screen if blank_mode != 0, else unblank. If blank == NULL * then the caller blanks by setting the CLUT (Color Look Up Table) to all * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due * to e.g. a video mode which doesn't support it. Implements VESA suspend * and powerdown modes on hardware that supports disabling hsync/vsync: * blank_mode == 2: suspend vsync * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown */ /* The display must be driven all the time, otherwise a DC voltage builds up which destroy the crystal put we can disable the display (if it has that function) and switch off the backlight */ if (blank_mode == 0) // Add your code here, for normal operation {#if defined(CONFIG_DRAGONIXVZ) PBDATA=(PBDATA&~0x80)|0x40; // Display on, backlight on#endif#endif } else // add your code here to save power and save the forest {#if defined(CONFIG_DRAGONIXVZ) PBDATA=(PBDATA&~0x40)|0x80; // Display on, backlight on#endif#endif }}static void dragon_initialize_display(struct display *disp){#if defined(DEBUG) printk(KERN_DEBUG "fb: start: dragon_initialize_display\n");#endif disp->screen_base = fb_info.screen_base;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -