xref: /netbsd-src/sys/dev/sbus/cgtwelve.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: cgtwelve.c,v 1.8 2021/08/07 16:19:15 thorpej Exp $ */
2da6c0e81Smacallan 
3da6c0e81Smacallan /*-
4da6c0e81Smacallan  * Copyright (c) 2010 Michael Lorenz
5da6c0e81Smacallan  * All rights reserved.
6da6c0e81Smacallan  *
7da6c0e81Smacallan  * Redistribution and use in source and binary forms, with or without
8da6c0e81Smacallan  * modification, are permitted provided that the following conditions
9da6c0e81Smacallan  * are met:
10da6c0e81Smacallan  * 1. Redistributions of source code must retain the above copyright
11da6c0e81Smacallan  *    notice, this list of conditions and the following disclaimer.
12da6c0e81Smacallan  * 2. Redistributions in binary form must reproduce the above copyright
13da6c0e81Smacallan  *    notice, this list of conditions and the following disclaimer in the
14da6c0e81Smacallan  *    documentation and/or other materials provided with the distribution.
15da6c0e81Smacallan  *
16da6c0e81Smacallan  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17da6c0e81Smacallan  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18da6c0e81Smacallan  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19da6c0e81Smacallan  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20da6c0e81Smacallan  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21da6c0e81Smacallan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22da6c0e81Smacallan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23da6c0e81Smacallan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24da6c0e81Smacallan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25da6c0e81Smacallan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26da6c0e81Smacallan  * POSSIBILITY OF SUCH DAMAGE.
27da6c0e81Smacallan  */
28da6c0e81Smacallan 
29da6c0e81Smacallan /* a console driver for the Sun CG12 / Matrox SG3 graphics board */
30da6c0e81Smacallan 
31da6c0e81Smacallan #include <sys/cdefs.h>
32*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: cgtwelve.c,v 1.8 2021/08/07 16:19:15 thorpej Exp $");
33da6c0e81Smacallan 
34da6c0e81Smacallan #include <sys/param.h>
35da6c0e81Smacallan #include <sys/systm.h>
36da6c0e81Smacallan #include <sys/buf.h>
37da6c0e81Smacallan #include <sys/device.h>
38da6c0e81Smacallan #include <sys/ioctl.h>
39da6c0e81Smacallan #include <sys/conf.h>
40b7af3021Smacallan #include <sys/kmem.h>
41da6c0e81Smacallan 
42da6c0e81Smacallan #include <sys/bus.h>
43da6c0e81Smacallan #include <machine/autoconf.h>
44da6c0e81Smacallan 
45da6c0e81Smacallan #include <dev/sbus/sbusvar.h>
46da6c0e81Smacallan #include <dev/sun/fbio.h>
47da6c0e81Smacallan #include <dev/sun/fbvar.h>
48da6c0e81Smacallan 
49da6c0e81Smacallan #include <dev/wscons/wsdisplayvar.h>
50da6c0e81Smacallan #include <dev/wscons/wsconsio.h>
51da6c0e81Smacallan #include <dev/wsfont/wsfont.h>
52da6c0e81Smacallan #include <dev/rasops/rasops.h>
53da6c0e81Smacallan 
54da6c0e81Smacallan #include <dev/wscons/wsdisplay_vconsvar.h>
55da6c0e81Smacallan 
56da6c0e81Smacallan #include <dev/sbus/cgtwelvereg.h>
5759c28997Smacallan #include <dev/ic/bt462reg.h>
58da6c0e81Smacallan 
59da6c0e81Smacallan #include "opt_wsemul.h"
60da6c0e81Smacallan #include "opt_cgtwelve.h"
61da6c0e81Smacallan 
62da6c0e81Smacallan 
63da6c0e81Smacallan struct cgtwelve_softc {
64da6c0e81Smacallan 	device_t	sc_dev;
65da6c0e81Smacallan 	bus_space_tag_t sc_tag;
66e8eb2869Smacallan 	bus_space_handle_t sc_regh;
67e8eb2869Smacallan 	bus_addr_t	sc_paddr;
68da6c0e81Smacallan 	void		*sc_fbaddr;
69b7af3021Smacallan 	void		*sc_shadow;
70e8eb2869Smacallan 	uint8_t		*sc_wids;
71e8eb2869Smacallan 	void		*sc_int;
72da6c0e81Smacallan 	int		sc_width;
73da6c0e81Smacallan 	int		sc_height;
74da6c0e81Smacallan 	int		sc_stride;
75da6c0e81Smacallan 	int		sc_fbsize;
76da6c0e81Smacallan 	int		sc_mode;
77da6c0e81Smacallan 	struct vcons_data vd;
78da6c0e81Smacallan };
79da6c0e81Smacallan 
80da6c0e81Smacallan static int	cgtwelve_match(device_t, cfdata_t, void *);
81da6c0e81Smacallan static void	cgtwelve_attach(device_t, device_t, void *);
82da6c0e81Smacallan static int	cgtwelve_ioctl(void *, void *, u_long, void *, int,
83da6c0e81Smacallan 				 struct lwp*);
84da6c0e81Smacallan static paddr_t	cgtwelve_mmap(void *, void *, off_t, int);
85da6c0e81Smacallan static void	cgtwelve_init_screen(void *, struct vcons_screen *, int,
86da6c0e81Smacallan 				 long *);
87e8eb2869Smacallan static void	cgtwelve_write_wid(struct cgtwelve_softc *, int, uint8_t);
88e8eb2869Smacallan static void	cgtwelve_select_ovl(struct cgtwelve_softc *, int);
89e8eb2869Smacallan #define CG12_SEL_OVL	0
90e8eb2869Smacallan #define CG12_SEL_ENABLE	1
91e8eb2869Smacallan #define CG12_SEL_8BIT	2
92e8eb2869Smacallan #define CG12_SEL_24BIT	3
93e8eb2869Smacallan #define CG12_SEL_WID	4
94e8eb2869Smacallan static void	cgtwelve_write_dac(struct cgtwelve_softc *, int, int, int, int);
95e8eb2869Smacallan static void	cgtwelve_setup(struct cgtwelve_softc *, int);
96da6c0e81Smacallan 
97da6c0e81Smacallan CFATTACH_DECL_NEW(cgtwelve, sizeof(struct cgtwelve_softc),
98da6c0e81Smacallan     cgtwelve_match, cgtwelve_attach, NULL, NULL);
99da6c0e81Smacallan 
100da6c0e81Smacallan struct wsscreen_descr cgtwelve_defscreendesc = {
101da6c0e81Smacallan 	"default",
102da6c0e81Smacallan 	0, 0,
103da6c0e81Smacallan 	NULL,
104da6c0e81Smacallan 	8, 16,
105da6c0e81Smacallan 	0,
106da6c0e81Smacallan };
107da6c0e81Smacallan 
108da6c0e81Smacallan static struct vcons_screen cgtwelve_console_screen;
109da6c0e81Smacallan 
110da6c0e81Smacallan const struct wsscreen_descr *_cgtwelve_scrlist[] = {
111da6c0e81Smacallan 	&cgtwelve_defscreendesc,
112da6c0e81Smacallan 	/* XXX other formats, graphics screen? */
113da6c0e81Smacallan };
114da6c0e81Smacallan 
115da6c0e81Smacallan struct wsscreen_list cgtwelve_screenlist = {
116da6c0e81Smacallan 	sizeof(_cgtwelve_scrlist) / sizeof(struct wsscreen_descr *),
117da6c0e81Smacallan 	_cgtwelve_scrlist
118da6c0e81Smacallan };
119da6c0e81Smacallan 
120da6c0e81Smacallan struct wsdisplay_accessops cgtwelve_accessops = {
121da6c0e81Smacallan 	cgtwelve_ioctl,
122da6c0e81Smacallan 	cgtwelve_mmap,
123da6c0e81Smacallan 	NULL,	/* vcons_alloc_screen */
124da6c0e81Smacallan 	NULL,	/* vcons_free_screen */
125da6c0e81Smacallan 	NULL,	/* vcons_show_screen */
126da6c0e81Smacallan 	NULL,	/* load_font */
127da6c0e81Smacallan 	NULL,	/* polls */
128da6c0e81Smacallan 	NULL,	/* scroll */
129da6c0e81Smacallan };
130da6c0e81Smacallan 
13159c28997Smacallan extern const u_char rasops_cmap[768];
13259c28997Smacallan 
133da6c0e81Smacallan static int
cgtwelve_match(device_t parent,cfdata_t cf,void * aux)134da6c0e81Smacallan cgtwelve_match(device_t parent, cfdata_t cf, void *aux)
135da6c0e81Smacallan {
136da6c0e81Smacallan 	struct sbus_attach_args *sa = aux;
137da6c0e81Smacallan 
138da6c0e81Smacallan 	if (strcmp("cgtwelve", sa->sa_name) == 0)
139da6c0e81Smacallan 		return 100;
140da6c0e81Smacallan 	return 0;
141da6c0e81Smacallan }
142da6c0e81Smacallan 
143da6c0e81Smacallan /*
144da6c0e81Smacallan  * Attach a display.  We need to notice if it is the console, too.
145da6c0e81Smacallan  */
146da6c0e81Smacallan static void
cgtwelve_attach(device_t parent,device_t self,void * args)147da6c0e81Smacallan cgtwelve_attach(device_t parent, device_t self, void *args)
148da6c0e81Smacallan {
149da6c0e81Smacallan 	struct cgtwelve_softc *sc = device_private(self);
150da6c0e81Smacallan 	struct sbus_attach_args *sa = args;
151da6c0e81Smacallan 	struct wsemuldisplaydev_attach_args aa;
152da6c0e81Smacallan 	struct rasops_info *ri;
153da6c0e81Smacallan 	unsigned long defattr;
154da6c0e81Smacallan 	bus_space_handle_t bh;
155da6c0e81Smacallan 	int node = sa->sa_node;
156da6c0e81Smacallan 	int isconsole;
157da6c0e81Smacallan 
158da6c0e81Smacallan 	aprint_normal("\n");
159da6c0e81Smacallan 	sc->sc_dev = self;
160da6c0e81Smacallan 	sc->sc_tag = sa->sa_bustag;
161da6c0e81Smacallan 
162e8eb2869Smacallan 	sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);
163e8eb2869Smacallan 
164da6c0e81Smacallan 	/* read geometry information from the device tree */
165da6c0e81Smacallan 	sc->sc_width = prom_getpropint(sa->sa_node, "width", 1152);
166da6c0e81Smacallan 	sc->sc_height = prom_getpropint(sa->sa_node, "height", 900);
16759c28997Smacallan #ifdef CG12_COLOR
16859c28997Smacallan 	sc->sc_stride = sc->sc_width;
16959c28997Smacallan #else
170da6c0e81Smacallan 	sc->sc_stride = (sc->sc_width + 7) >> 3;
17159c28997Smacallan #endif
172da6c0e81Smacallan 	sc->sc_fbsize = sc->sc_height * sc->sc_stride;
17359c28997Smacallan 
174da6c0e81Smacallan 	sc->sc_fbaddr = (void *)prom_getpropint(sa->sa_node, "address", 0);
175da6c0e81Smacallan 	if (sc->sc_fbaddr == NULL) {
176da6c0e81Smacallan 		if (sbus_bus_map(sa->sa_bustag,
177da6c0e81Smacallan 			 sa->sa_slot,
178da6c0e81Smacallan 			 sa->sa_offset + CG12_FB_MONO,
179da6c0e81Smacallan 			 sc->sc_fbsize,
180da6c0e81Smacallan 			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
181da6c0e81Smacallan 			aprint_error_dev(self, "cannot map framebuffer\n");
182da6c0e81Smacallan 			return;
183da6c0e81Smacallan 		}
184da6c0e81Smacallan 		sc->sc_fbaddr = bus_space_vaddr(sa->sa_bustag, bh);
185da6c0e81Smacallan 	}
186da6c0e81Smacallan 
187da6c0e81Smacallan 	aprint_normal_dev(self, "%d x %d\n", sc->sc_width, sc->sc_height);
188da6c0e81Smacallan 
189e8eb2869Smacallan 	if (sbus_bus_map(sa->sa_bustag,
190e8eb2869Smacallan 			 sa->sa_slot,
191e8eb2869Smacallan 			 sa->sa_offset + CG12_OFF_REGISTERS,
192e8eb2869Smacallan 			 0xc0000, 0, &sc->sc_regh) != 0) {
193e8eb2869Smacallan 		aprint_error("%s: couldn't map registers\n",
194e8eb2869Smacallan 		    device_xname(sc->sc_dev));
195e8eb2869Smacallan 		return;
196e8eb2869Smacallan 	}
197e8eb2869Smacallan 
198e8eb2869Smacallan 	if (sbus_bus_map(sa->sa_bustag,
199e8eb2869Smacallan 			 sa->sa_slot,
200e8eb2869Smacallan 			 sa->sa_offset + CG12_OFF_WID, 0x100000,
201e8eb2869Smacallan 			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
202e8eb2869Smacallan 			 &bh) != 0) {
203e8eb2869Smacallan 		aprint_error("%s: couldn't map WID\n",
204e8eb2869Smacallan 		    device_xname(sc->sc_dev));
205e8eb2869Smacallan 		return;
206e8eb2869Smacallan 	}
207e8eb2869Smacallan 	sc->sc_wids = bus_space_vaddr(sa->sa_bustag, bh);
208e8eb2869Smacallan 
209e8eb2869Smacallan 	if (sbus_bus_map(sa->sa_bustag,
210e8eb2869Smacallan 			 sa->sa_slot,
211e8eb2869Smacallan 			 sa->sa_offset + CG12_OFF_INTEN, 0x400000,
212e8eb2869Smacallan 			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
213e8eb2869Smacallan 			 &bh) != 0) {
214e8eb2869Smacallan 		aprint_error("%s: couldn't map colour fb\n",
215e8eb2869Smacallan 		    device_xname(sc->sc_dev));
216e8eb2869Smacallan 		return;
217e8eb2869Smacallan 	}
218e8eb2869Smacallan 	sc->sc_int = bus_space_vaddr(sa->sa_bustag, bh);
219e8eb2869Smacallan 
22059c28997Smacallan #ifdef CG12_COLOR
22159c28997Smacallan 	cgtwelve_setup(sc, 8);
22259c28997Smacallan #else
223e8eb2869Smacallan 	cgtwelve_setup(sc, 1);
22459c28997Smacallan #endif
22559c28997Smacallan #ifdef CG12_SHADOW
226b7af3021Smacallan 	sc->sc_shadow = kmem_alloc(sc->sc_fbsize, KM_SLEEP);
22759c28997Smacallan #else
22859c28997Smacallan 	sc->sc_shadow = NULL;
22959c28997Smacallan #endif
23059c28997Smacallan 
231da6c0e81Smacallan 	isconsole = fb_is_console(node);
232da6c0e81Smacallan 
233da6c0e81Smacallan 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
234da6c0e81Smacallan 	wsfont_init();
235da6c0e81Smacallan 
236da6c0e81Smacallan 	vcons_init(&sc->vd, sc, &cgtwelve_defscreendesc, &cgtwelve_accessops);
237da6c0e81Smacallan 	sc->vd.init_screen = cgtwelve_init_screen;
238da6c0e81Smacallan 
239da6c0e81Smacallan 	vcons_init_screen(&sc->vd, &cgtwelve_console_screen, 1, &defattr);
240da6c0e81Smacallan 	cgtwelve_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
241da6c0e81Smacallan 
242da6c0e81Smacallan 	ri = &cgtwelve_console_screen.scr_ri;
243da6c0e81Smacallan 
244da6c0e81Smacallan 	cgtwelve_defscreendesc.nrows = ri->ri_rows;
245da6c0e81Smacallan 	cgtwelve_defscreendesc.ncols = ri->ri_cols;
246da6c0e81Smacallan 	cgtwelve_defscreendesc.textops = &ri->ri_ops;
247da6c0e81Smacallan 	cgtwelve_defscreendesc.capabilities = ri->ri_caps;
248da6c0e81Smacallan 
249da6c0e81Smacallan 	if(isconsole) {
250da6c0e81Smacallan 		wsdisplay_cnattach(&cgtwelve_defscreendesc, ri, 0, 0, defattr);
251da6c0e81Smacallan 		vcons_replay_msgbuf(&cgtwelve_console_screen);
252da6c0e81Smacallan 	}
253da6c0e81Smacallan 
254da6c0e81Smacallan 	aa.console = isconsole;
255da6c0e81Smacallan 	aa.scrdata = &cgtwelve_screenlist;
256da6c0e81Smacallan 	aa.accessops = &cgtwelve_accessops;
257da6c0e81Smacallan 	aa.accesscookie = &sc->vd;
258da6c0e81Smacallan 
259*c7fb772bSthorpej 	config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
26059c28997Smacallan #ifdef CG12_DEBUG
261e8eb2869Smacallan 	{
26259c28997Smacallan 		int i;
26359c28997Smacallan 		for (i = 0; i < 0x10; i++) {
26459c28997Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
26559c28997Smacallan 			    CG12DAC_ADDR0, (i << 16) | (i << 8) | i);
26659c28997Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
26759c28997Smacallan 			    CG12DAC_ADDR1, 0x010101);
26859c28997Smacallan 			printf("%02x: %08x\n", i, bus_space_read_4(sc->sc_tag,
26959c28997Smacallan 			    sc->sc_regh, CG12DAC_CTRL));
270b7af3021Smacallan 		}
271b7af3021Smacallan 	}
272b7af3021Smacallan #endif
273da6c0e81Smacallan }
274da6c0e81Smacallan 
275e8eb2869Smacallan /* 0 - overlay plane, 1 - enable plane, 2 - 8bit fb, 3 - 24bit fb, 4 - WIDs */
276e8eb2869Smacallan static void
cgtwelve_select_ovl(struct cgtwelve_softc * sc,int which)277e8eb2869Smacallan cgtwelve_select_ovl(struct cgtwelve_softc *sc, int which)
278e8eb2869Smacallan {
279e8eb2869Smacallan 	switch(which) {
280e8eb2869Smacallan 		case 0:
281e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
282e8eb2869Smacallan 			    CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_OVERLAY);
283e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
284e8eb2869Smacallan 			    CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_OVERLAY);
285e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
286e8eb2869Smacallan 			    CG12DPU_PLN_SL_HOST, CG12_PLN_SL_OVERLAY);
287e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
288e8eb2869Smacallan 			    CG12APU_HPAGE, CG12_HPAGE_OVERLAY);
289e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
290e8eb2869Smacallan 			    CG12APU_HACCESS, CG12_HACCESS_OVERLAY);
291e8eb2869Smacallan 			break;
292e8eb2869Smacallan 		case 1:
293e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
294e8eb2869Smacallan 			    CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_ENABLE);
295e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
296e8eb2869Smacallan 			    CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_ENABLE);
297e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
298e8eb2869Smacallan 			    CG12DPU_PLN_SL_HOST, CG12_PLN_SL_ENABLE);
299e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
300e8eb2869Smacallan 			    CG12APU_HPAGE, CG12_HPAGE_ENABLE);
301e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
302e8eb2869Smacallan 			    CG12APU_HACCESS, CG12_HACCESS_ENABLE);
303e8eb2869Smacallan 			break;
304e8eb2869Smacallan 		case 2:
305e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
306e8eb2869Smacallan 			    CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_8BIT);
307e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
308e8eb2869Smacallan 			    CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_8BIT);
309e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
310e8eb2869Smacallan 			    CG12DPU_PLN_SL_HOST, CG12_PLN_SL_8BIT);
311e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
312e8eb2869Smacallan 			    CG12APU_HPAGE, CG12_HPAGE_8BIT);
313e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
314e8eb2869Smacallan 			    CG12APU_HACCESS, CG12_HACCESS_8BIT);
315e8eb2869Smacallan 			break;
316e8eb2869Smacallan 		case 3:
317e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
318e8eb2869Smacallan 			    CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_24BIT);
319e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
320e8eb2869Smacallan 			    CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_24BIT);
321e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
322e8eb2869Smacallan 			    CG12DPU_PLN_SL_HOST, CG12_PLN_SL_24BIT);
323e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
324e8eb2869Smacallan 			    CG12APU_HPAGE, CG12_HPAGE_24BIT);
325e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
326e8eb2869Smacallan 			    CG12APU_HACCESS, CG12_HACCESS_24BIT);
327e8eb2869Smacallan 			break;
328e8eb2869Smacallan 		case 4:
329e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
330e8eb2869Smacallan 			    CG12DPU_PLN_RDMSK_HOST, CG12_PLN_RD_WID);
331e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
332e8eb2869Smacallan 			    CG12DPU_PLN_WRMSK_HOST, CG12_PLN_WR_WID);
333e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
334e8eb2869Smacallan 			    CG12DPU_PLN_SL_HOST, CG12_PLN_SL_WID);
335e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
336e8eb2869Smacallan 			    CG12APU_HPAGE, CG12_HPAGE_WID);
337e8eb2869Smacallan 			bus_space_write_4(sc->sc_tag, sc->sc_regh,
338e8eb2869Smacallan 			    CG12APU_HACCESS, CG12_HACCESS_WID);
339e8eb2869Smacallan 			break;
340e8eb2869Smacallan 	}
341e8eb2869Smacallan }
342e8eb2869Smacallan 
343e8eb2869Smacallan static void
cgtwelve_write_wid(struct cgtwelve_softc * sc,int idx,uint8_t wid)344e8eb2869Smacallan cgtwelve_write_wid(struct cgtwelve_softc *sc, int idx, uint8_t wid)
345e8eb2869Smacallan {
346e8eb2869Smacallan 	bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12_WSC_ADDR, idx << 16);
347e8eb2869Smacallan 	bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12_WSC_DATA,
348e8eb2869Smacallan 	    ((uint32_t)wid) << 16);
349e8eb2869Smacallan }
350e8eb2869Smacallan 
351e8eb2869Smacallan static void
cgtwelve_write_dac(struct cgtwelve_softc * sc,int idx,int r,int g,int b)352e8eb2869Smacallan cgtwelve_write_dac(struct cgtwelve_softc *sc, int idx, int r, int g, int b)
353e8eb2869Smacallan {
354e8eb2869Smacallan 	uint32_t lo = (idx & 0xff);
355e8eb2869Smacallan 	uint32_t hi = (idx >> 8) & 0xff;
356e8eb2869Smacallan 
357e8eb2869Smacallan 	lo |= lo << 8 | lo << 16;
358e8eb2869Smacallan 	hi |= hi << 8 | hi << 16;
359e8eb2869Smacallan 	bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12DAC_ADDR0, lo);
360e8eb2869Smacallan 	bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12DAC_ADDR1, hi);
361e8eb2869Smacallan 	bus_space_write_4(sc->sc_tag, sc->sc_regh, CG12DAC_DATA,
362e8eb2869Smacallan 	    b << 16 | g << 8 | r);
363e8eb2869Smacallan }
364e8eb2869Smacallan 
365e8eb2869Smacallan static void
cgtwelve_setup(struct cgtwelve_softc * sc,int depth)366e8eb2869Smacallan cgtwelve_setup(struct cgtwelve_softc *sc, int depth)
367e8eb2869Smacallan {
36859c28997Smacallan 	int i, j;
369e8eb2869Smacallan 
370e8eb2869Smacallan 	/* first let's put some stuff into the WID table */
371e8eb2869Smacallan 	cgtwelve_write_wid(sc, 0, CG12_WID_8_BIT);
372e8eb2869Smacallan 	cgtwelve_write_wid(sc, 1, CG12_WID_24_BIT);
373e8eb2869Smacallan 
374e8eb2869Smacallan 	/* a linear ramp for the gamma table */
375e8eb2869Smacallan 	for (i = 0; i < 256; i++)
376e8eb2869Smacallan 		cgtwelve_write_dac(sc, i + 0x100, i, i, i);
377e8eb2869Smacallan 
37859c28997Smacallan 	j = 0;
37959c28997Smacallan 	/* rasops' ANSI colour map */
38059c28997Smacallan 	for (i = 0; i < 256; i++) {
38159c28997Smacallan 		cgtwelve_write_dac(sc, i,
38259c28997Smacallan 		    rasops_cmap[j],
38359c28997Smacallan 		    rasops_cmap[j + 1],
38459c28997Smacallan 		    rasops_cmap[j + 2]);
38559c28997Smacallan 		j += 3;
38659c28997Smacallan 	}
38759c28997Smacallan 
388e8eb2869Smacallan 	switch(depth) {
389e8eb2869Smacallan 	case 1:
390e8eb2869Smacallan 		/* setup the console */
391e8eb2869Smacallan 
392e8eb2869Smacallan 		/* first, make the overlay all opaque */
393e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_ENABLE);
394e8eb2869Smacallan 		memset(sc->sc_fbaddr, 0xff, 0x20000);
395e8eb2869Smacallan 
396e8eb2869Smacallan 		/* now write the right thing into the WID plane */
397e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_WID);
398e8eb2869Smacallan 		memset(sc->sc_wids, 0, 0x100000);
399e8eb2869Smacallan 
400e8eb2869Smacallan 		/* now clean the plane */
401e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_OVL);
402e8eb2869Smacallan 		memset(sc->sc_fbaddr, 0, 0x20000);
403e8eb2869Smacallan 		break;
40459c28997Smacallan 	case 8:
40559c28997Smacallan 		/* setup the 8bit fb */
40659c28997Smacallan 		/*
40759c28997Smacallan 		 * first clean the 8bit fb - for aesthetic reasons do it while
40859c28997Smacallan 		 * it's still not visible ( we hope... )
40959c28997Smacallan 		 */
41059c28997Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_8BIT);
41159c28997Smacallan 		memset(sc->sc_int, 0x00, 0x100000);
41259c28997Smacallan 
41359c28997Smacallan 		/* now write the right thing into the WID plane */
41459c28997Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_WID);
41559c28997Smacallan 		memset(sc->sc_wids, 0, 0x100000);
41659c28997Smacallan 
41759c28997Smacallan 		/* hide the overlay */
41859c28997Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_ENABLE);
41959c28997Smacallan 		memset(sc->sc_fbaddr, 0, 0x20000);
42059c28997Smacallan 
42159c28997Smacallan 		/* now clean the plane */
42259c28997Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_OVL);
42359c28997Smacallan 		memset(sc->sc_fbaddr, 0, 0x20000);
42459c28997Smacallan 
425edfa954bSmacallan 		/* and make sure we can write the 8bit fb */
42659c28997Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_8BIT);
42759c28997Smacallan 		break;
428e8eb2869Smacallan 	case 24:
429e8eb2869Smacallan 	case 32:
430e8eb2869Smacallan 		/* setup the 24bit fb for X */
431e8eb2869Smacallan 		/*
432e8eb2869Smacallan 		 * first clean the 24bit fb - for aesthetic reasons do it while
433e8eb2869Smacallan 		 * it's still not visible ( we hope... )
434e8eb2869Smacallan 		 */
435e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_24BIT);
436e8eb2869Smacallan 		memset(sc->sc_int, 0x80, 0x400000);
437e8eb2869Smacallan 
438e8eb2869Smacallan 		/* now write the right thing into the WID plane */
439e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_WID);
440e8eb2869Smacallan 		memset(sc->sc_wids, 1, 0x100000);
441e8eb2869Smacallan 
442e8eb2869Smacallan 		/* hide the overlay */
443e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_ENABLE);
444e8eb2869Smacallan 		memset(sc->sc_fbaddr, 0, 0x20000);
445e8eb2869Smacallan 
446e8eb2869Smacallan 		/* now clean the plane */
447e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_OVL);
448e8eb2869Smacallan 		memset(sc->sc_fbaddr, 0, 0x20000);
449e8eb2869Smacallan 
450e8eb2869Smacallan 		/* and make sure we can write the 24bit fb */
451e8eb2869Smacallan 		cgtwelve_select_ovl(sc, CG12_SEL_24BIT);
452e8eb2869Smacallan 		break;
453e8eb2869Smacallan 	}
454e8eb2869Smacallan }
455da6c0e81Smacallan 
456da6c0e81Smacallan static void
cgtwelve_init_screen(void * cookie,struct vcons_screen * scr,int existing,long * defattr)457da6c0e81Smacallan cgtwelve_init_screen(void *cookie, struct vcons_screen *scr,
458da6c0e81Smacallan     int existing, long *defattr)
459da6c0e81Smacallan {
460da6c0e81Smacallan 	struct cgtwelve_softc *sc = cookie;
461da6c0e81Smacallan 	struct rasops_info *ri = &scr->scr_ri;
462da6c0e81Smacallan 
46359c28997Smacallan #ifdef CG12_COLOR
46459c28997Smacallan 	ri->ri_depth = 8;
46559c28997Smacallan #else
466da6c0e81Smacallan 	ri->ri_depth = 1;
46759c28997Smacallan #endif
468da6c0e81Smacallan 	ri->ri_width = sc->sc_width;
469da6c0e81Smacallan 	ri->ri_height = sc->sc_height;
470da6c0e81Smacallan 	ri->ri_stride = sc->sc_stride;
471da6c0e81Smacallan 	ri->ri_flg = RI_CENTER;
472da6c0e81Smacallan 
473b7af3021Smacallan 	if (sc->sc_shadow == NULL) {
47459c28997Smacallan #ifdef CG12_COLOR
47559c28997Smacallan 		ri->ri_bits = sc->sc_int;
47659c28997Smacallan #else
477da6c0e81Smacallan 		ri->ri_bits = sc->sc_fbaddr;
47859c28997Smacallan #endif
47959c28997Smacallan 		scr->scr_flags |= VCONS_DONT_READ;
480b7af3021Smacallan 	} else {
48159c28997Smacallan #ifdef CG12_COLOR
48259c28997Smacallan 		ri->ri_hwbits = sc->sc_int;
48359c28997Smacallan #else
484b7af3021Smacallan 		ri->ri_hwbits = sc->sc_fbaddr;
48559c28997Smacallan #endif
486b7af3021Smacallan 		ri->ri_bits = sc->sc_shadow;
487b7af3021Smacallan 	}
488da6c0e81Smacallan 
4892cbec7eeSmacallan 	rasops_init(ri, 0, 0);
49059c28997Smacallan #ifdef CG12_COLOR
49159c28997Smacallan 	ri->ri_caps = WSSCREEN_REVERSE | WSSCREEN_WSCOLORS;
49259c28997Smacallan #else
493da6c0e81Smacallan 	ri->ri_caps = WSSCREEN_REVERSE;
49459c28997Smacallan #endif
495da6c0e81Smacallan 	rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight,
496da6c0e81Smacallan 		    ri->ri_width / ri->ri_font->fontwidth);
497da6c0e81Smacallan }
498da6c0e81Smacallan 
499da6c0e81Smacallan static int
cgtwelve_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)500da6c0e81Smacallan cgtwelve_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
501da6c0e81Smacallan     struct lwp *l)
502da6c0e81Smacallan {
503e8eb2869Smacallan 	struct vcons_data *vd = v;
504e8eb2869Smacallan 	struct cgtwelve_softc *sc = vd->cookie;
505e8eb2869Smacallan 	struct wsdisplay_fbinfo *wdf;
506e8eb2869Smacallan 	struct vcons_screen *ms = vd->active;
507da6c0e81Smacallan 
508da6c0e81Smacallan 	switch (cmd) {
509da6c0e81Smacallan 		case WSDISPLAYIO_GTYPE:
510da6c0e81Smacallan 			*(u_int *)data = WSDISPLAY_TYPE_SUNCG12;
511da6c0e81Smacallan 			return 0;
512e8eb2869Smacallan 
513e8eb2869Smacallan 		case WSDISPLAYIO_GINFO:
514e8eb2869Smacallan 			wdf = (void *)data;
515e8eb2869Smacallan 			wdf->height = sc->sc_height;
516e8eb2869Smacallan 			wdf->width = sc->sc_width;
517e8eb2869Smacallan 			wdf->depth = 32;
518e8eb2869Smacallan 			wdf->cmsize = 256;
519e8eb2869Smacallan 			return 0;
520e8eb2869Smacallan 
521e8eb2869Smacallan 		case FBIOGVIDEO:
522e8eb2869Smacallan 		case WSDISPLAYIO_GVIDEO:
523e8eb2869Smacallan 			*(int *)data = 1;
524e8eb2869Smacallan 			return 0;
525e8eb2869Smacallan 
526e8eb2869Smacallan 		case WSDISPLAYIO_SVIDEO:
527e8eb2869Smacallan 		case FBIOSVIDEO:
528e8eb2869Smacallan 			/* when we figure out how to do this... */
529e8eb2869Smacallan 			/*cgtwelve_set_video(sc, *(int *)data);*/
530e8eb2869Smacallan 			return 0;
531e8eb2869Smacallan 
532e8eb2869Smacallan 		case WSDISPLAYIO_LINEBYTES:
533e8eb2869Smacallan 			{
534e8eb2869Smacallan 				int *ret = (int *)data;
535e8eb2869Smacallan 				*ret = sc->sc_width << 2;
536e8eb2869Smacallan 			}
537e8eb2869Smacallan 			return 0;
538e8eb2869Smacallan 
539e8eb2869Smacallan 		case WSDISPLAYIO_SMODE:
540e8eb2869Smacallan 			{
541e8eb2869Smacallan 				int new_mode = *(int*)data;
542e8eb2869Smacallan 				if (new_mode != sc->sc_mode)
543e8eb2869Smacallan 				{
544e8eb2869Smacallan 					sc->sc_mode = new_mode;
545e8eb2869Smacallan 					if (new_mode == WSDISPLAYIO_MODE_EMUL)
546e8eb2869Smacallan 					{
54759c28997Smacallan #ifdef CG12_COLOR
54859c28997Smacallan 						cgtwelve_setup(sc, 8);
54959c28997Smacallan #else
550e8eb2869Smacallan 						cgtwelve_setup(sc, 1);
55159c28997Smacallan #endif
552e8eb2869Smacallan 						vcons_redraw_screen(ms);
553e8eb2869Smacallan 					} else {
554e8eb2869Smacallan 						cgtwelve_setup(sc, 32);
555e8eb2869Smacallan 					}
556e8eb2869Smacallan 				}
557e8eb2869Smacallan 			}
558da6c0e81Smacallan 	}
559da6c0e81Smacallan 
560da6c0e81Smacallan 	return EPASSTHROUGH;
561da6c0e81Smacallan }
562da6c0e81Smacallan 
563da6c0e81Smacallan static paddr_t
cgtwelve_mmap(void * v,void * vs,off_t offset,int prot)564da6c0e81Smacallan cgtwelve_mmap(void *v, void *vs, off_t offset, int prot)
565da6c0e81Smacallan {
566e8eb2869Smacallan 	struct vcons_data *vd = v;
567e8eb2869Smacallan 	struct cgtwelve_softc *sc = vd->cookie;
568da6c0e81Smacallan 
569da6c0e81Smacallan 	/* regular fb mapping at 0 */
570e8eb2869Smacallan 	if ((offset >= 0) && (offset < 0x400000)) {
571e8eb2869Smacallan 		return bus_space_mmap(sc->sc_tag, sc->sc_paddr + CG12_OFF_INTEN,
572e8eb2869Smacallan 		    offset, prot, BUS_SPACE_MAP_LINEAR);
573da6c0e81Smacallan 	}
574da6c0e81Smacallan 
575da6c0e81Smacallan 	return -1;
576da6c0e81Smacallan }
577