Framebuffer驱动详解

1. LCD简介

1.1 LCD屏幕

LCD由一个一个像素组成:每行有xres个像素,有yres行,它的分辨率是:xres * yres。

只要我们能控制任意一个像素的颜色,就可以在LCD上绘制文字、图片。

1.2 像素的颜色表示

用红绿蓝三颜色来表示,可以用24位数据来表示红绿蓝,也可以用16位等等格式,比如:

  • bpp:bits per pixel,每个像素用多少位来表示

  • 24bpp:实际上会用到32位,其中8位未使用,其余24位中分别用8位表示红(R)、绿(G)、蓝(B)

  • 16bpp:有rbg565,rgb555

    • rgb565:用5位表示红、6位表示绿、5位表示蓝

    • rgb555:16位数据中用5位表示红、5位表示绿、5位表示蓝,浪费一位

发送颜色过程:假设每个像素的颜色用16位来表示,那么一个LCD的所有像素点假设有xres * y res个, 需要的内存为:xres * yres * 16 / 8,也就是要设置所有像素的颜色,需要这么大小的内存。 这块内存就被称为framebuffer:

  • Framebuffer中每块数据对应一个像素

  • 每块数据的大小可能是16位、32位,这跟LCD上像素的颜色格式有关

  • 设置好LCD硬件后,只需要把颜色数据写入Framebuffer即可

1.3 从驱动角度理解LCD

驱动工程师对LCD的理解要深入硬件,比如要回答这几个问题:

  • Framebuffer在哪里?

  • 谁把Framebuffer中的数据发给LCD?

统一的LCD硬件模型:

 有一个MIPI标准:

MIPI表示Mobile Industry Processor Interface,即移动产业处理器接口。是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。主要是手机内部的接口(摄像头、显示屏接口、射频/基带接口)等标准化,从而减少手机内部接口的复杂程度及增加设计的灵活性。

对于LCD,MIPI接口可以分为3类:

  • MIPI-DBI (Display Bus Interface)

    • 这种接口是一种并行接口,能够同时发送数据和命令。
    • 它通常用于传统的LCD显示技术,与8080、6800等并行接口类似。
    • DBI接口支持多种数据宽度,包括8位、9位、16位、18位和24位,以适应不同的颜色深度和显示需求。
  • MIPI-DPI (Display Pixel Interface)

    • DPI接口专注于像素级别的操作,通常用于集成在微处理器单元(MPU)上的LCD控制器。
    • 这种接口支持不同的颜色深度,包括:
      • 24位每像素(R:8位,G:8位,B:8位)
      • 18位每像素(R:6位,G:6位,B:6位)
      • 16位每像素(R:5位,G:6位,B:5位)
    • DPI接口允许更精细的像素控制,适用于需要高色彩精度的显示应用。
  • MIPI-DSI (Display Serial Interface)

    • DSI接口是一种串行接口,与传统的并行接口相比,它需要更少的接口线,有助于减少设计复杂性和成本。
    • DSI接口支持单数据通道,最大速度可达500Mbps,足以应对高分辨率和高刷新率的显示需求。
    • 它支持DSI版本1.01,提供了一套标准化的通信协议,以实现高效的数据传输和显示控制。
  • 每种MIPI接口都有其特定的应用场景和优势:
    • MIPI-DBI适用于需要并行数据传输的传统LCD显示技术。
    • MIPI-DPI适用于集成在MPU中,需要精细控制像素的LCD控制器。
    • MIPI-DSI则以其高效的串行数据传输和较少的接口线,在现代移动设备中得到广泛应用。

2. Framebuffer驱动程序框架

2.1 如何编写字符设备驱动程序

字符驱动流程如图所示,一般编写字符驱动程序有以下步骤:

  • 驱动主设备号

  • 构造file_operations结构体,填充open/read/write等成员函数

  • 注册驱动:register_chrdev(major, name, &fops)

  • 入口函数

  • 出口函数

