bcm2835_fb.c revision 239922
1239922Sgonzo/*-
2239922Sgonzo * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
3239922Sgonzo * All rights reserved.
4239922Sgonzo *
5239922Sgonzo * Redistribution and use in source and binary forms, with or without
6239922Sgonzo * modification, are permitted provided that the following conditions
7239922Sgonzo * are met:
8239922Sgonzo * 1. Redistributions of source code must retain the above copyright
9239922Sgonzo *    notice, this list of conditions and the following disclaimer.
10239922Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11239922Sgonzo *    notice, this list of conditions and the following disclaimer in the
12239922Sgonzo *    documentation and/or other materials provided with the distribution.
13239922Sgonzo *
14239922Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15239922Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16239922Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17239922Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18239922Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19239922Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20239922Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21239922Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22239922Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23239922Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24239922Sgonzo * SUCH DAMAGE.
25239922Sgonzo *
26239922Sgonzo */
27239922Sgonzo#include <sys/cdefs.h>
28239922Sgonzo__FBSDID("$FreeBSD: head/sys/arm/broadcom/bcm2835/bcm2835_fb.c 239922 2012-08-30 20:59:37Z gonzo $");
29239922Sgonzo
30239922Sgonzo#include <sys/param.h>
31239922Sgonzo#include <sys/systm.h>
32239922Sgonzo#include <sys/bio.h>
33239922Sgonzo#include <sys/bus.h>
34239922Sgonzo#include <sys/conf.h>
35239922Sgonzo#include <sys/endian.h>
36239922Sgonzo#include <sys/kernel.h>
37239922Sgonzo#include <sys/kthread.h>
38239922Sgonzo#include <sys/lock.h>
39239922Sgonzo#include <sys/malloc.h>
40239922Sgonzo#include <sys/module.h>
41239922Sgonzo#include <sys/mutex.h>
42239922Sgonzo#include <sys/queue.h>
43239922Sgonzo#include <sys/resource.h>
44239922Sgonzo#include <sys/rman.h>
45239922Sgonzo#include <sys/time.h>
46239922Sgonzo#include <sys/timetc.h>
47239922Sgonzo#include <sys/fbio.h>
48239922Sgonzo#include <sys/consio.h>
49239922Sgonzo
50239922Sgonzo#include <sys/kdb.h>
51239922Sgonzo
52239922Sgonzo#include <machine/bus.h>
53239922Sgonzo#include <machine/cpu.h>
54239922Sgonzo#include <machine/cpufunc.h>
55239922Sgonzo#include <machine/resource.h>
56239922Sgonzo#include <machine/frame.h>
57239922Sgonzo#include <machine/intr.h>
58239922Sgonzo
59239922Sgonzo#include <dev/fdt/fdt_common.h>
60239922Sgonzo#include <dev/ofw/ofw_bus.h>
61239922Sgonzo#include <dev/ofw/ofw_bus_subr.h>
62239922Sgonzo
63239922Sgonzo#include <dev/fb/fbreg.h>
64239922Sgonzo#include <dev/syscons/syscons.h>
65239922Sgonzo
66239922Sgonzo#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
67239922Sgonzo#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
68239922Sgonzo
69239922Sgonzo#define	BCMFB_FONT_HEIGHT	16
70239922Sgonzo
71239922Sgonzo#define FB_WIDTH		640
72239922Sgonzo#define FB_HEIGHT		480
73239922Sgonzo
74239922Sgonzostruct bcm_fb_config {
75239922Sgonzo	uint32_t	xres;
76239922Sgonzo	uint32_t	yres;
77239922Sgonzo	uint32_t	vxres;
78239922Sgonzo	uint32_t	vyres;
79239922Sgonzo	uint32_t	pitch;
80239922Sgonzo	uint32_t	bpp;
81239922Sgonzo	uint32_t	xoffset;
82239922Sgonzo	uint32_t	yoffset;
83239922Sgonzo	/* Filled by videocore */
84239922Sgonzo	uint32_t	base;
85239922Sgonzo	uint32_t	screen_size;
86239922Sgonzo};
87239922Sgonzo
88239922Sgonzostruct bcmsc_softc {
89239922Sgonzo	device_t		dev;
90239922Sgonzo	struct cdev *		cdev;
91239922Sgonzo	struct mtx		mtx;
92239922Sgonzo	bus_dma_tag_t		dma_tag;
93239922Sgonzo	bus_dmamap_t		dma_map;
94239922Sgonzo	struct bcm_fb_config*	fb_config;
95239922Sgonzo	bus_addr_t		fb_config_phys;
96239922Sgonzo	struct intr_config_hook	init_hook;
97239922Sgonzo
98239922Sgonzo};
99239922Sgonzo
100239922Sgonzostruct video_adapter_softc {
101239922Sgonzo	/* Videoadpater part */
102239922Sgonzo	video_adapter_t	va;
103239922Sgonzo	int		console;
104239922Sgonzo
105239922Sgonzo	intptr_t	fb_addr;
106239922Sgonzo	unsigned int	fb_size;
107239922Sgonzo
108239922Sgonzo	unsigned int	height;
109239922Sgonzo	unsigned int	width;
110239922Sgonzo	unsigned int	stride;
111239922Sgonzo
112239922Sgonzo	unsigned int	xmargin;
113239922Sgonzo	unsigned int	ymargin;
114239922Sgonzo
115239922Sgonzo	unsigned char	*font;
116239922Sgonzo	int		initialized;
117239922Sgonzo};
118239922Sgonzo
119239922Sgonzostatic struct bcmsc_softc *bcmsc_softc;
120239922Sgonzostatic struct video_adapter_softc va_softc;
121239922Sgonzo
122239922Sgonzo#define	bcm_fb_lock(_sc)	mtx_lock(&(_sc)->mtx)
123239922Sgonzo#define	bcm_fb_unlock(_sc)	mtx_unlock(&(_sc)->mtx)
124239922Sgonzo#define	bcm_fb_lock_assert(sc)	mtx_assert(&(_sc)->mtx, MA_OWNED)
125239922Sgonzo
126239922Sgonzostatic int bcm_fb_probe(device_t);
127239922Sgonzostatic int bcm_fb_attach(device_t);
128239922Sgonzostatic void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err);
129239922Sgonzo
130239922Sgonzostatic void
131239922Sgonzobcm_fb_init(void *arg)
132239922Sgonzo{
133239922Sgonzo	struct bcmsc_softc *sc = arg;
134239922Sgonzo	struct video_adapter_softc *va_sc = &va_softc;
135239922Sgonzo	int err;
136239922Sgonzo	volatile struct bcm_fb_config*	fb_config = sc->fb_config;
137239922Sgonzo
138239922Sgonzo	/* TODO: replace it with FDT stuff */
139239922Sgonzo	fb_config->xres = FB_WIDTH;
140239922Sgonzo	fb_config->yres = FB_HEIGHT;
141239922Sgonzo	fb_config->vxres = 0;
142239922Sgonzo	fb_config->vyres = 0;
143239922Sgonzo	fb_config->xoffset = 0;
144239922Sgonzo	fb_config->yoffset = 0;
145239922Sgonzo	fb_config->bpp = 24;
146239922Sgonzo	fb_config->base = 0;
147239922Sgonzo	fb_config->pitch = 0;
148239922Sgonzo	fb_config->screen_size = 0;
149239922Sgonzo
150239922Sgonzo	bus_dmamap_sync(sc->dma_tag, sc->dma_map,
151239922Sgonzo		BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
152239922Sgonzo	bcm_mbox_write(BCM2835_MBOX_CHAN_FB, sc->fb_config_phys);
153239922Sgonzo	bcm_mbox_read(BCM2835_MBOX_CHAN_FB, &err);
154239922Sgonzo	bus_dmamap_sync(sc->dma_tag, sc->dma_map,
155239922Sgonzo		BUS_DMASYNC_POSTREAD);
156239922Sgonzo
157239922Sgonzo	if (err == 0) {
158239922Sgonzo		device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n",
159239922Sgonzo			fb_config->xres, fb_config->yres,
160239922Sgonzo			fb_config->vxres, fb_config->vyres,
161239922Sgonzo			fb_config->xoffset, fb_config->yoffset,
162239922Sgonzo			fb_config->bpp);
163239922Sgonzo
164239922Sgonzo
165239922Sgonzo		device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n",
166239922Sgonzo			fb_config->pitch, fb_config->base,
167239922Sgonzo			fb_config->screen_size);
168239922Sgonzo
169239922Sgonzo		if (fb_config->base) {
170239922Sgonzo			va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size);
171239922Sgonzo			va_sc->fb_size = fb_config->screen_size;
172239922Sgonzo			va_sc->stride = fb_config->pitch;
173239922Sgonzo		}
174239922Sgonzo	}
175239922Sgonzo	else
176239922Sgonzo		device_printf(sc->dev, "Failed to set framebuffer info\n");
177239922Sgonzo
178239922Sgonzo	config_intrhook_disestablish(&sc->init_hook);
179239922Sgonzo}
180239922Sgonzo
181239922Sgonzostatic int
182239922Sgonzobcm_fb_probe(device_t dev)
183239922Sgonzo{
184239922Sgonzo	int error;
185239922Sgonzo
186239922Sgonzo	if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb"))
187239922Sgonzo		return (ENXIO);
188239922Sgonzo
189239922Sgonzo	device_set_desc(dev, "BCM2835 framebuffer device");
190239922Sgonzo
191239922Sgonzo	error = sc_probe_unit(device_get_unit(dev),
192239922Sgonzo	    device_get_flags(dev) | SC_AUTODETECT_KBD);
193239922Sgonzo
194239922Sgonzo	if (error != 0)
195239922Sgonzo		return (error);
196239922Sgonzo
197239922Sgonzo	return (BUS_PROBE_DEFAULT);
198239922Sgonzo}
199239922Sgonzo
200239922Sgonzostatic int
201239922Sgonzobcm_fb_attach(device_t dev)
202239922Sgonzo{
203239922Sgonzo	struct bcmsc_softc *sc = device_get_softc(dev);
204239922Sgonzo	int dma_size = sizeof(struct bcm_fb_config);
205239922Sgonzo	int err;
206239922Sgonzo
207239922Sgonzo	if (bcmsc_softc)
208239922Sgonzo		return (ENXIO);
209239922Sgonzo
210239922Sgonzo	bcmsc_softc = sc;
211239922Sgonzo
212239922Sgonzo	sc->dev = dev;
213239922Sgonzo	mtx_init(&sc->mtx, "bcm2835fb", "fb", MTX_DEF);
214239922Sgonzo
215239922Sgonzo	err = bus_dma_tag_create(
216239922Sgonzo	    bus_get_dma_tag(sc->dev),
217239922Sgonzo	    PAGE_SIZE, 0,		/* alignment, boundary */
218239922Sgonzo	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
219239922Sgonzo	    BUS_SPACE_MAXADDR,		/* highaddr */
220239922Sgonzo	    NULL, NULL,			/* filter, filterarg */
221239922Sgonzo	    dma_size, 1,		/* maxsize, nsegments */
222239922Sgonzo	    dma_size, 0,		/* maxsegsize, flags */
223239922Sgonzo	    NULL, NULL,			/* lockfunc, lockarg */
224239922Sgonzo	    &sc->dma_tag);
225239922Sgonzo
226239922Sgonzo	err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config,
227239922Sgonzo	    0, &sc->dma_map);
228239922Sgonzo	if (err) {
229239922Sgonzo		device_printf(dev, "cannot allocate framebuffer\n");
230239922Sgonzo		goto fail;
231239922Sgonzo	}
232239922Sgonzo
233239922Sgonzo	err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config,
234239922Sgonzo	    dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT);
235239922Sgonzo
236239922Sgonzo	if (err) {
237239922Sgonzo		device_printf(dev, "cannot load DMA map\n");
238239922Sgonzo		goto fail;
239239922Sgonzo	}
240239922Sgonzo
241239922Sgonzo	err = (sc_attach_unit(device_get_unit(dev),
242239922Sgonzo	    device_get_flags(dev) | SC_AUTODETECT_KBD));
243239922Sgonzo
244239922Sgonzo	if (err) {
245239922Sgonzo		device_printf(dev, "failed to attach syscons\n");
246239922Sgonzo		goto fail;
247239922Sgonzo	}
248239922Sgonzo
249239922Sgonzo	/*
250239922Sgonzo	 * We have to wait until interrupts are enabled.
251239922Sgonzo	 * Mailbox relies on it to get data from VideoCore
252239922Sgonzo	 */
253239922Sgonzo        sc->init_hook.ich_func = bcm_fb_init;
254239922Sgonzo        sc->init_hook.ich_arg = sc;
255239922Sgonzo
256239922Sgonzo        if (config_intrhook_establish(&sc->init_hook) != 0) {
257239922Sgonzo		device_printf(dev, "failed to establish intrhook\n");
258239922Sgonzo                return (ENOMEM);
259239922Sgonzo	}
260239922Sgonzo
261239922Sgonzo	return (0);
262239922Sgonzo
263239922Sgonzofail:
264239922Sgonzo	return (ENXIO);
265239922Sgonzo}
266239922Sgonzo
267239922Sgonzo
268239922Sgonzostatic void
269239922Sgonzobcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
270239922Sgonzo{
271239922Sgonzo	bus_addr_t *addr;
272239922Sgonzo
273239922Sgonzo	if (err)
274239922Sgonzo		return;
275239922Sgonzo
276239922Sgonzo	addr = (bus_addr_t*)arg;
277239922Sgonzo	*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
278239922Sgonzo}
279239922Sgonzo
280239922Sgonzostatic device_method_t bcm_fb_methods[] = {
281239922Sgonzo	/* Device interface */
282239922Sgonzo	DEVMETHOD(device_probe,		bcm_fb_probe),
283239922Sgonzo	DEVMETHOD(device_attach,	bcm_fb_attach),
284239922Sgonzo
285239922Sgonzo	{ 0, 0 }
286239922Sgonzo};
287239922Sgonzo
288239922Sgonzostatic devclass_t bcm_fb_devclass;
289239922Sgonzo
290239922Sgonzostatic driver_t bcm_fb_driver = {
291239922Sgonzo	"fb",
292239922Sgonzo	bcm_fb_methods,
293239922Sgonzo	sizeof(struct bcmsc_softc),
294239922Sgonzo};
295239922Sgonzo
296239922SgonzoDRIVER_MODULE(bcm2835fb, simplebus, bcm_fb_driver, bcm_fb_devclass, 0, 0);
297239922Sgonzo
298239922Sgonzo/*
299239922Sgonzo * Video driver routines and glue.
300239922Sgonzo */
301239922Sgonzostatic int			bcmfb_configure(int);
302239922Sgonzostatic vi_probe_t		bcmfb_probe;
303239922Sgonzostatic vi_init_t		bcmfb_init;
304239922Sgonzostatic vi_get_info_t		bcmfb_get_info;
305239922Sgonzostatic vi_query_mode_t		bcmfb_query_mode;
306239922Sgonzostatic vi_set_mode_t		bcmfb_set_mode;
307239922Sgonzostatic vi_save_font_t		bcmfb_save_font;
308239922Sgonzostatic vi_load_font_t		bcmfb_load_font;
309239922Sgonzostatic vi_show_font_t		bcmfb_show_font;
310239922Sgonzostatic vi_save_palette_t	bcmfb_save_palette;
311239922Sgonzostatic vi_load_palette_t	bcmfb_load_palette;
312239922Sgonzostatic vi_set_border_t		bcmfb_set_border;
313239922Sgonzostatic vi_save_state_t		bcmfb_save_state;
314239922Sgonzostatic vi_load_state_t		bcmfb_load_state;
315239922Sgonzostatic vi_set_win_org_t		bcmfb_set_win_org;
316239922Sgonzostatic vi_read_hw_cursor_t	bcmfb_read_hw_cursor;
317239922Sgonzostatic vi_set_hw_cursor_t	bcmfb_set_hw_cursor;
318239922Sgonzostatic vi_set_hw_cursor_shape_t	bcmfb_set_hw_cursor_shape;
319239922Sgonzostatic vi_blank_display_t	bcmfb_blank_display;
320239922Sgonzostatic vi_mmap_t		bcmfb_mmap;
321239922Sgonzostatic vi_ioctl_t		bcmfb_ioctl;
322239922Sgonzostatic vi_clear_t		bcmfb_clear;
323239922Sgonzostatic vi_fill_rect_t		bcmfb_fill_rect;
324239922Sgonzostatic vi_bitblt_t		bcmfb_bitblt;
325239922Sgonzostatic vi_diag_t		bcmfb_diag;
326239922Sgonzostatic vi_save_cursor_palette_t	bcmfb_save_cursor_palette;
327239922Sgonzostatic vi_load_cursor_palette_t	bcmfb_load_cursor_palette;
328239922Sgonzostatic vi_copy_t		bcmfb_copy;
329239922Sgonzostatic vi_putp_t		bcmfb_putp;
330239922Sgonzostatic vi_putc_t		bcmfb_putc;
331239922Sgonzostatic vi_puts_t		bcmfb_puts;
332239922Sgonzostatic vi_putm_t		bcmfb_putm;
333239922Sgonzo
334239922Sgonzostatic video_switch_t bcmfbvidsw = {
335239922Sgonzo	.probe			= bcmfb_probe,
336239922Sgonzo	.init			= bcmfb_init,
337239922Sgonzo	.get_info		= bcmfb_get_info,
338239922Sgonzo	.query_mode		= bcmfb_query_mode,
339239922Sgonzo	.set_mode		= bcmfb_set_mode,
340239922Sgonzo	.save_font		= bcmfb_save_font,
341239922Sgonzo	.load_font		= bcmfb_load_font,
342239922Sgonzo	.show_font		= bcmfb_show_font,
343239922Sgonzo	.save_palette		= bcmfb_save_palette,
344239922Sgonzo	.load_palette		= bcmfb_load_palette,
345239922Sgonzo	.set_border		= bcmfb_set_border,
346239922Sgonzo	.save_state		= bcmfb_save_state,
347239922Sgonzo	.load_state		= bcmfb_load_state,
348239922Sgonzo	.set_win_org		= bcmfb_set_win_org,
349239922Sgonzo	.read_hw_cursor		= bcmfb_read_hw_cursor,
350239922Sgonzo	.set_hw_cursor		= bcmfb_set_hw_cursor,
351239922Sgonzo	.set_hw_cursor_shape	= bcmfb_set_hw_cursor_shape,
352239922Sgonzo	.blank_display		= bcmfb_blank_display,
353239922Sgonzo	.mmap			= bcmfb_mmap,
354239922Sgonzo	.ioctl			= bcmfb_ioctl,
355239922Sgonzo	.clear			= bcmfb_clear,
356239922Sgonzo	.fill_rect		= bcmfb_fill_rect,
357239922Sgonzo	.bitblt			= bcmfb_bitblt,
358239922Sgonzo	.diag			= bcmfb_diag,
359239922Sgonzo	.save_cursor_palette	= bcmfb_save_cursor_palette,
360239922Sgonzo	.load_cursor_palette	= bcmfb_load_cursor_palette,
361239922Sgonzo	.copy			= bcmfb_copy,
362239922Sgonzo	.putp			= bcmfb_putp,
363239922Sgonzo	.putc			= bcmfb_putc,
364239922Sgonzo	.puts			= bcmfb_puts,
365239922Sgonzo	.putm			= bcmfb_putm,
366239922Sgonzo};
367239922Sgonzo
368239922SgonzoVIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure);
369239922Sgonzo
370239922Sgonzoextern sc_rndr_sw_t txtrndrsw;
371239922SgonzoRENDERER(bcmfb, 0, txtrndrsw, gfb_set);
372239922SgonzoRENDERER_MODULE(bcmfb, gfb_set);
373239922Sgonzo
374239922Sgonzostatic uint16_t bcmfb_static_window[ROW*COL];
375239922Sgonzoextern u_char dflt_font_16[];
376239922Sgonzo
377239922Sgonzostatic int
378239922Sgonzobcmfb_configure(int flags)
379239922Sgonzo{
380239922Sgonzo	struct video_adapter_softc *sc;
381239922Sgonzo
382239922Sgonzo	sc = &va_softc;
383239922Sgonzo
384239922Sgonzo	if (sc->initialized)
385239922Sgonzo		return 0;
386239922Sgonzo
387239922Sgonzo	sc->height = FB_HEIGHT;
388239922Sgonzo	sc->width = FB_WIDTH;
389239922Sgonzo
390239922Sgonzo	bcmfb_init(0, &sc->va, 0);
391239922Sgonzo
392239922Sgonzo	sc->initialized = 1;
393239922Sgonzo
394239922Sgonzo	return (0);
395239922Sgonzo}
396239922Sgonzo
397239922Sgonzostatic int
398239922Sgonzobcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
399239922Sgonzo{
400239922Sgonzo
401239922Sgonzo	return (0);
402239922Sgonzo}
403239922Sgonzo
404239922Sgonzostatic int
405239922Sgonzobcmfb_init(int unit, video_adapter_t *adp, int flags)
406239922Sgonzo{
407239922Sgonzo	struct video_adapter_softc *sc;
408239922Sgonzo	video_info_t *vi;
409239922Sgonzo
410239922Sgonzo	sc = (struct video_adapter_softc *)adp;
411239922Sgonzo	vi = &adp->va_info;
412239922Sgonzo
413239922Sgonzo	vid_init_struct(adp, "bcmfb", -1, unit);
414239922Sgonzo
415239922Sgonzo	sc->font = dflt_font_16;
416239922Sgonzo	vi->vi_cheight = BCMFB_FONT_HEIGHT;
417239922Sgonzo	vi->vi_cwidth = 8;
418239922Sgonzo	vi->vi_width = sc->width/8;
419239922Sgonzo	vi->vi_height = sc->height/vi->vi_cheight;
420239922Sgonzo
421239922Sgonzo	/*
422239922Sgonzo	 * Clamp width/height to syscons maximums
423239922Sgonzo	 */
424239922Sgonzo	if (vi->vi_width > COL)
425239922Sgonzo		vi->vi_width = COL;
426239922Sgonzo	if (vi->vi_height > ROW)
427239922Sgonzo		vi->vi_height = ROW;
428239922Sgonzo
429239922Sgonzo	sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
430239922Sgonzo	sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
431239922Sgonzo
432239922Sgonzo	adp->va_window = (vm_offset_t) bcmfb_static_window;
433239922Sgonzo	adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
434239922Sgonzo
435239922Sgonzo	vid_register(&sc->va);
436239922Sgonzo
437239922Sgonzo	return (0);
438239922Sgonzo}
439239922Sgonzo
440239922Sgonzostatic int
441239922Sgonzobcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
442239922Sgonzo{
443239922Sgonzo	bcopy(&adp->va_info, info, sizeof(*info));
444239922Sgonzo	return (0);
445239922Sgonzo}
446239922Sgonzo
447239922Sgonzostatic int
448239922Sgonzobcmfb_query_mode(video_adapter_t *adp, video_info_t *info)
449239922Sgonzo{
450239922Sgonzo	return (0);
451239922Sgonzo}
452239922Sgonzo
453239922Sgonzostatic int
454239922Sgonzobcmfb_set_mode(video_adapter_t *adp, int mode)
455239922Sgonzo{
456239922Sgonzo	return (0);
457239922Sgonzo}
458239922Sgonzo
459239922Sgonzostatic int
460239922Sgonzobcmfb_save_font(video_adapter_t *adp, int page, int size, int width,
461239922Sgonzo    u_char *data, int c, int count)
462239922Sgonzo{
463239922Sgonzo	return (0);
464239922Sgonzo}
465239922Sgonzo
466239922Sgonzostatic int
467239922Sgonzobcmfb_load_font(video_adapter_t *adp, int page, int size, int width,
468239922Sgonzo    u_char *data, int c, int count)
469239922Sgonzo{
470239922Sgonzo	struct video_adapter_softc *sc = (struct video_adapter_softc *)adp;
471239922Sgonzo
472239922Sgonzo	sc->font = data;
473239922Sgonzo
474239922Sgonzo	return (0);
475239922Sgonzo}
476239922Sgonzo
477239922Sgonzostatic int
478239922Sgonzobcmfb_show_font(video_adapter_t *adp, int page)
479239922Sgonzo{
480239922Sgonzo	return (0);
481239922Sgonzo}
482239922Sgonzo
483239922Sgonzostatic int
484239922Sgonzobcmfb_save_palette(video_adapter_t *adp, u_char *palette)
485239922Sgonzo{
486239922Sgonzo	return (0);
487239922Sgonzo}
488239922Sgonzo
489239922Sgonzostatic int
490239922Sgonzobcmfb_load_palette(video_adapter_t *adp, u_char *palette)
491239922Sgonzo{
492239922Sgonzo	return (0);
493239922Sgonzo}
494239922Sgonzo
495239922Sgonzostatic int
496239922Sgonzobcmfb_set_border(video_adapter_t *adp, int border)
497239922Sgonzo{
498239922Sgonzo	return (bcmfb_blank_display(adp, border));
499239922Sgonzo}
500239922Sgonzo
501239922Sgonzostatic int
502239922Sgonzobcmfb_save_state(video_adapter_t *adp, void *p, size_t size)
503239922Sgonzo{
504239922Sgonzo	return (0);
505239922Sgonzo}
506239922Sgonzo
507239922Sgonzostatic int
508239922Sgonzobcmfb_load_state(video_adapter_t *adp, void *p)
509239922Sgonzo{
510239922Sgonzo	return (0);
511239922Sgonzo}
512239922Sgonzo
513239922Sgonzostatic int
514239922Sgonzobcmfb_set_win_org(video_adapter_t *adp, off_t offset)
515239922Sgonzo{
516239922Sgonzo	return (0);
517239922Sgonzo}
518239922Sgonzo
519239922Sgonzostatic int
520239922Sgonzobcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
521239922Sgonzo{
522239922Sgonzo	*col = *row = 0;
523239922Sgonzo
524239922Sgonzo	return (0);
525239922Sgonzo}
526239922Sgonzo
527239922Sgonzostatic int
528239922Sgonzobcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
529239922Sgonzo{
530239922Sgonzo	return (0);
531239922Sgonzo}
532239922Sgonzo
533239922Sgonzostatic int
534239922Sgonzobcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
535239922Sgonzo    int celsize, int blink)
536239922Sgonzo{
537239922Sgonzo	return (0);
538239922Sgonzo}
539239922Sgonzo
540239922Sgonzostatic int
541239922Sgonzobcmfb_blank_display(video_adapter_t *adp, int mode)
542239922Sgonzo{
543239922Sgonzo
544239922Sgonzo	return (0);
545239922Sgonzo}
546239922Sgonzo
547239922Sgonzostatic int
548239922Sgonzobcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
549239922Sgonzo    int prot, vm_memattr_t *memattr)
550239922Sgonzo{
551239922Sgonzo	struct video_adapter_softc *sc;
552239922Sgonzo
553239922Sgonzo	sc = (struct video_adapter_softc *)adp;
554239922Sgonzo
555239922Sgonzo	/*
556239922Sgonzo	 * This might be a legacy VGA mem request: if so, just point it at the
557239922Sgonzo	 * framebuffer, since it shouldn't be touched
558239922Sgonzo	 */
559239922Sgonzo	if (offset < sc->stride*sc->height) {
560239922Sgonzo		*paddr = sc->fb_addr + offset;
561239922Sgonzo		return (0);
562239922Sgonzo	}
563239922Sgonzo
564239922Sgonzo	return (EINVAL);
565239922Sgonzo}
566239922Sgonzo
567239922Sgonzostatic int
568239922Sgonzobcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
569239922Sgonzo{
570239922Sgonzo
571239922Sgonzo	return (0);
572239922Sgonzo}
573239922Sgonzo
574239922Sgonzostatic int
575239922Sgonzobcmfb_clear(video_adapter_t *adp)
576239922Sgonzo{
577239922Sgonzo
578239922Sgonzo	return (bcmfb_blank_display(adp, 0));
579239922Sgonzo}
580239922Sgonzo
581239922Sgonzostatic int
582239922Sgonzobcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
583239922Sgonzo{
584239922Sgonzo
585239922Sgonzo	return (0);
586239922Sgonzo}
587239922Sgonzo
588239922Sgonzostatic int
589239922Sgonzobcmfb_bitblt(video_adapter_t *adp, ...)
590239922Sgonzo{
591239922Sgonzo
592239922Sgonzo	return (0);
593239922Sgonzo}
594239922Sgonzo
595239922Sgonzostatic int
596239922Sgonzobcmfb_diag(video_adapter_t *adp, int level)
597239922Sgonzo{
598239922Sgonzo
599239922Sgonzo	return (0);
600239922Sgonzo}
601239922Sgonzo
602239922Sgonzostatic int
603239922Sgonzobcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
604239922Sgonzo{
605239922Sgonzo
606239922Sgonzo	return (0);
607239922Sgonzo}
608239922Sgonzo
609239922Sgonzostatic int
610239922Sgonzobcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
611239922Sgonzo{
612239922Sgonzo
613239922Sgonzo	return (0);
614239922Sgonzo}
615239922Sgonzo
616239922Sgonzostatic int
617239922Sgonzobcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
618239922Sgonzo{
619239922Sgonzo
620239922Sgonzo	return (0);
621239922Sgonzo}
622239922Sgonzo
623239922Sgonzostatic int
624239922Sgonzobcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
625239922Sgonzo    int size, int bpp, int bit_ltor, int byte_ltor)
626239922Sgonzo{
627239922Sgonzo
628239922Sgonzo	return (0);
629239922Sgonzo}
630239922Sgonzo
631239922Sgonzostatic int
632239922Sgonzobcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
633239922Sgonzo{
634239922Sgonzo	struct video_adapter_softc *sc;
635239922Sgonzo	int row;
636239922Sgonzo	int col;
637239922Sgonzo	int i, j, k;
638239922Sgonzo	uint8_t *addr;
639239922Sgonzo	u_char *p;
640239922Sgonzo	uint8_t fg, bg, color;
641239922Sgonzo
642239922Sgonzo	sc = (struct video_adapter_softc *)adp;
643239922Sgonzo
644239922Sgonzo	if (sc->fb_addr == 0)
645239922Sgonzo		return (0);
646239922Sgonzo
647239922Sgonzo	row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
648239922Sgonzo	col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
649239922Sgonzo	p = sc->font + c*BCMFB_FONT_HEIGHT;
650239922Sgonzo	addr = (uint8_t *)sc->fb_addr
651239922Sgonzo	    + (row + sc->ymargin)*(sc->stride)
652239922Sgonzo	    + 3 * (col + sc->xmargin);
653239922Sgonzo
654239922Sgonzo	/*
655239922Sgonzo	 * FIXME: hardcoded
656239922Sgonzo	 */
657239922Sgonzo	bg = 0x00;
658239922Sgonzo	fg = 0x80;
659239922Sgonzo
660239922Sgonzo	for (i = 0; i < BCMFB_FONT_HEIGHT; i++) {
661239922Sgonzo		for (j = 0, k = 7; j < 8; j++, k--) {
662239922Sgonzo			if ((p[i] & (1 << k)) == 0)
663239922Sgonzo				color = bg;
664239922Sgonzo			else
665239922Sgonzo				color = fg;
666239922Sgonzo
667239922Sgonzo			addr[3*j] = color;
668239922Sgonzo			addr[3*j+1] = color;
669239922Sgonzo			addr[3*j+2] = color;
670239922Sgonzo		}
671239922Sgonzo
672239922Sgonzo		addr += (sc->stride);
673239922Sgonzo	}
674239922Sgonzo
675239922Sgonzo        return (0);
676239922Sgonzo}
677239922Sgonzo
678239922Sgonzostatic int
679239922Sgonzobcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
680239922Sgonzo{
681239922Sgonzo	int i;
682239922Sgonzo
683239922Sgonzo	for (i = 0; i < len; i++)
684239922Sgonzo		bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
685239922Sgonzo
686239922Sgonzo	return (0);
687239922Sgonzo}
688239922Sgonzo
689239922Sgonzostatic int
690239922Sgonzobcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
691239922Sgonzo    uint32_t pixel_mask, int size, int width)
692239922Sgonzo{
693239922Sgonzo
694239922Sgonzo	return (0);
695239922Sgonzo}
696239922Sgonzo
697239922Sgonzo/*
698239922Sgonzo * Define a stub keyboard driver in case one hasn't been
699239922Sgonzo * compiled into the kernel
700239922Sgonzo */
701239922Sgonzo#include <sys/kbio.h>
702239922Sgonzo#include <dev/kbd/kbdreg.h>
703239922Sgonzo
704239922Sgonzostatic int dummy_kbd_configure(int flags);
705239922Sgonzo
706239922Sgonzokeyboard_switch_t bcmdummysw;
707239922Sgonzo
708239922Sgonzostatic int
709239922Sgonzodummy_kbd_configure(int flags)
710239922Sgonzo{
711239922Sgonzo
712239922Sgonzo	return (0);
713239922Sgonzo}
714239922SgonzoKEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure);
715