Fri Jun 1 17:18:44 2018 UTC ()
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.


(bouyer)
diff -r1.8 -r1.9 src/sys/arch/arm/sunxi/sunxi_debe.c
diff -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_display.h
diff -r1.3 -r1.4 src/sys/arch/arm/sunxi/sunxi_hdmi.c
diff -r1.6 -r1.7 src/sys/arch/arm/sunxi/sunxi_tcon.c

cvs diff -r1.8 -r1.9 src/sys/arch/arm/sunxi/sunxi_debe.c (expand / switch to unified diff)

--- src/sys/arch/arm/sunxi/sunxi_debe.c 2018/04/07 18:09:33 1.8
+++ src/sys/arch/arm/sunxi/sunxi_debe.c 2018/06/01 17:18:44 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $ */ 1/* $NetBSD: sunxi_debe.c,v 1.9 2018/06/01 17:18:44 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Manuel Bouyer <bouyer@antioche.eu.org> 4 * Copyright (c) 2018 Manuel Bouyer <bouyer@antioche.eu.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 7 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -28,27 +28,27 @@ @@ -28,27 +28,27 @@
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include "genfb.h" 32#include "genfb.h"
33 33
34#ifndef SUNXI_DEBE_VIDEOMEM 34#ifndef SUNXI_DEBE_VIDEOMEM
35#define SUNXI_DEBE_VIDEOMEM (16 * 1024 * 1024) 35#define SUNXI_DEBE_VIDEOMEM (16 * 1024 * 1024)
36#endif 36#endif
37 37
38#define SUNXI_DEBE_CURMAX 64 38#define SUNXI_DEBE_CURMAX 64
39 39
40#include <sys/cdefs.h> 40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.8 2018/04/07 18:09:33 bouyer Exp $"); 41__KERNEL_RCSID(0, "$NetBSD: sunxi_debe.c,v 1.9 2018/06/01 17:18:44 bouyer Exp $");
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/bus.h> 44#include <sys/bus.h>
45#include <sys/device.h> 45#include <sys/device.h>
46#include <sys/intr.h> 46#include <sys/intr.h>
47#include <sys/systm.h> 47#include <sys/systm.h>
48#include <sys/kernel.h> 48#include <sys/kernel.h>
49#include <sys/mutex.h> 49#include <sys/mutex.h>
50#include <sys/condvar.h> 50#include <sys/condvar.h>
51 51
52#include <dev/fdt/fdtvar.h> 52#include <dev/fdt/fdtvar.h>
53#include <dev/fdt/fdt_port.h> 53#include <dev/fdt/fdt_port.h>
54 54
@@ -67,26 +67,28 @@ enum sunxi_debe_type { @@ -67,26 +67,28 @@ enum sunxi_debe_type {
67 67
68struct sunxi_debe_softc { 68struct sunxi_debe_softc {
69 device_t sc_dev; 69 device_t sc_dev;
70 device_t sc_fbdev; 70 device_t sc_fbdev;
71 enum sunxi_debe_type sc_type; 71 enum sunxi_debe_type sc_type;
72 bus_space_tag_t sc_bst; 72 bus_space_tag_t sc_bst;
73 bus_space_handle_t sc_bsh; 73 bus_space_handle_t sc_bsh;
74 bus_dma_tag_t sc_dmat; 74 bus_dma_tag_t sc_dmat;
75 75
76 struct clk *sc_clk_ahb; 76 struct clk *sc_clk_ahb;
77 struct clk *sc_clk_mod; 77 struct clk *sc_clk_mod;
78 struct clk *sc_clk_ram; 78 struct clk *sc_clk_ram;
79 79
 80 struct fdtbus_reset *sc_rst;
 81
80 bus_dma_segment_t sc_dmasegs[1]; 82 bus_dma_segment_t sc_dmasegs[1];
81 bus_size_t sc_dmasize; 83 bus_size_t sc_dmasize;
82 bus_dmamap_t sc_dmamap; 84 bus_dmamap_t sc_dmamap;
83 void *sc_dmap; 85 void *sc_dmap;
84 86
85 bool sc_cursor_enable; 87 bool sc_cursor_enable;
86 int sc_cursor_x, sc_cursor_y; 88 int sc_cursor_x, sc_cursor_y;
87 int sc_hot_x, sc_hot_y; 89 int sc_hot_x, sc_hot_y;
88 uint8_t sc_cursor_bitmap[8 * SUNXI_DEBE_CURMAX]; 90 uint8_t sc_cursor_bitmap[8 * SUNXI_DEBE_CURMAX];
89 uint8_t sc_cursor_mask[8 * SUNXI_DEBE_CURMAX]; 91 uint8_t sc_cursor_mask[8 * SUNXI_DEBE_CURMAX];
90 92
91 int sc_phandle; 93 int sc_phandle;
92 struct fdt_device_ports sc_ports; 94 struct fdt_device_ports sc_ports;
@@ -142,118 +144,135 @@ sunxi_debe_match(device_t parent, cfdata @@ -142,118 +144,135 @@ sunxi_debe_match(device_t parent, cfdata
142 struct fdt_attach_args * const faa = aux; 144 struct fdt_attach_args * const faa = aux;
143 145
144 return of_match_compat_data(faa->faa_phandle, compat_data); 146 return of_match_compat_data(faa->faa_phandle, compat_data);
145} 147}
146 148
147static void 149static void
148sunxi_debe_attach(device_t parent, device_t self, void *aux) 150sunxi_debe_attach(device_t parent, device_t self, void *aux)
149{ 151{
150 struct sunxi_debe_softc *sc = device_private(self); 152 struct sunxi_debe_softc *sc = device_private(self);
151 struct fdt_attach_args * const faa = aux; 153 struct fdt_attach_args * const faa = aux;
152 const int phandle = faa->faa_phandle; 154 const int phandle = faa->faa_phandle;
153 bus_addr_t addr; 155 bus_addr_t addr;
154 bus_size_t size; 156 bus_size_t size;
155 struct fdtbus_reset *rst; 
156 int error; 157 int error;
157 158
158 sc->sc_dev = self; 159 sc->sc_dev = self;
159 sc->sc_phandle = phandle; 160 sc->sc_phandle = phandle;
160 sc->sc_bst = faa->faa_bst; 161 sc->sc_bst = faa->faa_bst;
161 sc->sc_dmat = faa->faa_dmat; 162 sc->sc_dmat = faa->faa_dmat;
162 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 163 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
163 aprint_error(": couldn't get registers\n"); 164 aprint_error(": couldn't get registers\n");
164 } 165 }
165 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 166 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
166 aprint_error(": couldn't map registers\n"); 167 aprint_error(": couldn't map registers\n");
167 return; 168 return;
168 } 169 }
169 170
170 sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb"); 171 sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb");
171 sc->sc_clk_mod = fdtbus_clock_get(phandle, "mod"); 172 sc->sc_clk_mod = fdtbus_clock_get(phandle, "mod");
172 sc->sc_clk_ram = fdtbus_clock_get(phandle, "ram"); 173 sc->sc_clk_ram = fdtbus_clock_get(phandle, "ram");
173 174
174 rst = fdtbus_reset_get_index(phandle, 0); 
175 if (rst == NULL) { 
176 aprint_error(": couldn't get reset\n"); 
177 return; 
178 } 
179 if (fdtbus_reset_assert(rst) != 0) { 
180 aprint_error(": couldn't assert reset\n"); 
181 return; 
182 } 
183 delay(1); 
184 if (fdtbus_reset_deassert(rst) != 0) { 
185 aprint_error(": couldn't de-assert reset\n"); 
186 return; 
187 } 
188 
189 if (sc->sc_clk_ahb == NULL || sc->sc_clk_mod == NULL 175 if (sc->sc_clk_ahb == NULL || sc->sc_clk_mod == NULL
190 || sc->sc_clk_ram == NULL) { 176 || sc->sc_clk_ram == NULL) {
191 aprint_error(": couldn't get clocks\n"); 177 aprint_error(": couldn't get clocks\n");
192 aprint_debug_dev(self, "clk ahb %s mod %s ram %s\n", 178 aprint_debug_dev(self, "clk ahb %s mod %s ram %s\n",
193 sc->sc_clk_ahb == NULL ? "missing" : "present", 179 sc->sc_clk_ahb == NULL ? "missing" : "present",
194 sc->sc_clk_mod == NULL ? "missing" : "present", 180 sc->sc_clk_mod == NULL ? "missing" : "present",
195 sc->sc_clk_ram == NULL ? "missing" : "present"); 181 sc->sc_clk_ram == NULL ? "missing" : "present");
196 return; 182 return;
197 } 183 }
198 184
199 error = clk_set_rate(sc->sc_clk_mod, 300000000); 185 sc->sc_rst = fdtbus_reset_get_index(phandle, 0);
200 if (error) { 186 if (sc->sc_rst == NULL) {
201 aprint_error("couln't set mod clock rate (%d)\n", error); 187 aprint_error(": couldn't get reset\n");
202 return; 
203 } 
204 
205 if (clk_enable(sc->sc_clk_ahb) != 0 || 
206 clk_enable(sc->sc_clk_mod) != 0) { 
207 aprint_error(": couldn't enable clocks\n"); 
208 return; 188 return;
209 } 189 }
210 if (clk_disable(sc->sc_clk_ram) != 0) { 
211 aprint_error(": couldn't disable ram clock\n"); 
212 } 
213 190
214 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data; 191 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
215 192
216 aprint_naive("\n"); 193 aprint_naive("\n");
217 aprint_normal(": Display Engine Backend (%s)\n", 194 aprint_normal(": Display Engine Backend (%s)\n",
218 fdtbus_get_string(phandle, "name")); 195 fdtbus_get_string(phandle, "name"));
219 196
220 197
221 for (unsigned int reg = 0x800; reg < 0x1000; reg += 4) { 
222 DEBE_WRITE(sc, reg, 0); 
223 } 
224 
225 DEBE_WRITE(sc, SUNXI_DEBE_MODCTL_REG, SUNXI_DEBE_MODCTL_EN); 
226 
227 sc->sc_dmasize = SUNXI_DEBE_VIDEOMEM; 198 sc->sc_dmasize = SUNXI_DEBE_VIDEOMEM;
228 199
229 DEBE_WRITE(sc, SUNXI_DEBE_HWC_PALETTE_TABLE, 0); 
230 
231 error = sunxi_debe_alloc_videomem(sc); 200 error = sunxi_debe_alloc_videomem(sc);
232 if (error) { 201 if (error) {
233 aprint_error_dev(sc->sc_dev, 202 aprint_error_dev(sc->sc_dev,
234 "couldn't allocate video memory, error = %d\n", error); 203 "couldn't allocate video memory, error = %d\n", error);
235 return; 204 return;
236 } 205 }
237 206
238 sc->sc_unit = -1; 207 sc->sc_unit = -1;
239 sc->sc_ports.dp_ep_connect = sunxi_debe_ep_connect; 208 sc->sc_ports.dp_ep_connect = sunxi_debe_ep_connect;
240 sc->sc_ports.dp_ep_enable = sunxi_debe_ep_enable; 209 sc->sc_ports.dp_ep_enable = sunxi_debe_ep_enable;
241 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER); 210 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER);
 211}
242 212
243 if (clk_disable(sc->sc_clk_ahb) != 0 || 213static void
244 clk_disable(sc->sc_clk_mod) != 0) { 214sunxi_debe_doreset(void)
245 aprint_error(": couldn't disable clocks\n"); 215{
246 return; 216 device_t dev;
 217 struct sunxi_debe_softc *sc;
 218 int error;
 219
 220 for (int i = 0;;i++) {
 221 dev = device_find_by_driver_unit("sunxidebe", i);
 222 if (dev == NULL)
 223 return;
 224 sc = device_private(dev);
 225
 226 if (fdtbus_reset_assert(sc->sc_rst) != 0) {
 227 aprint_error_dev(dev, ": couldn't assert reset\n");
 228 return;
 229 }
 230 delay(1);
 231 if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
 232 aprint_error_dev(dev, ": couldn't de-assert reset\n");
 233 return;
 234 }
 235
 236
 237 error = clk_set_rate(sc->sc_clk_mod, 300000000);
 238 if (error) {
 239 aprint_error_dev(dev,
 240 "couln't set mod clock rate (%d)\n", error);
 241 return;
 242 }
 243
 244 if (clk_enable(sc->sc_clk_ahb) != 0 ||
 245 clk_enable(sc->sc_clk_mod) != 0) {
 246 aprint_error_dev(dev, ": couldn't enable clocks\n");
 247 return;
 248 }
 249 if (clk_disable(sc->sc_clk_ram) != 0) {
 250 aprint_error_dev(dev, ": couldn't disable ram clock\n");
 251 }
 252
 253 for (unsigned int reg = 0x800; reg < 0x1000; reg += 4) {
 254 DEBE_WRITE(sc, reg, 0);
 255 }
 256
 257 DEBE_WRITE(sc, SUNXI_DEBE_MODCTL_REG, SUNXI_DEBE_MODCTL_EN);
 258
 259 DEBE_WRITE(sc, SUNXI_DEBE_HWC_PALETTE_TABLE, 0);
 260
 261 if (clk_disable(sc->sc_clk_ahb) != 0 ||
 262 clk_disable(sc->sc_clk_mod) != 0) {
 263 aprint_error_dev(sc->sc_dev,
 264 ": couldn't disable clocks\n");
 265 }
247 } 266 }
248} 267}
249 268
250static void 269static void
251sunxi_debe_ep_connect(device_t self, struct fdt_endpoint *ep, bool connect) 270sunxi_debe_ep_connect(device_t self, struct fdt_endpoint *ep, bool connect)
252{ 271{
253 struct sunxi_debe_softc *sc = device_private(self); 272 struct sunxi_debe_softc *sc = device_private(self);
254 struct fdt_endpoint *rep = fdt_endpoint_remote(ep); 273 struct fdt_endpoint *rep = fdt_endpoint_remote(ep);
255 int rep_idx = fdt_endpoint_index(rep); 274 int rep_idx = fdt_endpoint_index(rep);
256 275
257 KASSERT(device_is_a(self, "sunxidebe")); 276 KASSERT(device_is_a(self, "sunxidebe"));
258 if (!connect) { 277 if (!connect) {
259 aprint_error_dev(self, "endpoint disconnect not supported\n"); 278 aprint_error_dev(self, "endpoint disconnect not supported\n");
@@ -831,38 +850,46 @@ sunxi_befb_set_videomode(device_t dev, u @@ -831,38 +850,46 @@ sunxi_befb_set_videomode(device_t dev, u
831 if (sc->sc_gen.sc_width != width || sc->sc_gen.sc_height != height) { 850 if (sc->sc_gen.sc_width != width || sc->sc_gen.sc_height != height) {
832 device_printf(sc->sc_gen.sc_dev, 851 device_printf(sc->sc_gen.sc_dev,
833 "mode switching not yet supported\n"); 852 "mode switching not yet supported\n");
834 } 853 }
835} 854}
836 855
837int 856int
838sunxi_debe_pipeline(int phandle, bool active) 857sunxi_debe_pipeline(int phandle, bool active)
839{ 858{
840 device_t dev; 859 device_t dev;
841 struct sunxi_debe_softc *sc; 860 struct sunxi_debe_softc *sc;
842 struct fdt_endpoint *ep; 861 struct fdt_endpoint *ep;
843 int i, error; 862 int i, error;
 863 static bool reset_done = false;
844 864
845 if (!active) 865 if (!active)
846 return EOPNOTSUPP; 866 return EOPNOTSUPP;
847 867
848 for (i = 0;;i++) { 868 for (i = 0;;i++) {
849 dev = device_find_by_driver_unit("sunxidebe", i); 869 dev = device_find_by_driver_unit("sunxidebe", i);
850 if (dev == NULL) 870 if (dev == NULL)
851 return ENODEV; 871 return ENODEV;
852 sc = device_private(dev); 872 sc = device_private(dev);
853 if (sc->sc_phandle == phandle) 873 if (sc->sc_phandle == phandle)
854 break; 874 break;
855 } 875 }
 876 if (!reset_done) {
 877 sunxi_debe_doreset();
 878 sunxi_tcon_doreset();
 879 sunxi_hdmi_doreset();
 880 reset_done = true;
 881 }
 882
856 aprint_normal("activate %s\n", device_xname(dev)); 883 aprint_normal("activate %s\n", device_xname(dev));
857 if (clk_enable(sc->sc_clk_ahb) != 0 || 884 if (clk_enable(sc->sc_clk_ahb) != 0 ||
858 clk_enable(sc->sc_clk_mod) != 0) { 885 clk_enable(sc->sc_clk_mod) != 0) {
859 aprint_error_dev(dev, "couldn't enable clocks\n"); 886 aprint_error_dev(dev, "couldn't enable clocks\n");
860 return EIO; 887 return EIO;
861 } 888 }
862 /* connect debd0 to tcon0, debe1 to tcon1 */ 889 /* connect debd0 to tcon0, debe1 to tcon1 */
863 ep = fdt_endpoint_get_from_index(&sc->sc_ports, SUNXI_PORT_OUTPUT, 890 ep = fdt_endpoint_get_from_index(&sc->sc_ports, SUNXI_PORT_OUTPUT,
864 sc->sc_unit); 891 sc->sc_unit);
865 if (ep == NULL) { 892 if (ep == NULL) {
866 aprint_error_dev(dev, "no output endpoint for %d\n", 893 aprint_error_dev(dev, "no output endpoint for %d\n",
867 sc->sc_unit); 894 sc->sc_unit);
868 return ENODEV; 895 return ENODEV;

cvs diff -r1.2 -r1.3 src/sys/arch/arm/sunxi/sunxi_display.h (expand / switch to unified diff)

--- src/sys/arch/arm/sunxi/sunxi_display.h 2018/04/07 18:09:33 1.2
+++ src/sys/arch/arm/sunxi/sunxi_display.h 2018/06/01 17:18:44 1.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sunxi_display.h,v 1.2 2018/04/07 18:09:33 bouyer Exp $ */ 1/* $NetBSD: sunxi_display.h,v 1.3 2018/06/01 17:18:44 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Manuel Bouyer. 8 * by Manuel Bouyer.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -28,13 +28,16 @@ @@ -28,13 +28,16 @@
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32 32
33#define SUNXI_PORT_INPUT 0 33#define SUNXI_PORT_INPUT 0
34#define SUNXI_PORT_OUTPUT 1 34#define SUNXI_PORT_OUTPUT 1
35 35
36struct videomode; 36struct videomode;
37int sunxi_debe_pipeline(int, bool); 37int sunxi_debe_pipeline(int, bool);
38void sunxi_tcon1_set_videomode(device_t, const struct videomode *); 38void sunxi_tcon1_set_videomode(device_t, const struct videomode *);
39void sunxi_debe_set_videomode(device_t, const struct videomode *); 39void sunxi_debe_set_videomode(device_t, const struct videomode *);
40bool sunxi_tcon_is_console(device_t, const char *); 40bool sunxi_tcon_is_console(device_t, const char *);
 41
 42void sunxi_tcon_doreset(void);
 43void sunxi_hdmi_doreset(void);

cvs diff -r1.3 -r1.4 src/sys/arch/arm/sunxi/sunxi_hdmi.c (expand / switch to unified diff)

--- src/sys/arch/arm/sunxi/sunxi_hdmi.c 2018/04/03 16:17:59 1.3
+++ src/sys/arch/arm/sunxi/sunxi_hdmi.c 2018/06/01 17:18:44 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sunxi_hdmi.c,v 1.3 2018/04/03 16:17:59 bouyer Exp $ */ 1/* $NetBSD: sunxi_hdmi.c,v 1.4 2018/06/01 17:18:44 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_ddb.h" 29#include "opt_ddb.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.3 2018/04/03 16:17:59 bouyer Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: sunxi_hdmi.c,v 1.4 2018/06/01 17:18:44 bouyer Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/intr.h> 37#include <sys/intr.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40#include <sys/proc.h> 40#include <sys/proc.h>
41#include <sys/mutex.h> 41#include <sys/mutex.h>
42#include <sys/kthread.h> 42#include <sys/kthread.h>
43 43
44#include <dev/fdt/fdtvar.h> 44#include <dev/fdt/fdtvar.h>
45#include <dev/fdt/fdt_port.h> 45#include <dev/fdt/fdt_port.h>
@@ -155,27 +155,26 @@ sunxi_hdmi_match(device_t parent, cfdata @@ -155,27 +155,26 @@ sunxi_hdmi_match(device_t parent, cfdata
155 155
156 return of_match_compat_data(faa->faa_phandle, compat_data); 156 return of_match_compat_data(faa->faa_phandle, compat_data);
157} 157}
158 158
159static void 159static void
160sunxi_hdmi_attach(device_t parent, device_t self, void *aux) 160sunxi_hdmi_attach(device_t parent, device_t self, void *aux)
161{ 161{
162 struct sunxi_hdmi_softc *sc = device_private(self); 162 struct sunxi_hdmi_softc *sc = device_private(self);
163 struct fdt_attach_args * const faa = aux; 163 struct fdt_attach_args * const faa = aux;
164 const int phandle = faa->faa_phandle; 164 const int phandle = faa->faa_phandle;
165 bus_addr_t addr; 165 bus_addr_t addr;
166 bus_size_t size; 166 bus_size_t size;
167 uint32_t ver; 167 uint32_t ver;
168 int error; 
169 168
170 sc->sc_dev = self; 169 sc->sc_dev = self;
171 sc->sc_phandle = phandle; 170 sc->sc_phandle = phandle;
172 sc->sc_bst = faa->faa_bst; 171 sc->sc_bst = faa->faa_bst;
173 172
174 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data; 173 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
175 174
176 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 175 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
177 aprint_error(": couldn't get registers\n"); 176 aprint_error(": couldn't get registers\n");
178 } 177 }
179 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 178 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
180 aprint_error(": couldn't map registers\n"); 179 aprint_error(": couldn't map registers\n");
181 return; 180 return;
@@ -187,69 +186,84 @@ sunxi_hdmi_attach(device_t parent, devic @@ -187,69 +186,84 @@ sunxi_hdmi_attach(device_t parent, devic
187 sc->sc_clk_pll1 = fdtbus_clock_get(phandle, "pll-1"); 186 sc->sc_clk_pll1 = fdtbus_clock_get(phandle, "pll-1");
188 187
189 if (sc->sc_clk_ahb == NULL || sc->sc_clk_mod == NULL 188 if (sc->sc_clk_ahb == NULL || sc->sc_clk_mod == NULL
190 || sc->sc_clk_pll0 == NULL || sc->sc_clk_pll1 == NULL) { 189 || sc->sc_clk_pll0 == NULL || sc->sc_clk_pll1 == NULL) {
191 aprint_error(": couldn't get clocks\n"); 190 aprint_error(": couldn't get clocks\n");
192 aprint_debug_dev(self, "clk ahb %s mod %s pll-0 %s pll-1 %s\n", 191 aprint_debug_dev(self, "clk ahb %s mod %s pll-0 %s pll-1 %s\n",
193 sc->sc_clk_ahb == NULL ? "missing" : "present", 192 sc->sc_clk_ahb == NULL ? "missing" : "present",
194 sc->sc_clk_mod == NULL ? "missing" : "present", 193 sc->sc_clk_mod == NULL ? "missing" : "present",
195 sc->sc_clk_pll0 == NULL ? "missing" : "present", 194 sc->sc_clk_pll0 == NULL ? "missing" : "present",
196 sc->sc_clk_pll1 == NULL ? "missing" : "present"); 195 sc->sc_clk_pll1 == NULL ? "missing" : "present");
197 return; 196 return;
198 } 197 }
199 198
200 error = clk_disable(sc->sc_clk_mod); 
201 if (error) { 
202 aprint_error(": couldn't disable mod clock\n"); 
203 return; 
204 } 
205 
206 if (clk_enable(sc->sc_clk_ahb) != 0) { 199 if (clk_enable(sc->sc_clk_ahb) != 0) {
207 aprint_error(": couldn't enable ahb clock\n"); 200 aprint_error(": couldn't enable ahb clock\n");
208 return; 201 return;
209 } 202 }
210#if defined(SUNXI_HDMI_DEBUG) 
211 sunxi_hdmi_dump_regs(); 
212#endif 
213 
214 /* 
215 * reset device, in case it has been setup by firmware in an 
216 * incompatible way 
217 */ 
218 for (int i = 0; i <= 0x500; i += 4) { 
219 HDMI_WRITE(sc, i, 0); 
220 } 
221 
222 ver = HDMI_READ(sc, SUNXI_HDMI_VERSION_ID_REG); 203 ver = HDMI_READ(sc, SUNXI_HDMI_VERSION_ID_REG);
223 204
224 const int vmaj = __SHIFTOUT(ver, SUNXI_HDMI_VERSION_ID_H); 205 const int vmaj = __SHIFTOUT(ver, SUNXI_HDMI_VERSION_ID_H);
225 const int vmin = __SHIFTOUT(ver, SUNXI_HDMI_VERSION_ID_L); 206 const int vmin = __SHIFTOUT(ver, SUNXI_HDMI_VERSION_ID_L);
226 207
227 aprint_naive("\n"); 208 aprint_naive("\n");
228 aprint_normal(": HDMI %d.%d\n", vmaj, vmin); 209 aprint_normal(": HDMI %d.%d\n", vmaj, vmin);
229 210
230 sc->sc_ver = ver; 211 sc->sc_ver = ver;
231 sc->sc_i2c_blklen = 16; 212 sc->sc_i2c_blklen = 16;
232 213
233 sc->sc_ports.dp_ep_activate = sunxi_hdmi_ep_activate; 214 sc->sc_ports.dp_ep_activate = sunxi_hdmi_ep_activate;
234 sc->sc_ports.dp_ep_enable = sunxi_hdmi_ep_enable; 215 sc->sc_ports.dp_ep_enable = sunxi_hdmi_ep_enable;
235 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER); 216 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER);
236 217
237 mutex_init(&sc->sc_pwr_lock, MUTEX_DEFAULT, IPL_NONE); 218 mutex_init(&sc->sc_pwr_lock, MUTEX_DEFAULT, IPL_NONE);
238 sunxi_hdmi_i2c_init(sc); 219 sunxi_hdmi_i2c_init(sc);
 220}
