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

📄 neofb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	par->ref_count++;	return 0;}static intneofb_release(struct fb_info *info, int user){	struct neofb_par *par = info->par;	if (!par->ref_count)		return -EINVAL;	if (par->ref_count == 1) {		restore_vga(&par->state);	}	par->ref_count--;	return 0;}static intneofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct neofb_par *par = info->par;	int memlen, vramlen;	int mode_ok = 0;	DBG("neofb_check_var");	if (PICOS2KHZ(var->pixclock) > par->maxClock)		return -EINVAL;	/* Is the mode larger than the LCD panel? */	if (par->internal_display &&            ((var->xres > par->NeoPanelWidth) ||	     (var->yres > par->NeoPanelHeight))) {		printk(KERN_INFO		       "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",		       var->xres, var->yres, par->NeoPanelWidth,		       par->NeoPanelHeight);		return -EINVAL;	}	/* Is the mode one of the acceptable sizes? */	if (!par->internal_display)		mode_ok = 1;	else {		switch (var->xres) {		case 1280:			if (var->yres == 1024)				mode_ok = 1;			break;		case 1024:			if (var->yres == 768)				mode_ok = 1;			break;		case 800:			if (var->yres == (par->libretto ? 480 : 600))				mode_ok = 1;			break;		case 640:			if (var->yres == 480)				mode_ok = 1;			break;		}	}	if (!mode_ok) {		printk(KERN_INFO		       "Mode (%dx%d) won't display properly on LCD\n",		       var->xres, var->yres);		return -EINVAL;	}	var->red.msb_right = 0;	var->green.msb_right = 0;	var->blue.msb_right = 0;	var->transp.msb_right = 0;	var->transp.offset = 0;	var->transp.length = 0;	switch (var->bits_per_pixel) {	case 8:		/* PSEUDOCOLOUR, 256 */		var->red.offset = 0;		var->red.length = 8;		var->green.offset = 0;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		break;	case 16:		/* DIRECTCOLOUR, 64k */		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 24:		/* TRUECOLOUR, 16m */		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		break;#ifdef NO_32BIT_SUPPORT_YET	case 32:		/* TRUECOLOUR, 16m */		var->transp.offset = 24;		var->transp.length = 8;		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		break;#endif	default:		printk(KERN_WARNING "neofb: no support for %dbpp\n",		       var->bits_per_pixel);		return -EINVAL;	}	vramlen = info->fix.smem_len;	if (vramlen > 4 * 1024 * 1024)		vramlen = 4 * 1024 * 1024;	if (var->xres_virtual < var->xres)		var->xres_virtual = var->xres;	memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;	if (memlen > vramlen) {		var->yres_virtual =  vramlen * 8 / (var->xres_virtual *				   	var->bits_per_pixel);		memlen = var->xres_virtual * var->bits_per_pixel *				var->yres_virtual / 8;	}	/* we must round yres/xres down, we already rounded y/xres_virtual up	   if it was possible. We should return -EINVAL, but I disagree */	if (var->yres_virtual < var->yres)		var->yres = var->yres_virtual;	if (var->xoffset + var->xres > var->xres_virtual)		var->xoffset = var->xres_virtual - var->xres;	if (var->yoffset + var->yres > var->yres_virtual)		var->yoffset = var->yres_virtual - var->yres;	var->nonstd = 0;	var->height = -1;	var->width = -1;	if (var->bits_per_pixel >= 24 || !par->neo2200)		var->accel_flags &= ~FB_ACCELF_TEXT;	return 0;}static int neofb_set_par(struct fb_info *info){	struct neofb_par *par = info->par;	unsigned char temp;	int i, clock_hi = 0;	int lcd_stretch;	int hoffset, voffset;	int vsync_start, vtotal;	DBG("neofb_set_par");	neoUnlock();	vgaHWProtect(1);	/* Blank the screen */	vsync_start = info->var.yres + info->var.lower_margin;	vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;	/*	 * This will allocate the datastructure and initialize all of the	 * generic VGA registers.	 */	if (vgaHWInit(&info->var, par))		return -EINVAL;	/*	 * The default value assigned by vgaHW.c is 0x41, but this does	 * not work for NeoMagic.	 */	par->Attribute[16] = 0x01;	switch (info->var.bits_per_pixel) {	case 8:		par->CRTC[0x13] = info->var.xres_virtual >> 3;		par->ExtCRTOffset = info->var.xres_virtual >> 11;		par->ExtColorModeSelect = 0x11;		break;	case 16:		par->CRTC[0x13] = info->var.xres_virtual >> 2;		par->ExtCRTOffset = info->var.xres_virtual >> 10;		par->ExtColorModeSelect = 0x13;		break;	case 24:		par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;		par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;		par->ExtColorModeSelect = 0x14;		break;#ifdef NO_32BIT_SUPPORT_YET	case 32:		/* FIXME: guessed values */		par->CRTC[0x13] = info->var.xres_virtual >> 1;		par->ExtCRTOffset = info->var.xres_virtual >> 9;		par->ExtColorModeSelect = 0x15;		break;#endif	default:		break;	}	par->ExtCRTDispAddr = 0x10;	/* Vertical Extension */	par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)	    | (((info->var.yres - 1) & 0x400) >> 9)	    | (((vsync_start) & 0x400) >> 8)	    | (((vsync_start) & 0x400) >> 7);	/* Fast write bursts on unless disabled. */	if (par->pci_burst)		par->SysIfaceCntl1 = 0x30;	else		par->SysIfaceCntl1 = 0x00;	par->SysIfaceCntl2 = 0xc0;	/* VESA Bios sets this to 0x80! */	/* Initialize: by default, we want display config register to be read */	par->PanelDispCntlRegRead = 1;	/* Enable any user specified display devices. */	par->PanelDispCntlReg1 = 0x00;	if (par->internal_display)		par->PanelDispCntlReg1 |= 0x02;	if (par->external_display)		par->PanelDispCntlReg1 |= 0x01;	/* If the user did not specify any display devices, then... */	if (par->PanelDispCntlReg1 == 0x00) {		/* Default to internal (i.e., LCD) only. */		par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;	}	/* If we are using a fixed mode, then tell the chip we are. */	switch (info->var.xres) {	case 1280:		par->PanelDispCntlReg1 |= 0x60;		break;	case 1024:		par->PanelDispCntlReg1 |= 0x40;		break;	case 800:		par->PanelDispCntlReg1 |= 0x20;		break;	case 640:	default:		break;	}	/* Setup shadow register locking. */	switch (par->PanelDispCntlReg1 & 0x03) {	case 0x01:		/* External CRT only mode: */		par->GeneralLockReg = 0x00;		/* We need to program the VCLK for external display only mode. */		par->ProgramVCLK = 1;		break;	case 0x02:		/* Internal LCD only mode: */	case 0x03:		/* Simultaneous internal/external (LCD/CRT) mode: */		par->GeneralLockReg = 0x01;		/* Don't program the VCLK when using the LCD. */		par->ProgramVCLK = 0;		break;	}	/*	 * If the screen is to be stretched, turn on stretching for the	 * various modes.	 *	 * OPTION_LCD_STRETCH means stretching should be turned off!	 */	par->PanelDispCntlReg2 = 0x00;	par->PanelDispCntlReg3 = 0x00;	if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&	/* LCD only */	    (info->var.xres != par->NeoPanelWidth)) {		switch (info->var.xres) {		case 320:	/* Needs testing.  KEM -- 24 May 98 */		case 400:	/* Needs testing.  KEM -- 24 May 98 */		case 640:		case 800:		case 1024:			lcd_stretch = 1;			par->PanelDispCntlReg2 |= 0xC6;			break;		default:			lcd_stretch = 0;			/* No stretching in these modes. */		}	} else		lcd_stretch = 0;	/*	 * If the screen is to be centerd, turn on the centering for the	 * various modes.	 */	par->PanelVertCenterReg1 = 0x00;	par->PanelVertCenterReg2 = 0x00;	par->PanelVertCenterReg3 = 0x00;	par->PanelVertCenterReg4 = 0x00;	par->PanelVertCenterReg5 = 0x00;	par->PanelHorizCenterReg1 = 0x00;	par->PanelHorizCenterReg2 = 0x00;	par->PanelHorizCenterReg3 = 0x00;	par->PanelHorizCenterReg4 = 0x00;	par->PanelHorizCenterReg5 = 0x00;	if (par->PanelDispCntlReg1 & 0x02) {		if (info->var.xres == par->NeoPanelWidth) {			/*			 * No centering required when the requested display width			 * equals the panel width.			 */		} else {			par->PanelDispCntlReg2 |= 0x01;			par->PanelDispCntlReg3 |= 0x10;			/* Calculate the horizontal and vertical offsets. */			if (!lcd_stretch) {				hoffset =				    ((par->NeoPanelWidth -				      info->var.xres) >> 4) - 1;				voffset =				    ((par->NeoPanelHeight -				      info->var.yres) >> 1) - 2;			} else {				/* Stretched modes cannot be centered. */				hoffset = 0;				voffset = 0;			}			switch (info->var.xres) {			case 320:	/* Needs testing.  KEM -- 24 May 98 */				par->PanelHorizCenterReg3 = hoffset;				par->PanelVertCenterReg2 = voffset;				break;			case 400:	/* Needs testing.  KEM -- 24 May 98 */				par->PanelHorizCenterReg4 = hoffset;				par->PanelVertCenterReg1 = voffset;				break;			case 640:				par->PanelHorizCenterReg1 = hoffset;				par->PanelVertCenterReg3 = voffset;				break;			case 800:				par->PanelHorizCenterReg2 = hoffset;				par->PanelVertCenterReg4 = voffset;				break;			case 1024:				par->PanelHorizCenterReg5 = hoffset;				par->PanelVertCenterReg5 = voffset;				break;			case 1280:			default:				/* No centering in these modes. */				break;			}		}	}	par->biosMode =	    neoFindMode(info->var.xres, info->var.yres,			info->var.bits_per_pixel);	/*	 * Calculate the VCLK that most closely matches the requested dot	 * clock.	 */	neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));	/* Since we program the clocks ourselves, always use VCLK3. */	par->MiscOutReg |= 0x0C;	/* alread unlocked above */	/* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */	/* don't know what this is, but it's 0 from bootup anyway */	vga_wgfx(NULL, 0x15, 0x00);	/* was set to 0x01 by my bios in text and vesa modes */	vga_wgfx(NULL, 0x0A, par->GeneralLockReg);	/*	 * The color mode needs to be set before calling vgaHWRestore	 * to ensure the DAC is initialized properly.	 *	 * NOTE: Make sure we don't change bits make sure we don't change	 * any reserved bits.	 */	temp = vga_rgfx(NULL, 0x90);	switch (info->fix.accel) {	case FB_ACCEL_NEOMAGIC_NM2070:		temp &= 0xF0;	/* Save bits 7:4 */		temp |= (par->ExtColorModeSelect & ~0xF0);		break;	case FB_ACCEL_NEOMAGIC_NM2090:	case FB_ACCEL_NEOMAGIC_NM2093:	case FB_ACCEL_NEOMAGIC_NM2097:	case FB_ACCEL_NEOMAGIC_NM2160:	case FB_ACCEL_NEOMAGIC_NM2200:	case FB_ACCEL_NEOMAGIC_NM2230:	case FB_ACCEL_NEOMAGIC_NM2360:	case FB_ACCEL_NEOMAGIC_NM2380:		temp &= 0x70;	/* Save bits 6:4 */		temp |= (par->ExtColorModeSelect & ~0x70);		break;	}	vga_wgfx(NULL, 0x90, temp);	/*	 * In some rare cases a lockup might occur if we don't delay	 * here. (Reported by Miles Lane)	 */	//mdelay(200);	/*	 * Disable horizontal and vertical graphics and text expansions so	 * that vgaHWRestore works properly.	 */	temp = vga_rgfx(NULL, 0x25);	temp &= 0x39;	vga_wgfx(NULL, 0x25, temp);	/*	 * Sleep for 200ms to make sure that the two operations above have	 * had time to take effect.	 */	mdelay(200);	/*	 * This function handles restoring the generic VGA registers.  */	vgaHWRestore(info, par);	/* linear colormap for non palettized modes */	switch (info->var.bits_per_pixel) {	case 8:		/* PseudoColor, 256 */		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;		break;	case 16:		/* TrueColor, 64k */		info->fix.visual = FB_VISUAL_TRUECOLOR;		for (i = 0; i < 64; i++) {			outb(i, 0x3c8);			outb(i << 1, 0x3c9);			outb(i, 0x3c9);			outb(i << 1, 0x3c9);		}		break;	case 24:#ifdef NO_32BIT_SUPPORT_YET	case 32:#endif		/* TrueColor, 16m */		info->fix.visual = FB_VISUAL_TRUECOLOR;		for (i = 0; i < 256; i++) {			outb(i, 0x3c8);			outb(i, 0x3c9);			outb(i, 0x3c9);			outb(i, 0x3c9);		}		break;	}	vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);	vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);	temp = vga_rgfx(NULL, 0x10);	temp &= 0x0F;		/* Save bits 3:0 */	temp |= (par->SysIfaceCntl1 & ~0x0F);	/* VESA Bios sets bit 1! */	vga_wgfx(NULL, 0x10, temp);	vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);	vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );	vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );	temp = vga_rgfx(NULL, 0x20);	switch (info->fix.accel) {	case FB_ACCEL_NEOMAGIC_NM2070:		temp &= 0xFC;	/* Save bits 7:2 */		temp |= (par->PanelDispCntlReg1 & ~0xFC);		break;	case FB_ACCEL_NEOMAGIC_NM2090:	case FB_ACCEL_NEOMAGIC_NM2093:	case FB_ACCEL_NEOMAGIC_NM2097:	case FB_ACCEL_NEOMAGIC_NM2160:		temp &= 0xDC;	/* Save bits 7:6,4:2 */		temp |= (par->PanelDispCntlReg1 & ~0xDC);		break;	case FB_ACCEL_NEOMAGIC_NM2200:	case FB_ACCEL_NEOMAGIC_NM2230:	case FB_ACCEL_NEOMAGIC_NM2360:	case FB_ACCEL_NEOMAGIC_NM2380:		temp &= 0x98;	/* Save bits 7,4:3 */		temp |= (par->PanelDispCntlReg1 & ~0x98);		break;	}	vga_wgfx(NULL, 0x20, temp);	temp = vga_rgfx(NULL, 0x25);	temp &= 0x38;		/* Save bits 5:3 */	temp |= (par->PanelDispCntlReg2 & ~0x38);	vga_wgfx(NULL, 0x25, temp);	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {		temp = vga_rgfx(NULL, 0x30);		temp &= 0xEF;	/* Save bits 7:5 and bits 3:0 */		temp |= (par->PanelDispCntlReg3 & ~0xEF);		vga_wgfx(NULL, 0x30, temp);	}	vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);	vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);	vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);	if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {		vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);		vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);		vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);		vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);	}	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);	if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||	    info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {		vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);		vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);		vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);		clock_hi = 1;	}	/* Program VCLK3 if needed. */	if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)				 || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)				 || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)

⌨️ 快捷键说明

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