一款特殊的LCD屏幕驱动调试

Posted Linux学习之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一款特殊的LCD屏幕驱动调试相关的知识,希望对你有一定的参考价值。

问题分析

这款LCD屏幕的有效显示区域为 480 * 1280, 但是它的timing时序却是600 * 1280。
时序要求600 * 1280意味着主控需要通过物理接口输出600 * 1280的图像,然而LCD的背板芯片会剪裁掉左右两侧各60像素,得到480 * 1280的显示区域。

那么我们的LCD屏幕参数该如何配置?Framebuffer的参数该如何配置?

  1. Framebuffer 配置成 600 * 1280,请应用层同学自行解决,画UI的时候画600*1280的。
  2. Framebuffer 配置成 480 * 1280,在kernel中将这480 * 1280的图像变换到 600 * 1280 输出给LCD。

方案二的好处不言而喻,可以节约内存,可以减少cpu的开销

全志平台实现方案

那么如何实现这个功能呢。下面简单介绍一下在全志平台的处理方案。

全志平台的显示框架大致如下:
layer -> chanel -> disp engine -> interface -> panel

全志平台一般会有一到两个图形引擎简称DE,然后每个DE会包含多个通道,每个通道会有多个图层,显示时应用层比如我们通过fb绘图, fb 其实就对应多个图层中的其中一个,同时全志也提供了接口可以通过/dev/disp节点直接操作图层,应用层绘制完图层之后,DE会根据图层的属性对图层进行叠加混合处理,最终结果在通过 mipi lvds 等 interface 输出给 panel 进行显示。

具体一点,我们通过几个win的概念来理解Framebuffer中的数据是如何流转最终输出给LCD的

  • fb_win:假设framebuffer(其中一个layer)的大小为 480 * 1280, 我们称这个buffer所在的区域为 fb_win。
  • output_win:假设lcd的Timing为 600 * 1280, 我们称这个600 * 1280 对应的区域为 output_win,不管如何主控端最终输出的图像大小一定是和output_win等大的。
  • src_win:layer支持crop,我们可以在fb_win中进行crop,假设crop的参数为x=100,y=100,w=200,y=200,我们称剪裁后的win叫做src_win,为什么它叫做src_win呢,因为它对于DE来说是数据的源头。
  • screen_win:screen_win指的是src_win在output_win中的显示参数,包括坐标和宽高,坐标不难理解,screen_win的宽高如果与scr_win的宽高不相等,DE将对scr_win中的数据进行缩放。

我们的framebuffer对应的layer不会使用到crop操作,正常的LCD时序和有效显示区域的大小一致,因此fb_win和output_win的大小也是一样的。

对于这款时序和有效显示区域不一致的特殊LCD我们这样处理:

  • output_win 在代码中对应 fb_para->output_width 和 fb_para->output_height,它是从设备树中的lcd timing参数获得的,我们设置为 600 * 1280。
  • fb_win 对应设备树中的 fb0_width fb0_height,我们设置为 480 * 1280,应用层看到的fb大小与lcd有效显示区域一致。
  • scr_win 我们不需要剪裁crop的参数与fb_win的大小一致。
  • screen_win 我们需要将scr_win中的图像居中显示到output_win中,因此需要设置screen_win的坐标参数为(60, 0 )。

这个居中的操作需要在内核全志fb初始化的代码中处理,具体操作如下:

--- a/drivers/video/fbdev/sunxi/disp2/disp/dev_fb.c
+++ b/drivers/video/fbdev/sunxi/disp2/disp/dev_fb.c
@@ -2270,14 +2270,8 @@ static s32 display_fb_request(u32 fb_id, struct disp_fb_create_info *fb_para)
                         else
 #endif
                        
-                               config.info.screen_win.width =
-                                       (0 ==
-                                        fb_para->output_width) ? src_width : fb_para->
-                                       output_width;
-                               config.info.screen_win.height =
-                                       (0 ==
-                                        fb_para->output_height) ? src_width : fb_para->
-                                       output_height;
+                               config.info.screen_win.width = src_width;
+                               config.info.screen_win.height = src_height;
                        

                        config.info.mode = LAYER_MODE_BUFFER;
@@ -2290,7 +2284,7 @@ static s32 display_fb_request(u32 fb_id, struct disp_fb_create_info *fb_para)
                            ((long long)src_width) << 32;
                        config.info.fb.crop.height =
                            ((long long)src_height) << 32;
-                       config.info.screen_win.x = 0;
+                       config.info.screen_win.x = (fb_para->output_width - src_width) / 2;
                        config.info.screen_win.y = 0;
                        var_to_disp_fb(&(config.info.fb), &(info->var),
                                       &(info->fix));

以上是关于一款特殊的LCD屏幕驱动调试的主要内容,如果未能解决你的问题,请参考以下文章

一款特殊的LCD屏幕驱动调试

Linux MIPI DSI驱动调试笔记-LCD时序参数配置

Tina Linux LCD调试指南

lcd驱动屏幕旋转

Linux MIPI DSI驱动调试笔记-LCD时序参数配置

LCD屏幕的驱动