239 221
240 if (clk_disable(sc->sc_clk_ahb) != 0) { 222void
241 aprint_error(": couldn't disable ahb clock\n"); 223sunxi_hdmi_doreset(void)
242 return; 224{
 225 device_t dev;
 226 struct sunxi_hdmi_softc *sc;
 227 int error;
 228
 229 for (int i = 0;;i++) {
 230 dev = device_find_by_driver_unit("sunxihdmi", i);
 231 if (dev == NULL)
 232 return;
 233 sc = device_private(dev);
 234
 235 error = clk_disable(sc->sc_clk_mod);
 236 if (error) {
 237 aprint_error_dev(dev, ": couldn't disable mod clock\n");
 238 return;
 239 }
 240
 241#if defined(SUNXI_HDMI_DEBUG)
 242 sunxi_hdmi_dump_regs();
 243#endif
 244
 245 /*
 246 * reset device, in case it has been setup by firmware in an
 247 * incompatible way
 248 */
 249 for (int j = 0; j <= 0x500; j += 4) {
 250 HDMI_WRITE(sc, j, 0);
 251 }
 252
 253 if (clk_disable(sc->sc_clk_ahb) != 0) {
 254 aprint_error_dev(dev, ": couldn't disable ahb clock\n");
 255 return;
 256 }
243 } 257 }
244} 258}
245 259
246static void 260static void
247sunxi_hdmi_i2c_init(struct sunxi_hdmi_softc *sc) 261sunxi_hdmi_i2c_init(struct sunxi_hdmi_softc *sc)
248{ 262{
249 struct i2c_controller *ic = &sc->sc_ic; 263 struct i2c_controller *ic = &sc->sc_ic;
250 264
251 mutex_init(&sc->sc_ic_lock, MUTEX_DEFAULT, IPL_NONE); 265 mutex_init(&sc->sc_ic_lock, MUTEX_DEFAULT, IPL_NONE);
252 266
253 ic->ic_cookie = sc; 267 ic->ic_cookie = sc;
254 ic->ic_acquire_bus = sunxi_hdmi_i2c_acquire_bus; 268 ic->ic_acquire_bus = sunxi_hdmi_i2c_acquire_bus;
255 ic->ic_release_bus = sunxi_hdmi_i2c_release_bus; 269 ic->ic_release_bus = sunxi_hdmi_i2c_release_bus;

cvs diff -r1.6 -r1.7 src/sys/arch/arm/sunxi/sunxi_tcon.c (expand / switch to unified diff)

--- src/sys/arch/arm/sunxi/sunxi_tcon.c 2018/04/07 18:09:33 1.6
+++ src/sys/arch/arm/sunxi/sunxi_tcon.c 2018/06/01 17:18:44 1.7
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $ */ 1/* $NetBSD: sunxi_tcon.c,v 1.7 2018/06/01 17:18:44 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Manuel Bouyer <bouyer@antioche.eu.org> 4 * Copyright (c) 2018 Manuel Bouyer <bouyer@antioche.eu.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 7 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.6 2018/04/07 18:09:33 bouyer Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c,v 1.7 2018/06/01 17:18:44 bouyer Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/bus.h> 36#include <sys/bus.h>
37#include <sys/device.h> 37#include <sys/device.h>
38#include <sys/intr.h> 38#include <sys/intr.h>
39#include <sys/systm.h> 39#include <sys/systm.h>
40#include <sys/kernel.h> 40#include <sys/kernel.h>
41#include <sys/mutex.h> 41#include <sys/mutex.h>
42#include <sys/condvar.h> 42#include <sys/condvar.h>
43 43
44#include <dev/fdt/fdtvar.h> 44#include <dev/fdt/fdtvar.h>
45#include <dev/fdt/fdt_port.h> 45#include <dev/fdt/fdt_port.h>
46#include <dev/fdt/panel_fdt.h> 46#include <dev/fdt/panel_fdt.h>
@@ -55,26 +55,27 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c @@ -55,26 +55,27 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_tcon.c
55enum sunxi_tcon_type { 55enum sunxi_tcon_type {
56 TCON_A10 = 1, 56 TCON_A10 = 1,
57}; 57};
58 58
59struct sunxi_tcon_softc { 59struct sunxi_tcon_softc {
60 device_t sc_dev; 60 device_t sc_dev;
61 enum sunxi_tcon_type sc_type; 61 enum sunxi_tcon_type sc_type;
62 int sc_phandle; 62 int sc_phandle;
63 bus_space_tag_t sc_bst; 63 bus_space_tag_t sc_bst;
64 bus_space_handle_t sc_bsh; 64 bus_space_handle_t sc_bsh;
65 struct clk *sc_clk_ahb; 65 struct clk *sc_clk_ahb;
66 struct clk *sc_clk_ch0; 66 struct clk *sc_clk_ch0;
67 struct clk *sc_clk_ch1; 67 struct clk *sc_clk_ch1;
 68 struct fdtbus_reset *sc_rst, *sc_lvds_rst;
68 unsigned int sc_output_type; 69 unsigned int sc_output_type;
69#define OUTPUT_HDMI 0 70#define OUTPUT_HDMI 0
70#define OUTPUT_LVDS 1 71#define OUTPUT_LVDS 1
71#define OUTPUT_VGA 2 72#define OUTPUT_VGA 2
72 struct fdt_device_ports sc_ports; 73 struct fdt_device_ports sc_ports;
73 int sc_unit; /* tcon0 or tcon1 */ 74 int sc_unit; /* tcon0 or tcon1 */
74 struct fdt_endpoint *sc_in_ep; 75 struct fdt_endpoint *sc_in_ep;
75 struct fdt_endpoint *sc_in_rep; 76 struct fdt_endpoint *sc_in_rep;
76 struct fdt_endpoint *sc_out_ep; 77 struct fdt_endpoint *sc_out_ep;
77}; 78};
78 79
79static bus_space_handle_t tcon_mux_bsh; 80static bus_space_handle_t tcon_mux_bsh;
80static bool tcon_mux_inited = false; 81static bool tcon_mux_inited = false;
@@ -110,28 +111,26 @@ sunxi_tcon_match(device_t parent, cfdata @@ -110,28 +111,26 @@ sunxi_tcon_match(device_t parent, cfdata
110 struct fdt_attach_args * const faa = aux; 111 struct fdt_attach_args * const faa = aux;
111 112
112 return of_match_compat_data(faa->faa_phandle, compat_data); 113 return of_match_compat_data(faa->faa_phandle, compat_data);
113} 114}
114 115
115static void 116static void
116sunxi_tcon_attach(device_t parent, device_t self, void *aux) 117sunxi_tcon_attach(device_t parent, device_t self, void *aux)
117{ 118{
118 struct sunxi_tcon_softc *sc = device_private(self); 119 struct sunxi_tcon_softc *sc = device_private(self);
119 struct fdt_attach_args * const faa = aux; 120 struct fdt_attach_args * const faa = aux;
120 const int phandle = faa->faa_phandle; 121 const int phandle = faa->faa_phandle;
121 bus_addr_t addr; 122 bus_addr_t addr;
122 bus_size_t size; 123 bus_size_t size;
123 struct fdtbus_reset *rst, *lvds_rst; 
124 
125 124
126 sc->sc_dev = self; 125 sc->sc_dev = self;
127 sc->sc_phandle = phandle; 126 sc->sc_phandle = phandle;
128 sc->sc_bst = faa->faa_bst; 127 sc->sc_bst = faa->faa_bst;
129 128
130 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 129 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
131 aprint_error(": couldn't get registers\n"); 130 aprint_error(": couldn't get registers\n");
132 } 131 }
133 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 132 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
134 aprint_error(": couldn't map registers\n"); 133 aprint_error(": couldn't map registers\n");
135 return; 134 return;
136 } 135 }
137 136
@@ -139,104 +138,121 @@ sunxi_tcon_attach(device_t parent, devic @@ -139,104 +138,121 @@ sunxi_tcon_attach(device_t parent, devic
139 sc->sc_clk_ch0 = fdtbus_clock_get(phandle, "tcon-ch0"); 138 sc->sc_clk_ch0 = fdtbus_clock_get(phandle, "tcon-ch0");
140 sc->sc_clk_ch1 = fdtbus_clock_get(phandle, "tcon-ch1"); 139 sc->sc_clk_ch1 = fdtbus_clock_get(phandle, "tcon-ch1");
141 140
142 if (sc->sc_clk_ahb == NULL || sc->sc_clk_ch0 == NULL 141 if (sc->sc_clk_ahb == NULL || sc->sc_clk_ch0 == NULL
143 || sc->sc_clk_ch1 == NULL) { 142 || sc->sc_clk_ch1 == NULL) {
144 aprint_error(": couldn't get clocks\n"); 143 aprint_error(": couldn't get clocks\n");
145 aprint_debug_dev(self, "clk ahb %s tcon-ch0 %s tcon-ch1 %s\n", 144 aprint_debug_dev(self, "clk ahb %s tcon-ch0 %s tcon-ch1 %s\n",
146 sc->sc_clk_ahb == NULL ? "missing" : "present", 145 sc->sc_clk_ahb == NULL ? "missing" : "present",
147 sc->sc_clk_ch0 == NULL ? "missing" : "present", 146 sc->sc_clk_ch0 == NULL ? "missing" : "present",
148 sc->sc_clk_ch1 == NULL ? "missing" : "present"); 147 sc->sc_clk_ch1 == NULL ? "missing" : "present");
149 return; 148 return;
150 } 149 }
151 150
152 rst = fdtbus_reset_get(phandle, "lcd"); 151 sc->sc_rst = fdtbus_reset_get(phandle, "lcd");
153 if (rst == NULL) { 152 if (sc->sc_rst == NULL) {
154 aprint_error(": couldn't get lcd reset\n"); 153 aprint_error(": couldn't get lcd reset\n");
155 return; 154 return;
156 } 155 }
157 156
158 lvds_rst = fdtbus_reset_get(phandle, "lvds"); 157 sc->sc_lvds_rst = fdtbus_reset_get(phandle, "lvds");
159 
160 if (clk_disable(sc->sc_clk_ahb) != 0) { 
161 aprint_error(": couldn't disable ahb clock\n"); 
162 return; 
163 } 
164 if (clk_disable(sc->sc_clk_ch0) != 0) { 
165 aprint_error(": couldn't disable ch0 clock\n"); 
166 return; 
167 } 
168 
169 if (clk_disable(sc->sc_clk_ch1) != 0) { 
170 aprint_error(": couldn't disable ch1 clock\n"); 
171 return; 
172 } 
173 
174 if (fdtbus_reset_assert(rst) != 0) { 
175 aprint_error(": couldn't assert lcd reset\n"); 
176 return; 
177 } 
178 if (lvds_rst != NULL) { 
179 if (fdtbus_reset_assert(lvds_rst) != 0) { 
180 aprint_error(": couldn't assert lvds reset\n"); 
181 return; 
182 } 
183 } 
184 delay(1); 
185 if (fdtbus_reset_deassert(rst) != 0) { 
186 aprint_error(": couldn't de-assert lcd reset\n"); 
187 return; 
188 } 
189 if (lvds_rst != NULL) { 
190 if (fdtbus_reset_deassert(lvds_rst) != 0) { 
191 aprint_error(": couldn't de-assert lvds reset\n"); 
192 return; 
193 } 
194 } 
195 
196 if (clk_enable(sc->sc_clk_ahb) != 0) { 
197 aprint_error(": couldn't enable ahb clock\n"); 
198 return; 
199 } 
200 158
201 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data; 159 sc->sc_type = of_search_compatible(faa->faa_phandle, compat_data)->data;
202 160
203 aprint_naive("\n"); 161 aprint_naive("\n");
204 aprint_normal(": LCD/TV timing controller (%s)\n",  162 aprint_normal(": LCD/TV timing controller (%s)\n",
205 fdtbus_get_string(phandle, "name")); 163 fdtbus_get_string(phandle, "name"));
206 164
207 sc->sc_unit = -1; 165 sc->sc_unit = -1;
208 sc->sc_ports.dp_ep_connect = sunxi_tcon_ep_connect; 166 sc->sc_ports.dp_ep_connect = sunxi_tcon_ep_connect;
209 sc->sc_ports.dp_ep_activate = sunxi_tcon_ep_activate; 167 sc->sc_ports.dp_ep_activate = sunxi_tcon_ep_activate;
210 sc->sc_ports.dp_ep_enable = sunxi_tcon_ep_enable; 168 sc->sc_ports.dp_ep_enable = sunxi_tcon_ep_enable;
211 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER); 169 fdt_ports_register(&sc->sc_ports, self, phandle, EP_OTHER);
 170}
