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

📄 arkfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return 0;}static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,	60000, 250000, 14318};/* pd4 - allow only posdivider 4 (r=2) */static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,	60000, 335000, 14318};/* 270 MHz should be upper bound for VCO clock according to specs,   but that is too restrictive in pd4 case */static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq){	u16 m, n, r;	/* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */	int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)				  ? &ics5342_pll_pd4 : &ics5342_pll,				  freq, &m, &n, &r, 0);	if (rv < 0) {		return -EINVAL;	} else {		u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};		dac_write_regs(info, code, 3);		return 0;	}}static void ics5342_release(struct dac_info *info){	ics5342_set_mode(info, DAC_PSEUDO8_8);	kfree(info);}static struct dac_ops ics5342_ops = {	.dac_set_mode	= ics5342_set_mode,	.dac_set_freq	= ics5342_set_freq,	.dac_release	= ics5342_release};static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data){	struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);	if (! info)		return NULL;	info->dacops = &ics5342_ops;	info->dac_read_regs = drr;	info->dac_write_regs = dwr;	info->data = data;	DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */	return info;}/* ------------------------------------------------------------------------- */static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};static void ark_dac_read_regs(void *data, u8 *code, int count){	u8 regval = vga_rseq(NULL, 0x1C);	while (count != 0)	{		vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0);		code[1] = vga_r(NULL, dac_regs[code[0] & 3]);		count--;		code += 2;	}	vga_wseq(NULL, 0x1C, regval);}static void ark_dac_write_regs(void *data, u8 *code, int count){	u8 regval = vga_rseq(NULL, 0x1C);	while (count != 0)	{		vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0);		vga_w(NULL, dac_regs[code[0] & 3], code[1]);		count--;		code += 2;	}	vga_wseq(NULL, 0x1C, regval);}static void ark_set_pixclock(struct fb_info *info, u32 pixclock){	struct arkfb_info *par = info->par;	u8 regval;	int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);	if (rv < 0) {		printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);		return;	}	/* Set VGA misc register  */	regval = vga_r(NULL, VGA_MIS_R);	vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);}/* Open framebuffer */static int arkfb_open(struct fb_info *info, int user){	struct arkfb_info *par = info->par;	mutex_lock(&(par->open_lock));	if (par->ref_count == 0) {		memset(&(par->state), 0, sizeof(struct vgastate));		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;		par->state.num_crtc = 0x60;		par->state.num_seq = 0x30;		save_vga(&(par->state));	}	par->ref_count++;	mutex_unlock(&(par->open_lock));	return 0;}/* Close framebuffer */static int arkfb_release(struct fb_info *info, int user){	struct arkfb_info *par = info->par;	mutex_lock(&(par->open_lock));	if (par->ref_count == 0) {		mutex_unlock(&(par->open_lock));		return -EINVAL;	}	if (par->ref_count == 1) {		restore_vga(&(par->state));		dac_set_mode(par->dac, DAC_PSEUDO8_8);	}	par->ref_count--;	mutex_unlock(&(par->open_lock));	return 0;}/* Validate passed in var */static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	int rv, mem, step;	/* Find appropriate format */	rv = svga_match_format (arkfb_formats, var, NULL);	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 = arkfb_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 (&ark_timing_regs, var, info->node);	if (rv < 0)	{		printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);		return rv;	}	/* Interlaced mode is broken */	if (var->vmode & FB_VMODE_INTERLACED)		return -EINVAL;	return 0;}/* Set video mode from par */static int arkfb_set_par(struct fb_info *info){	struct arkfb_info *par = info->par;	u32 value, mode, hmul, hdiv, offset_value, screen_size;	u32 bpp = info->var.bits_per_pixel;	u8 regval;	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 = &arkfb_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 */	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(ark_line_compare_regs, 0xFFFFFFFF);	svga_wcrt_multi(ark_start_address_regs, 0);	/* ARK specific initialization */	svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */	svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */	vga_wseq(NULL, 0x13, info->fix.smem_start >> 16);	vga_wseq(NULL, 0x14, info->fix.smem_start >> 24);	vga_wseq(NULL, 0x15, 0);	vga_wseq(NULL, 0x16, 0);	/* Set the FIFO threshold register */	/* It is fascinating way to store 5-bit value in 8-bit register */	regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;	vga_wseq(NULL, 0x18, regval);	/* Set the offset register */	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);	svga_wcrt_multi(ark_offset_regs, offset_value);	/* fix for hi-res textmode */	svga_wcrt_mask(0x40, 0x08, 0x08);	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(0x44, 0x04, 0x04);	else		svga_wcrt_mask(0x44, 0x00, 0x04);	hmul = 1;	hdiv = 1;	mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));	/* Set mode-specific register values */	switch (mode) {	case 0:		pr_debug("fb%d: text mode\n", info->node);		svga_set_textmode_vga_regs();		vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */		svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */		dac_set_mode(par->dac, DAC_PSEUDO8_8);		break;	case 1:		pr_debug("fb%d: 4 bit pseudocolor\n", info->node);		vga_wgfx(NULL, VGA_GFX_MODE, 0x40);		vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */		svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */		dac_set_mode(par->dac, DAC_PSEUDO8_8);		break;	case 2:		pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);		vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */		svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */		dac_set_mode(par->dac, DAC_PSEUDO8_8);		break;	case 3:		pr_debug("fb%d: 8 bit pseudocolor\n", info->node);		vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */		if (info->var.pixclock > 20000) {			pr_debug("fb%d: not using multiplex\n", info->node);			svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */			dac_set_mode(par->dac, DAC_PSEUDO8_8);		} else {			pr_debug("fb%d: using multiplex\n", info->node);			svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */			dac_set_mode(par->dac, DAC_PSEUDO8_16);			hdiv = 2;		}		break;	case 4:		pr_debug("fb%d: 5/5/5 truecolor\n", info->node);		vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */		svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */		dac_set_mode(par->dac, DAC_RGB1555_16);		break;	case 5:		pr_debug("fb%d: 5/6/5 truecolor\n", info->node);		vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */		svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */		dac_set_mode(par->dac, DAC_RGB0565_16);		break;	case 6:		pr_debug("fb%d: 8/8/8 truecolor\n", info->node);		vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */		svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */		dac_set_mode(par->dac, DAC_RGB0888_16);		hmul = 3;		hdiv = 2;		break;	case 7:		pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);		vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */		svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */		dac_set_mode(par->dac, DAC_RGB8888_16);		hmul = 2;		break;	default:		printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);		return -EINVAL;	}	ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);	svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv,			 (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 / hdiv) / 8) - 5;	vga_wcrt(NULL, 0x42, (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 arkfb_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) {

⌨️ 快捷键说明

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