当前位置: 首页 > news >正文

5.6 framebuffer驱动

1. framebuffer介绍

        linux系统中把LCD这类设备称为帧缓冲(framebuffer)设备,是linux内核虚拟的一个设备。framebuffer是Linux系统为显示设备提供的一个接口,可以将framebuffer看成LCD设备内存的映射,应用程序通过对framebuffer读写,来简介操作LCD,从而实现LCD的显示功能。

2. 应用程序如何操作framebuffer设备

(1)通过open()函数打开设备文件(dev/fb0、dev/fb1、...)。

(2)通过mmap()函数将内存中的数据映射到framebuffer的显存上。

/*****************************************************************
*    @parm:
*        @addr:映射的内存基地址
*        @length:映射内存的大小(byte)
*        @prot:属性:
*                ①:PROT_EXEC       映射区可被执行
*                ②:PROT_READ       映射区可被读
*                ③:PROT_WRITE      映射区可被写
*                ④:PROT_NONE       映射区不可读写
*        @flags:保护标志。常用的是共享方式 MAP_SHARED
*        @fd:open返回的文件描述符
*        @offset:是从文件的哪个地方开始映射
********************************************************************/
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 

(3)通过ioctl()函数可以获取显示设备的信息(固定信息、可变信息)。

// framebuffer固定信息和可变信息结构体在/include/linux/fb.h文件中// 固定信息结构体
struct fb_fix_screeninfo 
{char id[16];			/* identification string eg "TT Builtin" */unsigned long smem_start;	/* Start of frame buffer mem *//* (physical address) */__u32 smem_len;			/* Length of frame buffer mem */__u32 type;			/* see FB_TYPE_*		*/__u32 type_aux;			/* Interleave for interleaved Planes */__u32 visual;			/* see FB_VISUAL_*		*/ __u16 xpanstep;			/* zero if no hardware panning  */__u16 ypanstep;			/* zero if no hardware panning  */__u16 ywrapstep;		/* zero if no hardware ywrap    */__u32 line_length;		/* length of a line in bytes    */unsigned long mmio_start;	/* Start of Memory Mapped I/O   *//* (physical address) */__u32 mmio_len;			/* Length of Memory Mapped I/O  */__u32 accel;			/* Indicate to driver which	*//*  specific chip/card we have	*/__u16 reserved[3];		/* Reserved for future compatibility */
};// 固定信息读取
struct fb_fix_screeninfo fb_fix_info; //固定参数
ioctl(fb, FBIOGET_FSCREENINFO, &fb_fix_info)//固定参数// 可变信息结构体
struct fb_var_screeninfo 
{__u32 xres;			/* visible resolution		*/__u32 yres;__u32 xres_virtual;		/* virtual resolution		*/__u32 yres_virtual;__u32 xoffset;			/* offset from virtual to visible */__u32 yoffset;			/* resolution			*/__u32 bits_per_pixel;		/* guess what			*/__u32 grayscale;		/* != 0 Graylevels instead of colors */struct fb_bitfield red;		/* bitfield in fb mem if true color, */struct fb_bitfield green;	/* else only length is significant */struct fb_bitfield blue;struct fb_bitfield transp;	/* transparency			*/	__u32 nonstd;			/* != 0 Non standard pixel format */__u32 activate;			/* see FB_ACTIVATE_*		*/__u32 height;			/* height of picture in mm    */__u32 width;			/* width of picture in mm     */__u32 accel_flags;		/* (OBSOLETE) see fb_info.flags *//* Timing: All values in pixclocks, except pixclock (of course) */__u32 pixclock;			/* pixel clock in ps (pico seconds) */__u32 left_margin;		/* time from sync to picture	*/__u32 right_margin;		/* time from picture to sync	*/__u32 upper_margin;		/* time from sync to picture	*/__u32 lower_margin;__u32 hsync_len;		/* length of horizontal sync	*/__u32 vsync_len;		/* length of vertical sync	*/__u32 sync;			/* see FB_SYNC_*		*/__u32 vmode;			/* see FB_VMODE_*		*/__u32 rotate;			/* angle we rotate counter clockwise */__u32 reserved[5];		/* Reserved for future compatibility */
};// 可变信息读取
struct fb_var_screeninfo fb_var_info;
ioctl(fb, FBIOGET_VSCREENINFO, &fb_var_info)//可变参数

3. framebuffer设备驱动结构

4. framebuffer驱动

4.1 framebuffer驱动框架

4.1.1 framebuffer驱动框架源码路径

(1)/drivers/video/fbmem.c 用于创建graphics类,注册fb字符设备驱动,提供framebuffer驱动注册结构

static int __init
fbmem_init(void)
{proc_create("fb", 0, NULL, &fb_proc_fops);if (register_chrdev(FB_MAJOR,"fb",&fb_fops))printk("unable to get major %d for fb devs\n", FB_MAJOR);fb_class = class_create(THIS_MODULE, "graphics");if (IS_ERR(fb_class)) {printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));fb_class = NULL;}return 0;
}#ifdef MODULE
module_init(fbmem_init);
static void __exit
fbmem_exit(void)
{remove_proc_entry("fb", NULL);class_destroy(fb_class);unregister_chrdev(FB_MAJOR, "fb");
}

framebuffer驱动注册接口:

/***	register_framebuffer - registers a frame buffer device*	@fb_info: frame buffer info structure**	Registers a frame buffer device @fb_info.**	Returns negative errno on error, or zero for success.**/int
register_framebuffer(struct fb_info *fb_info)
{int i;struct fb_event event;struct fb_videomode mode;if (num_registered_fb == FB_MAX)return -ENXIO;if (fb_check_foreignness(fb_info))return -ENOSYS;remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,fb_is_primary_device(fb_info));num_registered_fb++;for (i = 0 ; i < FB_MAX; i++)if (!registered_fb[i])break;fb_info->node = i;mutex_init(&fb_info->lock);mutex_init(&fb_info->mm_lock);fb_info->dev = device_create(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL, "fb%d", i);if (IS_ERR(fb_info->dev)) {/* Not fatal */printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));fb_info->dev = NULL;} elsefb_init_device(fb_info);if (fb_info->pixmap.addr == NULL) {fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);if (fb_info->pixmap.addr) {fb_info->pixmap.size = FBPIXMAPSIZE;fb_info->pixmap.buf_align = 1;fb_info->pixmap.scan_align = 1;fb_info->pixmap.access_align = 32;fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;}}	fb_info->pixmap.offset = 0;if (!fb_info->pixmap.blit_x)fb_info->pixmap.blit_x = ~(u32)0;if (!fb_info->pixmap.blit_y)fb_info->pixmap.blit_y = ~(u32)0;if (!fb_info->modelist.prev || !fb_info->modelist.next)INIT_LIST_HEAD(&fb_info->modelist);fb_var_to_videomode(&mode, &fb_info->var);fb_add_videomode(&mode, &fb_info->modelist);registered_fb[i] = fb_info;event.info = fb_info;if (!lock_fb_info(fb_info))return -ENODEV;fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);unlock_fb_info(fb_info);return 0;
}/***	unregister_framebuffer - releases a frame buffer device*	@fb_info: frame buffer info structure**	Unregisters a frame buffer device @fb_info.**	Returns negative errno on error, or zero for success.**      This function will also notify the framebuffer console*      to release the driver.**      This is meant to be called within a driver's module_exit()*      function. If this is called outside module_exit(), ensure*      that the driver implements fb_open() and fb_release() to*      check that no processes are using the device.*/int
unregister_framebuffer(struct fb_info *fb_info)
{struct fb_event event;int i, ret = 0;i = fb_info->node;if (!registered_fb[i]) {ret = -EINVAL;goto done;}if (!lock_fb_info(fb_info))return -ENODEV;event.info = fb_info;ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);unlock_fb_info(fb_info);if (ret) {ret = -EINVAL;goto done;}if (fb_info->pixmap.addr &&(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))kfree(fb_info->pixmap.addr);fb_destroy_modelist(&fb_info->modelist);registered_fb[i]=NULL;num_registered_fb--;fb_cleanup_device(fb_info);device_destroy(fb_class, MKDEV(FB_MAJOR, i));event.info = fb_info;fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);/* this may free fb info */if (fb_info->fbops->fb_destroy)fb_info->fbops->fb_destroy(fb_info);
done:return ret;
}

(2)drivers/video/fbsys.c  用于处理fb在/sys目录下的属性文件

(3)drivers/video/modedb.c  管理显示模式(例如:VGA、720P等)

(4)drivers/video/fb_notify.c

4.2 framebuffer驱动

4.2.1 framebuffer驱动源码路径

(1)drivers/video/samsung/s3cfb.c   驱动主体

static int __init s3cfb_register(void)
{platform_driver_register(&s3cfb_driver);return 0;
}
static void __exit s3cfb_unregister(void)
{platform_driver_unregister(&s3cfb_driver);
}module_init(s3cfb_register);
module_exit(s3cfb_unregister);

s3cfb_probe函数

static int __devinit s3cfb_probe(struct platform_device *pdev)
{struct s3c_platform_fb *pdata;struct s3cfb_global *fbdev;struct resource *res;int i, j, ret = 0;fbdev = kzalloc(sizeof(struct s3cfb_global), GFP_KERNEL);if (!fbdev) {dev_err(&pdev->dev, "failed to allocate for ""global fb structure\n");ret = -ENOMEM;goto err_global;}fbdev->dev = &pdev->dev;fbdev->regulator = regulator_get(&pdev->dev, "pd");if (!fbdev->regulator) {dev_err(fbdev->dev, "failed to get regulator\n");ret = -EINVAL;goto err_regulator;}ret = regulator_enable(fbdev->regulator);if (ret < 0) {dev_err(fbdev->dev, "failed to enable regulator\n");ret = -EINVAL;goto err_regulator;}pdata = to_fb_plat(&pdev->dev);if (!pdata) {dev_err(fbdev->dev, "failed to get platform data\n");ret = -EINVAL;goto err_pdata;}fbdev->lcd = (struct s3cfb_lcd *)pdata->lcd;if (pdata->cfg_gpio)pdata->cfg_gpio(pdev);if (pdata->clk_on)pdata->clk_on(pdev, &fbdev->clock);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!res) {dev_err(fbdev->dev, "failed to get io memory region\n");ret = -EINVAL;goto err_io;}res = request_mem_region(res->start,res->end - res->start + 1, pdev->name);if (!res) {dev_err(fbdev->dev, "failed to request io memory region\n");ret = -EINVAL;goto err_io;}fbdev->regs = ioremap(res->start, res->end - res->start + 1);if (!fbdev->regs) {dev_err(fbdev->dev, "failed to remap io region\n");ret = -EINVAL;goto err_mem;}s3cfb_set_vsync_interrupt(fbdev, 1);s3cfb_set_global_interrupt(fbdev, 1);s3cfb_init_global(fbdev);if (s3cfb_alloc_framebuffer(fbdev)) {ret = -ENOMEM;goto err_alloc;}if (s3cfb_register_framebuffer(fbdev)) {ret = -EINVAL;goto err_register;}s3cfb_set_clock(fbdev);s3cfb_set_window(fbdev, pdata->default_win, 1);s3cfb_display_on(fbdev);fbdev->irq = platform_get_irq(pdev, 0);if (request_irq(fbdev->irq, s3cfb_irq_frame, IRQF_SHARED,pdev->name, fbdev)) {dev_err(fbdev->dev, "request_irq failed\n");ret = -EINVAL;goto err_irq;}#ifdef CONFIG_FB_S3C_LCD_INITif (pdata->backlight_on)pdata->backlight_on(pdev);if (!bootloaderfb && pdata->reset_lcd)pdata->reset_lcd(pdev);
#endif#ifdef CONFIG_HAS_EARLYSUSPENDfbdev->early_suspend.suspend = s3cfb_early_suspend;fbdev->early_suspend.resume = s3cfb_late_resume;fbdev->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;register_early_suspend(&fbdev->early_suspend);
#endifret = device_create_file(&(pdev->dev), &dev_attr_win_power);if (ret < 0)dev_err(fbdev->dev, "failed to add sysfs entries\n");dev_info(fbdev->dev, "registered successfully\n");#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)if (fb_prepare_logo( fbdev->fb[pdata->default_win], FB_ROTATE_UR)) {printk("Start display and show logo\n");/* Start display and show logo on boot */fb_set_cmap(&fbdev->fb[pdata->default_win]->cmap, fbdev->fb[pdata->default_win]);fb_show_logo(fbdev->fb[pdata->default_win], FB_ROTATE_UR);}
#endifmdelay(100);if (pdata->backlight_on)pdata->backlight_on(pdev);return 0;err_irq:s3cfb_display_off(fbdev);s3cfb_set_window(fbdev, pdata->default_win, 0);for (i = pdata->default_win;i < pdata->nr_wins + pdata->default_win; i++) {j = i % pdata->nr_wins;unregister_framebuffer(fbdev->fb[j]);}
err_register:for (i = 0; i < pdata->nr_wins; i++) {if (i == pdata->default_win)s3cfb_unmap_default_video_memory(fbdev->fb[i]);framebuffer_release(fbdev->fb[i]);}kfree(fbdev->fb);err_alloc:iounmap(fbdev->regs);err_mem:release_mem_region(res->start,res->end - res->start + 1);err_io:pdata->clk_off(pdev, &fbdev->clock);err_pdata:regulator_disable(fbdev->regulator);err_regulator:kfree(fbdev);err_global:return ret;
}

(2)drivers/video/samsung/s3cfb_fimd6x.c   提供LCD硬件操作函数

(3)arch/arm/mach-s5pv210/mach-x210.c  提供platfrom_device

(4)arch/arm/plat-s5p/devs.c

http://www.xdnf.cn/news/1163449.html

相关文章:

  • 人工智能之数学基础:事件间的关系
  • MySQL 核心知识点梳理(3)
  • Qualcomm Linux 蓝牙指南学习--验证 Fluoride 协议栈的功能(2)
  • Java学习----NIO模型
  • 爬虫实战指南:从定位数据到解析请求的全流程解析
  • PyTorch 实现 CIFAR-10 图像分类:从数据预处理到模型训练与评估
  • 【PHP安全】免费解密支持:zend52、zend53、zend54好工具
  • C# 结构体
  • AI Agent与MCP协议构建标准技术报告(2025Q3)
  • 【科研绘图系列】R语言绘制棒棒图和哑铃图
  • PyQt5—QInputDialog 学习笔记
  • MySQL 8.0 OCP 1Z0-908 题目解析(31)
  • Python并发编程:突破GIL枷锁,高效利用多核CPU
  • Vue组件之间通信
  • ps aux 和 ps -ef
  • react class和function 如何模拟vue中的 双向绑定 监听 computed的方式
  • 区块链之以太坊合约开发工具——Metamask钱包和Remix IDE
  • 架构设计衡量标准
  • 系统分析师-计算机系统-操作系统-存储器管理设备管理
  • 【每日算法】专题四_前缀和
  • 【算法基础】二分查找
  • 选择排序 冒泡排序
  • TPS61194PWPRQ1适用于汽车照明低 EMI、高性能 4 通道 LED 驱动器TPS61194
  • Java 二叉树
  • 【Java学习|黑马笔记|Day19】方法引用、异常(try...catch、自定义异常)及其练习
  • 洛谷 P1480 A/B Problem
  • Apache Ignite Binary Object 调优
  • Js进阶案例合集
  • 《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——1. 启航:你的第一个工业视觉应用
  • 原型设计模式