您尚未登录。

楼主 #1 2018-07-08 18:49:14

Morgan
会员
注册时间: 2018-07-03
已发帖子: 28
积分: 23

tiny4412 lcd驱动移植

前言
在移植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寸屏,器芯片手册给了支持频率的范围,如下图
    FluxBB
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 背光
FluxBB
VLED+和VLED-就是LCD的背光,但是这两个脚由BL_EN和LEDDM控制,挺简单的不就看下RT9293B芯片如何控制就好了。但是Tiny4412开发板就不这样,看下BL_EN接到哪里去?
FluxBB

一看真™的恶心,想要背光亮还得去控制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>;
		};
	};
};

离线

楼主 #4 2018-08-14 15:49:40

Morgan
会员
注册时间: 2018-07-03
已发帖子: 28
积分: 23

Re: tiny4412 lcd驱动移植

去www.kernel.org下载一份就好了

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn