Module Name:    src
Committed By:   bouyer
Date:           Sat Apr  7 18:09:34 UTC 2018

Modified Files:
        src/sys/arch/arm/sunxi: sunxi_debe.c sunxi_dep.c sunxi_display.h
            sunxi_tcon.c

Log Message:
Allow the graphic driver to be the kernel's console.
Match either from the allwinner,pipeline entry in the simple-framebuffer
fdt entry, or from console= from the command line.
console=fb0 and console=fb1 selects display backend unit 0 or 1 respectively;
console=fb selects the first activated display backend.


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/sunxi/sunxi_debe.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_dep.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_display.h
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/sunxi/sunxi_tcon.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/sunxi/sunxi_debe.c
diff -u src/sys/arch/arm/sunxi/sunxi_debe.c:1.7 src/sys/arch/arm/sunxi/sunxi_debe.c:1.8
--- src/sys/arch/arm/sunxi/sunxi_debe.c:1.7	Thu Apr  5 10:21:39 2018
+++ src/sys/arch/arm/sunxi/sunxi_debe.c	Sat Apr  7 18:09:33 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_debe.c,v 1.7 2018/04/05 10:21:39 jmcneill Exp $ */
+/* $NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2018 Manuel Bouyer <bou...@antioche.eu.org>
@@ -38,7 +38,7 @@
 #define SUNXI_DEBE_CURMAX	64
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.7 2018/04/05 10:21:39 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -58,6 +58,8 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c
 
 #include <arm/sunxi/sunxi_debereg.h>
 #include <arm/sunxi/sunxi_display.h>
+#include <arm/sunxi/sunxi_platform.h>
+#include <machine/bootconfig.h>
 
 enum sunxi_debe_type {
 	DEBE_A10 = 1,
@@ -128,6 +130,9 @@ static int	sunxi_debe_ioctl(device_t, u_
 static void	sunxi_befb_set_videomode(device_t, u_int, u_int);
 void sunxi_debe_dump_regs(int);
 
+static struct sunxi_debe_softc *debe_console_sc;
+static int sunxi_simplefb_phandle = -1;
+
 CFATTACH_DECL_NEW(sunxi_debe, sizeof(struct sunxi_debe_softc),
 	sunxi_debe_match, sunxi_debe_attach, NULL, NULL);
 
@@ -242,8 +247,6 @@ sunxi_debe_attach(device_t parent, devic
 	}
 }
 
-
-
 static void
 sunxi_debe_ep_connect(device_t self, struct fdt_endpoint *ep, bool connect)
 {
@@ -337,6 +340,32 @@ sunxi_debe_setup_fbdev(struct sunxi_debe
 	const u_int fb_height = (mode->vdisplay << interlace_p);
 
 	if (mode && sc->sc_fbdev == NULL) {
+		/* see if we are the console */
+		if (sunxi_simplefb_phandle >= 0) {
+			const char *cons_pipeline =
+			    fdtbus_get_string(sunxi_simplefb_phandle,
+			        "allwinner,pipeline");
+			struct fdt_endpoint *ep = fdt_endpoint_get_from_index(
+			    &sc->sc_ports, SUNXI_PORT_OUTPUT, sc->sc_unit);
+			struct fdt_endpoint *rep = fdt_endpoint_remote(ep);
+			if (sunxi_tcon_is_console(
+			    fdt_endpoint_device(rep), cons_pipeline))
+				debe_console_sc = sc;
+		} else if (debe_console_sc == NULL) {
+			if (match_bootconf_option(boot_args,
+			    "console", "fb0")) {
+				if (sc->sc_unit == 0)
+					debe_console_sc = sc;
+			} else if (match_bootconf_option(boot_args,
+			    "console", "fb1")) {
+				if (sc->sc_unit == 1)
+					debe_console_sc = sc;
+			} else if (match_bootconf_option(boot_args,
+			    "console", "fb")) {
+				/* match first activated */
+				debe_console_sc = sc;
+			}
+		}
 		struct sunxifb_attach_args afb = {
 			.afb_fb = sc->sc_dmap,
 			.afb_width = fb_width,
@@ -684,9 +713,6 @@ sunxi_befb_attach(device_t parent, devic
 	prop_dictionary_t cfg = device_properties(self);
 	struct genfb_ops ops;
 
-	if (sunxi_befb_consoledev == NULL)
-		sunxi_befb_consoledev = self;
-
 	sc->sc_gen.sc_dev = self;
 	sc->sc_debedev = parent;
 	sc->sc_dmat = afb->afb_dmat;
@@ -716,14 +742,27 @@ sunxi_befb_attach(device_t parent, devic
 
 	aprint_naive("\n");
 
-	bool is_console = false;
-	prop_dictionary_set_bool(cfg, "is_console", is_console);
-
+	bool is_console = (debe_console_sc == device_private(parent));
 	if (is_console)
 		aprint_normal(": switching to framebuffer console\n");
 	else
 		aprint_normal("\n");
 
+#ifdef WSDISPLAY_MULTICONS
+	/*
+	 * if we support multicons, only the first framebuffer is console,
+	 * unless we already know which framebuffer will be the console
+	 */
+	if (!is_console && debe_console_sc == NULL &&
+	    sunxi_befb_consoledev == NULL)
+		is_console = true;
+#endif
+	prop_dictionary_set_bool(cfg, "is_console", is_console);
+	if (is_console) {
+		KASSERT(sunxi_befb_consoledev == NULL);
+		sunxi_befb_consoledev = self;
+	}
+
 	genfb_attach(&sc->sc_gen, &ops);
 }
 
@@ -829,13 +868,47 @@ sunxi_debe_pipeline(int phandle, bool ac
 		return ENODEV;
 	}
 	error = fdt_endpoint_activate(ep, true);
-	if (error == 0) {
-		sc->sc_out_ep = ep;
-		fdt_endpoint_enable(ep, true);
-	}
+	if (error)
+		return error;
+
+	sc->sc_out_ep = ep;
+	error = fdt_endpoint_enable(ep, true);
 	return error;
 }
 
+/*
+ * we don't want to take over console at this time - simplefb will
+ * do a better job than us. We will take over later.
+ * But we want to record the /chose/framebuffer phandle if there is one
+ */
+
+static const char * const simplefb_compatible[] = {
+	"allwinner,simple-framebuffer",
+	NULL
+};
+
+static int
+sunxidebe_console_match(int phandle)
+{
+	if (of_match_compatible(phandle, simplefb_compatible)) {
+		sunxi_simplefb_phandle = phandle;
+	}
+	return 0;
+}
+
+static void
+sunxidebe_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
+{
+	panic("sunxidebe_console_consinit");
+}
+
+static const struct fdt_console sunxidebe_fdt_console = {
+	.match = sunxidebe_console_match,
+	.consinit = sunxidebe_console_consinit
+};
+
+FDT_CONSOLE(sunxidebe, &sunxidebe_fdt_console);
+
 #if defined(SUNXI_DEBE_DEBUG)
 void
 sunxi_debe_dump_regs(int u)

Index: src/sys/arch/arm/sunxi/sunxi_dep.c
diff -u src/sys/arch/arm/sunxi/sunxi_dep.c:1.2 src/sys/arch/arm/sunxi/sunxi_dep.c:1.3
--- src/sys/arch/arm/sunxi/sunxi_dep.c:1.2	Tue Apr  3 13:38:13 2018
+++ src/sys/arch/arm/sunxi/sunxi_dep.c	Sat Apr  7 18:09:33 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: sunxi_dep.c,v 1.2 2018/04/03 13:38:13 bouyer Exp $	*/
+/*	$NetBSD: sunxi_dep.c,v 1.3 2018/04/07 18:09:33 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: sunxi_dep.c,v 1.2 2018/04/03 13:38:13 bouyer Exp $");
+__KERNEL_RCSID(1, "$NetBSD: sunxi_dep.c,v 1.3 2018/04/07 18:09:33 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -57,6 +57,11 @@ static const struct of_compat_data compa
 	{NULL}
 };
 
+static const char *fb_compat[] = {
+	"allwinner,simple-framebuffer",
+	NULL
+};
+
 static int sunxi_dep_match(device_t, cfdata_t, void *);
 static void sunxi_dep_attach(device_t, device_t, void *);
 
@@ -68,9 +73,8 @@ sunxi_dep_match(device_t parent, cfdata_
 {
 #if NSUNXI_DEBE > 0
 	struct fdt_attach_args * const faa = aux;
-	if (!of_match_compat_data(faa->faa_phandle, compat_data))
-		return 0;
-	return 1;
+
+	return  of_match_compat_data(faa->faa_phandle, compat_data);
 #else
 	return 0;
 #endif
@@ -82,6 +86,7 @@ sunxi_dep_attach(device_t parent, device
 	struct sunxi_dep_softc * const sc = device_private(self);
 	struct fdt_attach_args * const faa = aux;
 	const int phandle = faa->faa_phandle;
+	int sunxi_dep_npipelines = 0;
 	int len;
 	const u_int *buf;
 	u_int ref;
@@ -95,7 +100,6 @@ sunxi_dep_attach(device_t parent, device
 		aprint_error("bad/missing allwinner,pipelines property\n");
 		return;
 	}
-	aprint_naive("\n");
 	aprint_normal(": ");
 #if NSUNXI_DEBE > 0
 	for (int i = 0; i < (len / sizeof(ref)); i++) {
@@ -106,7 +110,12 @@ sunxi_dep_attach(device_t parent, device
 		    fdtbus_get_phandle_from_native(ref), true);
 		if (error)
 			aprint_error("can't activate pipeline %d\n", i);
+		else
+			sunxi_dep_npipelines++;
 	}
+	aprint_naive("\n");
+	if (sunxi_dep_npipelines > 0)
+		fdt_remove_bycompat(fb_compat);
 #else
 	aprint_error("debe not configured\n");
 	return;

Index: src/sys/arch/arm/sunxi/sunxi_display.h
diff -u src/sys/arch/arm/sunxi/sunxi_display.h:1.1 src/sys/arch/arm/sunxi/sunxi_display.h:1.2
--- src/sys/arch/arm/sunxi/sunxi_display.h:1.1	Tue Apr  3 12:52:16 2018
+++ src/sys/arch/arm/sunxi/sunxi_display.h	Sat Apr  7 18:09:33 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: sunxi_display.h,v 1.1 2018/04/03 12:52:16 bouyer Exp $	*/
+/*	$NetBSD: sunxi_display.h,v 1.2 2018/04/07 18:09:33 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -37,3 +37,4 @@ struct videomode;
 int sunxi_debe_pipeline(int, bool);
 void sunxi_tcon1_set_videomode(device_t, const struct videomode *);
 void sunxi_debe_set_videomode(device_t, const struct videomode *);
+bool sunxi_tcon_is_console(device_t, const char *);

Index: src/sys/arch/arm/sunxi/sunxi_tcon.c
diff -u src/sys/arch/arm/sunxi/sunxi_tcon.c:1.5 src/sys/arch/arm/sunxi/sunxi_tcon.c:1.6
--- src/sys/arch/arm/sunxi/sunxi_tcon.c:1.5	Fri Apr  6 08:23:40 2018
+++ src/sys/arch/arm/sunxi/sunxi_tcon.c	Sat Apr  7 18:09:33 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_tcon.c,v 1.5 2018/04/06 08:23:40 bouyer Exp $ */
+/* $NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2018 Manuel Bouyer <bou...@antioche.eu.org>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.5 2018/04/06 08:23:40 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -812,6 +812,55 @@ sunxi_tcon1_set_videomode(device_t dev, 
 	}
 }
 
+/* check if this tcon is the console chosen by firmare */
+bool
+sunxi_tcon_is_console(device_t dev, const char *pipeline)
+{
+	struct sunxi_tcon_softc *sc = device_private(dev);
+	char p[64];
+	char *e, *n = p;
+	bool is_console = false;
+
+	KASSERT(device_is_a(dev, "sunxitcon"));
+	strncpy(p, pipeline, sizeof(p) - 1);
+	p[sizeof(p) - 1] = '\0';
+
+	/*
+	 * pipeline is like "de_be0-lcd0-hdmi"
+	 * of "de_be0-lcd1".
+	 * In the first case check output type
+	 * In the second check tcon unit number
+	 */
+	 n = p;
+	 e = strsep(&n, "-");
+	 if (e == NULL || memcmp(e, "de_be", 5) != 0)
+		goto bad;
+	 e = strsep(&n, "-");
+	 if (e == NULL)
+		goto bad;
+	 if (n == NULL) {
+		/* second case */
+		if (strcmp(e, "lcd0") == 0) {
+			if (sc->sc_unit == 0)
+				is_console = true;
+		 } else if (strcmp(e, "lcd1") == 0) {
+			if (sc->sc_unit == 1)
+				is_console = true;
+		} else
+			goto bad;
+		return is_console;
+	}
+	/* first case */
+	if (strcmp(n, "hdmi") == 0) {
+		if (sc->sc_output_type == OUTPUT_HDMI)
+			is_console = true;
+		return is_console;
+	}
+bad:
+	aprint_error("warning: can't parse pipeline %s\n", pipeline);
+	return is_console;
+}
+
 #if defined(DDB) || defined(SUNXI_TCON_DEBUG)
 void
 sunxi_tcon_dump_regs(int u)

Reply via email to