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

📄 pxafb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		goto decode_mode;	}	if (lcd_conn == LCD_MONO_STN_8BPP)		fbi->lccr0 |= LCCR0_DPD;	fbi->lccr0 |= (lcd_conn & LCD_ALTERNATE_MAPPING) ? LCCR0_LDDALT : 0;	fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);	fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;	fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL)  ? LCCR3_PCP : 0;decode_mode:	pxafb_setmode(&fbi->fb.var, &inf->modes[0]);	/* decide video memory size as follows:	 * 1. default to mode of maximum resolution	 * 2. allow platform to override	 * 3. allow module parameter to override	 */	for (i = 0, m = &inf->modes[0]; i < inf->num_modes; i++, m++)		fbi->video_mem_size = max_t(size_t, fbi->video_mem_size,				m->xres * m->yres * m->bpp / 8);	if (inf->video_mem_size > fbi->video_mem_size)		fbi->video_mem_size = inf->video_mem_size;	if (video_mem_size > fbi->video_mem_size)		fbi->video_mem_size = video_mem_size;}static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev){	struct pxafb_info *fbi;	void *addr;	struct pxafb_mach_info *inf = dev->platform_data;	/* Alloc the pxafb_info and pseudo_palette in one step */	fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);	if (!fbi)		return NULL;	memset(fbi, 0, sizeof(struct pxafb_info));	fbi->dev = dev;	fbi->clk = clk_get(dev, NULL);	if (IS_ERR(fbi->clk)) {		kfree(fbi);		return NULL;	}	strcpy(fbi->fb.fix.id, PXA_NAME);	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;	fbi->fb.fix.type_aux	= 0;	fbi->fb.fix.xpanstep	= 0;	fbi->fb.fix.ypanstep	= 1;	fbi->fb.fix.ywrapstep	= 0;	fbi->fb.fix.accel	= FB_ACCEL_NONE;	fbi->fb.var.nonstd	= 0;	fbi->fb.var.activate	= FB_ACTIVATE_NOW;	fbi->fb.var.height	= -1;	fbi->fb.var.width	= -1;	fbi->fb.var.accel_flags	= FB_ACCELF_TEXT;	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;	fbi->fb.fbops		= &pxafb_ops;	fbi->fb.flags		= FBINFO_DEFAULT;	fbi->fb.node		= -1;	addr = fbi;	addr = addr + sizeof(struct pxafb_info);	fbi->fb.pseudo_palette	= addr;	fbi->state		= C_STARTUP;	fbi->task_state		= (u_char)-1;	pxafb_decode_mach_info(fbi, inf);	init_waitqueue_head(&fbi->ctrlr_wait);	INIT_WORK(&fbi->task, pxafb_task);	mutex_init(&fbi->ctrlr_lock);	init_completion(&fbi->disable_done);	return fbi;}#ifdef CONFIG_FB_PXA_PARAMETERSstatic int __devinit parse_opt_mode(struct device *dev, const char *this_opt){	struct pxafb_mach_info *inf = dev->platform_data;	const char *name = this_opt+5;	unsigned int namelen = strlen(name);	int res_specified = 0, bpp_specified = 0;	unsigned int xres = 0, yres = 0, bpp = 0;	int yres_specified = 0;	int i;	for (i = namelen-1; i >= 0; i--) {		switch (name[i]) {		case '-':			namelen = i;			if (!bpp_specified && !yres_specified) {				bpp = simple_strtoul(&name[i+1], NULL, 0);				bpp_specified = 1;			} else				goto done;			break;		case 'x':			if (!yres_specified) {				yres = simple_strtoul(&name[i+1], NULL, 0);				yres_specified = 1;			} else				goto done;			break;		case '0' ... '9':			break;		default:			goto done;		}	}	if (i < 0 && yres_specified) {		xres = simple_strtoul(name, NULL, 0);		res_specified = 1;	}done:	if (res_specified) {		dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);		inf->modes[0].xres = xres; inf->modes[0].yres = yres;	}	if (bpp_specified)		switch (bpp) {		case 1:		case 2:		case 4:		case 8:		case 16:			inf->modes[0].bpp = bpp;			dev_info(dev, "overriding bit depth: %d\n", bpp);			break;		default:			dev_err(dev, "Depth %d is not valid\n", bpp);			return -EINVAL;		}	return 0;}static int __devinit parse_opt(struct device *dev, char *this_opt){	struct pxafb_mach_info *inf = dev->platform_data;	struct pxafb_mode_info *mode = &inf->modes[0];	char s[64];	s[0] = '\0';	if (!strncmp(this_opt, "vmem:", 5)) {		video_mem_size = memparse(this_opt + 5, NULL);	} else if (!strncmp(this_opt, "mode:", 5)) {		return parse_opt_mode(dev, this_opt);	} else if (!strncmp(this_opt, "pixclock:", 9)) {		mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);		sprintf(s, "pixclock: %ld\n", mode->pixclock);	} else if (!strncmp(this_opt, "left:", 5)) {		mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);		sprintf(s, "left: %u\n", mode->left_margin);	} else if (!strncmp(this_opt, "right:", 6)) {		mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);		sprintf(s, "right: %u\n", mode->right_margin);	} else if (!strncmp(this_opt, "upper:", 6)) {		mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);		sprintf(s, "upper: %u\n", mode->upper_margin);	} else if (!strncmp(this_opt, "lower:", 6)) {		mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);		sprintf(s, "lower: %u\n", mode->lower_margin);	} else if (!strncmp(this_opt, "hsynclen:", 9)) {		mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);		sprintf(s, "hsynclen: %u\n", mode->hsync_len);	} else if (!strncmp(this_opt, "vsynclen:", 9)) {		mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);		sprintf(s, "vsynclen: %u\n", mode->vsync_len);	} else if (!strncmp(this_opt, "hsync:", 6)) {		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {			sprintf(s, "hsync: Active Low\n");			mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;		} else {			sprintf(s, "hsync: Active High\n");			mode->sync |= FB_SYNC_HOR_HIGH_ACT;		}	} else if (!strncmp(this_opt, "vsync:", 6)) {		if (simple_strtoul(this_opt+6, NULL, 0) == 0) {			sprintf(s, "vsync: Active Low\n");			mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;		} else {			sprintf(s, "vsync: Active High\n");			mode->sync |= FB_SYNC_VERT_HIGH_ACT;		}	} else if (!strncmp(this_opt, "dpc:", 4)) {		if (simple_strtoul(this_opt+4, NULL, 0) == 0) {			sprintf(s, "double pixel clock: false\n");			inf->lccr3 &= ~LCCR3_DPC;		} else {			sprintf(s, "double pixel clock: true\n");			inf->lccr3 |= LCCR3_DPC;		}	} else if (!strncmp(this_opt, "outputen:", 9)) {		if (simple_strtoul(this_opt+9, NULL, 0) == 0) {			sprintf(s, "output enable: active low\n");			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;		} else {			sprintf(s, "output enable: active high\n");			inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;		}	} else if (!strncmp(this_opt, "pixclockpol:", 12)) {		if (simple_strtoul(this_opt+12, NULL, 0) == 0) {			sprintf(s, "pixel clock polarity: falling edge\n");			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;		} else {			sprintf(s, "pixel clock polarity: rising edge\n");			inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;		}	} else if (!strncmp(this_opt, "color", 5)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;	} else if (!strncmp(this_opt, "mono", 4)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;	} else if (!strncmp(this_opt, "active", 6)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;	} else if (!strncmp(this_opt, "passive", 7)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;	} else if (!strncmp(this_opt, "single", 6)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;	} else if (!strncmp(this_opt, "dual", 4)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;	} else if (!strncmp(this_opt, "4pix", 4)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;	} else if (!strncmp(this_opt, "8pix", 4)) {		inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;	} else {		dev_err(dev, "unknown option: %s\n", this_opt);		return -EINVAL;	}	if (s[0] != '\0')		dev_info(dev, "override %s", s);	return 0;}static int __devinit pxafb_parse_options(struct device *dev, char *options){	char *this_opt;	int ret;	if (!options || !*options)		return 0;	dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");	/* could be made table driven or similar?... */	while ((this_opt = strsep(&options, ",")) != NULL) {		ret = parse_opt(dev, this_opt);		if (ret)			return ret;	}	return 0;}static char g_options[256] __devinitdata = "";#ifndef MODULEstatic int __init pxafb_setup_options(void){	char *options = NULL;	if (fb_get_options("pxafb", &options))		return -ENODEV;	if (options)		strlcpy(g_options, options, sizeof(g_options));	return 0;}#else#define pxafb_setup_options()		(0)module_param_string(options, g_options, sizeof(g_options), 0);MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");#endif#else#define pxafb_parse_options(...)	(0)#define pxafb_setup_options()		(0)#endif#ifdef DEBUG_VAR/* Check for various illegal bit-combinations. Currently only * a warning is given. */static void __devinit pxafb_check_options(struct device *dev,					  struct pxafb_mach_info *inf){	if (inf->lcd_conn)		return;	if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)		dev_warn(dev, "machine LCCR0 setting contains "				"illegal bits: %08x\n",			inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);	if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)		dev_warn(dev, "machine LCCR3 setting contains "				"illegal bits: %08x\n",			inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);	if (inf->lccr0 & LCCR0_DPD &&	    ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||	     (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||	     (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))		dev_warn(dev, "Double Pixel Data (DPD) mode is "				"only valid in passive mono"				" single panel mode\n");	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&	    (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)		dev_warn(dev, "Dual panel only valid in passive mode\n");	if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&	     (inf->modes->upper_margin || inf->modes->lower_margin))		dev_warn(dev, "Upper and lower margins must be 0 in "				"passive mode\n");}#else#define pxafb_check_options(...)	do {} while (0)#endifstatic int __devinit pxafb_probe(struct platform_device *dev){	struct pxafb_info *fbi;	struct pxafb_mach_info *inf;	struct resource *r;	int irq, ret;	dev_dbg(&dev->dev, "pxafb_probe\n");	inf = dev->dev.platform_data;	ret = -ENOMEM;	fbi = NULL;	if (!inf)		goto failed;	ret = pxafb_parse_options(&dev->dev, g_options);	if (ret < 0)		goto failed;	pxafb_check_options(&dev->dev, inf);	dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",			inf->modes->xres,			inf->modes->yres,			inf->modes->bpp);	if (inf->modes->xres == 0 ||	    inf->modes->yres == 0 ||	    inf->modes->bpp == 0) {		dev_err(&dev->dev, "Invalid resolution or bit depth\n");		ret = -EINVAL;		goto failed;	}	fbi = pxafb_init_fbinfo(&dev->dev);	if (!fbi) {		/* only reason for pxafb_init_fbinfo to fail is kmalloc */		dev_err(&dev->dev, "Failed to initialize framebuffer device\n");		ret = -ENOMEM;		goto failed;	}	fbi->backlight_power = inf->pxafb_backlight_power;	fbi->lcd_power = inf->pxafb_lcd_power;	r = platform_get_resource(dev, IORESOURCE_MEM, 0);	if (r == NULL) {		dev_err(&dev->dev, "no I/O memory resource defined\n");		ret = -ENODEV;		goto failed_fbi;	}	r = request_mem_region(r->start, r->end - r->start + 1, dev->name);	if (r == NULL) {		dev_err(&dev->dev, "failed to request I/O memory\n");		ret = -EBUSY;		goto failed_fbi;	}	fbi->mmio_base = ioremap(r->start, r->end - r->start + 1);	if (fbi->mmio_base == NULL) {		dev_err(&dev->dev, "failed to map I/O memory\n");		ret = -EBUSY;		goto failed_free_res;	}	fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));	fbi->dma_buff = dma_alloc_coherent(fbi->dev, fbi->dma_buff_size,				&fbi->dma_buff_phys, GFP_KERNEL);	if (fbi->dma_buff == NULL) {		dev_err(&dev->dev, "failed to allocate memory for DMA\n");		ret = -ENOMEM;		goto failed_free_io;	}	ret = pxafb_init_video_memory(fbi);	if (ret) {		dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);		ret = -ENOMEM;		goto failed_free_dma;	}	irq = platform_get_irq(dev, 0);	if (irq < 0) {		dev_err(&dev->dev, "no IRQ defined\n");		ret = -ENODEV;		goto failed_free_mem;	}	ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);	if (ret) {		dev_err(&dev->dev, "request_irq failed: %d\n", ret);		ret = -EBUSY;		goto failed_free_mem;	}	ret = pxafb_smart_init(fbi);	if (ret) {		dev_err(&dev->dev, "failed to initialize smartpanel\n");		goto failed_free_irq;	}	/*	 * This makes sure that our colour bitfield	 * descriptors are correctly initialised.	 */	ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);	if (ret) {		dev_err(&dev->dev, "failed to get suitable mode\n");		goto failed_free_irq;	}	ret = pxafb_set_par(&fbi->fb);	if (ret) {		dev_err(&dev->dev, "Failed to set parameters\n");		goto failed_free_irq;	}	platform_set_drvdata(dev, fbi);	ret = register_framebuffer(&fbi->fb);	if (ret < 0) {		dev_err(&dev->dev,			"Failed to register framebuffer device: %d\n", ret);		goto failed_free_cmap;	}	pxafb_overlay_init(fbi);#ifdef CONFIG_CPU_FREQ	fbi->freq_transition.notifier_call = pxafb_freq_transition;	fbi->freq_policy.notifier_call = pxafb_freq_policy;	cpufreq_register_notifier(&fbi->freq_transition,				CPUFREQ_TRANSITION_NOTIFIER);	cpufreq_register_notifier(&fbi->freq_policy,				CPUFREQ_POLICY_NOTIFIER);#endif	/*	 * Ok, now enable the LCD controller	 */	set_ctrlr_state(fbi, C_ENABLE);	return 0;failed_free_cmap:	if (fbi->fb.cmap.len)		fb_dealloc_cmap(&fbi->fb.cmap);failed_free_irq:	free_irq(irq, fbi);failed_free_mem:	free_pages_exact(fbi->video_mem, fbi->video_mem_size);failed_free_dma:	dma_free_coherent(&dev->dev, fbi->dma_buff_size,			fbi->dma_buff, fbi->dma_buff_phys);failed_free_io:	iounmap(fbi->mmio_base);failed_free_res:	release_mem_region(r->start, r->end - r->start + 1);failed_fbi:	clk_put(fbi->clk);	platform_set_drvdata(dev, NULL);	kfree(fbi);failed:	return ret;}static int __devexit pxafb_remove(struct platform_device *dev){	struct pxafb_info *fbi = platform_get_drvdata(dev);	struct resource *r;	int irq;	struct fb_info *info;	if (!fbi)		return 0;	info = &fbi->fb;	pxafb_overlay_exit(fbi);	unregister_framebuffer(info);	pxafb_disable_controller(fbi);	if (fbi->fb.cmap.len)		fb_dealloc_cmap(&fbi->fb.cmap);	irq = platform_get_irq(dev, 0);	free_irq(irq, fbi);	free_pages_exact(fbi->video_mem, fbi->video_mem_size);	dma_free_writecombine(&dev->dev, fbi->dma_buff_size,			fbi->dma_buff, fbi->dma_buff_phys);	iounmap(fbi->mmio_base);	r = platform_get_resource(dev, IORESOURCE_MEM, 0);	release_mem_region(r->start, r->end - r->start + 1);	clk_put(fbi->clk);	kfree(fbi);	return 0;}static struct platform_driver pxafb_driver = {	.probe		= pxafb_probe,	.remove 	= __devexit_p(pxafb_remove),	.suspend	= pxafb_suspend,	.resume		= pxafb_resume,	.driver		= {		.owner	= THIS_MODULE,		.name	= "pxa2xx-fb",	},};static int __init pxafb_init(void){	if (pxafb_setup_options())		return -EINVAL;	return platform_driver_register(&pxafb_driver);}static void __exit pxafb_exit(void){	platform_driver_unregister(&pxafb_driver);}module_init(pxafb_init);module_exit(pxafb_exit);MODULE_DESCRIPTION("loadable framebuffer driver for PXA");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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