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

📄 atmel_lcdfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo){	struct fb_info *info = sinfo->info;	int ret = 0;	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;	dev_info(info->device,	       "%luKiB frame buffer at %08lx (mapped at %p)\n",	       (unsigned long)info->fix.smem_len / 1024,	       (unsigned long)info->fix.smem_start,	       info->screen_base);	/* Allocate colormap */	ret = fb_alloc_cmap(&info->cmap, 256, 0);	if (ret < 0)		dev_err(info->device, "Alloc color map failed\n");	return ret;}static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo){	if (sinfo->bus_clk)		clk_enable(sinfo->bus_clk);	clk_enable(sinfo->lcdc_clk);}static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo){	if (sinfo->bus_clk)		clk_disable(sinfo->bus_clk);	clk_disable(sinfo->lcdc_clk);}static int __init atmel_lcdfb_probe(struct platform_device *pdev){	struct device *dev = &pdev->dev;	struct fb_info *info;	struct atmel_lcdfb_info *sinfo;	struct atmel_lcdfb_info *pdata_sinfo;	struct fb_videomode fbmode;	struct resource *regs = NULL;	struct resource *map = NULL;	int ret;	dev_dbg(dev, "%s BEGIN\n", __func__);	ret = -ENOMEM;	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);	if (!info) {		dev_err(dev, "cannot allocate memory\n");		goto out;	}	sinfo = info->par;	if (dev->platform_data) {		pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;		sinfo->default_bpp = pdata_sinfo->default_bpp;		sinfo->default_dmacon = pdata_sinfo->default_dmacon;		sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;		sinfo->default_monspecs = pdata_sinfo->default_monspecs;		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;		sinfo->guard_time = pdata_sinfo->guard_time;		sinfo->smem_len = pdata_sinfo->smem_len;		sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;		sinfo->lcd_wiring_mode = pdata_sinfo->lcd_wiring_mode;	} else {		dev_err(dev, "cannot get default configuration\n");		goto free_info;	}	sinfo->info = info;	sinfo->pdev = pdev;	strcpy(info->fix.id, sinfo->pdev->name);	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;	info->pseudo_palette = sinfo->pseudo_palette;	info->fbops = &atmel_lcdfb_ops;	memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));	info->fix = atmel_lcdfb_fix;	/* Enable LCDC Clocks */	if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {		sinfo->bus_clk = clk_get(dev, "hck1");		if (IS_ERR(sinfo->bus_clk)) {			ret = PTR_ERR(sinfo->bus_clk);			goto free_info;		}	}	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");	if (IS_ERR(sinfo->lcdc_clk)) {		ret = PTR_ERR(sinfo->lcdc_clk);		goto put_bus_clk;	}	atmel_lcdfb_start_clock(sinfo);	ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,			info->monspecs.modedb_len, info->monspecs.modedb,			sinfo->default_bpp);	if (!ret) {		dev_err(dev, "no suitable video mode found\n");		goto stop_clk;	}	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!regs) {		dev_err(dev, "resources unusable\n");		ret = -ENXIO;		goto stop_clk;	}	sinfo->irq_base = platform_get_irq(pdev, 0);	if (sinfo->irq_base < 0) {		dev_err(dev, "unable to get irq\n");		ret = sinfo->irq_base;		goto stop_clk;	}	/* Initialize video memory */	map = platform_get_resource(pdev, IORESOURCE_MEM, 1);	if (map) {		/* use a pre-allocated memory buffer */		info->fix.smem_start = map->start;		info->fix.smem_len = map->end - map->start + 1;		if (!request_mem_region(info->fix.smem_start,					info->fix.smem_len, pdev->name)) {			ret = -EBUSY;			goto stop_clk;		}		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);		if (!info->screen_base)			goto release_intmem;		/*		 * Don't clear the framebuffer -- someone may have set		 * up a splash image.		 */	} else {		/* alocate memory buffer */		ret = atmel_lcdfb_alloc_video_memory(sinfo);		if (ret < 0) {			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);			goto stop_clk;		}	}	/* LCDC registers */	info->fix.mmio_start = regs->start;	info->fix.mmio_len = regs->end - regs->start + 1;	if (!request_mem_region(info->fix.mmio_start,				info->fix.mmio_len, pdev->name)) {		ret = -EBUSY;		goto free_fb;	}	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);	if (!sinfo->mmio) {		dev_err(dev, "cannot map LCDC registers\n");		goto release_mem;	}	/* Initialize PWM for contrast or backlight ("off") */	init_contrast(sinfo);	/* interrupt */	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);	if (ret) {		dev_err(dev, "request_irq failed: %d\n", ret);		goto unmap_mmio;	}	/* Some operations on the LCDC might sleep and	 * require a preemptible task context */	INIT_WORK(&sinfo->task, atmel_lcdfb_task);	ret = atmel_lcdfb_init_fbinfo(sinfo);	if (ret < 0) {		dev_err(dev, "init fbinfo failed: %d\n", ret);		goto unregister_irqs;	}	/*	 * This makes sure that our colour bitfield	 * descriptors are correctly initialised.	 */	atmel_lcdfb_check_var(&info->var, info);	ret = fb_set_var(info, &info->var);	if (ret) {		dev_warn(dev, "unable to set display parameters\n");		goto free_cmap;	}	dev_set_drvdata(dev, info);	/*	 * Tell the world that we're ready to go	 */	ret = register_framebuffer(info);	if (ret < 0) {		dev_err(dev, "failed to register framebuffer device: %d\n", ret);		goto reset_drvdata;	}	/* add selected videomode to modelist */	fb_var_to_videomode(&fbmode, &info->var);	fb_add_videomode(&fbmode, &info->modelist);	/* Power up the LCDC screen */	if (sinfo->atmel_lcdfb_power_control)		sinfo->atmel_lcdfb_power_control(1);	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n",		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);	return 0;reset_drvdata:	dev_set_drvdata(dev, NULL);free_cmap:	fb_dealloc_cmap(&info->cmap);unregister_irqs:	cancel_work_sync(&sinfo->task);	free_irq(sinfo->irq_base, info);unmap_mmio:	exit_backlight(sinfo);	iounmap(sinfo->mmio);release_mem: 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);free_fb:	if (map)		iounmap(info->screen_base);	else		atmel_lcdfb_free_video_memory(sinfo);release_intmem:	if (map)		release_mem_region(info->fix.smem_start, info->fix.smem_len);stop_clk:	atmel_lcdfb_stop_clock(sinfo);	clk_put(sinfo->lcdc_clk);put_bus_clk:	if (sinfo->bus_clk)		clk_put(sinfo->bus_clk);free_info:	framebuffer_release(info);out:	dev_dbg(dev, "%s FAILED\n", __func__);	return ret;}static int __exit atmel_lcdfb_remove(struct platform_device *pdev){	struct device *dev = &pdev->dev;	struct fb_info *info = dev_get_drvdata(dev);	struct atmel_lcdfb_info *sinfo;	if (!info || !info->par)		return 0;	sinfo = info->par;	cancel_work_sync(&sinfo->task);	exit_backlight(sinfo);	if (sinfo->atmel_lcdfb_power_control)		sinfo->atmel_lcdfb_power_control(0);	unregister_framebuffer(info);	atmel_lcdfb_stop_clock(sinfo);	clk_put(sinfo->lcdc_clk);	if (sinfo->bus_clk)		clk_put(sinfo->bus_clk);	fb_dealloc_cmap(&info->cmap);	free_irq(sinfo->irq_base, info);	iounmap(sinfo->mmio); 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {		iounmap(info->screen_base);		release_mem_region(info->fix.smem_start, info->fix.smem_len);	} else {		atmel_lcdfb_free_video_memory(sinfo);	}	dev_set_drvdata(dev, NULL);	framebuffer_release(info);	return 0;}#ifdef CONFIG_PMstatic int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg){	struct fb_info *info = platform_get_drvdata(pdev);	struct atmel_lcdfb_info *sinfo = info->par;	/*	 * We don't want to handle interrupts while the clock is	 * stopped. It may take forever.	 */	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);	if (sinfo->atmel_lcdfb_power_control)		sinfo->atmel_lcdfb_power_control(0);	atmel_lcdfb_stop(sinfo);	atmel_lcdfb_stop_clock(sinfo);	return 0;}static int atmel_lcdfb_resume(struct platform_device *pdev){	struct fb_info *info = platform_get_drvdata(pdev);	struct atmel_lcdfb_info *sinfo = info->par;	atmel_lcdfb_start_clock(sinfo);	atmel_lcdfb_start(sinfo);	if (sinfo->atmel_lcdfb_power_control)		sinfo->atmel_lcdfb_power_control(1);	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, sinfo->saved_lcdcon);	/* Enable FIFO & DMA errors */	lcdc_writel(sinfo, ATMEL_LCDC_IER, ATMEL_LCDC_UFLWI			| ATMEL_LCDC_OWRI | ATMEL_LCDC_MERI);	return 0;}#else#define atmel_lcdfb_suspend	NULL#define atmel_lcdfb_resume	NULL#endifstatic struct platform_driver atmel_lcdfb_driver = {	.remove		= __exit_p(atmel_lcdfb_remove),	.suspend	= atmel_lcdfb_suspend,	.resume		= atmel_lcdfb_resume,	.driver		= {		.name	= "atmel_lcdfb",		.owner	= THIS_MODULE,	},};static int __init atmel_lcdfb_init(void){	return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);}static void __exit atmel_lcdfb_exit(void){	platform_driver_unregister(&atmel_lcdfb_driver);}module_init(atmel_lcdfb_init);module_exit(atmel_lcdfb_exit);MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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