1239478Sadrian/*-
2239478Sadrian * Copyright (C) 2012 Margarida Gouveia
3239478Sadrian * Copyright (c) 2003 Peter Grehan
4239478Sadrian * All rights reserved.
5239478Sadrian *
6239478Sadrian * Redistribution and use in source and binary forms, with or without
7239478Sadrian * modification, are permitted provided that the following conditions
8239478Sadrian * are met:
9239478Sadrian * 1. Redistributions of source code must retain the above copyright
10239478Sadrian *    notice, this list of conditions and the following disclaimer,
11239478Sadrian *    without modification, immediately at the beginning of the file.
12239478Sadrian * 2. Redistributions in binary form must reproduce the above copyright
13239478Sadrian *    notice, this list of conditions and the following disclaimer in the
14239478Sadrian *    documentation and/or other materials provided with the distribution.
15239478Sadrian *
16239478Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17239478Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18239478Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19239478Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20239478Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21239478Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22239478Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23239478Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24239478Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25239478Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26239478Sadrian */
27239478Sadrian#include <sys/cdefs.h>
28239478Sadrian__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/wii/wii_fb.c 249965 2013-04-27 01:57:45Z rpaulo $");
29239478Sadrian
30239478Sadrian#include <sys/param.h>
31239478Sadrian#include <sys/systm.h>
32239478Sadrian#include <sys/module.h>
33239478Sadrian#include <sys/bus.h>
34239478Sadrian#include <sys/kernel.h>
35239478Sadrian#include <sys/sysctl.h>
36239478Sadrian#include <sys/limits.h>
37239478Sadrian#include <sys/conf.h>
38239478Sadrian#include <sys/cons.h>
39239478Sadrian#include <sys/proc.h>
40239478Sadrian#include <sys/fcntl.h>
41239478Sadrian#include <sys/malloc.h>
42239478Sadrian#include <sys/fbio.h>
43239478Sadrian#include <sys/consio.h>
44239478Sadrian
45239478Sadrian#include <vm/vm.h>
46239478Sadrian#include <vm/pmap.h>
47239478Sadrian
48239478Sadrian#include <machine/bus.h>
49239478Sadrian#include <machine/sc_machdep.h>
50239478Sadrian#include <machine/platform.h>
51239478Sadrian#include <machine/pmap.h>
52239478Sadrian
53239478Sadrian#include <sys/rman.h>
54239478Sadrian
55239478Sadrian#include <dev/fb/fbreg.h>
56239478Sadrian#include <dev/syscons/syscons.h>
57239478Sadrian
58239478Sadrian#include <powerpc/wii/wii_fbreg.h>
59239478Sadrian#include <powerpc/wii/wii_fbvar.h>
60239478Sadrian
61239478Sadrian/*
62239478Sadrian * Driver for the Nintendo Wii's framebuffer. Based on Linux's gcnfb.c.
63239478Sadrian */
64239478Sadrian
65239478Sadrian/*
66239478Sadrian * Syscons glue.
67239478Sadrian */
68239478Sadrianstatic int	wiifb_scprobe(device_t);
69239478Sadrianstatic int	wiifb_scattach(device_t);
70239478Sadrian
71239478Sadrianstatic device_method_t wiifb_sc_methods[] = {
72239478Sadrian	DEVMETHOD(device_probe,		wiifb_scprobe),
73239478Sadrian	DEVMETHOD(device_attach,	wiifb_scattach),
74239478Sadrian
75239478Sadrian	DEVMETHOD_END
76239478Sadrian};
77239478Sadrian
78239478Sadrianstatic driver_t wiifb_sc_driver = {
79239478Sadrian	"wiifb",
80239478Sadrian	wiifb_sc_methods,
81239478Sadrian	sizeof(sc_softc_t),
82239478Sadrian};
83239478Sadrian
84239478Sadrianstatic devclass_t sc_devclass;
85239478Sadrian
86239478SadrianDRIVER_MODULE(sc, wiibus, wiifb_sc_driver, sc_devclass, 0, 0);
87239478Sadrian
88239478Sadrianstatic int
89239478Sadrianwiifb_scprobe(device_t dev)
90239478Sadrian{
91239478Sadrian	int error;
92239478Sadrian
93239478Sadrian	device_set_desc(dev, "Nintendo Wii frambuffer");
94239478Sadrian
95239478Sadrian	error = sc_probe_unit(device_get_unit(dev),
96239478Sadrian	    device_get_flags(dev) | SC_AUTODETECT_KBD);
97239478Sadrian	if (error != 0)
98239478Sadrian		return (error);
99239478Sadrian
100239478Sadrian	/* This is a fake device, so make sure we added it ourselves */
101239478Sadrian	return (BUS_PROBE_NOWILDCARD);
102239478Sadrian}
103239478Sadrian
104239478Sadrianstatic int
105239478Sadrianwiifb_scattach(device_t dev)
106239478Sadrian{
107239478Sadrian
108239478Sadrian	return (sc_attach_unit(device_get_unit(dev),
109239478Sadrian	    device_get_flags(dev) | SC_AUTODETECT_KBD));
110239478Sadrian}
111239478Sadrian
112239478Sadrian/*
113239478Sadrian * Video driver routines and glue.
114239478Sadrian */
115239478Sadrianstatic void			wiifb_reset_video(struct wiifb_softc *);
116239478Sadrianstatic void			wiifb_enable_interrupts(struct wiifb_softc *);
117239478Sadrianstatic void			wiifb_configure_tv_mode(struct wiifb_softc *);
118239478Sadrianstatic void			wiifb_setup_framebuffer(struct wiifb_softc *);
119239478Sadrianstatic int			wiifb_configure(int);
120239478Sadrianstatic vi_probe_t		wiifb_probe;
121239478Sadrianstatic vi_init_t		wiifb_init;
122239478Sadrianstatic vi_get_info_t		wiifb_get_info;
123239478Sadrianstatic vi_query_mode_t		wiifb_query_mode;
124239478Sadrianstatic vi_set_mode_t		wiifb_set_mode;
125239478Sadrianstatic vi_save_font_t		wiifb_save_font;
126239478Sadrianstatic vi_load_font_t		wiifb_load_font;
127239478Sadrianstatic vi_show_font_t		wiifb_show_font;
128239478Sadrianstatic vi_save_palette_t	wiifb_save_palette;
129239478Sadrianstatic vi_load_palette_t	wiifb_load_palette;
130239478Sadrianstatic vi_set_border_t		wiifb_set_border;
131239478Sadrianstatic vi_save_state_t		wiifb_save_state;
132239478Sadrianstatic vi_load_state_t		wiifb_load_state;
133239478Sadrianstatic vi_set_win_org_t		wiifb_set_win_org;
134239478Sadrianstatic vi_read_hw_cursor_t	wiifb_read_hw_cursor;
135239478Sadrianstatic vi_set_hw_cursor_t	wiifb_set_hw_cursor;
136239478Sadrianstatic vi_set_hw_cursor_shape_t	wiifb_set_hw_cursor_shape;
137239478Sadrianstatic vi_blank_display_t	wiifb_blank_display;
138239478Sadrianstatic vi_mmap_t		wiifb_mmap;
139239478Sadrianstatic vi_ioctl_t		wiifb_ioctl;
140239478Sadrianstatic vi_clear_t		wiifb_clear;
141239478Sadrianstatic vi_fill_rect_t		wiifb_fill_rect;
142239478Sadrianstatic vi_bitblt_t		wiifb_bitblt;
143239478Sadrianstatic vi_diag_t		wiifb_diag;
144239478Sadrianstatic vi_save_cursor_palette_t	wiifb_save_cursor_palette;
145239478Sadrianstatic vi_load_cursor_palette_t	wiifb_load_cursor_palette;
146239478Sadrianstatic vi_copy_t		wiifb_copy;
147239478Sadrianstatic vi_putp_t		wiifb_putp;
148239478Sadrianstatic vi_putc_t		wiifb_putc;
149239478Sadrianstatic vi_puts_t		wiifb_puts;
150239478Sadrianstatic vi_putm_t		wiifb_putm;
151239478Sadrian
152239478Sadrianstatic video_switch_t wiifbvidsw = {
153239478Sadrian	.probe			= wiifb_probe,
154239478Sadrian	.init			= wiifb_init,
155239478Sadrian	.get_info		= wiifb_get_info,
156239478Sadrian	.query_mode		= wiifb_query_mode,
157239478Sadrian	.set_mode		= wiifb_set_mode,
158239478Sadrian	.save_font		= wiifb_save_font,
159239478Sadrian	.load_font		= wiifb_load_font,
160239478Sadrian	.show_font		= wiifb_show_font,
161239478Sadrian	.save_palette		= wiifb_save_palette,
162239478Sadrian	.load_palette		= wiifb_load_palette,
163239478Sadrian	.set_border		= wiifb_set_border,
164239478Sadrian	.save_state		= wiifb_save_state,
165239478Sadrian	.load_state		= wiifb_load_state,
166239478Sadrian	.set_win_org		= wiifb_set_win_org,
167239478Sadrian	.read_hw_cursor		= wiifb_read_hw_cursor,
168239478Sadrian	.set_hw_cursor		= wiifb_set_hw_cursor,
169239478Sadrian	.set_hw_cursor_shape	= wiifb_set_hw_cursor_shape,
170239478Sadrian	.blank_display		= wiifb_blank_display,
171239478Sadrian	.mmap			= wiifb_mmap,
172239478Sadrian	.ioctl			= wiifb_ioctl,
173239478Sadrian	.clear			= wiifb_clear,
174239478Sadrian	.fill_rect		= wiifb_fill_rect,
175239478Sadrian	.bitblt			= wiifb_bitblt,
176239478Sadrian	.diag			= wiifb_diag,
177239478Sadrian	.save_cursor_palette	= wiifb_save_cursor_palette,
178239478Sadrian	.load_cursor_palette	= wiifb_load_cursor_palette,
179239478Sadrian	.copy			= wiifb_copy,
180239478Sadrian	.putp			= wiifb_putp,
181239478Sadrian	.putc			= wiifb_putc,
182239478Sadrian	.puts			= wiifb_puts,
183239478Sadrian	.putm			= wiifb_putm,
184239478Sadrian};
185239478Sadrian
186239478SadrianVIDEO_DRIVER(wiifb, wiifbvidsw, wiifb_configure);
187239478Sadrian
188239478Sadrianextern sc_rndr_sw_t txtrndrsw;
189239478SadrianRENDERER(wiifb, 0, txtrndrsw, gfb_set);
190239478SadrianRENDERER_MODULE(wiifb, gfb_set);
191239478Sadrian
192239478Sadrianstatic struct wiifb_softc wiifb_softc;
193239478Sadrianstatic uint16_t wiifb_static_window[ROW*COL];
194239478Sadrianextern u_char dflt_font_8[];
195239478Sadrian
196239478Sadrian/*
197239478Sadrian * Map the syscons colors to YUY2 (Y'UV422).
198239478Sadrian * Some colours are an approximation.
199239478Sadrian *
200239478Sadrian * The Wii has a 16 bit pixel, so each 32 bit DWORD encodes
201239478Sadrian * two pixels.  The upper 16 bits is for pixel 0 (left hand pixel
202239478Sadrian * in a pair), the lower 16 bits is for pixel 1.
203239478Sadrian *
204239478Sadrian * For now, we're going to ignore that entirely and just use the
205239478Sadrian * lower 16 bits for each pixel. We'll take the upper value into
206239478Sadrian * account later.
207239478Sadrian */
208239478Sadrianstatic uint32_t wiifb_cmap[16] = {
209239478Sadrian	0x00800080,	/* Black */
210239478Sadrian	0x1dff1d6b,	/* Blue */
211239478Sadrian	0x4b554b4a,	/* Green */
212239478Sadrian	0x80808080,	/* Cyan */
213239478Sadrian	0x4c544cff,	/* Red */
214239478Sadrian	0x3aaa34b5,	/* Magenta */
215239478Sadrian	0x7140718a,	/* Brown */
216239478Sadrian	0xff80ff80,	/* White */
217239478Sadrian	0x80808080,	/* Gray */
218239478Sadrian	0xc399c36a,	/* Bright Blue */
219239478Sadrian	0xd076d074,	/* Bright Green */
220239478Sadrian	0x80808080,	/* Bright Cyan */
221239478Sadrian	0x4c544cff,	/* Bright Red */
222239478Sadrian	0x3aaa34b5,	/* Bright Magenta */
223239478Sadrian	0xe100e194,	/* Bright Yellow */
224239478Sadrian	0xff80ff80	/* Bright White */
225239478Sadrian};
226239478Sadrian
227239478Sadrianstatic struct wiifb_mode_desc wiifb_modes[] = {
228239478Sadrian	[WIIFB_MODE_NTSC_480i] = {
229239478Sadrian		"NTSC 480i",
230239478Sadrian		640, 480,
231239478Sadrian		525,
232239478Sadrian		WIIFB_MODE_FLAG_INTERLACED,
233239478Sadrian	},
234239478Sadrian	[WIIFB_MODE_NTSC_480p] = {
235239478Sadrian		"NTSC 480p",
236239478Sadrian		640, 480,
237239478Sadrian		525,
238239478Sadrian		WIIFB_MODE_FLAG_PROGRESSIVE,
239239478Sadrian	},
240239478Sadrian	[WIIFB_MODE_PAL_576i] = {
241239478Sadrian		"PAL 576i (50Hz)",
242239478Sadrian		640, 574,
243239478Sadrian		625,
244239478Sadrian		WIIFB_MODE_FLAG_INTERLACED,
245239478Sadrian	},
246239478Sadrian	[WIIFB_MODE_PAL_480i] = {
247239478Sadrian		"PAL 480i (60Hz)",
248239478Sadrian		640, 480,
249239478Sadrian		525,
250239478Sadrian		WIIFB_MODE_FLAG_INTERLACED,
251239478Sadrian	},
252239478Sadrian	[WIIFB_MODE_PAL_480p] = {
253239478Sadrian		"PAL 480p",
254239478Sadrian		640, 480,
255239478Sadrian		525,
256239478Sadrian		WIIFB_MODE_FLAG_PROGRESSIVE,
257239478Sadrian	},
258239478Sadrian};
259239478Sadrian
260239478Sadrianstatic const uint32_t wiifb_filter_coeft[] = {
261239478Sadrian	0x1ae771f0, 0x0db4a574, 0x00c1188e, 0xc4c0cbe2, 0xfcecdecf,
262239478Sadrian	0x13130f08, 0x00080c0f
263239478Sadrian};
264239478Sadrian
265239478Sadrianstatic __inline int
266239478Sadrianwiifb_background(uint8_t attr)
267239478Sadrian{
268239478Sadrian
269239478Sadrian	return (attr >> 4);
270239478Sadrian}
271239478Sadrian
272239478Sadrianstatic __inline int
273239478Sadrianwiifb_foreground(uint8_t attr)
274239478Sadrian{
275239478Sadrian
276239478Sadrian	return (attr & 0x0f);
277239478Sadrian}
278239478Sadrian
279239478Sadrianstatic void
280239478Sadrianwiifb_reset_video(struct wiifb_softc *sc)
281239478Sadrian{
282239478Sadrian	struct wiifb_dispcfg dc;
283239478Sadrian
284239478Sadrian	wiifb_dispcfg_read(sc, &dc);
285239478Sadrian	dc.dc_reset = 1;
286239478Sadrian	wiifb_dispcfg_write(sc, &dc);
287239478Sadrian	dc.dc_reset = 0;
288239478Sadrian	wiifb_dispcfg_write(sc, &dc);
289239478Sadrian}
290239478Sadrian
291239478Sadrianstatic void
292239478Sadrianwiifb_enable_interrupts(struct wiifb_softc *sc)
293239478Sadrian{
294239478Sadrian	struct wiifb_dispint di;
295239478Sadrian
296239478Sadrian#ifdef notyet
297239478Sadrian	/*
298239478Sadrian	 * Display Interrupt 0
299239478Sadrian	 */
300239478Sadrian	di.di_htiming = 1;
301239478Sadrian	di.di_vtiming = 1;
302239478Sadrian	di.di_enable = 1;
303239478Sadrian	di.di_irq    = 1;
304239478Sadrian	wiifb_dispint_write(sc, 0, &di);
305239478Sadrian
306239478Sadrian	/*
307239478Sadrian	 * Display Interrupt 1
308239478Sadrian	 */
309239478Sadrian	di.di_htiming = sc->sc_format == WIIFB_FORMAT_PAL ? 433 : 430;
310239478Sadrian	di.di_vtiming = sc->sc_mode->fd_lines;
311239478Sadrian	di.di_enable = 1;
312239478Sadrian	di.di_irq    = 1;
313239478Sadrian	if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
314239478Sadrian		di.di_vtiming /= 2;
315239478Sadrian	wiifb_dispint_write(sc, 1, &di);
316239478Sadrian
317239478Sadrian	/*
318239478Sadrian	 * Display Interrupts 2 and 3 are not used.
319239478Sadrian	 */
320239478Sadrian	memset(&di, 0, sizeof(di));
321239478Sadrian	wiifb_dispint_write(sc, 2, &di);
322239478Sadrian	wiifb_dispint_write(sc, 3, &di);
323239478Sadrian#else
324239478Sadrian	memset(&di, 0, sizeof(di));
325239478Sadrian	wiifb_dispint_write(sc, 0, &di);
326239478Sadrian	wiifb_dispint_write(sc, 1, &di);
327239478Sadrian	wiifb_dispint_write(sc, 2, &di);
328239478Sadrian	wiifb_dispint_write(sc, 3, &di);
329239478Sadrian#endif
330239478Sadrian}
331239478Sadrian
332239478Sadrian/*
333239478Sadrian * Reference gcnfb.c for an in depth explanation.
334239478Sadrian * XXX only works with NTSC.
335239478Sadrian */
336239478Sadrianstatic void
337239478Sadrianwiifb_configure_tv_mode(struct wiifb_softc *sc)
338239478Sadrian{
339239478Sadrian	struct wiifb_vtiming vt;
340239478Sadrian	struct wiifb_hscaling hs;
341239478Sadrian	struct wiifb_htiming0 ht0;
342239478Sadrian	struct wiifb_htiming1 ht1;
343239478Sadrian	struct wiifb_vtimingodd vto;
344239478Sadrian	struct wiifb_vtimingeven vte;
345239478Sadrian	struct wiifb_burstblankodd bbo;
346239478Sadrian	struct wiifb_burstblankeven bbe;
347239478Sadrian	struct wiifb_picconf pc;
348239478Sadrian	struct wiifb_mode_desc *mode = sc->sc_mode;
349239478Sadrian	unsigned int height = mode->fd_height;
350239478Sadrian	unsigned int width = mode->fd_width;
351239478Sadrian	unsigned int eqpulse, interlacebias, shift;
352239478Sadrian	const unsigned int maxwidth = 714;
353239478Sadrian	unsigned int hblanking = maxwidth - width;
354239478Sadrian	unsigned int hmargin = hblanking / 2;
355239478Sadrian	unsigned int A = 20 + hmargin, C = 60 + hblanking - hmargin;
356239478Sadrian	unsigned int maxheight = 484;
357239478Sadrian	unsigned int P = 2 * (20 - 10 + 1);
358239478Sadrian	unsigned int Q = 1;
359239478Sadrian	unsigned int vblanking = maxheight - height;
360239478Sadrian	unsigned int vmargin = vblanking / 2;
361239478Sadrian	unsigned int prb = vmargin;
362239478Sadrian	unsigned int psb = vblanking - vmargin;
363239478Sadrian	int i;
364239478Sadrian
365239478Sadrian	/*
366239478Sadrian	 * Vertical timing.
367239478Sadrian	 */
368239478Sadrian	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) {
369239478Sadrian		vt.vt_actvideo = height / 2;
370239478Sadrian		interlacebias = 1;
371239478Sadrian		shift = 0;
372239478Sadrian	} else {
373239478Sadrian		vt.vt_actvideo = height;
374239478Sadrian		interlacebias = 0;
375239478Sadrian		shift = 1;
376239478Sadrian	}
377239478Sadrian	/* Lines of equalization */
378239478Sadrian	if (mode->fd_lines == 625)
379239478Sadrian		eqpulse = 2 * 2.5;
380239478Sadrian	else
381239478Sadrian		eqpulse = 2 * 3;
382239478Sadrian	vt.vt_eqpulse = eqpulse << shift;
383239478Sadrian	wiifb_vtiming_write(sc, &vt);
384239478Sadrian
385239478Sadrian	/*
386239478Sadrian	 * Horizontal timings.
387239478Sadrian	 */
388239478Sadrian	ht0.ht0_hlinew = 858 / 2;
389239478Sadrian	ht1.ht1_hsyncw = 64;
390239478Sadrian	ht0.ht0_hcolourstart = 71;
391239478Sadrian	ht0.ht0_hcolourend = 71 + 34;
392239478Sadrian	ht1.ht1_hblankstart = (858 / 2) - A;
393239478Sadrian	ht1.ht1_hblankend = 64 + C;
394239478Sadrian	wiifb_htiming0_write(sc, &ht0);
395239478Sadrian	wiifb_htiming1_write(sc, &ht1);
396239478Sadrian
397239478Sadrian	/*
398239478Sadrian	 * Vertical timing odd/even.
399239478Sadrian	 */
400239478Sadrian	if (vmargin & 1) {
401239478Sadrian		vto.vto_preb = (P + interlacebias + prb) << shift;
402239478Sadrian		vto.vto_postb = (Q - interlacebias + psb) << shift;
403239478Sadrian		vte.vte_preb = (P + prb) << shift;
404239478Sadrian		vte.vte_postb = (Q - psb) << shift;
405239478Sadrian	} else {
406239478Sadrian		/* XXX if this isn't 0, it doesn't work? */
407239478Sadrian		prb = 0;
408239478Sadrian		psb = 0;
409239478Sadrian		vte.vte_preb = (P + interlacebias + prb) << shift;
410239478Sadrian		vte.vte_postb = (Q - interlacebias + psb) << shift;
411239478Sadrian		vto.vto_preb = (P + prb) << shift;
412239478Sadrian		vto.vto_postb = (Q - psb) << shift;
413239478Sadrian	}
414239478Sadrian	wiifb_vtimingodd_write(sc, &vto);
415239478Sadrian	wiifb_vtimingeven_write(sc, &vte);
416239478Sadrian
417239478Sadrian	/*
418239478Sadrian	 * Burst blanking odd/even interval.
419239478Sadrian	 */
420239478Sadrian	bbo.bbo_bs1 = 2 * (18 - 7 + 1);
421239478Sadrian	bbe.bbe_bs2 = bbo.bbo_bs3 = bbe.bbe_bs4 = bbo.bbo_bs1;
422239478Sadrian	bbo.bbo_be1 = 2 * (525 - 7 + 1);
423239478Sadrian	bbe.bbe_be2 = bbo.bbo_be3 = bbe.bbe_be4 = bbo.bbo_be1;
424239478Sadrian	wiifb_burstblankodd_write(sc, &bbo);
425239478Sadrian	wiifb_burstblankeven_write(sc, &bbe);
426239478Sadrian
427239478Sadrian	/*
428239478Sadrian	 * Picture configuration.
429239478Sadrian	 */
430239478Sadrian	pc.pc_strides = (mode->fd_width * 2) / 32;
431239478Sadrian	if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
432239478Sadrian		pc.pc_strides *= 2;
433239478Sadrian	pc.pc_reads = (mode->fd_width * 2) / 32;
434239478Sadrian	wiifb_picconf_write(sc, &pc);
435239478Sadrian
436239478Sadrian	/*
437239478Sadrian	 * Horizontal scaling disabled.
438239478Sadrian	 */
439239478Sadrian	hs.hs_enable = 0;
440239478Sadrian	hs.hs_step = 256;
441239478Sadrian	wiifb_hscaling_write(sc, &hs);
442239478Sadrian
443239478Sadrian	/*
444239478Sadrian	 * Filter coeficient table.
445239478Sadrian	 */
446239478Sadrian	for (i = 0; i < 7; i++)
447239478Sadrian		wiifb_filtcoeft_write(sc, i, wiifb_filter_coeft[i]);
448239478Sadrian
449239478Sadrian	/*
450239478Sadrian	 * Anti alias.
451239478Sadrian	 */
452239478Sadrian	wiifb_antialias_write(sc, 0x00ff0000);
453239478Sadrian
454239478Sadrian	/*
455239478Sadrian	 * Video clock.
456239478Sadrian	 */
457239478Sadrian	wiifb_videoclk_write(sc,
458239478Sadrian	    mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED ? 0 : 1);
459239478Sadrian
460239478Sadrian	/*
461239478Sadrian	 * Disable horizontal scaling width.
462239478Sadrian	 */
463239478Sadrian	wiifb_hscalingw_write(sc, mode->fd_width);
464239478Sadrian
465239478Sadrian	/*
466239478Sadrian	 * DEBUG mode borders. Not used.
467239478Sadrian	 */
468239478Sadrian	wiifb_hborderend_write(sc, 0);
469239478Sadrian	wiifb_hborderstart_write(sc, 0);
470239478Sadrian
471239478Sadrian	/*
472239478Sadrian	 * XXX unknown registers.
473239478Sadrian	 */
474239478Sadrian	wiifb_unknown1_write(sc, 0x00ff);
475239478Sadrian	wiifb_unknown2_write(sc, 0x00ff00ff);
476239478Sadrian	wiifb_unknown3_write(sc, 0x00ff00ff);
477239478Sadrian}
478239478Sadrian
479239478Sadrianstatic void
480239478Sadrianwiifb_setup_framebuffer(struct wiifb_softc *sc)
481239478Sadrian{
482239478Sadrian	intptr_t addr = sc->sc_fb_addr;
483239478Sadrian	struct wiifb_topfieldbasel tfbl;
484239478Sadrian	struct wiifb_bottomfieldbasel bfbl;
485239478Sadrian	struct wiifb_topfieldbaser tfbr;
486239478Sadrian	struct wiifb_bottomfieldbaser bfbr;
487239478Sadrian
488239478Sadrian	tfbl.tfbl_fbaddr     = addr >> 5;
489239478Sadrian	tfbl.tfbl_xoffset    = (addr / 2) & 0xf;
490239478Sadrian	tfbl.tfbl_pageoffbit = 1;
491239478Sadrian	wiifb_topfieldbasel_write(sc, &tfbl);
492239478Sadrian
493239478Sadrian	if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED)
494239478Sadrian		addr += sc->sc_mode->fd_width * 2;
495239478Sadrian	bfbl.bfbl_fbaddr     = addr >> 5;
496239478Sadrian	bfbl.bfbl_xoffset    = (addr / 2) & 0xf;
497239478Sadrian	bfbl.bfbl_pageoffbit = 1;
498239478Sadrian	wiifb_bottomfieldbasel_write(sc, &bfbl);
499239478Sadrian
500239478Sadrian	/*
501239478Sadrian	 * Only used used for 3D.
502239478Sadrian	 */
503239478Sadrian	memset(&tfbr, 0, sizeof(tfbr));
504239478Sadrian	memset(&bfbr, 0, sizeof(bfbr));
505239478Sadrian	wiifb_topfieldbaser_write(sc, &tfbr);
506239478Sadrian	wiifb_bottomfieldbaser_write(sc, &bfbr);
507239478Sadrian}
508239478Sadrian
509239478Sadrianstatic int
510239478Sadrianwiifb_configure(int flags)
511239478Sadrian{
512239478Sadrian	struct wiifb_softc *sc;
513239478Sadrian	struct wiifb_dispcfg dc;
514239478Sadrian	int progressive;
515239478Sadrian
516239478Sadrian	sc = &wiifb_softc;
517249965Srpaulo	if (sc->sc_initialized) {
518249965Srpaulo		/* XXX We should instead use bus_space */
519249965Srpaulo		sc->sc_fb_addr = (intptr_t)pmap_mapdev(WIIFB_FB_ADDR, WIIFB_FB_LEN);
520249965Srpaulo		sc->sc_reg_addr = (intptr_t)pmap_mapdev(WIIFB_REG_ADDR, WIIFB_REG_LEN);
521239478Sadrian		return 0;
522249965Srpaulo	}
523239478Sadrian
524239478Sadrian	sc->sc_console = 1;
525239478Sadrian
526239478Sadrian	sc->sc_fb_addr = WIIFB_FB_ADDR;
527239478Sadrian	sc->sc_fb_size = WIIFB_FB_LEN;
528239478Sadrian
529239478Sadrian	sc->sc_reg_addr = WIIFB_REG_ADDR;
530239478Sadrian	sc->sc_reg_size = WIIFB_REG_LEN;
531239478Sadrian
532239478Sadrian	wiifb_reset_video(sc);
533239478Sadrian	wiifb_dispcfg_read(sc, &dc);
534239478Sadrian	sc->sc_format = dc.dc_format;
535239478Sadrian	sc->sc_component = wiifb_component_enabled(sc);
536239478Sadrian	progressive = dc.dc_noninterlaced;
537239478Sadrian	switch (sc->sc_format) {
538239478Sadrian	case WIIFB_FORMAT_MPAL:
539239478Sadrian	case WIIFB_FORMAT_DEBUG:
540239478Sadrian	case WIIFB_FORMAT_NTSC:
541239478Sadrian		sc->sc_mode = progressive ?
542239478Sadrian		    &wiifb_modes[WIIFB_MODE_NTSC_480p] :
543239478Sadrian		    &wiifb_modes[WIIFB_MODE_NTSC_480i];
544239478Sadrian		break;
545239478Sadrian	case WIIFB_FORMAT_PAL:
546239478Sadrian		sc->sc_mode = progressive ?
547239478Sadrian		    &wiifb_modes[WIIFB_MODE_PAL_480p] :
548239478Sadrian		    &wiifb_modes[WIIFB_MODE_PAL_480i];
549239478Sadrian		break;
550239478Sadrian	}
551239478Sadrian	sc->sc_height = sc->sc_mode->fd_height;
552239478Sadrian	sc->sc_width = sc->sc_mode->fd_width;
553239478Sadrian	/* Usually we multiply by 4, but I think this looks better. */
554239478Sadrian	sc->sc_stride = sc->sc_width * 2;
555239478Sadrian
556239478Sadrian	wiifb_init(0, &sc->sc_va, 0);
557239478Sadrian
558239478Sadrian	sc->sc_initialized = 1;
559239478Sadrian
560239478Sadrian	return (0);
561239478Sadrian}
562239478Sadrian
563239478Sadrianstatic int
564239478Sadrianwiifb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
565239478Sadrian{
566239478Sadrian
567239478Sadrian	return (0);
568239478Sadrian}
569239478Sadrian
570239478Sadrianstatic int
571239478Sadrianwiifb_init(int unit, video_adapter_t *adp, int flags)
572239478Sadrian{
573239478Sadrian	struct wiifb_softc *sc;
574239478Sadrian	video_info_t *vi;
575239478Sadrian
576239478Sadrian	sc = (struct wiifb_softc *)adp;
577239478Sadrian	vi = &adp->va_info;
578239478Sadrian
579239478Sadrian	vid_init_struct(adp, "wiifb", -1, unit);
580239478Sadrian
581239478Sadrian	sc->sc_font = dflt_font_8;
582239478Sadrian	vi->vi_cheight = WIIFB_FONT_HEIGHT;
583239478Sadrian	vi->vi_width = sc->sc_width/8;
584239478Sadrian	vi->vi_height = sc->sc_height/vi->vi_cheight;
585239478Sadrian	vi->vi_cwidth = 8;
586239478Sadrian
587239478Sadrian	/*
588239478Sadrian	 * Clamp width/height to syscons maximums
589239478Sadrian	 */
590239478Sadrian	if (vi->vi_width > COL)
591239478Sadrian		vi->vi_width = COL;
592239478Sadrian	if (vi->vi_height > ROW)
593239478Sadrian		vi->vi_height = ROW;
594239478Sadrian
595239478Sadrian	sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
596239478Sadrian	sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2;
597239478Sadrian
598239478Sadrian	adp->va_window = (vm_offset_t) wiifb_static_window;
599239478Sadrian	/* XXX no colour support */
600239478Sadrian	adp->va_flags |= V_ADP_FONT | /*V_ADP_COLOR |*/ V_ADP_MODECHANGE;
601239478Sadrian
602239478Sadrian	vid_register(&sc->sc_va);
603239478Sadrian
604239478Sadrian	wiifb_configure_tv_mode(sc);
605239478Sadrian	wiifb_setup_framebuffer(sc);
606239478Sadrian	wiifb_enable_interrupts(sc);
607239478Sadrian	wiifb_clear(adp);
608239478Sadrian
609239478Sadrian	return (0);
610239478Sadrian}
611239478Sadrian
612239478Sadrianstatic int
613239478Sadrianwiifb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
614239478Sadrian{
615239478Sadrian
616239478Sadrian	bcopy(&adp->va_info, info, sizeof(*info));
617239478Sadrian	return (0);
618239478Sadrian}
619239478Sadrian
620239478Sadrianstatic int
621239478Sadrianwiifb_query_mode(video_adapter_t *adp, video_info_t *info)
622239478Sadrian{
623239478Sadrian
624239478Sadrian	return (0);
625239478Sadrian}
626239478Sadrian
627239478Sadrianstatic int
628239478Sadrianwiifb_set_mode(video_adapter_t *adp, int mode)
629239478Sadrian{
630239478Sadrian
631239478Sadrian	return (0);
632239478Sadrian}
633239478Sadrian
634239478Sadrianstatic int
635239478Sadrianwiifb_save_font(video_adapter_t *adp, int page, int size, int width,
636239478Sadrian    u_char *data, int c, int count)
637239478Sadrian{
638239478Sadrian
639239478Sadrian	return (0);
640239478Sadrian}
641239478Sadrian
642239478Sadrianstatic int
643239478Sadrianwiifb_load_font(video_adapter_t *adp, int page, int size, int width,
644239478Sadrian    u_char *data, int c, int count)
645239478Sadrian{
646239478Sadrian	struct wiifb_softc *sc = (struct wiifb_softc *)adp;
647239478Sadrian
648239478Sadrian	sc->sc_font = data;
649239478Sadrian
650239478Sadrian	return (0);
651239478Sadrian}
652239478Sadrian
653239478Sadrianstatic int
654239478Sadrianwiifb_show_font(video_adapter_t *adp, int page)
655239478Sadrian{
656239478Sadrian
657239478Sadrian	return (0);
658239478Sadrian}
659239478Sadrian
660239478Sadrianstatic int
661239478Sadrianwiifb_save_palette(video_adapter_t *adp, u_char *palette)
662239478Sadrian{
663239478Sadrian
664239478Sadrian	return (0);
665239478Sadrian}
666239478Sadrian
667239478Sadrianstatic int
668239478Sadrianwiifb_load_palette(video_adapter_t *adp, u_char *palette)
669239478Sadrian{
670239478Sadrian
671239478Sadrian	return (0);
672239478Sadrian}
673239478Sadrian
674239478Sadrianstatic int
675239478Sadrianwiifb_set_border(video_adapter_t *adp, int border)
676239478Sadrian{
677239478Sadrian
678239478Sadrian	return (wiifb_blank_display(adp, border));
679239478Sadrian}
680239478Sadrian
681239478Sadrianstatic int
682239478Sadrianwiifb_save_state(video_adapter_t *adp, void *p, size_t size)
683239478Sadrian{
684239478Sadrian
685239478Sadrian	return (0);
686239478Sadrian}
687239478Sadrian
688239478Sadrianstatic int
689239478Sadrianwiifb_load_state(video_adapter_t *adp, void *p)
690239478Sadrian{
691239478Sadrian
692239478Sadrian	return (0);
693239478Sadrian}
694239478Sadrian
695239478Sadrianstatic int
696239478Sadrianwiifb_set_win_org(video_adapter_t *adp, off_t offset)
697239478Sadrian{
698239478Sadrian
699239478Sadrian	return (0);
700239478Sadrian}
701239478Sadrian
702239478Sadrianstatic int
703239478Sadrianwiifb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
704239478Sadrian{
705239478Sadrian
706239478Sadrian	*col = *row = 0;
707239478Sadrian
708239478Sadrian	return (0);
709239478Sadrian}
710239478Sadrian
711239478Sadrianstatic int
712239478Sadrianwiifb_set_hw_cursor(video_adapter_t *adp, int col, int row)
713239478Sadrian{
714239478Sadrian
715239478Sadrian	return (0);
716239478Sadrian}
717239478Sadrian
718239478Sadrianstatic int
719239478Sadrianwiifb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
720239478Sadrian    int celsize, int blink)
721239478Sadrian{
722239478Sadrian
723239478Sadrian	return (0);
724239478Sadrian}
725239478Sadrian
726239478Sadrianstatic int
727239478Sadrianwiifb_blank_display(video_adapter_t *adp, int mode)
728239478Sadrian{
729239478Sadrian	struct wiifb_softc *sc = (struct wiifb_softc *)adp;
730239478Sadrian	uint32_t *p;
731239478Sadrian
732239478Sadrian	for (p = (uint32_t *)sc->sc_fb_addr;
733239478Sadrian	    p < (uint32_t *)(sc->sc_fb_addr + sc->sc_fb_size);
734239478Sadrian	    p++)
735239478Sadrian		*p = wiifb_cmap[wiifb_background(SC_NORM_ATTR)];
736239478Sadrian
737239478Sadrian	return (0);
738239478Sadrian}
739239478Sadrian
740239478Sadrianstatic int
741239478Sadrianwiifb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
742239478Sadrian    int prot, vm_memattr_t *memattr)
743239478Sadrian{
744239478Sadrian	struct wiifb_softc *sc;
745239478Sadrian
746239478Sadrian	sc = (struct wiifb_softc *)adp;
747239478Sadrian
748239478Sadrian	/*
749239478Sadrian	 * This might be a legacy VGA mem request: if so, just point it at the
750239478Sadrian	 * framebuffer, since it shouldn't be touched
751239478Sadrian	 */
752239478Sadrian	if (offset < sc->sc_stride*sc->sc_height) {
753239478Sadrian		*paddr = sc->sc_fb_addr + offset;
754239478Sadrian		return (0);
755239478Sadrian	}
756239478Sadrian
757239478Sadrian	return (EINVAL);
758239478Sadrian}
759239478Sadrian
760239478Sadrianstatic int
761239478Sadrianwiifb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
762239478Sadrian{
763239478Sadrian
764239478Sadrian	return (0);
765239478Sadrian}
766239478Sadrian
767239478Sadrianstatic int
768239478Sadrianwiifb_clear(video_adapter_t *adp)
769239478Sadrian{
770239478Sadrian
771239478Sadrian	return (wiifb_blank_display(adp, 0));
772239478Sadrian}
773239478Sadrian
774239478Sadrianstatic int
775239478Sadrianwiifb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
776239478Sadrian{
777239478Sadrian
778239478Sadrian	return (0);
779239478Sadrian}
780239478Sadrian
781239478Sadrianstatic int
782239478Sadrianwiifb_bitblt(video_adapter_t *adp, ...)
783239478Sadrian{
784239478Sadrian
785239478Sadrian	return (0);
786239478Sadrian}
787239478Sadrian
788239478Sadrianstatic int
789239478Sadrianwiifb_diag(video_adapter_t *adp, int level)
790239478Sadrian{
791239478Sadrian
792239478Sadrian	return (0);
793239478Sadrian}
794239478Sadrian
795239478Sadrianstatic int
796239478Sadrianwiifb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
797239478Sadrian{
798239478Sadrian
799239478Sadrian	return (0);
800239478Sadrian}
801239478Sadrian
802239478Sadrianstatic int
803239478Sadrianwiifb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
804239478Sadrian{
805239478Sadrian
806239478Sadrian	return (0);
807239478Sadrian}
808239478Sadrian
809239478Sadrianstatic int
810239478Sadrianwiifb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
811239478Sadrian{
812239478Sadrian
813239478Sadrian	return (0);
814239478Sadrian}
815239478Sadrian
816239478Sadrianstatic int
817239478Sadrianwiifb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
818239478Sadrian    int size, int bpp, int bit_ltor, int byte_ltor)
819239478Sadrian{
820239478Sadrian
821239478Sadrian	return (0);
822239478Sadrian}
823239478Sadrian
824239478Sadrianstatic int
825239478Sadrianwiifb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
826239478Sadrian{
827239478Sadrian	struct wiifb_softc *sc;
828239478Sadrian	int row;
829239478Sadrian	int col;
830239478Sadrian	int i, j, k;
831239478Sadrian	uint32_t *addr;
832239478Sadrian	u_char *p;
833239478Sadrian	uint32_t fg, bg;
834239478Sadrian	unsigned long pixel[2];
835239478Sadrian
836239478Sadrian	sc = (struct wiifb_softc *)adp;
837239478Sadrian	row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
838239478Sadrian	col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth / 2;
839239478Sadrian	p = sc->sc_font + c*WIIFB_FONT_HEIGHT;
840239478Sadrian	addr = (uint32_t *)sc->sc_fb_addr
841239478Sadrian	    + (row + sc->sc_ymargin)*(sc->sc_stride/4)
842239478Sadrian	    + col + sc->sc_xmargin;
843239478Sadrian
844239478Sadrian	bg = wiifb_cmap[wiifb_background(a)];
845239478Sadrian	fg = wiifb_cmap[wiifb_foreground(a)];
846239478Sadrian
847239478Sadrian	for (i = 0; i < WIIFB_FONT_HEIGHT; i++) {
848239478Sadrian		for (j = 0, k = 7; j < 4; j++, k--) {
849239478Sadrian			if ((p[i] & (1 << k)) == 0)
850239478Sadrian				pixel[0] = bg;
851239478Sadrian			else
852239478Sadrian				pixel[0] = fg;
853239478Sadrian			k--;
854239478Sadrian			if ((p[i] & (1 << k)) == 0)
855239478Sadrian				pixel[1] = bg;
856239478Sadrian			else
857239478Sadrian				pixel[1] = fg;
858239478Sadrian
859239478Sadrian			addr[j] = (pixel[0] & 0xffff00ff) |
860239478Sadrian			          (pixel[1] & 0x0000ff00);
861239478Sadrian		}
862239478Sadrian		addr += (sc->sc_stride/4);
863239478Sadrian	}
864239478Sadrian
865239478Sadrian        return (0);
866239478Sadrian}
867239478Sadrian
868239478Sadrianstatic int
869239478Sadrianwiifb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
870239478Sadrian{
871239478Sadrian	int i;
872239478Sadrian
873239478Sadrian	for (i = 0; i < len; i++)
874239478Sadrian		wiifb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
875239478Sadrian
876239478Sadrian	return (0);
877239478Sadrian}
878239478Sadrian
879239478Sadrianstatic int
880239478Sadrianwiifb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
881239478Sadrian    uint32_t pixel_mask, int size, int width)
882239478Sadrian{
883239478Sadrian
884239478Sadrian	return (0);
885239478Sadrian}
886