LCD驱动端与设备端名称匹配过程分析(Tiny4412)

Posted DS小龙哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LCD驱动端与设备端名称匹配过程分析(Tiny4412)相关的知识,希望对你有一定的参考价值。

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驱动端与设备端名称匹配过程分析(Tiny4412)的主要内容,如果未能解决你的问题,请参考以下文章

平台设备驱动注册及使用分析

LCD驱动分析字符设备驱动框架分析

tiny4412SDK 1161下的HD700驱动设置

Linux驱动分析之LCD驱动架构

LCD驱动程序之层次分析

七 linux LCD驱动代分析

(c)2006-2024 SYSTEM All Rights Reserved IT常识