2.2 Framebuffer驱动程序框架

概述:分为上下两层:

  • fbmem.c:承上启下

    • 实现、注册file_operations结构体

    • 把APP的调用向下转发到具体的硬件驱动程序

  • xxx_fb.c:硬件相关的驱动程序

    • 实现、注册fb_info结构体

    • 实现硬件操作

Framebuffer驱动程序框架主要分为两个层次:核心层和硬件相关层。下面是这两个层次的简要概述和关键组件:

1. 核心层(fbmem.c)

核心层主要负责处理与VFS(虚拟文件系统)的交互,以及将应用程序的调用转发到具体的硬件驱动程序。这一层通常包含以下组件:

  • file_operations结构体:定义了针对Framebuffer的特殊文件操作,例如open(), release(), ioctl(), mmap()等。这些操作处理来自用户空间的请求。

  • 帧缓冲区管理:管理帧缓冲区的内存分配和释放。这可能包括请求内存区域、处理内存映射等。

  • 事件处理:处理与Framebuffer相关的各种事件,如模式变化、显示关闭和打开等。

  • 数据转发:将应用程序的调用(如读写操作)转发到具体的硬件驱动程序。

2. 硬件相关层(xxx_fb.c)

硬件相关层专注于与特定硬件的交互。这一层通常包含以下组件:

  • fb_info结构体:包含了Framebuffer的所有必要信息,如屏幕大小、颜色深度、帧缓冲区的物理地址等。

  • 硬件操作:实现对硬件的具体操作,包括但不限于:

    • 初始化和配置LCD控制器。
    • 配置屏幕的分辨率、颜色深度等参数。
    • 控制屏幕的开启和关闭。
  • 数据传输:实现数据从CPU内存到Framebuffer的传输,以及可能的DMA(直接内存访问)操作。

  • 中断处理:如果硬件支持中断,注册并实现中断服务例程,以处理例如垂直同步等事件。

  • 注册和注销:在驱动程序加载和卸载时,注册和注销fb_info结构体。

2.3. 怎么编写Framebuffer驱动程序

概述:

  • 分配fb_info

    • framebuffer_alloc

  • 设置fb_info

    • var

    • fbops

    • 硬件相关操作

  • 注册fb_info

    • register_framebuffe

在Linux内核中,分配和设置fb_info结构体以及注册Framebuffer设备通常涉及以下步骤:

1. 分配fb_info

使用framebuffer_alloc()函数从内核内存中分配fb_info结构体的内存。这个函数通常分配一个足够大的内存块,用于存储fb_info结构体以及Framebuffer设备的私有数据。

这里sizeof(struct myfb_data)指定了需要分配的额外内存大小,用于存储特定于驱动程序的数据。

2. 初始化fb_info

设置fb_info结构体的基本属性,包括指向文件操作的指针、固定屏幕信息、可变屏幕信息等。

 

其中固定屏幕信息和可变屏幕信息是指:

在Linux Framebuffer API中,"固定屏幕信息"(fb_fix_screeninfo)和"可变屏幕信息"(fb_var_screeninfo)是两个关键的结构体,它们分别描述了Framebuffer的一些固定属性和可变属性:

固定屏幕信息(fb_fix_screeninfo)

fb_fix_screeninfo结构体包含了一些关于Framebuffer的固定属性,这些属性在设备运行时通常不会改变。这些信息通常由Framebuffer驱动程序设置,并且在注册Framebuffer时提供给内核。固定屏幕信息主要包括:

  • id:Framebuffer设备的标识符。
  • smem_start:Framebuffer内存的起始物理地址。
  • smem_len:Framebuffer内存的长度。
  • type:Framebuffer的类型(例如,真彩色、伪彩色等)。
  • visual:颜色视觉类型(例如,真彩色、伪彩色、直接色等)。
  • xpanstepypanstep:水平和垂直的扫描线长度,决定了屏幕的水平和垂直分辨率。
  • ywrapstep:用于硬件支持的行间隔。
  • line_length:每行的字节长度。

