From: Lothar Waßmann Date: Wed, 25 Oct 2017 12:04:56 +0000 (+0200) Subject: board: karo: add support for using Linux simple-panel LCD driver X-Git-Tag: KARO-TX6-2017-10-27 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=commitdiff_plain;h=63652ce377ee8ce60a6217aefe238313d0989c60 board: karo: add support for using Linux simple-panel LCD driver Provide support for updating the 'compatible' property of the simple-panel DT node according to the LCD timing selected via the 'video_mode' variable. --- diff --git a/board/karo/common/fdt.c b/board/karo/common/fdt.c index d43a1170fc..65b6a86a28 100644 --- a/board/karo/common/fdt.c +++ b/board/karo/common/fdt.c @@ -553,15 +553,27 @@ static int karo_fdt_find_video_timings(void *blob) return off; } -int karo_fdt_get_fb_mode(void *blob, const char *name, struct fb_videomode *fb_mode) +static int karo_fdt_check_panel_name(const char *pn, const char *name, int len) { - int off = karo_fdt_find_video_timings(blob); + const char *endp = pn + len; - if (off < 0) - return off; + if (len < 0) + return 0; + while (pn < endp) { + if (strcasecmp(pn, name) == 0) + return 1; + pn += strlen(pn) + 1; + } + return 0; +} + +static int karo_fdt_find_panel(const void *blob, int off, const char *name) +{ + debug("Searching panel '%s'\n", name); while (off > 0) { - const char *n, *endp; - int len, d = 1; + const char *pn; + int d = 1; + int len; off = fdt_next_node(blob, off, &d); if (off < 0) @@ -574,28 +586,30 @@ int karo_fdt_get_fb_mode(void *blob, const char *name, struct fb_videomode *fb_m continue; } - n = fdt_getprop(blob, off, "panel-name", &len); - if (!n) { - n = fdt_get_name(blob, off, NULL); - if (strcasecmp(n, name) == 0) { - break; - } - } else { - int found = 0; - - for (endp = n + len; n < endp; n += strlen(n) + 1) { - debug("Checking panel-name '%s'\n", n); - if (strcasecmp(n, name) == 0) { - debug("Using node %s @ %04x\n", - fdt_get_name(blob, off, NULL), off); - found = 1; - break; - } - } - if (found) - break; - } + pn = fdt_get_name(blob, off, NULL); + debug("Checking node name '%s'\n", pn); + if (strcasecmp(pn, name) == 0) + break; + pn = fdt_getprop(blob, off, "u-boot,panel-name", &len); + if (!pn) + continue; + if (karo_fdt_check_panel_name(pn, name, len)) + break; } + if (off > 0) + debug("Found LCD panel: '%s' @ off %03x\n", + fdt_get_name(blob, off, NULL), off); + return off; +} + +int karo_fdt_get_fb_mode(void *blob, const char *name, + struct fb_videomode *fb_mode) +{ + int off = karo_fdt_find_video_timings(blob); + + if (off < 0) + return off; + off = karo_fdt_find_panel(blob, off, name); if (off > 0) { return fdt_init_fb_mode(blob, off, fb_mode); } @@ -698,21 +712,36 @@ out: return ret; } -int karo_fdt_update_fb_mode(void *blob, const char *name) +int karo_fdt_update_fb_mode(void *blob, const char *name, + const char *panel_name) { + int ret; int off = fdt_path_offset(blob, "display"); + int panel_off = -1; const char *subnode = "display-timings"; - if (off < 0) + if (panel_name) + panel_off = fdt_path_offset(blob, panel_name); + + if (off < 0 && panel_off < 0) return off; if (name == NULL) { - int ret; - debug("Disabling node '%s' at %03x\n", fdt_get_name(blob, off, NULL), off); ret = fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); - return ret; + if (ret) + printf("Failed to disable node '%s': %s\n", + fdt_get_name(blob, off, NULL), + fdt_strerror(ret)); + if (!panel_name) + return ret; + + panel_off = fdt_path_offset(blob, panel_name); + if (panel_off < 0) + return 0; + return fdt_set_node_status(blob, panel_off, + FDT_STATUS_DISABLED, 0); } off = fdt_subnode_offset(blob, off, subnode); @@ -721,46 +750,41 @@ int karo_fdt_update_fb_mode(void *blob, const char *name) fdt_strerror(off)); return off; } - while (off > 0) { - const char *n, *endp; - int len, d = 1; - - off = fdt_next_node(blob, off, &d); - if (off < 0) - return off; - if (d < 1) - return -EINVAL; - if (d > 2) { - debug("Skipping node @ %04x %s depth %d\n", off, - fdt_get_name(blob, off, NULL), d); - continue; - } + off = karo_fdt_find_panel(blob, off, name); + if (off > 0) + ret = fdt_update_native_fb_mode(blob, off); + else + ret = 0; + if (!panel_name) + return ret; - n = fdt_getprop(blob, off, "panel-name", &len); - if (!n) { - n = fdt_get_name(blob, off, NULL); - if (strcasecmp(n, name) == 0) { - break; - } - } else { - int found = 0; - - for (endp = n + len; n < endp; n += strlen(n) + 1) { - debug("Checking panel-name '%s'\n", n); - if (strcasecmp(n, name) == 0) { - debug("Using node %s @ %04x\n", - fdt_get_name(blob, off, NULL), off); - found = 1; - break; - } - } - if (found) - break; - } + off = fdt_path_offset(blob, "display/display-timings"); + off = karo_fdt_find_panel(blob, off, name); + panel_off = fdt_path_offset(blob, panel_name); + if (panel_off > 0) { + char *pn; + + name = fdt_getprop(blob, off, "u-boot,panel-name", + NULL); + if (!name) + return 0; + pn = strdup(name); + if (!pn) + return -ENOMEM; + debug("%s@%d: Updating 'compatible' property of '%s' from '%s' to '%s'\n", + __func__, __LINE__, fdt_get_name(blob, panel_off, NULL), + (char *)fdt_getprop(blob, panel_off, "compatible", NULL), + pn); + + ret = fdt_setprop_string(blob, panel_off, "compatible", + pn); + if (ret) + printf("Failed to set 'compatible' property of node '%s': %s\n", + fdt_get_name(blob, panel_off, NULL), + fdt_strerror(off)); + free(pn); } - if (off > 0) - return fdt_update_native_fb_mode(blob, off); - return off; + return ret; } #ifdef CONFIG_SYS_LVDS_IF diff --git a/board/karo/common/karo.h b/board/karo/common/karo.h index d4f5cdb9e8..06427e49d4 100644 --- a/board/karo/common/karo.h +++ b/board/karo/common/karo.h @@ -40,7 +40,8 @@ void karo_fdt_del_prop(void *blob, const char *compat, u32 offs, void karo_fdt_enable_node(void *blob, const char *node, int enable); int karo_fdt_get_fb_mode(void *blob, const char *name, struct fb_videomode *fb_mode); -int karo_fdt_update_fb_mode(void *blob, const char *name); +int karo_fdt_update_fb_mode(void *blob, const char *name, + const char *panel_name); int karo_fdt_create_fb_mode(void *blob, const char *name, struct fb_videomode *mode); int karo_fdt_get_backlight_polarity(const void *blob); diff --git a/board/karo/tx28/tx28.c b/board/karo/tx28/tx28.c index b7ece9272e..a0f5ac9bba 100644 --- a/board/karo/tx28/tx28.c +++ b/board/karo/tx28/tx28.c @@ -1033,7 +1033,7 @@ int ft_board_setup(void *blob, bd_t *bd) ARRAY_SIZE(tx28_touchpanels)); karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); karo_fdt_fixup_flexcan(blob, stk5_v5); - karo_fdt_update_fb_mode(blob, video_mode); + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); return 0; } diff --git a/board/karo/tx48/tx48.c b/board/karo/tx48/tx48.c index 7383738a24..91b4764d15 100644 --- a/board/karo/tx48/tx48.c +++ b/board/karo/tx48/tx48.c @@ -916,7 +916,7 @@ int ft_board_setup(void *blob, bd_t *bd) karo_fdt_fixup_usb_otg(blob, "usb0", "phys", "vcc-supply"); karo_fdt_fixup_flexcan(blob, stk5_v5); - karo_fdt_update_fb_mode(blob, video_mode); + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); tx48_disable_watchdog(); diff --git a/board/karo/tx51/tx51.c b/board/karo/tx51/tx51.c index 00f82621b3..3f5b496b3c 100644 --- a/board/karo/tx51/tx51.c +++ b/board/karo/tx51/tx51.c @@ -1131,7 +1131,7 @@ int ft_board_setup(void *blob, bd_t *bd) karo_fdt_fixup_touchpanel(blob, tx51_touchpanels, ARRAY_SIZE(tx51_touchpanels)); karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); - karo_fdt_update_fb_mode(blob, video_mode); + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); return 0; } diff --git a/board/karo/tx53/tx53.c b/board/karo/tx53/tx53.c index 49cc641fc6..3a80a28730 100644 --- a/board/karo/tx53/tx53.c +++ b/board/karo/tx53/tx53.c @@ -1451,8 +1451,12 @@ int ft_board_setup(void *blob, bd_t *bd) karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); karo_fdt_fixup_flexcan(blob, stk5_v5); tx53_fixup_rtc(blob); - karo_fdt_update_fb_mode(blob, video_mode); - +#ifdef CONFIG_SYS_LVDS_IF + karo_fdt_update_fb_mode(blob, video_mode, "/lvds0-panel"); + karo_fdt_update_fb_mode(blob, video_mode, "/lvds1-panel"); +#else + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); +#endif return 0; } #endif /* CONFIG_OF_BOARD_SETUP */ diff --git a/board/karo/tx6/tx6qdl.c b/board/karo/tx6/tx6qdl.c index bb57a796e1..17d7d5724a 100644 --- a/board/karo/tx6/tx6qdl.c +++ b/board/karo/tx6/tx6qdl.c @@ -887,7 +887,6 @@ vidinfo_t panel_info = { }; static struct fb_videomode tx6_fb_modes[] = { -#ifndef CONFIG_SYS_LVDS_IF { /* Standard VGA timing */ .name = "VGA", @@ -921,6 +920,24 @@ static struct fb_videomode tx6_fb_modes[] = { .lower_margin = 10, .sync = FB_SYNC_CLK_LAT_FALL, }, + { + /* Emerging ETM0700G0DH6 800 x 480 display. + * 152.4 mm x 91.44 mm display area. + */ + .name = "ET0700", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33260), + .left_margin = 88, + .hsync_len = 128, + .right_margin = 40, + .upper_margin = 33, + .vsync_len = 2, + .lower_margin = 10, + .sync = FB_SYNC_CLK_LAT_FALL, + }, +#ifndef CONFIG_SYS_LVDS_IF { /* Emerging ET0350G0DH6 320 x 240 display. * 70.08 mm x 52.56 mm display area. @@ -930,10 +947,10 @@ static struct fb_videomode tx6_fb_modes[] = { .xres = 320, .yres = 240, .pixclock = KHZ2PICOS(6500), - .left_margin = 68 - 34, + .left_margin = 34, .hsync_len = 34, .right_margin = 20, - .upper_margin = 18 - 3, + .upper_margin = 15, .vsync_len = 3, .lower_margin = 4, .sync = FB_SYNC_CLK_LAT_FALL, @@ -963,12 +980,12 @@ static struct fb_videomode tx6_fb_modes[] = { .xres = 800, .yres = 480, .pixclock = KHZ2PICOS(33260), - .left_margin = 216 - 128, + .left_margin = 88, .hsync_len = 128, - .right_margin = 1056 - 800 - 216, - .upper_margin = 35 - 2, + .right_margin = 40, + .upper_margin = 33, .vsync_len = 2, - .lower_margin = 525 - 480 - 35, + .lower_margin = 10, .sync = FB_SYNC_CLK_LAT_FALL, }, { @@ -988,40 +1005,6 @@ static struct fb_videomode tx6_fb_modes[] = { .lower_margin = 4, /* 4.5 according to datasheet */ .sync = FB_SYNC_CLK_LAT_FALL, }, - { - /* Emerging ET0700G0DH6 800 x 480 display. - * 152.4 mm x 91.44 mm display area. - */ - .name = "ET0700", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = KHZ2PICOS(33260), - .left_margin = 216 - 128, - .hsync_len = 128, - .right_margin = 1056 - 800 - 216, - .upper_margin = 35 - 2, - .vsync_len = 2, - .lower_margin = 525 - 480 - 35, - .sync = FB_SYNC_CLK_LAT_FALL, - }, - { - /* Emerging ET070001DM6 800 x 480 display. - * 152.4 mm x 91.44 mm display area. - */ - .name = "ET070001DM6", - .refresh = 60, - .xres = 800, - .yres = 480, - .pixclock = KHZ2PICOS(33260), - .left_margin = 216 - 128, - .hsync_len = 128, - .right_margin = 1056 - 800 - 216, - .upper_margin = 35 - 2, - .vsync_len = 2, - .lower_margin = 525 - 480 - 35, - .sync = 0, - }, #else { /* HannStar HSD100PXN1 @@ -1565,8 +1548,12 @@ int ft_board_setup(void *blob, bd_t *bd) karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); karo_fdt_fixup_flexcan(blob, stk5_v5); - karo_fdt_update_fb_mode(blob, video_mode); - +#ifdef CONFIG_SYS_LVDS_IF + karo_fdt_update_fb_mode(blob, video_mode, "/lvds0-panel"); + karo_fdt_update_fb_mode(blob, video_mode, "/lvds1-panel"); +#else + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); +#endif return 0; } #endif /* CONFIG_OF_BOARD_SETUP */ diff --git a/board/karo/tx6/tx6ul.c b/board/karo/tx6/tx6ul.c index eb55401470..5dccba67eb 100644 --- a/board/karo/tx6/tx6ul.c +++ b/board/karo/tx6/tx6ul.c @@ -1505,7 +1505,7 @@ int ft_board_setup(void *blob, bd_t *bd) karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); karo_fdt_fixup_flexcan(blob, stk5_v5); - karo_fdt_update_fb_mode(blob, video_mode); + karo_fdt_update_fb_mode(blob, video_mode, "/lcd-panel"); return 0; } diff --git a/board/karo/txa5/txa5.c b/board/karo/txa5/txa5.c index 147f2e02fa..950de2e51f 100644 --- a/board/karo/txa5/txa5.c +++ b/board/karo/txa5/txa5.c @@ -876,7 +876,7 @@ int ft_board_setup(void *blob, bd_t *bd) ARRAY_SIZE(txa5_touchpanels)); // karo_fdt_fixup_usb_otg(blob, "usbotg", "fsl,usbphy", "vbus-supply"); // karo_fdt_fixup_flexcan(blob, stk5_v5); - karo_fdt_update_fb_mode(blob, video_mode); + karo_fdt_update_fb_mode(blob, video_mode, NULL); return 0; }