📄 neofb.c
字号:
outb(i << 1, 0x3c9); } break; case 24:#ifdef NO_32BIT_SUPPORT_YET case 32:#endif for (i=0; i<256; i++) { outb(i, 0x3c8); outb(i, 0x3c9); outb(i, 0x3c9); outb(i, 0x3c9); } break; } /* alread unlocked above */ /* BOGUS VGAwGR (0x09, 0x26);*/ /* don't know what this is, but it's 0 from bootup anyway */ VGAwGR (0x15, 0x00); /* was set to 0x01 by my bios in text and vesa modes */ VGAwGR (0x0A, par->GeneralLockReg); /* * The color mode needs to be set before calling vgaHWRestore * to ensure the DAC is initialized properly. * * NOTE: Make sure we don't change bits make sure we don't change * any reserved bits. */ temp = VGArGR(0x90); switch (info->accel) { case FB_ACCEL_NEOMAGIC_NM2070: temp &= 0xF0; /* Save bits 7:4 */ temp |= (par->ExtColorModeSelect & ~0xF0); break; case FB_ACCEL_NEOMAGIC_NM2090: case FB_ACCEL_NEOMAGIC_NM2093: case FB_ACCEL_NEOMAGIC_NM2097: case FB_ACCEL_NEOMAGIC_NM2160: case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: temp &= 0x70; /* Save bits 6:4 */ temp |= (par->ExtColorModeSelect & ~0x70); break; } VGAwGR(0x90,temp); /* * In some rare cases a lockup might occur if we don't delay * here. (Reported by Miles Lane) */ //mdelay(200); /* * Disable horizontal and vertical graphics and text expansions so * that vgaHWRestore works properly. */ temp = VGArGR(0x25); temp &= 0x39; VGAwGR (0x25, temp); /* * Sleep for 200ms to make sure that the two operations above have * had time to take effect. */ mdelay(200); /* * This function handles restoring the generic VGA registers. */ vgaHWRestore (info, par); VGAwGR(0x0E, par->ExtCRTDispAddr); VGAwGR(0x0F, par->ExtCRTOffset); temp = VGArGR(0x10); temp &= 0x0F; /* Save bits 3:0 */ temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */ VGAwGR(0x10, temp); VGAwGR(0x11, par->SysIfaceCntl2); VGAwGR(0x15, 0 /*par->SingleAddrPage*/); VGAwGR(0x16, 0 /*par->DualAddrPage*/); temp = VGArGR(0x20); switch (info->accel) { case FB_ACCEL_NEOMAGIC_NM2070: temp &= 0xFC; /* Save bits 7:2 */ temp |= (par->PanelDispCntlReg1 & ~0xFC); break; case FB_ACCEL_NEOMAGIC_NM2090: case FB_ACCEL_NEOMAGIC_NM2093: case FB_ACCEL_NEOMAGIC_NM2097: case FB_ACCEL_NEOMAGIC_NM2160: temp &= 0xDC; /* Save bits 7:6,4:2 */ temp |= (par->PanelDispCntlReg1 & ~0xDC); break; case FB_ACCEL_NEOMAGIC_NM2200: case FB_ACCEL_NEOMAGIC_NM2230: case FB_ACCEL_NEOMAGIC_NM2360: case FB_ACCEL_NEOMAGIC_NM2380: temp &= 0x98; /* Save bits 7,4:3 */ temp |= (par->PanelDispCntlReg1 & ~0x98); break; } VGAwGR(0x20, temp); temp = VGArGR(0x25); temp &= 0x38; /* Save bits 5:3 */ temp |= (par->PanelDispCntlReg2 & ~0x38); VGAwGR(0x25, temp); if (info->accel != FB_ACCEL_NEOMAGIC_NM2070) { temp = VGArGR(0x30); temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ temp |= (par->PanelDispCntlReg3 & ~0xEF); VGAwGR(0x30, temp); } VGAwGR(0x28, par->PanelVertCenterReg1); VGAwGR(0x29, par->PanelVertCenterReg2); VGAwGR(0x2a, par->PanelVertCenterReg3); if (info->accel != FB_ACCEL_NEOMAGIC_NM2070) { VGAwGR(0x32, par->PanelVertCenterReg4); VGAwGR(0x33, par->PanelHorizCenterReg1); VGAwGR(0x34, par->PanelHorizCenterReg2); VGAwGR(0x35, par->PanelHorizCenterReg3); } if (info->accel == FB_ACCEL_NEOMAGIC_NM2160) VGAwGR(0x36, par->PanelHorizCenterReg4); if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || info->accel == FB_ACCEL_NEOMAGIC_NM2230 || info->accel == FB_ACCEL_NEOMAGIC_NM2360 || info->accel == FB_ACCEL_NEOMAGIC_NM2380) { VGAwGR(0x36, par->PanelHorizCenterReg4); VGAwGR(0x37, par->PanelVertCenterReg5); VGAwGR(0x38, par->PanelHorizCenterReg5); clock_hi = 1; } /* Program VCLK3 if needed. */ if (par->ProgramVCLK && ((VGArGR(0x9B) != par->VCLK3NumeratorLow) || (VGArGR(0x9F) != par->VCLK3Denominator) || (clock_hi && ((VGArGR(0x8F) & ~0x0f) != (par->VCLK3NumeratorHigh & ~0x0F))))) { VGAwGR(0x9B, par->VCLK3NumeratorLow); if (clock_hi) { temp = VGArGR(0x8F); temp &= 0x0F; /* Save bits 3:0 */ temp |= (par->VCLK3NumeratorHigh & ~0x0F); VGAwGR(0x8F, temp); } VGAwGR(0x9F, par->VCLK3Denominator); } if (par->biosMode) VGAwCR(0x23, par->biosMode); VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */ /* Program vertical extension register */ if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || info->accel == FB_ACCEL_NEOMAGIC_NM2230 || info->accel == FB_ACCEL_NEOMAGIC_NM2360 || info->accel == FB_ACCEL_NEOMAGIC_NM2380) { VGAwCR(0x70, par->VerticalExt); } vgaHWProtect (0); /* Turn on screen */ /* Calling this also locks offset registers required in update_start */ neoLock();}static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var){ int oldExtCRTDispAddr; int Base; DBG("neofb_update_start"); Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; Base *= (var->bits_per_pixel + 7) / 8; neoUnlock(); /* * These are the generic starting address registers. */ VGAwCR(0x0C, (Base & 0x00FF00) >> 8); VGAwCR(0x0D, (Base & 0x00FF)); /* * Make sure we don't clobber some other bits that might already * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't * be needed. */ oldExtCRTDispAddr = VGArGR(0x0E); VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0))); neoLock();}/* * Set the Colormap */static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb){ struct neofb_info *info = (struct neofb_info *)fb; struct display* disp = (con < 0) ? fb->disp : (fb_display + con); struct fb_cmap *dcmap = &disp->cmap; int err = 0; /* no colormap allocated? */ if (!dcmap->len) { int size; if (fb->var.bits_per_pixel == 8) size = NR_PALETTE; else size = 32; err = fb_alloc_cmap (dcmap, size, 0); } /* * we should be able to remove this test once fbcon has been * "improved" --rmk */ if (!err && con == info->currcon) { err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb); dcmap = &fb->cmap; } if (!err) fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1); return err;}/* * neoCalcVCLK -- * * Determine the closest clock frequency to the one requested. */#define REF_FREQ 0xe517 /* 14.31818 in 20.12 fixed point */#define MAX_N 127#define MAX_D 31#define MAX_F 1static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq){ int n, d, f; int n_best = 0, d_best = 0, f_best = 0; long f_best_diff = (0x7ffff << 12); /* 20.12 */ long f_target = (freq << 12) / 1000; /* 20.12 */ for (f = 0; f <= MAX_F; f++) for (n = 0; n <= MAX_N; n++) for (d = 0; d <= MAX_D; d++) { long f_out; /* 20.12 */ long f_diff; /* 20.12 */ f_out = ((((n+1) << 12) / ((d+1)*(1<<f))) >> 12) * REF_FREQ; f_diff = abs(f_out-f_target); if (f_diff < f_best_diff) { f_best_diff = f_diff; n_best = n; d_best = d; f_best = f; } } if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 || info->accel == FB_ACCEL_NEOMAGIC_NM2230 || info->accel == FB_ACCEL_NEOMAGIC_NM2360 || info->accel == FB_ACCEL_NEOMAGIC_NM2380) { /* NOT_DONE: We are trying the full range of the 2200 clock. We should be able to try n up to 2047 */ par->VCLK3NumeratorLow = n_best; par->VCLK3NumeratorHigh = (f_best << 7); } else par->VCLK3NumeratorLow = n_best | (f_best << 7); par->VCLK3Denominator = d_best;#ifdef NEOFB_DEBUG printk ("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n", f_target >> 12, par->VCLK3NumeratorLow, par->VCLK3NumeratorHigh, par->VCLK3Denominator, f_best_diff >> 12);#endif}/* * vgaHWInit -- * Handle the initialization, etc. of a screen. * Return FALSE on failure. */static int vgaHWInit (const struct fb_var_screeninfo *var, const struct neofb_info *info, struct neofb_par *par, struct xtimings *timings){ par->MiscOutReg = 0x23; if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT)) par->MiscOutReg |= 0x40; if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT)) par->MiscOutReg |= 0x80; /* * Time Sequencer */ par->Sequencer[0] = 0x00; par->Sequencer[1] = 0x01; par->Sequencer[2] = 0x0F; par->Sequencer[3] = 0x00; /* Font select */ par->Sequencer[4] = 0x0E; /* Misc */ /* * CRTC Controller */ par->CRTC[0] = (timings->HTotal >> 3) - 5; par->CRTC[1] = (timings->HDisplay >> 3) - 1; par->CRTC[2] = (timings->HDisplay >> 3) - 1; par->CRTC[3] = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80; par->CRTC[4] = (timings->HSyncStart >> 3); par->CRTC[5] = ((((timings->HTotal >> 3) - 1) & 0x20) << 2) | (((timings->HSyncEnd >> 3)) & 0x1F); par->CRTC[6] = (timings->VTotal - 2) & 0xFF; par->CRTC[7] = (((timings->VTotal - 2) & 0x100) >> 8) | (((timings->VDisplay - 1) & 0x100) >> 7) | ((timings->VSyncStart & 0x100) >> 6) | (((timings->VDisplay - 1) & 0x100) >> 5) | 0x10 | (((timings->VTotal - 2) & 0x200) >> 4) | (((timings->VDisplay - 1) & 0x200) >> 3) | ((timings->VSyncStart & 0x200) >> 2); par->CRTC[8] = 0x00; par->CRTC[9] = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40; if (timings->dblscan) par->CRTC[9] |= 0x80; par->CRTC[10] = 0x00; par->CRTC[11] = 0x00; par->CRTC[12] = 0x00; par->CRTC[13] = 0x00; par->CRTC[14] = 0x00; par->CRTC[15] = 0x00; par->CRTC[16] = timings->VSyncStart & 0xFF; par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20; par->CRTC[18] = (timings->VDisplay - 1) & 0xFF; par->CRTC[19] = var->xres_virtual >> 4; par->CRTC[20] = 0x00; par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; par->CRTC[22] = (timings->VTotal - 1) & 0xFF; par->CRTC[23] = 0xC3; par->CRTC[24] = 0xFF; /* * are these unnecessary? * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); */ /* * Graphics Display Controller */ par->Graphics[0] = 0x00; par->Graphics[1] = 0x00; par->Graphics[2] = 0x00; par->Graphics[3] = 0x00; par->Graphics[4] = 0x00; par->Graphics[5] = 0x40; par->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ par->Graphics[7] = 0x0F; par->Graphics[8] = 0xFF; par->Attribute[0] = 0x00; /* standard colormap translation */ par->Attribute[1] = 0x01; par->Attribute[2] = 0x02; par->Attribute[3] = 0x03; par->Attribute[4] = 0x04; par->Attribute[5] = 0x05; par->Attribute[6] = 0x06; par->Attribute[7] = 0x07; par->Attribute[8] = 0x08; par->Attribute[9] = 0x09; par->Attribute[10] = 0x0A; par->Attribute[11] = 0x0B; par->Attribute[12] = 0x0C; par->Attribute[13] = 0x0D; par->Attribute[14] = 0x0E; par->Attribute[15] = 0x0F; par->Attribute[16] = 0x41; par->Attribute[17] = 0xFF; par->Attribute[18] = 0x0F; par->Attribute[19] = 0x00; par->Attribute[20] = 0x00; return 0;}static int neofb_decode_var (struct fb_var_screeninfo *var, const struct neofb_info *info, struct neofb_par *par){ struct xtimings timings; int lcd_stretch; int hoffset, voffset; int memlen, vramlen; int mode_ok = 0; unsigned int pixclock = var->pixclock; DBG("neofb_decode_var"); if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */ timings.pixclock = 1000000000 / pixclock; if (timings.pixclock < 1) timings.pixclock = 1; timings.dblscan = var->vmode & FB_VMODE_DOUBLE; timings.interlaced = var->vmode & FB_VMODE_INTERLACED; timings.HDisplay = var->xres; timings.HSyncStart = timings.HDisplay + var->right_margin; timings.HSyncEnd = timings.HSyncStart + var->hsync_len; timings.HTotal = timings.HSyncEnd + var->left_margin; timings.VDisplay = var->yres; timings.VSyncStart = timings.VDisplay + var->lower_margin; timings.VSyncEnd = timings.VSyncStart + var->vsync_len; timings.VTotal = timings.VSyncEnd + var->upper_margin; timings.sync = var->sync; if (timings.pixclock > info->maxClock) return -EINVAL; /* Is the mode larger than the LCD panel? */ if ((var->xres > info->NeoPanelWidth) || (var->yres > info->NeoPanelHeight)) { printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n", var->xres, var->yres, info->NeoPanelWidth, info->NeoPanelHeight); return -EINVAL; } /* Is the mode one of the acceptable sizes? */ switch (var->xres) { case 1280: if (var->yres == 1024) mode_ok = 1; break; case 1024: if (var->yres == 768) mode_ok = 1; break; case 800: if (var->yres == 600) mode_ok = 1; break; case 640: if (var->yres == 480) mode_ok = 1; break; } if (!mode_ok) { printk (KERN_INFO "Mode (%dx%d) won't display properly on LCD\n", var->xres, var->yres); return -EINVAL; } switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB8 case 8: break;#endif#ifdef FBCON_HAS_CFB16 case 16: break;#endif#ifdef FBCON_HAS_CFB24 case 24: break;#endif#ifdef NO_32BIT_SUPPORT_YET# ifdef FBCON_HAS_CFB32 case 32: break;# endif#endif default: return -EINVAL; } par->depth = var->bits_per_pixel; vramlen = info->video.len; if (vramlen > 4*1024*1024) vramlen = 4*1024*1024; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; if (memlen > vramlen) { var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel); memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; } /* we must round yres/xres down, we already rounded y/xres_virtual up if it was possible. We should return -EINVAL, but I disagree */ if (var->yres_virtual < var->yres) var->yres = var->yres_virtual; if (var->xres_virtual < var->xres) var->xres = var->xres_virtual; if (var->xoffset + var->xres > var->xres_virtual) var->xoffset = var->xres_virtual - var->xres; if (var->yoffset + var->yres > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; /* * This will allocate the datastructure and initialize all of the * generic VGA registers. */ if (vgaHWInit (var, info, par, &timings)) return -EINVAL; /* * The default value assigned by vgaHW.c is 0x41, but this does * not work for NeoMagic. */ par->Attribute[16] = 0x01; switch (var->bits_per_pixel) { case 8: par->CRTC[0x13] = var->xres_virtual >> 3; par->ExtCRTOffset = var->xres_virtual >> 11; par->ExtColorModeSelect = 0x11; break; case 16: par->CRTC[0x13] = var->xres_virtual >> 2; par->ExtCRTOffset = var->xres_virtual >> 10; par->ExtColorModeSelect = 0x13; break; case 24: par->CRTC[0x13] = (var->xres_virtual * 3) >> 3; par->ExtCRTOffset = (var->xres_virtual * 3) >> 11; par->ExtColorModeSelect = 0x14; break;#ifdef NO_32BIT_SUPPORT_YET case 32: /* FIXME: guessed values */ par->CRTC[0x13] = var->xres_virtual >> 1; par->ExtCRTOffset = var->xres_virtual >> 9; par->ExtColorModeSelect = 0x15; break;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -