一,前言
s3c2440 lcd 驱动分析,涉及到的内容有,LCD图像显示原理、s3c2440的LCD控制器的操作、LCD驱动使用平台总线-设备-驱动模型的实例、LCD相关参数的设置、fb字符设备驱动实例、framebuffer的注册和管理、以及一次LCD显示的完整过程分析。
二,LCD原理和硬件分析
2.1 LCD原理解析
SDRAM:在SDRAM中申请了一块连续的内存作为LCD显示数据的存储,叫做显存(framebuffer)。
LCD控制器:LCD控制器通过硬件电路和LCD屏连接。
LCD屏:作为一个外设通过硬件电路和MCU(引脚配置为LCD引脚)连接。
图像在LCD屏上显示,可以看成是LCD控制器先从显存中取出一帧图像数据,然后输入到LCD屏上。480272的屏,所显示的一帧有480272个像素点、272行、480列。对于每一行的像素点,LCD控制器有一个VCLK信号控制,每来一个VCLK,显示的像素点就向右移动一个,当移动到这一行中的最后一个像素点时,LCD控制器有一个HSYNC信号,控制像素点跳到下一行的第一个像素显示。对于一帧图像(也叫一场),即当像素点移动到最后一行的最后一个位置显示完后,LCD控制器有一个VSYNC信号,控制像素点重新移动到第一行的第一个像素显示下一帧图像。
2.2 硬件电路
2.2.1 LCD背光电路
开启LCD显示,需要使能KEYBOARD(一般EN表示高电平有效,EN上面画一横表示低电平有效)开启背光。
背光开关通过主控,GPB0引脚设置
2.2.2 LCD屏
VLINE:HSYNC信号输出引脚(由LCD控制器操作)
VFRAME:VSYNC信号输出引脚(由LCD控制器操作)
VCLK:VCLK信号输出引脚(由LCD控制器操作)
VD3~VD7:RGB(565)中B数据输出引脚
VD10~VD15:RGB(565)中G数据输出引脚
VD19~VD23:RGB(565)中R数据输出引脚
TS*:供ts触摸屏连接
2.2.3 S3c2440主控
涉及 GPG、GPD、GPC引脚。
VM:LCD控制器使能引脚(由LCD控制器的寄存器配置),开启LCD显示需要配置相关寄存器的相应位使能。 LCD_PWREN:LCD电源使能引脚(由LCD控制器的寄存器配置),开启LCD显示需要配置相关寄存器的相应位使能。
三,LCD应用平台总线-设备-驱动模型
3.1 lcd 设备的加载和注册
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, .timer = &s3c24xx_timer, MACHINE_END 将上面的宏展开 static const struct machine_desc __mach_desc_SMDK2440 __attribute_used__ __attribute__((__section__(".arch.info.init"))) = { .nr = MACH_TYPE_SMDK2410, /* architecture number */ .name = "SMDK2440", /* architecture name */ /* Maintainer: Jonas Dietsche */ .phys_io = S3C2410_PA_UART, /* start of physical io */ .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, /* tagged list */ .map_io = smdk2440_map_io, /* IO mapping function */ .init_irq = s3c24xx_init_irq, .init_machine = smdk2440_machine_init, .timer = &s3c24xx_timer, } MACHINE_START主要是定义了"struct machine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel 起来之后将被丢弃。 各个成员函数在不同时期被调用: 1.init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用。 2. init_irq在start_kernel() -> init_IRQ() -> init_arch_irq() 被调用 3. map_io 在 setup_arch() -> paging_init() -> devicemaps_init()被调用 其他主要都在 setup_arch() 中用到。 系统初始化时,会调用smdk2440_machine_init static void __init smdk2440_machine_init(void) { // 这里设置LCD的参数,和驱动分离。这样要修改LCD时,驱动层程序可以不需要改动,只需修改设备层参数就行了,方便移植。 s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg); // 将smdk2440_devices数组中的设备注册到平台总线 platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); smdk_machine_init(); } // smdk2440_devices数组 static struct platform_device *smdk2440_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c, &s3c_device_iis, &s3c2440_device_sdi, }; // lcd设备 struct platform_device s3c_device_lcd = { .name = "s3c2410-lcd", .id = -1, .num_resources = ARRAY_SIZE(s3c_lcd_resource), .resource = s3c_lcd_resource, .dev = { .dma_mask = &s3c_device_lcd_dmamask, .coherent_dma_mask = 0xffffffffUL } }; // 设置lcd设备参数 smdk2440_lcd_cfg。各参数含义后面在probe分析时解析 /* 480x272 */ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = { .regs = { .lcdcon1 = S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT | S3C2410_LCDCON1_CLKVAL(0x04), .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | S3C2410_LCDCON2_LINEVAL(271) | S3C2410_LCDCON2_VFPD(1) | S3C2410_LCDCON2_VSPW(9), .lcdcon3 = S3C2410_LCDCON3_HBPD(1) | S3C2410_LCDCON3_HOZVAL(479) | S3C2410_LCDCON3_HFPD(1), .lcdcon4 = S3C2410_LCDCON4_HSPW(40), .lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, }, .gpccon = 0xaaaaaaaa, .gpccon_mask = 0xffffffff, .gpcup = 0xffffffff, .gpcup_mask = 0xffffffff, .gpdcon = 0xaaaaaaaa, .gpdcon_mask = 0xffffffff, .gpdup = 0xffffffff, .gpdup_mask = 0xffffffff, .fixed_syncs = 1, .type = S3C2410_LCDCON1_TFT, .width = 480, .height = 272, .xres = { .min = 480, .max = 480, .defval = 480, }, .yres = { .max = 272, .min = 272, .defval = 272, }, .bpp = { .min = 16, .max = 16, .defval = 16, }, }; 调用platform_device_register注册平台设备 int platform_add_devices(struct platform_device **devs, int num) { int i, ret = 0; for (i = 0; i < num; i++) { ret = platform_device_register(devs[i]); if (ret) { while (--i >= 0) platform_device_unregister(devs[i]); break; } } return ret; } 3.2 lcd 驱动的加载和注册 3.2.1 编译进内核,加载驱动 编译内核设置,make menuconfig -> Device Drivers -> Graphics support <*> Support for frame buffer devices linux-2.6.22.6/.config CONFIG_FB_S3C2410=y linux-2.6.22.6/drivers/video/Makefile obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o 然后make uImage,将s3c2410fb驱动编译进内核,系统启动便会加载,即调用驱动的s3c2410fb_init函数。 int __devinit s3c2410fb_init(void) { // 注册到平台总线驱动 return platform_driver_register(&s3c2410fb_driver); } 3.3 lcd 设备和驱动的匹配 3.3.1 lcd设备注册时的匹配 platform_device_register -> platform_device_add -> device_add -> bus_attach_device -> device_attach -> bus_for_each_drv -> // 从平台总线的的驱动链表中,取出每一项驱动进行匹配 __device_attach -> driver_probe_device -> if (drv->bus->match && !drv->bus->match(dev, drv)) 此总线类型为平台总线,其存在match函数,即调用platform_match进行匹配 // 平台总线 struct bus_type platform_bus_type = { .name = "platform", .dev_attrs = platform_dev_attrs, .match = platform_match, .uevent = platform_uevent, .suspend = platform_suspend, .suspend_late = platform_suspend_late, .resume_early = platform_resume_early, .resume = platform_resume, }; static int platform_match(struct device * dev, struct device_driver * drv) { struct platform_device *pdev = container_of(dev, struct platform_device, dev); // 平台总线匹配设备和驱动的名称 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } // lcd 设备 name = "s3c2410-lcd" struct platform_device s3c_device_lcd = { .name = "s3c2410-lcd", .id = -1, .num_resources = ARRAY_SIZE(s3c_lcd_resource), .resource = s3c_lcd_resource, .dev = { .dma_mask = &s3c_device_lcd_dmamask, .coherent_dma_mask = 0xffffffffUL
上一篇:Linux驱动:s3c2440 lcd 驱动分析
下一篇:Linux驱动:s3c2410/s3c2440 ts驱动分析 之二
推荐阅读最新更新时间:2024-11-18 12:50
设计资源 培训 开发板 精华推荐
- AZ431大电流并联稳压器典型应用电路
- LM324ADTBG 双四路滤波器运算放大器的典型应用
- 具有过压/欠压保护电路的可调式精密并联稳压器的典型应用
- 具有固定输出电压和精密使能引脚的 ADP5135 降压稳压器的典型应用
- 使用 ROHM Semiconductor 的 BD4858 的参考设计
- LTM8042EV 1A 升压 LED 驱动器的典型应用电路,驱动 8 个白光 LED
- 使用 ON Semiconductor 的 SR20010 的参考设计
- STR-10-16V-BLDC-MDK-GEVK:600W、10-16V 电机开发套件
- SiGe BFP640 作为 2.4GHz 低噪声放大器
- DC2111A-B,基于 LTC3774EUHE 4 相 (LTC3774 x2) 的演示板,10V = VIN = 14V,Vout = 1.2V @ 120A 同步降压控制器
- 团结起来,问倒TI专家团!!!
- 安森美半导体重磅推出超低功耗蓝牙芯片 RSL10 — 观视频答题送样片 更有丰富礼品等你拿!
- 打造健康生活,成就强劲工具 TE Connectivity (TE) 智慧生活子系统解决方案
- 下载有礼:2017年泰克亚太专家大讲堂第二期: 100G/200G/400G通讯标准发展趋势及解决方案
- 免费申请 | ST多款开发板返场测评
- 开启Altera SoC体验之旅,玩转Altera Cyclone V系列SoC
- 了解Keithley 4200-SCS参数分析仪,下载技术文章,抽奖赢礼!
- 申请ufun学习板,入门&深度学习模拟,工程技能
- 数据采集系统设计原则与基本方法