Module Name:    src
Committed By:   bouyer
Date:           Fri Jun  1 17:18:44 UTC 2018

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

Log Message:
Defer display hardware reset to pipeline activation. This way, if we have a
pipeline setup which we can't manage, the simple framebuffer will keep working.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/sunxi/sunxi_debe.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_display.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/sunxi/sunxi_hdmi.c
cvs rdiff -u -r1.6 -r1.7 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.8 src/sys/arch/arm/sunxi/sunxi_debe.c:1.9
--- src/sys/arch/arm/sunxi/sunxi_debe.c:1.8	Sat Apr  7 18:09:33 2018
+++ src/sys/arch/arm/sunxi/sunxi_debe.c	Fri Jun  1 17:18:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $ */
+/* $NetBSD: sunxi_debe.c,v 1.9 2018/06/01 17:18:44 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2018 Manuel Bouyer <[email protected]>
@@ -38,7 +38,7 @@
 #define SUNXI_DEBE_CURMAX	64
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.9 2018/06/01 17:18:44 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -77,6 +77,8 @@ struct sunxi_debe_softc {
 	struct clk *sc_clk_mod;
 	struct clk *sc_clk_ram;
 
+	struct fdtbus_reset *sc_rst;
+
 	bus_dma_segment_t sc_dmasegs[1];
 	bus_size_t sc_dmasize;
 	bus_dmamap_t sc_dmamap;
@@ -152,7 +154,6 @@ sunxi_debe_attach(device_t parent, devic
 	const int phandle = faa->faa_phandle;
 	bus_addr_t addr;
 	bus_size_t size;
-	struct fdtbus_reset *rst;
 	int error;
 
 	sc->sc_dev = self;
@@ -171,21 +172,6 @@ sunxi_debe_attach(device_t parent, devic
 	sc->sc_clk_mod = fdtbus_clock_get(phandle, "mod");
 	sc->sc_clk_ram = fdtbus_clock_get(phandle, "ram");
 
-	rst = fdtbus_reset_get_index(phandle, 0);
-	if (rst == NULL) {
-		aprint_error(": couldn't get reset\n");
-		return;
-	}
-	if (fdtbus_reset_assert(rst) != 0) {
-		aprint_error(": couldn't assert reset\n");
-		return;
-	}
-	delay(1);
-	if (fdtbus_reset_deassert(rst) != 0) {
-		aprint_error(": couldn't de-assert reset\n");
-		return;
-	}
-
 	if (sc->sc_clk_ahb == NULL || sc->sc_clk_mod == NULL
 	    || sc->sc_clk_ram == NULL) {
 		aprint_error(": couldn't get clocks\n");
@@ -196,20 +182,11 @@ sunxi_debe_attach(device_t parent, devic
 		return;
 	}
 
-	error = clk_set_rate(sc->sc_clk_mod, 300000000);
-	if (error) {
-		aprint_error("couln't set mod clock rate (%d)\n", error);
-		return;
-	}
-
-	if (clk_enable(sc->sc_clk_ahb) != 0 ||
-	    clk_enable(sc->sc_clk_mod) != 0) {
-		aprint_error(": couldn't enable clocks\n");
+	sc->sc_rst = fdtbus_reset_get_index(phandle, 0);
+	if (sc->sc_rst == NULL) {
+		aprint_error(": couldn't get reset\n");
 		return;
 	}
-	if (clk_disable(sc->sc_clk_ram) != 0) {
-		aprint_error(": couldn't disable ram clock\n");
-	}
 
 	sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
 
@@ -218,16 +195,8 @@ sunxi_debe_attach(device_t parent, devic
 	    fdtbus_get_string(phandle, "name"));
 
 
-	for (unsigned int reg = 0x800; reg < 0x1000; reg += 4) {
-		DEBE_WRITE(sc, reg, 0);
-	}
-
-	DEBE_WRITE(sc, SUNXI_DEBE_MODCTL_REG, SUNXI_DEBE_MODCTL_EN);
-
 	sc->sc_dmasize = SUNXI_DEBE_VIDEOMEM;
 
-	DEBE_WRITE(sc, SUNXI_DEBE_HWC_PALETTE_TABLE, 0);
-
 	error = sunxi_debe_alloc_videomem(sc);
 	if (error) {
 		aprint_error_dev(sc->sc_dev,
@@ -239,11 +208,61 @@ sunxi_debe_attach(device_t parent, devic
 	sc->sc_ports.dp_ep_connect = sunxi_debe_ep_connect;
 	sc->sc_ports.dp_ep_enable = sunxi_debe_ep_enable;
 	fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER);
+}
 
-	if (clk_disable(sc->sc_clk_ahb) != 0 ||
-	    clk_disable(sc->sc_clk_mod) != 0) {
-		aprint_error(": couldn't disable clocks\n");
-		return;
+static void
+sunxi_debe_doreset(void)
+{
+	device_t dev;
+	struct sunxi_debe_softc *sc;
+	int error;
+
+	for (int i = 0;;i++) {
+		dev = device_find_by_driver_unit("sunxidebe", i);
+		if (dev == NULL)
+			return;
+		sc = device_private(dev);
+
+		if (fdtbus_reset_assert(sc->sc_rst) != 0) {
+			aprint_error_dev(dev, ": couldn't assert reset\n");
+			return;
+		}
+		delay(1);
+		if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
+			aprint_error_dev(dev, ": couldn't de-assert reset\n");
+			return;
+		}
+
+
+		error = clk_set_rate(sc->sc_clk_mod, 300000000);
+		if (error) {
+			aprint_error_dev(dev,
+			    "couln't set mod clock rate (%d)\n", error);
+			return;
+		}
+
+		if (clk_enable(sc->sc_clk_ahb) != 0 ||
+		    clk_enable(sc->sc_clk_mod) != 0) {
+			aprint_error_dev(dev, ": couldn't enable clocks\n");
+			return;
+		}
+		if (clk_disable(sc->sc_clk_ram) != 0) {
+			aprint_error_dev(dev, ": couldn't disable ram clock\n");
+		}
+
+		for (unsigned int reg = 0x800; reg < 0x1000; reg += 4) {
+			DEBE_WRITE(sc, reg, 0);
+		}
+
+		DEBE_WRITE(sc, SUNXI_DEBE_MODCTL_REG, SUNXI_DEBE_MODCTL_EN);
+
+		DEBE_WRITE(sc, SUNXI_DEBE_HWC_PALETTE_TABLE, 0);
+
+		if (clk_disable(sc->sc_clk_ahb) != 0 ||
+		    clk_disable(sc->sc_clk_mod) != 0) {
+			aprint_error_dev(sc->sc_dev,
+			    ": couldn't disable clocks\n");
+		}
 	}
 }
 
@@ -841,6 +860,7 @@ sunxi_debe_pipeline(int phandle, bool ac
 	struct sunxi_debe_softc *sc;
 	struct fdt_endpoint *ep;
 	int i, error;
+	static bool reset_done = false;
 
 	if (!active)
 		return EOPNOTSUPP;
@@ -853,6 +873,13 @@ sunxi_debe_pipeline(int phandle, bool ac
 		if (sc->sc_phandle == phandle)
 			break;
 	}
+	if (!reset_done) {
+		sunxi_debe_doreset();
+		sunxi_tcon_doreset();
+		sunxi_hdmi_doreset();
+		reset_done = true;
+	}
+
 	aprint_normal("activate %s\n", device_xname(dev));
 	if (clk_enable(sc->sc_clk_ahb) != 0 ||
 	    clk_enable(sc->sc_clk_mod) != 0) {

Index: src/sys/arch/arm/sunxi/sunxi_display.h
diff -u src/sys/arch/arm/sunxi/sunxi_display.h:1.2 src/sys/arch/arm/sunxi/sunxi_display.h:1.3
--- src/sys/arch/arm/sunxi/sunxi_display.h:1.2	Sat Apr  7 18:09:33 2018
+++ src/sys/arch/arm/sunxi/sunxi_display.h	Fri Jun  1 17:18:44 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: sunxi_display.h,v 1.2 2018/04/07 18:09:33 bouyer Exp $	*/
+/*	$NetBSD: sunxi_display.h,v 1.3 2018/06/01 17:18:44 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -38,3 +38,6 @@ 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 *);
+
+void sunxi_tcon_doreset(void);
+void sunxi_hdmi_doreset(void);

Index: src/sys/arch/arm/sunxi/sunxi_hdmi.c
diff -u src/sys/arch/arm/sunxi/sunxi_hdmi.c:1.3 src/sys/arch/arm/sunxi/sunxi_hdmi.c:1.4
--- src/sys/arch/arm/sunxi/sunxi_hdmi.c:1.3	Tue Apr  3 16:17:59 2018
+++ src/sys/arch/arm/sunxi/sunxi_hdmi.c	Fri Jun  1 17:18:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_hdmi.c,v 1.3 2018/04/03 16:17:59 bouyer Exp $ */
+/* $NetBSD: sunxi_hdmi.c,v 1.4 2018/06/01 17:18:44 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <[email protected]>
@@ -29,7 +29,7 @@
 #include "opt_ddb.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.3 2018/04/03 16:17:59 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.4 2018/06/01 17:18:44 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -165,7 +165,6 @@ sunxi_hdmi_attach(device_t parent, devic
 	bus_addr_t addr;
 	bus_size_t size;
 	uint32_t ver;
-	int error;
 
 	sc->sc_dev = self;
 	sc->sc_phandle = phandle;
@@ -197,28 +196,10 @@ sunxi_hdmi_attach(device_t parent, devic
 		return;
 	}
 
-	error = clk_disable(sc->sc_clk_mod);
-	if (error) {
-		aprint_error(": couldn't disable mod clock\n");
-		return;
-	}
-
 	if (clk_enable(sc->sc_clk_ahb) != 0) {
 		aprint_error(": couldn't enable ahb clock\n");
 		return;
 	}
-#if defined(SUNXI_HDMI_DEBUG)
-	sunxi_hdmi_dump_regs();
-#endif
-
-	/*
-	 * reset device, in case it has been setup by firmware in an
-	 * incompatible way
-	 */
-	for (int i = 0; i <= 0x500; i += 4) {
-		HDMI_WRITE(sc, i, 0);
-	}
-
 	ver = HDMI_READ(sc, SUNXI_HDMI_VERSION_ID_REG);
 
 	const int vmaj = __SHIFTOUT(ver, SUNXI_HDMI_VERSION_ID_H);
@@ -236,10 +217,43 @@ sunxi_hdmi_attach(device_t parent, devic
 
 	mutex_init(&sc->sc_pwr_lock, MUTEX_DEFAULT, IPL_NONE);
 	sunxi_hdmi_i2c_init(sc);
+}
 
-	if (clk_disable(sc->sc_clk_ahb) != 0) {
-		aprint_error(": couldn't disable ahb clock\n");
-		return;
+void
+sunxi_hdmi_doreset(void)
+{
+	device_t dev;
+	struct sunxi_hdmi_softc *sc;
+	int error;
+
+	for (int i = 0;;i++) {
+		dev = device_find_by_driver_unit("sunxihdmi", i);
+		if (dev == NULL)
+			return;
+		sc = device_private(dev);
+	
+		error = clk_disable(sc->sc_clk_mod);
+		if (error) {
+			aprint_error_dev(dev, ": couldn't disable mod clock\n");
+			return;
+		}
+
+#if defined(SUNXI_HDMI_DEBUG)
+		sunxi_hdmi_dump_regs();
+#endif
+
+		/*
+		 * reset device, in case it has been setup by firmware in an
+		 * incompatible way
+		 */
+		for (int j = 0; j <= 0x500; j += 4) {
+			HDMI_WRITE(sc, j, 0);
+		}
+
+		if (clk_disable(sc->sc_clk_ahb) != 0) {
+			aprint_error_dev(dev, ": couldn't disable ahb clock\n");
+			return;
+		}
 	}
 }
 

Index: src/sys/arch/arm/sunxi/sunxi_tcon.c
diff -u src/sys/arch/arm/sunxi/sunxi_tcon.c:1.6 src/sys/arch/arm/sunxi/sunxi_tcon.c:1.7
--- src/sys/arch/arm/sunxi/sunxi_tcon.c:1.6	Sat Apr  7 18:09:33 2018
+++ src/sys/arch/arm/sunxi/sunxi_tcon.c	Fri Jun  1 17:18:44 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $ */
+/* $NetBSD: sunxi_tcon.c,v 1.7 2018/06/01 17:18:44 bouyer Exp $ */
 
 /*-
  * Copyright (c) 2018 Manuel Bouyer <[email protected]>
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.7 2018/06/01 17:18:44 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -65,6 +65,7 @@ struct sunxi_tcon_softc {
 	struct clk *sc_clk_ahb;
 	struct clk *sc_clk_ch0;
 	struct clk *sc_clk_ch1;
+	struct fdtbus_reset *sc_rst, *sc_lvds_rst;
 	unsigned int sc_output_type;
 #define OUTPUT_HDMI 0
 #define OUTPUT_LVDS 1
@@ -120,8 +121,6 @@ sunxi_tcon_attach(device_t parent, devic
 	const int phandle = faa->faa_phandle;
 	bus_addr_t addr;
 	bus_size_t size;
-	struct fdtbus_reset *rst, *lvds_rst;
-
 
 	sc->sc_dev = self;
 	sc->sc_phandle = phandle;
@@ -149,54 +148,13 @@ sunxi_tcon_attach(device_t parent, devic
 		return;
 	}
 
-	rst = fdtbus_reset_get(phandle, "lcd");
-	if (rst == NULL) {
+	sc->sc_rst = fdtbus_reset_get(phandle, "lcd");
+	if (sc->sc_rst == NULL) {
 		aprint_error(": couldn't get lcd reset\n");
 		return;
 	}
 
-	lvds_rst = fdtbus_reset_get(phandle, "lvds");
-
-	if (clk_disable(sc->sc_clk_ahb) != 0) {
-		aprint_error(": couldn't disable ahb clock\n");
-		return;
-	}
-	if (clk_disable(sc->sc_clk_ch0) != 0) {
-		aprint_error(": couldn't disable ch0 clock\n");
-		return;
-	}
-
-	if (clk_disable(sc->sc_clk_ch1) != 0) {
-		aprint_error(": couldn't disable ch1 clock\n");
-		return;
-	}
-
-	if (fdtbus_reset_assert(rst) != 0) {
-		aprint_error(": couldn't assert lcd reset\n");
-		return;
-	}
-	if (lvds_rst != NULL) {
-		if (fdtbus_reset_assert(lvds_rst) != 0) {
-			aprint_error(": couldn't assert lvds reset\n");
-			return;
-		}
-	}
-	delay(1);
-	if (fdtbus_reset_deassert(rst) != 0) {
-		aprint_error(": couldn't de-assert lcd reset\n");
-		return;
-	}
-	if (lvds_rst != NULL) {
-		if (fdtbus_reset_deassert(lvds_rst) != 0) {
-			aprint_error(": couldn't de-assert lvds reset\n");
-			return;
-		}
-	}
-
-	if (clk_enable(sc->sc_clk_ahb) != 0) {
-		aprint_error(": couldn't enable ahb clock\n");
-		return;
-	}
+	sc->sc_lvds_rst = fdtbus_reset_get(phandle, "lvds");
 
 	sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
 
@@ -209,24 +167,82 @@ sunxi_tcon_attach(device_t parent, devic
 	sc->sc_ports.dp_ep_activate = sunxi_tcon_ep_activate;
 	sc->sc_ports.dp_ep_enable = sunxi_tcon_ep_enable;
 	fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER);
+}
 
-	TCON_WRITE(sc, SUNXI_TCON_GINT0_REG, 0);
-	TCON_WRITE(sc, SUNXI_TCON_GINT1_REG,
-	    __SHIFTIN(0x20, SUNXI_TCON_GINT1_TCON0_LINENO));
-	TCON_WRITE(sc, SUNXI_TCON0_DCLK_REG, 0xf0000000);
-	TCON_WRITE(sc, SUNXI_TCON0_LVDS_IF_REG, 0x0);
-	TCON_WRITE(sc, SUNXI_TCON0_CTL_REG, 0);
-	TCON_WRITE(sc, SUNXI_TCON0_IO_TRI_REG, 0xffffffff);
-	TCON_WRITE(sc, SUNXI_TCON1_CTL_REG, 0);
-	TCON_WRITE(sc, SUNXI_TCON1_IO_TRI_REG, 0xffffffff);
-	TCON_WRITE(sc, SUNXI_TCON_GCTL_REG, 0);
+void
+sunxi_tcon_doreset(void)
+{
+	device_t dev;
+	struct sunxi_tcon_softc *sc;
+	for (int i = 0;;i++) {
+		dev = device_find_by_driver_unit("sunxitcon", i);
+		if (dev == NULL)
+			return;
+		sc = device_private(dev);
 
-	/* clock needed for the mux in unit 0 */
-	if (sc->sc_unit != 0) {
 		if (clk_disable(sc->sc_clk_ahb) != 0) {
-			aprint_error(": couldn't disable ahb clock\n");
+			aprint_error_dev(dev, ": couldn't disable ahb clock\n");
+			return;
+		}
+		if (clk_disable(sc->sc_clk_ch0) != 0) {
+			aprint_error_dev(dev, ": couldn't disable ch0 clock\n");
+			return;
+		}
+
+		if (clk_disable(sc->sc_clk_ch1) != 0) {
+			aprint_error_dev(dev, ": couldn't disable ch1 clock\n");
+			return;
+		}
+
+		if (fdtbus_reset_assert(sc->sc_rst) != 0) {
+			aprint_error_dev(dev, ": couldn't assert lcd reset\n");
+			return;
+		}
+		if (sc->sc_lvds_rst != NULL) {
+			if (fdtbus_reset_assert(sc->sc_lvds_rst) != 0) {
+				aprint_error_dev(dev,
+				    ": couldn't assert lvds reset\n");
+				return;
+			}
+		}
+		delay(1);
+		if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
+			aprint_error_dev(dev,
+			    ": couldn't de-assert lcd reset\n");
 			return;
 		}
+		if (sc->sc_lvds_rst != NULL) {
+			if (fdtbus_reset_deassert(sc->sc_lvds_rst) != 0) {
+				aprint_error_dev(dev,
+				    ": couldn't de-assert lvds reset\n");
+				return;
+			}
+		}
+
+		if (clk_enable(sc->sc_clk_ahb) != 0) {
+			aprint_error_dev(dev, ": couldn't enable ahb clock\n");
+			return;
+		}
+
+		TCON_WRITE(sc, SUNXI_TCON_GINT0_REG, 0);
+		TCON_WRITE(sc, SUNXI_TCON_GINT1_REG,
+		    __SHIFTIN(0x20, SUNXI_TCON_GINT1_TCON0_LINENO));
+		TCON_WRITE(sc, SUNXI_TCON0_DCLK_REG, 0xf0000000);
+		TCON_WRITE(sc, SUNXI_TCON0_LVDS_IF_REG, 0x0);
+		TCON_WRITE(sc, SUNXI_TCON0_CTL_REG, 0);
+		TCON_WRITE(sc, SUNXI_TCON0_IO_TRI_REG, 0xffffffff);
+		TCON_WRITE(sc, SUNXI_TCON1_CTL_REG, 0);
+		TCON_WRITE(sc, SUNXI_TCON1_IO_TRI_REG, 0xffffffff);
+		TCON_WRITE(sc, SUNXI_TCON_GCTL_REG, 0);
+
+		/* clock needed for the mux in unit 0 */
+		if (sc->sc_unit != 0) {
+			if (clk_disable(sc->sc_clk_ahb) != 0) {
+				aprint_error_dev(dev,
+				    ": couldn't disable ahb clock\n");
+				return;
+			}
+		}
 	}
 }
 

Reply via email to