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

📄 neofb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
						  != (par->VCLK3NumeratorHigh &						      ~0x0F))))) {		vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);		if (clock_hi) {			temp = vga_rgfx(NULL, 0x8F);			temp &= 0x0F;	/* Save bits 3:0 */			temp |= (par->VCLK3NumeratorHigh & ~0x0F);			vga_wgfx(NULL, 0x8F, temp);		}		vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);	}	if (par->biosMode)		vga_wcrt(NULL, 0x23, par->biosMode);	vga_wgfx(NULL, 0x93, 0xc0);	/* Gives 5x faster framebuffer writes !!! */	/* Program vertical extension register */	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_wcrt(NULL, 0x70, par->VerticalExt);	}	vgaHWProtect(0);	/* Turn on screen */	/* Calling this also locks offset registers required in update_start */	neoLock(&par->state);	info->fix.line_length =	    info->var.xres_virtual * (info->var.bits_per_pixel >> 3);	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230: 		case FB_ACCEL_NEOMAGIC_NM2360: 		case FB_ACCEL_NEOMAGIC_NM2380: 			neo2200_accel_init(info, &info->var);			break;		default:			break;	}		return 0;}/* *    Pan or Wrap the Display */static int neofb_pan_display(struct fb_var_screeninfo *var,			     struct fb_info *info){	struct neofb_par *par = info->par;	struct vgastate *state = &par->state;	int oldExtCRTDispAddr;	int Base;	DBG("neofb_update_start");	Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;	Base *= (var->bits_per_pixel + 7) / 8;	neoUnlock();	/*	 * These are the generic starting address registers.	 */	vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);	vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));	/*	 * Make sure we don't clobber some other bits that might already	 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't	 * be needed.	 */	oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);	vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));	neoLock(state);	return 0;}static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			   u_int transp, struct fb_info *fb){	if (regno >= fb->cmap.len || regno > 255)		return -EINVAL;	if (fb->var.bits_per_pixel <= 8) {		outb(regno, 0x3c8);		outb(red >> 10, 0x3c9);		outb(green >> 10, 0x3c9);		outb(blue >> 10, 0x3c9);	} else if (regno < 16) {		switch (fb->var.bits_per_pixel) {		case 16:			((u32 *) fb->pseudo_palette)[regno] =				((red & 0xf800)) | ((green & 0xfc00) >> 5) |				((blue & 0xf800) >> 11);			break;		case 24:			((u32 *) fb->pseudo_palette)[regno] =				((red & 0xff00) << 8) | ((green & 0xff00)) |				((blue & 0xff00) >> 8);			break;#ifdef NO_32BIT_SUPPORT_YET		case 32:			((u32 *) fb->pseudo_palette)[regno] =				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |				((green & 0xff00)) | ((blue & 0xff00) >> 8);			break;#endif		default:			return 1;		}	}	return 0;}/* *    (Un)Blank the display. */static int neofb_blank(int blank_mode, struct fb_info *info){	/*	 *  Blank the screen if blank_mode != 0, else unblank.	 *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to	 *  e.g. a video mode which doesn't support it. Implements VESA suspend	 *  and powerdown modes for monitors, and backlight control on LCDs.	 *    blank_mode == 0: unblanked (backlight on)	 *    blank_mode == 1: blank (backlight on)	 *    blank_mode == 2: suspend vsync (backlight off)	 *    blank_mode == 3: suspend hsync (backlight off)	 *    blank_mode == 4: powerdown (backlight off)	 *	 *  wms...Enable VESA DPMS compatible powerdown mode	 *  run "setterm -powersave powerdown" to take advantage	 */	struct neofb_par *par = info->par;	int seqflags, lcdflags, dpmsflags, reg, tmpdisp;	/*	 * Read back the register bits related to display configuration. They might	 * have been changed underneath the driver via Fn key stroke.	 */	neoUnlock();	tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;	neoLock(&par->state);	/* In case we blank the screen, we want to store the possibly new	 * configuration in the driver. During un-blank, we re-apply this setting,	 * since the LCD bit will be cleared in order to switch off the backlight.	 */	if (par->PanelDispCntlRegRead) {		par->PanelDispCntlReg1 = tmpdisp;	}	par->PanelDispCntlRegRead = !blank_mode;	switch (blank_mode) {	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */		seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */		lcdflags = 0;			/* LCD off */		dpmsflags = NEO_GR01_SUPPRESS_HSYNC |			    NEO_GR01_SUPPRESS_VSYNC;#ifdef CONFIG_TOSHIBA		/* Do we still need this ? */		/* attempt to turn off backlight on toshiba; also turns off external */		{			SMMRegisters regs;			regs.eax = 0xff00; /* HCI_SET */			regs.ebx = 0x0002; /* HCI_BACKLIGHT */			regs.ecx = 0x0000; /* HCI_DISABLE */			tosh_smm(&regs);		}#endif		break;	case FB_BLANK_HSYNC_SUSPEND:		/* hsync off */		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */		lcdflags = 0;			/* LCD off */		dpmsflags = NEO_GR01_SUPPRESS_HSYNC;		break;	case FB_BLANK_VSYNC_SUSPEND:		/* vsync off */		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */		lcdflags = 0;			/* LCD off */		dpmsflags = NEO_GR01_SUPPRESS_VSYNC;		break;	case FB_BLANK_NORMAL:		/* just blank screen (backlight stays on) */		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */		/*		 * During a blank operation with the LID shut, we might store "LCD off"		 * by mistake. Due to timing issues, the BIOS may switch the lights		 * back on, and we turn it back off once we "unblank".		 *		 * So here is an attempt to implement ">=" - if we are in the process		 * of unblanking, and the LCD bit is unset in the driver but set in the		 * register, we must keep it.		 */		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */		dpmsflags = 0x00;	/* no hsync/vsync suppression */		break;	case FB_BLANK_UNBLANK:		/* unblank */		seqflags = 0;			/* Enable sequencer */		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */		dpmsflags = 0x00;	/* no hsync/vsync suppression */#ifdef CONFIG_TOSHIBA		/* Do we still need this ? */		/* attempt to re-enable backlight/external on toshiba */		{			SMMRegisters regs;			regs.eax = 0xff00; /* HCI_SET */			regs.ebx = 0x0002; /* HCI_BACKLIGHT */			regs.ecx = 0x0001; /* HCI_ENABLE */			tosh_smm(&regs);		}#endif		break;	default:	/* Anything else we don't understand; return 1 to tell			 * fb_blank we didn't aactually do anything */		return 1;	}	neoUnlock();	reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;	vga_wseq(NULL, 0x01, reg);	reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;	vga_wgfx(NULL, 0x20, reg);	reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;	vga_wgfx(NULL, 0x01, reg);	neoLock(&par->state);	return 0;}static voidneo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect){	struct neofb_par *par = info->par;	u_long dst, rop;	dst = rect->dx + rect->dy * info->var.xres_virtual;	rop = rect->rop ? 0x060000 : 0x0c0000;	neo2200_wait_fifo(info, 4);	/* set blt control */	writel(NEO_BC3_FIFO_EN |	       NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |	       //               NEO_BC3_DST_XY_ADDR  |	       //               NEO_BC3_SRC_XY_ADDR  |	       rop, &par->neo2200->bltCntl);	switch (info->var.bits_per_pixel) {	case 8:		writel(rect->color, &par->neo2200->fgColor);		break;	case 16:	case 24:		writel(((u32 *) (info->pseudo_palette))[rect->color],		       &par->neo2200->fgColor);		break;	}	writel(dst * ((info->var.bits_per_pixel + 7) >> 3),	       &par->neo2200->dstStart);	writel((rect->height << 16) | (rect->width & 0xffff),	       &par->neo2200->xyExt);}static voidneo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area){	u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;	struct neofb_par *par = info->par;	u_long src, dst, bltCntl;	bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;	if ((dy > sy) || ((dy == sy) && (dx > sx))) {		/* Start with the lower right corner */		sy += (area->height - 1);		dy += (area->height - 1);		sx += (area->width - 1);		dx += (area->width - 1);		bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;	}	src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;	dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;	neo2200_wait_fifo(info, 4);	/* set blt control */	writel(bltCntl, &par->neo2200->bltCntl);	writel(src, &par->neo2200->srcStart);	writel(dst, &par->neo2200->dstStart);	writel((area->height << 16) | (area->width & 0xffff),	       &par->neo2200->xyExt);}static voidneo2200_imageblit(struct fb_info *info, const struct fb_image *image){	struct neofb_par *par = info->par;	int s_pitch = (image->width * image->depth + 7) >> 3;	int scan_align = info->pixmap.scan_align - 1;	int buf_align = info->pixmap.buf_align - 1;	int bltCntl_flags, d_pitch, data_len;	// The data is padded for the hardware	d_pitch = (s_pitch + scan_align) & ~scan_align;	data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;	neo2200_sync(info);	if (image->depth == 1) {		if (info->var.bits_per_pixel == 24 && image->width < 16) {			/* FIXME. There is a bug with accelerated color-expanded			 * transfers in 24 bit mode if the image being transferred			 * is less than 16 bits wide. This is due to insufficient			 * padding when writing the image. We need to adjust			 * struct fb_pixmap. Not yet done. */			cfb_imageblit(info, image);			return;		}		bltCntl_flags = NEO_BC0_SRC_MONO;	} else if (image->depth == info->var.bits_per_pixel) {		bltCntl_flags = 0;	} else {		/* We don't currently support hardware acceleration if image		 * depth is different from display */		cfb_imageblit(info, image);		return;	}	switch (info->var.bits_per_pixel) {	case 8:		writel(image->fg_color, &par->neo2200->fgColor);		writel(image->bg_color, &par->neo2200->bgColor);		break;	case 16:	case 24:		writel(((u32 *) (info->pseudo_palette))[image->fg_color],		       &par->neo2200->fgColor);		writel(((u32 *) (info->pseudo_palette))[image->bg_color],		       &par->neo2200->bgColor);		break;	}	writel(NEO_BC0_SYS_TO_VID |		NEO_BC3_SKIP_MAPPING | bltCntl_flags |		// NEO_BC3_DST_XY_ADDR |		0x0c0000, &par->neo2200->bltCntl);	writel(0, &par->neo2200->srcStart);//      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);	writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +		image->dy * info->fix.line_length), &par->neo2200->dstStart);	writel((image->height << 16) | (image->width & 0xffff),	       &par->neo2200->xyExt);	memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);}static voidneofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230: 		case FB_ACCEL_NEOMAGIC_NM2360: 		case FB_ACCEL_NEOMAGIC_NM2380:			neo2200_fillrect(info, rect);			break;		default:			cfb_fillrect(info, rect);			break;	}	}static voidneofb_copyarea(struct fb_info *info, const struct fb_copyarea *area){	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230: 		case FB_ACCEL_NEOMAGIC_NM2360: 		case FB_ACCEL_NEOMAGIC_NM2380: 			neo2200_copyarea(info, area);			break;		default:			cfb_copyarea(info, area);			break;	}	}static voidneofb_imageblit(struct fb_info *info, const struct fb_image *image){	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230:		case FB_ACCEL_NEOMAGIC_NM2360:		case FB_ACCEL_NEOMAGIC_NM2380:			neo2200_imageblit(info, image);			break;		default:			cfb_imageblit(info, image);			break;	}}static int neofb_sync(struct fb_info *info){	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230: 		case FB_ACCEL_NEOMAGIC_NM2360: 		case FB_ACCEL_NEOMAGIC_NM2380: 			neo2200_sync(info);			break;		default:			break;	}	return 0;		}/*static voidneofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width){	//memset_io(info->sprite.addr, 0xff, 1);}static intneofb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct neofb_par *par = (struct neofb_par *) info->par;	* Disable cursor *	write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);	if (cursor->set & FB_CUR_SETPOS) {		u32 x = cursor->image.dx;		u32 y = cursor->image.dy;		info->cursor.image.dx = x;		info->cursor.image.dy = y;		write_le32(NEOREG_CURSX, x, par);		write_le32(NEOREG_CURSY, y, par);	}	if (cursor->set & FB_CUR_SETSIZE) {		info->cursor.image.height = cursor->image.height;		info->cursor.image.width = cursor->image.width;	}	if (cursor->set & FB_CUR_SETHOT)		info->cursor.hot = cursor->hot;	if (cursor->set & FB_CUR_SETCMAP) {		if (cursor->image.depth == 1) {			u32 fg = cursor->image.fg_color;			u32 bg = cursor->image.bg_color;			info->cursor.image.fg_color = fg;			info->cursor.image.bg_color = bg;			fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);			bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);			write_le32(NEOREG_CURSFGCOLOR, fg, par);			write_le32(NEOREG_CURSBGCOLOR, bg, par);		}	}	if (cursor->set & FB_CUR_SETSHAPE)		fb_load_cursor_image(info);	if (info->cursor.enable)		write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);	return 0;}*/static struct fb_ops neofb_ops = {	.owner		= THIS_MODULE,	.fb_open	= neofb_open,	.fb_release	= neofb_release,	.fb_check_var	= neofb_check_var,	.fb_set_par	= neofb_set_par,	.fb_setcolreg	= neofb_setcolreg,	.fb_pan_display	= neofb_pan_display,	.fb_blank	= neofb_blank,	.fb_sync	= neofb_sync,	.fb_fillrect	= neofb_fillrect,	.fb_copyarea	= neofb_copyarea,	.fb_imageblit	= neofb_imageblit,};/* --------------------------------------------------------------------- */static struct fb_videomode __devinitdata mode800x480 = {	.xres           = 800,	.yres           = 480,	.pixclock       = 25000,	.left_margin    = 88,	.right_margin   = 40,	.upper_margin   = 23,	.lower_margin   = 1,	.hsync_len      = 128,	.vsync_len      = 4,	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,	.vmode          = FB_VMODE_NONINTERLACED};static int __devinit neo_map_mmio(struct fb_info *info,				  struct pci_dev *dev){	struct neofb_par *par = info->par;	DBG("neo_map_mmio");	switch (info->fix.accel) {		case FB_ACCEL_NEOMAGIC_NM2070:			info->fix.mmio_start = pci_resource_start(dev, 0)+				0x100000;			break;		case FB_ACCEL_NEOMAGIC_NM2090:		case FB_ACCEL_NEOMAGIC_NM2093:			info->fix.mmio_start = pci_resource_start(dev, 0)+				0x200000;			break;		case FB_ACCEL_NEOMAGIC_NM2160:		case FB_ACCEL_NEOMAGIC_NM2097:		case FB_ACCEL_NEOMAGIC_NM2200:		case FB_ACCEL_NEOMAGIC_NM2230:		case FB_ACCEL_NEOMAGIC_NM2360:		case FB_ACCEL_NEOMAGIC_NM2380:			info->fix.mmio_start = pci_resource_start(dev, 1);			break;		default:			info->fix.mmio_start = pci_resource_start(dev, 0);	}	info->fix.mmio_len = MMIO_SIZE;	if (!request_mem_region	    (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {		printk("neofb: memory mapped IO in use\n");		return -EBUSY;	}	par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);	if (!par->mmio_vbase) {		printk("neofb: unable to map memory mapped IO\n");		release_mem_region(info->fix.mmio_start,				   info->fix.mmio_len);		return -ENOMEM;	} else

⌨️ 快捷键说明

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