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

📄 acornfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	printk(KERN_DEBUG " Fsize            : 0x%08X\n", fsize);#endif}/* * We have to take note of the VIDC20's 16-bit palette here. * The VIDC20 looks up a 16 bit pixel as follows: * *   bits   111111 *          5432109876543210 *   red            ++++++++  (8 bits,  7 to 0) *  green       ++++++++      (8 bits, 11 to 4) *   blue   ++++++++          (8 bits, 15 to 8) * * We use a pixel which looks like: * *   bits   111111 *          5432109876543210 *   red               +++++  (5 bits,  4 to  0) *  green         +++++       (5 bits,  9 to  5) *   blue    +++++            (5 bits, 14 to 10) */static intacornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,		  u_int trans, struct fb_info *info){	union palette pal;	if (regno >= current_par.palette_size)		return 1;	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {		u32 pseudo_val;		pseudo_val  = regno << info->var.red.offset;		pseudo_val |= regno << info->var.green.offset;		pseudo_val |= regno << info->var.blue.offset;		((u32 *)info->pseudo_palette)[regno] = pseudo_val;	}	pal.p = 0;	pal.vidc20.red   = red >> 8;	pal.vidc20.green = green >> 8;	pal.vidc20.blue  = blue >> 8;	current_par.palette[regno] = pal;	if (info->var.bits_per_pixel == 16) {		int i;		pal.p = 0;		vidc_writel(0x10000000);		for (i = 0; i < 256; i += 1) {			pal.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;			pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;			pal.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;			vidc_writel(pal.p);			/* Palette register pointer auto-increments */		}	} else {		vidc_writel(0x10000000 | regno);		vidc_writel(pal.p);	}	return 0;}#endif/* * Before selecting the timing parameters, adjust * the resolution to fit the rules. */static intacornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, u_int fontht){	u_int font_line_len, sam_size, min_size, size, nr_y;	/* xres must be even */	var->xres = (var->xres + 1) & ~1;	/*	 * We don't allow xres_virtual to differ from xres	 */	var->xres_virtual = var->xres;	var->xoffset = 0;	if (current_par.using_vram)		sam_size = current_par.vram_half_sam * 2;	else		sam_size = 16;	/*	 * Now, find a value for yres_virtual which allows	 * us to do ywrap scrolling.  The value of	 * yres_virtual must be such that the end of the	 * displayable frame buffer must be aligned with	 * the start of a font line.	 */	font_line_len = var->xres * var->bits_per_pixel * fontht / 8;	min_size = var->xres * var->yres * var->bits_per_pixel / 8;	/*	 * If minimum screen size is greater than that we have	 * available, reject it.	 */	if (min_size > info->fix.smem_len)		return -EINVAL;	/* Find int 'y', such that y * fll == s * sam < maxsize	 * y = s * sam / fll; s = maxsize / sam	 */	for (size = info->fix.smem_len;	     nr_y = size / font_line_len, min_size <= size;	     size -= sam_size) {		if (nr_y * font_line_len == size)			break;	}	nr_y *= fontht;	if (var->accel_flags & FB_ACCELF_TEXT) {		if (min_size > size) {			/*			 * failed, use ypan			 */			size = info->fix.smem_len;			var->yres_virtual = size / (font_line_len / fontht);		} else			var->yres_virtual = nr_y;	} else if (var->yres_virtual > nr_y)		var->yres_virtual = nr_y;	current_par.screen_end = info->fix.smem_start + size;	/*	 * Fix yres & yoffset if needed.	 */	if (var->yres > var->yres_virtual)		var->yres = var->yres_virtual;	if (var->vmode & FB_VMODE_YWRAP) {		if (var->yoffset > var->yres_virtual)			var->yoffset = var->yres_virtual;	} else {		if (var->yoffset + var->yres > var->yres_virtual)			var->yoffset = var->yres_virtual - var->yres;	}	/* hsync_len must be even */	var->hsync_len = (var->hsync_len + 1) & ~1;#ifdef HAS_VIDC	/* left_margin must be odd */	if ((var->left_margin & 1) == 0) {		var->left_margin -= 1;		var->right_margin += 1;	}	/* right_margin must be odd */	var->right_margin |= 1;#elif defined(HAS_VIDC20)	/* left_margin must be even */	if (var->left_margin & 1) {		var->left_margin += 1;		var->right_margin -= 1;	}	/* right_margin must be even */	if (var->right_margin & 1)		var->right_margin += 1;#endif	if (var->vsync_len < 1)		var->vsync_len = 1;	return 0;}static intacornfb_validate_timing(struct fb_var_screeninfo *var,			struct fb_monspecs *monspecs){	unsigned long hs, vs;	/*	 * hs(Hz) = 10^12 / (pixclock * xtotal)	 * vs(Hz) = hs(Hz) / ytotal	 *	 * No need to do long long divisions or anything	 * like that if you factor it correctly	 */	hs = 1953125000 / var->pixclock;	hs = hs * 512 /	     (var->xres + var->left_margin + var->right_margin + var->hsync_len);	vs = hs /	     (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);	return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&		hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;}static inline voidacornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var){	u_int off = var->yoffset * info->fix.line_length;#if defined(HAS_MEMC)	memc_write(VDMA_INIT, off >> 2);#elif defined(HAS_IOMD)	iomd_writel(info->fix.smem_start + off, IOMD_VIDINIT);#endif}static intacornfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	u_int fontht;	int err;	/*	 * FIXME: Find the font height	 */	fontht = 8;	var->red.msb_right = 0;	var->green.msb_right = 0;	var->blue.msb_right = 0;	var->transp.msb_right = 0;	switch (var->bits_per_pixel) {	case 1:	case 2:	case 4:	case 8:		var->red.offset    = 0;		var->red.length    = var->bits_per_pixel;		var->green         = var->red;		var->blue          = var->red;		var->transp.offset = 0;		var->transp.length = 0;		break;#ifdef HAS_VIDC20	case 16:		var->red.offset    = 0;		var->red.length    = 5;		var->green.offset  = 5;		var->green.length  = 5;		var->blue.offset   = 10;		var->blue.length   = 5;		var->transp.offset = 15;		var->transp.length = 1;		break;	case 32:		var->red.offset    = 0;		var->red.length    = 8;		var->green.offset  = 8;		var->green.length  = 8;		var->blue.offset   = 16;		var->blue.length   = 8;		var->transp.offset = 24;		var->transp.length = 4;		break;#endif	default:		return -EINVAL;	}	/*	 * Check to see if the pixel rate is valid.	 */	if (!acornfb_valid_pixrate(var))		return -EINVAL;	/*	 * Validate and adjust the resolution to	 * match the video generator hardware.	 */	err = acornfb_adjust_timing(info, var, fontht);	if (err)		return err;	/*	 * Validate the timing against the	 * monitor hardware.	 */	return acornfb_validate_timing(var, &info->monspecs);}static int acornfb_set_par(struct fb_info *info){	switch (info->var.bits_per_pixel) {	case 1:		current_par.palette_size = 2;		info->fix.visual = FB_VISUAL_MONO10;		break;	case 2:		current_par.palette_size = 4;		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;		break;	case 4:		current_par.palette_size = 16;		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;		break;	case 8:		current_par.palette_size = VIDC_PALETTE_SIZE;#ifdef HAS_VIDC		info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;#else		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;#endif		break;#ifdef HAS_VIDC20	case 16:		current_par.palette_size = 32;		info->fix.visual = FB_VISUAL_DIRECTCOLOR;		break;	case 32:		current_par.palette_size = VIDC_PALETTE_SIZE;		info->fix.visual = FB_VISUAL_DIRECTCOLOR;		break;#endif	default:		BUG();	}	info->fix.line_length	= (info->var.xres * info->var.bits_per_pixel) / 8;#if defined(HAS_MEMC)	{		unsigned long size = info->fix.smem_len - VDMA_XFERSIZE;		memc_write(VDMA_START, 0);		memc_write(VDMA_END, size >> 2);	}#elif defined(HAS_IOMD)	{		unsigned long start, size;		u_int control;		start = info->fix.smem_start;		size  = current_par.screen_end;		if (current_par.using_vram) {			size -= current_par.vram_half_sam;			control = DMA_CR_E | (current_par.vram_half_sam / 256);		} else {			size -= 16;			control = DMA_CR_E | DMA_CR_D | 16;		}		iomd_writel(start,   IOMD_VIDSTART);		iomd_writel(size,    IOMD_VIDEND);		iomd_writel(control, IOMD_VIDCR);	}#endif	acornfb_update_dma(info, &info->var);	acornfb_set_timing(info);	return 0;}static intacornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	u_int y_bottom = var->yoffset;	if (!(var->vmode & FB_VMODE_YWRAP))		y_bottom += var->yres;	BUG_ON(y_bottom > var->yres_virtual);	acornfb_update_dma(info, var);	return 0;}/* * Note that we are entered with the kernel locked. */static intacornfb_mmap(struct fb_info *info, struct vm_area_struct *vma){	unsigned long off, start;	u32 len;	off = vma->vm_pgoff << PAGE_SHIFT;	start = info->fix.smem_start;	len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len;	start &= PAGE_MASK;	if ((vma->vm_end - vma->vm_start + off) > len)		return -EINVAL;	off += start;	vma->vm_pgoff = off >> PAGE_SHIFT;	/* This is an IO map - tell maydump to skip this VMA */	vma->vm_flags |= VM_IO;	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);	/*	 * Don't alter the page protection flags; we want to keep the area	 * cached for better performance.  This does mean that we may miss	 * some updates to the screen occasionally, but process switches	 * should cause the caches and buffers to be flushed often enough.	 */	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,				vma->vm_end - vma->vm_start,				vma->vm_page_prot))		return -EAGAIN;	return 0;}static struct fb_ops acornfb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= acornfb_check_var,	.fb_set_par	= acornfb_set_par,	.fb_setcolreg	= acornfb_setcolreg,	.fb_pan_display	= acornfb_pan_display,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,	.fb_mmap	= acornfb_mmap,};/* * Everything after here is initialisation!!! */static struct fb_videomode modedb[] __initdata = {	{	/* 320x256 @ 50Hz */		NULL, 50,  320,  256, 125000,  92,  62,  35, 19,  38, 2,		FB_SYNC_COMP_HIGH_ACT,		FB_VMODE_NONINTERLACED	}, {	/* 640x250 @ 50Hz, 15.6 kHz hsync */		NULL, 50,  640,  250,  62500, 185, 123,  38, 21,  76, 3,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x256 @ 50Hz, 15.6 kHz hsync */		NULL, 50,  640,  256,  62500, 185, 123,  35, 18,  76, 3,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x512 @ 50Hz, 26.8 kHz hsync */		NULL, 50,  640,  512,  41667, 113,  87,  18,  1,  56, 3,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x250 @ 70Hz, 31.5 kHz hsync */		NULL, 70,  640,  250,  39722,  48,  16, 109, 88,  96, 2,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x256 @ 70Hz, 31.5 kHz hsync */		NULL, 70,  640,  256,  39722,  48,  16, 106, 85,  96, 2,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x352 @ 70Hz, 31.5 kHz hsync */		NULL, 70,  640,  352,  39722,  48,  16,  58, 37,  96, 2,		0,		FB_VMODE_NONINTERLACED	}, {	/* 640x480 @ 60Hz, 31.5 kHz hsync */		NULL, 60,  640,  480,  39722,  48,  16,  32, 11,  96, 2,		0,		FB_VMODE_NONINTERLACED	}, {	/* 800x600 @ 56Hz, 35.2 kHz hsync */		NULL, 56,  800,  600,  27778, 101,  23,  22,  1, 100, 2,		0,		FB_VMODE_NONINTERLACED	}, {	/* 896x352 @ 60Hz, 21.8 kHz hsync */		NULL, 60,  896,  352,  41667,  59,  27,   9,  0, 118, 3,		0,		FB_VMODE_NONINTERLACED	}, {	/* 1024x 768 @ 60Hz, 48.4 kHz hsync */		NULL, 60, 1024,  768,  15385, 160,  24,  29,  3, 136, 6,		0,		FB_VMODE_NONINTERLACED	}, {	/* 1280x1024 @ 60Hz, 63.8 kHz hsync */		NULL, 60, 1280, 1024,   9090, 186,  96,  38,  1, 160, 3,		0,		FB_VMODE_NONINTERLACED	}};static struct fb_videomode __initdataacornfb_default_mode = {	.name =		NULL,	.refresh =	60,	.xres =		640,

⌨️ 快捷键说明

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