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

📄 s3c2410fb.c

📁 S3C2410 LCD驱动 | |-- s3c2410fb.c | `-- s3c2410fb.h
💻 C
📖 第 1 页 / 共 2 页
字号:
static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf){	return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");}static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,					   const char *buf, size_t len){	if (mach_info == NULL)		return -EINVAL;	if (len < 1)		return -EINVAL;	if (strnicmp(buf, "on", 2) == 0 ||	    strnicmp(buf, "1", 1) == 0) {		debug = 1;		printk(KERN_DEBUG "s3c2410fb: Debug On");	} else if (strnicmp(buf, "off", 3) == 0 ||		   strnicmp(buf, "0", 1) == 0) {		debug = 0;		printk(KERN_DEBUG "s3c2410fb: Debug Off");	} else {		return -EINVAL;	}	return len;}static DEVICE_ATTR(debug, 0666,		   s3c2410fb_debug_show,		   s3c2410fb_debug_store);static struct fb_ops s3c2410fb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= s3c2410fb_check_var,	.fb_set_par	= s3c2410fb_set_par,	.fb_blank	= s3c2410fb_blank,	.fb_setcolreg	= s3c2410fb_setcolreg,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,};/* * s3c2410fb_map_video_memory(): *	Allocates the DRAM memory for the frame buffer.  This buffer is *	remapped into a non-cached, non-buffered, memory region to *	allow palette and pixel writes to occur without flushing the *	cache.  Once this area is remapped, all virtual memory *	access to the video memory should occur at the new region. */static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi){	dprintk("map_video_memory(fbi=%p)\n", fbi);	fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);	fbi->map_cpu  = dma_alloc_writecombine(fbi->dev, fbi->map_size,					       &fbi->map_dma, GFP_KERNEL);	fbi->map_size = fbi->fb->fix.smem_len;	if (fbi->map_cpu) {		/* prevent initial garbage on screen */		dprintk("map_video_memory: clear %p:%08x\n",			fbi->map_cpu, fbi->map_size);		memset(fbi->map_cpu, 0xf0, fbi->map_size);		fbi->screen_dma		= fbi->map_dma;		fbi->fb->screen_base	= fbi->map_cpu;		fbi->fb->fix.smem_start  = fbi->screen_dma;		dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",			fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);	}	return fbi->map_cpu ? 0 : -ENOMEM;}static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi){	dma_free_writecombine(fbi->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma);}static inline void modify_gpio(void __iomem *reg,			       unsigned long set, unsigned long mask){	unsigned long tmp;	tmp = readl(reg) & ~mask;	writel(tmp | set, reg);}/* * s3c2410fb_init_registers - Initialise all LCD-related registers */static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi){	unsigned long flags;	/* Initialise LCD with values from haret */	local_irq_save(flags);	/* modify the gpio(s) with interrupts set (bjd) */	modify_gpio(S3C2410_GPCUP,  mach_info->gpcup,  mach_info->gpcup_mask);	modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);	modify_gpio(S3C2410_GPDUP,  mach_info->gpdup,  mach_info->gpdup_mask);	modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);	local_irq_restore(flags);	writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);	writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);	writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);	writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);	writel(fbi->regs.lcdcon5, S3C2410_LCDCON5); 	s3c2410fb_set_lcdaddr(fbi);	dprintk("LPCSEL    = 0x%08lx\n", mach_info->lpcsel);	writel(mach_info->lpcsel, S3C2410_LPCSEL);	dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL));	/* ensure temporary palette disabled */	writel(0x00, S3C2410_TPAL);	/* Enable video by setting the ENVID bit to 1 */	fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;	writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);	return 0;}static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi){	unsigned int i;	unsigned long ent;	fbi->palette_ready = 0;	for (i = 0; i < 256; i++) {		if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)			continue;		writel(ent, S3C2410_TFTPAL(i));		/* it seems the only way to know exactly		 * if the palette wrote ok, is to check		 * to see if the value verifies ok		 */		if (readw(S3C2410_TFTPAL(i)) == ent)			fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;		else			fbi->palette_ready = 1;   /* retry */	}}static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r){	struct s3c2410fb_info *fbi = dev_id;	unsigned long lcdirq = readl(S3C2410_LCDINTPND);	if (lcdirq & S3C2410_LCDINT_FRSYNC) {		if (fbi->palette_ready)			s3c2410fb_write_palette(fbi);		writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND);		writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND);	}	return IRQ_HANDLED;}static char driver_name[]="s3c2410fb";static int __init s3c2410fb_probe(struct platform_device *pdev){	struct s3c2410fb_info *info;	struct fb_info	   *fbinfo;	struct s3c2410fb_hw *mregs;	int ret;	int irq;	int i;	mach_info = pdev->dev.platform_data;	if (mach_info == NULL) {		dev_err(&pdev->dev,"no platform data for lcd, cannot attach\n");		return -EINVAL;	}	mregs = &mach_info->regs;	irq = platform_get_irq(pdev, 0);	if (irq < 0) {		dev_err(&pdev->dev, "no irq for device\n");		return -ENOENT;	}	fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);	if (!fbinfo) {		return -ENOMEM;	}	info = fbinfo->par;	info->fb = fbinfo;	platform_set_drvdata(pdev, fbinfo);	dprintk("devinit\n");	strcpy(fbinfo->fix.id, driver_name);	memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));	info->mach_info		    = pdev->dev.platform_data;	fbinfo->fix.type	    = FB_TYPE_PACKED_PIXELS;	fbinfo->fix.type_aux	    = 0;	fbinfo->fix.xpanstep	    = 0;	fbinfo->fix.ypanstep	    = 0;	fbinfo->fix.ywrapstep	    = 0;	fbinfo->fix.accel	    = FB_ACCEL_NONE;	fbinfo->var.nonstd	    = 0;	fbinfo->var.activate	    = FB_ACTIVATE_NOW;	fbinfo->var.height	    = mach_info->height;	fbinfo->var.width	    = mach_info->width;	fbinfo->var.accel_flags     = 0;	fbinfo->var.vmode	    = FB_VMODE_NONINTERLACED;	fbinfo->fbops		    = &s3c2410fb_ops;	fbinfo->flags		    = FBINFO_FLAG_DEFAULT;	fbinfo->pseudo_palette      = &info->pseudo_pal;	fbinfo->var.xres	    = mach_info->xres.defval;	fbinfo->var.xres_virtual    = mach_info->xres.defval;	fbinfo->var.yres	    = mach_info->yres.defval;	fbinfo->var.yres_virtual    = mach_info->yres.defval;	fbinfo->var.bits_per_pixel  = mach_info->bpp.defval;	fbinfo->var.upper_margin    = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) + 1;	fbinfo->var.lower_margin    = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) + 1;	fbinfo->var.vsync_len	    = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;	fbinfo->var.left_margin	    = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;	fbinfo->var.right_margin    = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;	fbinfo->var.hsync_len	    = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;	fbinfo->var.red.offset      = 11;	fbinfo->var.green.offset    = 5;	fbinfo->var.blue.offset     = 0;	fbinfo->var.transp.offset   = 0;	fbinfo->var.red.length      = 5;	fbinfo->var.green.length    = 6;	fbinfo->var.blue.length     = 5;	fbinfo->var.transp.length   = 0;	fbinfo->fix.smem_len        =	mach_info->xres.max *					mach_info->yres.max *					mach_info->bpp.max / 8;	for (i = 0; i < 256; i++)		info->palette_buffer[i] = PALETTE_BUFF_CLEAR;	if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) {		ret = -EBUSY;		goto dealloc_fb;	}	dprintk("got LCD region\n");	ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, info);	if (ret) {		dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);		ret = -EBUSY;		goto release_mem;	}	info->clk = clk_get(NULL, "lcd");	if (!info->clk || IS_ERR(info->clk)) {		printk(KERN_ERR "failed to get lcd clock source\n");		ret = -ENOENT;		goto release_irq;	}	clk_enable(info->clk);	dprintk("got and enabled clock\n");	msleep(1);	/* Initialize video memory */	ret = s3c2410fb_map_video_memory(info);	if (ret) {		printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);		ret = -ENOMEM;		goto release_clock;	}	dprintk("got video memory\n");	ret = s3c2410fb_init_registers(info);	ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);	ret = register_framebuffer(fbinfo);	if (ret < 0) {		printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);		goto free_video_memory;	}	/* create device files */	device_create_file(&pdev->dev, &dev_attr_debug);	printk(KERN_INFO "fb%d: %s frame buffer device\n",		fbinfo->node, fbinfo->fix.id);	return 0;free_video_memory:	s3c2410fb_unmap_video_memory(info);release_clock:	clk_disable(info->clk);	clk_put(info->clk);release_irq:	free_irq(irq,info);release_mem: 	release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);dealloc_fb:	framebuffer_release(fbinfo);	return ret;}/* s3c2410fb_stop_lcd * * shutdown the lcd controller*/static void s3c2410fb_stop_lcd(void){	unsigned long flags;	unsigned long tmp;	local_irq_save(flags);	tmp = readl(S3C2410_LCDCON1);	writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);	local_irq_restore(flags);}/* *  Cleanup */static int s3c2410fb_remove(struct platform_device *pdev){	struct fb_info	   *fbinfo = platform_get_drvdata(pdev);	struct s3c2410fb_info *info = fbinfo->par;	int irq;	s3c2410fb_stop_lcd();	msleep(1);	s3c2410fb_unmap_video_memory(info); 	if (info->clk) { 		clk_disable(info->clk); 		clk_put(info->clk); 		info->clk = NULL;	}	irq = platform_get_irq(pdev, 0);	free_irq(irq,info);	release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);	unregister_framebuffer(fbinfo);	return 0;}#ifdef CONFIG_PM/* suspend and resume support for the lcd controller */static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state){	struct fb_info	   *fbinfo = platform_get_drvdata(dev);	struct s3c2410fb_info *info = fbinfo->par;	s3c2410fb_stop_lcd();	/* sleep before disabling the clock, we need to ensure	 * the LCD DMA engine is not going to get back on the bus	 * before the clock goes off again (bjd) */	msleep(1);	clk_disable(info->clk);	return 0;}static int s3c2410fb_resume(struct platform_device *dev){	struct fb_info	   *fbinfo = platform_get_drvdata(dev);	struct s3c2410fb_info *info = fbinfo->par;	clk_enable(info->clk);	msleep(1);	s3c2410fb_init_registers(info);	return 0;}#else#define s3c2410fb_suspend NULL#define s3c2410fb_resume  NULL#endifstatic struct platform_driver s3c2410fb_driver = {	.probe		= s3c2410fb_probe,	.remove		= s3c2410fb_remove,	.suspend	= s3c2410fb_suspend,	.resume		= s3c2410fb_resume,	.driver		= {		.name	= "s3c2410-lcd",		.owner	= THIS_MODULE,	},};int __devinit s3c2410fb_init(void){	return platform_driver_register(&s3c2410fb_driver);}static void __exit s3c2410fb_cleanup(void){	platform_driver_unregister(&s3c2410fb_driver);}module_init(s3c2410fb_init);module_exit(s3c2410fb_cleanup);MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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