兼容方案
定做LCD fpc
1 | 该方案是硬件设计时预留几个gpio,不同厂家的屏对不同的gpio进行上拉或者下拉,将上下拉电阻直接贴到fpc上, |
软件读取IC的 ID
1 | 该方案是在系统启动时读取 LCD IC的寄存器,不同的IC其内容不同,以此达到区分的目的。 |
使用gpio
1 | 该方案对软件来说与方案1相同,不同点在于该方案是将上下拉电阻贴到PCB板上。 |
增加特定分区
1 | 该方案是在原有的emmc或ufs分区的基础上增加一个oem分区,在生产时针对不同的屏烧录对应的oem.img文件即可。 |
Parameter.txt(rk平台特有)
1 | 该方案效果与方案4相同,都是修改commandline,区别在于方案4是读取oem分区的内容后再修改,该方案时直接修改原始commandline。 |
根据项目实际情况采用方案5, 以下介绍兼容过程中涉及的修改。
本文介绍双屏兼容方案(lvds+edp)
涉及到的文件修改如下:
1 | device/rockchip/rk3288/{parameter_gl.txt => parameter_primary-dl_sub-dl.txt} | 2 +- |
Device tree修改
device tree中lvds 和 edp部分保留公共部分,将timging相关部分提取到单独的dts中。如:
1 | &edp_panel { |
其中 _edpdl 为识别关键字,在不同部分添加对应的关键字以区分不同的屏。
uboot 代码修改
在进行LCD初始化前,读取parameter.txt中commandline的LCD信息,保存在global date结构中。使用方案5时commandline中已经包含了LCD信息,因此uboot中无需修改。
- u-boot/include/asm-generic/global_data.h
globaldata中点击lcd数组,用于存放parameter解析后得到的关键字,如device tree中 _edpdl
1 | index 8c91ab913e..fcc6e03818 100644 |
u-boot/board/rockchip/common/rkloader/parameter.c
添加对parameter中关键字的解析,这个实现方式以 “_” 作为分隔符,以最后一个_为基准往后的字符作为识别关键词,如rk_primary_display_edpdl,最终得到的是 _edpdl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21static int lcd_detect()
{
char cmdline[1024*64] = {0};
char *panel_name = NULL;
char *ptr1 = NULL, *ptr2 = NULL, *safe = NULL, *tmp = NULL;
strncpy(cmdline, gBootInfo.cmd_line, strlen(gBootInfo.cmd_line));
panel_name = strstr(cmdline, RK_PRIMARY_DISPLAY);
ptr1 = strtok(panel_name, " ");
ptr2 = strtok(ptr1, "_");
while (ptr2 != NULL) {
tmp = ptr2;
ptr2 = strtok(NULL, "_");
}
strncpy(gd->lcd_module, "_", 1);
strncat(gd->lcd_module, tmp, strlen(tmp));
return 0;
}u-boot/drivers/video/rockchip_display.c
在driver获取dts的位置添加解析到的后缀。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19diff --git a/u-boot/drivers/video/rockchip_display.c b/u-boot/drivers/video/rockchip_display.c
index f477b20c23..bfbef19fad 100644
--- a/u-boot/drivers/video/rockchip_display.c
+++ b/u-boot/drivers/video/rockchip_display.c
@@ -363,8 +363,14 @@ static int display_get_timing_from_dts(int panel, const void *blob,
│ int hfront_porch, hback_porch, hsync_len;
│ int vfront_porch, vback_porch, vsync_len;
│ int val, flags = 0;
+│ char node_name[128];
-
-│ timing = fdt_subnode_offset(blob, panel, "display-timings");
+│ memset(node_name, 0, sizeof(node_name));
+│ strncpy(node_name, "display-timings", strlen("display-timings"));
+│ strncat(node_name, gd->lcd_module, strlen(gd->lcd_module));
+│ printf("[lcd_detect_timings] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);
+
+│ timing = fdt_subnode_offset(blob, panel, node_name);
│ if (timing < 0)
│ │ return -ENODEV;u-boot/include/lcd.h
添加对应的主副屏关键词定义
1
2
3
4
5
6
7
8
9
10
11
12--- a/u-boot/include/lcd.h
+++ b/u-boot/include/lcd.h
@@ -13,6 +13,9 @@
#ifndef _LCD_H_
#define _LCD_H_
-
+#define RK_PRIMARY_DISPLAY │ │ "rk_primary_display"
+#define RK_SUB_DISPLAY││ │ "rk_sub_display"
+
extern char lcd_is_enabled;
-
extern int lcd_line_length;
kernel 代码修改
kernel/include/linux/lcd_compatible.h
同uboot,添加对应的主副屏关键词定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18diff --git a/kernel/include/linux/lcd_compatible.h b/kernel/include/linux/lcd_compatible.h
new file mode 100644
index 0000000000..13550016ec
--- /dev/null
+++ b/kernel/include/linux/lcd_compatible.h
@@ -0,0 +1,12 @@
+#ifndef _LCD_COMPATIBLE_H
+#define _LCD_COMPATIBLE_H
+
+#define STRING_LEN │ │ 32
+
+#define RK_PRIMARY_DISPLAY│ │ "rk_primary_display"
+#define RK_SUB_DISPLAY││ │ "rk_sub_display"
+#define RK_PRIMARY_PANEL_NAME│ │ "edp-panel"
+#define RK_SUB_PANEL_NAME│ │ "lvds-panel"
+extern char primary_lcd_module[STRING_LEN];
+extern char sub_lcd_module[STRING_LEN];
+#endif /* _LCD_COMPATIBLE_H */kernel/drivers/video/of_display_timing.c
同uboot,完整patch见文章末尾
kernel/drivers/gpu/drm/panel/panel-simple.c
由于edp lvds使用的都是panel-simple驱动,因此需要在代码中区分是edp还是lvds
1 | -static int panel_simple_get_cmds(struct panel_simple *panel) |
完整patch
1 | diff --git a/device/rockchip/rk3288/parameter_gl.txt b/device/rockchip/rk3288/parameter_primary-dl_sub-dl.txt |