LCD 驱动程序分析

更新时间:
2024-01-09
下载文档

LCD 驱动程序分析

设备创建

LCD 驱动需调用 API_GMemDevAdd 函数,以在图形显示设备层中创建一个可供应用程序调用的显示设备,其函数原型如下:

#include <SylixOS.h> 
INT   API_GMemDevAdd (CPCHAR  cpcName, PLW_GM_DEVICE  pgmdev);

函数 API_GMemDevAdd 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 cpcName 是创建的图形显示设备的名称。
  • 参数 pgmdev 是该图形显示设备的 LW_GM_DEVICE 结构。

驱动程序在调用 API_GMemDevAdd 之前应初始化该图形显示设备使用的操作集指针,如在 S3C2440 中 LCD 设备创建函数中有如下的实现:

INT  lcdDevCreate (VOID)
{
_G_gmfoS3c2440a.GMFO_pfuncOpen           = __lcdOpen;
_G_gmfoS3c2440a.GMFO_pfuncClose          = __lcdClose;
_G_gmfoS3c2440a.GMFO_pfuncGetVarInfo     = (INT (*)(LONG,
                                                    PLW_GM_VARINFO))__lcdGetVarInfo;
_G_gmfoS3c2440a.GMFO_pfuncGetScrInfo     = (INT (*)(LONG, 
PLW_GM_SCRINFO))__lcdGetScrInfo;
_G_gmdevS3c2440a.GMDEV_gmfileop          = &_G_gmfoS3c2440a;

return  (gmemDevAdd("/dev/fb0", &_G_gmdevS3c2440a));
}

实现属性读取接口

LCD 驱动里需要实现获取显示规格的接口,并初始化可视区域大小、像素点色彩模式等数据,S3C2440 的 LCD 获取显示规格的接口如下:

#define LCD_XSIZE                   800
#define LCD_YSIZE                   480
static INT    __lcdGetVarInfo (PLW_GM_DEVICE  pgmdev, PLW_GM_VARINFO  pgmvi)
{
if (pgmvi) {
     pgmvi->GMVI_ulXRes                   = LCD_XSIZE;
     pgmvi->GMVI_ulYRes                   = LCD_YSIZE;
     pgmvi->GMVI_ulXResVirtual            = LCD_XSIZE;
     pgmvi->GMVI_ulYResVirtual            = LCD_YSIZE;
     pgmvi->GMVI_ulXOffset                = 0;
     pgmvi->GMVI_ulYOffset                = 0;
     pgmvi->GMVI_ulBitsPerPixel           = 16;
     pgmvi->GMVI_ulBytesPerPixel          = 2;
     pgmvi->GMVI_ulGrayscale              = 65536;
     pgmvi->GMVI_ulRedMask                = 0xF800;
     pgmvi->GMVI_ulGreenMask              = 0x03E0;
     pgmvi->GMVI_ulBlueMask               = 0x001F;
     pgmvi->GMVI_ulTransMask              = 0;
     pgmvi->GMVI_bHardwareAccelerate      = LW_FALSE;
     pgmvi->GMVI_ulMode                   = LW_GM_SET_MODE;
     pgmvi->GMVI_ulStatus                 = 0;
}    
return  (ERROR_NONE);
}

由此可知,S3C2440 的 LCD 初始化设置为 RGB565 的色彩模式,可视区域的宽为 800 像素,高为 480 像素。

LCD 驱动里需要实现获取显示属性的接口,如下:

static INT   __lcdGetScrInfo (PLW_GM_DEVICE  pgmdev, PLW_GM_SCRINFO  pgmsi)
{
if (pgmsi) {
     pgmsi->GMSI_pcName                 = "/dev/fb0";
     pgmsi->GMSI_ulId                   = 0;
     pgmsi->GMSI_stMemSize              = 800 * 480 * 2;
     pgmsi->GMSI_stMemSizePerLine       = LCD_XSIZE * 2;
     pgmsi->GMSI_pcMem                  = (caddr_t)__LCD_FRAMEBUFFER_BASE;
}    
return  (ERROR_NONE);
}

由此可知,S3C2440 的 LCD 对应设备节点“/dev/fb0”,设备 ID 为 0,其申请的 FrameBuffer 大小为 800×480×2 个字节。

申请 FrameBuffer 使用的基地址

在显示属性获取的接口中需要初始化 FrameBuffer 使用的基地址,FrameBuffer 的基址一般为满足对齐关系的 DMA 物理内存,申请的 DMA 内存大小为:最大高度 × 最大宽度 × 每个像素所占字节数。在 S3C2440 中,FrameBuffer 内存申请操作如下:

if (GpvFbMemBase == LW_NULL) {
GpvFbMemBase =  API_VmmPhyAllocAlign(800 * 480 * 2,             
                                           4 * 1024 * 1024,
                                           LW_ZONE_ATTR_DMA);             
if (GpvFbMemBase == LW_NULL) {
    __lcdOff();
    printk(KERN_ERR "__lcdOpen() low vmm memory!\n");
    return  (PX_ERROR);
}
__lcdInit();
}

应用程序 mmap 驱动程序中申请的 FrameBuffer 内存,并初始化 LCD 显示时序后,按照规定的格式将显示数据拷贝到 FrameBuffer 中,屏幕上就能显示出图像。

LCD 时序设置

LCD 驱动中最核心的是设置 LCD 显示时序,一般 LCD 控制器中会提供一组时序控制寄存器。在 LCD 初始化时,应该将对应屏幕能够显示的时序(VSYNC、HSYNC 等)数据设置到这组寄存器中。

背光亮度调节

LCD 屏幕的背光亮度一般由 PWM 控制,调整 PWM 的占空比即可实现对 LCD 背光亮度的调节。一般应将 PWM 的驱动单独实现为字符设备,并提供调节占空比的方法,在 LCD 中调用该调节接口,则可实现对背光亮度的调节。

文档内容是否对您有所帮助?
有帮助
没帮助