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

📄 s3fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Find appropriate format */	rv = svga_match_format (s3fb_formats, var, NULL);	/* 32bpp mode is not supported on VIRGE VX,	   24bpp is not supported on others */	if ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6))		rv = -EINVAL;	if (rv < 0) {		printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);		return rv;	}	/* Do not allow to have real resoulution larger than virtual */	if (var->xres > var->xres_virtual)		var->xres_virtual = var->xres;	if (var->yres > var->yres_virtual)		var->yres_virtual = var->yres;	/* Round up xres_virtual to have proper alignment of lines */	step = s3fb_formats[rv].xresstep - 1;	var->xres_virtual = (var->xres_virtual+step) & ~step;	/* Check whether have enough memory */	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;	if (mem > info->screen_size) {		printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n",			info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));		return -EINVAL;	}	rv = svga_check_timings (&s3_timing_regs, var, info->node);	if (rv < 0) {		printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);		return rv;	}	rv = svga_compute_pll(&s3_pll, PICOS2KHZ(var->pixclock), &m, &n, &r,				info->node);	if (rv < 0) {		printk(KERN_ERR "fb%d: invalid pixclock value requested\n",			info->node);		return rv;	}	return 0;}/* Set video mode from par */static int s3fb_set_par(struct fb_info *info){	struct s3fb_info *par = info->par;	u32 value, mode, hmul, offset_value, screen_size, multiplex;	u32 bpp = info->var.bits_per_pixel;	if (bpp != 0) {		info->fix.ypanstep = 1;		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;		info->flags &= ~FBINFO_MISC_TILEBLITTING;		info->tileops = NULL;		/* in 4bpp supports 8p wide tiles only, any tiles otherwise */		info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);		info->pixmap.blit_y = ~(u32)0;		offset_value = (info->var.xres_virtual * bpp) / 64;		screen_size = info->var.yres_virtual * info->fix.line_length;	} else {		info->fix.ypanstep = 16;		info->fix.line_length = 0;		info->flags |= FBINFO_MISC_TILEBLITTING;		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;		/* supports 8x16 tiles only */		info->pixmap.blit_x = 1 << (8 - 1);		info->pixmap.blit_y = 1 << (16 - 1);		offset_value = info->var.xres_virtual / 16;		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;	}	info->var.xoffset = 0;	info->var.yoffset = 0;	info->var.activate = FB_ACTIVATE_NOW;	/* Unlock registers */	vga_wcrt(NULL, 0x38, 0x48);	vga_wcrt(NULL, 0x39, 0xA5);	vga_wseq(NULL, 0x08, 0x06);	svga_wcrt_mask(0x11, 0x00, 0x80);	/* Blank screen and turn off sync */	svga_wseq_mask(0x01, 0x20, 0x20);	svga_wcrt_mask(0x17, 0x00, 0x80);	/* Set default values */	svga_set_default_gfx_regs();	svga_set_default_atc_regs();	svga_set_default_seq_regs();	svga_set_default_crt_regs();	svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF);	svga_wcrt_multi(s3_start_address_regs, 0);	/* S3 specific initialization */	svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */	svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB *//*	svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ?	*//*	svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ?	*/	svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ?	*/	svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ?	*/	svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits/*	svga_wcrt_mask(0x58, 0x03, 0x03); *//*	svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO *//*	svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */	/* Set the offset register */	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);	svga_wcrt_multi(s3_offset_regs, offset_value);	vga_wcrt(NULL, 0x54, 0x18); /* M parameter */	vga_wcrt(NULL, 0x60, 0xff); /* N parameter */	vga_wcrt(NULL, 0x61, 0xff); /* L parameter */	vga_wcrt(NULL, 0x62, 0xff); /* L parameter */	vga_wcrt(NULL, 0x3A, 0x35);	svga_wattr(0x33, 0x00);	if (info->var.vmode & FB_VMODE_DOUBLE)		svga_wcrt_mask(0x09, 0x80, 0x80);	else		svga_wcrt_mask(0x09, 0x00, 0x80);	if (info->var.vmode & FB_VMODE_INTERLACED)		svga_wcrt_mask(0x42, 0x20, 0x20);	else		svga_wcrt_mask(0x42, 0x00, 0x20);	/* Disable hardware graphics cursor */	svga_wcrt_mask(0x45, 0x00, 0x01);	/* Disable Streams engine */	svga_wcrt_mask(0x67, 0x00, 0x0C);	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));	/* S3 virge DX hack */	if (par->chip == CHIP_375_VIRGE_DX) {		vga_wcrt(NULL, 0x86, 0x80);		vga_wcrt(NULL, 0x90, 0x00);	}	/* S3 virge VX hack */	if (par->chip == CHIP_988_VIRGE_VX) {		vga_wcrt(NULL, 0x50, 0x00);		vga_wcrt(NULL, 0x67, 0x50);		vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09);		vga_wcrt(NULL, 0x66, 0x90);	}	svga_wcrt_mask(0x31, 0x00, 0x40);	multiplex = 0;	hmul = 1;	/* Set mode-specific register values */	switch (mode) {	case 0:		pr_debug("fb%d: text mode\n", info->node);		svga_set_textmode_vga_regs();		/* Set additional registers like in 8-bit mode */		svga_wcrt_mask(0x50, 0x00, 0x30);		svga_wcrt_mask(0x67, 0x00, 0xF0);		/* Disable enhanced mode */		svga_wcrt_mask(0x3A, 0x00, 0x30);		if (fasttext) {			pr_debug("fb%d: high speed text mode set\n", info->node);			svga_wcrt_mask(0x31, 0x40, 0x40);		}		break;	case 1:		pr_debug("fb%d: 4 bit pseudocolor\n", info->node);		vga_wgfx(NULL, VGA_GFX_MODE, 0x40);		/* Set additional registers like in 8-bit mode */		svga_wcrt_mask(0x50, 0x00, 0x30);		svga_wcrt_mask(0x67, 0x00, 0xF0);		/* disable enhanced mode */		svga_wcrt_mask(0x3A, 0x00, 0x30);		break;	case 2:		pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);		/* Set additional registers like in 8-bit mode */		svga_wcrt_mask(0x50, 0x00, 0x30);		svga_wcrt_mask(0x67, 0x00, 0xF0);		/* disable enhanced mode */		svga_wcrt_mask(0x3A, 0x00, 0x30);		break;	case 3:		pr_debug("fb%d: 8 bit pseudocolor\n", info->node);		if (info->var.pixclock > 20000) {			svga_wcrt_mask(0x50, 0x00, 0x30);			svga_wcrt_mask(0x67, 0x00, 0xF0);		} else {			svga_wcrt_mask(0x50, 0x00, 0x30);			svga_wcrt_mask(0x67, 0x10, 0xF0);			multiplex = 1;		}		break;	case 4:		pr_debug("fb%d: 5/5/5 truecolor\n", info->node);		if (par->chip == CHIP_988_VIRGE_VX) {			if (info->var.pixclock > 20000)				svga_wcrt_mask(0x67, 0x20, 0xF0);			else				svga_wcrt_mask(0x67, 0x30, 0xF0);		} else {			svga_wcrt_mask(0x50, 0x10, 0x30);			svga_wcrt_mask(0x67, 0x30, 0xF0);			hmul = 2;		}		break;	case 5:		pr_debug("fb%d: 5/6/5 truecolor\n", info->node);		if (par->chip == CHIP_988_VIRGE_VX) {			if (info->var.pixclock > 20000)				svga_wcrt_mask(0x67, 0x40, 0xF0);			else				svga_wcrt_mask(0x67, 0x50, 0xF0);		} else {			svga_wcrt_mask(0x50, 0x10, 0x30);			svga_wcrt_mask(0x67, 0x50, 0xF0);			hmul = 2;		}		break;	case 6:		/* VIRGE VX case */		pr_debug("fb%d: 8/8/8 truecolor\n", info->node);		svga_wcrt_mask(0x67, 0xD0, 0xF0);		break;	case 7:		pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);		svga_wcrt_mask(0x50, 0x30, 0x30);		svga_wcrt_mask(0x67, 0xD0, 0xF0);		break;	default:		printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);		return -EINVAL;	}	if (par->chip != CHIP_988_VIRGE_VX) {		svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10);		svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80);	}	s3_set_pixclock(info, info->var.pixclock);	svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1,			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,			 hmul, info->node);	/* Set interlaced mode start/end register */	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;	value = ((value * hmul) / 8) - 5;	vga_wcrt(NULL, 0x3C, (value + 1) / 2);	memset_io(info->screen_base, 0x00, screen_size);	/* Device and screen back on */	svga_wcrt_mask(0x17, 0x80, 0x80);	svga_wseq_mask(0x01, 0x00, 0x20);	return 0;}/* Set a colour register */static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,				u_int transp, struct fb_info *fb){	switch (fb->var.bits_per_pixel) {	case 0:	case 4:		if (regno >= 16)			return -EINVAL;		if ((fb->var.bits_per_pixel == 4) &&		    (fb->var.nonstd == 0)) {			outb(0xF0, VGA_PEL_MSK);			outb(regno*16, VGA_PEL_IW);		} else {			outb(0x0F, VGA_PEL_MSK);			outb(regno, VGA_PEL_IW);		}		outb(red >> 10, VGA_PEL_D);		outb(green >> 10, VGA_PEL_D);		outb(blue >> 10, VGA_PEL_D);		break;	case 8:		if (regno >= 256)			return -EINVAL;		outb(0xFF, VGA_PEL_MSK);		outb(regno, VGA_PEL_IW);		outb(red >> 10, VGA_PEL_D);		outb(green >> 10, VGA_PEL_D);		outb(blue >> 10, VGA_PEL_D);		break;	case 16:		if (regno >= 16)			return 0;		if (fb->var.green.length == 5)			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);		else if (fb->var.green.length == 6)			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);		else return -EINVAL;		break;	case 24:	case 32:		if (regno >= 16)			return 0;		((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |			(green & 0xFF00) | ((blue & 0xFF00) >> 8);		break;	default:		return -EINVAL;	}	return 0;}/* Set the display blanking state */static int s3fb_blank(int blank_mode, struct fb_info *info){	switch (blank_mode) {	case FB_BLANK_UNBLANK:		pr_debug("fb%d: unblank\n", info->node);		svga_wcrt_mask(0x56, 0x00, 0x06);		svga_wseq_mask(0x01, 0x00, 0x20);		break;	case FB_BLANK_NORMAL:		pr_debug("fb%d: blank\n", info->node);		svga_wcrt_mask(0x56, 0x00, 0x06);		svga_wseq_mask(0x01, 0x20, 0x20);		break;	case FB_BLANK_HSYNC_SUSPEND:		pr_debug("fb%d: hsync\n", info->node);		svga_wcrt_mask(0x56, 0x02, 0x06);		svga_wseq_mask(0x01, 0x20, 0x20);		break;	case FB_BLANK_VSYNC_SUSPEND:		pr_debug("fb%d: vsync\n", info->node);		svga_wcrt_mask(0x56, 0x04, 0x06);		svga_wseq_mask(0x01, 0x20, 0x20);		break;	case FB_BLANK_POWERDOWN:		pr_debug("fb%d: sync down\n", info->node);		svga_wcrt_mask(0x56, 0x06, 0x06);		svga_wseq_mask(0x01, 0x20, 0x20);		break;	}	return 0;}/* Pan the display */static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) {	unsigned int offset;	/* Calculate the offset */	if (var->bits_per_pixel == 0) {		offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);		offset = offset >> 2;	} else {		offset = (var->yoffset * info->fix.line_length) +			 (var->xoffset * var->bits_per_pixel / 8);		offset = offset >> 2;	}	/* Set the offset */	svga_wcrt_multi(s3_start_address_regs, offset);

⌨️ 快捷键说明

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