基于Exynos4412的lcd驱动1

用于温故而知新,也希望能够帮到大家,当中也许会有错误,欢迎大家帮我纠错。
驱动层(控制器层):一般由芯片原厂提供,实现了LCD控制器通用的操作接口和配置接口,本章用到的是三星提供的s3cfb_main.c和s3cfb_ops.c
设备层:一般由单板厂商提供,本章用到的是arch/arm/plat-s5p/dev-fimd-s5p.c文件
注意:有的开发板的驱动层可能是s3c-fb.c,这要取决于:

  1. drivers/video/Makefile中的约束条件,比如我的Makefile是obj-$(CONFIG_FB_S3C) += s3c-fb.o
  2. 内核根目录下的.config是否配置了CONFIG_FB_S3C这个宏,比如我的.config是

接下来开始我们的代码跟读。

内核定义的config

以下是查看.config得到的信息,关于lcd一些宏的定义
CONFIG_FB_S5P_LMS501KF03 is not set
CONFIG_FB_S3C is not set
CONFIG_FB_S5P_TRACE_UNDERRUN is not set
CONFIG_FB_S5P_VIRTUAL is not set
CONFIG_FB_S5P_LCD_INIT=y
CONFIG_FB_S5P=y
CONFIG_ARCH_EXYNOS4=y
CONFIG_FB_S5P_DEFAULT_WINDOW=0
CONFIG_FB_S5P_NR_BUFFERS=2
CONFIG_HAS_WAKELOCK=y
CONFIG_FB_S5P_NR_BUFFERS=2

进入linux/arch/arm/mach-exynos/mach-itop4412.c

这是我们的启动文件
smdk4x12_machine_init
|
#ifdef CONFIG_FB_S5P_LMS501KF03 //这个宏没定义
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
s3cfb_set_platdata(&lms501kf03_data);
#else
s3cfb_set_platdata(NULL); //真正执行的函数,下一节分析
|
platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
|
smdk4412_devices
|
#ifdef CONFIG_FB_S5P(这个宏有定义,看第一节config)
&s3c_device_fb,

总结:会执行s3cfb_set_platdata(NULL)这个函数,注册s3c_device_fb这个设备

跳转到linux/arch/arm/plat-s5p/dev-fimd-s5p.c

1.如下,注册设备,名字、资源、dma
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掩码
.dma_mask = &fb_dma_mask,
.coherent_dma_mask = 0xffffffffUL
}
};

2.在看s3cfb_set_platdata函数前先了解一个结构体,这个结构体主要定义了关于lcd的一系列操作函数,如背光打开,设置引脚状态,开时钟。
struct s3c_platform_fb {
int hw_ver;
char clk_name[16];
int nr_wins;
int nr_buffers[5];
int default_win;
void (*cfg_gpio)(struct platform_device *dev);
int (*backlight_on)(struct platform_device *dev);
int (*backlight_off)(struct platform_device *dev);
int (*lcd_on)(struct platform_device *dev);
int (*lcd_off)(struct platform_device *dev);
int (*clk_on)(struct platform_device *pdev, struct clk **s3cfb_clk);
int (*clk_off)(struct platform_device *pdev, struct clk **clk);
};
接下来定义了一个结构体变量default_fb_data ,对那些参数进行赋值。
static struct s3c_platform_fb default_fb_data __initdata = {
#if defined(CONFIG_ARCH_EXYNOS4)
.hw_ver = 0x70,
#else
.hw_ver = 0x62,
#endif
.nr_wins = 5,
#if defined(CONFIG_FB_S5P_DEFAULT_WINDOW)
.default_win = CONFIG_FB_S5P_DEFAULT_WINDOW,
#else
.default_win = 0,
#endif
.swap = FB_SWAP_WORD | FB_SWAP_HWORD,
};

最后主角来了,s3cfb_set_platdata函数,这个函数主要用来将上面s3c_platform_fb 结构体的值赋值到dev.platform_data(私有数据中去),这样在驱动中,我们也能调用这些数据。
void __init s3cfb_set_platdata(struct s3c_platform_fb *pd)
{
struct s3c_platform_fb *npd;
int i;

if (!pd)
	pd = &default_fb_data;

//npd就是pd,pd是default_fb_data
npd = kmemdup(pd, sizeof(struct s3c_platform_fb), GFP_KERNEL);
if (!npd)
printk(KERN_ERR “%s: no memory for platform data\n”, func);
else {
for (i = 0; i < npd->nr_wins; i++)
npd->nr_buffers[i] = 1;
s3cfb_get_clk_name(npd->clk_name);
npd->cfg_gpio = s3cfb_cfg_gpio;
npd->backlight_on = s3cfb_backlight_on;
npd->backlight_off = s3cfb_backlight_off;
npd->lcd_on = s3cfb_lcd_on;
npd->lcd_off = s3cfb_lcd_off;
npd->clk_on = s3cfb_clk_on;
npd->clk_off = s3cfb_clk_off;
//将npd赋值到pdev私有数据,npd中定义有lcd的应用函数,lcd的硬件初始化
s3c_device_fb.dev.platform_data = npd;
}
}

总结:所以说在启动的时候内核会自动调用s3cfb_set_platdata函数,这个函数主要内容是硬件初始化,然后把这些数据赋值到dev.platform_data,以便于后续再pdrv中使用。

在分析pdrv之前先熟悉几个结构体

这是一个全局变量s3cfb_global 。
struct s3cfb_global {
struct device *dev;
struct clk *clock;
struct fb_info **fb;
atomic_t enabled_win;
enum s3cfb_output_t output;
enum s3cfb_rgb_mode_t rgb_mode;
struct s3cfb_lcd *lcd;
};

这个结构体中包括分辨率、时钟、极性等
struct s3cfb_lcd {
int width;
int height;
int bpp;
int freq;
struct s3cfb_lcd_timing timing;
struct s3cfb_lcd_polarity polarity;

};

在介绍pdrv之前再介绍一下设备参数相关文件

在linux/drivers/video/samsung/s3cfb_wa101s.c中
s3cfb_setup_lcd主要用来设置lcd硬件参数,包括分辨率、时钟、极性等,这些需要根据手册设置。
s3cfb_set_lcd_info函数的作用就是把s3cfb_global 结构体中的lcd指向wa101,所以说,硬件方面我们主要是在这里进行设置,然后内核调用s3cfb_set_lcd_info就把我们设置的参数传递进去了。
static struct s3cfb_lcd wa101 ;
void s3cfb_setup_lcd()
{
wa101.width = 480;
wa101.height = 272;
wa101.bpp = 24;
wa101.freq = 40;//60;
wa101.timing.h_fp = 10;//48,
wa101.timing.h_bp = 30;//80,
wa101.timing.h_sw = 41;//32,
wa101.timing.v_fp = 10;//2,//3,
wa101.timing.v_fpe = 0;
wa101.timing.v_bp = 10;//2,//14,
wa101.timing.v_bpe = 0;
wa101.timing.v_sw = 10;//5,
wa101.polarity.rise_vclk = 0;//1,
wa101.polarity.inv_hsync = 0;
wa101.polarity.inv_vsync = 0;//1,
wa101.polarity.inv_vden = 0;//0,
}

}

void s3cfb_set_lcd_info(struct s3cfb_global *ctrl)
{
s3cfb_setup_lcd();
wa101.init_ldi = NULL;
ctrl->lcd = &wa101;
}

这样pdev的内容就讲完了,主要讲了硬件参数是包装在什么结构体之中,是如何传递给驱动的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值