board: karo: add support for using Linux simple-panel LCD driver KARO-TX6-2017-10-27
authorLothar Waßmann <LW@KARO-electronics.de>
Wed, 25 Oct 2017 12:04:56 +0000 (14:04 +0200)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 25 Oct 2017 12:04:56 +0000 (14:04 +0200)
Provide support for updating the 'compatible' property of the
simple-panel DT node according to the LCD timing selected via
the 'video_mode' variable.

board/karo/common/fdt.c
board/karo/common/karo.h
board/karo/tx28/tx28.c
board/karo/tx48/tx48.c
board/karo/tx51/tx51.c
board/karo/tx53/tx53.c
board/karo/tx6/tx6qdl.c
board/karo/tx6/tx6ul.c
board/karo/txa5/txa5.c

index d43a117..65b6a86 100644 (file)
@@ -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
index d4f5cdb..06427e4 100644 (file)
@@ -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);
index b7ece92..a0f5ac9 100644 (file)
@@ -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;
 }
index 7383738..91b4764 100644 (file)
@@ -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();
 
index 00f8262..3f5b496 100644 (file)
@@ -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;
 }
index 49cc641..3a80a28 100644 (file)
@@ -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 */
index bb57a79..17d7d57 100644 (file)
@@ -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",
@@ -922,6 +921,24 @@ static struct fb_videomode tx6_fb_modes[] = {
                .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 */
index eb55401..5dccba6 100644 (file)
@@ -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;
 }
index 147f2e0..950de2e 100644 (file)
@@ -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;
 }