目录
0. 前言
2. 编译报错与打补丁
3. 设备树与display-timings
4. 拓展:RGB24
0. 前言
这次的工作主要是把某项目设备上(iMX6DL)的内核版本从 4.19.x 升级到 5.15.32,是作为该项目整个BSP升级计划的一部分。
该内核升级工作移交给笔者的时候,其实 5.15.32版本的内核已经初步移植好了,可以在设备上跑起来。只是显卡、声卡和网卡还未使能和配置,这便是笔者需要做的事情。
值得一提的是,笔者手上有 4.19.x 版本的内核 configs 和 zImage,可以作为开发时的参考。
1. menuconfig
一般而言,配置内核驱动,首先需要在menuconfig的图形界面里,把该选的配置、该设置的参数和该关闭的选项都给设置好。笔者大量参考了4.19.x的menuconfig设置。
首先我们查询手册和原理图,知道了显示器型号为 LG的LB070WV8SL02。
我们在 linux-menuconfig 里面如下设置:进入 Device Drivers ---> Graphics support
取消 < > IPUv3 Core support
进入 Display Panels:
进入 Display Interface Bridges:
进入 Frame buffer Devices:
进入 Backlight & LCD device support:
进入 Console display driver support:
我们再在 linux-menuconfig 里面如下设置:进入 Device Drivers ---> MXC support drivers
PS: 这里MXC的设置是笔者反反复复最多的,因为它跟后面编译报错的原因直接相关。
如此这般配置,感觉上跟 4.19.x 的配置几乎一样或者说没有冲突。那么,退出menuconfig,直接编译内核,果不其然,一开始就报错了。
2. 编译报错与打补丁
现如今,linux内核的源代码已经极其庞大了,以至于完全可能发生两个不同时期由不同组织提交的不相关的源文件里存在重名函数的情况!如果把这些源文件都选中加入编译的话,那可不就发生报错了嘛。
笔者一开始发生的编译报错就是显示 multiple definitions。不过一开始,最好不要直接修改源代码,毕竟这样的修改牵一发而动全身(万一以后其他人要用这个函数呢)。
比如说 文件A 和 文件B 现在都有名字为 ipu_csi_init_interface(...)的函数(尽管它们内容完全不同),笔者想让 文件B妥协, 把文件B 排除于编译外。为了这个目的,又在menuconfig里面选了好久。。。但最后得出结论,如果通过menuconfig关闭一些选项来去除文件B,产生了连锁效应(很多其他文件也被排除了),反而会有更多的编译报错。
写文件A的公司 和 写文件B的公司 确实会把自己的文件好好测试,但的确不一定会考虑到跟世界上其他公司提交的文件产生冲突的情况。所以笔者在咨询了老法师同事的意见后,不得不采取了修改文件B的做法。把函数名改成了 imx_ipu_csi_init_interface(...),其他重名函数也就是加上了imx_前缀而已。
如此这般修改,再编译内核。确实就没有报错了。笔者就此写了专门的patch补丁文件,将这些把函数名修改的操作可以动态的执行于编译过程之中。
3. 设备树与display-timings
现在编译不报错了,把生成的zImage放到SD卡上,在设备上跑一下。看看打印输出和显示效果。
我们关注这几个关键字:fb、ldb、display-panel 和 /dev/fb0 ( frame buffer 显示设备的驱动名 ),看看打印输出里面有没有相关的信息。也可以结合4.19.x的打印输出一起看看。
结果,打印输出没有问题,但默认开机显示的 那两个Linux小企鹅是绿色的!也就是显示失真了。
那么我们需要研究一下设备树了。
dts文件里,跟显卡相关的地方如下:(截图是已经修改好的情况,原来很多内容是没有的)
这其中 display-timings原来是没有的,但它却是调整显示屏时序的关键。
我们可以打开内核里面的panel-timing.yaml,里面有一些提示:
我们可以得到 hactive 和 vactive 的含义:
通过查询器件手册,我们可知这块屏幕是800X480,主频是33.246MHz,所以 hactive=800,vactive=480,clock-frequency=33246000。
但其他参数,如 hback-porch、hfront-porch、vback-porch、vfront-porch、hsync-len和vsync-len,器件手册里没有直接提示。
通过查询网络上相关资料和讨论,LVDS时序配置有这么一个公式:
水平总周期 = hback-porch + hfront-porch + hsync-len + hactive
垂直总周期 = vback-porch + vfront-porch + vsync-len + vactive
我们再看一下手册:
所以可以推算:
1056 = hback-porch + hfront-porch + hsync-len + 800
hback-porch + hfront-porch + hsync-len = 256;
525 = vback-porch + vfront-porch + vsync-len + 480
vback-porch + vfront-porch + vsync-len = 45;
而且只要确保 水平和垂直参数总和是 256与45就行,具体每一项大小可以自定。所以我们最终可以得到:
display-timings {
native-mode = <&timing0>;
timing0: hsd100pxn1 {
clock-frequency = <33246000>;
hactive = <800>;
vactive = <480>;
hback-porch = <88>;
hfront-porch = <88>;
hsync-len = <80>;
vback-porch = <10>;
vfront-porch = <10>;
vsync-len = <25>;
};
};
这样一设置,再编译出zImage,放到板子上一跑,小企鹅颜色就正常了。
4. 拓展:RGB24
设备树里有这么一个参数,interface_pix_fmt
interface_pix_fmt 指LCD HW 输出信号格式。如RGB565,RGB888(即RGB24),GRB888,BGR888,RGB666等。顾名思义,interface_pix_fmt 就是一个LCD 接口输出一个像素的格式。
一个18bit的LCD有可能输出RGB666, BGR666,GBR666.一个24bit的LCD有可能输出RGB24, BGR24,GBR24.
查询器件手册,可知这块屏幕的输出信号格式为24bit。所以笔者选择了RGB24这种最常见的格式。选择BGR24、GBR24会出现三种原色位置对调的情况。
在有些场合,比如屏幕数据线接错,新屏幕接口顺序变动等情况下,可以改变这个interface_pix_fmt 参数。让显示效果最终还是正确的。以软件的设置减少硬件变动的工作量。