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

📄 acornfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		cmap = &fb_display[current_par.currcon].cmap;		if (cmap->len)			fb_get_cmap(cmap, 1, acornfb_getcolreg, info);	}	current_par.currcon = con;	fb_display[con].var.activate = FB_ACTIVATE_NOW;	acornfb_set_var(&fb_display[con].var, con, info);	return 0;}static voidacornfb_blank(int blank, struct fb_info *info){	union palette p;	int i, bpp = fb_display[current_par.currcon].var.bits_per_pixel;#ifdef FBCON_HAS_CFB16	if (bpp == 16) {		p.p = 0;		for (i = 0; i < 256; i++) {			if (blank)				p = acornfb_palette_encode(i, 0, 0, 0, 0);			else {				p.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;				p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;				p.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;			}			acornfb_palette_write(i, current_par.palette[i]);		}	} else#endif	{		for (i = 0; i < current_par.palette_size; i++) {			if (blank)				p = acornfb_palette_encode(i, 0, 0, 0, 0);			else				p = current_par.palette[i];			acornfb_palette_write(i, p);		}	}}/* * 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,	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 __initacornfb_init_fbinfo(void){	static int first = 1;	if (!first)		return;	first = 0;	strcpy(fb_info.modename, "Acorn");	strcpy(fb_info.fontname, "Acorn8x8");	fb_info.node		   = -1;	fb_info.fbops		   = &acornfb_ops;	fb_info.disp		   = &global_disp;	fb_info.changevar	   = NULL;	fb_info.switch_con	   = acornfb_switch;	fb_info.updatevar	   = acornfb_updatevar;	fb_info.blank		   = acornfb_blank;	fb_info.flags		   = FBINFO_FLAG_DEFAULT;	global_disp.dispsw	   = &fbcon_dummy;	/*	 * setup initial parameters	 */	memset(&init_var, 0, sizeof(init_var));#if defined(HAS_VIDC20)	init_var.red.length	   = 8;	init_var.transp.length	   = 4;#elif defined(HAS_VIDC)	init_var.red.length	   = 4;	init_var.transp.length	   = 1;#endif	init_var.green		   = init_var.red;	init_var.blue		   = init_var.red;	init_var.nonstd		   = 0;	init_var.activate	   = FB_ACTIVATE_NOW;	init_var.height		   = -1;	init_var.width		   = -1;	init_var.vmode		   = FB_VMODE_NONINTERLACED;	init_var.accel_flags	   = FB_ACCELF_TEXT;	current_par.dram_size	   = 0;	current_par.montype	   = -1;	current_par.dpms	   = 0;}/* * setup acornfb options: * *  font:fontname *	Set fontname * *  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_font(char *opt){	strcpy(fb_info.fontname, opt);}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;	init_var.width = simple_strtoul(p + 1, &p, 0);	if (*p != ':')		goto check_values;	init_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 = {	{ "font",    acornfb_parse_font    },	{ "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. */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);		atomic_set(&page->count, 1);		free_page(virtual_start);		virtual_start += PAGE_SIZE;		mb_freed += PAGE_SIZE / 1024;	}	printk("acornfb: freed %dK memory\n", mb_freed);}int __initacornfb_init(void){	unsigned long size;	u_int h_sync, v_sync;	int rc, i;	acornfb_init_fbinfo();	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 < sizeof(modedb) / sizeof(*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;		}	}	current_par.currcon	   = -1;	current_par.screen_base	   = SCREEN_BASE;	current_par.screen_base_p  = 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) {		/*		 * RiscPC needs to allocate the DRAM memory		 * for the framebuffer if we are not using		 * VRAM.  Archimedes/A5000 machines use a		 * fixed address for their framebuffers.		 */		int order = 0;		unsigned long page, top;		while (size > (PAGE_SIZE * (1 << order)))			order++;		current_par.screen_base = __get_free_pages(GFP_KERNEL, order);		if (current_par.screen_base == 0) {			printk(KERN_ERR "acornfb: unable to allocate screen "			       "memory\n");			return -ENOMEM;		}		top = current_par.screen_base + (PAGE_SIZE * (1 << order));		/* Mark the framebuffer pages as reserved so mmap will work. */		for (page = current_par.screen_base; 		     page < PAGE_ALIGN(current_par.screen_base + size);		     page += PAGE_SIZE)			SetPageReserved(virt_to_page(page));		/* Hand back any excess pages that we allocated. */		for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE)			free_page(page);		current_par.screen_base_p =			virt_to_phys((void *)current_par.screen_base);	}#endif#if defined(HAS_VIDC)	/*	 * Free unused pages	 */	free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);#endif		current_par.screen_size	   = 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(&init_var, &fb_info, NULL, modedb,				 sizeof(modedb) / sizeof(*modedb),				 &acornfb_default_mode, DEFAULT_BPP);		/*		 * If we found an exact match, all ok.		 */		if (rc == 1)			break;		rc = fb_find_mode(&init_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(&init_var, &fb_info, NULL, modedb,				 sizeof(modedb) / sizeof(*modedb),				 &acornfb_default_mode, DEFAULT_BPP);		if (rc)			break;		rc = fb_find_mode(&init_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 / init_var.pixclock;	h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +		 init_var.right_margin + init_var.hsync_len);	v_sync = h_sync / (init_var.yres + init_var.upper_margin +		 init_var.lower_margin + init_var.vsync_len);	printk(KERN_INFO "Acornfb: %ldkB %cRAM, %s, using %dx%d, "		"%d.%03dkHz, %dHz\n",		current_par.screen_size / 1024,		current_par.using_vram ? 'V' : 'D',		VIDC_NAME, init_var.xres, init_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 (acornfb_set_var(&init_var, -1, &fb_info))		printk(KERN_ERR "Acornfb: unable to set display parameters\n");	if (register_framebuffer(&fb_info) < 0)		return -EINVAL;	return 0;}MODULE_AUTHOR("Russell King");MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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