bcm2835_fbd.c revision 245389
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 245389 2013-01-13 22:05:46Z ray $"); 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 71243423Sgonzostruct argb { 72243423Sgonzo uint8_t a; 73243423Sgonzo uint8_t r; 74243423Sgonzo uint8_t g; 75243423Sgonzo uint8_t b; 76243423Sgonzo}; 77243423Sgonzo 78243423Sgonzostatic struct argb bcmfb_palette[16] = { 79243423Sgonzo {0x00, 0x00, 0x00, 0x00}, 80243423Sgonzo {0x00, 0x00, 0x00, 0xaa}, 81243423Sgonzo {0x00, 0x00, 0xaa, 0x00}, 82243423Sgonzo {0x00, 0x00, 0xaa, 0xaa}, 83243423Sgonzo {0x00, 0xaa, 0x00, 0x00}, 84243423Sgonzo {0x00, 0xaa, 0x00, 0xaa}, 85243423Sgonzo {0x00, 0xaa, 0x55, 0x00}, 86243423Sgonzo {0x00, 0xaa, 0xaa, 0xaa}, 87243423Sgonzo {0x00, 0x55, 0x55, 0x55}, 88243423Sgonzo {0x00, 0x55, 0x55, 0xff}, 89243423Sgonzo {0x00, 0x55, 0xff, 0x55}, 90243423Sgonzo {0x00, 0x55, 0xff, 0xff}, 91243423Sgonzo {0x00, 0xff, 0x55, 0x55}, 92243423Sgonzo {0x00, 0xff, 0x55, 0xff}, 93243423Sgonzo {0x00, 0xff, 0xff, 0x55}, 94243423Sgonzo {0x00, 0xff, 0xff, 0xff} 95243423Sgonzo}; 96243423Sgonzo 97244762Sgonzo/* mouse pointer from dev/syscons/scgfbrndr.c */ 98244762Sgonzostatic u_char mouse_pointer[16] = { 99244762Sgonzo 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 100244762Sgonzo 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 101244762Sgonzo}; 102244762Sgonzo 103239922Sgonzo#define FB_WIDTH 640 104239922Sgonzo#define FB_HEIGHT 480 105243423Sgonzo#define FB_DEPTH 24 106239922Sgonzo 107239922Sgonzostruct bcm_fb_config { 108239922Sgonzo uint32_t xres; 109239922Sgonzo uint32_t yres; 110239922Sgonzo uint32_t vxres; 111239922Sgonzo uint32_t vyres; 112239922Sgonzo uint32_t pitch; 113239922Sgonzo uint32_t bpp; 114239922Sgonzo uint32_t xoffset; 115239922Sgonzo uint32_t yoffset; 116239922Sgonzo /* Filled by videocore */ 117239922Sgonzo uint32_t base; 118239922Sgonzo uint32_t screen_size; 119239922Sgonzo}; 120239922Sgonzo 121239922Sgonzostruct bcmsc_softc { 122239922Sgonzo device_t dev; 123239922Sgonzo struct cdev * cdev; 124239922Sgonzo struct mtx mtx; 125239922Sgonzo bus_dma_tag_t dma_tag; 126239922Sgonzo bus_dmamap_t dma_map; 127239922Sgonzo struct bcm_fb_config* fb_config; 128239922Sgonzo bus_addr_t fb_config_phys; 129239922Sgonzo struct intr_config_hook init_hook; 130239922Sgonzo 131239922Sgonzo}; 132239922Sgonzo 133239922Sgonzostruct video_adapter_softc { 134239922Sgonzo /* Videoadpater part */ 135239922Sgonzo video_adapter_t va; 136239922Sgonzo int console; 137239922Sgonzo 138239922Sgonzo intptr_t fb_addr; 139245389Sray intptr_t fb_paddr; 140239922Sgonzo unsigned int fb_size; 141239922Sgonzo 142239922Sgonzo unsigned int height; 143239922Sgonzo unsigned int width; 144243423Sgonzo unsigned int depth; 145239922Sgonzo unsigned int stride; 146239922Sgonzo 147239922Sgonzo unsigned int xmargin; 148239922Sgonzo unsigned int ymargin; 149239922Sgonzo 150239922Sgonzo unsigned char *font; 151239922Sgonzo int initialized; 152239922Sgonzo}; 153239922Sgonzo 154239922Sgonzostatic struct bcmsc_softc *bcmsc_softc; 155239922Sgonzostatic struct video_adapter_softc va_softc; 156239922Sgonzo 157239922Sgonzo#define bcm_fb_lock(_sc) mtx_lock(&(_sc)->mtx) 158239922Sgonzo#define bcm_fb_unlock(_sc) mtx_unlock(&(_sc)->mtx) 159239922Sgonzo#define bcm_fb_lock_assert(sc) mtx_assert(&(_sc)->mtx, MA_OWNED) 160239922Sgonzo 161239922Sgonzostatic int bcm_fb_probe(device_t); 162239922Sgonzostatic int bcm_fb_attach(device_t); 163239922Sgonzostatic void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); 164243423Sgonzostatic void bcmfb_update_margins(video_adapter_t *adp); 165243423Sgonzostatic int bcmfb_configure(int); 166239922Sgonzo 167239922Sgonzostatic void 168239922Sgonzobcm_fb_init(void *arg) 169239922Sgonzo{ 170239922Sgonzo struct bcmsc_softc *sc = arg; 171239922Sgonzo struct video_adapter_softc *va_sc = &va_softc; 172239922Sgonzo int err; 173239922Sgonzo volatile struct bcm_fb_config* fb_config = sc->fb_config; 174243423Sgonzo phandle_t node; 175243423Sgonzo pcell_t cell; 176239922Sgonzo 177243423Sgonzo node = ofw_bus_get_node(sc->dev); 178243423Sgonzo 179243423Sgonzo fb_config->xres = 0; 180243423Sgonzo fb_config->yres = 0; 181243423Sgonzo fb_config->bpp = 0; 182243423Sgonzo 183243423Sgonzo if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0) 184243423Sgonzo fb_config->xres = (int)fdt32_to_cpu(cell); 185243423Sgonzo if (fb_config->xres == 0) 186243423Sgonzo fb_config->xres = FB_WIDTH; 187243423Sgonzo 188243423Sgonzo if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0) 189243423Sgonzo fb_config->yres = (uint32_t)fdt32_to_cpu(cell); 190243423Sgonzo if (fb_config->yres == 0) 191243423Sgonzo fb_config->yres = FB_HEIGHT; 192243423Sgonzo 193243423Sgonzo if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0) 194243423Sgonzo fb_config->bpp = (uint32_t)fdt32_to_cpu(cell); 195243423Sgonzo if (fb_config->bpp == 0) 196243423Sgonzo fb_config->bpp = FB_DEPTH; 197243423Sgonzo 198239922Sgonzo fb_config->vxres = 0; 199239922Sgonzo fb_config->vyres = 0; 200239922Sgonzo fb_config->xoffset = 0; 201239922Sgonzo fb_config->yoffset = 0; 202239922Sgonzo fb_config->base = 0; 203239922Sgonzo fb_config->pitch = 0; 204239922Sgonzo fb_config->screen_size = 0; 205239922Sgonzo 206239922Sgonzo bus_dmamap_sync(sc->dma_tag, sc->dma_map, 207239922Sgonzo BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 208239922Sgonzo bcm_mbox_write(BCM2835_MBOX_CHAN_FB, sc->fb_config_phys); 209239922Sgonzo bcm_mbox_read(BCM2835_MBOX_CHAN_FB, &err); 210239922Sgonzo bus_dmamap_sync(sc->dma_tag, sc->dma_map, 211239922Sgonzo BUS_DMASYNC_POSTREAD); 212239922Sgonzo 213243423Sgonzo if (fb_config->base != 0) { 214239922Sgonzo device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", 215239922Sgonzo fb_config->xres, fb_config->yres, 216239922Sgonzo fb_config->vxres, fb_config->vyres, 217239922Sgonzo fb_config->xoffset, fb_config->yoffset, 218239922Sgonzo fb_config->bpp); 219239922Sgonzo 220239922Sgonzo 221239922Sgonzo device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n", 222239922Sgonzo fb_config->pitch, fb_config->base, 223239922Sgonzo fb_config->screen_size); 224239922Sgonzo 225243423Sgonzo va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size); 226245389Sray va_sc->fb_paddr = fb_config->base; 227243423Sgonzo va_sc->fb_size = fb_config->screen_size; 228243423Sgonzo va_sc->depth = fb_config->bpp; 229243423Sgonzo va_sc->stride = fb_config->pitch; 230243423Sgonzo 231243423Sgonzo va_sc->width = fb_config->xres; 232243423Sgonzo va_sc->height = fb_config->yres; 233243423Sgonzo bcmfb_update_margins(&va_sc->va); 234239922Sgonzo } 235243423Sgonzo else { 236239922Sgonzo device_printf(sc->dev, "Failed to set framebuffer info\n"); 237243423Sgonzo return; 238243423Sgonzo } 239239922Sgonzo 240239922Sgonzo config_intrhook_disestablish(&sc->init_hook); 241239922Sgonzo} 242239922Sgonzo 243239922Sgonzostatic int 244239922Sgonzobcm_fb_probe(device_t dev) 245239922Sgonzo{ 246243423Sgonzo int error = 0; 247239922Sgonzo 248239922Sgonzo if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb")) 249239922Sgonzo return (ENXIO); 250239922Sgonzo 251239922Sgonzo device_set_desc(dev, "BCM2835 framebuffer device"); 252239922Sgonzo 253239922Sgonzo error = sc_probe_unit(device_get_unit(dev), 254239922Sgonzo device_get_flags(dev) | SC_AUTODETECT_KBD); 255239922Sgonzo if (error != 0) 256239922Sgonzo return (error); 257239922Sgonzo 258243423Sgonzo 259239922Sgonzo return (BUS_PROBE_DEFAULT); 260239922Sgonzo} 261239922Sgonzo 262239922Sgonzostatic int 263239922Sgonzobcm_fb_attach(device_t dev) 264239922Sgonzo{ 265239922Sgonzo struct bcmsc_softc *sc = device_get_softc(dev); 266239922Sgonzo int dma_size = sizeof(struct bcm_fb_config); 267239922Sgonzo int err; 268239922Sgonzo 269239922Sgonzo if (bcmsc_softc) 270239922Sgonzo return (ENXIO); 271239922Sgonzo 272239922Sgonzo bcmsc_softc = sc; 273239922Sgonzo 274239922Sgonzo sc->dev = dev; 275239922Sgonzo mtx_init(&sc->mtx, "bcm2835fb", "fb", MTX_DEF); 276239922Sgonzo 277239922Sgonzo err = bus_dma_tag_create( 278239922Sgonzo bus_get_dma_tag(sc->dev), 279239922Sgonzo PAGE_SIZE, 0, /* alignment, boundary */ 280239922Sgonzo BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 281239922Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 282239922Sgonzo NULL, NULL, /* filter, filterarg */ 283239922Sgonzo dma_size, 1, /* maxsize, nsegments */ 284239922Sgonzo dma_size, 0, /* maxsegsize, flags */ 285239922Sgonzo NULL, NULL, /* lockfunc, lockarg */ 286239922Sgonzo &sc->dma_tag); 287239922Sgonzo 288239922Sgonzo err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, 289239922Sgonzo 0, &sc->dma_map); 290239922Sgonzo if (err) { 291239922Sgonzo device_printf(dev, "cannot allocate framebuffer\n"); 292239922Sgonzo goto fail; 293239922Sgonzo } 294239922Sgonzo 295239922Sgonzo err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config, 296239922Sgonzo dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT); 297239922Sgonzo 298239922Sgonzo if (err) { 299239922Sgonzo device_printf(dev, "cannot load DMA map\n"); 300239922Sgonzo goto fail; 301239922Sgonzo } 302239922Sgonzo 303239922Sgonzo err = (sc_attach_unit(device_get_unit(dev), 304239922Sgonzo device_get_flags(dev) | SC_AUTODETECT_KBD)); 305239922Sgonzo 306239922Sgonzo if (err) { 307239922Sgonzo device_printf(dev, "failed to attach syscons\n"); 308239922Sgonzo goto fail; 309239922Sgonzo } 310239922Sgonzo 311239922Sgonzo /* 312239922Sgonzo * We have to wait until interrupts are enabled. 313239922Sgonzo * Mailbox relies on it to get data from VideoCore 314239922Sgonzo */ 315239922Sgonzo sc->init_hook.ich_func = bcm_fb_init; 316239922Sgonzo sc->init_hook.ich_arg = sc; 317239922Sgonzo 318239922Sgonzo if (config_intrhook_establish(&sc->init_hook) != 0) { 319239922Sgonzo device_printf(dev, "failed to establish intrhook\n"); 320239922Sgonzo return (ENOMEM); 321239922Sgonzo } 322239922Sgonzo 323239922Sgonzo return (0); 324239922Sgonzo 325239922Sgonzofail: 326239922Sgonzo return (ENXIO); 327239922Sgonzo} 328239922Sgonzo 329239922Sgonzo 330239922Sgonzostatic void 331239922Sgonzobcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 332239922Sgonzo{ 333239922Sgonzo bus_addr_t *addr; 334239922Sgonzo 335239922Sgonzo if (err) 336239922Sgonzo return; 337239922Sgonzo 338239922Sgonzo addr = (bus_addr_t*)arg; 339239922Sgonzo *addr = PHYS_TO_VCBUS(segs[0].ds_addr); 340239922Sgonzo} 341239922Sgonzo 342239922Sgonzostatic device_method_t bcm_fb_methods[] = { 343239922Sgonzo /* Device interface */ 344239922Sgonzo DEVMETHOD(device_probe, bcm_fb_probe), 345239922Sgonzo DEVMETHOD(device_attach, bcm_fb_attach), 346239922Sgonzo 347239922Sgonzo { 0, 0 } 348239922Sgonzo}; 349239922Sgonzo 350239922Sgonzostatic devclass_t bcm_fb_devclass; 351239922Sgonzo 352239922Sgonzostatic driver_t bcm_fb_driver = { 353239922Sgonzo "fb", 354239922Sgonzo bcm_fb_methods, 355239922Sgonzo sizeof(struct bcmsc_softc), 356239922Sgonzo}; 357239922Sgonzo 358243423SgonzoDRIVER_MODULE(bcm2835fb, fdtbus, bcm_fb_driver, bcm_fb_devclass, 0, 0); 359239922Sgonzo 360239922Sgonzo/* 361239922Sgonzo * Video driver routines and glue. 362239922Sgonzo */ 363239922Sgonzostatic vi_probe_t bcmfb_probe; 364239922Sgonzostatic vi_init_t bcmfb_init; 365239922Sgonzostatic vi_get_info_t bcmfb_get_info; 366239922Sgonzostatic vi_query_mode_t bcmfb_query_mode; 367239922Sgonzostatic vi_set_mode_t bcmfb_set_mode; 368239922Sgonzostatic vi_save_font_t bcmfb_save_font; 369239922Sgonzostatic vi_load_font_t bcmfb_load_font; 370239922Sgonzostatic vi_show_font_t bcmfb_show_font; 371239922Sgonzostatic vi_save_palette_t bcmfb_save_palette; 372239922Sgonzostatic vi_load_palette_t bcmfb_load_palette; 373239922Sgonzostatic vi_set_border_t bcmfb_set_border; 374239922Sgonzostatic vi_save_state_t bcmfb_save_state; 375239922Sgonzostatic vi_load_state_t bcmfb_load_state; 376239922Sgonzostatic vi_set_win_org_t bcmfb_set_win_org; 377239922Sgonzostatic vi_read_hw_cursor_t bcmfb_read_hw_cursor; 378239922Sgonzostatic vi_set_hw_cursor_t bcmfb_set_hw_cursor; 379239922Sgonzostatic vi_set_hw_cursor_shape_t bcmfb_set_hw_cursor_shape; 380239922Sgonzostatic vi_blank_display_t bcmfb_blank_display; 381239922Sgonzostatic vi_mmap_t bcmfb_mmap; 382239922Sgonzostatic vi_ioctl_t bcmfb_ioctl; 383239922Sgonzostatic vi_clear_t bcmfb_clear; 384239922Sgonzostatic vi_fill_rect_t bcmfb_fill_rect; 385239922Sgonzostatic vi_bitblt_t bcmfb_bitblt; 386239922Sgonzostatic vi_diag_t bcmfb_diag; 387239922Sgonzostatic vi_save_cursor_palette_t bcmfb_save_cursor_palette; 388239922Sgonzostatic vi_load_cursor_palette_t bcmfb_load_cursor_palette; 389239922Sgonzostatic vi_copy_t bcmfb_copy; 390239922Sgonzostatic vi_putp_t bcmfb_putp; 391239922Sgonzostatic vi_putc_t bcmfb_putc; 392239922Sgonzostatic vi_puts_t bcmfb_puts; 393239922Sgonzostatic vi_putm_t bcmfb_putm; 394239922Sgonzo 395239922Sgonzostatic video_switch_t bcmfbvidsw = { 396239922Sgonzo .probe = bcmfb_probe, 397239922Sgonzo .init = bcmfb_init, 398239922Sgonzo .get_info = bcmfb_get_info, 399239922Sgonzo .query_mode = bcmfb_query_mode, 400239922Sgonzo .set_mode = bcmfb_set_mode, 401239922Sgonzo .save_font = bcmfb_save_font, 402239922Sgonzo .load_font = bcmfb_load_font, 403239922Sgonzo .show_font = bcmfb_show_font, 404239922Sgonzo .save_palette = bcmfb_save_palette, 405239922Sgonzo .load_palette = bcmfb_load_palette, 406239922Sgonzo .set_border = bcmfb_set_border, 407239922Sgonzo .save_state = bcmfb_save_state, 408239922Sgonzo .load_state = bcmfb_load_state, 409239922Sgonzo .set_win_org = bcmfb_set_win_org, 410239922Sgonzo .read_hw_cursor = bcmfb_read_hw_cursor, 411239922Sgonzo .set_hw_cursor = bcmfb_set_hw_cursor, 412239922Sgonzo .set_hw_cursor_shape = bcmfb_set_hw_cursor_shape, 413239922Sgonzo .blank_display = bcmfb_blank_display, 414239922Sgonzo .mmap = bcmfb_mmap, 415239922Sgonzo .ioctl = bcmfb_ioctl, 416239922Sgonzo .clear = bcmfb_clear, 417239922Sgonzo .fill_rect = bcmfb_fill_rect, 418239922Sgonzo .bitblt = bcmfb_bitblt, 419239922Sgonzo .diag = bcmfb_diag, 420239922Sgonzo .save_cursor_palette = bcmfb_save_cursor_palette, 421239922Sgonzo .load_cursor_palette = bcmfb_load_cursor_palette, 422239922Sgonzo .copy = bcmfb_copy, 423239922Sgonzo .putp = bcmfb_putp, 424239922Sgonzo .putc = bcmfb_putc, 425239922Sgonzo .puts = bcmfb_puts, 426239922Sgonzo .putm = bcmfb_putm, 427239922Sgonzo}; 428239922Sgonzo 429239922SgonzoVIDEO_DRIVER(bcmfb, bcmfbvidsw, bcmfb_configure); 430239922Sgonzo 431244762Sgonzostatic vr_init_t bcmrend_init; 432244762Sgonzostatic vr_clear_t bcmrend_clear; 433244762Sgonzostatic vr_draw_border_t bcmrend_draw_border; 434244762Sgonzostatic vr_draw_t bcmrend_draw; 435244762Sgonzostatic vr_set_cursor_t bcmrend_set_cursor; 436244762Sgonzostatic vr_draw_cursor_t bcmrend_draw_cursor; 437244762Sgonzostatic vr_blink_cursor_t bcmrend_blink_cursor; 438244762Sgonzostatic vr_set_mouse_t bcmrend_set_mouse; 439244762Sgonzostatic vr_draw_mouse_t bcmrend_draw_mouse; 440244762Sgonzo 441244762Sgonzo/* 442244762Sgonzo * We use our own renderer; this is because we must emulate a hardware 443244762Sgonzo * cursor. 444244762Sgonzo */ 445244762Sgonzostatic sc_rndr_sw_t bcmrend = { 446244762Sgonzo bcmrend_init, 447244762Sgonzo bcmrend_clear, 448244762Sgonzo bcmrend_draw_border, 449244762Sgonzo bcmrend_draw, 450244762Sgonzo bcmrend_set_cursor, 451244762Sgonzo bcmrend_draw_cursor, 452244762Sgonzo bcmrend_blink_cursor, 453244762Sgonzo bcmrend_set_mouse, 454244762Sgonzo bcmrend_draw_mouse 455244762Sgonzo}; 456244762Sgonzo 457244762SgonzoRENDERER(bcmfb, 0, bcmrend, gfb_set); 458239922SgonzoRENDERER_MODULE(bcmfb, gfb_set); 459239922Sgonzo 460244762Sgonzostatic void 461244762Sgonzobcmrend_init(scr_stat* scp) 462244762Sgonzo{ 463244762Sgonzo} 464244762Sgonzo 465244762Sgonzostatic void 466244762Sgonzobcmrend_clear(scr_stat* scp, int c, int attr) 467244762Sgonzo{ 468244762Sgonzo} 469244762Sgonzo 470244762Sgonzostatic void 471244762Sgonzobcmrend_draw_border(scr_stat* scp, int color) 472244762Sgonzo{ 473244762Sgonzo} 474244762Sgonzo 475244762Sgonzostatic void 476244762Sgonzobcmrend_draw(scr_stat* scp, int from, int count, int flip) 477244762Sgonzo{ 478244762Sgonzo video_adapter_t* adp = scp->sc->adp; 479244762Sgonzo int i, c, a; 480244762Sgonzo 481244762Sgonzo if (!flip) { 482244762Sgonzo /* Normal printing */ 483244762Sgonzo vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); 484244762Sgonzo } else { 485244762Sgonzo /* This is for selections and such: invert the color attribute */ 486244762Sgonzo for (i = count; i-- > 0; ++from) { 487244762Sgonzo c = sc_vtb_getc(&scp->vtb, from); 488244762Sgonzo a = sc_vtb_geta(&scp->vtb, from) >> 8; 489244762Sgonzo vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); 490244762Sgonzo } 491244762Sgonzo } 492244762Sgonzo} 493244762Sgonzo 494244762Sgonzostatic void 495244762Sgonzobcmrend_set_cursor(scr_stat* scp, int base, int height, int blink) 496244762Sgonzo{ 497244762Sgonzo} 498244762Sgonzo 499244762Sgonzostatic void 500244762Sgonzobcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) 501244762Sgonzo{ 502244762Sgonzo video_adapter_t* adp = scp->sc->adp; 503244762Sgonzo struct video_adapter_softc *sc; 504244762Sgonzo int row, col; 505244762Sgonzo uint8_t *addr; 506244762Sgonzo int i, j, bytes; 507244762Sgonzo 508244762Sgonzo sc = (struct video_adapter_softc *)adp; 509244762Sgonzo 510244762Sgonzo if (scp->curs_attr.height <= 0) 511244762Sgonzo return; 512244762Sgonzo 513244762Sgonzo if (sc->fb_addr == 0) 514244762Sgonzo return; 515244762Sgonzo 516244762Sgonzo if (off >= adp->va_info.vi_width * adp->va_info.vi_height) 517244762Sgonzo return; 518244762Sgonzo 519244762Sgonzo /* calculate the coordinates in the video buffer */ 520244762Sgonzo row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 521244762Sgonzo col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 522244762Sgonzo 523244762Sgonzo addr = (uint8_t *)sc->fb_addr 524244762Sgonzo + (row + sc->ymargin)*(sc->stride) 525244762Sgonzo + (sc->depth/8) * (col + sc->xmargin); 526244762Sgonzo 527244762Sgonzo bytes = sc->depth/8; 528244762Sgonzo 529244762Sgonzo /* our cursor consists of simply inverting the char under it */ 530244762Sgonzo for (i = 0; i < adp->va_info.vi_cheight; i++) { 531244762Sgonzo for (j = 0; j < adp->va_info.vi_cwidth; j++) { 532244762Sgonzo switch (sc->depth) { 533244762Sgonzo case 32: 534244762Sgonzo case 24: 535244762Sgonzo addr[bytes*j + 2] ^= 0xff; 536244762Sgonzo /* FALLTHROUGH */ 537244762Sgonzo case 16: 538244762Sgonzo addr[bytes*j + 1] ^= 0xff; 539244762Sgonzo addr[bytes*j] ^= 0xff; 540244762Sgonzo break; 541244762Sgonzo default: 542244762Sgonzo break; 543244762Sgonzo } 544244762Sgonzo } 545244762Sgonzo 546244762Sgonzo addr += sc->stride; 547244762Sgonzo } 548244762Sgonzo} 549244762Sgonzo 550244762Sgonzostatic void 551244762Sgonzobcmrend_blink_cursor(scr_stat* scp, int at, int flip) 552244762Sgonzo{ 553244762Sgonzo} 554244762Sgonzo 555244762Sgonzostatic void 556244762Sgonzobcmrend_set_mouse(scr_stat* scp) 557244762Sgonzo{ 558244762Sgonzo} 559244762Sgonzo 560244762Sgonzostatic void 561244762Sgonzobcmrend_draw_mouse(scr_stat* scp, int x, int y, int on) 562244762Sgonzo{ 563244762Sgonzo vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); 564244762Sgonzo} 565244762Sgonzo 566239922Sgonzostatic uint16_t bcmfb_static_window[ROW*COL]; 567239922Sgonzoextern u_char dflt_font_16[]; 568239922Sgonzo 569243423Sgonzo/* 570243423Sgonzo * Update videoadapter settings after changing resolution 571243423Sgonzo */ 572243423Sgonzostatic void 573243423Sgonzobcmfb_update_margins(video_adapter_t *adp) 574243423Sgonzo{ 575243423Sgonzo struct video_adapter_softc *sc; 576243423Sgonzo video_info_t *vi; 577243423Sgonzo 578243423Sgonzo sc = (struct video_adapter_softc *)adp; 579243423Sgonzo vi = &adp->va_info; 580243423Sgonzo 581243423Sgonzo sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 582243423Sgonzo sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 583243423Sgonzo} 584243423Sgonzo 585239922Sgonzostatic int 586239922Sgonzobcmfb_configure(int flags) 587239922Sgonzo{ 588243423Sgonzo struct video_adapter_softc *va_sc; 589239922Sgonzo 590243423Sgonzo va_sc = &va_softc; 591243423Sgonzo phandle_t display, root; 592243423Sgonzo pcell_t cell; 593239922Sgonzo 594243423Sgonzo if (va_sc->initialized) 595243423Sgonzo return (0); 596239922Sgonzo 597243423Sgonzo va_sc->width = 0; 598243423Sgonzo va_sc->height = 0; 599239922Sgonzo 600243423Sgonzo /* 601243423Sgonzo * It seems there is no way to let syscons framework know 602243423Sgonzo * that framebuffer resolution has changed. So just try 603243423Sgonzo * to fetch data from FDT and go with defaults if failed 604243423Sgonzo */ 605243423Sgonzo root = OF_finddevice("/"); 606243423Sgonzo if ((root != 0) && 607243423Sgonzo (display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) { 608243423Sgonzo if ((OF_getprop(display, "broadcom,width", 609243423Sgonzo &cell, sizeof(cell))) > 0) 610243423Sgonzo va_sc->width = (int)fdt32_to_cpu(cell); 611239922Sgonzo 612243423Sgonzo if ((OF_getprop(display, "broadcom,height", 613243423Sgonzo &cell, sizeof(cell))) > 0) 614243423Sgonzo va_sc->height = (int)fdt32_to_cpu(cell); 615243423Sgonzo } 616239922Sgonzo 617243423Sgonzo if (va_sc->width == 0) 618243423Sgonzo va_sc->width = FB_WIDTH; 619243423Sgonzo if (va_sc->height == 0) 620243423Sgonzo va_sc->height = FB_HEIGHT; 621243423Sgonzo 622243423Sgonzo bcmfb_init(0, &va_sc->va, 0); 623243423Sgonzo 624243423Sgonzo va_sc->initialized = 1; 625243423Sgonzo 626239922Sgonzo return (0); 627239922Sgonzo} 628239922Sgonzo 629239922Sgonzostatic int 630239922Sgonzobcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 631239922Sgonzo{ 632239922Sgonzo 633239922Sgonzo return (0); 634239922Sgonzo} 635239922Sgonzo 636239922Sgonzostatic int 637239922Sgonzobcmfb_init(int unit, video_adapter_t *adp, int flags) 638239922Sgonzo{ 639239922Sgonzo struct video_adapter_softc *sc; 640239922Sgonzo video_info_t *vi; 641239922Sgonzo 642239922Sgonzo sc = (struct video_adapter_softc *)adp; 643239922Sgonzo vi = &adp->va_info; 644239922Sgonzo 645239922Sgonzo vid_init_struct(adp, "bcmfb", -1, unit); 646239922Sgonzo 647239922Sgonzo sc->font = dflt_font_16; 648239922Sgonzo vi->vi_cheight = BCMFB_FONT_HEIGHT; 649239922Sgonzo vi->vi_cwidth = 8; 650243423Sgonzo 651239922Sgonzo vi->vi_width = sc->width/8; 652239922Sgonzo vi->vi_height = sc->height/vi->vi_cheight; 653239922Sgonzo 654239922Sgonzo /* 655239922Sgonzo * Clamp width/height to syscons maximums 656239922Sgonzo */ 657239922Sgonzo if (vi->vi_width > COL) 658239922Sgonzo vi->vi_width = COL; 659239922Sgonzo if (vi->vi_height > ROW) 660239922Sgonzo vi->vi_height = ROW; 661239922Sgonzo 662239922Sgonzo sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 663239922Sgonzo sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 664239922Sgonzo 665243423Sgonzo 666239922Sgonzo adp->va_window = (vm_offset_t) bcmfb_static_window; 667239922Sgonzo adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; 668239922Sgonzo 669239922Sgonzo vid_register(&sc->va); 670239922Sgonzo 671239922Sgonzo return (0); 672239922Sgonzo} 673239922Sgonzo 674239922Sgonzostatic int 675239922Sgonzobcmfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 676239922Sgonzo{ 677239922Sgonzo bcopy(&adp->va_info, info, sizeof(*info)); 678239922Sgonzo return (0); 679239922Sgonzo} 680239922Sgonzo 681239922Sgonzostatic int 682239922Sgonzobcmfb_query_mode(video_adapter_t *adp, video_info_t *info) 683239922Sgonzo{ 684239922Sgonzo return (0); 685239922Sgonzo} 686239922Sgonzo 687239922Sgonzostatic int 688239922Sgonzobcmfb_set_mode(video_adapter_t *adp, int mode) 689239922Sgonzo{ 690239922Sgonzo return (0); 691239922Sgonzo} 692239922Sgonzo 693239922Sgonzostatic int 694239922Sgonzobcmfb_save_font(video_adapter_t *adp, int page, int size, int width, 695239922Sgonzo u_char *data, int c, int count) 696239922Sgonzo{ 697239922Sgonzo return (0); 698239922Sgonzo} 699239922Sgonzo 700239922Sgonzostatic int 701239922Sgonzobcmfb_load_font(video_adapter_t *adp, int page, int size, int width, 702239922Sgonzo u_char *data, int c, int count) 703239922Sgonzo{ 704239922Sgonzo struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; 705239922Sgonzo 706239922Sgonzo sc->font = data; 707239922Sgonzo 708239922Sgonzo return (0); 709239922Sgonzo} 710239922Sgonzo 711239922Sgonzostatic int 712239922Sgonzobcmfb_show_font(video_adapter_t *adp, int page) 713239922Sgonzo{ 714239922Sgonzo return (0); 715239922Sgonzo} 716239922Sgonzo 717239922Sgonzostatic int 718239922Sgonzobcmfb_save_palette(video_adapter_t *adp, u_char *palette) 719239922Sgonzo{ 720239922Sgonzo return (0); 721239922Sgonzo} 722239922Sgonzo 723239922Sgonzostatic int 724239922Sgonzobcmfb_load_palette(video_adapter_t *adp, u_char *palette) 725239922Sgonzo{ 726239922Sgonzo return (0); 727239922Sgonzo} 728239922Sgonzo 729239922Sgonzostatic int 730239922Sgonzobcmfb_set_border(video_adapter_t *adp, int border) 731239922Sgonzo{ 732239922Sgonzo return (bcmfb_blank_display(adp, border)); 733239922Sgonzo} 734239922Sgonzo 735239922Sgonzostatic int 736239922Sgonzobcmfb_save_state(video_adapter_t *adp, void *p, size_t size) 737239922Sgonzo{ 738239922Sgonzo return (0); 739239922Sgonzo} 740239922Sgonzo 741239922Sgonzostatic int 742239922Sgonzobcmfb_load_state(video_adapter_t *adp, void *p) 743239922Sgonzo{ 744239922Sgonzo return (0); 745239922Sgonzo} 746239922Sgonzo 747239922Sgonzostatic int 748239922Sgonzobcmfb_set_win_org(video_adapter_t *adp, off_t offset) 749239922Sgonzo{ 750239922Sgonzo return (0); 751239922Sgonzo} 752239922Sgonzo 753239922Sgonzostatic int 754239922Sgonzobcmfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 755239922Sgonzo{ 756239922Sgonzo *col = *row = 0; 757239922Sgonzo 758239922Sgonzo return (0); 759239922Sgonzo} 760239922Sgonzo 761239922Sgonzostatic int 762239922Sgonzobcmfb_set_hw_cursor(video_adapter_t *adp, int col, int row) 763239922Sgonzo{ 764239922Sgonzo return (0); 765239922Sgonzo} 766239922Sgonzo 767239922Sgonzostatic int 768239922Sgonzobcmfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 769239922Sgonzo int celsize, int blink) 770239922Sgonzo{ 771239922Sgonzo return (0); 772239922Sgonzo} 773239922Sgonzo 774239922Sgonzostatic int 775239922Sgonzobcmfb_blank_display(video_adapter_t *adp, int mode) 776239922Sgonzo{ 777239922Sgonzo 778243423Sgonzo struct video_adapter_softc *sc; 779243423Sgonzo 780243423Sgonzo sc = (struct video_adapter_softc *)adp; 781243423Sgonzo if (sc && sc->fb_addr) 782243423Sgonzo memset((void*)sc->fb_addr, 0, sc->fb_size); 783243423Sgonzo 784239922Sgonzo return (0); 785239922Sgonzo} 786239922Sgonzo 787239922Sgonzostatic int 788239922Sgonzobcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 789239922Sgonzo int prot, vm_memattr_t *memattr) 790239922Sgonzo{ 791239922Sgonzo struct video_adapter_softc *sc; 792239922Sgonzo 793239922Sgonzo sc = (struct video_adapter_softc *)adp; 794239922Sgonzo 795239922Sgonzo /* 796239922Sgonzo * This might be a legacy VGA mem request: if so, just point it at the 797239922Sgonzo * framebuffer, since it shouldn't be touched 798239922Sgonzo */ 799239922Sgonzo if (offset < sc->stride*sc->height) { 800245389Sray *paddr = sc->fb_paddr + offset; 801239922Sgonzo return (0); 802239922Sgonzo } 803239922Sgonzo 804239922Sgonzo return (EINVAL); 805239922Sgonzo} 806239922Sgonzo 807239922Sgonzostatic int 808239922Sgonzobcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 809239922Sgonzo{ 810245389Sray struct video_adapter_softc *sc; 811245389Sray struct fbtype *fb; 812239922Sgonzo 813245389Sray sc = (struct video_adapter_softc *)adp; 814245389Sray 815245389Sray switch (cmd) { 816245389Sray case FBIOGTYPE: 817245389Sray fb = (struct fbtype *)data; 818245389Sray fb->fb_type = FBTYPE_PCIMISC; 819245389Sray fb->fb_height = sc->height; 820245389Sray fb->fb_width = sc->width; 821245389Sray fb->fb_depth = sc->depth; 822245389Sray if (sc->depth <= 1 || sc->depth > 8) 823245389Sray fb->fb_cmsize = 0; 824245389Sray else 825245389Sray fb->fb_cmsize = 1 << sc->depth; 826245389Sray fb->fb_size = sc->fb_size; 827245389Sray break; 828245389Sray default: 829245389Sray return (fb_commonioctl(adp, cmd, data)); 830245389Sray } 831245389Sray 832239922Sgonzo return (0); 833239922Sgonzo} 834239922Sgonzo 835239922Sgonzostatic int 836239922Sgonzobcmfb_clear(video_adapter_t *adp) 837239922Sgonzo{ 838239922Sgonzo 839239922Sgonzo return (bcmfb_blank_display(adp, 0)); 840239922Sgonzo} 841239922Sgonzo 842239922Sgonzostatic int 843239922Sgonzobcmfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 844239922Sgonzo{ 845239922Sgonzo 846239922Sgonzo return (0); 847239922Sgonzo} 848239922Sgonzo 849239922Sgonzostatic int 850239922Sgonzobcmfb_bitblt(video_adapter_t *adp, ...) 851239922Sgonzo{ 852239922Sgonzo 853239922Sgonzo return (0); 854239922Sgonzo} 855239922Sgonzo 856239922Sgonzostatic int 857239922Sgonzobcmfb_diag(video_adapter_t *adp, int level) 858239922Sgonzo{ 859239922Sgonzo 860239922Sgonzo return (0); 861239922Sgonzo} 862239922Sgonzo 863239922Sgonzostatic int 864239922Sgonzobcmfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 865239922Sgonzo{ 866239922Sgonzo 867239922Sgonzo return (0); 868239922Sgonzo} 869239922Sgonzo 870239922Sgonzostatic int 871239922Sgonzobcmfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 872239922Sgonzo{ 873239922Sgonzo 874239922Sgonzo return (0); 875239922Sgonzo} 876239922Sgonzo 877239922Sgonzostatic int 878239922Sgonzobcmfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 879239922Sgonzo{ 880239922Sgonzo 881239922Sgonzo return (0); 882239922Sgonzo} 883239922Sgonzo 884239922Sgonzostatic int 885239922Sgonzobcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 886239922Sgonzo int size, int bpp, int bit_ltor, int byte_ltor) 887239922Sgonzo{ 888239922Sgonzo 889239922Sgonzo return (0); 890239922Sgonzo} 891239922Sgonzo 892239922Sgonzostatic int 893239922Sgonzobcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 894239922Sgonzo{ 895239922Sgonzo struct video_adapter_softc *sc; 896239922Sgonzo int row; 897239922Sgonzo int col; 898239922Sgonzo int i, j, k; 899239922Sgonzo uint8_t *addr; 900239922Sgonzo u_char *p; 901239922Sgonzo uint8_t fg, bg, color; 902243423Sgonzo uint16_t rgb; 903239922Sgonzo 904239922Sgonzo sc = (struct video_adapter_softc *)adp; 905239922Sgonzo 906239922Sgonzo if (sc->fb_addr == 0) 907239922Sgonzo return (0); 908239922Sgonzo 909239922Sgonzo row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 910239922Sgonzo col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 911239922Sgonzo p = sc->font + c*BCMFB_FONT_HEIGHT; 912239922Sgonzo addr = (uint8_t *)sc->fb_addr 913239922Sgonzo + (row + sc->ymargin)*(sc->stride) 914243666Sgonzo + (sc->depth/8) * (col + sc->xmargin); 915239922Sgonzo 916243423Sgonzo fg = a & 0xf ; 917245071Sgonzo bg = (a >> 4) & 0xf; 918239922Sgonzo 919239922Sgonzo for (i = 0; i < BCMFB_FONT_HEIGHT; i++) { 920239922Sgonzo for (j = 0, k = 7; j < 8; j++, k--) { 921239922Sgonzo if ((p[i] & (1 << k)) == 0) 922239922Sgonzo color = bg; 923239922Sgonzo else 924239922Sgonzo color = fg; 925239922Sgonzo 926243423Sgonzo switch (sc->depth) { 927243423Sgonzo case 32: 928243423Sgonzo addr[4*j+0] = bcmfb_palette[color].r; 929243423Sgonzo addr[4*j+1] = bcmfb_palette[color].g; 930243423Sgonzo addr[4*j+2] = bcmfb_palette[color].b; 931243423Sgonzo addr[4*j+3] = bcmfb_palette[color].a; 932243423Sgonzo break; 933243423Sgonzo case 24: 934243423Sgonzo addr[3*j] = bcmfb_palette[color].r; 935243423Sgonzo addr[3*j+1] = bcmfb_palette[color].g; 936243423Sgonzo addr[3*j+2] = bcmfb_palette[color].b; 937243423Sgonzo break; 938243423Sgonzo case 16: 939243687Sgonzo rgb = (bcmfb_palette[color].r >> 3) << 11; 940243687Sgonzo rgb |= (bcmfb_palette[color].g >> 2) << 5; 941243423Sgonzo rgb |= (bcmfb_palette[color].b >> 3); 942243687Sgonzo addr[2*j] = rgb & 0xff; 943243687Sgonzo addr[2*j + 1] = (rgb >> 8) & 0xff; 944243423Sgonzo default: 945243423Sgonzo /* Not supported yet */ 946243423Sgonzo break; 947243423Sgonzo } 948239922Sgonzo } 949239922Sgonzo 950239922Sgonzo addr += (sc->stride); 951239922Sgonzo } 952239922Sgonzo 953239922Sgonzo return (0); 954239922Sgonzo} 955239922Sgonzo 956239922Sgonzostatic int 957239922Sgonzobcmfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 958239922Sgonzo{ 959239922Sgonzo int i; 960239922Sgonzo 961239922Sgonzo for (i = 0; i < len; i++) 962239922Sgonzo bcmfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 963239922Sgonzo 964239922Sgonzo return (0); 965239922Sgonzo} 966239922Sgonzo 967239922Sgonzostatic int 968239922Sgonzobcmfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 969239922Sgonzo uint32_t pixel_mask, int size, int width) 970239922Sgonzo{ 971239922Sgonzo 972239922Sgonzo return (0); 973239922Sgonzo} 974239922Sgonzo 975239922Sgonzo/* 976239922Sgonzo * Define a stub keyboard driver in case one hasn't been 977239922Sgonzo * compiled into the kernel 978239922Sgonzo */ 979239922Sgonzo#include <sys/kbio.h> 980239922Sgonzo#include <dev/kbd/kbdreg.h> 981239922Sgonzo 982239922Sgonzostatic int dummy_kbd_configure(int flags); 983239922Sgonzo 984239922Sgonzokeyboard_switch_t bcmdummysw; 985239922Sgonzo 986239922Sgonzostatic int 987239922Sgonzodummy_kbd_configure(int flags) 988239922Sgonzo{ 989239922Sgonzo 990239922Sgonzo return (0); 991239922Sgonzo} 992239922SgonzoKEYBOARD_DRIVER(bcmdummy, bcmdummysw, dummy_kbd_configure); 993