?? sstfb.c
字號:
static void __sst_dac_write(u_long vbase, u8 reg, u8 val){ r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);#ifdef SST_DEBUG if ((reg & 0x07) != reg) dprintk("bug line %d: register adress '%d' is too high\n", __LINE__,reg);#endif reg &= 0x07; __sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);}/* indexed access to ti/att dacs */static u32 __dac_i_read(u_long vbase, u8 reg){ u32 ret; __sst_dac_write(vbase, DACREG_ADDR_I, reg); ret = __sst_dac_read(vbase, DACREG_DATA_I); r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret); return ret;}static void __dac_i_write(u_long vbase, u8 reg,u8 val){ r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val); __sst_dac_write(vbase, DACREG_ADDR_I, reg); __sst_dac_write(vbase, DACREG_DATA_I, val);}/* * * Internal routines * */static void sstfb_install_cmap(int con, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) f_dprintk("sstfb_install_cmap(con: %d)\n",con); f_ddprintk("currcon: %d\n", sst_info->currcon); if (con != sst_info->currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, 1, sstfb_setcolreg, info); else fb_set_cmap( fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1, sstfb_setcolreg, info);#undef sst_info}static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) f_dddprintk("sstfb_getcolreg\n"); if (regno >= 16) return 1; *red = sst_info->palette[regno].red; *green = sst_info->palette[regno].green; *blue = sst_info->palette[regno].blue; *transp = sst_info->palette[regno].transp; f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", regno,*red, *green, *blue, *transp); return 0;#undef sst_info}static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){#define sst_info ((struct sstfb_info *) info) u32 col; struct display * disp; f_dddprintk("sstfb_setcolreg\n"); f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", regno, red, green, blue, transp); if (regno >= 16) return 1; sst_info->palette[regno].red = red; sst_info->palette[regno].green = green; sst_info->palette[regno].blue = blue; sst_info->palette[regno].transp= transp; disp=&sst_info->disp; 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: sst_info->fbcon_cmap.cfb16[regno]=(u16)col; break;#endif#ifdef EN_24_32_BPP#ifdef FBCON_HAS_CFB24 case 24: sst_info->fbcon_cmap.cfb32[regno]=col; break;#endif#ifdef FBCON_HAS_CFB32 case 32: sst_info->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;#undef sst_info}/* 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 */ par->valid=0; 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; if(sst_calc_pll (PS2KHZ(var->pixclock), &par->freq, &par->pll)) { eprintk("Pixclock %d out of range\n", var->pixclock); return -EINVAL; //XXX } par->sync=var->sync & (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); par->vmode=var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE); /* in laced mode, vBackPorch should be even. odd -> funky display */ if (par->vmode & FB_VMODE_INTERLACED) par->vBackPorch += (par->vBackPorch % 2); if (par->vmode & FB_VMODE_DOUBLE) { par->vBackPorch <<= 1; par->yDim <<=1; par->vSyncOn <<=1; par->vSyncOff <<=1; } 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 (IS_VOODOO2(sst_info)) { /* 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; } /* validity tests */ if((par->xDim <= 1) || (par->yDim <= 0 ) || (par->hSyncOn <= 1) || (par->hSyncOff <= 1) || (par->hBackPorch <= 2) || (par->vSyncOn <= 0) || (par->vSyncOff <= 0) || (par->vBackPorch <= 0) || (par->tiles_in_X <= 0)) { return -EINVAL; } if (IS_VOODOO2(sst_info)) { /* Voodoo 2 limits */ if(((par->xDim-1) >= POW2(11)) || (par->yDim >= POW2(11))) { eprintk ("Unsupported resolution %dx%d\n", var->xres, var->yres); return -EINVAL; } if (((par->hSyncOn-1) >= POW2(9)) || ((par->hSyncOff-1) >= POW2(11)) || ((par->hBackPorch-2) >= POW2(9)) || (par->vSyncOn >= POW2(13)) || (par->vSyncOff >= POW2(13)) || (par->vBackPorch >= POW2(9)) || (par->tiles_in_X >= POW2(6))) { eprintk ("Unsupported Timing\n"); return -EINVAL; } } else { /* Voodoo limits */ if (par->vmode) { eprintk("Interlace/Doublescan not supported %#x\n", par->vmode); return -EINVAL; } if(((par->xDim-1) >= POW2(10)) || (par->yDim >= POW2(10))) { eprintk ("Unsupported resolution %dx%d\n", var->xres, var->yres); return -EINVAL; } if (((par->hSyncOn-1) >= POW2(8)) || ((par->hSyncOff-1) >= POW2(10)) || ((par->hBackPorch-2) >= POW2(8)) || (par->vSyncOn >= POW2(12)) || (par->vSyncOff >= POW2(12)) || (par->vBackPorch >= POW2(8)) || (par->tiles_in_X >= POW2(4))) { eprintk ("Unsupported Timings\n"); return -EINVAL; } } /* 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 * (IS_VOODOO2(sst_info) ? 32 : 64 ) * ((par->bpp == 16) ? 2 : 4); if ((real_length * var->yres) > sst_info->video.len) { eprintk ("Not enough video memory\n"); return -ENOMEM; } par->valid=1; 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->sync = par->sync; var->vmode = par->vmode; if (var->vmode & FB_VMODE_DOUBLE) { var->yres >>=1; var->yres_virtual >>=1; var->vsync_len >>=1; var->upper_margin >>=1; var->lower_margin >>=1; } /* * 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); return 0;}static int sstfb_release(struct fb_info *info, int user){ f_dprintk("sstfb_release(user: %d)\n",user); 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) sstfb_encode_var(var, &sst_info->current_par, sst_info); 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){#define sst_info ((struct sstfb_info *) info) f_dprintk("sstfb_get_var(con: %d)\n",con); if (con == -1) sstfb_encode_var(var, &sst_info->current_par, sst_info); else *var = fb_display[con].var; print_var(var, "var"); return 0;#undef sst_info }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 = &sst_info->disp; else display = &fb_display[con]; if ((err = sstfb_decode_var(var, &par, sst_info))) 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;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -