当前位置: 首页 > 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.lryc.cn/news/594741.html

相关文章:

  • 录音转写:颠覆传统共享下载体验 | 如何提升团队效率?
  • 【前端状态更新与异步协调完全指南:React、Vue架构原理与复杂业务场景实战】
  • RustDesk自建服务器完整部署指南:从零开始到成功连接。成功解决rustdesk报错:未就绪,请检查网络连接
  • Vue 脚手架——render函数
  • 网络与信息安全有哪些岗位:(1)网络安全工程师
  • 【系统全面】Linux进程——基础知识介绍
  • 在本地WSL中的CentOS 7子系统中部署Ewomail邮件服务器
  • AC身份认证实验之AAA服务器
  • django filter按两个属性 去重
  • 第15次:商品搜索
  • 信息整合注意力IIA,通过双方向注意力机制重构空间位置信息,动态增强目标关键特征并抑制噪声
  • 来伊份养馋记社区零售 4.0 上海首店落沪:重构 “家门口” 的生活服务生态
  • 卷积神经网络中的注意力机制:CBAM详解与实践
  • Go-通俗易懂垃圾回收及运行过程
  • WPF——自定义ListBox
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(二)
  • 学习秒杀系统-异步下单(包含RabbitMQ基础知识)
  • ASP.NET Core Web API 中集成 DeveloperSharp.RabbitMQ
  • 关于校准 ARM 开发板时间的步骤和常见问题:我应该是RTC电池没电了才导致我设置了重启开发板又变回去2025年的时间
  • Android NDK ffmpeg 音视频开发实战
  • 什么是“差分“?
  • 包装类简单了解泛型
  • 图片转 PDF三个免费方法总结
  • 支持不限制大小,大文件分段批量上传功能(不受nginx /apache 上传大小限制)
  • 网络设备功能对照表
  • 【Spark征服之路-3.6-Spark-SQL核心编程(五)】
  • Linux 文件操作详解:结构、系统调用、权限与实践
  • 第二阶段-第二章—8天Python从入门到精通【itheima】-134节(SQL——DQL——分组聚合)
  • leetcode-sql-627变更性别
  • 深入解析IP协议:组成、地址管理与路由选择