可变屏幕信息(fb_var_screeninfo)

fb_var_screeninfo结构体定义了Framebuffer的一些可变属性,这些属性可以由用户空间程序通过ioctl调用来改变。可变屏幕信息主要包括:

  • xresyres:屏幕的水平和垂直分辨率。
  • xres_virtualyres_virtual:虚拟屏幕的分辨率,用于支持硬件加速的滚动。
  • bits_per_pixel:每个像素的位数。
  • redgreenblue:颜色分量的掩码和位移。
  • transp:透明度掩码和位移(如果支持)。
  • nonstd:非标准模式标志。
  • activate:激活方式。

在Framebuffer驱动程序中,fb_fix_screeninfofb_var_screeninfo通常在驱动加载时初始化,并在注册Framebuffer时作为参数传递给fb_info结构体。这样,当用户空间程序需要查询或设置屏幕参数时,它们可以通过读取或写入fb_info结构体来获取这些信息。

3. 设置var结构体

var结构体(fb_var_screeninfo)定义了屏幕的可变参数,如分辨率、颜色深度、虚拟宽度等。

 

4. 设置fbops结构体

fbopsstruct fb_ops)定义了Framebuffer的操作函数,如fb_open(), fb_release(), fb_ioctl()等。

 

5. 硬件相关操作

实现与硬件交互的函数,包括初始化硬件、设置显示模式、数据传输等。

 

6. 注册fb_info

使用register_framebuffer()函数将fb_info注册到内核中,使其成为系统的一部分。

 

7. 清理和注销

在模块卸载时,需要注销Framebuffer并释放分配的资源。

 

注意事项:

  • 在使用framebuffer_alloc()时,确保提供了足够的内存来存储私有数据。
  • 在设置fb_var_screeninfo时,确保所有参数都符合硬件能力,并且正确反映了屏幕的特性。
  • 在实现fbops中的函数时,确保它们能够正确地处理来自用户空间的请求。
  • 在注册Framebuffer之前,确保所有必要的初始化工作都已完成。

Framebuffer驱动程序的编写需要对Linux内核的Framebuffer API有深入的了解,以及对所操作的硬件有充分的认识。

 3. 编写 Framebuffer_程序框架

通用CFB(Color Frame Buffer)函数:是一组预先定义好的Framebuffer操作函数,它们提供了对Framebuffer进行基本图形操作的能力。这些函数通常在Linux内核的Framebuffer驱动框架中作为默认实现提供,以简化驱动程序的编写。

CFB函数的实现通常考虑了不同颜色深度和像素格式,使得它们可以在多种硬件配置上工作。这些函数作为Framebuffer驱动程序的fb_ops结构体的一部分,当驱动程序注册Framebuffer设备时,它们会被关联到fb_info结构体上。在驱动程序的fb_ops中指定CFB函数,可以让内核知道如何操作Framebuffer进行基本的图形绘制。例如,当用户空间的应用程序请求绘制一个填充矩形时,内核会调用fb_ops中的fb_fillrect函数来执行这个操作。使用CFB函数的好处是它们已经被优化和测试过,可以直接用于多种显示硬件。然而,如果需要更高性能或特殊功能的图形操作,可能需要编写特定硬件的Framebuffer操作函数来替代这些通用函数。

/驱动程序的初始化入口函数:

分配fb_info指的是分配内存给要注册的framebuffer设备。

设置fb_info指的是设置可变屏幕参数,RGB的偏移量和长度(即驱动支持的是哪种格式图片,图片数据中红绿蓝的相应位置),c分配内存:这些操作的目的是为Framebuffer设备分配一块内存,这块内存将用于存储屏幕上显示的像素数据。通过分配DMA一致性内存,可以确保硬件设备(如图形加速器或LCD控制器)能够高效地访问这些数据,从而提高显示性能。

 驱动程序的退出函数,当模块被卸载时调用:

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值