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)