[Android7.1][rk3288/rk3399]lcd兼容方案

兼容方案

定做LCD fpc

1
2
3
4
5
6
该方案是硬件设计时预留几个gpio,不同厂家的屏对不同的gpio进行上拉或者下拉,将上下拉电阻直接贴到fpc上,
系统启动时读取gpio电平进行判断。
优点:
硬件更改版号时不需要考虑屏的区别,软件无需单独出版本,生产时也没有烧录错误的风险,该方案对我们来说是最简单的。
缺点:
需要模组厂配合。

软件读取IC的 ID

1
2
3
4
5
该方案是在系统启动时读取 LCD IC的寄存器,不同的IC其内容不同,以此达到区分的目的。
优点:
该方案不需要模组厂配合,硬件也无需考虑屏的区别,在明确LCD IC的情况下,可以考虑使用。
缺点:
如果不同模组厂使用的是相同的IC该方案便不可行。

使用gpio

1
2
3
4
5
该方案对软件来说与方案1相同,不同点在于该方案是将上下拉电阻贴到PCB板上。
优点:
不依赖模组厂。
缺点:
针对不同的屏在贴片时需要做区分,如果后期改换其他屏,需要修改电阻,该方案只能做到软件兼容,硬件无法兼容。

增加特定分区

1
2
3
4
5
6
该方案是在原有的emmc或ufs分区的基础上增加一个oem分区,在生产时针对不同的屏烧录对应的oem.img文件即可。
优点:
该方案可以做到软硬件同时兼容,如果后期需要更换,只需要重新烧录对应的oem.img文件即可,同时一些特有的信息也可以添加到该分区,
软件升级时无需对该分区进行操作。
缺点:
生产时需要区分不同的屏,不能出现烧录错误的情况,否则会出现显示异常。

Parameter.txt(rk平台特有)

1
2
该方案效果与方案4相同,都是修改commandline,区别在于方案4是读取oem分区的内容后再修改,该方案时直接修改原始commandline。
优缺点与方案4相同。

根据项目实际情况采用方案5, 以下介绍兼容过程中涉及的修改。

本文介绍双屏兼容方案(lvds+edp)

涉及到的文件修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
device/rockchip/rk3288/{parameter_gl.txt => parameter_primary-dl_sub-dl.txt} |  2 +-
kernel/arch/arm/boot/dts/rk3288-xxx-perform.dts | 45 ++-------------------------------------------
kernel/drivers/gpu/drm/panel/panel-simple.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
kernel/drivers/video/of_display_timing.c | 18 +++++++++++++++++-
kernel/include/dt-bindings/display/screen-timing/lcd-edp-dl.dtsi | 21 +++++++++++++++++++++
kernel/include/dt-bindings/display/screen-timing/lcd-lvds-dl.dtsi | 21 +++++++++++++++++++++
kernel/include/linux/lcd_compatible.h | 12 ++++++++++++
u-boot/board/rockchip/common/rkloader/parameter.c | 25 +++++++++++++++++++++++++
u-boot/drivers/video/rockchip_display.c | 8 +++++++-
u-boot/include/asm-generic/global_data.h | 1 +
u-boot/include/lcd.h | 3 +++
11 files changed, 204 insertions(+), 51 deletions(-)

Device tree修改

device tree中lvds 和 edp部分保留公共部分,将timging相关部分提取到单独的dts中。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&edp_panel {

│ display-timings_edpdl {
│ │ native-mode = <&timing_edpdl>;
│ │ timing_edpdl: timing_edpdl {
│ │ │ clock-frequency = <128000000>;
│ │ │ hactive = <1920>;
│ │ │ vactive = <1080>;
│ │ │ hfront-porch = <15>;
│ │ │ hback-porch = <15>;
│ │ │ vfront-porch = <15>;
│ │ │ vback-porch = <15>;
│ │ │ hsync-len = <7>;
│ │ │ vsync-len = <5>;
│ │ │ hsync-active = <0>;
│ │ │ vsync-active = <0>;
│ │ │ de-active = <0>;
│ │ │ pixelclk-active = <0>;
│ │ };
│ };
};

其中 _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
2
3
4
5
6
7
8
9
index 8c91ab913e..fcc6e03818 100644
--- a/u-boot/include/asm-generic/global_data.h
+++ b/u-boot/include/asm-generic/global_data.h
@@ -46,6 +46,7 @@ typedef struct global_data {
│ unsigned long mem_clk;
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) || defined(CONFIG_ROCKCHIP_DISPLAY)
│ unsigned long fb_base;│ /* Base address of framebuffer mem */
+│ char lcd_module[32];
#endif
  • 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
    21
    static 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
    19
    diff --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
    18
    diff --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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
-static int panel_simple_get_cmds(struct panel_simple *panel)
+static int panel_simple_get_cmds(struct panel_simple *panel, const char *name)
{
│ const void *data;
│ int len;
│ int err;
+│ char node_name[STRING_LEN];
+│ char lcd_module[STRING_LEN];
+
+│ memset(lcd_module, 0, sizeof(lcd_module));
+
+│ if (0 == strncmp(RK_PRIMARY_PANEL_NAME, name, strlen(name))) {
+│ │ strncpy(lcd_module, primary_lcd_module, strlen(primary_lcd_module));
+
+│ } else if (0 == strncmp(RK_SUB_PANEL_NAME, name, strlen(name))) {
+│ │ strncpy(lcd_module, sub_lcd_module, strlen(sub_lcd_module));
+│ }
-
-│ data = of_get_property(panel->dev->of_node, "panel-init-sequence",
+│ memset(node_name, 0, sizeof(node_name));
+│ strncpy(node_name, "panel-init-sequence", strlen("panel-init-sequence"));
+│ strncat(node_name, lcd_module, strlen(lcd_module));
+│ printk("[lcd_detect_panel-init-sequence] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);
+
+│ data = of_get_property(panel->dev->of_node, node_name,
│ │ │ &len);
│ if (data) {
│ │ panel->on_cmds = devm_kzalloc(panel->dev,
@@ -469,10 +539,27 @@ static int panel_simple_of_get_native_mode(struct panel_simple *panel)
│ struct drm_device *drm = panel->base.drm;
│ struct drm_display_mode *mode;
│ struct device_node *timings_np;
+│ char *name = panel->dev->of_node->name;
│ int ret;
+│ char node_name[STRING_LEN];
+│ char lcd_module[STRING_LEN];
+
+│ memset(lcd_module, 0, sizeof(lcd_module));
+
+│ if (0 == strncmp(RK_PRIMARY_PANEL_NAME, name, strlen(name))) {
+│ │ strncpy(lcd_module, primary_lcd_module, strlen(primary_lcd_module));
+
+│ } else if (0 == strncmp(RK_SUB_PANEL_NAME, name, strlen(name))) {
+│ │ strncpy(lcd_module, sub_lcd_module, strlen(sub_lcd_module));
+│ }
+
+│ memset(node_name, 0, sizeof(node_name));
+│ strncpy(node_name, "display-timings", strlen("display-timings"));
+│ strncat(node_name, lcd_module, strlen(lcd_module));
+│ printk("[lcd_detect_display-timings] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);
-
│ timings_np = of_get_child_by_name(panel->dev->of_node,
-│ │ │ │ │ "display-timings");
+│ │ │ │ │ node_name);
│ if (!timings_np) {
│ │ dev_dbg(panel->dev, "failed to find display-timings node\n");
│ │ return 0;

完整patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
diff --git a/device/rockchip/rk3288/parameter_gl.txt b/device/rockchip/rk3288/parameter_primary-dl_sub-dl.txt
old mode 100755
new mode 100644
similarity index 91%
rename from device/rockchip/rk3288/parameter_gl.txt
rename to device/rockchip/rk3288/parameter_primary-dl_sub-dl.txt
index 20ddaabe99..ab2be98ace
--- a/device/rockchip/rk3288/parameter_gl.txt
+++ b/device/rockchip/rk3288/parameter_primary-dl_sub-dl.txt
@@ -7,4 +7,4 @@ ATAG: 0x60000800
MACHINE: 3288
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
-CMDLINE: console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init initrd=0x62000000,0x00800000 mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(misc),0x00008000@0x00008000(resource),0x0000C000@0x00010000(kernel),0x00010000@0x0001C000(boot),0x00010000@0x0002C000(recovery),0x00038000@0x0003C000(backup),0x00040000@0x00074000(cache),0x00400000@0x000B4000(system),0x00008000@0x004B4000(metadata),0x00019000@0x004BC000(vendor0),0x00019000@0x004D5000(vendor1),0x00096000@0x004EE000(oem),0x00002000@0x00584000(logo),-@0x00586000(userdata) rk_display_edp_gl
+CMDLINE: console=ttyFIQ0 androidboot.baseband=N/A androidboot.selinux=permissive androidboot.hardware=rk30board androidboot.console=ttyFIQ0 init=/init initrd=0x62000000,0x00800000 mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(trust),0x00002000@0x00006000(misc),0x00008000@0x00008000(resource),0x0000C000@0x00010000(kernel),0x00010000@0x0001C000(boot),0x00010000@0x0002C000(recovery),0x00038000@0x0003C000(backup),0x00040000@0x00074000(cache),0x00400000@0x000B4000(system),0x00008000@0x004B4000(metadata),0x00019000@0x004BC000(vendor0),0x00019000@0x004D5000(vendor1),0x00096000@0x004EE000(oem),0x00002000@0x00584000(logo),-@0x00586000(userdata) rk_primary_display_edpdl rk_sub_display_lvdsdl
diff --git a/kernel/arch/arm/boot/dts/rk3288-xxx-perform.dts b/kernel/arch/arm/boot/dts/rk3288-xxx-perform.dts
index 7195a1ef82..d4d99da6c2 100644
--- a/kernel/arch/arm/boot/dts/rk3288-xxx-perform.dts
+++ b/kernel/arch/arm/boot/dts/rk3288-xxx-perform.dts
@@ -41,6 +41,8 @@
/dts-v1/;
#include "rk3288-xxx.dtsi"
#include "rk3288-xxx-android.dtsi"
+#include <dt-bindings/display/screen-timing/lcd-edp-dl.dtsi>
+#include <dt-bindings/display/screen-timing/lcd-lvds-dl.dtsi>

/ {
compatible = "rockchip,rk3288-xxx-perform", "rockchip,rk3288";
@@ -181,29 +183,8 @@
backlight = <&backlight>;
power-supply = <&vcc_lcd>;
status = "okay";
-
- disp_timings: display-timings {
- native-mode = <&timing0>;
-
- timing0: timing0 {
- clock-frequency = <128000000>;
- hactive = <1920>;
- vactive = <1080>;
- hfront-porch = <15>;
- hback-porch = <15>;
- vfront-porch = <15>;
- vback-porch = <15>;
- hsync-len = <7>;
- vsync-len = <5>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <0>;
- pixelclk-active = <0>;
- };
- };
};

-
&lvds_panel {
status = "okay";
compatible ="simple-panel";
@@ -215,28 +196,6 @@
rockchip,data-mapping = "vesa";
rockchip,data-width = <24>;
rockchip,output = "lvds";
-
- display-timings {
- native-mode = <&lvds_timing>;
-
- lvds_timing: lvds_timing {
-
- clock-frequency = <138000000>;
- hactive = <1920>;
- vactive = <1080>;
- hback-porch = <148>;
- hfront-porch = <88>;
- vback-porch = <36>;
- vfront-porch = <4>;
- hsync-len = <44>;
- vsync-len = <5>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <0>;
- pixelclk-active = <0>;
-
- };
- };
};

&i2c0 {
diff --git a/kernel/drivers/gpu/drm/panel/panel-simple.c b/kernel/drivers/gpu/drm/panel/panel-simple.c
index 087ded7b43..6251ab06e2 100644
--- a/kernel/drivers/gpu/drm/panel/panel-simple.c
+++ b/kernel/drivers/gpu/drm/panel/panel-simple.c
@@ -39,8 +39,10 @@
#include <video/of_display_timing.h>
#include <linux/of_graph.h>
#include <video/videomode.h>
+#include <linux/lcd_compatible.h>

-#include <linux/of_gpio.h>
+char primary_lcd_module[STRING_LEN];
+char sub_lcd_module[STRING_LEN];

struct cmd_ctrl_hdr {
u8 dtype; /* data type */
@@ -139,6 +141,58 @@ enum MCU_IOCTL {
MCU_SETBYPASS,
};

+int primary_lcd_detect(void)
+{
+ char *panel_name = NULL, *cmdline;
+ char *ptr1 = NULL, *ptr2 = NULL, *tmp = NULL;
+
+ cmdline = (char *)kzalloc(4096 + 1, GFP_KERNEL);
+ strncpy(cmdline, saved_command_line, strlen(saved_command_line));
+ panel_name = strstr(cmdline, RK_PRIMARY_DISPLAY);
+ ptr1 = strsep(&panel_name, " ");
+ ptr2 = strsep(&ptr1, "_");
+ while (ptr2 != NULL) {
+ tmp = ptr2;
+ ptr2 = strsep(&ptr1, "_");
+ }
+ memset(primary_lcd_module, 0, sizeof(primary_lcd_module));
+ strncpy(primary_lcd_module, "_", 1);
+ strncat(primary_lcd_module, tmp, strlen(tmp));
+
+ kfree(cmdline);
+ return 0;
+}
+
+int sub_lcd_detect(void)
+{
+ char *panel_name = NULL, *cmdline;
+ char *ptr1 = NULL, *ptr2 = NULL, *tmp = NULL;
+
+ cmdline = (char *)kzalloc(4096 + 1, GFP_KERNEL);
+ strncpy(cmdline, saved_command_line, strlen(saved_command_line));
+ panel_name = strstr(cmdline, RK_SUB_DISPLAY);
+ ptr1 = strsep(&panel_name, " ");
+ ptr2 = strsep(&ptr1, "_");
+ while (ptr2 != NULL) {
+ tmp = ptr2;
+ ptr2 = strsep(&ptr1, "_");
+ }
+ memset(sub_lcd_module, 0, sizeof(sub_lcd_module));
+ strncpy(sub_lcd_module, "_", 1);
+ strncat(sub_lcd_module, tmp, strlen(tmp));
+
+ kfree(cmdline);
+ return 0;
+}
+
+int lcd_detect(void)
+{
+ primary_lcd_detect();
+ sub_lcd_detect();
+
+ return 0;
+}
+
static inline int get_panel_cmd_type(const char *s)
{
if (!s)
@@ -366,13 +420,29 @@ static inline int panel_simple_dsi_send_cmds(struct panel_simple *panel,
}
#endif

-static int panel_simple_get_cmds(struct panel_simple *panel)
+static int panel_simple_get_cmds(struct panel_simple *panel, const char *name)
{
const void *data;
int len;
int err;
+ char node_name[STRING_LEN];
+ char lcd_module[STRING_LEN];
+
+ memset(lcd_module, 0, sizeof(lcd_module));
+
+ if (0 == strncmp(RK_PRIMARY_PANEL_NAME, name, strlen(name))) {
+ strncpy(lcd_module, primary_lcd_module, strlen(primary_lcd_module));
+
+ } else if (0 == strncmp(RK_SUB_PANEL_NAME, name, strlen(name))) {
+ strncpy(lcd_module, sub_lcd_module, strlen(sub_lcd_module));
+ }

- data = of_get_property(panel->dev->of_node, "panel-init-sequence",
+ memset(node_name, 0, sizeof(node_name));
+ strncpy(node_name, "panel-init-sequence", strlen("panel-init-sequence"));
+ strncat(node_name, lcd_module, strlen(lcd_module));
+ printk("[lcd_detect_panel-init-sequence] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);
+
+ data = of_get_property(panel->dev->of_node, node_name,
&len);
if (data) {
panel->on_cmds = devm_kzalloc(panel->dev,
@@ -469,10 +539,27 @@ static int panel_simple_of_get_native_mode(struct panel_simple *panel)
struct drm_device *drm = panel->base.drm;
struct drm_display_mode *mode;
struct device_node *timings_np;
+ char *name = panel->dev->of_node->name;
int ret;
+ char node_name[STRING_LEN];
+ char lcd_module[STRING_LEN];
+
+ memset(lcd_module, 0, sizeof(lcd_module));
+
+ if (0 == strncmp(RK_PRIMARY_PANEL_NAME, name, strlen(name))) {
+ strncpy(lcd_module, primary_lcd_module, strlen(primary_lcd_module));
+
+ } else if (0 == strncmp(RK_SUB_PANEL_NAME, name, strlen(name))) {
+ strncpy(lcd_module, sub_lcd_module, strlen(sub_lcd_module));
+ }
+
+ memset(node_name, 0, sizeof(node_name));
+ strncpy(node_name, "display-timings", strlen("display-timings"));
+ strncat(node_name, lcd_module, strlen(lcd_module));
+ printk("[lcd_detect_display-timings] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);

timings_np = of_get_child_by_name(panel->dev->of_node,
- "display-timings");
+ node_name);
if (!timings_np) {
dev_dbg(panel->dev, "failed to find display-timings node\n");
return 0;
@@ -755,6 +842,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
if (!panel)
return -ENOMEM;

+ lcd_detect();
+
if (!desc)
of_desc = devm_kzalloc(dev, sizeof(*of_desc), GFP_KERNEL);
else
@@ -786,7 +875,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
panel->desc = of_desc;
panel->dev = dev;

- err = panel_simple_get_cmds(panel);
+ err = panel_simple_get_cmds(panel, dev->of_node->name);
if (err) {
dev_err(dev, "failed to get init cmd: %d\n", err);
return err;
diff --git a/kernel/drivers/video/of_display_timing.c b/kernel/drivers/video/of_display_timing.c
index b253875e99..4f90777d43 100644
--- a/kernel/drivers/video/of_display_timing.c
+++ b/kernel/drivers/video/of_display_timing.c
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <video/display_timing.h>
#include <video/of_display_timing.h>
+#include <linux/lcd_compatible.h>

/**
* parse_timing_property - parse timing_entry from device_node
@@ -193,11 +194,26 @@ struct display_timings *of_get_display_timings(struct device_node *np)
struct device_node *entry;
struct device_node *native_mode;
struct display_timings *disp;
+ char node_name[STRING_LEN];
+ char lcd_module[STRING_LEN];
+
+ memset(lcd_module, 0, sizeof(lcd_module));
+ if (0 == strncmp(RK_PRIMARY_PANEL_NAME, np->name, strlen(np->name))) {
+ strncpy(lcd_module, primary_lcd_module, strlen(primary_lcd_module));
+
+ } else if (0 == strncmp(RK_SUB_PANEL_NAME, np->name, strlen(np->name))) {
+ strncpy(lcd_module, sub_lcd_module, strlen(sub_lcd_module));
+ }

if (!np)
return NULL;

- timings_np = of_get_child_by_name(np, "display-timings");
+ memset(node_name, 0, sizeof(node_name));
+ strncpy(node_name, "display-timings", strlen("display-timings"));
+ strncat(node_name, lcd_module, strlen(lcd_module));
+ printk("[lcd_detect_display-timings] node_name = %s, %s: %d\n",node_name, __func__, __LINE__);
+
+ timings_np = of_get_child_by_name(np, node_name);
if (!timings_np) {
pr_err("%s: could not find display-timings node\n",
of_node_full_name(np));
diff --git a/kernel/include/dt-bindings/display/screen-timing/lcd-edp-dl.dtsi b/kernel/include/dt-bindings/display/screen-timing/lcd-edp-dl.dtsi
new file mode 100644
index 0000000000..1ac2988b3c
--- /dev/null
+++ b/kernel/include/dt-bindings/display/screen-timing/lcd-edp-dl.dtsi
@@ -0,0 +1,21 @@
+&edp_panel {
+
+ display-timings_edpdl {
+ native-mode = <&timing_edpdl>;
+ timing_edpdl: timing_edpdl {
+ clock-frequency = <128000000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hfront-porch = <15>;
+ hback-porch = <15>;
+ vfront-porch = <15>;
+ vback-porch = <15>;
+ hsync-len = <7>;
+ vsync-len = <5>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+};
diff --git a/kernel/include/dt-bindings/display/screen-timing/lcd-lvds-dl.dtsi b/kernel/include/dt-bindings/display/screen-timing/lcd-lvds-dl.dtsi
new file mode 100644
index 0000000000..613c7c08c0
--- /dev/null
+++ b/kernel/include/dt-bindings/display/screen-timing/lcd-lvds-dl.dtsi
@@ -0,0 +1,21 @@
+&lvds_panel {
+
+ display-timings_lvdsdl {
+ native-mode = <&timing_lvdsdl>;
+ timing_lvdsdl: timing_lvdsdl {
+ clock-frequency = <138000000>;
+ hactive = <1920>;
+ vactive = <1080>;
+ hback-porch = <148>;
+ hfront-porch = <88>;
+ vback-porch = <36>;
+ vfront-porch = <4>;
+ hsync-len = <44>;
+ vsync-len = <5>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <0>;
+ pixelclk-active = <0>;
+ };
+ };
+};
diff --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 */
diff --git a/u-boot/board/rockchip/common/rkloader/parameter.c b/u-boot/board/rockchip/common/rkloader/parameter.c
index bc8a0d44dd..68127ddf65 100755
--- a/u-boot/board/rockchip/common/rkloader/parameter.c
+++ b/u-boot/board/rockchip/common/rkloader/parameter.c
@@ -10,10 +10,33 @@

#include "../config.h"
#include "parameter.h"
+#include <lcd.h>


BootInfo gBootInfo;

+static 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;
+}
+
static int find_mtd_part(cmdline_mtd_partition *this_mtd, const char *part_name)
{
int i = 0;
@@ -411,5 +434,7 @@ end:
if (param)
free(param);

+ lcd_detect();
+
return ret;
}
diff --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;

diff --git a/u-boot/include/asm-generic/global_data.h b/u-boot/include/asm-generic/global_data.h
index 8c91ab913e..fcc6e03818 100644
--- a/u-boot/include/asm-generic/global_data.h
+++ b/u-boot/include/asm-generic/global_data.h
@@ -46,6 +46,7 @@ typedef struct global_data {
unsigned long mem_clk;
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO) || defined(CONFIG_ROCKCHIP_DISPLAY)
unsigned long fb_base; /* Base address of framebuffer mem */
+ char lcd_module[32];
#endif
#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER)
unsigned long post_log_word; /* Record POST activities */
diff --git a/u-boot/include/lcd.h b/u-boot/include/lcd.h
index 818589e847..98762aade9 100755
--- 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;
您的支持将鼓励我继续创作!