1330897Seadler/*- 2330897Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330897Seadler * 4331402Sgonzo * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo@freebsd.org> 5244197Sgonzo * All rights reserved. 6244197Sgonzo * 7244197Sgonzo * Redistribution and use in source and binary forms, with or without 8244197Sgonzo * modification, are permitted provided that the following conditions 9244197Sgonzo * are met: 10244197Sgonzo * 1. Redistributions of source code must retain the above copyright 11244197Sgonzo * notice, this list of conditions and the following disclaimer. 12244197Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 13244197Sgonzo * notice, this list of conditions and the following disclaimer in the 14244197Sgonzo * documentation and/or other materials provided with the distribution. 15244197Sgonzo * 16244197Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17244197Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18244197Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19244197Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20244197Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21244197Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22244197Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23244197Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24244197Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25244197Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26244197Sgonzo * SUCH DAMAGE. 27244197Sgonzo */ 28244197Sgonzo 29244197Sgonzo#include <sys/cdefs.h> 30244197Sgonzo__FBSDID("$FreeBSD: stable/11/sys/arm/versatile/versatile_clcd.c 356110 2019-12-27 03:00:18Z kevans $"); 31244197Sgonzo 32244197Sgonzo#include <sys/param.h> 33244197Sgonzo#include <sys/systm.h> 34244197Sgonzo#include <sys/bus.h> 35244197Sgonzo#include <sys/kernel.h> 36244197Sgonzo#include <sys/module.h> 37244197Sgonzo#include <sys/malloc.h> 38244197Sgonzo#include <sys/rman.h> 39244197Sgonzo#include <sys/fbio.h> 40244197Sgonzo#include <sys/consio.h> 41244197Sgonzo#include <sys/kdb.h> 42244197Sgonzo 43244197Sgonzo#include <machine/bus.h> 44244197Sgonzo#include <machine/cpu.h> 45244197Sgonzo#include <machine/intr.h> 46244197Sgonzo 47244197Sgonzo#include <dev/fdt/fdt_common.h> 48244197Sgonzo#include <dev/ofw/openfirm.h> 49244197Sgonzo#include <dev/ofw/ofw_bus.h> 50244197Sgonzo#include <dev/ofw/ofw_bus_subr.h> 51244197Sgonzo 52244197Sgonzo#include <dev/fb/fbreg.h> 53244197Sgonzo#include <dev/syscons/syscons.h> 54244197Sgonzo 55331402Sgonzo#include <arm/versatile/versatile_scm.h> 56331402Sgonzo 57244197Sgonzo#include <machine/bus.h> 58244197Sgonzo 59244197Sgonzo#define PL110_VENDOR_ARM926PXP 1 60244197Sgonzo 61244197Sgonzo#define CLCD_MODE_RGB888 0x0 62244197Sgonzo#define CLCD_MODE_RGB555 0x01 63244197Sgonzo#define CLCD_MODE_RBG565 0x02 64244197Sgonzo#define CLCD_MODE_RGB565 0x03 65244197Sgonzo 66244197Sgonzo#define CLCDC_TIMING0 0x00 67244197Sgonzo#define CLCDC_TIMING1 0x04 68244197Sgonzo#define CLCDC_TIMING2 0x08 69244197Sgonzo#define CLCDC_TIMING3 0x0C 70244197Sgonzo#define CLCDC_TIMING3 0x0C 71244197Sgonzo#define CLCDC_UPBASE 0x10 72244197Sgonzo#define CLCDC_LPBASE 0x14 73244197Sgonzo#ifdef PL110_VENDOR_ARM926PXP 74244197Sgonzo#define CLCDC_CONTROL 0x18 75244197Sgonzo#define CLCDC_IMSC 0x1C 76244197Sgonzo#else 77244197Sgonzo#define CLCDC_IMSC 0x18 78244197Sgonzo#define CLCDC_CONTROL 0x1C 79244197Sgonzo#endif 80244197Sgonzo#define CONTROL_WATERMARK (1 << 16) 81244197Sgonzo#define CONTROL_VCOMP_VS (0 << 12) 82244197Sgonzo#define CONTROL_VCOMP_BP (1 << 12) 83244197Sgonzo#define CONTROL_VCOMP_SAV (2 << 12) 84244197Sgonzo#define CONTROL_VCOMP_FP (3 << 12) 85244197Sgonzo#define CONTROL_PWR (1 << 11) 86244197Sgonzo#define CONTROL_BEPO (1 << 10) 87244197Sgonzo#define CONTROL_BEBO (1 << 9) 88244197Sgonzo#define CONTROL_BGR (1 << 8) 89244197Sgonzo#define CONTROL_DUAL (1 << 7) 90244197Sgonzo#define CONTROL_MONO8 (1 << 6) 91244197Sgonzo#define CONTROL_TFT (1 << 5) 92244197Sgonzo#define CONTROL_BW (1 << 4) 93244197Sgonzo#define CONTROL_BPP1 (0x00 << 1) 94244197Sgonzo#define CONTROL_BPP2 (0x01 << 1) 95244197Sgonzo#define CONTROL_BPP4 (0x02 << 1) 96244197Sgonzo#define CONTROL_BPP8 (0x03 << 1) 97244197Sgonzo#define CONTROL_BPP16 (0x04 << 1) 98244197Sgonzo#define CONTROL_BPP24 (0x05 << 1) 99244197Sgonzo#define CONTROL_EN (1 << 0) 100244197Sgonzo#define CLCDC_RIS 0x20 101244197Sgonzo#define CLCDC_MIS 0x24 102244197Sgonzo#define INTR_MBERR (1 << 4) 103244197Sgonzo#define INTR_VCOMP (1 << 3) 104244197Sgonzo#define INTR_LNB (1 << 2) 105244197Sgonzo#define INTR_FUF (1 << 1) 106244197Sgonzo#define CLCDC_ICR 0x28 107244197Sgonzo 108244197Sgonzo#ifdef DEBUG 109244197Sgonzo#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ 110244197Sgonzo printf(fmt,##args); } while (0) 111244197Sgonzo#else 112244197Sgonzo#define dprintf(fmt, args...) 113244197Sgonzo#endif 114244197Sgonzo 115244197Sgonzo#define versatile_clcdc_read_4(sc, reg) \ 116331402Sgonzo bus_read_4((sc)->mem_res, (reg)) 117244197Sgonzo#define versatile_clcdc_write_4(sc, reg, val) \ 118331402Sgonzo bus_write_4((sc)->mem_res, (reg), (val)) 119244197Sgonzo 120244197Sgonzostruct versatile_clcdc_softc { 121331402Sgonzo struct resource* mem_res; 122244197Sgonzo 123244197Sgonzo struct mtx mtx; 124244197Sgonzo 125244197Sgonzo int width; 126244197Sgonzo int height; 127244197Sgonzo int mode; 128244197Sgonzo 129244197Sgonzo bus_dma_tag_t dma_tag; 130244197Sgonzo bus_dmamap_t dma_map; 131244197Sgonzo bus_addr_t fb_phys; 132244197Sgonzo uint8_t *fb_base; 133244197Sgonzo 134244197Sgonzo}; 135244197Sgonzo 136244197Sgonzostruct video_adapter_softc { 137244197Sgonzo /* Videoadpater part */ 138244197Sgonzo video_adapter_t va; 139244197Sgonzo int console; 140244197Sgonzo 141244197Sgonzo intptr_t fb_addr; 142244197Sgonzo unsigned int fb_size; 143244197Sgonzo 144244197Sgonzo unsigned int height; 145244197Sgonzo unsigned int width; 146244197Sgonzo unsigned int depth; 147244197Sgonzo unsigned int stride; 148244197Sgonzo 149244197Sgonzo unsigned int xmargin; 150244197Sgonzo unsigned int ymargin; 151244197Sgonzo 152244197Sgonzo unsigned char *font; 153244197Sgonzo int initialized; 154244197Sgonzo}; 155244197Sgonzo 156244197Sgonzostruct argb { 157244197Sgonzo uint8_t a; 158244197Sgonzo uint8_t r; 159244197Sgonzo uint8_t g; 160244197Sgonzo uint8_t b; 161244197Sgonzo}; 162244197Sgonzo 163244197Sgonzostatic struct argb versatilefb_palette[16] = { 164244197Sgonzo {0x00, 0x00, 0x00, 0x00}, 165244197Sgonzo {0x00, 0x00, 0x00, 0xaa}, 166244197Sgonzo {0x00, 0x00, 0xaa, 0x00}, 167244197Sgonzo {0x00, 0x00, 0xaa, 0xaa}, 168244197Sgonzo {0x00, 0xaa, 0x00, 0x00}, 169244197Sgonzo {0x00, 0xaa, 0x00, 0xaa}, 170244197Sgonzo {0x00, 0xaa, 0x55, 0x00}, 171244197Sgonzo {0x00, 0xaa, 0xaa, 0xaa}, 172244197Sgonzo {0x00, 0x55, 0x55, 0x55}, 173244197Sgonzo {0x00, 0x55, 0x55, 0xff}, 174244197Sgonzo {0x00, 0x55, 0xff, 0x55}, 175244197Sgonzo {0x00, 0x55, 0xff, 0xff}, 176244197Sgonzo {0x00, 0xff, 0x55, 0x55}, 177244197Sgonzo {0x00, 0xff, 0x55, 0xff}, 178244197Sgonzo {0x00, 0xff, 0xff, 0x55}, 179244197Sgonzo {0x00, 0xff, 0xff, 0xff} 180244197Sgonzo}; 181244197Sgonzo 182244755Sgonzo/* mouse pointer from dev/syscons/scgfbrndr.c */ 183244755Sgonzostatic u_char mouse_pointer[16] = { 184244755Sgonzo 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 185244755Sgonzo 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 186244755Sgonzo}; 187244755Sgonzo 188244197Sgonzo#define FB_WIDTH 640 189244197Sgonzo#define FB_HEIGHT 480 190244197Sgonzo#define FB_DEPTH 16 191244197Sgonzo 192244197Sgonzo#define VERSATILE_FONT_HEIGHT 16 193244197Sgonzo 194244197Sgonzostatic struct video_adapter_softc va_softc; 195244197Sgonzo 196244197Sgonzostatic int versatilefb_configure(int); 197244197Sgonzostatic void versatilefb_update_margins(video_adapter_t *adp); 198244197Sgonzo 199244197Sgonzostatic void 200244197Sgonzoversatile_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 201244197Sgonzo{ 202244197Sgonzo bus_addr_t *addr; 203244197Sgonzo 204244197Sgonzo if (err) 205244197Sgonzo return; 206244197Sgonzo 207244197Sgonzo addr = (bus_addr_t*)arg; 208244197Sgonzo *addr = segs[0].ds_addr; 209244197Sgonzo} 210244197Sgonzo 211244197Sgonzostatic int 212244197Sgonzoversatile_clcdc_probe(device_t dev) 213244197Sgonzo{ 214244197Sgonzo 215261410Sian if (!ofw_bus_status_okay(dev)) 216261410Sian return (ENXIO); 217261410Sian 218244197Sgonzo if (ofw_bus_is_compatible(dev, "arm,pl110")) { 219244197Sgonzo device_set_desc(dev, "PL110 CLCD controller"); 220244197Sgonzo return (BUS_PROBE_DEFAULT); 221244197Sgonzo } 222244197Sgonzo 223244197Sgonzo return (ENXIO); 224244197Sgonzo} 225244197Sgonzo 226244197Sgonzostatic int 227244197Sgonzoversatile_clcdc_attach(device_t dev) 228244197Sgonzo{ 229244197Sgonzo struct versatile_clcdc_softc *sc = device_get_softc(dev); 230244197Sgonzo struct video_adapter_softc *va_sc = &va_softc; 231331402Sgonzo int err, rid; 232244197Sgonzo uint32_t reg; 233244197Sgonzo int clcdid; 234244197Sgonzo int dma_size; 235244197Sgonzo 236244197Sgonzo /* Request memory resources */ 237331402Sgonzo rid = 0; 238331402Sgonzo sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 239331402Sgonzo if (sc->mem_res == NULL) { 240331402Sgonzo device_printf(dev, "could not allocate memory resources\n"); 241244197Sgonzo return (ENXIO); 242244197Sgonzo } 243244197Sgonzo 244331402Sgonzo err = versatile_scm_reg_read_4(SCM_CLCD, ®); 245331402Sgonzo if (err) { 246331402Sgonzo device_printf(dev, "failed to read SCM register\n"); 247331402Sgonzo goto fail; 248331402Sgonzo } 249331402Sgonzo clcdid = (reg >> SCM_CLCD_CLCDID_SHIFT) & SCM_CLCD_CLCDID_MASK; 250244197Sgonzo switch (clcdid) { 251244197Sgonzo case 31: 252244197Sgonzo device_printf(dev, "QEMU VGA 640x480\n"); 253244197Sgonzo sc->width = 640; 254244197Sgonzo sc->height = 480; 255244197Sgonzo break; 256244197Sgonzo default: 257244197Sgonzo device_printf(dev, "Unsupported: %d\n", clcdid); 258244197Sgonzo goto fail; 259244197Sgonzo } 260244197Sgonzo 261331402Sgonzo reg &= ~SCM_CLCD_LCD_MODE_MASK; 262244197Sgonzo reg |= CLCD_MODE_RGB565; 263244197Sgonzo sc->mode = CLCD_MODE_RGB565; 264331402Sgonzo versatile_scm_reg_write_4(SCM_CLCD, reg); 265331402Sgonzo dma_size = sc->width*sc->height*2; 266331402Sgonzo 267331402Sgonzo /* 268244197Sgonzo * Power on LCD 269244197Sgonzo */ 270331402Sgonzo reg |= SCM_CLCD_PWR3V5VSWITCH | SCM_CLCD_NLCDIOON; 271331402Sgonzo versatile_scm_reg_write_4(SCM_CLCD, reg); 272244197Sgonzo 273244197Sgonzo /* 274244197Sgonzo * XXX: hardcoded timing for VGA. For other modes/panels 275244197Sgonzo * we need to keep table of timing register values 276244197Sgonzo */ 277244197Sgonzo /* 278244197Sgonzo * XXX: set SYS_OSC1 279244197Sgonzo */ 280244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_TIMING0, 0x3F1F3F9C); 281244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_TIMING1, 0x090B61DF); 282244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_TIMING2, 0x067F1800); 283244197Sgonzo /* XXX: timing 3? */ 284244197Sgonzo 285244197Sgonzo /* 286244197Sgonzo * Now allocate framebuffer memory 287244197Sgonzo */ 288244197Sgonzo err = bus_dma_tag_create( 289244197Sgonzo bus_get_dma_tag(dev), 290244197Sgonzo 4, 0, /* alignment, boundary */ 291244197Sgonzo BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 292244197Sgonzo BUS_SPACE_MAXADDR, /* highaddr */ 293244197Sgonzo NULL, NULL, /* filter, filterarg */ 294244197Sgonzo dma_size, 1, /* maxsize, nsegments */ 295244197Sgonzo dma_size, 0, /* maxsegsize, flags */ 296244197Sgonzo NULL, NULL, /* lockfunc, lockarg */ 297244197Sgonzo &sc->dma_tag); 298244197Sgonzo 299244197Sgonzo err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_base, 300244197Sgonzo 0, &sc->dma_map); 301244197Sgonzo if (err) { 302244197Sgonzo device_printf(dev, "cannot allocate framebuffer\n"); 303244197Sgonzo goto fail; 304244197Sgonzo } 305244197Sgonzo 306244197Sgonzo err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_base, 307244197Sgonzo dma_size, versatile_fb_dmamap_cb, &sc->fb_phys, BUS_DMA_NOWAIT); 308244197Sgonzo 309244197Sgonzo if (err) { 310244197Sgonzo device_printf(dev, "cannot load DMA map\n"); 311244197Sgonzo goto fail; 312244197Sgonzo } 313244197Sgonzo 314244197Sgonzo /* Make sure it's blank */ 315244197Sgonzo memset(sc->fb_base, 0x00, dma_size); 316244197Sgonzo 317244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_UPBASE, sc->fb_phys); 318244197Sgonzo 319244197Sgonzo err = (sc_attach_unit(device_get_unit(dev), 320244197Sgonzo device_get_flags(dev) | SC_AUTODETECT_KBD)); 321244197Sgonzo 322244197Sgonzo if (err) { 323244197Sgonzo device_printf(dev, "failed to attach syscons\n"); 324244197Sgonzo goto fail; 325244197Sgonzo } 326244197Sgonzo 327244197Sgonzo /* 328244197Sgonzo * XXX: hardcoded for VGA 329244197Sgonzo */ 330244197Sgonzo reg = CONTROL_VCOMP_BP | CONTROL_TFT | CONTROL_BGR | CONTROL_EN; 331244197Sgonzo reg |= CONTROL_BPP16; 332244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); 333244197Sgonzo DELAY(20); 334244197Sgonzo reg |= CONTROL_PWR; 335244197Sgonzo versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); 336244197Sgonzo 337244197Sgonzo va_sc->fb_addr = (vm_offset_t)sc->fb_base; 338244197Sgonzo va_sc->fb_size = dma_size; 339244197Sgonzo va_sc->width = sc->width; 340244197Sgonzo va_sc->height = sc->height; 341244197Sgonzo va_sc->depth = 16; 342244197Sgonzo va_sc->stride = sc->width * 2; 343244197Sgonzo versatilefb_update_margins(&va_sc->va); 344244197Sgonzo 345244197Sgonzo return (0); 346244197Sgonzo 347244197Sgonzofail: 348244197Sgonzo if (sc->fb_base) 349244197Sgonzo bus_dmamem_free(sc->dma_tag, sc->fb_base, sc->dma_map); 350244197Sgonzo if (sc->dma_tag) 351244197Sgonzo bus_dma_tag_destroy(sc->dma_tag); 352244197Sgonzo return (err); 353244197Sgonzo} 354244197Sgonzo 355244197Sgonzostatic device_method_t versatile_clcdc_methods[] = { 356244197Sgonzo DEVMETHOD(device_probe, versatile_clcdc_probe), 357244197Sgonzo DEVMETHOD(device_attach, versatile_clcdc_attach), 358244197Sgonzo 359244197Sgonzo DEVMETHOD_END 360244197Sgonzo}; 361244197Sgonzo 362244197Sgonzostatic driver_t versatile_clcdc_driver = { 363244197Sgonzo "clcdc", 364244197Sgonzo versatile_clcdc_methods, 365244197Sgonzo sizeof(struct versatile_clcdc_softc), 366244197Sgonzo}; 367244197Sgonzo 368244197Sgonzostatic devclass_t versatile_clcdc_devclass; 369244197Sgonzo 370244197SgonzoDRIVER_MODULE(versatile_clcdc, simplebus, versatile_clcdc_driver, versatile_clcdc_devclass, 0, 0); 371244197Sgonzo 372244197Sgonzo/* 373244197Sgonzo * Video driver routines and glue. 374244197Sgonzo */ 375244197Sgonzostatic vi_probe_t versatilefb_probe; 376244197Sgonzostatic vi_init_t versatilefb_init; 377244197Sgonzostatic vi_get_info_t versatilefb_get_info; 378244197Sgonzostatic vi_query_mode_t versatilefb_query_mode; 379244197Sgonzostatic vi_set_mode_t versatilefb_set_mode; 380244197Sgonzostatic vi_save_font_t versatilefb_save_font; 381244197Sgonzostatic vi_load_font_t versatilefb_load_font; 382244197Sgonzostatic vi_show_font_t versatilefb_show_font; 383244197Sgonzostatic vi_save_palette_t versatilefb_save_palette; 384244197Sgonzostatic vi_load_palette_t versatilefb_load_palette; 385244197Sgonzostatic vi_set_border_t versatilefb_set_border; 386244197Sgonzostatic vi_save_state_t versatilefb_save_state; 387244197Sgonzostatic vi_load_state_t versatilefb_load_state; 388244197Sgonzostatic vi_set_win_org_t versatilefb_set_win_org; 389244197Sgonzostatic vi_read_hw_cursor_t versatilefb_read_hw_cursor; 390244197Sgonzostatic vi_set_hw_cursor_t versatilefb_set_hw_cursor; 391244197Sgonzostatic vi_set_hw_cursor_shape_t versatilefb_set_hw_cursor_shape; 392244197Sgonzostatic vi_blank_display_t versatilefb_blank_display; 393244197Sgonzostatic vi_mmap_t versatilefb_mmap; 394244197Sgonzostatic vi_ioctl_t versatilefb_ioctl; 395244197Sgonzostatic vi_clear_t versatilefb_clear; 396244197Sgonzostatic vi_fill_rect_t versatilefb_fill_rect; 397244197Sgonzostatic vi_bitblt_t versatilefb_bitblt; 398244197Sgonzostatic vi_diag_t versatilefb_diag; 399244197Sgonzostatic vi_save_cursor_palette_t versatilefb_save_cursor_palette; 400244197Sgonzostatic vi_load_cursor_palette_t versatilefb_load_cursor_palette; 401244197Sgonzostatic vi_copy_t versatilefb_copy; 402244197Sgonzostatic vi_putp_t versatilefb_putp; 403244197Sgonzostatic vi_putc_t versatilefb_putc; 404244197Sgonzostatic vi_puts_t versatilefb_puts; 405244197Sgonzostatic vi_putm_t versatilefb_putm; 406244197Sgonzo 407244197Sgonzostatic video_switch_t versatilefbvidsw = { 408244197Sgonzo .probe = versatilefb_probe, 409244197Sgonzo .init = versatilefb_init, 410244197Sgonzo .get_info = versatilefb_get_info, 411244197Sgonzo .query_mode = versatilefb_query_mode, 412244197Sgonzo .set_mode = versatilefb_set_mode, 413244197Sgonzo .save_font = versatilefb_save_font, 414244197Sgonzo .load_font = versatilefb_load_font, 415244197Sgonzo .show_font = versatilefb_show_font, 416244197Sgonzo .save_palette = versatilefb_save_palette, 417244197Sgonzo .load_palette = versatilefb_load_palette, 418244197Sgonzo .set_border = versatilefb_set_border, 419244197Sgonzo .save_state = versatilefb_save_state, 420244197Sgonzo .load_state = versatilefb_load_state, 421244197Sgonzo .set_win_org = versatilefb_set_win_org, 422244197Sgonzo .read_hw_cursor = versatilefb_read_hw_cursor, 423244197Sgonzo .set_hw_cursor = versatilefb_set_hw_cursor, 424244197Sgonzo .set_hw_cursor_shape = versatilefb_set_hw_cursor_shape, 425244197Sgonzo .blank_display = versatilefb_blank_display, 426244197Sgonzo .mmap = versatilefb_mmap, 427244197Sgonzo .ioctl = versatilefb_ioctl, 428244197Sgonzo .clear = versatilefb_clear, 429244197Sgonzo .fill_rect = versatilefb_fill_rect, 430244197Sgonzo .bitblt = versatilefb_bitblt, 431244197Sgonzo .diag = versatilefb_diag, 432244197Sgonzo .save_cursor_palette = versatilefb_save_cursor_palette, 433244197Sgonzo .load_cursor_palette = versatilefb_load_cursor_palette, 434244197Sgonzo .copy = versatilefb_copy, 435244197Sgonzo .putp = versatilefb_putp, 436244197Sgonzo .putc = versatilefb_putc, 437244197Sgonzo .puts = versatilefb_puts, 438244197Sgonzo .putm = versatilefb_putm, 439244197Sgonzo}; 440244197Sgonzo 441244197SgonzoVIDEO_DRIVER(versatilefb, versatilefbvidsw, versatilefb_configure); 442244197Sgonzo 443244755Sgonzostatic vr_init_t clcdr_init; 444244755Sgonzostatic vr_clear_t clcdr_clear; 445244755Sgonzostatic vr_draw_border_t clcdr_draw_border; 446244755Sgonzostatic vr_draw_t clcdr_draw; 447244755Sgonzostatic vr_set_cursor_t clcdr_set_cursor; 448244755Sgonzostatic vr_draw_cursor_t clcdr_draw_cursor; 449244755Sgonzostatic vr_blink_cursor_t clcdr_blink_cursor; 450244755Sgonzostatic vr_set_mouse_t clcdr_set_mouse; 451244755Sgonzostatic vr_draw_mouse_t clcdr_draw_mouse; 452244755Sgonzo 453244755Sgonzo/* 454244755Sgonzo * We use our own renderer; this is because we must emulate a hardware 455244755Sgonzo * cursor. 456244755Sgonzo */ 457244755Sgonzostatic sc_rndr_sw_t clcdrend = { 458244755Sgonzo clcdr_init, 459244755Sgonzo clcdr_clear, 460244755Sgonzo clcdr_draw_border, 461244755Sgonzo clcdr_draw, 462244755Sgonzo clcdr_set_cursor, 463244755Sgonzo clcdr_draw_cursor, 464244755Sgonzo clcdr_blink_cursor, 465244755Sgonzo clcdr_set_mouse, 466244755Sgonzo clcdr_draw_mouse 467244755Sgonzo}; 468244755Sgonzo 469244755SgonzoRENDERER(versatilefb, 0, clcdrend, gfb_set); 470244197SgonzoRENDERER_MODULE(versatilefb, gfb_set); 471244197Sgonzo 472244755Sgonzostatic void 473244755Sgonzoclcdr_init(scr_stat* scp) 474244755Sgonzo{ 475244755Sgonzo} 476244755Sgonzo 477244755Sgonzostatic void 478244755Sgonzoclcdr_clear(scr_stat* scp, int c, int attr) 479244755Sgonzo{ 480244755Sgonzo} 481244755Sgonzo 482244755Sgonzostatic void 483244755Sgonzoclcdr_draw_border(scr_stat* scp, int color) 484244755Sgonzo{ 485244755Sgonzo} 486244755Sgonzo 487244755Sgonzostatic void 488244755Sgonzoclcdr_draw(scr_stat* scp, int from, int count, int flip) 489244755Sgonzo{ 490244755Sgonzo video_adapter_t* adp = scp->sc->adp; 491244755Sgonzo int i, c, a; 492244755Sgonzo 493244755Sgonzo if (!flip) { 494244755Sgonzo /* Normal printing */ 495244755Sgonzo vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); 496244755Sgonzo } else { 497244755Sgonzo /* This is for selections and such: invert the color attribute */ 498244755Sgonzo for (i = count; i-- > 0; ++from) { 499244755Sgonzo c = sc_vtb_getc(&scp->vtb, from); 500244755Sgonzo a = sc_vtb_geta(&scp->vtb, from) >> 8; 501244755Sgonzo vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); 502244755Sgonzo } 503244755Sgonzo } 504244755Sgonzo} 505244755Sgonzo 506244755Sgonzostatic void 507244755Sgonzoclcdr_set_cursor(scr_stat* scp, int base, int height, int blink) 508244755Sgonzo{ 509244755Sgonzo} 510244755Sgonzo 511244755Sgonzostatic void 512244755Sgonzoclcdr_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) 513244755Sgonzo{ 514244755Sgonzo video_adapter_t* adp = scp->sc->adp; 515244755Sgonzo struct video_adapter_softc *sc; 516244755Sgonzo int row, col; 517244755Sgonzo uint8_t *addr; 518244755Sgonzo int i,j; 519244755Sgonzo 520244755Sgonzo sc = (struct video_adapter_softc *)adp; 521244755Sgonzo 522244755Sgonzo if (scp->curs_attr.height <= 0) 523244755Sgonzo return; 524244755Sgonzo 525244755Sgonzo if (sc->fb_addr == 0) 526244755Sgonzo return; 527244755Sgonzo 528244755Sgonzo if (off >= adp->va_info.vi_width * adp->va_info.vi_height) 529244755Sgonzo return; 530244755Sgonzo 531244755Sgonzo /* calculate the coordinates in the video buffer */ 532244755Sgonzo row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 533244755Sgonzo col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 534244755Sgonzo 535244755Sgonzo addr = (uint8_t *)sc->fb_addr 536244755Sgonzo + (row + sc->ymargin)*(sc->stride) 537244755Sgonzo + (sc->depth/8) * (col + sc->xmargin); 538244755Sgonzo 539244755Sgonzo /* our cursor consists of simply inverting the char under it */ 540244755Sgonzo for (i = 0; i < adp->va_info.vi_cheight; i++) { 541244755Sgonzo for (j = 0; j < adp->va_info.vi_cwidth; j++) { 542244755Sgonzo 543244755Sgonzo addr[2*j] ^= 0xff; 544244755Sgonzo addr[2*j + 1] ^= 0xff; 545244755Sgonzo } 546244755Sgonzo 547244755Sgonzo addr += sc->stride; 548244755Sgonzo } 549244755Sgonzo} 550244755Sgonzo 551244755Sgonzostatic void 552244755Sgonzoclcdr_blink_cursor(scr_stat* scp, int at, int flip) 553244755Sgonzo{ 554244755Sgonzo} 555244755Sgonzo 556244755Sgonzostatic void 557244755Sgonzoclcdr_set_mouse(scr_stat* scp) 558244755Sgonzo{ 559244755Sgonzo} 560244755Sgonzo 561244755Sgonzostatic void 562244755Sgonzoclcdr_draw_mouse(scr_stat* scp, int x, int y, int on) 563244755Sgonzo{ 564244755Sgonzo vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); 565244755Sgonzo 566244755Sgonzo} 567244755Sgonzo 568244197Sgonzostatic uint16_t versatilefb_static_window[ROW*COL]; 569244197Sgonzoextern u_char dflt_font_16[]; 570244197Sgonzo 571244197Sgonzo/* 572244197Sgonzo * Update videoadapter settings after changing resolution 573244197Sgonzo */ 574244197Sgonzostatic void 575244197Sgonzoversatilefb_update_margins(video_adapter_t *adp) 576244197Sgonzo{ 577244197Sgonzo struct video_adapter_softc *sc; 578244197Sgonzo video_info_t *vi; 579244197Sgonzo 580244197Sgonzo sc = (struct video_adapter_softc *)adp; 581244197Sgonzo vi = &adp->va_info; 582244197Sgonzo 583244197Sgonzo sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 584244197Sgonzo sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 585244197Sgonzo} 586244197Sgonzo 587244197Sgonzostatic int 588244197Sgonzoversatilefb_configure(int flags) 589244197Sgonzo{ 590244197Sgonzo struct video_adapter_softc *va_sc; 591244197Sgonzo 592244197Sgonzo va_sc = &va_softc; 593244197Sgonzo 594244197Sgonzo if (va_sc->initialized) 595244197Sgonzo return (0); 596244197Sgonzo 597244197Sgonzo va_sc->width = FB_WIDTH; 598244197Sgonzo va_sc->height = FB_HEIGHT; 599244197Sgonzo va_sc->depth = FB_DEPTH; 600244197Sgonzo 601244197Sgonzo versatilefb_init(0, &va_sc->va, 0); 602244197Sgonzo 603244197Sgonzo va_sc->initialized = 1; 604244197Sgonzo 605244197Sgonzo return (0); 606244197Sgonzo} 607244197Sgonzo 608244197Sgonzostatic int 609244197Sgonzoversatilefb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 610244197Sgonzo{ 611244197Sgonzo 612244197Sgonzo return (0); 613244197Sgonzo} 614244197Sgonzo 615244197Sgonzostatic int 616244197Sgonzoversatilefb_init(int unit, video_adapter_t *adp, int flags) 617244197Sgonzo{ 618244197Sgonzo struct video_adapter_softc *sc; 619244197Sgonzo video_info_t *vi; 620244197Sgonzo 621244197Sgonzo sc = (struct video_adapter_softc *)adp; 622244197Sgonzo vi = &adp->va_info; 623244197Sgonzo 624244197Sgonzo vid_init_struct(adp, "versatilefb", -1, unit); 625244197Sgonzo 626244197Sgonzo sc->font = dflt_font_16; 627244197Sgonzo vi->vi_cheight = VERSATILE_FONT_HEIGHT; 628244197Sgonzo vi->vi_cwidth = 8; 629244197Sgonzo 630244197Sgonzo vi->vi_width = sc->width/8; 631244197Sgonzo vi->vi_height = sc->height/vi->vi_cheight; 632244197Sgonzo 633244197Sgonzo /* 634244197Sgonzo * Clamp width/height to syscons maximums 635244197Sgonzo */ 636244197Sgonzo if (vi->vi_width > COL) 637244197Sgonzo vi->vi_width = COL; 638244197Sgonzo if (vi->vi_height > ROW) 639244197Sgonzo vi->vi_height = ROW; 640244197Sgonzo 641244197Sgonzo sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 642244197Sgonzo sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 643244197Sgonzo 644244197Sgonzo adp->va_window = (vm_offset_t) versatilefb_static_window; 645244197Sgonzo adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; 646244197Sgonzo 647244197Sgonzo vid_register(&sc->va); 648244197Sgonzo 649244197Sgonzo return (0); 650244197Sgonzo} 651244197Sgonzo 652244197Sgonzostatic int 653244197Sgonzoversatilefb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 654244197Sgonzo{ 655244197Sgonzo bcopy(&adp->va_info, info, sizeof(*info)); 656244197Sgonzo return (0); 657244197Sgonzo} 658244197Sgonzo 659244197Sgonzostatic int 660244197Sgonzoversatilefb_query_mode(video_adapter_t *adp, video_info_t *info) 661244197Sgonzo{ 662244197Sgonzo return (0); 663244197Sgonzo} 664244197Sgonzo 665244197Sgonzostatic int 666244197Sgonzoversatilefb_set_mode(video_adapter_t *adp, int mode) 667244197Sgonzo{ 668244197Sgonzo return (0); 669244197Sgonzo} 670244197Sgonzo 671244197Sgonzostatic int 672244197Sgonzoversatilefb_save_font(video_adapter_t *adp, int page, int size, int width, 673244197Sgonzo u_char *data, int c, int count) 674244197Sgonzo{ 675244197Sgonzo return (0); 676244197Sgonzo} 677244197Sgonzo 678244197Sgonzostatic int 679244197Sgonzoversatilefb_load_font(video_adapter_t *adp, int page, int size, int width, 680244197Sgonzo u_char *data, int c, int count) 681244197Sgonzo{ 682244197Sgonzo struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; 683244197Sgonzo 684244197Sgonzo sc->font = data; 685244197Sgonzo 686244197Sgonzo return (0); 687244197Sgonzo} 688244197Sgonzo 689244197Sgonzostatic int 690244197Sgonzoversatilefb_show_font(video_adapter_t *adp, int page) 691244197Sgonzo{ 692244197Sgonzo return (0); 693244197Sgonzo} 694244197Sgonzo 695244197Sgonzostatic int 696244197Sgonzoversatilefb_save_palette(video_adapter_t *adp, u_char *palette) 697244197Sgonzo{ 698244197Sgonzo return (0); 699244197Sgonzo} 700244197Sgonzo 701244197Sgonzostatic int 702244197Sgonzoversatilefb_load_palette(video_adapter_t *adp, u_char *palette) 703244197Sgonzo{ 704244197Sgonzo return (0); 705244197Sgonzo} 706244197Sgonzo 707244197Sgonzostatic int 708244197Sgonzoversatilefb_set_border(video_adapter_t *adp, int border) 709244197Sgonzo{ 710244197Sgonzo return (versatilefb_blank_display(adp, border)); 711244197Sgonzo} 712244197Sgonzo 713244197Sgonzostatic int 714244197Sgonzoversatilefb_save_state(video_adapter_t *adp, void *p, size_t size) 715244197Sgonzo{ 716244197Sgonzo return (0); 717244197Sgonzo} 718244197Sgonzo 719244197Sgonzostatic int 720244197Sgonzoversatilefb_load_state(video_adapter_t *adp, void *p) 721244197Sgonzo{ 722244197Sgonzo return (0); 723244197Sgonzo} 724244197Sgonzo 725244197Sgonzostatic int 726244197Sgonzoversatilefb_set_win_org(video_adapter_t *adp, off_t offset) 727244197Sgonzo{ 728244197Sgonzo return (0); 729244197Sgonzo} 730244197Sgonzo 731244197Sgonzostatic int 732244197Sgonzoversatilefb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 733244197Sgonzo{ 734244197Sgonzo *col = *row = 0; 735244197Sgonzo 736244197Sgonzo return (0); 737244197Sgonzo} 738244197Sgonzo 739244197Sgonzostatic int 740244197Sgonzoversatilefb_set_hw_cursor(video_adapter_t *adp, int col, int row) 741244197Sgonzo{ 742244755Sgonzo 743244197Sgonzo return (0); 744244197Sgonzo} 745244197Sgonzo 746244197Sgonzostatic int 747244197Sgonzoversatilefb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 748244197Sgonzo int celsize, int blink) 749244197Sgonzo{ 750244197Sgonzo return (0); 751244197Sgonzo} 752244197Sgonzo 753244197Sgonzostatic int 754244197Sgonzoversatilefb_blank_display(video_adapter_t *adp, int mode) 755244197Sgonzo{ 756244197Sgonzo 757244197Sgonzo struct video_adapter_softc *sc; 758244197Sgonzo 759244197Sgonzo sc = (struct video_adapter_softc *)adp; 760244197Sgonzo if (sc && sc->fb_addr) 761244197Sgonzo memset((void*)sc->fb_addr, 0, sc->fb_size); 762244197Sgonzo 763244197Sgonzo return (0); 764244197Sgonzo} 765244197Sgonzo 766244197Sgonzostatic int 767244197Sgonzoversatilefb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 768244197Sgonzo int prot, vm_memattr_t *memattr) 769244197Sgonzo{ 770244197Sgonzo struct video_adapter_softc *sc; 771244197Sgonzo 772244197Sgonzo sc = (struct video_adapter_softc *)adp; 773244197Sgonzo 774244197Sgonzo /* 775244197Sgonzo * This might be a legacy VGA mem request: if so, just point it at the 776244197Sgonzo * framebuffer, since it shouldn't be touched 777244197Sgonzo */ 778244197Sgonzo if (offset < sc->stride*sc->height) { 779244197Sgonzo *paddr = sc->fb_addr + offset; 780244197Sgonzo return (0); 781244197Sgonzo } 782244197Sgonzo 783244197Sgonzo return (EINVAL); 784244197Sgonzo} 785244197Sgonzo 786244197Sgonzostatic int 787244197Sgonzoversatilefb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 788244197Sgonzo{ 789244197Sgonzo 790244197Sgonzo return (0); 791244197Sgonzo} 792244197Sgonzo 793244197Sgonzostatic int 794244197Sgonzoversatilefb_clear(video_adapter_t *adp) 795244197Sgonzo{ 796244197Sgonzo 797244197Sgonzo return (versatilefb_blank_display(adp, 0)); 798244197Sgonzo} 799244197Sgonzo 800244197Sgonzostatic int 801244197Sgonzoversatilefb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 802244197Sgonzo{ 803244197Sgonzo 804244197Sgonzo return (0); 805244197Sgonzo} 806244197Sgonzo 807244197Sgonzostatic int 808244197Sgonzoversatilefb_bitblt(video_adapter_t *adp, ...) 809244197Sgonzo{ 810244197Sgonzo 811244197Sgonzo return (0); 812244197Sgonzo} 813244197Sgonzo 814244197Sgonzostatic int 815244197Sgonzoversatilefb_diag(video_adapter_t *adp, int level) 816244197Sgonzo{ 817244197Sgonzo 818244197Sgonzo return (0); 819244197Sgonzo} 820244197Sgonzo 821244197Sgonzostatic int 822244197Sgonzoversatilefb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 823244197Sgonzo{ 824244197Sgonzo 825244197Sgonzo return (0); 826244197Sgonzo} 827244197Sgonzo 828244197Sgonzostatic int 829244197Sgonzoversatilefb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 830244197Sgonzo{ 831244197Sgonzo 832244197Sgonzo return (0); 833244197Sgonzo} 834244197Sgonzo 835244197Sgonzostatic int 836244197Sgonzoversatilefb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 837244197Sgonzo{ 838244197Sgonzo 839244197Sgonzo return (0); 840244197Sgonzo} 841244197Sgonzo 842244197Sgonzostatic int 843244197Sgonzoversatilefb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 844244197Sgonzo int size, int bpp, int bit_ltor, int byte_ltor) 845244197Sgonzo{ 846244197Sgonzo 847244197Sgonzo return (0); 848244197Sgonzo} 849244197Sgonzo 850244197Sgonzostatic int 851244197Sgonzoversatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 852244197Sgonzo{ 853244197Sgonzo struct video_adapter_softc *sc; 854244197Sgonzo int row; 855244197Sgonzo int col; 856244197Sgonzo int i, j, k; 857244197Sgonzo uint8_t *addr; 858244197Sgonzo u_char *p; 859244197Sgonzo uint8_t fg, bg, color; 860244197Sgonzo uint16_t rgb; 861244197Sgonzo 862244197Sgonzo sc = (struct video_adapter_softc *)adp; 863244197Sgonzo 864244197Sgonzo if (sc->fb_addr == 0) 865244197Sgonzo return (0); 866244197Sgonzo 867244755Sgonzo if (off >= adp->va_info.vi_width * adp->va_info.vi_height) 868244755Sgonzo return (0); 869244755Sgonzo 870244197Sgonzo row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 871244197Sgonzo col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 872244197Sgonzo p = sc->font + c*VERSATILE_FONT_HEIGHT; 873244197Sgonzo addr = (uint8_t *)sc->fb_addr 874244197Sgonzo + (row + sc->ymargin)*(sc->stride) 875244197Sgonzo + (sc->depth/8) * (col + sc->xmargin); 876244197Sgonzo 877244197Sgonzo fg = a & 0xf ; 878245071Sgonzo bg = (a >> 4) & 0xf; 879244197Sgonzo 880244197Sgonzo for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) { 881244197Sgonzo for (j = 0, k = 7; j < 8; j++, k--) { 882244197Sgonzo if ((p[i] & (1 << k)) == 0) 883244197Sgonzo color = bg; 884244197Sgonzo else 885244197Sgonzo color = fg; 886244197Sgonzo 887244197Sgonzo switch (sc->depth) { 888244197Sgonzo case 16: 889244197Sgonzo rgb = (versatilefb_palette[color].r >> 3) << 11; 890244197Sgonzo rgb |= (versatilefb_palette[color].g >> 2) << 5; 891244197Sgonzo rgb |= (versatilefb_palette[color].b >> 3); 892244197Sgonzo addr[2*j] = rgb & 0xff; 893244197Sgonzo addr[2*j + 1] = (rgb >> 8) & 0xff; 894244197Sgonzo default: 895244197Sgonzo /* Not supported yet */ 896244197Sgonzo break; 897244197Sgonzo } 898244197Sgonzo } 899244197Sgonzo 900244197Sgonzo addr += (sc->stride); 901244197Sgonzo } 902244197Sgonzo 903244197Sgonzo return (0); 904244197Sgonzo} 905244197Sgonzo 906244197Sgonzostatic int 907244197Sgonzoversatilefb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 908244197Sgonzo{ 909244197Sgonzo int i; 910244197Sgonzo 911244197Sgonzo for (i = 0; i < len; i++) 912244197Sgonzo versatilefb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 913244197Sgonzo 914244197Sgonzo return (0); 915244197Sgonzo} 916244197Sgonzo 917244197Sgonzostatic int 918244197Sgonzoversatilefb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 919244197Sgonzo uint32_t pixel_mask, int size, int width) 920244197Sgonzo{ 921244197Sgonzo 922244197Sgonzo return (0); 923244197Sgonzo} 924