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

📄 gbefb.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	return 0;}static void gbefb_encode_fix(struct fb_fix_screeninfo *fix,			     struct fb_var_screeninfo *var){	memset(fix, 0, sizeof(struct fb_fix_screeninfo));	strcpy(fix->id, "SGI GBE");	fix->smem_start = (unsigned long) gbe_mem;	fix->smem_len = gbe_mem_size;	fix->type = FB_TYPE_PACKED_PIXELS;	fix->type_aux = 0;	fix->accel = FB_ACCEL_NONE;	switch (var->bits_per_pixel) {	case 8:		fix->visual = FB_VISUAL_PSEUDOCOLOR;		break;	default:		fix->visual = FB_VISUAL_TRUECOLOR;		break;	}	fix->ywrapstep = 0;	fix->xpanstep = 0;	fix->ypanstep = 0;	fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;	fix->mmio_start = GBE_BASE;	fix->mmio_len = sizeof(struct sgi_gbe);}/* *  Set a single color register. The values supplied are already *  rounded down to the hardware's capabilities (according to the *  entries in the var structure). Return != 0 for invalid regno. */static int gbefb_setcolreg(unsigned regno, unsigned red, unsigned green,			     unsigned blue, unsigned transp,			     struct fb_info *info){	int i;	if (regno > 255)		return 1;	red >>= 8;	green >>= 8;	blue >>= 8;	switch (info->var.bits_per_pixel) {	case 8:		/* wait for the color map FIFO to have a free entry */		for (i = 0; i < 1000 && gbe->cm_fifo >= 63; i++)			udelay(10);		if (i == 1000) {			printk(KERN_ERR "gbefb: cmap FIFO timeout\n");			return 1;		}		gbe->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);		break;	case 15:	case 16:		red >>= 3;		green >>= 3;		blue >>= 3;		pseudo_palette[regno] =			(red << info->var.red.offset) |			(green << info->var.green.offset) |			(blue << info->var.blue.offset);		break;	case 32:		pseudo_palette[regno] =			(red << info->var.red.offset) |			(green << info->var.green.offset) |			(blue << info->var.blue.offset);		break;	}	return 0;}/* *  Check video mode validity, eventually modify var to best match. */static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	unsigned int line_length;	struct gbe_timing_info timing;	/* Limit bpp to 8, 16, and 32 */	if (var->bits_per_pixel <= 8)		var->bits_per_pixel = 8;	else if (var->bits_per_pixel <= 16)		var->bits_per_pixel = 16;	else if (var->bits_per_pixel <= 32)		var->bits_per_pixel = 32;	else		return -EINVAL;	/* Check the mode can be mapped linearly with the tile table trick. */	/* This requires width x height x bytes/pixel be a multiple of 512 */	if ((var->xres * var->yres * var->bits_per_pixel) & 4095)		return -EINVAL;	var->grayscale = 0;	/* No grayscale for now */	if ((var->pixclock = compute_gbe_timing(var, &timing)) < 0)		return(-EINVAL);	/* Adjust virtual resolution, if necessary */	if (var->xres > var->xres_virtual || (!ywrap && !ypan))		var->xres_virtual = var->xres;	if (var->yres > var->yres_virtual || (!ywrap && !ypan))		var->yres_virtual = var->yres;	if (var->vmode & FB_VMODE_CONUPDATE) {		var->vmode |= FB_VMODE_YWRAP;		var->xoffset = info->var.xoffset;		var->yoffset = info->var.yoffset;	}	/* No grayscale for now */	var->grayscale = 0;	/* Memory limit */	line_length = var->xres_virtual * var->bits_per_pixel / 8;	if (line_length * var->yres_virtual > gbe_mem_size)		return -ENOMEM;	/* Virtual resolution too high */	switch (var->bits_per_pixel) {	case 8:		var->red.offset = 0;		var->red.length = 8;		var->green.offset = 0;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		break;	case 16:		/* RGB 1555 */		var->red.offset = 10;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 5;		var->blue.offset = 0;		var->blue.length = 5;		var->transp.offset = 0;		var->transp.length = 0;		break;	case 32:		/* RGB 8888 */		var->red.offset = 24;		var->red.length = 8;		var->green.offset = 16;		var->green.length = 8;		var->blue.offset = 8;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 8;		break;	}	var->red.msb_right = 0;	var->green.msb_right = 0;	var->blue.msb_right = 0;	var->transp.msb_right = 0;	var->left_margin = timing.htotal - timing.hsync_end;	var->right_margin = timing.hsync_start - timing.width;	var->upper_margin = timing.vtotal - timing.vsync_end;	var->lower_margin = timing.vsync_start - timing.height;	var->hsync_len = timing.hsync_end - timing.hsync_start;	var->vsync_len = timing.vsync_end - timing.vsync_start;	return 0;}static int gbefb_mmap(struct fb_info *info, struct file *file,			struct vm_area_struct *vma){	unsigned long size = vma->vm_end - vma->vm_start;	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	unsigned long addr;	unsigned long phys_addr, phys_size;	u16 *tile;	/* check range */	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	if (offset + size > gbe_mem_size)		return -EINVAL;	/* remap using the fastest write-through mode on architecture */	/* try not polluting the cache when possible */	pgprot_val(vma->vm_page_prot) =		pgprot_fb(pgprot_val(vma->vm_page_prot));	vma->vm_flags |= VM_IO | VM_RESERVED;	vma->vm_file = file;	/* look for the starting tile */	tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];	addr = vma->vm_start;	offset &= TILE_MASK;	/* remap each tile separately */	do {		phys_addr = (((unsigned long) (*tile)) << TILE_SHIFT) + offset;		if ((offset + size) < TILE_SIZE)			phys_size = size;		else			phys_size = TILE_SIZE - offset;		if (remap_page_range		    (vma, addr, phys_addr, phys_size, vma->vm_page_prot))			return -EAGAIN;		offset = 0;		size -= phys_size;		addr += phys_size;		tile++;	} while (size);	return 0;}static struct fb_ops gbefb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= gbefb_check_var,	.fb_set_par	= gbefb_set_par,	.fb_setcolreg	= gbefb_setcolreg,	.fb_mmap	= gbefb_mmap,	.fb_blank	= gbefb_blank,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,	.fb_cursor	= soft_cursor,};/* * Initialization */int __init gbefb_setup(char *options){	char *this_opt;	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!strncmp(this_opt, "monitor:", 8)) {			if (!strncmp(this_opt + 8, "crt", 3)) {				flat_panel_enabled = 0;				default_var = &default_var_CRT;				default_mode = &default_mode_CRT;			} else if (!strncmp(this_opt + 8, "1600sw", 6) ||				   !strncmp(this_opt + 8, "lcd", 3)) {				flat_panel_enabled = 1;				default_var = &default_var_LCD;				default_mode = &default_mode_LCD;			}		} else if (!strncmp(this_opt, "mem:", 4)) {			gbe_mem_size = memparse(this_opt + 4, &this_opt);			if (gbe_mem_size > CONFIG_FB_GBE_MEM * 1024 * 1024)				gbe_mem_size = CONFIG_FB_GBE_MEM * 1024 * 1024;			if (gbe_mem_size < TILE_SIZE)				gbe_mem_size = TILE_SIZE;		} else			mode_option = this_opt;	}	return 0;}int __init gbefb_init(void){	int i, ret = 0;#ifndef MODULE	char *option = NULL;	if (fb_get_options("gbefb", &option))		return -ENODEV;	gbefb_setup(options);#endif	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");		return -EBUSY;	}	gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe));	if (!gbe) {		printk(KERN_ERR "gbefb: couldn't map mmio region\n");		ret = -ENXIO;		goto out_release_mem_region;	}	gbe_revision = gbe->ctrlstat & 15;	gbe_tiles.cpu =		dma_alloc_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),				   &gbe_tiles.dma, GFP_KERNEL);	if (!gbe_tiles.cpu) {		printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");		ret = -ENOMEM;		goto out_unmap;	}	if (gbe_mem_phys) {		/* memory was allocated at boot time */		gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size);		gbe_dma_addr = 0;	} else {		/* try to allocate memory with the classical allocator		 * this has high chance to fail on low memory machines */		gbe_mem = dma_alloc_coherent(NULL, gbe_mem_size, &gbe_dma_addr,					     GFP_KERNEL);		gbe_mem_phys = (unsigned long) gbe_dma_addr;	}#ifdef CONFIG_X86	mtrr_add(gbe_mem_phys, gbe_mem_size, MTRR_TYPE_WRCOMB, 1);#endif	if (!gbe_mem) {		printk(KERN_ERR "gbefb: couldn't map framebuffer\n");		ret = -ENXIO;		goto out_tiles_free;	}	/* map framebuffer memory into tiles table */	for (i = 0; i < (gbe_mem_size >> TILE_SHIFT); i++)		gbe_tiles.cpu[i] = (gbe_mem_phys >> TILE_SHIFT) + i;	fb_info.currcon = -1;	fb_info.fbops = &gbefb_ops;	fb_info.pseudo_palette = pseudo_palette;	fb_info.flags = FBINFO_DEFAULT;	fb_info.screen_base = gbe_mem;	fb_alloc_cmap(&fb_info.cmap, 256, 0);	/* reset GBE */	gbe_reset();	/* turn on default video mode */	if (fb_find_mode(&par_current.var, &fb_info, mode_option, NULL, 0,			 default_mode, 8) == 0)		par_current.var = *default_var;	fb_info.var = par_current.var;	gbefb_check_var(&par_current.var, &fb_info);	gbefb_encode_fix(&fb_info.fix, &fb_info.var);	fb_info.par = &par_current;	if (register_framebuffer(&fb_info) < 0) {		ret = -ENXIO;		printk(KERN_ERR "gbefb: couldn't register framebuffer\n");		goto out_gbe_unmap;	}	printk(KERN_INFO "fb%d: %s rev %d @ 0x%08x using %dkB memory\n",	       fb_info.node, fb_info.fix.id, gbe_revision, (unsigned) GBE_BASE,	       gbe_mem_size >> 10);	return 0;out_gbe_unmap:	if (gbe_dma_addr)		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);	else		iounmap(gbe_mem);out_tiles_free:	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),			  (void *)gbe_tiles.cpu, gbe_tiles.dma);out_unmap:	iounmap(gbe);out_release_mem_region:	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));	return ret;}void __exit gbefb_exit(void){	unregister_framebuffer(&fb_info);	gbe_turn_off();	if (gbe_dma_addr)		dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);	else		iounmap(gbe_mem);	dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),			  (void *)gbe_tiles.cpu, gbe_tiles.dma);	release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));	iounmap(gbe);}module_init(gbefb_init);#ifdef MODULEmodule_exit(gbefb_exit);#endifMODULE_LICENSE("GPL");

⌨️ 快捷键说明

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