📄 savagefb_driver.c
字号:
/* This function is used to debug, it prints out the contents of s3 regs */static void SavagePrintRegs(struct savagefb_par *par){ unsigned char i; int vgaCRIndex = 0x3d4; int vgaCRReg = 0x3d5; printk(KERN_DEBUG "SR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE " "xF"); for (i = 0; i < 0x70; i++) { if (!(i % 16)) printk(KERN_DEBUG "\nSR%xx ", i >> 4); vga_out8(0x3c4, i, par); printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par)); } printk(KERN_DEBUG "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC " "xD xE xF"); for (i = 0; i < 0xB7; i++) { if (!(i % 16)) printk(KERN_DEBUG "\nCR%xx ", i >> 4); vga_out8(vgaCRIndex, i, par); printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par)); } printk(KERN_DEBUG "\n\n");}#endif/* --------------------------------------------------------------------- */static void savage_get_default_par(struct savagefb_par *par, struct savage_reg *reg){ unsigned char cr3a, cr53, cr66; vga_out16(0x3d4, 0x4838, par); vga_out16(0x3d4, 0xa039, par); vga_out16(0x3c4, 0x0608, 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); vga_out8(0x3d4, 0x53, par); cr53 = vga_in8(0x3d5, par); vga_out8(0x3d5, cr53 & 0x7f, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); /* unlock extended seq regs */ vga_out8(0x3c4, 0x08, par); reg->SR08 = vga_in8(0x3c5, par); vga_out8(0x3c5, 0x06, par); /* now save all the extended regs we need */ vga_out8(0x3d4, 0x31, par); reg->CR31 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x32, par); reg->CR32 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x34, par); reg->CR34 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x36, par); reg->CR36 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x3a, par); reg->CR3A = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x40, par); reg->CR40 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x42, par); reg->CR42 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x45, par); reg->CR45 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x50, par); reg->CR50 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x51, par); reg->CR51 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x53, par); reg->CR53 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x58, par); reg->CR58 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x60, par); reg->CR60 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x66, par); reg->CR66 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x67, par); reg->CR67 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x68, par); reg->CR68 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x69, par); reg->CR69 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x6f, par); reg->CR6F = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x33, par); reg->CR33 = 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); vga_out8(0x3d4, 0x90, par); reg->CR90 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x91, par); reg->CR91 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0xb0, par); reg->CRB0 = vga_in8(0x3d5, par) | 0x80; /* extended mode timing regs */ vga_out8(0x3d4, 0x3b, par); reg->CR3B = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x3c, par); reg->CR3C = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x43, par); reg->CR43 = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x5d, par); reg->CR5D = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x5e, par); reg->CR5E = vga_in8(0x3d5, par); vga_out8(0x3d4, 0x65, par); reg->CR65 = vga_in8(0x3d5, par); /* save seq extended regs for DCLK PLL programming */ vga_out8(0x3c4, 0x0e, par); reg->SR0E = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x0f, par); reg->SR0F = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x10, par); reg->SR10 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x11, par); reg->SR11 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x12, par); reg->SR12 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x13, par); reg->SR13 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x29, par); reg->SR29 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x15, par); reg->SR15 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x30, par); reg->SR30 = vga_in8(0x3c5, par); vga_out8(0x3c4, 0x18, par); reg->SR18 = vga_in8(0x3c5, par); /* Save flat panel expansion regsters. */ if (par->chip == S3_SAVAGE_MX) { int i; for (i = 0; i < 8; i++) { vga_out8(0x3c4, 0x54+i, par); reg->SR54[i] = vga_in8(0x3c5, 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); /* now save MIU regs */ if (par->chip != S3_SAVAGE_MX) { reg->MMPR0 = savage_in32(FIFO_CONTROL_REG, par); reg->MMPR1 = savage_in32(MIU_CONTROL_REG, par); reg->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par); reg->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par); } vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par);}static void savage_set_default_par(struct savagefb_par *par, struct savage_reg *reg){ unsigned char cr3a, cr53, cr66; vga_out16(0x3d4, 0x4838, par); vga_out16(0x3d4, 0xa039, par); vga_out16(0x3c4, 0x0608, 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); vga_out8(0x3d4, 0x53, par); cr53 = vga_in8(0x3d5, par); vga_out8(0x3d5, cr53 & 0x7f, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); /* unlock extended seq regs */ vga_out8(0x3c4, 0x08, par); vga_out8(0x3c5, reg->SR08, par); vga_out8(0x3c5, 0x06, par); /* now restore all the extended regs we need */ 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, 0x34, par); vga_out8(0x3d5, reg->CR34, par); vga_out8(0x3d4, 0x36, par); vga_out8(0x3d5,reg->CR36, par); vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, reg->CR3A, 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); vga_out8(0x3d4, 0x53, par); vga_out8(0x3d5, reg->CR53, par); vga_out8(0x3d4, 0x58, par); vga_out8(0x3d5, reg->CR58, par); vga_out8(0x3d4, 0x60, par); vga_out8(0x3d5, reg->CR60, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, reg->CR66, par); vga_out8(0x3d4, 0x67, par); vga_out8(0x3d5, reg->CR67, 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); vga_out8(0x3d4, 0xb0, par); vga_out8(0x3d5, reg->CRB0, par); /* extended mode timing regs */ 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, 0x5d, par); vga_out8(0x3d5, reg->CR5D, par); vga_out8(0x3d4, 0x5e, par); vga_out8(0x3d5, reg->CR5E, par); vga_out8(0x3d4, 0x65, par); vga_out8(0x3d5, reg->CR65, par); /* save seq extended regs for DCLK PLL programming */ 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, 0x10, par); vga_out8(0x3c5, reg->SR10, par); vga_out8(0x3c4, 0x11, par); vga_out8(0x3c5, reg->SR11, 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, 0x15, par); vga_out8(0x3c5, reg->SR15, par); vga_out8(0x3c4, 0x30, par); vga_out8(0x3c5, reg->SR30, par); vga_out8(0x3c4, 0x18, par); vga_out8(0x3c5, reg->SR18, par); /* Save 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); } } 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); /* now save MIU regs */ if (par->chip != S3_SAVAGE_MX) { savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par); savage_out32(MIU_CONTROL_REG, reg->MMPR1, par); savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par); savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par); } vga_out8(0x3d4, 0x3a, par); vga_out8(0x3d5, cr3a, par); vga_out8(0x3d4, 0x66, par); vga_out8(0x3d5, cr66, par);}static void savage_update_var(struct fb_var_screeninfo *var, const struct fb_videomode *modedb){ var->xres = var->xres_virtual = modedb->xres; var->yres = modedb->yres; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; var->xoffset = var->yoffset = 0; var->pixclock = modedb->pixclock; var->left_margin = modedb->left_margin; var->right_margin = modedb->right_margin; var->upper_margin = modedb->upper_margin; var->lower_margin = modedb->lower_margin; var->hsync_len = modedb->hsync_len; var->vsync_len = modedb->vsync_len; var->sync = modedb->sync; var->vmode = modedb->vmode;}static int savagefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct savagefb_par *par = info->par; int memlen, vramlen, mode_valid = 0; DBG("savagefb_check_var"); var->transp.offset = 0; var->transp.length = 0; switch (var->bits_per_pixel) { case 8: var->red.offset = var->green.offset = var->blue.offset = 0; var->red.length = var->green.length = var->blue.length = var->bits_per_pixel; break; case 16: var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; break; case 32: var->transp.offset = 24; var->transp.length = 8; var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; break; default: return -EINVAL; } if (!info->monspecs.hfmax || !info->monspecs.vfmax || !info->monspecs.dclkmax || !fb_validate_mode(var, info)) mode_valid = 1; /* calculate modeline if supported by monitor */ if (!mode_valid && info->monspecs.gtf) { if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info)) mode_valid = 1; } if (!mode_valid) { const struct fb_videomode *mode; mode = fb_find_best_mode(var, &info->modelist); if (mode) { savage_update_var(var, mode); mode_valid = 1; } } if (!mode_valid && info->monspecs.modedb_len) return -EINVAL; /* Is the mode larger than the LCD panel? */ if (par->SavagePanelWidth && (var->xres > par->SavagePanelWidth || var->yres > par->SavagePanelHeight)) { printk(KERN_INFO "Mode (%dx%d) larger than the LCD panel " "(%dx%d)\n", var->xres, var->yres, par->SavagePanelWidth, par->SavagePanelHeight); return -1; } if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; vramlen = info->fix.smem_len; 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; return 0;}static int savagefb_decode_var(struct fb_var_screeninfo *var, struct savagefb_par *par, struct savage_reg *reg){ struct xtimings timings; int width, dclk, i, j; /*, refresh; */ unsigned int m, n, r; unsigned char tmp = 0; unsigned int pixclock = var->pixclock; DBG("savagefb_decode_var"); memset(&timings, 0, sizeof(timings)); if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */ timings.Clock = 1000000000 / pixclock; if (timings.Clock < 1) timings.Clock = 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; par->depth = var->bits_per_pixel; par->vwidth = var->xres_virtual; if (var->bits_per_pixel == 16 && par->chip == S3_SAVAGE3D) { timings.HDisplay *= 2; timings.HSyncStart *= 2; timings.HSyncEnd *= 2; timings.HTotal *= 2; } /* * This will allocate the datastructure and initialize all of the * generic VGA registers. */ vgaHWInit(var, par, &timings, reg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -