📄 savagefb_driver.c
字号:
/* We need to set CR67 whether or not we use the BIOS. */ dclk = timings.Clock; reg->CR67 = 0x00; switch(var->bits_per_pixel) { case 8: if ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) reg->CR67 = 0x10; /* 8bpp, 2 pixels/clock */ else reg->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ break; case 15: if (S3_SAVAGE_MOBILE_SERIES(par->chip) || ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))) reg->CR67 = 0x30; /* 15bpp, 2 pixel/clock */ else reg->CR67 = 0x20; /* 15bpp, 1 pixels/clock */ break; case 16: if (S3_SAVAGE_MOBILE_SERIES(par->chip) || ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))) reg->CR67 = 0x50; /* 16bpp, 2 pixel/clock */ else reg->CR67 = 0x40; /* 16bpp, 1 pixels/clock */ break; case 24: reg->CR67 = 0x70; break; case 32: reg->CR67 = 0xd0; break; } /* * Either BIOS use is disabled, or we failed to find a suitable * match. Fall back to traditional register-crunching. */ vga_out8(0x3d4, 0x3a, par); tmp = vga_in8(0x3d5, par); if (1 /*FIXME:psav->pci_burst*/) reg->CR3A = (tmp & 0x7f) | 0x15; else reg->CR3A = tmp | 0x95; reg->CR53 = 0x00; reg->CR31 = 0x8c; reg->CR66 = 0x89; vga_out8(0x3d4, 0x58, par); reg->CR58 = vga_in8(0x3d5, par) & 0x80; reg->CR58 |= 0x13; reg->SR15 = 0x03 | 0x80; reg->SR18 = 0x00; reg->CR43 = reg->CR45 = reg->CR65 = 0x00; vga_out8(0x3d4, 0x40, par); reg->CR40 = vga_in8(0x3d5, par) & ~0x01; reg->MMPR0 = 0x010400; reg->MMPR1 = 0x00; reg->MMPR2 = 0x0808; reg->MMPR3 = 0x08080810; SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r); /* m = 107; n = 4; r = 2; */ if (par->MCLK <= 0) { reg->SR10 = 255; reg->SR11 = 255; } else { common_calc_clock(par->MCLK, 1, 1, 31, 0, 3, 135000, 270000, ®->SR11, ®->SR10); /* reg->SR10 = 80; // MCLK == 286000 */ /* reg->SR11 = 125; */ } reg->SR12 = (r << 6) | (n & 0x3f); reg->SR13 = m & 0xff; reg->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; if (var->bits_per_pixel < 24) reg->MMPR0 -= 0x8000; else reg->MMPR0 -= 0x4000; if (timings.interlaced) reg->CR42 = 0x20; else reg->CR42 = 0x00; reg->CR34 = 0x10; /* display fifo */ i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) | ((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) | ((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) | ((timings.HSyncStart & 0x800) >> 7); if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64) i |= 0x08; if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32) i |= 0x20; j = (reg->CRTC[0] + ((i & 0x01) << 8) + reg->CRTC[4] + ((i & 0x10) << 4) + 1) / 2; if (j - (reg->CRTC[4] + ((i & 0x10) << 4)) < 4) { if (reg->CRTC[4] + ((i & 0x10) << 4) + 4 <= reg->CRTC[0] + ((i & 0x01) << 8)) j = reg->CRTC[4] + ((i & 0x10) << 4) + 4; else j = reg->CRTC[0] + ((i & 0x01) << 8) + 1; } reg->CR3B = j & 0xff; i |= (j & 0x100) >> 2; reg->CR3C = (reg->CRTC[0] + ((i & 0x01) << 8)) / 2; reg->CR5D = i; reg->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) | (((timings.VDisplay - 1) & 0x400) >> 9) | (((timings.VSyncStart) & 0x400) >> 8) | (((timings.VSyncStart) & 0x400) >> 6) | 0x40; width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3; reg->CR91 = reg->CRTC[19] = 0xff & width; reg->CR51 = (0x300 & width) >> 4; reg->CR90 = 0x80 | (width >> 8); reg->MiscOutReg |= 0x0c; /* Set frame buffer description. */ if (var->bits_per_pixel <= 8) reg->CR50 = 0; else if (var->bits_per_pixel <= 16) reg->CR50 = 0x10; else reg->CR50 = 0x30; if (var->xres_virtual <= 640) reg->CR50 |= 0x40; else if (var->xres_virtual == 800) reg->CR50 |= 0x80; else if (var->xres_virtual == 1024) reg->CR50 |= 0x00; else if (var->xres_virtual == 1152) reg->CR50 |= 0x01; else if (var->xres_virtual == 1280) reg->CR50 |= 0xc0; else if (var->xres_virtual == 1600) reg->CR50 |= 0x81; else reg->CR50 |= 0xc1; /* Use GBD */ if (par->chip == S3_SAVAGE2000) reg->CR33 = 0x08; else reg->CR33 = 0x20; reg->CRTC[0x17] = 0xeb; reg->CR67 |= 1; vga_out8(0x3d4, 0x36, par); reg->CR36 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x68, par); reg->CR68 = vga_in8(0x3d5, par); reg->CR69 = 0; vga_out8(0x3d4, 0x6f, par); reg->CR6F = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x86, par); reg->CR86 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x88, par); reg->CR88 = vga_in8(0x3d5, par) | 0x08; vga_out8(0x3d4, 0xb0, par); reg->CRB0 = vga_in8(0x3d5, par) | 0x80; return 0;}/* --------------------------------------------------------------------- *//* * Set a single color register. Return != 0 for invalid regno. */static int savagefb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct savagefb_par *par = info->par; if (regno >= NR_PALETTE) return -EINVAL; par->palette[regno].red = red; par->palette[regno].green = green; par->palette[regno].blue = blue; par->palette[regno].transp = transp; switch (info->var.bits_per_pixel) { case 8: vga_out8(0x3c8, regno, par); vga_out8(0x3c9, red >> 10, par); vga_out8(0x3c9, green >> 10, par); vga_out8(0x3c9, blue >> 10, par); break; case 16: if (regno < 16) ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) ) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 24: if (regno < 16) ((u32 *)info->pseudo_palette)[regno] = ((red & 0xff00) << 8) | ((green & 0xff00) ) | ((blue & 0xff00) >> 8); break; case 32: if (regno < 16) ((u32 *)info->pseudo_palette)[regno] = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) | ((green & 0xff00) ) | ((blue & 0xff00) >> 8); break; default: return 1; } return 0;}static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *reg){ unsigned char tmp, cr3a, cr66, cr67; DBG("savagefb_set_par_int"); par->SavageWaitIdle(par); vga_out8(0x3c2, 0x23, par); vga_out16(0x3d4, 0x4838, par); vga_out16(0x3d4, 0xa539, par); vga_out16(0x3c4, 0x0608, par); vgaHWProtect(par, 1); /* * Some Savage/MX and /IX systems go nuts when trying to exit the * server after WindowMaker has displayed a gradient background. I * haven't been able to find what causes it, but a non-destructive * switch to mode 3 here seems to eliminate the issue. */ VerticalRetraceWait(par); vga_out8(0x3d4, 0x67, par); cr67 = vga_in8(0x3d5, par); vga_out8(0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */ vga_out8(0x3d4, 0x23, par); vga_out8(0x3d5, 0x00, par); vga_out8(0x3d4, 0x26, par); vga_out8(0x3d5, 0x00, par); /* restore extended regs */ vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, reg->CR66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, reg->CR3A, par); vga_out8(0x3d4, 0x31, par); vga_out8(0x3d5, reg->CR31, par); vga_out8(0x3d4, 0x32, par); vga_out8(0x3d5, reg->CR32, par); vga_out8(0x3d4, 0x58, par); vga_out8(0x3d5, reg->CR58, par); vga_out8(0x3d4, 0x53, par); vga_out8(0x3d5, reg->CR53 & 0x7f, par); vga_out16(0x3c4, 0x0608, par); /* Restore DCLK registers. */ vga_out8(0x3c4, 0x0e, par); vga_out8(0x3c5, reg->SR0E, par); vga_out8(0x3c4, 0x0f, par); vga_out8(0x3c5, reg->SR0F, par); vga_out8(0x3c4, 0x29, par); vga_out8(0x3c5, reg->SR29, par); vga_out8(0x3c4, 0x15, par); vga_out8(0x3c5, reg->SR15, par); /* Restore flat panel expansion regsters. */ if (par->chip == S3_SAVAGE_MX) { int i; for (i = 0; i < 8; i++) { vga_out8(0x3c4, 0x54+i, par); vga_out8(0x3c5, reg->SR54[i], par); } } vgaHWRestore (par, reg); /* extended mode timing registers */ vga_out8(0x3d4, 0x53, par); vga_out8(0x3d5, reg->CR53, par); vga_out8(0x3d4, 0x5d, par); vga_out8(0x3d5, reg->CR5D, par); vga_out8(0x3d4, 0x5e, par); vga_out8(0x3d5, reg->CR5E, par); vga_out8(0x3d4, 0x3b, par); vga_out8(0x3d5, reg->CR3B, par); vga_out8(0x3d4, 0x3c, par); vga_out8(0x3d5, reg->CR3C, par); vga_out8(0x3d4, 0x43, par); vga_out8(0x3d5, reg->CR43, par); vga_out8(0x3d4, 0x65, par); vga_out8(0x3d5, reg->CR65, par); /* restore the desired video mode with cr67 */ vga_out8(0x3d4, 0x67, par); /* following part not present in X11 driver */ cr67 = vga_in8(0x3d5, par) & 0xf; vga_out8(0x3d5, 0x50 | cr67, par); udelay(10000); vga_out8(0x3d4, 0x67, par); /* end of part */ vga_out8(0x3d5, reg->CR67 & ~0x0c, par); /* other mode timing and extended regs */ vga_out8(0x3d4, 0x34, par); vga_out8(0x3d5, reg->CR34, par); vga_out8(0x3d4, 0x40, par); vga_out8(0x3d5, reg->CR40, par); vga_out8(0x3d4, 0x42, par); vga_out8(0x3d5, reg->CR42, par); vga_out8(0x3d4, 0x45, par); vga_out8(0x3d5, reg->CR45, par); vga_out8(0x3d4, 0x50, par); vga_out8(0x3d5, reg->CR50, par); vga_out8(0x3d4, 0x51, par); vga_out8(0x3d5, reg->CR51, par); /* memory timings */ vga_out8(0x3d4, 0x36, par); vga_out8(0x3d5, reg->CR36, par); vga_out8(0x3d4, 0x60, par); vga_out8(0x3d5, reg->CR60, par); vga_out8(0x3d4, 0x68, par); vga_out8(0x3d5, reg->CR68, par); vga_out8(0x3d4, 0x69, par); vga_out8(0x3d5, reg->CR69, par); vga_out8(0x3d4, 0x6f, par); vga_out8(0x3d5, reg->CR6F, par); vga_out8(0x3d4, 0x33, par); vga_out8(0x3d5, reg->CR33, par); vga_out8(0x3d4, 0x86, par); vga_out8(0x3d5, reg->CR86, par); vga_out8(0x3d4, 0x88, par); vga_out8(0x3d5, reg->CR88, par); vga_out8(0x3d4, 0x90, par); vga_out8(0x3d5, reg->CR90, par); vga_out8(0x3d4, 0x91, par); vga_out8(0x3d5, reg->CR91, par); if (par->chip == S3_SAVAGE4) { vga_out8(0x3d4, 0xb0, par); vga_out8(0x3d5, reg->CRB0, par); } vga_out8(0x3d4, 0x32, par); vga_out8(0x3d5, reg->CR32, par); /* unlock extended seq regs */ vga_out8(0x3c4, 0x08, par); vga_out8(0x3c5, 0x06, par); /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates * that we should leave the default SR10 and SR11 values there. */ if (reg->SR10 != 255) { vga_out8(0x3c4, 0x10, par); vga_out8(0x3c5, reg->SR10, par); vga_out8(0x3c4, 0x11, par); vga_out8(0x3c5, reg->SR11, par); } /* restore extended seq regs for dclk */ vga_out8(0x3c4, 0x0e, par); vga_out8(0x3c5, reg->SR0E, par); vga_out8(0x3c4, 0x0f, par); vga_out8(0x3c5, reg->SR0F, par); vga_out8(0x3c4, 0x12, par); vga_out8(0x3c5, reg->SR12, par); vga_out8(0x3c4, 0x13, par); vga_out8(0x3c5, reg->SR13, par); vga_out8(0x3c4, 0x29, par); vga_out8(0x3c5, reg->SR29, par); vga_out8(0x3c4, 0x18, par); vga_out8(0x3c5, reg->SR18, par); /* load new m, n pll values for dclk & mclk */ vga_out8(0x3c4, 0x15, par); tmp = vga_in8(0x3c5, par) & ~0x21; vga_out8(0x3c5, tmp | 0x03, par); vga_out8(0x3c5, tmp | 0x23, par); vga_out8(0x3c5, tmp | 0x03, par); vga_out8(0x3c5, reg->SR15, par); udelay(100); vga_out8(0x3c4, 0x30, par); vga_out8(0x3c5, reg->SR30, par); vga_out8(0x3c4, 0x08, par); vga_out8(0x3c5, reg->SR08, par); /* now write out cr67 in full, possibly starting STREAMS */ VerticalRetraceWait(par); vga_out8(0x3d4, 0x67, par); vga_out8(0x3d5, reg->CR67, par); vga_out8(0x3d4, 0x66, par); cr66 = vga_in8(0x3d5, par); vga_out8(0x3d5, cr66 | 0x80, par); vga_out8(0x3d4, 0x3a, par); cr3a = vga_in8(0x3d5, par); vga_out8(0x3d5, cr3a | 0x80, par); if (par->chip != S3_SAVAGE_MX) { VerticalRetraceWait(par); savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par); par->SavageWaitIdle(par); savage_out32(MIU_CONTROL_REG, reg->MMPR1, par); par->SavageWaitIdle(par); savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par); par->SavageWaitIdle(par); savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par); } vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); SavageSetup2DEngine(par); vgaHWProtect(par, 0);}static void savagefb_update_start(struct savagefb_par *par, struct fb_var_screeninfo *var){ int base; base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1)) * ((var->bits_per_pixel+7) / 8)) >> 2; /* now program the start address registers */ vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); vga_out8(0x3d4, 0x69, par); vga_out8(0x3d5, (base & 0x7f0000) >> 16, par);}static void savagefb_set_fix(struct fb_info *info){ info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8; if (info->var.bits_per_pixel == 8) { info->fix.visual = FB_VISUAL_PSEUDOCOLOR; info->fix.xpanstep = 4; } else { info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.xpanstep = 2; }}static int savagefb_set_par(struct fb_info *info){ struct savagefb_par *par = info->par; struct fb_var_screeninfo *var = &info->var; int err; DBG("savagefb_set_par"); err = savagefb_decode_var(var, par, &par->state); if (err) return err; if (par->dacSpeedBpp <= 0) { if (var->bits_per_pixel > 24) par->dacSpeedBpp = par->clock[3]; else if (var->bits_per_pixel >= 24) par->dacSpeedBpp = par->clock[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -