帧设备驱动(二)

一是对LCD及其相关部件的初始化,包括画面缓冲区的创建和对DMA通道的设置;二是对画面缓冲区的读写,具体到代码为readwrite等系统调用接口。

 

这些都是由帧缓冲设备驱动来完成的。帧缓冲设备对应的设备文件通常为/dev/fb031Linux的帧缓冲设备的驱动主要基于两个文件:

 

  1)linux/include/linux/fb.h

 

  2)linux/drivers/video/fbmem.c

 

  帧缓冲设备属于字符设备,采用“文件层-驱动层”的接口方式。

文件fbmem.c中定义了帧缓冲设备的文件层接口file_operations结构体,它对应用程序可见,该结构体的定义如下:

 

 static const struct file_operations fb_fops = {

         .owner=  THIS_MODULE,

         .read=               fb_read,

         .write=    fb_write,

         .unlocked_ioctl= fb_ioctl,

#ifdef CONFIG_COMPAT

         .compat_ioctl= fb_compat_ioctl,

#endif

         .mmap=           fb_mmap,

         .open=              fb_open,

         .release=         fb_release,

#ifdef HAVE_ARCH_FB_UNMAPPED_AREA

         .get_unmapped_area= get_fb_unmapped_area,

#endif

#ifdef CONFIG_FB_DEFERRED_IO

         .fsync=    fb_deferred_io_fsync,

#endif

         .llseek=   default_llseek,

};

在这个结构体中功能函数open()release()不需要底层的支持,而read()write()mmap()则需要调用fb-get-fix()fb-get-var()fb-set-var()(这些函数位于结构体fb-info中指针fbops指向的结构体变量中)等与底层LCD硬件相关的函数的支持。另一个功能函数是ioctl()ioctl()是设备驱动程序中对设备的I/O通道进行管理的函数,应用程序应用ioctl()系统调用来调用fb-get-fix()fb-get-var()fb-set-var()等方法来获得和设置结构体fb-infovarfixcmap等变量的信息。

 

  帧缓冲设备在驱动层所要做的工作仅仅是对Linux为帧缓冲的驱动层接口fb_info进行初始化,然后调用这两个函数对其注册或注销。

 

     帧缓冲设备驱动层接口直接对LCD设备硬件进行操作,而fbmem.c可以记录和管理多个底层设备驱动。

     

LCD控制器经常被集成到SOC上作为一个独立硬件模块而存在(成为platform_device,因此,模块加载函数中完成的只是注册平台驱动,而初始化FBI结构体中固定参数和可变参数,申请帧缓冲设备的显示缓冲区,注册缓冲区则交给探测函数完成。

 

int __init s3c2410fb_init(void)

{

         intret = platform_driver_register(&s3c2410fb_driver);

 

         if(ret == 0)

                   ret= platform_driver_register(&s3c2412fb_driver);

 

         returnret;

}

 

static void __exit s3c2410fb_cleanup(void)

{

         platform_driver_unregister(&s3c2410fb_driver);

         platform_driver_unregister(&s3c2412fb_driver);

}

 

module_init(s3c2410fb_init); 使用insmod 或者modprobe 命令加载时自动调用

module_exit(s3c2410fb_cleanup);  使用rmmod 卸载时自动调用

 MODULE_AUTHOR("ArnaudPatard <arnaud.patard@rtp-net.org>, "

               "Ben Dooks<ben-linux@fluff.org>");

MODULE_DESCRIPTION("Framebuffer driverfor the s3c2410");

MODULE_LICENSE("GPL");

MODULE_ALIAS("platform:s3c2410-lcd");

MODULE_ALIAS("platform:s3c2412-lcd");

对应的platform_driver结构体为:

static struct platform_drivers3c2410fb_driver = {

         .probe                = s3c2410fb_probe,

         .remove            = __devexit_p(s3c2410fb_remove),

         .suspend  = s3c2410fb_suspend,

         .resume            = s3c2410fb_resume,

         .driver                = {

                   .name       = "s3c2410-lcd", //驱动名

                   .owner     = THIS_MODULE,

         },

};

struct platform_device {

         constchar        * name;

         int              id;

         struct device    dev;

         u32            num_resources;

         structresource        * resource;

 

         conststruct platform_device_id     *id_entry;

 

         /*arch specific additions */

         structpdev_archdata      archdata;

};

 

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,

};

那么平台设备的资源呢?

 

/* LCD Controller */

 

 

static u64 s3c_device_lcd_dmamask =0xffffffffUL;

 

 

struct platform_device s3c_device_lcd = {

.name  = "s3c-lcd",

.id  = -1,设备编号,-1表示只有这样一个设备

.num_resources =ARRAY_SIZE(s3c_lcd_resource),

.resource  = s3c_lcd_resource,

.dev              = {

.dma_mask  =&s3c_device_lcd_dmamask,

.coherent_dma_mask= 0xffffffffUL

}

};

/*

 *  Probe平台驱动探测函数

 */

static int __devinit s3c2410fb_probe(structplatform_device *pdev)

{

         returns3c24xxfb_probe(pdev, DRV_S3C2410);

}

static int __devinit s3c24xxfb_probe(structplatform_device *pdev,

                                       enum s3c_drv_type drv_type)

{

         structs3c2410fb_info *info;

         structs3c2410fb_display *display;

         structfb_info *fbinfo;

         structs3c2410fb_mach_info *mach_info;

         structresource *res;

         intret;

         intirq;

         inti;

         intsize;

         u32lcdcon1;

 

         mach_info= pdev->dev.platform_data;

         if(mach_info == NULL) {

                   dev_err(&pdev->dev,

                            "noplatform data for lcd, cannot attach\n");

                   return-EINVAL;

         }

 

         if(mach_info->default_display >= mach_info->num_displays) {

                   dev_err(&pdev->dev,"default is %d but only %d displays\n",

                            mach_info->default_display,mach_info->num_displays);

                   return-EINVAL;

         }

 

         display= mach_info->displays + mach_info->default_display;

 

         irq= platform_get_irq(pdev, 0);

         if(irq < 0) {

                   dev_err(&pdev->dev,"no irq for device\n");

                   return-ENOENT;

         }

//分配fb_info空间

         fbinfo= framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);

         if(!fbinfo)

                   return-ENOMEM;

 

         platform_set_drvdata(pdev,fbinfo);

 

         info= fbinfo->par;

         info->dev= &pdev->dev;

         info->drv_type= drv_type;

 

         res= platform_get_resource(pdev, IORESOURCE_MEM, 0);

         if(res == NULL) {

                   dev_err(&pdev->dev,"failed to get memory registers\n");

                   ret= -ENXIO;

                   gotodealloc_fb;

         }

 

         size= (res->end - res->start) + 1;

         info->mem= request_mem_region(res->start, size, pdev->name);

         if(info->mem == NULL) {

                   dev_err(&pdev->dev,"failed to get memory region\n");

                   ret= -ENOENT;

                   gotodealloc_fb;

         }

 

         info->io= ioremap(res->start, size);

         if(info->io == NULL) {

                   dev_err(&pdev->dev,"ioremap() of registers failed\n");

                   ret= -ENXIO;

                   gotorelease_mem;

         }

 

         info->irq_base= info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE :S3C2410_LCDINTBASE);

 

         dprintk("devinit\n");

 

         strcpy(fbinfo->fix.id,driver_name);

 

         /*Stop the video */

         lcdcon1= readl(info->io + S3C2410_LCDCON1);

         writel(lcdcon1& ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);

 

         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.accel_flags     = 0;

         fbinfo->var.vmode        =FB_VMODE_NONINTERLACED;

 

         fbinfo->fbops                = &s3c2410fb_ops;

         fbinfo->flags                 = FBINFO_FLAG_DEFAULT;

         fbinfo->pseudo_palette      = &info->pseudo_pal;

 

         for(i = 0; i < 256; i++)

                   info->palette_buffer[i]= PALETTE_BUFF_CLEAR;

 

         ret= request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);

         if(ret) {

                   dev_err(&pdev->dev,"cannot get irq %d - err %d\n", irq, ret);

                   ret= -EBUSY;

                   gotorelease_regs;

         }

 

         info->clk= clk_get(NULL, "lcd");

         if(IS_ERR(info->clk)) {

                   printk(KERN_ERR"failed to get lcd clock source\n");

                   ret= PTR_ERR(info->clk);

                   gotorelease_irq;

         }

 

         clk_enable(info->clk);

         dprintk("gotand enabled clock\n");

 

         msleep(1);

 

         info->clk_rate= clk_get_rate(info->clk);

 

         /*find maximum required memory size for display */

         for(i = 0; i < mach_info->num_displays; i++) {

                   unsignedlong smem_len = mach_info->displays[i].xres;

 

                   smem_len*= mach_info->displays[i].yres;

                   smem_len*= mach_info->displays[i].bpp;

                   smem_len>>= 3;

                   if(fbinfo->fix.smem_len < smem_len)

                            fbinfo->fix.smem_len= smem_len;

         }

 

 

         /*Initialize video memory */

         ret= s3c2410fb_map_video_memory(fbinfo);

         if(ret) {

                   printk(KERN_ERR"Failed to allocate video RAM: %d\n", ret);

                   ret= -ENOMEM;

                   gotorelease_clock;

         }

 

         dprintk("gotvideo memory\n");

 

         fbinfo->var.xres= display->xres;

         fbinfo->var.yres= display->yres;

         fbinfo->var.bits_per_pixel= display->bpp;

 

         s3c2410fb_init_registers(fbinfo);

    //检查可变参数

         s3c2410fb_check_var(&fbinfo->var,fbinfo);

 

         ret= s3c2410fb_cpufreq_register(info);

         if(ret < 0) {

                   dev_err(&pdev->dev,"Failed to register cpufreq\n");

                   gotofree_video_memory;

         }

  //注册FBI

         ret= register_framebuffer(fbinfo);

         if(ret < 0) {

                   printk(KERN_ERR"Failed to register framebuffer device: %d\n",

                            ret);

                   gotofree_cpufreq;

         }

 

         /*create device files */

         ret= device_create_file(&pdev->dev, &dev_attr_debug);

         if(ret) {

                   printk(KERN_ERR"failed to add debug attribute\n");

         }

 

         printk(KERN_INFO"fb%d: %s frame buffer device\n",

                   fbinfo->node,fbinfo->fix.id);

 

         return0;

 

 free_cpufreq:

         s3c2410fb_cpufreq_deregister(info);

free_video_memory:

         s3c2410fb_unmap_video_memory(fbinfo);

release_clock:

         clk_disable(info->clk);

         clk_put(info->clk);

release_irq:

         free_irq(irq,info);

release_regs:

         iounmap(info->io);

release_mem:

         release_resource(info->mem);

         kfree(info->mem);

dealloc_fb:

         platform_set_drvdata(pdev,NULL);

         framebuffer_release(fbinfo);

         returnret;

}

static int __devexits3c2410fb_remove(struct platform_device *pdev)

{

         structfb_info *fbinfo = platform_get_drvdata(pdev);

         structs3c2410fb_info *info = fbinfo->par;

         intirq;

 

         unregister_framebuffer(fbinfo);//注销fb_info

         s3c2410fb_cpufreq_deregister(info);

 

         s3c2410fb_lcd_enable(info,0);

         msleep(1);

 

         s3c2410fb_unmap_video_memory(fbinfo);

 

         if(info->clk) {

                   clk_disable(info->clk);

                   clk_put(info->clk);

                   info->clk= NULL;

         }

 

         irq= platform_get_irq(pdev, 0);

         free_irq(irq,info);

 

         iounmap(info->io);

 

         release_resource(info->mem);

         kfree(info->mem);

 

         platform_set_drvdata(pdev,NULL);

         framebuffer_release(fbinfo);

 

         return0;

}

 

 

 

 

技术选型 【后端】:Java 【框架】:springboot 【前端】:vue 【JDK版本】:JDK1.8 【服务器】:tomcat7+ 【数据库】:mysql 5.7+ 项目包含前后台完整源码。 项目都经过严格调试,确保可以运行! 具体项目介绍可查看博主文章或私聊获取 助力学习实践,提升编程技能,快来获取这份宝贵的资源吧! 在当今快速发展的信息技术领域,技术选型是决定一个项目成功与否的重要因素之一。基于以下的技术栈,我们为您带来了一份完善且经过实践验证的项目资源,让您在学习和提升编程技能的道路上事半功倍。以下是该项目的技术选型和其组件的详细介绍。 在后端技术方面,我们选择了Java作为编程语言。Java以其稳健性、跨平台性和丰富的库支持,在企业级应用中处于领导地位。项目采用了流行的Spring Boot框架,这个框架以简化Java企业级开发而闻名。Spring Boot提供了简洁的配置方式、内置的嵌入式服务器支持以及强大的生态系统,使开发者能够更高效地构建和部署应用。 前端技术方面,我们使用了Vue.js,这是一个用于构建用户界面的渐进式JavaScript框架。Vue以其易上手、灵活和性能出色而受到开发者的青睐,它的组件化开发思想也有助于提高代码的复用性和可维护性。 项目的编译和运行环境选择了JDK 1.8。尽管Java已经推出了更新的版本,但JDK 1.8依旧是一种成熟且稳定的选择,广泛应用于各类项目中,确保了兼容性和稳定性。 在服务器方面,本项目部署在Tomcat 7+之上。Tomcat是Apache软件基金会下的一个开源Servlet容器,也是应用最为广泛的Java Web服务器之一。其稳定性和可靠的性能表现为Java Web应用提供了坚实的支持。 数据库方面,我们采用了MySQL 5.7+。MySQL是一种高效、可靠且使用广泛的关系型数据库管理系统,5.7版本在性能和功能上都有显著的提升。 值得一提的是,该项目包含了前后台的完整源码,并经过严格调试,确保可以顺利运行。通过项目的学习和实践,您将能更好地掌握从后端到前端的完整开发流程,提升自己的编程技能。欢迎参考博主的详细文章或私信获取更多信息,利用这一宝贵资源来推进您的技术成长之路!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值