summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorrin <rin@NetBSD.org>2020-10-19 01:12:14 +0000
committerrin <rin@NetBSD.org>2020-10-19 01:12:14 +0000
commit6deedafda44b855bfb8eb6ba4120bee600d47455 (patch)
treee9c583f54661713efb71185f05dc147dd70bbe39 /sys
parentbc55fab413e4a543149ca618f7ef2b6ec1e30b18 (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.c19
-rw-r--r--sys/arch/evbarm/fdt/fdt_machdep.c53
-rw-r--r--sys/dev/fdt/simplefb.c8
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 {