Module Name: src Committed By: rin Date: Mon Oct 19 01:12:14 UTC 2020
Modified Files: src/sys/arch/arm/fdt: arm_simplefb.c src/sys/arch/evbarm/fdt: fdt_machdep.c src/sys/dev/fdt: simplefb.c Log Message: 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!! To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/fdt/arm_simplefb.c cvs rdiff -u -r1.75 -r1.76 src/sys/arch/evbarm/fdt/fdt_machdep.c cvs rdiff -u -r1.8 -r1.9 src/sys/dev/fdt/simplefb.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/fdt/arm_simplefb.c diff -u src/sys/arch/arm/fdt/arm_simplefb.c:1.1 src/sys/arch/arm/fdt/arm_simplefb.c:1.2 --- src/sys/arch/arm/fdt/arm_simplefb.c:1.1 Sat Oct 10 15:25:31 2020 +++ src/sys/arch/arm/fdt/arm_simplefb.c Mon Oct 19 01:12:14 2020 @@ -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 @@ static struct arm_simplefb_softc { 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 @@ arm_simplefb_init_screen(void *cookie, s 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 @@ arm_simplefb_preattach(void) 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 @@ arm_simplefb_preattach(void) 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 @@ arm_simplefb_preattach(void) sc->sc_depth = depth; sc->sc_stride = stride; sc->sc_bits = bus_space_vaddr(bst, bsh); + sc->sc_swapped = swapped; wsfont_init(); Index: src/sys/arch/evbarm/fdt/fdt_machdep.c diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.75 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.76 --- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.75 Sat Oct 10 15:25:30 2020 +++ src/sys/arch/evbarm/fdt/fdt_machdep.c Mon Oct 19 01:12:14 2020 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep. #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_cpu_rootconf(void); 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 @@ initarm(void *arg) 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 @@ fdt_powerdown(void) { 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 Index: src/sys/dev/fdt/simplefb.c diff -u src/sys/dev/fdt/simplefb.c:1.8 src/sys/dev/fdt/simplefb.c:1.9 --- src/sys/dev/fdt/simplefb.c:1.8 Tue Jul 23 14:34:12 2019 +++ src/sys/dev/fdt/simplefb.c Mon Oct 19 01:12:14 2020 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ simplefb_attach_genfb(struct simplefb_so 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 {