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

📄 acornfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	.yres =		480,	.pixclock =	39722,	.left_margin =	56,	.right_margin =	16,	.upper_margin =	34,	.lower_margin =	9,	.hsync_len =	88,	.vsync_len =	2,	.sync =		0,	.vmode =	FB_VMODE_NONINTERLACED};static void __init acornfb_init_fbinfo(void){	static int first = 1;	if (!first)		return;	first = 0;	fb_info.fbops		= &acornfb_ops;	fb_info.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;	fb_info.pseudo_palette	= current_par.pseudo_palette;	strcpy(fb_info.fix.id, "Acorn");	fb_info.fix.type	= FB_TYPE_PACKED_PIXELS;	fb_info.fix.type_aux	= 0;	fb_info.fix.xpanstep	= 0;	fb_info.fix.ypanstep	= 1;	fb_info.fix.ywrapstep	= 1;	fb_info.fix.line_length	= 0;	fb_info.fix.accel	= FB_ACCEL_NONE;	/*	 * setup initial parameters	 */	memset(&fb_info.var, 0, sizeof(fb_info.var));#if defined(HAS_VIDC20)	fb_info.var.red.length	   = 8;	fb_info.var.transp.length  = 4;#elif defined(HAS_VIDC)	fb_info.var.red.length	   = 4;	fb_info.var.transp.length  = 1;#endif	fb_info.var.green	   = fb_info.var.red;	fb_info.var.blue	   = fb_info.var.red;	fb_info.var.nonstd	   = 0;	fb_info.var.activate	   = FB_ACTIVATE_NOW;	fb_info.var.height	   = -1;	fb_info.var.width	   = -1;	fb_info.var.vmode	   = FB_VMODE_NONINTERLACED;	fb_info.var.accel_flags	   = FB_ACCELF_TEXT;	current_par.dram_size	   = 0;	current_par.montype	   = -1;	current_par.dpms	   = 0;}/* * setup acornfb options: * *  mon:hmin-hmax:vmin-vmax:dpms:width:height *	Set monitor parameters: *		hmin   = horizontal minimum frequency (Hz) *		hmax   = horizontal maximum frequency (Hz)	(optional) *		vmin   = vertical minimum frequency (Hz) *		vmax   = vertical maximum frequency (Hz)	(optional) *		dpms   = DPMS supported?			(optional) *		width  = width of picture in mm.		(optional) *		height = height of picture in mm.		(optional) * * montype:type *	Set RISC-OS style monitor type: *		0 (or tv)	- TV frequency *		1 (or multi)	- Multi frequency *		2 (or hires)	- Hi-res monochrome *		3 (or vga)	- VGA *		4 (or svga)	- SVGA *		auto, or option missing *				- try hardware detect * * dram:size *	Set the amount of DRAM to use for the frame buffer *	(even if you have VRAM). *	size can optionally be followed by 'M' or 'K' for *	MB or KB respectively. */static void __initacornfb_parse_mon(char *opt){	char *p = opt;	current_par.montype = -2;	fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0);	if (*p == '-')		fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0);	else		fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;	if (*p != ':')		goto bad;	fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0);	if (*p == '-')		fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0);	else		fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;	if (*p != ':')		goto check_values;	fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0);	if (*p != ':')		goto check_values;	fb_info.var.width = simple_strtoul(p + 1, &p, 0);	if (*p != ':')		goto check_values;	fb_info.var.height = simple_strtoul(p + 1, NULL, 0);check_values:	if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin ||	    fb_info.monspecs.vfmax < fb_info.monspecs.vfmin)		goto bad;	return;bad:	printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt);	current_par.montype = -1;}static void __initacornfb_parse_montype(char *opt){	current_par.montype = -2;	if (strncmp(opt, "tv", 2) == 0) {		opt += 2;		current_par.montype = 0;	} else if (strncmp(opt, "multi", 5) == 0) {		opt += 5;		current_par.montype = 1;	} else if (strncmp(opt, "hires", 5) == 0) {		opt += 5;		current_par.montype = 2;	} else if (strncmp(opt, "vga", 3) == 0) {		opt += 3;		current_par.montype = 3;	} else if (strncmp(opt, "svga", 4) == 0) {		opt += 4;		current_par.montype = 4;	} else if (strncmp(opt, "auto", 4) == 0) {		opt += 4;		current_par.montype = -1;	} else if (isdigit(*opt))		current_par.montype = simple_strtoul(opt, &opt, 0);	if (current_par.montype == -2 ||	    current_par.montype > NR_MONTYPES) {		printk(KERN_ERR "acornfb: unknown monitor type: %s\n",			opt);		current_par.montype = -1;	} else	if (opt && *opt) {		if (strcmp(opt, ",dpms") == 0)			current_par.dpms = 1;		else			printk(KERN_ERR			       "acornfb: unknown monitor option: %s\n",			       opt);	}}static void __initacornfb_parse_dram(char *opt){	unsigned int size;	size = simple_strtoul(opt, &opt, 0);	if (opt) {		switch (*opt) {		case 'M':		case 'm':			size *= 1024;		case 'K':		case 'k':			size *= 1024;		default:			break;		}	}	current_par.dram_size = size;}static struct options {	char *name;	void (*parse)(char *opt);} opt_table[] __initdata = {	{ "mon",     acornfb_parse_mon     },	{ "montype", acornfb_parse_montype },	{ "dram",    acornfb_parse_dram    },	{ NULL, NULL }};int __initacornfb_setup(char *options){	struct options *optp;	char *opt;	if (!options || !*options)		return 0;	acornfb_init_fbinfo();	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;		for (optp = opt_table; optp->name; optp++) {			int optlen;			optlen = strlen(optp->name);			if (strncmp(opt, optp->name, optlen) == 0 &&			    opt[optlen] == ':') {				optp->parse(opt + optlen + 1);				break;			}		}		if (!optp->name)			printk(KERN_ERR "acornfb: unknown parameter: %s\n",			       opt);	}	return 0;}/* * Detect type of monitor connected *  For now, we just assume SVGA */static int __initacornfb_detect_monitortype(void){	return 4;}/* * This enables the unused memory to be freed on older Acorn machines. * We are freeing memory on behalf of the architecture initialisation * code here. */static inline voidfree_unused_pages(unsigned int virtual_start, unsigned int virtual_end){	int mb_freed = 0;	/*	 * Align addresses	 */	virtual_start = PAGE_ALIGN(virtual_start);	virtual_end = PAGE_ALIGN(virtual_end);	while (virtual_start < virtual_end) {		struct page *page;		/*		 * Clear page reserved bit,		 * set count to 1, and free		 * the page.		 */		page = virt_to_page(virtual_start);		ClearPageReserved(page);		init_page_count(page);		free_page(virtual_start);		virtual_start += PAGE_SIZE;		mb_freed += PAGE_SIZE / 1024;	}	printk("acornfb: freed %dK memory\n", mb_freed);}static int __init acornfb_probe(struct platform_device *dev){	unsigned long size;	u_int h_sync, v_sync;	int rc, i;	char *option = NULL;	if (fb_get_options("acornfb", &option))		return -ENODEV;	acornfb_setup(option);	acornfb_init_fbinfo();	current_par.dev = &dev->dev;	if (current_par.montype == -1)		current_par.montype = acornfb_detect_monitortype();	if (current_par.montype == -1 || current_par.montype > NR_MONTYPES)		current_par.montype = 4;	if (current_par.montype >= 0) {		fb_info.monspecs = monspecs[current_par.montype];		fb_info.monspecs.dpms = current_par.dpms;	}	/*	 * Try to select a suitable default mode	 */	for (i = 0; i < ARRAY_SIZE(modedb); i++) {		unsigned long hs;		hs = modedb[i].refresh *		     (modedb[i].yres + modedb[i].upper_margin +		      modedb[i].lower_margin + modedb[i].vsync_len);		if (modedb[i].xres == DEFAULT_XRES &&		    modedb[i].yres == DEFAULT_YRES &&		    modedb[i].refresh >= fb_info.monspecs.vfmin &&		    modedb[i].refresh <= fb_info.monspecs.vfmax &&		    hs                >= fb_info.monspecs.hfmin &&		    hs                <= fb_info.monspecs.hfmax) {			acornfb_default_mode = modedb[i];			break;		}	}	fb_info.screen_base    = (char *)SCREEN_BASE;	fb_info.fix.smem_start = SCREEN_START;	current_par.using_vram = 0;	/*	 * If vram_size is set, we are using VRAM in	 * a Risc PC.  However, if the user has specified	 * an amount of DRAM then use that instead.	 */	if (vram_size && !current_par.dram_size) {		size = vram_size;		current_par.vram_half_sam = vram_size / 1024;		current_par.using_vram = 1;	} else if (current_par.dram_size)		size = current_par.dram_size;	else		size = MAX_SIZE;	/*	 * Limit maximum screen size.	 */	if (size > MAX_SIZE)		size = MAX_SIZE;	size = PAGE_ALIGN(size);#if defined(HAS_VIDC20)	if (!current_par.using_vram) {		dma_addr_t handle;		void *base;		/*		 * RiscPC needs to allocate the DRAM memory		 * for the framebuffer if we are not using		 * VRAM.		 */		base = dma_alloc_writecombine(current_par.dev, size, &handle,					      GFP_KERNEL);		if (base == NULL) {			printk(KERN_ERR "acornfb: unable to allocate screen "			       "memory\n");			return -ENOMEM;		}		fb_info.screen_base = base;		fb_info.fix.smem_start = handle;	}#endif#if defined(HAS_VIDC)	/*	 * Archimedes/A5000 machines use a fixed address for their	 * framebuffers.  Free unused pages	 */	free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);#endif	fb_info.fix.smem_len = size;	current_par.palette_size   = VIDC_PALETTE_SIZE;	/*	 * Lookup the timing for this resolution.  If we can't	 * find it, then we can't restore it if we change	 * the resolution, so we disable this feature.	 */	do {		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,				 ARRAY_SIZE(modedb),				 &acornfb_default_mode, DEFAULT_BPP);		/*		 * If we found an exact match, all ok.		 */		if (rc == 1)			break;		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,				  &acornfb_default_mode, DEFAULT_BPP);		/*		 * If we found an exact match, all ok.		 */		if (rc == 1)			break;		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb,				 ARRAY_SIZE(modedb),				 &acornfb_default_mode, DEFAULT_BPP);		if (rc)			break;		rc = fb_find_mode(&fb_info.var, &fb_info, NULL, NULL, 0,				  &acornfb_default_mode, DEFAULT_BPP);	} while (0);	/*	 * If we didn't find an exact match, try the	 * generic database.	 */	if (rc == 0) {		printk("Acornfb: no valid mode found\n");		return -EINVAL;	}	h_sync = 1953125000 / fb_info.var.pixclock;	h_sync = h_sync * 512 / (fb_info.var.xres + fb_info.var.left_margin +		 fb_info.var.right_margin + fb_info.var.hsync_len);	v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +		 fb_info.var.lower_margin + fb_info.var.vsync_len);	printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "		"%d.%03dkHz, %dHz\n",		fb_info.fix.smem_len / 1024,		current_par.using_vram ? 'V' : 'D',		VIDC_NAME, fb_info.var.xres, fb_info.var.yres,		h_sync / 1000, h_sync % 1000, v_sync);	printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n",		fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000,		fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000,		fb_info.monspecs.vfmin, fb_info.monspecs.vfmax,		fb_info.monspecs.dpms ? ", DPMS" : "");	if (fb_set_var(&fb_info, &fb_info.var))		printk(KERN_ERR "Acornfb: unable to set display parameters\n");	if (register_framebuffer(&fb_info) < 0)		return -EINVAL;	return 0;}static struct platform_driver acornfb_driver = {	.probe	= acornfb_probe,	.driver	= {		.name	= "acornfb",	},};static int __init acornfb_init(void){	return platform_driver_register(&acornfb_driver);}module_init(acornfb_init);MODULE_AUTHOR("Russell King");MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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