212 171
213 TCON_WRITE(sc, SUNXI_TCON_GINT0_REG, 0); 172void
214 TCON_WRITE(sc, SUNXI_TCON_GINT1_REG, 173sunxi_tcon_doreset(void)
215 __SHIFTIN(0x20, SUNXI_TCON_GINT1_TCON0_LINENO)); 174{
216 TCON_WRITE(sc, SUNXI_TCON0_DCLK_REG, 0xf0000000); 175 device_t dev;
217 TCON_WRITE(sc, SUNXI_TCON0_LVDS_IF_REG, 0x0); 176 struct sunxi_tcon_softc *sc;
218 TCON_WRITE(sc, SUNXI_TCON0_CTL_REG, 0); 177 for (int i = 0;;i++) {
219 TCON_WRITE(sc, SUNXI_TCON0_IO_TRI_REG, 0xffffffff); 178 dev = device_find_by_driver_unit("sunxitcon", i);
220 TCON_WRITE(sc, SUNXI_TCON1_CTL_REG, 0); 179 if (dev == NULL)
221 TCON_WRITE(sc, SUNXI_TCON1_IO_TRI_REG, 0xffffffff); 180 return;
222 TCON_WRITE(sc, SUNXI_TCON_GCTL_REG, 0); 181 sc = device_private(dev);
223 182
224 /* clock needed for the mux in unit 0 */ 
225 if (sc->sc_unit != 0) { 
226 if (clk_disable(sc->sc_clk_ahb) != 0) { 183 if (clk_disable(sc->sc_clk_ahb) != 0) {
227 aprint_error(": couldn't disable ahb clock\n"); 184 aprint_error_dev(dev, ": couldn't disable ahb clock\n");
 185 return;
 186 }
 187 if (clk_disable(sc->sc_clk_ch0) != 0) {
 188 aprint_error_dev(dev, ": couldn't disable ch0 clock\n");
 189 return;
 190 }
 191
 192 if (clk_disable(sc->sc_clk_ch1) != 0) {
 193 aprint_error_dev(dev, ": couldn't disable ch1 clock\n");
 194 return;
 195 }
 196
 197 if (fdtbus_reset_assert(sc->sc_rst) != 0) {
 198 aprint_error_dev(dev, ": couldn't assert lcd reset\n");
 199 return;
 200 }
 201 if (sc->sc_lvds_rst != NULL) {
 202 if (fdtbus_reset_assert(sc->sc_lvds_rst) != 0) {
 203 aprint_error_dev(dev,
 204 ": couldn't assert lvds reset\n");
 205 return;
 206 }
 207 }
 208 delay(1);
 209 if (fdtbus_reset_deassert(sc->sc_rst) != 0) {
 210 aprint_error_dev(dev,
 211 ": couldn't de-assert lcd reset\n");
228 return; 212 return;
229 } 213 }
 214 if (sc->sc_lvds_rst != NULL) {
 215 if (fdtbus_reset_deassert(sc->sc_lvds_rst) != 0) {
 216 aprint_error_dev(dev,
 217 ": couldn't de-assert lvds reset\n");
 218 return;
 219 }
 220 }
 221
 222 if (clk_enable(sc->sc_clk_ahb) != 0) {
 223 aprint_error_dev(dev, ": couldn't enable ahb clock\n");
 224 return;
 225 }
 226
 227 TCON_WRITE(sc, SUNXI_TCON_GINT0_REG, 0);
 228 TCON_WRITE(sc, SUNXI_TCON_GINT1_REG,
 229 __SHIFTIN(0x20, SUNXI_TCON_GINT1_TCON0_LINENO));
 230 TCON_WRITE(sc, SUNXI_TCON0_DCLK_REG, 0xf0000000);
 231 TCON_WRITE(sc, SUNXI_TCON0_LVDS_IF_REG, 0x0);
 232 TCON_WRITE(sc, SUNXI_TCON0_CTL_REG, 0);
 233 TCON_WRITE(sc, SUNXI_TCON0_IO_TRI_REG, 0xffffffff);
 234 TCON_WRITE(sc, SUNXI_TCON1_CTL_REG, 0);
 235 TCON_WRITE(sc, SUNXI_TCON1_IO_TRI_REG, 0xffffffff);
 236 TCON_WRITE(sc, SUNXI_TCON_GCTL_REG, 0);
 237
 238 /* clock needed for the mux in unit 0 */
 239 if (sc->sc_unit != 0) {
 240 if (clk_disable(sc->sc_clk_ahb) != 0) {
 241 aprint_error_dev(dev,
 242 ": couldn't disable ahb clock\n");
 243 return;
 244 }
 245 }
230 } 246 }
231} 247}
232 248
233static void 249static void
234sunxi_tcon_ep_connect(device_t self, struct fdt_endpoint *ep, bool connect) 250sunxi_tcon_ep_connect(device_t self, struct fdt_endpoint *ep, bool connect)
235{ 251{
236 struct sunxi_tcon_softc *sc = device_private(self); 252 struct sunxi_tcon_softc *sc = device_private(self);
237 struct fdt_endpoint *rep = fdt_endpoint_remote(ep); 253 struct fdt_endpoint *rep = fdt_endpoint_remote(ep);
238 int rep_idx = fdt_endpoint_index(rep); 254 int rep_idx = fdt_endpoint_index(rep);
239 255
240 KASSERT(device_is_a(self, "sunxitcon")); 256 KASSERT(device_is_a(self, "sunxitcon"));
241 if (!connect) { 257 if (!connect) {
242 aprint_error_dev(self, "endpoint disconnect not supported\n"); 258 aprint_error_dev(self, "endpoint disconnect not supported\n");