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

📄 tdfxfb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {		DPRINTK("interlace not supported\n");		return -EINVAL;	}	var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);	if (var->xres < 320 || var->xres > 2048) {		DPRINTK("width not supported: %u\n", var->xres);		return -EINVAL;	}	if (var->yres < 200 || var->yres > 2048) {		DPRINTK("height not supported: %u\n", var->yres);		return -EINVAL;	}	if (lpitch * var->yres_virtual > info->fix.smem_len) {		var->yres_virtual = info->fix.smem_len / lpitch;		if (var->yres_virtual < var->yres) {			DPRINTK("no memory for screen (%ux%ux%u)\n",				var->xres, var->yres_virtual,				var->bits_per_pixel);			return -EINVAL;		}	}	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {		DPRINTK("pixclock too high (%ldKHz)\n",			PICOS2KHZ(var->pixclock));		return -EINVAL;	}	var->transp.offset = 0;	var->transp.length = 0;	switch (var->bits_per_pixel) {	case 8:		var->red.length = 8;		var->red.offset = 0;		var->green = var->red;		var->blue = var->red;		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;	case 24:		var->red.offset = 16;		var->green.offset = 8;		var->blue.offset = 0;		var->red.length = var->green.length = var->blue.length = 8;		break;	}	var->width = -1;	var->height = -1;	var->accel_flags = FB_ACCELF_TEXT;	DPRINTK("Checking graphics mode at %dx%d depth %d\n",		var->xres, var->yres, var->bits_per_pixel);	return 0;}static int tdfxfb_set_par(struct fb_info *info){	struct tdfx_par *par = info->par;	u32 hdispend = info->var.xres;	u32 hsyncsta = hdispend + info->var.right_margin;	u32 hsyncend = hsyncsta + info->var.hsync_len;	u32 htotal   = hsyncend + info->var.left_margin;	u32 hd, hs, he, ht, hbs, hbe;	u32 vd, vs, ve, vt, vbs, vbe;	struct banshee_reg reg;	int fout, freq;	u32 wd;	u32 cpp = (info->var.bits_per_pixel + 7) >> 3;	memset(&reg, 0, sizeof(reg));	reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE |		     VIDCFG_CURS_X11 |		     ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |		     (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);	/* PLL settings */	freq = PICOS2KHZ(info->var.pixclock);	reg.vidcfg &= ~VIDCFG_2X;	if (freq > par->max_pixclock / 2) {		freq = freq > par->max_pixclock ? par->max_pixclock : freq;		reg.dacmode |= DACMODE_2X;		reg.vidcfg  |= VIDCFG_2X;		hdispend >>= 1;		hsyncsta >>= 1;		hsyncend >>= 1;		htotal   >>= 1;	}	wd = (hdispend >> 3) - 1;	hd  = wd;	hs  = (hsyncsta >> 3) - 1;	he  = (hsyncend >> 3) - 1;	ht  = (htotal >> 3) - 1;	hbs = hd;	hbe = ht;	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		vd = (info->var.yres << 1) - 1;		vs  = vd + (info->var.lower_margin << 1);		ve  = vs + (info->var.vsync_len << 1);		vt = ve + (info->var.upper_margin << 1) - 1;		reg.screensize = info->var.xres | (info->var.yres << 13);		reg.vidcfg |= VIDCFG_HALF_MODE;		reg.crt[0x09] = 0x80;	} else {		vd = info->var.yres - 1;		vs  = vd + info->var.lower_margin;		ve  = vs + info->var.vsync_len;		vt = ve + info->var.upper_margin - 1;		reg.screensize = info->var.xres | (info->var.yres << 12);		reg.vidcfg &= ~VIDCFG_HALF_MODE;	}	vbs = vd;	vbe = vt;	/* this is all pretty standard VGA register stuffing */	reg.misc[0x00] = 0x0f |			(info->var.xres < 400 ? 0xa0 :			 info->var.xres < 480 ? 0x60 :			 info->var.xres < 768 ? 0xe0 : 0x20);	reg.gra[0x05] = 0x40;	reg.gra[0x06] = 0x05;	reg.gra[0x07] = 0x0f;	reg.gra[0x08] = 0xff;	reg.att[0x00] = 0x00;	reg.att[0x01] = 0x01;	reg.att[0x02] = 0x02;	reg.att[0x03] = 0x03;	reg.att[0x04] = 0x04;	reg.att[0x05] = 0x05;	reg.att[0x06] = 0x06;	reg.att[0x07] = 0x07;	reg.att[0x08] = 0x08;	reg.att[0x09] = 0x09;	reg.att[0x0a] = 0x0a;	reg.att[0x0b] = 0x0b;	reg.att[0x0c] = 0x0c;	reg.att[0x0d] = 0x0d;	reg.att[0x0e] = 0x0e;	reg.att[0x0f] = 0x0f;	reg.att[0x10] = 0x41;	reg.att[0x12] = 0x0f;	reg.seq[0x00] = 0x03;	reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */	reg.seq[0x02] = 0x0f;	reg.seq[0x03] = 0x00;	reg.seq[0x04] = 0x0e;	reg.crt[0x00] = ht - 4;	reg.crt[0x01] = hd;	reg.crt[0x02] = hbs;	reg.crt[0x03] = 0x80 | (hbe & 0x1f);	reg.crt[0x04] = hs;	reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);	reg.crt[0x06] = vt;	reg.crt[0x07] = ((vs & 0x200) >> 2) |			((vd & 0x200) >> 3) |			((vt & 0x200) >> 4) | 0x10 |			((vbs & 0x100) >> 5) |			((vs & 0x100) >> 6) |			((vd & 0x100) >> 7) |			((vt & 0x100) >> 8);	reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);	reg.crt[0x10] = vs;	reg.crt[0x11] = (ve & 0x0f) | 0x20;	reg.crt[0x12] = vd;	reg.crt[0x13] = wd;	reg.crt[0x15] = vbs;	reg.crt[0x16] = vbe + 1;	reg.crt[0x17] = 0xc3;	reg.crt[0x18] = 0xff;	/* Banshee's nonvga stuff */	reg.ext[0x00] = (((ht & 0x100) >> 8) |			((hd & 0x100) >> 6) |			((hbs & 0x100) >> 4) |			((hbe & 0x40) >> 1) |			((hs & 0x100) >> 2) |			((he & 0x20) << 2));	reg.ext[0x01] = (((vt & 0x400) >> 10) |			((vd & 0x400) >> 8) |			((vbs & 0x400) >> 6) |			((vbe & 0x400) >> 4));	reg.vgainit0 =	VGAINIT0_8BIT_DAC     |			VGAINIT0_EXT_ENABLE   |			VGAINIT0_WAKEUP_3C3   |			VGAINIT0_ALT_READBACK |			VGAINIT0_EXTSHIFTOUT;	reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;	if (hwcursor)		reg.curspataddr = info->fix.smem_len;	reg.cursloc   = 0;	reg.cursc0    = 0;	reg.cursc1    = 0xffffff;	reg.stride    = info->var.xres * cpp;	reg.startaddr = info->var.yoffset * reg.stride			+ info->var.xoffset * cpp;	reg.vidpll = do_calc_pll(freq, &fout);#if 0	reg.mempll = do_calc_pll(..., &fout);	reg.gfxpll = do_calc_pll(..., &fout);#endif	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)		reg.vidcfg |= VIDCFG_INTERLACE;	reg.miscinit0 = tdfx_inl(par, MISCINIT0);#if defined(__BIG_ENDIAN)	switch (info->var.bits_per_pixel) {	case 8:	case 24:		reg.miscinit0 &= ~(1 << 30);		reg.miscinit0 &= ~(1 << 31);		break;	case 16:		reg.miscinit0 |= (1 << 30);		reg.miscinit0 |= (1 << 31);		break;	case 32:		reg.miscinit0 |= (1 << 30);		reg.miscinit0 &= ~(1 << 31);		break;	}#endif	do_write_regs(info, &reg);	/* Now change fb_fix_screeninfo according to changes in par */	info->fix.line_length = reg.stride;	info->fix.visual = (info->var.bits_per_pixel == 8)				? FB_VISUAL_PSEUDOCOLOR				: FB_VISUAL_TRUECOLOR;	DPRINTK("Graphics mode is now set at %dx%d depth %d\n",		info->var.xres, info->var.yres, info->var.bits_per_pixel);	return 0;}/* A handy macro shamelessly pinched from matroxfb */#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,			    unsigned blue, unsigned transp,			    struct fb_info *info){	struct tdfx_par *par = info->par;	u32 rgbcol;	if (regno >= info->cmap.len || regno > 255)		return 1;	/* grayscale works only partially under directcolor */	if (info->var.grayscale) {		/* grayscale = 0.30*R + 0.59*G + 0.11*B */		blue = (red * 77 + green * 151 + blue * 28) >> 8;		green = blue;		red = blue;	}	switch (info->fix.visual) {	case FB_VISUAL_PSEUDOCOLOR:		rgbcol = (((u32)red   & 0xff00) << 8) |			 (((u32)green & 0xff00) << 0) |			 (((u32)blue  & 0xff00) >> 8);		do_setpalentry(par, regno, rgbcol);		break;	/* Truecolor has no hardware color palettes. */	case FB_VISUAL_TRUECOLOR:		if (regno < 16) {			rgbcol = (CNVT_TOHW(red, info->var.red.length) <<				  info->var.red.offset) |				(CNVT_TOHW(green, info->var.green.length) <<				 info->var.green.offset) |				(CNVT_TOHW(blue, info->var.blue.length) <<				 info->var.blue.offset) |				(CNVT_TOHW(transp, info->var.transp.length) <<				 info->var.transp.offset);			par->palette[regno] = rgbcol;		}		break;	default:		DPRINTK("bad depth %u\n", info->var.bits_per_pixel);		break;	}	return 0;}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static int tdfxfb_blank(int blank, struct fb_info *info){	struct tdfx_par *par = info->par;	int vgablank = 1;	u32 dacmode = tdfx_inl(par, DACMODE);	dacmode &= ~(BIT(1) | BIT(3));	switch (blank) {	case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */		vgablank = 0;		break;	case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */		break;	case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */		dacmode |= BIT(3);		break;	case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */		dacmode |= BIT(1);		break;	case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */		dacmode |= BIT(1) | BIT(3);		break;	}	banshee_make_room(par, 1);	tdfx_outl(par, DACMODE, dacmode);	if (vgablank)		vga_disable_video(par);	else		vga_enable_video(par);	return 0;}/* * Set the starting position of the visible screen to var->yoffset */static int tdfxfb_pan_display(struct fb_var_screeninfo *var,			      struct fb_info *info){	struct tdfx_par *par = info->par;	u32 addr = var->yoffset * info->fix.line_length;	if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))		return -EINVAL;	if ((var->yoffset + var->yres > var->yres_virtual && nowrap))		return -EINVAL;	banshee_make_room(par, 1);	tdfx_outl(par, VIDDESKSTART, addr);	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	return 0;}#ifdef CONFIG_FB_3DFX_ACCEL/* * FillRect 2D command (solidfill or invert (via ROP_XOR)) */static void tdfxfb_fillrect(struct fb_info *info,			    const struct fb_fillrect *rect){	struct tdfx_par *par = info->par;	u32 bpp = info->var.bits_per_pixel;	u32 stride = info->fix.line_length;	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);	int tdfx_rop;	u32 dx = rect->dx;	u32 dy = rect->dy;	u32 dstbase = 0;	if (rect->rop == ROP_COPY)		tdfx_rop = TDFX_ROP_COPY;	else		tdfx_rop = TDFX_ROP_XOR;	/* asume always rect->height < 4096 */	if (dy + rect->height > 4095) {		dstbase = stride * dy;		dy = 0;	}	/* asume always rect->width < 4096 */	if (dx + rect->width > 4095) {		dstbase += dx * bpp >> 3;		dx = 0;	}	banshee_make_room(par, 6);	tdfx_outl(par, DSTFORMAT, fmt);	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {		tdfx_outl(par, COLORFORE, rect->color);	} else { /* FB_VISUAL_TRUECOLOR */		tdfx_outl(par, COLORFORE, par->palette[rect->color]);	}	tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));	tdfx_outl(par, DSTBASE, dstbase);	tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));	tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));}/* * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) */static void tdfxfb_copyarea(struct fb_info *info,			    const struct fb_copyarea *area){	struct tdfx_par *par = info->par;	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;	u32 bpp = info->var.bits_per_pixel;	u32 stride = info->fix.line_length;	u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);	u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);	u32 dstbase = 0;	u32 srcbase = 0;	/* asume always area->height < 4096 */	if (sy + area->height > 4095) {		srcbase = stride * sy;		sy = 0;	}	/* asume always area->width < 4096 */	if (sx + area->width > 4095) {		srcbase += sx * bpp >> 3;		sx = 0;	}	/* asume always area->height < 4096 */	if (dy + area->height > 4095) {		dstbase = stride * dy;		dy = 0;	}	/* asume always area->width < 4096 */	if (dx + area->width > 4095) {		dstbase += dx * bpp >> 3;		dx = 0;	}	if (area->sx <= area->dx) {		/* -X */		blitcmd |= BIT(14);		sx += area->width - 1;		dx += area->width - 1;	}	if (area->sy <= area->dy) {		/* -Y */		blitcmd |= BIT(15);		sy += area->height - 1;		dy += area->height - 1;	}	banshee_make_room(par, 8);	tdfx_outl(par, SRCFORMAT, fmt);	tdfx_outl(par, DSTFORMAT, fmt);	tdfx_outl(par, COMMAND_2D, blitcmd);	tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));	tdfx_outl(par, DSTXY, dx | (dy << 16));	tdfx_outl(par, SRCBASE, srcbase);	tdfx_outl(par, DSTBASE, dstbase);	tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));}static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image){

⌨️ 快捷键说明

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