LCD驱动的相关源码路径如下: - kernel/arch/arm/mach-x4412.c
- kernel/arch/arm/plat-s5p/dev-fimd-s5p.c
- kernel/drivers/video/samsung/x4412_lcds.c
- kernel/drivers/video/samsung/s3cfb_main.c
- kernel/drivers/video/samsung/s3cfb.h
复制代码LCD驱动的核心就是初始化LCD控制器的相关寄存器,初始化framebuffer,然后显示数据只需往framebuffer里面填充图像即可。在LCD驱动的移植中,往往我们只是做一些屏的更换,因此我们只需要关心不同的屏之间的差异。在无需多窗口混合显示等要求时,我们完全不必要关心其他的一长串寄存器,因此真正在进行LCD驱动的移植时,就会显得相当的简单。 首先分析LCD驱动的加载过程。在s3cfb_main.c的模块初始化函数s3cfb_register中,通过platform_driver_register函数注册了一个名为s3cfb的平台驱动,在dev-fimd-s5p.c中定义了名为s3cfb的平台设备: - struct platform_device s3c_device_fb = {
- .name = "s3cfb",
- #if defined(CONFIG_ARCH_EXYNOS4)
- .id = 0,
- #else
- .id = -1,
- #endif
- .num_resources = ARRAY_SIZE(s3cfb_resource),
- .resource = s3cfb_resource,
- .dev = {
- .dma_mask = &fb_dma_mask,
- .coherent_dma_mask = 0xffffffffUL
- }
- };
复制代码在mach-x4412.c中注册该平台设备,故s3cfb_main.c中的探测函数s3cfb_probe得到执行,该探测函数构成了整个LCD驱动的主体,用于初始化相关寄存器,申请framebuffer等。与液晶屏相关的函数为s3cfb_set_lcd_info,在探测函数中用于设置液晶屏硬件参数信息,再通过s3cfb_init_global函数设置寄存器,达到液晶屏初始化的目的。 当我们需要更换LCD屏时,通常情况下只需修改LCD的硬件参数即可。在x4412_lcds.c中定义了五组显示屏的参数,依次为ek070tn93、vs070cxn、vga-1024x768、vga-1280x1024以及vga-1920x1200。他们对应800*480的群创屏AT070TN92,1024*600的视声高清屏VS070CXN,1024*768的VGA输出,1280*1024的VGA输出以及1920*1200的VGA输出。默认x4412使用vs070cxn液晶屏,其硬件参数定义如下: - static struct s3cfb_lcd vs070cxn = {
- .width = 1024,
- .height = 600,
- .bpp = 32,
- .freq = 60,
- .timing = {
- .h_fp = 160,
- .h_bp = 140,
- .h_sw = 20,
- .v_fp = 12,
- .v_fpe = 1,
- .v_bp = 20,
- .v_bpe = 1,
- .v_sw = 3,
- },
- .polarity = {
- .rise_vclk = 0,
- .inv_hsync = 1,
- .inv_vsync = 1,
- .inv_vden = 0,
- },
- .init_ldi = NULL,
- };
复制代码该结构体描述了液晶屏的分辨率,显示位数,帧率,行场前后肩,行场时钟有效信号等。不同的屏,这些参数会有所不同,当更改液晶屏时,基本上修改这些参数就可以大功告成了。为此,我们特别在x4412_lcds.c中定义了多组液晶屏参数,通过uboot传参实现不同显示设备的切换,如下代码用于指定液晶屏名称: - static unsigned char lcd_name[32] = "ek070tn93";
- static int __init lcd_setup(char * str)
- {
- if((str != NULL) && (*str != '\0'))//如果lcd的定义不为空,则将它的定义赋给lcd_name
- strcpy(lcd_name, str);
- return 1;
- }
- __setup("lcd=", lcd_setup);//将uboot环境变量中lcd的定义传递给函数lcd_setup
复制代码默认为ek070tn93,当uboot的环境变量中有关于lcd的定义时,将它定义的值赋给lcd_name,在s3cfb_set_lcd_info函数中,通过lcd_name将对应的硬件参数传递给s3cfb_main.c中的探测函数,达到同一个映像实现多款LCD屏的支持。s3cfb_set_lcd_info函数内容如下: - void s3cfb_set_lcd_info(struct s3cfb_global *ctrl)
- {
- struct s3cfb_lcd * lcd = x4412_lcd_config[0].lcd;
- int i;
- for(i = 0; i < ARRAY_SIZE(x4412_lcd_config); i++)
- {
- if(strcasecmp(x4412_lcd_config[i].name, lcd_name) == 0)
- {
- lcd = x4412_lcd_config[i].lcd;
- break;
- }
- }
- ctrl->lcd = lcd;
- printk("lcd: select %s\r\n", lcd_name);
- }
复制代码 该程序通过lcd_name和数组x4412_lcd_config中的名称进行比对,找到指定名称的LCD,并通过形参传递出去。
|