Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/fdt Fix colors of 32-bpp raster console for evbarm/a...



details:   https://anonhg.NetBSD.org/src/rev/79000f975998
branches:  trunk
changeset: 945033:79000f975998
user:      rin <rin%NetBSD.org@localhost>
date:      Mon Oct 19 01:12:14 2020 +0000

description:
Fix colors of 32-bpp raster console for evbarm/aarch64eb and armeb.

Most boards are configured to little-endian in initial, and switched
to big-endian after kernel is loaded. In this case, framebuffer seems
byte-swapped to CPU.

It is best to reconfigure framebuffer (as done recently for sunxi_mixer
by jmcneill), but in most cases, HW is incapable, or we just don't know
register bits to configure them.

Therefore, override "format" FDT property for "simple-framebuffer" to
let drivers know byte-order for 32-bpp framebuffer.

Then, make fdt/simplefb (genfb) and arm_simplefb (early console) detect
byte-swapped FB, and configure genfb(4) or rasops(4) layers accordingly.

Tested on Pine A64+ (arm_simplefb) and Cubietruck (both fdt/simplefb and
arm_simplefb).

Discussed with jmcneill. Thanks!!

diffstat:

 sys/arch/arm/fdt/arm_simplefb.c   |  19 ++++++++++++-
 sys/arch/evbarm/fdt/fdt_machdep.c |  53 +++++++++++++++++++++++++++++++++++++-
 sys/dev/fdt/simplefb.c            |   8 ++++-
 3 files changed, 74 insertions(+), 6 deletions(-)

diffs (189 lines):

diff -r 88d0c320a3bf -r 79000f975998 sys/arch/arm/fdt/arm_simplefb.c
--- a/sys/arch/arm/fdt/arm_simplefb.c   Mon Oct 19 01:08:06 2020 +0000
+++ b/sys/arch/arm/fdt/arm_simplefb.c   Mon Oct 19 01:12:14 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: arm_simplefb.c,v 1.1 2020/10/10 15:25:31 jmcneill Exp $ */
+/* $NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $ */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
 #include "opt_pci.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.1 2020/10/10 15:25:31 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm_simplefb.c,v 1.2 2020/10/19 01:12:14 rin Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -66,6 +66,7 @@
        uint32_t        sc_height;
        uint32_t        sc_stride;
        uint16_t        sc_depth;
+       bool            sc_swapped;
        void            *sc_bits;
 } arm_simplefb_softc;
 
@@ -120,6 +121,14 @@
        ri->ri_bits = sc->sc_bits;
        ri->ri_flg = RI_CENTER | RI_FULLCLEAR | RI_CLEAR;
 
+       if (sc->sc_swapped) {
+               KASSERT(ri->ri_depth == 32);
+               ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8;
+               ri->ri_rpos =  8;
+               ri->ri_gpos = 16;
+               ri->ri_bpos = 24;
+       }
+
        scr->scr_flags |= VCONS_LOADFONT;
        scr->scr_flags |= VCONS_DONT_READ;
 
@@ -161,6 +170,7 @@
        bus_size_t size;
        uint16_t depth;
        long defattr;
+       bool swapped = false;
 
        const int phandle = arm_simplefb_find_node();
        if (phandle == -1)
@@ -181,6 +191,10 @@
        if (strcmp(format, "a8b8g8r8") == 0 ||
            strcmp(format, "x8r8g8b8") == 0) {
                depth = 32;
+       } else if (strcmp(format, "r8g8b8a8") == 0 ||
+                  strcmp(format, "b8g8r8x8") == 0) {
+               depth = 32;
+               swapped = true;
        } else if (strcmp(format, "r5g6b5") == 0) {
                depth = 16;
        } else {
@@ -196,6 +210,7 @@
        sc->sc_depth = depth;
        sc->sc_stride = stride;
        sc->sc_bits = bus_space_vaddr(bst, bsh);
+       sc->sc_swapped = swapped;
 
        wsfont_init();
 
diff -r 88d0c320a3bf -r 79000f975998 sys/arch/evbarm/fdt/fdt_machdep.c
--- a/sys/arch/evbarm/fdt/fdt_machdep.c Mon Oct 19 01:08:06 2020 +0000
+++ b/sys/arch/evbarm/fdt/fdt_machdep.c Mon Oct 19 01:12:14 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_machdep.c,v 1.75 2020/10/10 15:25:30 jmcneill Exp $ */
+/* $NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.75 2020/10/10 15:25:30 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.76 2020/10/19 01:12:14 rin Exp $");
 
 #include "opt_machdep.h"
 #include "opt_bootconfig.h"
@@ -48,6 +48,7 @@
 #include <sys/atomic.h>
 #include <sys/cpu.h>
 #include <sys/device.h>
+#include <sys/endian.h>
 #include <sys/exec.h>
 #include <sys/kernel.h>
 #include <sys/kmem.h>
@@ -143,6 +144,10 @@
 static void fdt_reset(void);
 static void fdt_powerdown(void);
 
+#if BYTE_ORDER == BIG_ENDIAN
+static void fdt_update_fb_format(void);
+#endif
+
 static void
 earlyconsputc(dev_t dev, int c)
 {
@@ -578,6 +583,17 @@
        VPRINTF("stdout\n");
        fdt_update_stdout_path();
 
+#if BYTE_ORDER == BIG_ENDIAN
+       /*
+        * Most boards are configured to little-endian mode in initial, and
+        * switched to big-endian mode after kernel is loaded. In this case,
+        * framebuffer seems byte-swapped to CPU. Override FDT to let
+        * drivers know.
+        */
+       VPRINTF("fb_format\n");
+       fdt_update_fb_format();
+#endif
+
        /*
         * Done making changes to the FDT.
         */
@@ -916,3 +932,36 @@
 {
        fdtbus_power_poweroff();
 }
+
+#if BYTE_ORDER == BIG_ENDIAN
+static void
+fdt_update_fb_format(void)
+{
+       int off, len;
+       const char *format, *replace;
+
+       off = fdt_path_offset(fdt_data, "/chosen");
+       if (off < 0)
+               return;
+
+       for (;;) {
+               off = fdt_node_offset_by_compatible(fdt_data, off,
+                   "simple-framebuffer");
+               if (off < 0)
+                       return;
+
+               format = fdt_getprop(fdt_data, off, "format", &len);
+               if (format == NULL)
+                       continue;
+
+               replace = NULL;
+               if (strcmp(format, "a8b8g8r8") == 0)
+                       replace = "r8g8b8a8";
+               else if (strcmp(format, "x8r8g8b8") == 0)
+                       replace = "b8g8r8x8";
+               if (replace != NULL)
+                       fdt_setprop(fdt_data, off, "format", replace,
+                           strlen(replace) + 1);
+       }
+}
+#endif
diff -r 88d0c320a3bf -r 79000f975998 sys/dev/fdt/simplefb.c
--- a/sys/dev/fdt/simplefb.c    Mon Oct 19 01:08:06 2020 +0000
+++ b/sys/dev/fdt/simplefb.c    Mon Oct 19 01:12:14 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: simplefb.c,v 1.8 2019/07/23 14:34:12 rin Exp $ */
+/* $NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_wsdisplay_compat.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.8 2019/07/23 14:34:12 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: simplefb.c,v 1.9 2020/10/19 01:12:14 rin Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -157,6 +157,10 @@
        if (strcmp(format, "a8b8g8r8") == 0 ||
            strcmp(format, "x8r8g8b8") == 0) {
                depth = 32;
+       } else if (strcmp(format, "r8g8b8a8") == 0 ||
+                  strcmp(format, "b8g8r8x8") == 0) {
+               depth = 32;
+               prop_dictionary_set_bool(dict, "is_swapped", true);
        } else if (strcmp(format, "r5g6b5") == 0) {
                depth = 16;
        } else {



Home | Main Index | Thread Index | Old Index