diff options
| author | bouyer <bouyer@NetBSD.org> | 2018-04-07 18:09:33 +0000 |
|---|---|---|
| committer | bouyer <bouyer@NetBSD.org> | 2018-04-07 18:09:33 +0000 |
| commit | 99fdfc4fcd75e33edd4fbdf97eae23c19431f7ca (patch) | |
| tree | 0c69e1993b6a22aa5c7057ff17758f5aca4d5041 /sys/arch | |
| parent | a8b319e7e6e5b1243dc03a584213d7b3174bd3c9 (diff) | |
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.
Diffstat (limited to 'sys/arch')
| -rw-r--r-- | sys/arch/arm/sunxi/sunxi_debe.c | 101 | ||||
| -rw-r--r-- | sys/arch/arm/sunxi/sunxi_dep.c | 21 | ||||
| -rw-r--r-- | sys/arch/arm/sunxi/sunxi_display.h | 3 | ||||
| -rw-r--r-- | sys/arch/arm/sunxi/sunxi_tcon.c | 53 |
4 files changed, 155 insertions, 23 deletions
diff --git a/sys/arch/arm/sunxi/sunxi_debe.c b/sys/arch/arm/sunxi/sunxi_debe.c index 72e54657b7d..0b3ac9ee9e8 100644 --- a/sys/arch/arm/sunxi/sunxi_debe.c +++ b/sys/arch/arm/sunxi/sunxi_debe.c @@ -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 <bouyer@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,v 1.7 2018/04/05 10:21:39 jmcneill Exp #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_long, void *); 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, device_t self, void *aux) } } - - 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_softc *sc, const struct videomode *mode 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, device_t self, void *aux) 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, device_t self, void *aux) 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 active) 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) diff --git a/sys/arch/arm/sunxi/sunxi_dep.c b/sys/arch/arm/sunxi/sunxi_dep.c index e77f650951a..0b7be8f3ce7 100644 --- a/sys/arch/arm/sunxi/sunxi_dep.c +++ b/sys/arch/arm/sunxi/sunxi_dep.c @@ -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 compat_data[] = { {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_t cf, void *aux) { #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_t self, void *aux) 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_t self, void *aux) 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_t self, void *aux) 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; diff --git a/sys/arch/arm/sunxi/sunxi_display.h b/sys/arch/arm/sunxi/sunxi_display.h index 2320c988514..05db6031979 100644 --- a/sys/arch/arm/sunxi/sunxi_display.h +++ b/sys/arch/arm/sunxi/sunxi_display.h @@ -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 *); diff --git a/sys/arch/arm/sunxi/sunxi_tcon.c b/sys/arch/arm/sunxi/sunxi_tcon.c index 7aa4c09a5dd..35d43b8b302 100644 --- a/sys/arch/arm/sunxi/sunxi_tcon.c +++ b/sys/arch/arm/sunxi/sunxi_tcon.c @@ -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 <bouyer@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, const struct videomode *mode) } } +/* 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) |
