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 + -
显示快捷键?