⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tridentfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		       ca->width, ca->height);}static int tridentfb_sync(struct fb_info *info){	struct tridentfb_par *par = info->par;	if (!(info->flags & FBINFO_HWACCEL_DISABLED))		par->wait_engine(par);	return 0;}#else#define tridentfb_fillrect cfb_fillrect#define tridentfb_copyarea cfb_copyarea#define tridentfb_imageblit cfb_imageblit#endif /* CONFIG_FB_TRIDENT_ACCEL *//* * Hardware access functions */static inline unsigned char read3X4(struct tridentfb_par *par, int reg){	return vga_mm_rcrt(par->io_virt, reg);}static inline void write3X4(struct tridentfb_par *par, int reg,			    unsigned char val){	vga_mm_wcrt(par->io_virt, reg, val);}static inline unsigned char read3CE(struct tridentfb_par *par,				    unsigned char reg){	return vga_mm_rgfx(par->io_virt, reg);}static inline void writeAttr(struct tridentfb_par *par, int reg,			     unsigned char val){	fb_readb(par->io_virt + VGA_IS1_RC);	/* flip-flop to index */	vga_mm_wattr(par->io_virt, reg, val);}static inline void write3CE(struct tridentfb_par *par, int reg,			    unsigned char val){	vga_mm_wgfx(par->io_virt, reg, val);}static void enable_mmio(struct tridentfb_par *par){	/* Goto New Mode */	vga_io_rseq(0x0B);	/* Unprotect registers */	vga_io_wseq(NewMode1, 0x80);	if (!is_oldprotect(par->chip_id))		vga_io_wseq(Protection, 0x92);	/* Enable MMIO */	outb(PCIReg, 0x3D4);	outb(inb(0x3D5) | 0x01, 0x3D5);}static void disable_mmio(struct tridentfb_par *par){	/* Goto New Mode */	vga_mm_rseq(par->io_virt, 0x0B);	/* Unprotect registers */	vga_mm_wseq(par->io_virt, NewMode1, 0x80);	if (!is_oldprotect(par->chip_id))		vga_mm_wseq(par->io_virt, Protection, 0x92);	/* Disable MMIO */	t_outb(par, PCIReg, 0x3D4);	t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);}static inline void crtc_unlock(struct tridentfb_par *par){	write3X4(par, VGA_CRTC_V_SYNC_END,		 read3X4(par, VGA_CRTC_V_SYNC_END) & 0x7F);}/*  Return flat panel's maximum x resolution */static int __devinit get_nativex(struct tridentfb_par *par){	int x, y, tmp;	if (nativex)		return nativex;	tmp = (read3CE(par, 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 inline void set_lwidth(struct tridentfb_par *par, int width){	write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);	write3X4(par, AddColReg,		 (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));}/* For resolutions smaller than FP resolution stretch */static void screen_stretch(struct tridentfb_par *par){	if (par->chip_id != CYBERBLADEXPAi1)		write3CE(par, BiosReg, 0);	else		write3CE(par, BiosReg, 8);	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 1);	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 1);}/* For resolutions smaller than FP resolution center */static inline void screen_center(struct tridentfb_par *par){	write3CE(par, VertStretch, (read3CE(par, VertStretch) & 0x7C) | 0x80);	write3CE(par, HorStretch, (read3CE(par, HorStretch) & 0x7C) | 0x80);}/* Address of first shown pixel in display memory */static void set_screen_start(struct tridentfb_par *par, int base){	u8 tmp;	write3X4(par, VGA_CRTC_START_LO, base & 0xFF);	write3X4(par, VGA_CRTC_START_HI, (base & 0xFF00) >> 8);	tmp = read3X4(par, CRTCModuleTest) & 0xDF;	write3X4(par, CRTCModuleTest, tmp | ((base & 0x10000) >> 11));	tmp = read3X4(par, CRTHiOrd) & 0xF8;	write3X4(par, CRTHiOrd, tmp | ((base & 0xE0000) >> 17));}/* Set dotclock frequency */static void set_vclk(struct tridentfb_par *par, unsigned long freq){	int m, n, k;	unsigned long fi, d, di;	unsigned char best_m = 0, best_n = 0, best_k = 0;	unsigned char hi, lo;	unsigned char shift = !is_oldclock(par->chip_id) ? 2 : 1;	d = 20000;	for (k = shift; k >= 0; k--)		for (m = 1; m < 32; m++) {			n = ((m + 2) << shift) - 8;			for (n = (n < 0 ? 0 : n); n < 122; n++) {				fi = ((14318l * (n + 8)) / (m + 2)) >> k;				di = abs(fi - freq);				if (di < d || (di == d && k == best_k)) {					d = di;					best_n = n;					best_m = m;					best_k = k;				}				if (fi > freq)					break;			}		}	if (is_oldclock(par->chip_id)) {		lo = best_n | (best_m << 7);		hi = (best_m >> 1) | (best_k << 4);	} else {		lo = best_n;		hi = best_m | (best_k << 6);	}	if (is3Dchip(par->chip_id)) {		vga_mm_wseq(par->io_virt, ClockHigh, hi);		vga_mm_wseq(par->io_virt, ClockLow, lo);	} else {		t_outb(par, lo, 0x43C8);		t_outb(par, hi, 0x43C9);	}	debug("VCLK = %X %X\n", hi, lo);}/* Set number of lines for flat panels*/static void set_number_of_lines(struct tridentfb_par *par, int lines){	int tmp = read3CE(par, 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(par, CyberEnhance, tmp);}/* * If we see that FP is active we assume we have one. * Otherwise we have a CRT display. User can override. */static int __devinit is_flatpanel(struct tridentfb_par *par){	if (fp)		return 1;	if (crt || !iscyber(par->chip_id))		return 0;	return (read3CE(par, FPConfig) & 0x10) ? 1 : 0;}/* Try detecting the video memory size */static unsigned int __devinit get_memsize(struct tridentfb_par *par){	unsigned char tmp, tmp2;	unsigned int k;	/* If memory size provided by user */	if (memsize)		k = memsize * Kb;	else		switch (par->chip_id) {		case CYBER9525DVD:			k = 2560 * Kb;			break;		default:			tmp = read3X4(par, SPR) & 0x0F;			switch (tmp) {			case 0x01:				k = 512 * Kb;				break;			case 0x02:				k = 6 * Mb;	/* XP */				break;			case 0x03:				k = 1 * Mb;				break;			case 0x04:				k = 8 * Mb;				break;			case 0x06:				k = 10 * Mb;	/* XP */				break;			case 0x07:				k = 2 * Mb;				break;			case 0x08:				k = 12 * Mb;	/* XP */				break;			case 0x0A:				k = 14 * Mb;	/* XP */				break;			case 0x0C:				k = 16 * Mb;	/* XP */				break;			case 0x0E:		/* XP */				tmp2 = vga_mm_rseq(par->io_virt, 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;				break;			}		}	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){	struct tridentfb_par *par = info->par;	int bpp = var->bits_per_pixel;	int line_length;	int ramdac = 230000; /* 230MHz for most 3D chips */	debug("enter\n");	/* check color depth */	if (bpp == 24)		bpp = var->bits_per_pixel = 32;	if (bpp != 8 && bpp != 16 && bpp != 32)		return -EINVAL;	if (par->chip_id == TGUI9440 && bpp == 32)		return -EINVAL;	/* check whether resolution fits on panel and in memory */	if (par->flatpanel && nativex && var->xres > nativex)		return -EINVAL;	/* various resolution checks */	var->xres = (var->xres + 7) & ~0x7;	if (var->xres > var->xres_virtual)		var->xres_virtual = var->xres;	if (var->yres > var->yres_virtual)		var->yres_virtual = var->yres;	if (var->xres_virtual > 4095 || var->yres > 2048)		return -EINVAL;	/* prevent from position overflow for acceleration */	if (var->yres_virtual > 0xffff)		return -EINVAL;	line_length = var->xres_virtual * bpp / 8;	if (!is3Dchip(par->chip_id) &&	    !(info->flags & FBINFO_HWACCEL_DISABLED)) {		/* acceleration requires line length to be power of 2 */		if (line_length <= 512)			var->xres_virtual = 512 * 8 / bpp;		else if (line_length <= 1024)			var->xres_virtual = 1024 * 8 / bpp;		else if (line_length <= 2048)			var->xres_virtual = 2048 * 8 / bpp;		else if (line_length <= 4096)			var->xres_virtual = 4096 * 8 / bpp;		else if (line_length <= 8192)			var->xres_virtual = 8192 * 8 / bpp;		else			return -EINVAL;		line_length = var->xres_virtual * bpp / 8;	}	/* datasheet specifies how to set panning only up to 4 MB */	if (line_length * (var->yres_virtual - var->yres) > (4 << 20))		var->yres_virtual = ((4 << 20) / line_length) + var->yres;	if (line_length * var->yres_virtual > info->fix.smem_len)		return -EINVAL;	switch (bpp) {	case 8:		var->red.offset = 0;		var->red.length = 8;		var->green = var->red;		var->blue = var->red;		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;	}	if (is_xp(par->chip_id))		ramdac = 350000;	switch (par->chip_id) {	case TGUI9440:		ramdac = (bpp >= 16) ? 45000 : 90000;		break;	case CYBER9320:	case TGUI9660:		ramdac = 135000;		break;	case PROVIDIA9685:	case CYBER9388:	case CYBER9382:	case CYBER9385:		ramdac = 170000;		break;	}	/* The clock is doubled for 32 bpp */	if (bpp == 32)		ramdac /= 2;	if (PICOS2KHZ(var->pixclock) > ramdac)		return -EINVAL;	debug("exit\n");	return 0;}/* Pan the display */static int tridentfb_pan_display(struct fb_var_screeninfo *var,				 struct fb_info *info){	struct tridentfb_par *par = info->par;	unsigned int offset;	debug("enter\n");	offset = (var->xoffset + (var->yoffset * var->xres_virtual))		* var->bits_per_pixel / 32;	set_screen_start(par, offset);	debug("exit\n");	return 0;}static inline void shadowmode_on(struct tridentfb_par *par){	write3CE(par, CyberControl, read3CE(par, CyberControl) | 0x81);}static inline void shadowmode_off(struct tridentfb_par *par){	write3CE(par, CyberControl, read3CE(par, CyberControl) & 0x7E);}/* Set the hardware to the requested video mode */static int tridentfb_set_par(struct fb_info *info){	struct tridentfb_par *par = info->par;	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;	u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;	struct fb_var_screeninfo *var = &info->var;	int bpp = var->bits_per_pixel;	unsigned char tmp;	unsigned long vclk;	debug("enter\n");	hdispend = var->xres / 8 - 1;	hsyncstart = (var->xres + var->right_margin) / 8;	hsyncend = (var->xres + var->right_margin + var->hsync_len) / 8;	htotal = (var->xres + var->left_margin + var->right_margin +		  var->hsync_len) / 8 - 5;	hblankstart = hdispend + 1;	hblankend = htotal + 3;	vdispend = var->yres - 1;	vsyncstart = var->yres + var->lower_margin;	vsyncend = vsyncstart + var->vsync_len;	vtotal = var->upper_margin + vsyncend - 2;	vblankstart = vdispend + 1;	vblankend = vtotal;	if (info->var.vmode & FB_VMODE_INTERLACED) {		vtotal /= 2;		vdispend /= 2;		vsyncstart /= 2;		vsyncend /= 2;		vblankstart /= 2;		vblankend /= 2;	}	enable_mmio(par);	crtc_unlock(par);	write3CE(par, CyberControl, 8);	tmp = 0xEB;	if (var->sync & FB_SYNC_HOR_HIGH_ACT)		tmp &= ~0x40;	if (var->sync & FB_SYNC_VERT_HIGH_ACT)		tmp &= ~0x80;	if (par->flatpanel && var->xres < nativex) {		/*		 * on flat panels with native size larger		 * than requested resolution decide whether		 * we stretch or center		 */		t_outb(par, tmp | 0xC0, VGA_MIS_W);		shadowmode_on(par);		if (center)			screen_center(par);		else if (stretch)			screen_stretch(par);	} else {		t_outb(par, tmp, VGA_MIS_W);		write3CE(par, CyberControl, 8);	}	/* vertical timing values */	write3X4(par, VGA_CRTC_V_TOTAL, vtotal & 0xFF);	write3X4(par, VGA_CRTC_V_DISP_END, vdispend & 0xFF);	write3X4(par, VGA_CRTC_V_SYNC_START, vsyncstart & 0xFF);	write3X4(par, VGA_CRTC_V_SYNC_END, (vsyncend & 0x0F));	write3X4(par, VGA_CRTC_V_BLANK_START, vblankstart & 0xFF);	write3X4(par, VGA_CRTC_V_BLANK_END, vblankend & 0xFF);	/* horizontal timing values */	write3X4(par, VGA_CRTC_H_TOTAL, htotal & 0xFF);	write3X4(par, VGA_CRTC_H_DISP, hdispend & 0xFF);	write3X4(par, VGA_CRTC_H_SYNC_START, hsyncstart & 0xFF);	write3X4(par, VGA_CRTC_H_SYNC_END,		 (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));	write3X4(par, VGA_CRTC_H_BLANK_START, hblankstart & 0xFF);	write3X4(par, VGA_CRTC_H_BLANK_END, 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(par, VGA_CRTC_OVERFLOW, tmp);	tmp = read3X4(par, CRTHiOrd) & 0x07;	tmp |= 0x08;	/* line compare bit 10 */	if (vtotal & 0x400) tmp |= 0x80;	if (vblankstart & 0x400) tmp |= 0x40;	if (vsyncstart & 0x400) tmp |= 0x20;	if (vdispend & 0x400) tmp |= 0x10;	write3X4(par, CRTHiOrd, tmp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -