关键词:
LCD驱动端与设备端名称匹配过程
在tiny4412提供的内核下,LCD屏的平台设备名字和平台驱动名字不匹配也能驱动屏点亮,
这是怎么回事的呢?下面我们来分析这是如何实现的。
- 硬件平台
Cpu:exynos4412
板子:tiny4412
Linux内核:linux-3.5
21.6.1 lcd平台驱动层相关代码构架
Lcd平台驱动层在S3c-fb.c (linux-3.5\\drivers\\video)中实现。
21.6.2 s3c_fb_driver平台驱动结构变量
平台驱动结构变量如下:
static struct platform_driver s3c_fb_driver = .probe= s3c_fb_probe, .remove= __devexit_p(s3c_fb_remove), .id_table= s3c_fb_driver_ids, .driver= .name= "s3c-fb", .owner= THIS_MODULE, .pm= &s3cfb_pm_ops, , ; |
驱动层的平台驱动结构实现了id_table,按常理就会根据这个id_table去匹配。
平台驱动结构原型如下:
struct platform_driver int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; ; |
21.6.3 platform_device_id结构变量
先给出platform_device_id结构原型如下:
struct platform_device_id char name[PLATFORM_NAME_SIZE]; kernel_ulong_t driver_data __attribute__((aligned(sizeof(kernel_ulong_t)))); ; |
name数组:用于存放设备的名字,也就是用来和平台设备结构匹配的依据。
driver_data :类型实际上是 unsigned long;
由驱动编写者决定这个整数的用途;
一般是传入一个结构体变量的地址。
内核中定义kernel_ulong_t如下:
typedef unsigned long kernel_ulong_t; |
那么我们就查看s3c_fb_driver_ids,SI跳转进去发现s3c_fb_driver_ids是一个结构数组。定义了许多这个内核支持的cpu的lcd控制器驱动。
代码如下:
static struct platform_device_id s3c_fb_driver_ids[] = .name= "s3c-fb", .driver_data= (unsigned long)&s3c_fb_data_64xx,//arm11 , .name= "s5pc100-fb", .driver_data= (unsigned long)&s3c_fb_data_s5pc100,//A8 , .name= "s5pv210-fb", .driver_data= (unsigned long)&s3c_fb_data_s5pv210,//A8 , .name= "exynos4-fb",//A9,这个就是tiny4412配套的lcd屏 .driver_data= (unsigned long)&s3c_fb_data_exynos4, , .name= "exynos5-fb", .driver_data= (unsigned long)&s3c_fb_data_exynos5, , .name= "s3c2443-fb", .driver_data= (unsigned long)&s3c_fb_data_s3c2443, , .name= "s5p64x0-fb", .driver_data= (unsigned long)&s3c_fb_data_s5p64x0, , , ; |
按常理来说,lcd屏的设备层会来跟上面的id_table数组进行匹配,匹配成就会获取相应的.driver_data结构数据。
在tiny4412板子上,lcd平台设备端的name应该是"exynos4-fb"才会成功匹配。
21.6.4 lcd平台设备层相关代码构架
Tiny4412 开发板所带内核源码中已经集成了 LCD 驱动的平台设备层代码;
21.6.5 内核启动阶段,板级相关设备驱动初始化结构
内核在启动阶段把平台设备注册进内核,这段代码实现在:
Mach-tiny4412.c (linux-3.5\\arch\\arm\\mach-exynos)文件中。
在文件最后有如下代码段:
MACHINE_START(TINY4412, "TINY4412") /* Maintainer: FriendlyARM (www.arm9.net) */ /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */ /* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */ .atag_offset= 0x100, .init_irq= exynos4_init_irq, .map_io= smdk4x12_map_io, .handle_irq= gic_handle_irq, .init_machine= smdk4x12_machine_init, .init_late= exynos_init_late, .timer= &exynos4_timer, .restart= exynos4_restart, .reserve= &smdk4x12_reserve, MACHINE_END |
代码中给 .init_machine 指针赋值 smdk4x12_machine_init;
.init_machine 指针指向的函数在系统启动前期就会被运行,板级相关设备驱动初始化、注册一般都是写在这个函数中,平台设备注册一般就是在此函数中编写。
那么接下来找到 smdk4x12_machine_init 函数实现,然后再寻找和平台设备注册相关的代码进行分析。
21.6.6 smdk4x12_machine_init函数实现
smdk4x12_machine_init函数实现代码如下:
static void __initsmdk4x12_machine_init(void) #ifdef CONFIG_S3C64XX_DEV_SPI0 spi_register_board_info(spi0_board_info, ARRAY_SIZE(spi0_board_info)); #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 spi_register_board_info(spi1_board_info, ARRAY_SIZE(spi1_board_info)); #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 spi_register_board_info(spi2_board_info, ARRAY_SIZE(spi2_board_info)); #endif s3c_i2c0_set_platdata(NULL); if (samsung_pack() == EXYNOS4412_PACK_SCP) #ifdef CONFIG_REGULATOR_S5M8767 i2c_register_board_info(0, smdk4x12_i2c_devs0_s5m8767, ARRAY_SIZE(smdk4x12_i2c_devs0_s5m8767)); #endif else #ifdef CONFIG_REGULATOR_MAX77686 max77686_populate_pdata(); i2c_register_board_info(0, smdk4x12_i2c_devs0_max77686, ARRAY_SIZE(smdk4x12_i2c_devs0_max77686)); #endif s3c_i2c1_set_platdata(NULL); i2c_register_board_info(1, smdk4x12_i2c_devs1, ARRAY_SIZE(smdk4x12_i2c_devs1)); s3c_i2c2_set_platdata(NULL); i2c_register_board_info(2, smdk4x12_i2c_devs2, ARRAY_SIZE(smdk4x12_i2c_devs2)); s3c_i2c3_set_platdata(NULL); i2c_register_board_info(3, smdk4x12_i2c_devs3, ARRAY_SIZE(smdk4x12_i2c_devs3)); s3c_i2c4_set_platdata(NULL); smdk4x12_rtc_wake_init(); smdk4x12_pmu_wdt_init(); smdk4x12_touch_init(); s3c_i2c7_set_platdata(NULL); i2c_register_board_info(7, smdk4x12_i2c_devs7, ARRAY_SIZE(smdk4x12_i2c_devs7)); s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata); #ifdef CONFIG_USB_EXYNOS_SWITCH smdk4x12_usbswitch_init(); #endif samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data); s5p_fimd0_set_platdata(&smdk4x12_lcd0_pdata);//设置私有数据 #ifdef CONFIG_LCD_LMS501KF03 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); #endif samsung_keypad_set_platdata(&smdk4x12_keypad_data); #ifdef CONFIG_EXYNOS4_DEV_DWMCI exynos_dwmci_set_platdata(&exynos_dwmci_pdata); #endif s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata); s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata); #ifdef CONFIG_ION_EXYNOS exynos_ion_set_platdata(); #endif s5p_tv_setup(); s5p_i2c_hdmiphy_set_platdata(NULL); s5p_hdmi_set_platdata(smdk4x12_i2c_hdmiphy, NULL, 0); #ifdef CONFIG_VIDEO_EXYNOS_FIMG2D s5p_fimg2d_set_platdata(&fimg2d_data); #endif #if defined(CONFIG_VIDEO_M5MOLS) || defined(CONFIG_VIDEO_S5K6A3) smdk4x12_camera_init(); #endif #ifdef CONFIG_VIDEO_EXYNOS_FIMC_LITE smdk4x12_set_camera_flite_platdata(); s3c_set_platdata(&exynos_flite0_default_data, sizeof(exynos_flite0_default_data), &exynos_device_flite0); s3c_set_platdata(&exynos_flite1_default_data, sizeof(exynos_flite1_default_data), &exynos_device_flite1); #endif smdk4x12_ehci_init(); #ifdef CONFIG_S3C64XX_DEV_SPI0 s3c64xx_spi0_set_platdata(NULL, 0, 1); #endif #ifdef CONFIG_S3C64XX_DEV_SPI1 s3c64xx_spi1_set_platdata(NULL, 0, 1); #endif #ifdef CONFIG_S3C64XX_DEV_SPI2 s3c64xx_spi2_set_platdata(NULL, 0, 1); #endif smdk4x12_ohci_init(); /* 注册多个平台设备 */ platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices)); #ifdef CONFIG_VIDEO_EXYNOS_FIMC_IS exynos4_fimc_is_set_platdata(NULL); #endif if (soc_is_exynos4412()) if ((samsung_rev() >= EXYNOS4412_REV_2_0)) initialize_prime_clocks(); else initialize_non_prime_clocks(); #ifdef CONFIG_BUSFREQ_OPP dev_add(&busfreq, &exynos4_busfreq.dev); ppmu_init(&exynos_ppmu[PPMU_DMC0], &exynos4_busfreq.dev); ppmu_init(&exynos_ppmu[PPMU_DMC1], &exynos4_busfreq.dev); ppmu_init(&exynos_ppmu[PPMU_CPU], &exynos4_busfreq.dev); #endif set_tmu_platdata(); |
在上面函数中会调用平台设备注册函数,如下:
/* 注册多个平台设备 */ platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices)); |
其中参数smdk4x12_devices就是注册的平台设备结构数组指针;
21.6.7 smdk4x12_devices平台设备结构数组
SI跳转查看smdk4x12_devices结构,代码段如下:
/* 多平台设备结构变量指针 */ static struct platform_device *smdk4x12_devices[] __initdata = #ifdef CONFIG_EXYNOS4_DEV_DWMCI &exynos_device_dwmci, #endif &s3c_device_hsmmc2, &s3c_device_hsmmc3, &wm8994_fixed_voltage0, &wm8994_fixed_voltage1, &wm8994_fixed_voltage2, &s3c_device_i2c0, &s3c_device_i2c1, &s3c_device_i2c2, &s3c_device_i2c3, #ifdef CONFIG_VIDEO_M5MOLS &s3c_device_i2c4, #endif &s3c_device_i2c7, &s3c_device_adc, &s3c_device_rtc, &s3c_device_wdt, #ifdef CONFIG_TINY4412_BUZZER &s3c_device_timer[0], #endif #ifdef CONFIG_VIDEO_EXYNOS_FIMC_LITE & LCD驱动也是字符设备驱动,也遵循字符设备驱动的流程:a.分配主设备号b.构建file_operations结构体中的open,write,read...等函数c.调用register_chrdev()函数注册字符设备d.调用class_register()注册类e.调用device_create()创建设备,linux会在sysfs目... 查看详情 ...总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver。Linux 2.6的设备驱动模型中,把I2C、RTC、LCD等都归纳为platform_device。总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱... 查看详情 ...一副图像所需要的数据。因此,帧缓冲其实就是LCD设备的驱动程序) 一.LCD驱动程序框架根据上述思路,LinuxLCD驱动程分为两个层次,如下图所示类似于Platform平台驱动框架,也将驱动程序分为相对稳定的算法驱动,即fb总线... 查看详情 1、驱动源码分析大致思路(1)分析LCD驱动首先需要分析内核的帧缓冲子系统,因为LCD驱动就是按照帧缓冲子系统提供的注册接口来注册的;(2)内核帧缓冲子系统参考博客:《Linux帧缓冲子系统详解:LCD介绍、framebuffe... 查看详情 ...作起来。全志的boot阶段,对应平板这一块,它会驱动LCD,显示一些开机LOGO,这个过程很快,也就1-2秒钟的时间。然而对于车载行业应用来说,可能需要再boot阶段做一些事 查看详情 ...能用,看屏幕显示了三排小企鹅,并且存在色差,怀疑lcd驱动并不配套HD700之个型号,故需要做调整。解决办法:linux3.5中内核已经具备了HD700型号显示的驱动,只需在uboot引导内核传参的时候加上“ 查看详情 一、LCD硬件原理 利用液晶制成的显示器LCD,依据驱动方式可分为静态驱动、简单矩阵驱动以及主动矩阵驱动3中。其中,简单矩阵型又可再区分扭转向列型(TN)和超扭转式向列型(STN)两种,而主动矩阵型则以薄膜式晶体管... 查看详情 LCD驱动分析原文地址:http://blog.csdn.net/woshidahuaidan2011/article/details/520547951、对LCD驱动添加设备信息对lcd驱动程序,跟之前分析的方式一样,还是先看设备信息,其定义在Mach-smdk2440.c(arch\\arm\\mach-s3c24xx)文件中,在该文... 查看详情 参考:S3C2440LCD驱动(FrameBuffer)实例开发<一> S3C2440LCD驱动(FrameBuffer)实例开发<二> 查看详情 ...习笔记,基于DPDK17.11版本源码分析。主要分析一下igb_uio驱动源码。首先简单介绍一下kernel中的总线-设备-驱动模型,以pci总线为例,pci总线上有两个表,一个用于保存系统中的pci设备,一个用于保存pci设备对应的驱动。每当加载... 查看详情 目录Linux下LCD驱动简析1Framebuffer设备LCD驱动简析硬件原理图分析LCD驱动程序编写运行测试LCD屏幕基本测试设置LCD作为终端控制台LCD背光调节从LCD自动关闭解决方法LCD是很常用的一个外设,在裸机篇中我们讲解了如何编写LCD裸... 查看详情 ...---------------------------------------在上一节我们已经移植了LCD驱动,那么本节将会移植LCD触摸屏驱动。有关触摸屏的原理,以及硬件接线,我们在linux驱动移植-LCD触摸屏设备驱动章节已经介绍的非常清楚了。同时在这一篇博客,我们... 查看详情 LCD是Liquid Crystal Display的简称,也就是经常所说的液晶显示器LCD能够支持彩色图像的显示和视频的播放,是一种非常重要的输出设备 Framebuffer是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件... 查看详情 ...U盘)固件基础5.LinuxUSB子系统初始化6.LinuxUSB主机控制器(HCD)驱动6.1USB主机控制器驱动初始化6.2USB主机控制器设备对象注册和驱动加载7.LinuxUSB设备驱动加载过程7.1`HUB类设备`驱动加载过程7.2`非HUB类设备`驱动加载过程7.2.1... 查看详情 转自:http://blog.csdn.net/hanmengaidudu/article/details/215591531.S3C2440上LCD驱动(FrameBuffer)实例开发讲解其中的代码也可直接参考:drivers/video/s3c2410fb.c以下为转载文章,文章原地址:http://blog.csdn.net/jianyun123/archive/2010/04/24/55 查看详情 编程_LCD驱动程序框架_使用设备树参考资料,GIT仓库里:基于这个程序修改:IMX6ULL\\source\\03_LCD\\03_lcd_drv_qemu_okSTM32MP157\\source\\A7\\03_LCD\\03_lcd_drv_qemu_ok参考:内核自带的示例驱动程序Linux驱动源码:drivers/v 查看详情 本章内容:Linux设备驱动的基本概念Linux设备驱动程序的基本功能linux设备驱动的运作过程常见设备驱动接口函数掌握LCD设备驱动程序编写步骤掌握键盘设备驱动程序编写步骤设备驱动简介设备驱动程序是内核的一部分。OS通过各... 查看详情 对屏幕进行抓屏cp/dev/fb0myfile.png帧缓冲设备的主设备号29,次设备号0-31,也就是dev/fb0-dev/fb31填充一个fbinfo结构。用register_framebuffer(fbinfo*)将fbinfo结构注冊到内核,对于fbinfo结构,最基本的是fs_ops成员,须要针对详细设备实现fs_ops... 查看详情 |