📄 tridentfb.c
字号:
bmove: trident_bmove, clear: trident_16bpp_clear, putc: fbcon_cfb16_putc, putcs: fbcon_cfb16_putcs, revc: fbcon_cfb16_revc, clear_margins: fbcon_cfb16_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)};#endif#ifdef FBCON_HAS_CFB32static void trident_32bpp_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width){ int c; c = ((u32*)p->dispsw_data)[attr_bgcol_ec(p,conp)]; trident_clear_helper(c,p,sy,sx,height,width);}static struct display_switch trident_32bpp = { setup: fbcon_cfb32_setup, bmove: trident_bmove, clear: trident_32bpp_clear, putc: fbcon_cfb32_putc, putcs: fbcon_cfb32_putcs, revc: fbcon_cfb32_revc, clear_margins: fbcon_cfb32_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)};#endif/* * Hardware access functions */static inline unsigned char read3X4(int reg){ writeb(reg, fb_info.io_virt + CRT + 4); return readb(fb_info.io_virt + CRT + 5);}static inline void write3X4(int reg, unsigned char val){ writeb(reg, fb_info.io_virt + CRT + 4); writeb(val, fb_info.io_virt + CRT + 5);}static inline unsigned char read3C4(int reg){ t_outb(reg, 0x3C4); return t_inb(0x3C5);}static inline void write3C4(int reg, unsigned char val){ t_outb(reg, 0x3C4); t_outb(val, 0x3C5);}static inline unsigned char read3CE(int reg){ t_outb(reg, 0x3CE); return t_inb(0x3CF);}static inline void writeAttr(int reg, unsigned char val){ readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index t_outb(reg, 0x3C0); t_outb(val, 0x3C0);}static inline unsigned char readAttr(int reg){ readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index t_outb(reg, 0x3C0); return t_inb(0x3C1);}static inline void write3CE(int reg, unsigned char val){ t_outb(reg, 0x3CE); t_outb(val, 0x3CF);}#define bios_reg(reg) write3CE(BiosReg, reg)#if 0static inline void unprotect_all(void){ outb(Protection, 0x3C4); outb(0x92, 0x3C5);}#endifstatic inline void enable_mmio(void){ /* Goto New Mode */ outb(0x0B, 0x3C4); inb(0x3C5); /* Unprotect registers */ outb(NewMode1, 0x3C4); outb(0x80, 0x3C5); /* Enable MMIO */ outb(PCIReg, 0x3D4); outb(inb(0x3D5) | 0x01, 0x3D5);}#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)/* Return flat panel's maximum x resolution */static int __init get_nativex(void){ int x,y,tmp; if (nativex) return nativex; tmp = (read3CE(VertStretch) >> 4) & 3; switch (tmp) { case 0: x = 1280; y = 1024; break; case 2: x = 1024; y = 768; break; case 3: x = 800; y = 600; break; case 4: x = 1400; y = 1050; break; case 1: default:x = 640; y = 480; break; } output("%dx%d flat panel found\n", x, y); return x;}/* Set pitch */static void set_lwidth(int width){ write3X4(Offset, width & 0xFF); write3X4(AddColReg, (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >>4));}/* For resolutions smaller than FP resolution stretch */static void screen_stretch(void){ write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 1); write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 1);}/* For resolutions smaller than FP resolution center */static void screen_center(void){ bios_reg(0); // no stretch write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 0x80); write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 0x80);}/* Address of first shown pixel in display memory */static void set_screen_start(int base){ write3X4(StartAddrLow, base & 0xFF); write3X4(StartAddrHigh, (base & 0xFF00) >> 8); write3X4(CRTCModuleTest, (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >> 11)); write3X4(CRTHiOrd, (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17));}/* Use 20.12 fixed-point for NTSC value and frequency calculation */#define calc_freq(n,m,k) ( ((unsigned long)0xE517 * (n+8) / ((m+2)*(1<<k))) >> 12 )/* Set dotclock frequency */static void set_vclk(int freq){ int m,n,k; int f,fi,d,di; unsigned char lo=0,hi=0; d = 20; for(k = 2;k>=0;k--) for(m = 0;m<63;m++) for(n = 0;n<128;n++) { fi = calc_freq(n,m,k); if ((di = abs(fi - freq)) < d) { d = di; f = fi; lo = n; hi = (k<<6) | m; } } if (chip3D) { write3C4(ClockHigh,hi); write3C4(ClockLow,lo); } else { outb(lo,0x43C8); outb(hi,0x43C9); } debug("VCLK = %X %X\n",hi,lo);}/* Set number of lines for flat panels*/static void set_number_of_lines(int lines){ int tmp = read3CE(CyberEnhance) & 0x8F; if (lines > 768) tmp |= 0x30; else if (lines > 600) tmp |= 0x20; else if (lines > 480) tmp |= 0x10; write3CE(CyberEnhance, tmp);}/* * If we see that FP is active we assume we have one. * Otherwise we have a CRT display.User can override. */static unsigned int __init get_displaytype(void){ if (fp) return DISPLAY_FP; if (crt) return DISPLAY_CRT; return (read3CE(FPConfig) & 0x10)?DISPLAY_FP:DISPLAY_CRT;}/* Try detecting the video memory size */static unsigned int __init get_memsize(void){ unsigned char tmp, tmp2; unsigned int k; /* If memory size provided by user */ if (memsize) k = memsize * Kb; else switch (chip_id) { case CYBER9525DVD: k = 2560 * Kb; break; default: tmp = read3X4(SPR) & 0x0F; switch (tmp) { case 0x01: k = 512; break; case 0x02: k = 6 * Mb; break; /* XP */ case 0x03: k = 1 * Mb; break; case 0x04: k = 8 * Mb; break; case 0x06: k = 10 * Mb; break; /* XP */ case 0x07: k = 2 * Mb; break; case 0x08: k = 12 * Mb; break; /* XP */ case 0x0A: k = 14 * Mb; break; /* XP */ case 0x0C: k = 16 * Mb; break; /* XP */ case 0x0E: /* XP */ tmp2 = read3C4(0xC1); switch (tmp2) { case 0x00: k = 20 * Mb; break; case 0x01: k = 24 * Mb; break; case 0x10: k = 28 * Mb; break; case 0x11: k = 32 * Mb; break; default: k = 1 * Mb; break; } break; case 0x0F: k = 4 * Mb; break; default: k = 1 * Mb; } } k -= memdiff * Kb; output("framebuffer size = %d Kb\n", k/Kb); return k;}/* Fill in fix */static int trident_encode_fix(struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info){ struct tridentfb_info * i = (struct tridentfb_info *)info; struct tridentfb_par * p = (struct tridentfb_par *)par; debug("enter\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,tridentfb_name); fix->smem_start = i->fbmem; fix->smem_len = i->memsize; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = p->bpp==8 ? FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; fix->line_length = p->linelength; fix->mmio_start = 0; fix->mmio_len = 0; fix->accel = FB_ACCEL_NONE; debug("exit\n"); return 0;}/* Fill in par from var */static int trident_decode_var(const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info){ struct tridentfb_par * p = (struct tridentfb_par *)par; struct tridentfb_info * i = (struct tridentfb_info *)info; int vres,vfront,vback,vsync; debug("enter\n"); p->var = *var; p->bpp = var->bits_per_pixel; if (p->bpp == 24 ) p->bpp = 32; p->linelength = var->xres_virtual * p->bpp/8; switch (p->bpp) { case 8: p->var.red.offset = 0; p->var.green.offset = 0; p->var.blue.offset = 0; p->var.red.length = 6; p->var.green.length = 6; p->var.blue.length = 6; break; case 16: p->var.red.offset = 11; p->var.green.offset = 5; p->var.blue.offset = 0; p->var.red.length = 5; p->var.green.length = 6; p->var.blue.length = 5; break; case 32: p->var.red.offset = 16; p->var.green.offset = 8; p->var.blue.offset = 0; p->var.red.length = 8; p->var.green.length = 8; p->var.blue.length = 8; break; default: return -EINVAL; } /* convert from picoseconds to MHz */ p->vclk = 1000000/var->pixclock; if (p->bpp == 32) p->vclk *=2; p->hres = var->xres; vres = p->vres = var->yres; /* See if requested resolution is larger than flat panel */ if (p->hres > i->nativex && flatpanel) { return -EINVAL; } /* See if requested resolution fits in available memory */ if (p->hres * p->vres * p->bpp/8 > i->memsize) { return -EINVAL; } vfront = var->upper_margin; vback = var->lower_margin; vsync = var->vsync_len; /* Compute horizontal and vertical VGA CRTC timing values */ if (var->vmode & FB_VMODE_INTERLACED) { vres /= 2; vfront /=2; vback /=2; vsync /=2; } if (var->vmode & FB_VMODE_DOUBLE) { vres *= 2; vfront *=2; vback *=2; vsync *=2; } p->htotal = (p->hres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10; p->hdispend = p->hres/8 - 1; p->hsyncstart = (p->hres + var->right_margin)/8; p->hsyncend = var->hsync_len/8; p->hblankstart = p->hdispend + 1; p->hblankend = p->htotal + 5; p->vtotal = vres + vfront + vback + vsync - 2; p->vdispend = vres - 1; p->vsyncstart = vres + vback; p->vsyncend = vsync; p->vblankstart = vres; p->vblankend = p->vtotal + 2; debug("exit\n"); return 0;}/* Fill in var from info */static int trident_encode_var(struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info){ struct tridentfb_par * p = (struct tridentfb_par *)par; debug("enter\n"); *var = p->var; var->bits_per_pixel = p->bpp; debug("exit\n"); return 0;}/* Fill in par from hardware */static void trident_get_par(void *par, struct fb_info_gen *info){ struct tridentfb_par * p = (struct tridentfb_par *)par; struct tridentfb_info * i = (struct tridentfb_info *)info; debug("enter\n"); *p = i->currentmode; debug("exit\n");}/* Pan the display */static int trident_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info){ unsigned int offset; struct tridentfb_info * i = (struct tridentfb_info *)info; debug("enter\n"); offset = (var->xoffset + (var->yoffset * var->xres)) * var->bits_per_pixel/32; i->currentmode.var.xoffset = var->xoffset; i->currentmode.var.yoffset = var->yoffset; set_screen_start(offset); debug("exit\n"); return 0;}/* Set the hardware from par */static void trident_set_par(const void *par, struct fb_info_gen *info){ struct tridentfb_par * p = (struct tridentfb_par *)par; struct tridentfb_info * i = (struct tridentfb_info *)info; unsigned char tmp; debug("enter\n"); i->currentmode = *p; enable_mmio(); crtc_unlock(); write3CE(CyberControl,8); if (flatpanel && p->hres < i->nativex) { /* * on flat panels with native size larger * than requested resolution decide whether * we stretch or center */ t_outb(0xEB,0x3C2); write3CE(CyberControl,0x81); if (center) screen_center(); else if (stretch) screen_stretch(); } else { t_outb(0x2B,0x3C2); write3CE(CyberControl,8); } /* vertical timing values */ write3X4(CRTVTotal, p->vtotal & 0xFF); write3X4(CRTVDispEnd, p->vdispend & 0xFF); write3X4(CRTVSyncStart, p->vsyncstart & 0xFF); write3X4(CRTVSyncEnd, (p->vsyncend & 0x0F)); write3X4(CRTVBlankStart, p->vblankstart & 0xFF); write3X4(CRTVBlankEnd, 0/*p->vblankend & 0xFF*/); /* horizontal timing values */ write3X4(CRTHTotal, p->htotal & 0xFF); write3X4(CRTHDispEnd, p->hdispend & 0xFF); write3X4(CRTHSyncStart, p->hsyncstart & 0xFF); write3X4(CRTHSyncEnd, (p->hsyncend & 0x1F) | ((p->hblankend & 0x20)<<2)); write3X4(CRTHBlankStart, p->hblankstart & 0xFF); write3X4(CRTHBlankEnd, 0/*(p->hblankend & 0x1F)*/); /* higher bits of vertical timing values */ tmp = 0x10; if (p->vtotal & 0x100) tmp |= 0x01; if (p->vdispend & 0x100) tmp |= 0x02; if (p->vsyncstart & 0x100) tmp |= 0x04; if (p->vblankstart & 0x100) tmp |= 0x08; if (p->vtotal & 0x200) tmp |= 0x20;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -