diff options
| author | rin <rin@NetBSD.org> | 2020-10-19 01:12:14 +0000 |
|---|---|---|
| committer | rin <rin@NetBSD.org> | 2020-10-19 01:12:14 +0000 |
| commit | 6deedafda44b855bfb8eb6ba4120bee600d47455 (patch) | |
| tree | e9c583f54661713efb71185f05dc147dd70bbe39 /sys | |
| parent | bc55fab413e4a543149ca618f7ef2b6ec1e30b18 (diff) | |
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 (limited to 'sys')
| -rw-r--r-- | sys/arch/arm/fdt/arm_simplefb.c | 19 | ||||
| -rw-r--r-- | sys/arch/evbarm/fdt/fdt_machdep.c | 53 | ||||
| -rw-r--r-- | sys/dev/fdt/simplefb.c | 8 |
3 files changed, 74 insertions, 6 deletions
diff --git a/sys/arch/arm/fdt/arm_simplefb.c b/sys/arch/arm/fdt/arm_simplefb.c index df20e2508a3..681c8771bae 100644 --- a/sys/arch/arm/fdt/arm_simplefb.c +++ b/sys/arch/arm/fdt/arm_simplefb.c @@ -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, struct vcons_screen *scr, 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(); diff --git a/sys/arch/evbarm/fdt/fdt_machdep.c b/sys/arch/evbarm/fdt/fdt_machdep.c index 06acc4c2d76..68f04811cc8 100644 --- a/sys/arch/evbarm/fdt/fdt_machdep.c +++ b/sys/arch/evbarm/fdt/fdt_machdep.c @@ -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> @@ -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.c,v 1.75 2020/10/10 15:25:30 jmcneill Ex #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 diff --git a/sys/dev/fdt/simplefb.c b/sys/dev/fdt/simplefb.c index d766538e60a..9c4af114b29 100644 --- a/sys/dev/fdt/simplefb.c +++ b/sys/dev/fdt/simplefb.c @@ -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> @@ -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_softc *sc) 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 { |
