📄 sstfb.c
字号:
fb_set_cmap( fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1, sstfb_setcolreg, info);}static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info){ f_ddprintk("sstfb_getcolreg\n"); if (regno >= 16) return 1; *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = palette[regno].transp; f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", regno,*red, *green, *blue, *transp); return 0;}static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ u32 col; f_ddprintk("sstfb_setcolreg\n"); f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", regno, red, green, blue, transp); if (regno >= 16) return 1; palette[regno].red = red; palette[regno].green = green; palette[regno].blue = blue; red >>= (16 - disp.var.red.length); green >>= (16 - disp.var.green.length); blue >>= (16 - disp.var.blue.length); transp >>= (16 - disp.var.transp.length); col = (red << disp.var.red.offset) | (green << disp.var.green.offset) | (blue << disp.var.blue.offset) | (transp << disp.var.transp.offset); switch(disp.var.bits_per_pixel) {#ifdef FBCON_HAS_CFB16 case 16: fbcon_cmap.cfb16[regno]=(u16)col; break;#endif#ifdef EN_24_32_BPP#ifdef FBCON_HAS_CFB24 case 24: fbcon_cmap.cfb32[regno]=col; break;#endif#ifdef FBCON_HAS_CFB32 case 32: fbcon_cmap.cfb32[regno]=col; break;#endif#endif default: eprintk("bug line %d: bad depth '%u'\n",__LINE__, disp.var.bits_per_pixel); break; } f_dddprintk("bpp: %d . encoded color: %#x\n", disp.var.bits_per_pixel, col); return 0;}/* set par according to var ( checks var ) */static int sstfb_decode_var (const struct fb_var_screeninfo *var, struct sstfb_par *par, const struct sstfb_info *sst_info){ int real_length; f_dprintk("sstfb_decode_var\n"); /* Check var validity */ if ((var->xres > 1024) || (!var->xres) || (!var->xres)) { eprintk ("Unsupported resolution %dx%d\n", var->xres, var->yres); return -EINVAL; } if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) { eprintk("Interlace non supported %#x\n", (var->vmode & FB_VMODE_MASK)); return -EINVAL; } memset(par, 0, sizeof(par)); par->xDim = var->xres; par->hSyncOn = var->hsync_len; par->hSyncOff = var->xres + var->right_margin + var->left_margin; par->hBackPorch = var->left_margin; par->yDim = var->yres; par->vSyncOn = var->vsync_len; par->vSyncOff = var->yres + var->lower_margin + var->upper_margin; par->vBackPorch = var->upper_margin; switch (var->bits_per_pixel) { case 0 ... 16 : par->bpp = 16; break;#ifdef EN_24_32_BPP case 17 ... 24 : par->bpp = 24; break; case 25 ... 32 : par->bpp = 32; break;#endif default : eprintk ("Unsupported bpp %d\n", par->bpp); return -EINVAL; break; } if (sst_info->is_voodoo2) { /* voodoo2 has 32 pixel wide tiles , BUT stange things happen with odd number of tiles */ par->tiles_in_X= (par->xDim + 63 ) / 64 * 2; } else { /* voodoo1 has 64 pixels wide tiles. */ par->tiles_in_X= (par->xDim + 63 ) / 64; } /* * mem check */ /* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem*/ /* FIXME: i don't like this... looks wrong*/ real_length = par->tiles_in_X * (sst_info->is_voodoo2 ? 32 : 64 ) * ((par->bpp == 16) ? 2 : 4);/*shoud this function change var ? for instance with yvirt > yres ?*/ if ((real_length * var->yres) > fb_info.video.len) { eprintk ("Not enough video memory\n"); return -ENOMEM; } par->freq = PS2KHZ(var->pixclock); /* TODO add checks for timings */ return 0;}/* sets var according to par (basicaly, sets sane values) */static int sstfb_encode_var (struct fb_var_screeninfo *var, const struct sstfb_par *par, const struct sstfb_info *sst_info){ memset(var,0,sizeof(struct fb_var_screeninfo)); var->xres = par->xDim; var->yres = par->yDim; var->xres_virtual = par->xDim; var->yres_virtual = par->yDim; var->bits_per_pixel = par->bpp; /* {x|y}offset = 0 ; sync=0 */ var->height = -1; var->width = -1; var->pixclock = KHZ2PS(par->freq); var->left_margin = par->hBackPorch; var->right_margin = par->hSyncOff - par->xDim - par->hBackPorch; var->upper_margin = par->vBackPorch; var->lower_margin = par->vSyncOff - par->yDim - par->vBackPorch; var->hsync_len = par->hSyncOn; var->vsync_len = par->vSyncOn; var->vmode = FB_VMODE_NONINTERLACED; /* * correct the color bit fields */ /* var->{red|green|blue}.msb_right = 0; */ switch (par->bpp) { case 16: /* RGB 565 LfbMode 0 */ var->red.length = 5; var->green.length = 6; var->blue.length = 5; var->transp.length = 0; var->red.offset = 11; var->green.offset = 5; var->blue.offset = 0; var->transp.offset = 0; break;#ifdef EN_24_32_BPP case 24: /* RGB 888 LfbMode 4 */ case 32: /* ARGB 8888 LfbMode 5 */ var->red.length = 8; var->green.length = 8; var->blue.length = 8; var->transp.length = 0; var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */ break;#endif default: eprintk ("bug line %d: bad depth '%u'\n", __LINE__, par->bpp); break; } return 0;}/* * Frame buffer API */static int sstfb_open(struct fb_info *info, int user){ f_dprintk("sstfb_open(user: %d)\n",user); MOD_INC_USE_COUNT; return 0;}static int sstfb_release(struct fb_info *info, int user){ f_dprintk("sstfb_release(user: %d)\n",user); MOD_DEC_USE_COUNT; return 0;}static int sstfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) struct fb_var_screeninfo *var; f_dprintk("sstfb_get_fix(con: %d)\n",con); if (con == -1) var = &sstfb_default; else var = &fb_display[con].var; strcpy(fix->id, sst_info->info.modename); /* lfb phys address = membase + 4Mb */ fix->smem_start = sst_info->video.base; fix->smem_len = sst_info->video.len; fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_TRUECOLOR; /* * According to the specs, the linelength must be of 1024 *pixels*. * and the 24bpp mode is in fact a 32 bpp mode. */ fix->line_length = (var->bits_per_pixel == 16) ? 2048 : 4096 ; return 0;#undef sst_info}static int sstfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ f_dprintk("sstfb_get_var(con: %d)\n",con); if (con == -1) *var = sstfb_default; else *var = fb_display[con].var; print_var(var, "var"); return 0; }static int sstfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) struct sstfb_par par; struct display *display; int err; int old_bpp,old_xres,old_yres; f_dprintk("sstfb_set_var(con: %d)\n",con); f_ddprintk("xres yres vxres vyres bpp activate\n"); f_ddprintk("%-4d %-4d %-5d %-5d %-3d %#-8x\n", var->xres,var->yres,var->xres_virtual,var->yres_virtual, var->bits_per_pixel,var->activate); if (con < 0) display = &disp; else display = &fb_display[con]; err = sstfb_decode_var(var, &par, sst_info); if (err) return err; sstfb_encode_var (var, &par, sst_info); switch (var->activate & FB_ACTIVATE_MASK) { case FB_ACTIVATE_TEST: return 0; case FB_ACTIVATE_NXTOPEN: case FB_ACTIVATE_NOW: break; default: return -EINVAL; } old_xres = display->var.xres; old_yres = display->var.yres; old_bpp = display->var.bits_per_pixel; display->var = *var; if ((old_xres != var->xres) || (old_yres != var->yres) || (old_bpp != var->bits_per_pixel)) { /* 2-3 lignes redondantes avec get_fix */ display->screen_base = (char *) sst_info->video.vbase; display->visual = FB_VISUAL_TRUECOLOR; display->type = FB_TYPE_PACKED_PIXELS; display->type_aux = 0; display->ypanstep = 0; display->ywrapstep = 0; display->line_length = (var->bits_per_pixel==16) ? 2048 : 4096; display->inverse = 0; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; display->dispsw_data = fbcon_cmap.cfb16; break;#endif#ifdef EN_24_32_BPP#if defined (FBCON_HAS_CFB24) || defined (FBCON_HAS_CFB32 ) case 24: /*24bpp non packed <=> 32 bpp */ case 32: display->dispsw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break;#endif#endif default: display->dispsw = &fbcon_dummy; break; } display->scrollmode = SCROLL_YREDRAW; if (sst_info->info.changevar) { v_dprintk("fb_info.changevar(con: %d)\n", con); (*sst_info->info.changevar)(con); v_dprintk("fb_info.changevar: done \n"); } else { v_dprintk("fb_info.changevar() == NULL . \n"); } } if ((con <0) || (con==currcon)) { sstfb_set_par (&par, sst_info); } print_var(var, "var"); print_var(&display->var, "&display->var"); if (old_bpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; sstfb_install_cmap(con, info); } return 0;#undef sst_info}static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct display *d = (con<0) ? info->disp : fb_display + con; f_dprintk("sstfb_set_cmap\n"); f_ddprintk("con: %d, currcon: %d, d->cmap.len %d\n", con, currcon, d->cmap.len); if (d->cmap.len != 16 ) { /* or test if cmap.len == 0 ? */ int err; err = fb_alloc_cmap(&d->cmap, 16, 0); /* cmap size=16 */ if (err) return err; } if (con == currcon) { return fb_set_cmap(cmap, kspc, sstfb_setcolreg, info); } else { fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1); } return 0;}static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ f_dprintk("sstfb_get_cmap\n"); f_ddprintk("con %d, curcon %d, cmap.len %d\n", con, currcon, fb_display[con].cmap.len); /* FIXME: check if con = -1 ? cf sstfb_set_cmap... */ if (con == currcon) return fb_get_cmap(cmap, kspc, sstfb_getcolreg, info); else if (fb_display[con].cmap.len) 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;}/* TODO */static int sstfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info){ f_dprintk("sstfb_pan_display\n"); return -EINVAL;}static int sstfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) #if (SST_DEBUG_IOCTL >0) int i; u_long p; u32 tmp; u32 fbiinit0; struct pci_dev * sst_dev = sst_info->dev;#endif f_dprintk("sstfb_ioctl(%x)\n", cmd);#if (SST_DEBUG_IOCTL >0) switch (cmd) {# if (SST_DEBUG_VAR >0)/* tmp ioctl : dumps fb_display[0-5] */ case _IO('F', 0xdb): /* 0x46db */ f_dprintk("dumping fb_display[0-5].var\n"); for (i = 0 ; i< 6 ; i++) { print_var(&fb_display[i].var, "var(%d)", i); } return 0;# endif /* (SST_DEBUG_VAR >0) *//* fills the lfb up to *(u32*)arg */ case _IOW('F', 0xdc, u32): /* 0x46dc */ if (*(u32*)arg > 0x400000 ) *(u32*) arg = 0x400000; f_dprintk("filling %#x \n", *(u32*)arg); for (p = 0 ; p < *(u32*)arg; p+=2) writew( p >> 6 , sst_info->video.vbase + p); return 0;/* change VGA pass_through */ case _IOW('F', 0xdd, u32): /* 0x46dd */ f_dprintk("switch VGA pass-through\n"); pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp); pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp | PCI_EN_INIT_WR ); fbiinit0 = sst_read (FBIINIT0); if (* (u32*)arg) { sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH); iprintk ( "Disabling VGA pass-through\n"); } else { sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH); iprintk ( "Enabling VGA pass-through\n"); } pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); return 0; case _IO('F', 0xde): /* 0x46de */ f_dprintk("test color display\n"); f_ddprintk("currcon: %d, bpp %d\n", currcon, fb_display[currcon].var.bits_per_pixel); memset_io(sst_info->video.vbase, 0, sst_info->video.len); switch (fb_display[currcon].var.bits_per_pixel) {/* FIXME broken : if we call this ioctl from a tty not bound to the fb, we use its depth and not the current one ... */ case 16: sstfb_test16(sst_info); break;# ifdef EN_24_32_BPP case 24: case 32: sstfb_test32(sst_info); break;# endif default: dprintk("bug line %d: bad depth '%u'\n", __LINE__, fb_display[currcon].var.bits_per_pixel); } return 0; }#endif /* (SST_DEBUG_IOCTL >0) */ return -EINVAL;#undef sst_info}/* * Low level routines *//* get lfb size */static int sst_get_memsize(u_long *memsize){ u32 fbbase_virt = fb_info.video.vbase; f_dprintk("sst_get_memsize\n"); /* force memsize */ if ((mem >= 1 ) && (mem <= 4)) { *memsize = (mem * 0x100000); iprintk("supplied memsize: %#lx\n", *memsize); return 1; } writel (0xdeadbeef, fbbase_virt); writel (0xdeadbeef, fbbase_virt+0x100000); writel (0xdeadbeef, fbbase_virt+0x200000); f_ddprintk("0Mb: %#x, 1Mb: %#x, 2Mb: %#x\n", readl(fbbase_virt), readl(fbbase_virt + 0x100000), readl(fbbase_virt + 0x200000));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -