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