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