前言
在移植LCD驱动,当然得找到LCD驱动的驱动端了,根据以前了解的很快就能找到下面的配置:
Device Drivers --->
Graphics support --->
Frame buffer Devices --->
<*> Samsung S3C framebuffer support //在配置上还是有这个,那样只要把设备端配置好就行
[*] Bootup logo --->
但是接下来,并不以这个来移植LCD驱动程序。居然用了设备树,那么就用内核自带的设备树来做,所以才有下面的LCD驱动移植。
1、使用新的LCD驱动
新的LCD驱动文件在:linux-4.2.6\drivers\gpu\drm\exynos\exynos_drm_fimd.c
1.1 配置支持新的LCD驱动
其中exynos_drm_dpi.c的函数会被exynos_drm_fimd.c中调用,配置下面两个文件
exynosdrm-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o
exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o
1.2 配置
Device Drivers --->
Graphics support --->
Direct Rendering Manager --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
[*] Exynos DRM FIMD
[*] EXYNOS DRM parallel output support
2、使用设备树描述LCD设备
2.1 FIMD的SoC配置
在arch/arm/boot/dts/exynos4.dtsi 已经帮咱们定义好了fimd的信息,这个fimd信息是属于SoC级别的定义,可以参考:linux-4.2.6\documentation\devicetree\bindings\video\samsung-fimd.txt
fimd: fimd@11c00000 {
compatible = "samsung,exynos4210-fimd";
interrupt-parent = <&combiner>;
reg = <0x11c00000 0x20000>;
interrupt-names = "fifo", "vsync", "lcd_sys";
interrupts = <11 0>, <11 1>, <11 2>;
clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
clock-names = "sclk_fimd", "fimd";
power-domains = <&pd_lcd0>;
iommus = <&sysmmu_fimd0>;
samsung,sysreg = <&sys_reg>;
status = "disabled";
};
2.2 FIMD的Board配置
&fimd {
pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
pinctrl-names = "default";
samsung,invert-vclk; //vclk翻转
status = "okay";
};
2.3 LCD时序配置
此配置可以参考:linux-4.2.6\documentation\devicetree\bindings\video\display-timing.txt
display-timings {
native-mode = <&timing0>;
timing0: timing {
pixelclk-active = <1>;
clock-frequency = <33000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <80>;
hback-porch = <36>;
hsync-len = <10>;
vback-porch = <15>;
vfront-porch = <1>;
vsync-len = <8>;
};
};
4、编译烧写,把dtb放入bootloader
启动信息如下:
[ 1.475756] [drm] Initialized drm 1.1.0 20060810
[ 1.481573] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops)
[ 1.486849] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 1.493444] [drm] No driver support for vblank timestamp query.
[ 1.499351] [drm] Initialized exynos 1.0.0 20110530 on minor 0
启动后,并没有/dev/fb0设备出现,那么就加打印咯,当然也可以使用KDB来调试,可以参考个人博客。不过KDB调试会导致CPU过热,最终程序不是跑飞就是不断重启,非常郁闷的。
经过加打印信息,终于找到原来问题时解析不了dts中的display_timings这个属性,原来在解析的过程中,代码是按照display_timings是从属于fimd的一个节点解析的,而不是display_timings就是root下的一个节点来解析。那么就好办了,直接把display_timings添加到fimd进去,如下:(文档和例子都是坑)
&fimd {
pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>;
pinctrl-names = "default";
samsung,invert-vclk;
status = "okay";
display-timings {
native-mode = <&timing0>;
timing0: timing {
pixelclk-active = <1>;
clock-frequency = <33000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <80>;
hback-porch = <36>;
hsync-len = <10>;
vback-porch = <15>;
vfront-porch = <1>;
vsync-len = <8>;
};
};
};
5 重新编译设备树
重新启动启动信息如下:
[ 1.469053] [drm] Initialized drm 1.1.0 20060810
[ 1.473455] drivers/gpu/drm/exynos/exynos_drm_fimd.c fimd_probe 999
[ 1.479165] lcd_clk = 1500000 添加的打印信息
[ 1.561894] exynos-drm exynos-drm: bound 11c00000.fimd (ops fimd_component_ops)
[ 1.569049] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 1.575641] [drm] No driver support for vblank timestamp query.
[ 1.591038] Console: switching to colour frame buffer device 114x34
[ 1.595286] exynos-drm exynos-drm: fb0: frame buffer device (看到这一句就表示创建出fb0了)
[ 1.595342] exynos-drm exynos-drm: registered panic notifier
[ 1.614515] [drm] Initialized exynos 1.0.0 20110530 on minor 0
.... //中间省略
Myroot /# cat /sys/class/graphics/fb0/virtual_size
800,480 //打印出来的信息对应hactive = <800>;vactive = <480>;也就是说设置成功了。
虽然能看到/dev/fb0了,但是屏幕背光不亮,没图像。而且在调试的过程中本人在代码里面添加了输出LCD时钟频率的大小。从上面启动信息看出来了,LCD的频率才1.5Mhz。看来还得慢慢的分析代码,调试咯。路漫漫代码挖坑给吾跳。
6. 升频和背光支持
6.1 升频
6.1.1 S70的频率
Tiny4412开发板接的LCD为群创的7寸屏,器芯片手册给了支持频率的范围,如下图
6.1.1 sclk_fimd0升频到800Mhz
想要升频,就必须去看Linux内核中与Clock相关的代码,不过也是可以通过常用的Clock提供的API去升频。
根据S70的时钟范围,至少也得升频到50Mhz,通过看exynos4412的芯片手册,可以知道sclk_fimd0可以从mpll时钟过来,也就是说可以设置为800Mhz。
自从Linx3.7内核提供完善CCF开始,现在的Clock使用的是CCF框架的,但是各种时钟还是使用表格的方式在填充的。那么就能在这些表格中找到SCLK_FIMD0的父时钟在进行设置即可,过程就不多说了,直接看代码。代码添加到linux4.2.6/drivers/clk/samsung/clk-exynos4.c文件:
static void __init exynos4_clk_init(struct device_node *np,enum exynos4_soc soc)
{
struct clk *mout_mpll_user_t = NULL;
struct clk *mount_fimd0 = NULL;
struct clk *sclk_fimd0 = NULL;
.....
/* Frequency up to 800Mhz */
/* code start... */
pr_info("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
mout_mpll_user_t = __clk_lookup("mout_mpll_user_t");
if (IS_ERR(mout_mpll_user_t)) {
pr_info("failed to get mout_mpll_user_t clock\n");
return;
}
pr_info("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
mount_fimd0 = __clk_lookup("mout_fimd0");
if (IS_ERR(mount_fimd0)) {
pr_info("failed to get mout_fimd0 clock\n");
return ;
}
pr_info("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
sclk_fimd0 = __clk_lookup("sclk_fimd0");
if (IS_ERR(sclk_fimd0)) {
pr_info("failed to get sclk_fimd0 clock\n");
return ;
}
clk_set_parent(mount_fimd0,mout_mpll_user_t);
ret = clk_set_rate(mount_fimd0,800000000);
if(ret){
pr_info("failed to clock set rate\n");
return ;
}
pr_info("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
ret = clk_set_rate(sclk_fimd0,800000000);
if(ret){
pr_info("failed to clock set rate\n");
return ;
}
pr_info("mout_mpll_user_t = %ld mount_fimd0 = %ld sclk_fimd0 = %ld\n",clk_get_rate(mout_mpll_user_t),clk_get_rate(mount_fimd0),clk_get_rate(sclk_fimd0));
/* code end... */
}
编译,重新启动,板子信息如下:
[ 1.605811] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[ 1.612402] [drm] No driver support for vblank timestamp query.
[ 1.622973] lcd_clk = 800000000 //成功升频到800Mhz
[ 1.627903] Console: switching to colour frame buffer device 114x34
[ 1.659366] exynos-drm exynos-drm: fb0: frame buffer device
[ 1.665007] exynos-drm exynos-drm: registered panic notifier
[ 1.684532] [drm] Initialized exynos 1.0.0 20110530 on minor 0
6.2 背光
VLED+和VLED-就是LCD的背光,但是这两个脚由BL_EN和LEDDM控制,挺简单的不就看下RT9293B芯片如何控制就好了。但是Tiny4412开发板就不这样,看下BL_EN接到哪里去?
一看真™的恶心,想要背光亮还得去控制STC这个芯片,怎么控制?通过EINT10去控制,EIN10是exynos4412的外部中断10(GPX1_2)。更重要的是使用了一根线来发送数据,就像单总线的18B20温度传感器一样,那么这个时序也可以去看代码,分析然后在自己编写,但是本人完全不想去了解这种自定义的单总线的时序,所以直接移植,懒得看了。(真™的恶心)。
那么参考厂家给的Linux3.5的内核中的tiny4412_1wire_host.,将其移植Linx4.2.6内核中了,当然肯定是以支持设备树的方式来移植的。直接看代码(F:\share\devtree_drv\3th_backlight\1th\backlight_drv.c)
好了,背光和升频都整好了。
7. 把背光驱动安装到内核,启动内核
成功启动内核,并且可以看到四只可爱的小企鹅,不过小企鹅身上有一个一个的小黑点,刷上一张图片看更明显。这是因为,LCD取数据的边沿弄错了,很简单,翻转下LCD的时钟就行了。
完美的dts配置如下:
&fimd {
pinctrl-0 = <&lcd_clk &lcd_data24>;
pinctrl-names = "default";
status = "okay";
samsung,invert-vclk; //翻转
display-timings {
native-mode = <&timing0>;
timing0: timing {
hsync-active = <1>; //行同步信号开始位高
vsync-active = <1>;
de-active = <0>;
clock-frequency = <33000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <80>;
hback-porch = <36>;
hsync-len = <10>;
vback-porch = <15>;
vfront-porch = <1>;
vsync-len = <8>;
};
};
};
离线
去www.kernel.org下载一份就好了
离线