1239278Sgonzo/*- 2239278Sgonzo * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org> 3239278Sgonzo * All rights reserved. 4239278Sgonzo * 5239278Sgonzo * Redistribution and use in source and binary forms, with or without 6239278Sgonzo * modification, are permitted provided that the following conditions 7239278Sgonzo * are met: 8239278Sgonzo * 1. Redistributions of source code must retain the above copyright 9239278Sgonzo * notice, this list of conditions and the following disclaimer. 10239278Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 11239278Sgonzo * notice, this list of conditions and the following disclaimer in the 12239278Sgonzo * documentation and/or other materials provided with the distribution. 13239278Sgonzo * 14239278Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15239278Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16239278Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17239278Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18239278Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19239278Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20239278Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21239278Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22239278Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23239278Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24239278Sgonzo * SUCH DAMAGE. 25239278Sgonzo * 26239278Sgonzo */ 27239278Sgonzo#include <sys/cdefs.h> 28239278Sgonzo__FBSDID("$FreeBSD$"); 29239278Sgonzo 30239278Sgonzo#include <sys/param.h> 31239278Sgonzo#include <sys/systm.h> 32239278Sgonzo#include <sys/bio.h> 33239278Sgonzo#include <sys/bus.h> 34239278Sgonzo#include <sys/conf.h> 35239278Sgonzo#include <sys/endian.h> 36239278Sgonzo#include <sys/kernel.h> 37239278Sgonzo#include <sys/kthread.h> 38239278Sgonzo#include <sys/lock.h> 39239278Sgonzo#include <sys/malloc.h> 40239278Sgonzo#include <sys/module.h> 41239278Sgonzo#include <sys/mutex.h> 42239278Sgonzo#include <sys/queue.h> 43239278Sgonzo#include <sys/resource.h> 44239278Sgonzo#include <sys/rman.h> 45239278Sgonzo#include <sys/time.h> 46239278Sgonzo#include <sys/timetc.h> 47239278Sgonzo#include <sys/watchdog.h> 48239278Sgonzo 49239278Sgonzo#include <sys/kdb.h> 50239278Sgonzo 51239278Sgonzo#include <machine/bus.h> 52239278Sgonzo#include <machine/cpu.h> 53239278Sgonzo#include <machine/cpufunc.h> 54239278Sgonzo#include <machine/resource.h> 55239278Sgonzo#include <machine/intr.h> 56239278Sgonzo 57239278Sgonzo#include <dev/fdt/fdt_common.h> 58239278Sgonzo#include <dev/ofw/ofw_bus.h> 59239278Sgonzo#include <dev/ofw/ofw_bus_subr.h> 60239278Sgonzo 61239278Sgonzo#include <arm/lpc/lpcreg.h> 62239278Sgonzo#include <arm/lpc/lpcvar.h> 63239278Sgonzo 64239278Sgonzo 65239278Sgonzostruct lpc_fb_dmamap_arg { 66239278Sgonzo bus_addr_t lf_dma_busaddr; 67239278Sgonzo}; 68239278Sgonzo 69239278Sgonzostruct lpc_lcd_config { 70239278Sgonzo int lc_xres; 71239278Sgonzo int lc_yres; 72239278Sgonzo int lc_bpp; 73239278Sgonzo uint32_t lc_pixelclock; 74239278Sgonzo int lc_left_margin; 75239278Sgonzo int lc_right_margin; 76239278Sgonzo int lc_upper_margin; 77239278Sgonzo int lc_lower_margin; 78239278Sgonzo int lc_hsync_len; 79239278Sgonzo int lc_vsync_len; 80239278Sgonzo}; 81239278Sgonzo 82239278Sgonzostruct lpc_fb_softc { 83239278Sgonzo device_t lf_dev; 84239278Sgonzo struct cdev * lf_cdev; 85239278Sgonzo struct mtx lf_mtx; 86239278Sgonzo struct resource * lf_mem_res; 87239278Sgonzo struct resource * lf_irq_res; 88239278Sgonzo bus_space_tag_t lf_bst; 89239278Sgonzo bus_space_handle_t lf_bsh; 90239278Sgonzo void * lf_intrhand; 91239278Sgonzo bus_dma_tag_t lf_dma_tag; 92239278Sgonzo bus_dmamap_t lf_dma_map; 93239278Sgonzo void * lf_buffer; 94239278Sgonzo bus_addr_t lf_buffer_phys; 95239278Sgonzo bus_size_t lf_buffer_size; 96239278Sgonzo struct lpc_lcd_config lf_lcd_config; 97239278Sgonzo int lf_initialized; 98239278Sgonzo int lf_opened; 99239278Sgonzo}; 100239278Sgonzo 101239278Sgonzoextern void ssd1289_configure(void); 102239278Sgonzo 103239278Sgonzo#define lpc_fb_lock(_sc) mtx_lock(&(_sc)->lf_mtx) 104239278Sgonzo#define lpc_fb_unlock(_sc) mtx_unlock(&(_sc)->lf_mtx) 105239278Sgonzo#define lpc_fb_lock_assert(sc) mtx_assert(&(_sc)->lf_mtx, MA_OWNED) 106239278Sgonzo 107239278Sgonzo#define lpc_fb_read_4(_sc, _reg) \ 108239278Sgonzo bus_space_read_4((_sc)->lf_bst, (_sc)->lf_bsh, (_reg)) 109239278Sgonzo#define lpc_fb_write_4(_sc, _reg, _val) \ 110239278Sgonzo bus_space_write_4((_sc)->lf_bst, (_sc)->lf_bsh, (_reg), (_val)) 111239278Sgonzo 112239278Sgonzo 113239278Sgonzo 114239278Sgonzostatic int lpc_fb_probe(device_t); 115239278Sgonzostatic int lpc_fb_attach(device_t); 116239278Sgonzostatic void lpc_fb_intr(void *); 117239278Sgonzostatic void lpc_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err); 118239278Sgonzo 119239278Sgonzostatic int lpc_fb_fdt_read(phandle_t, const char *, uint32_t *); 120239278Sgonzostatic int lpc_fb_read_lcd_config(phandle_t, struct lpc_lcd_config *); 121239278Sgonzo 122239278Sgonzostatic int lpc_fb_open(struct cdev *, int, int, struct thread *); 123239278Sgonzostatic int lpc_fb_close(struct cdev *, int, int, struct thread *); 124239278Sgonzostatic int lpc_fb_ioctl(struct cdev *, u_long, caddr_t, int, struct thread *); 125239278Sgonzostatic int lpc_fb_mmap(struct cdev *, vm_ooffset_t, vm_paddr_t *, int, vm_memattr_t *); 126239278Sgonzo 127239278Sgonzostatic void lpc_fb_blank(struct lpc_fb_softc *); 128239278Sgonzo 129239278Sgonzostatic struct cdevsw lpc_fb_cdevsw = { 130239278Sgonzo .d_open = lpc_fb_open, 131239278Sgonzo .d_close = lpc_fb_close, 132239278Sgonzo .d_ioctl = lpc_fb_ioctl, 133239278Sgonzo .d_mmap = lpc_fb_mmap, 134239278Sgonzo .d_name = "lpcfb", 135239278Sgonzo .d_version = D_VERSION, 136239278Sgonzo}; 137239278Sgonzo 138239278Sgonzostatic int 139239278Sgonzolpc_fb_probe(device_t dev) 140239278Sgonzo{ 141266152Sian 142266152Sian if (!ofw_bus_status_okay(dev)) 143266152Sian return (ENXIO); 144266152Sian 145239278Sgonzo if (!ofw_bus_is_compatible(dev, "lpc,fb")) 146239278Sgonzo return (ENXIO); 147239278Sgonzo 148239278Sgonzo device_set_desc(dev, "LPC32x0 framebuffer device"); 149239278Sgonzo return (BUS_PROBE_DEFAULT); 150239278Sgonzo} 151239278Sgonzo 152239278Sgonzostatic int 153239278Sgonzolpc_fb_attach(device_t dev) 154239278Sgonzo{ 155239278Sgonzo struct lpc_fb_softc *sc = device_get_softc(dev); 156239278Sgonzo struct lpc_fb_dmamap_arg ctx; 157239278Sgonzo phandle_t node; 158239278Sgonzo int mode, rid, err = 0; 159239278Sgonzo 160239278Sgonzo sc->lf_dev = dev; 161239278Sgonzo mtx_init(&sc->lf_mtx, "lpcfb", "fb", MTX_DEF); 162239278Sgonzo 163239278Sgonzo rid = 0; 164239278Sgonzo sc->lf_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 165239278Sgonzo RF_ACTIVE); 166239278Sgonzo if (!sc->lf_mem_res) { 167239278Sgonzo device_printf(dev, "cannot allocate memory window\n"); 168239278Sgonzo return (ENXIO); 169239278Sgonzo } 170239278Sgonzo 171239278Sgonzo sc->lf_bst = rman_get_bustag(sc->lf_mem_res); 172239278Sgonzo sc->lf_bsh = rman_get_bushandle(sc->lf_mem_res); 173239278Sgonzo 174239278Sgonzo rid = 0; 175239278Sgonzo sc->lf_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 176239278Sgonzo RF_ACTIVE); 177239278Sgonzo if (!sc->lf_irq_res) { 178239278Sgonzo device_printf(dev, "cannot allocate interrupt\n"); 179239278Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lf_mem_res); 180239278Sgonzo return (ENXIO); 181239278Sgonzo } 182239278Sgonzo 183239278Sgonzo if (bus_setup_intr(dev, sc->lf_irq_res, INTR_TYPE_MISC | INTR_MPSAFE, 184239278Sgonzo NULL, lpc_fb_intr, sc, &sc->lf_intrhand)) 185239278Sgonzo { 186239278Sgonzo bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lf_mem_res); 187239278Sgonzo bus_release_resource(dev, SYS_RES_IRQ, 1, sc->lf_irq_res); 188239278Sgonzo device_printf(dev, "cannot setup interrupt handler\n"); 189239278Sgonzo return (ENXIO); 190239278Sgonzo } 191239278Sgonzo 192239278Sgonzo node = ofw_bus_get_node(dev); 193239278Sgonzo 194239278Sgonzo err = lpc_fb_read_lcd_config(node, &sc->lf_lcd_config); 195239278Sgonzo if (err) { 196239278Sgonzo device_printf(dev, "cannot read LCD configuration\n"); 197239278Sgonzo goto fail; 198239278Sgonzo } 199239278Sgonzo 200239278Sgonzo sc->lf_buffer_size = sc->lf_lcd_config.lc_xres * 201239278Sgonzo sc->lf_lcd_config.lc_yres * 202239278Sgonzo (sc->lf_lcd_config.lc_bpp == 24 ? 3 : 2); 203239278Sgonzo 204239278Sgonzo device_printf(dev, "%dx%d LCD, %d bits per pixel, %dkHz pixel clock\n", 205239278Sgonzo sc->lf_lcd_config.lc_xres, sc->lf_lcd_config.lc_yres, 206239278Sgonzo sc->lf_lcd_config.lc_bpp, sc->lf_lcd_config.lc_pixelclock / 1000); 207239278Sgonzo 208239278Sgonzo err = bus_dma_tag_create( 209239278Sgonzo bus_get_dma_tag(sc->lf_dev), 210239278Sgonzo 4, 0, /* alignment, boundary */ 211239278Sgonzo BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 212239278Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 213239278Sgonzo NULL, NULL, /* filter, filterarg */ 214239278Sgonzo sc->lf_buffer_size, 1, /* maxsize, nsegments */ 215239278Sgonzo sc->lf_buffer_size, 0, /* maxsegsize, flags */ 216239278Sgonzo NULL, NULL, /* lockfunc, lockarg */ 217239278Sgonzo &sc->lf_dma_tag); 218239278Sgonzo 219239278Sgonzo err = bus_dmamem_alloc(sc->lf_dma_tag, (void **)&sc->lf_buffer, 220239278Sgonzo 0, &sc->lf_dma_map); 221239278Sgonzo if (err) { 222239278Sgonzo device_printf(dev, "cannot allocate framebuffer\n"); 223239278Sgonzo goto fail; 224239278Sgonzo } 225239278Sgonzo 226239278Sgonzo err = bus_dmamap_load(sc->lf_dma_tag, sc->lf_dma_map, sc->lf_buffer, 227239278Sgonzo sc->lf_buffer_size, lpc_fb_dmamap_cb, &ctx, BUS_DMA_NOWAIT); 228239278Sgonzo if (err) { 229239278Sgonzo device_printf(dev, "cannot load DMA map\n"); 230239278Sgonzo goto fail; 231239278Sgonzo } 232239278Sgonzo 233239278Sgonzo switch (sc->lf_lcd_config.lc_bpp) { 234239278Sgonzo case 12: 235239278Sgonzo mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_12; 236239278Sgonzo break; 237239278Sgonzo case 15: 238239278Sgonzo mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_15; 239239278Sgonzo break; 240239278Sgonzo case 16: 241239278Sgonzo mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_16; 242239278Sgonzo break; 243239278Sgonzo case 24: 244239278Sgonzo mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_24; 245239278Sgonzo break; 246239278Sgonzo default: 247239278Sgonzo panic("unsupported bpp"); 248239278Sgonzo } 249239278Sgonzo 250239278Sgonzo lpc_pwr_write(sc->lf_dev, LPC_CLKPWR_LCDCLK_CTRL, 251239278Sgonzo LPC_CLKPWR_LCDCLK_CTRL_MODE(mode) | 252239278Sgonzo LPC_CLKPWR_LCDCLK_CTRL_HCLKEN); 253239278Sgonzo 254239278Sgonzo sc->lf_buffer_phys = ctx.lf_dma_busaddr; 255239278Sgonzo sc->lf_cdev = make_dev(&lpc_fb_cdevsw, 0, UID_ROOT, GID_WHEEL, 256239278Sgonzo 0600, "lpcfb"); 257239278Sgonzo 258239278Sgonzo sc->lf_cdev->si_drv1 = sc; 259239278Sgonzo 260239278Sgonzo return (0); 261239278Sgonzofail: 262239278Sgonzo return (ENXIO); 263239278Sgonzo} 264239278Sgonzo 265239278Sgonzostatic void 266239278Sgonzolpc_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 267239278Sgonzo{ 268239278Sgonzo struct lpc_fb_dmamap_arg *ctx; 269239278Sgonzo 270239278Sgonzo if (err) 271239278Sgonzo return; 272239278Sgonzo 273239278Sgonzo ctx = (struct lpc_fb_dmamap_arg *)arg; 274239278Sgonzo ctx->lf_dma_busaddr = segs[0].ds_addr; 275239278Sgonzo} 276239278Sgonzo 277239278Sgonzostatic void 278239278Sgonzolpc_fb_intr(void *arg) 279239278Sgonzo{ 280239278Sgonzo} 281239278Sgonzo 282239278Sgonzostatic int 283239278Sgonzolpc_fb_fdt_read(phandle_t node, const char *name, uint32_t *ret) 284239278Sgonzo{ 285239278Sgonzo if (OF_getprop(node, name, ret, sizeof(uint32_t)) <= 0) 286239278Sgonzo return (ENOENT); 287239278Sgonzo 288239278Sgonzo *ret = fdt32_to_cpu(*ret); 289239278Sgonzo return (0); 290239278Sgonzo} 291239278Sgonzo 292239278Sgonzostatic int 293239278Sgonzolpc_fb_read_lcd_config(phandle_t node, struct lpc_lcd_config *cfg) 294239278Sgonzo{ 295239278Sgonzo if (lpc_fb_fdt_read(node, "horizontal-resolution", &cfg->lc_xres)) 296239278Sgonzo return (ENXIO); 297239278Sgonzo 298239278Sgonzo if (lpc_fb_fdt_read(node, "vertical-resolution", &cfg->lc_yres)) 299239278Sgonzo return (ENXIO); 300239278Sgonzo 301239278Sgonzo if (lpc_fb_fdt_read(node, "bits-per-pixel", &cfg->lc_bpp)) 302239278Sgonzo return (ENXIO); 303239278Sgonzo 304239278Sgonzo if (lpc_fb_fdt_read(node, "pixel-clock", &cfg->lc_pixelclock)) 305239278Sgonzo return (ENXIO); 306239278Sgonzo 307239278Sgonzo if (lpc_fb_fdt_read(node, "left-margin", &cfg->lc_left_margin)) 308239278Sgonzo return (ENXIO); 309239278Sgonzo 310239278Sgonzo if (lpc_fb_fdt_read(node, "right-margin", &cfg->lc_right_margin)) 311239278Sgonzo return (ENXIO); 312239278Sgonzo 313239278Sgonzo if (lpc_fb_fdt_read(node, "upper-margin", &cfg->lc_upper_margin)) 314239278Sgonzo return (ENXIO); 315239278Sgonzo 316239278Sgonzo if (lpc_fb_fdt_read(node, "lower-margin", &cfg->lc_lower_margin)) 317239278Sgonzo return (ENXIO); 318239278Sgonzo 319239278Sgonzo if (lpc_fb_fdt_read(node, "hsync-len", &cfg->lc_hsync_len)) 320239278Sgonzo return (ENXIO); 321239278Sgonzo 322239278Sgonzo if (lpc_fb_fdt_read(node, "vsync-len", &cfg->lc_vsync_len)) 323239278Sgonzo return (ENXIO); 324239278Sgonzo 325239278Sgonzo return (0); 326239278Sgonzo} 327239278Sgonzo 328239278Sgonzostatic void 329239278Sgonzolpc_fb_setup(struct lpc_fb_softc *sc) 330239278Sgonzo{ 331239278Sgonzo struct lpc_lcd_config *cfg = &sc->lf_lcd_config; 332239278Sgonzo uint32_t bpp; 333239278Sgonzo 334239278Sgonzo lpc_fb_write_4(sc, LPC_LCD_TIMH, 335239278Sgonzo LPC_LCD_TIMH_PPL(cfg->lc_xres) | 336239278Sgonzo LPC_LCD_TIMH_HSW(cfg->lc_hsync_len - 1) | 337239278Sgonzo LPC_LCD_TIMH_HFP(cfg->lc_right_margin - 1) | 338239278Sgonzo LPC_LCD_TIMH_HBP(cfg->lc_left_margin - 1)); 339239278Sgonzo 340239278Sgonzo lpc_fb_write_4(sc, LPC_LCD_TIMV, 341239278Sgonzo LPC_LCD_TIMV_LPP(cfg->lc_yres - 1) | 342239278Sgonzo LPC_LCD_TIMV_VSW(cfg->lc_vsync_len - 1) | 343239278Sgonzo LPC_LCD_TIMV_VFP(cfg->lc_lower_margin) | 344239278Sgonzo LPC_LCD_TIMV_VBP(cfg->lc_upper_margin)); 345239278Sgonzo 346239278Sgonzo /* XXX LPC_LCD_POL_PCD_LO */ 347239278Sgonzo lpc_fb_write_4(sc, LPC_LCD_POL, 348239278Sgonzo LPC_LCD_POL_IHS | LPC_LCD_POL_IVS | 349239278Sgonzo LPC_LCD_POL_CPL(cfg->lc_xres - 1) | 350239278Sgonzo LPC_LCD_POL_PCD_LO(4)); 351239278Sgonzo 352239278Sgonzo lpc_fb_write_4(sc, LPC_LCD_UPBASE, sc->lf_buffer_phys); 353239278Sgonzo 354239278Sgonzo switch (cfg->lc_bpp) { 355239278Sgonzo case 1: 356239278Sgonzo bpp = LPC_LCD_CTRL_BPP1; 357239278Sgonzo break; 358239278Sgonzo case 2: 359239278Sgonzo bpp = LPC_LCD_CTRL_BPP2; 360239278Sgonzo break; 361239278Sgonzo case 4: 362239278Sgonzo bpp = LPC_LCD_CTRL_BPP4; 363239278Sgonzo break; 364239278Sgonzo case 8: 365239278Sgonzo bpp = LPC_LCD_CTRL_BPP8; 366239278Sgonzo break; 367239278Sgonzo case 12: 368239278Sgonzo bpp = LPC_LCD_CTRL_BPP12_444; 369239278Sgonzo break; 370239278Sgonzo case 15: 371239278Sgonzo bpp = LPC_LCD_CTRL_BPP16; 372239278Sgonzo break; 373239278Sgonzo case 16: 374239278Sgonzo bpp = LPC_LCD_CTRL_BPP16_565; 375239278Sgonzo break; 376239278Sgonzo case 24: 377239278Sgonzo bpp = LPC_LCD_CTRL_BPP24; 378239278Sgonzo break; 379239278Sgonzo default: 380239278Sgonzo panic("LCD unknown bpp: %d", cfg->lc_bpp); 381239278Sgonzo } 382239278Sgonzo 383239278Sgonzo lpc_fb_write_4(sc, LPC_LCD_CTRL, 384239278Sgonzo LPC_LCD_CTRL_LCDVCOMP(1) | 385239278Sgonzo LPC_LCD_CTRL_LCDPWR | 386239278Sgonzo LPC_LCD_CTRL_BGR | 387239278Sgonzo LPC_LCD_CTRL_LCDTFT | 388239278Sgonzo LPC_LCD_CTRL_LCDBPP(bpp) | 389239278Sgonzo LPC_LCD_CTRL_LCDEN); 390239278Sgonzo} 391239278Sgonzo 392239278Sgonzo 393239278Sgonzostatic int 394239278Sgonzolpc_fb_open(struct cdev *cdev, int oflags, int devtype, struct thread *td) 395239278Sgonzo{ 396239278Sgonzo struct lpc_fb_softc *sc = cdev->si_drv1; 397239278Sgonzo 398239278Sgonzo lpc_fb_lock(sc); 399239278Sgonzo 400239278Sgonzo if (sc->lf_opened) 401239278Sgonzo return (EBUSY); 402239278Sgonzo 403239278Sgonzo sc->lf_opened = 1; 404239278Sgonzo 405239278Sgonzo lpc_fb_unlock(sc); 406239278Sgonzo 407239278Sgonzo if (!sc->lf_initialized) { 408239278Sgonzo ssd1289_configure(); 409239278Sgonzo lpc_fb_setup(sc); 410239278Sgonzo lpc_fb_blank(sc); 411239278Sgonzo sc->lf_initialized = 1; 412239278Sgonzo } 413239278Sgonzo 414239278Sgonzo return (0); 415239278Sgonzo} 416239278Sgonzo 417239278Sgonzostatic int 418239278Sgonzolpc_fb_close(struct cdev *cdev, int fflag, int devtype, struct thread *td) 419239278Sgonzo{ 420239278Sgonzo struct lpc_fb_softc *sc = cdev->si_drv1; 421239278Sgonzo 422239278Sgonzo lpc_fb_lock(sc); 423239278Sgonzo sc->lf_opened = 0; 424239278Sgonzo lpc_fb_unlock(sc); 425239278Sgonzo 426239278Sgonzo return (0); 427239278Sgonzo} 428239278Sgonzo 429239278Sgonzostatic int 430239278Sgonzolpc_fb_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int x, 431239278Sgonzo struct thread *td) 432239278Sgonzo{ 433239278Sgonzo 434239278Sgonzo return (EINVAL); 435239278Sgonzo} 436239278Sgonzo 437239278Sgonzostatic int 438239278Sgonzolpc_fb_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, 439239278Sgonzo int nprot, vm_memattr_t *memattr) 440239278Sgonzo{ 441239278Sgonzo struct lpc_fb_softc *sc = cdev->si_drv1; 442239278Sgonzo 443239278Sgonzo *paddr = (vm_paddr_t)(sc->lf_buffer_phys + offset); 444239278Sgonzo return (0); 445239278Sgonzo} 446239278Sgonzo 447239278Sgonzostatic void 448239278Sgonzolpc_fb_blank(struct lpc_fb_softc *sc) 449239278Sgonzo{ 450239278Sgonzo memset(sc->lf_buffer, 0xffff, sc->lf_buffer_size); 451239278Sgonzo} 452239278Sgonzo 453239278Sgonzostatic device_method_t lpc_fb_methods[] = { 454239278Sgonzo /* Device interface */ 455239278Sgonzo DEVMETHOD(device_probe, lpc_fb_probe), 456239278Sgonzo DEVMETHOD(device_attach, lpc_fb_attach), 457239278Sgonzo 458239278Sgonzo { 0, 0 } 459239278Sgonzo}; 460239278Sgonzo 461239278Sgonzostatic devclass_t lpc_fb_devclass; 462239278Sgonzo 463239278Sgonzostatic driver_t lpc_fb_driver = { 464239278Sgonzo "lpcfb", 465239278Sgonzo lpc_fb_methods, 466239278Sgonzo sizeof(struct lpc_fb_softc), 467239278Sgonzo}; 468239278Sgonzo 469239278SgonzoDRIVER_MODULE(lpcfb, simplebus, lpc_fb_driver, lpc_fb_devclass, 0, 0); 470