📄 clgenfb.c
字号:
{0, 0, 0}, 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 128, 16, 24, 2, 96, 6, 0, FB_VMODE_NONINTERLACED } }, /* Modeline from XF86Config: Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 */ {"1024x768", /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ { 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_ACCEL_NONE, 12500, 144, 32, 30, 2, 192, 6, 0, FB_VMODE_NONINTERLACED } }};#define NUM_TOTAL_MODES ARRAY_SIZE(clgenfb_predefined)static struct fb_var_screeninfo clgenfb_default;/* * Frame Buffer Name */static const char *clgenfb_name = "CLgen";/****************************************************************************//**** BEGIN PROTOTYPES ******************************************************//*--- Interface used by the world ------------------------------------------*/int clgenfb_init (void);int clgenfb_setup (char *options);static int clgenfb_open (struct fb_info *info, int user);static int clgenfb_release (struct fb_info *info, int user);/* function table of the above functions */static struct fb_ops clgenfb_ops = { owner: THIS_MODULE, fb_open: clgenfb_open, fb_release: clgenfb_release, fb_get_fix: fbgen_get_fix, fb_get_var: fbgen_get_var, fb_set_var: fbgen_set_var, fb_get_cmap: fbgen_get_cmap, fb_set_cmap: fbgen_set_cmap, fb_pan_display: fbgen_pan_display,};/*--- Hardware Specific Routines -------------------------------------------*/static void clgen_detect (void);static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info);static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info);static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info);static void clgen_get_par (void *par, struct fb_info_gen *info);static void clgen_set_par (const void *par, struct fb_info_gen *info);static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info);static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);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_disp (const void *par, struct display *disp, struct fb_info_gen *info);/* function table of the above functions */static struct fbgen_hwswitch clgen_hwswitch ={ clgen_detect, clgen_encode_fix, clgen_decode_var, clgen_encode_var, clgen_get_par, clgen_set_par, clgen_getcolreg, clgen_setcolreg, clgen_pan_display, clgen_blank, clgen_set_disp};/* Text console acceleration */#ifdef FBCON_HAS_CFB8static void fbcon_clgen8_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width);static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width);static struct display_switch fbcon_clgen_8 = { setup: fbcon_cfb8_setup, bmove: fbcon_clgen8_bmove, clear: fbcon_clgen8_clear, putc: fbcon_cfb8_putc, putcs: fbcon_cfb8_putcs, revc: fbcon_cfb8_revc, clear_margins: fbcon_cfb8_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)};#endif#ifdef FBCON_HAS_CFB16static void fbcon_clgen16_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width);static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width);static struct display_switch fbcon_clgen_16 = { setup: fbcon_cfb16_setup, bmove: fbcon_clgen16_bmove, clear: fbcon_clgen16_clear, putc: fbcon_cfb16_putc, putcs: fbcon_cfb16_putcs, revc: fbcon_cfb16_revc, clear_margins: fbcon_cfb16_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)};#endif#ifdef FBCON_HAS_CFB32static void fbcon_clgen32_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width);static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width);static struct display_switch fbcon_clgen_32 = { setup: fbcon_cfb32_setup, bmove: fbcon_clgen32_bmove, clear: fbcon_clgen32_clear, putc: fbcon_cfb32_putc, putcs: fbcon_cfb32_putcs, revc: fbcon_cfb32_revc, clear_margins: fbcon_cfb32_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)};#endif/*--- Internal routines ----------------------------------------------------*/static void init_vgachip (struct clgenfb_info *fb_info);static void switch_monitor (struct clgenfb_info *fb_info, int on);static void WGen (const struct clgenfb_info *fb_info, int regnum, unsigned char val);static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);static void AttrOn (const struct clgenfb_info *fb_info);static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);static void WSFR (struct clgenfb_info *fb_info, unsigned char val);static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue);#if 0static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue);#endifstatic void clgen_WaitBLT (caddr_t regbase);static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty, u_short width, u_short height, u_short line_length);static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y, u_short width, u_short height, u_char color, u_short line_length);static void bestclock (long freq, long *best, long *nom, long *den, long *div, long maxfreq);#ifdef CLGEN_DEBUGstatic void clgen_dump (void);static void clgen_dbg_reg_dump (caddr_t regbase);static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);static void clgen_dbg_print_byte (const char *name, unsigned char val);#endif /* CLGEN_DEBUG *//*** END PROTOTYPES ********************************************************//*****************************************************************************//*** BEGIN Interface Used by the World ***************************************/static int opencount = 0;/*--- Open /dev/fbx ---------------------------------------------------------*/static int clgenfb_open (struct fb_info *info, int user){ if (opencount++ == 0) switch_monitor ((struct clgenfb_info *) info, 1); return 0;}/*--- Close /dev/fbx --------------------------------------------------------*/static int clgenfb_release (struct fb_info *info, int user){ if (--opencount == 0) switch_monitor ((struct clgenfb_info *) info, 0); return 0;}/**** END Interface used by the World *************************************//****************************************************************************//**** BEGIN Hardware specific Routines **************************************/static void clgen_detect (void){ DPRINTK ("ENTER\n"); DPRINTK ("EXIT\n");}static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info){ struct clgenfb_par *_par = (struct clgenfb_par *) par; struct clgenfb_info *_info = (struct clgenfb_info *) info; DPRINTK ("ENTER\n"); memset (fix, 0, sizeof (struct fb_fix_screeninfo)); strcpy (fix->id, clgenfb_name); if (_info->btype == BT_GD5480) { /* Select proper byte-swapping aperture */ switch (_par->var.bits_per_pixel) { case 1: case 8: fix->smem_start = _info->fbmem_phys; break; case 16: fix->smem_start = _info->fbmem_phys + 1 * MB_; break; case 24: case 32: fix->smem_start = _info->fbmem_phys + 2 * MB_; break; } } else { fix->smem_start = _info->fbmem_phys; } /* monochrome: only 1 memory plane */ /* 8 bit and above: Use whole memory area */ fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4 : _info->size; fix->type = _par->type; fix->type_aux = 0; fix->visual = _par->visual; fix->xpanstep = 1; fix->ypanstep = 1; fix->ywrapstep = 0; fix->line_length = _par->line_length; /* FIXME: map region at 0xB8000 if available, fill in here */ fix->mmio_start = 0; fix->mmio_len = 0; fix->accel = FB_ACCEL_NONE; DPRINTK ("EXIT\n"); return 0;}/* Get a good MCLK value */static long clgen_get_mclk (long freq, int bpp, long *div){ long mclk; assert (div != NULL); /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. * Assume a 64-bit data path for now. The formula is: * ((B * PCLK * 2)/W) * 1.2 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ mclk = ((bpp / 8) * freq * 2) / 4; mclk = (mclk * 12) / 10; if (mclk < 50000) mclk = 50000; DPRINTK ("Use MCLK of %ld kHz\n", mclk); /* Calculate value for SR1F. Multiply by 2 so we can round up. */ mclk = ((mclk * 16) / 14318); mclk = (mclk + 1) / 2; DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk); /* Determine if we should use MCLK instead of VCLK, and if so, what we * should divide it by to get VCLK */ switch (freq) { case 24751 ... 25249: *div = 2; DPRINTK ("Using VCLK = MCLK/2\n"); break; case 49501 ... 50499: *div = 1; DPRINTK ("Using VCLK = MCLK\n"); break; default: *div = 0; break; } return mclk;}static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info){ long freq; long maxclock; int xres, hfront, hsync, hback; int yres, vfront, vsync, vback; int nom, den; /* translyting from pixels->bytes */ int i; static struct { int xres, yres; } modes[] = { { 1600, 1280 }, { 1280, 1024 }, { 1024, 768 }, { 800, 600 }, { 640, 480 }, { -1, -1 } }; struct clgenfb_par *_par = (struct clgenfb_par *) par; struct clgenfb_info *fb_info = (struct clgenfb_info *) info; assert (var != NULL); assert (par != NULL); assert (info != NULL); DPRINTK ("ENTER\n"); DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); DPRINTK (" virtual: %dx%d\n", var->xres_virtual, var->yres_virtual); DPRINTK (" offset: (%d,%d)\n", var->xoffset, var->yoffset); DPRINTK ("grayscale: %d\n", var->grayscale); memset (par, 0, sizeof (struct clgenfb_par)); _par->var = *var; switch (var->bits_per_pixel) { case 1: nom = 4; den = 8; break; /* 8 pixel per byte, only 1/4th of mem usable */ case 2 ... 8: _par->var.bits_per_pixel = 8; nom = 1; den = 1; break; /* 1 pixel == 1 byte */ case 9 ... 16: _par->var.bits_per_pixel = 16; nom = 2; den = 1; break; /* 2 bytes per pixel */ case 17 ... 24: _par->var.bits_per_pixel = 24; nom = 3; den = 1; break; /* 3 bytes per pixel */ case 25 ... 32: _par->var.bits_per_pixel = 32; nom = 4; den = 1; break; /* 4 bytes per pixel */ default: printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n", var->xres, var->yres, var->bits_per_pixel); DPRINTK ("EXIT - EINVAL error\n"); return -EINVAL; } if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) { printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", var->xres, var->yres, var->bits_per_pixel); DPRINTK ("EXIT - EINVAL error\n"); return -EINVAL; } /* use highest possible virtual resolution */ if (_par->var.xres_virtual == -1 && _par->var.yres_virtual == -1) { printk ("clgen: using maximum available virtual resolution\n"); for (i = 0; modes[i].xres != -1; i++) { if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2) break; } if (modes[i].xres == -1) { printk ("clgen: could not find a virtual resolution that fits into video memory!!\n"); DPRINTK ("EXIT - EINVAL error\n"); return -EINVAL; } _par->var.xres_virtual = modes[i].xres; _par->var.yres_virtual = modes[i].yres; printk ("clgen: virtual resolution set to maximum of %dx%d\n", _par->var.xres_virtual, _par->var.yres_virtual); } else if (_par->var.xres_virtual == -1) { /* FIXME: maximize X virtual resolution only */ } else if (_par->var.yres_virtual == -1) { /* FIXME: maximize Y virtual resolution only */ } if (_par->var.xoffset < 0) _par->var.xoffset = 0; if (_par->var.yoffset < 0) _par->var.yoffset = 0; /* truncate xoffset and yoffset to maximum if too high */ if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres) _par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1; if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres) _par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1; switch (_par->var.bits_per_pixel) { case 1: _par->line_length = _par->var.xres_virtual / 8; _par->visual = FB_VISUAL_MONO10; break; case 8: _par->line_length = _par->var.xres_virtual; _par->visual = FB_VISUAL_PSEUDOCOLOR; _par->var.red.offset = 0; _par->var.red.length = 6; _par->var.green.offset = 0; _par->var.green.length = 6; _par->var.blue.offset = 0; _par->var.blue.length = 6; break; case 16: _par->line_length = _par->var.xres_virtual * 2; _par->visual = FB_VISUAL_DIRECTCOLOR; if(isPReP) { _par->var.red.offset = 2; _par->var.green.offset = -3; _par->var.blue.offset = 8; } else { _par->var.red.offset = 10; _par->var.green.offset = 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -