tridentfb.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,298 行 · 第 1/3 页
C
1,298 行
writemmr(SR1,direction?s2:s1); writemmr(SR2,direction?s1:s2); writemmr(DR1,direction?d2:d1); writemmr(DR2,direction?d1:d2); writemmr(0x2124,0x80000000|1<<22|1<<10|1<<7|direction);}static struct accel_switch accel_image = { image_init_accel, image_wait_engine, image_fill_rect, image_copy_rect,};/* * Accel functions called by the upper layers */#ifdef CONFIG_FB_TRIDENT_ACCELstatic void tridentfb_fillrect(struct fb_info * info, const struct fb_fillrect *fr){ int bpp = info->var.bits_per_pixel; int col; switch (bpp) { default: case 8: col = fr->color; break; case 16: col = ((u16 *)(info->pseudo_palette))[fr->color]; break; case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; break; } acc->fill_rect(fr->dx, fr->dy, fr->width, fr->height, col, fr->rop); acc->wait_engine();}static void tridentfb_copyarea(struct fb_info *info, const struct fb_copyarea *ca){ acc->copy_rect(ca->sx,ca->sy,ca->dx,ca->dy,ca->width,ca->height); acc->wait_engine();}#else /* !CONFIG_FB_TRIDENT_ACCEL */#define tridentfb_fillrect cfb_fillrect#define tridentfb_copyarea cfb_copyarea#endif /* CONFIG_FB_TRIDENT_ACCEL *//* * Hardware access functions */static inline unsigned char read3X4(int reg){ struct tridentfb_par * par = (struct tridentfb_par *)fb_info.par; writeb(reg, par->io_virt + CRT + 4); return readb( par->io_virt + CRT + 5);}static inline void write3X4(int reg, unsigned char val){ struct tridentfb_par * par = (struct tridentfb_par *)fb_info.par; writeb(reg, par->io_virt + CRT + 4); writeb(val, par->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(((struct tridentfb_par *)fb_info.par)->io_virt + CRT + 0x0A); //flip-flop to index t_outb(reg, 0x3C0); t_outb(val, 0x3C0);}static inline unsigned char readAttr(int reg){ readb(((struct tridentfb_par *)fb_info.par)->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);}static 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){ if (chip_id != CYBERBLADEXPAi1) write3CE(BiosReg,0); else write3CE(BiosReg,8); write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 1); write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 1);}/* For resolutions smaller than FP resolution center */static void screen_center(void){ 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 > 1024) tmp |= 0x50; else 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 || !chipcyber) 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;}/* See if we can handle the video mode described in var */static int tridentfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ int bpp = var->bits_per_pixel; debug("enter\n"); /* check color depth */ if (bpp == 24 ) bpp = var->bits_per_pixel = 32; /* check whether resolution fits on panel and in memory*/ if (flatpanel && nativex && var->xres > nativex) return -EINVAL; if (var->xres * var->yres_virtual * bpp/8 > info->fix.smem_len) return -EINVAL; switch (bpp) { case 8: var->red.offset = 0; var->green.offset = 0; var->blue.offset = 0; var->red.length = 6; var->green.length = 6; var->blue.length = 6; break; case 16: var->red.offset = 11; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 6; var->blue.length = 5; break; case 32: var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; var->red.length = 8; var->green.length = 8; var->blue.length = 8; break; default: return -EINVAL; } debug("exit\n"); return 0;}/* Pan the display */static int tridentfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ unsigned int offset; debug("enter\n"); offset = (var->xoffset + (var->yoffset * var->xres)) * var->bits_per_pixel/32; info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; set_screen_start(offset); debug("exit\n"); return 0;}#define shadowmode_on() write3CE(CyberControl,read3CE(CyberControl) | 0x81)#define shadowmode_off() write3CE(CyberControl,read3CE(CyberControl) & 0x7E)/* Set the hardware to the requested video mode */static int tridentfb_set_par(struct fb_info *info){ struct tridentfb_par * par = (struct tridentfb_par *)(info->par); u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend, vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend; struct fb_var_screeninfo *var = &info->var; int bpp = var->bits_per_pixel; unsigned char tmp; debug("enter\n"); htotal = (var->xres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10; hdispend = var->xres/8 - 1; hsyncstart = (var->xres + var->right_margin)/8; hsyncend = var->hsync_len/8; hblankstart = hdispend + 1; hblankend = htotal + 5; vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len - 2; vdispend = var->yres - 1; vsyncstart = var->yres + var->lower_margin; vsyncend = var->vsync_len; vblankstart = var->yres; vblankend = vtotal + 2; enable_mmio(); crtc_unlock(); write3CE(CyberControl,8); if (flatpanel && var->xres < nativex) { /* * on flat panels with native size larger * than requested resolution decide whether * we stretch or center */ t_outb(0xEB,0x3C2); shadowmode_on(); if (center) screen_center(); else if (stretch) screen_stretch(); } else { t_outb(0x2B,0x3C2); write3CE(CyberControl,8); } /* vertical timing values */ write3X4(CRTVTotal, vtotal & 0xFF); write3X4(CRTVDispEnd, vdispend & 0xFF); write3X4(CRTVSyncStart, vsyncstart & 0xFF); write3X4(CRTVSyncEnd, (vsyncend & 0x0F)); write3X4(CRTVBlankStart, vblankstart & 0xFF); write3X4(CRTVBlankEnd, 0/*p->vblankend & 0xFF*/); /* horizontal timing values */ write3X4(CRTHTotal, htotal & 0xFF); write3X4(CRTHDispEnd, hdispend & 0xFF); write3X4(CRTHSyncStart, hsyncstart & 0xFF); write3X4(CRTHSyncEnd, (hsyncend & 0x1F) | ((hblankend & 0x20)<<2)); write3X4(CRTHBlankStart, hblankstart & 0xFF); write3X4(CRTHBlankEnd, 0/*(p->hblankend & 0x1F)*/); /* higher bits of vertical timing values */ tmp = 0x10; if (vtotal & 0x100) tmp |= 0x01; if (vdispend & 0x100) tmp |= 0x02; if (vsyncstart & 0x100) tmp |= 0x04; if (vblankstart & 0x100) tmp |= 0x08; if (vtotal & 0x200) tmp |= 0x20; if (vdispend & 0x200) tmp |= 0x40; if (vsyncstart & 0x200) tmp |= 0x80; write3X4(CRTOverflow, tmp); tmp = read3X4(CRTHiOrd) | 0x08; //line compare bit 10 if (vtotal & 0x400) tmp |= 0x80; if (vblankstart & 0x400) tmp |= 0x40;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?