1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/11/sys/arm/versatile/versatile_clcd.c 356110 2019-12-27 03:00:18Z kevans $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/kernel.h> 36#include <sys/module.h> 37#include <sys/malloc.h> 38#include <sys/rman.h> 39#include <sys/fbio.h> 40#include <sys/consio.h> 41#include <sys/kdb.h> 42 43#include <machine/bus.h> 44#include <machine/cpu.h> 45#include <machine/intr.h> 46 47#include <dev/fdt/fdt_common.h> 48#include <dev/ofw/openfirm.h> 49#include <dev/ofw/ofw_bus.h> 50#include <dev/ofw/ofw_bus_subr.h> 51 52#include <dev/fb/fbreg.h> 53#include <dev/syscons/syscons.h> 54 55#include <arm/versatile/versatile_scm.h> 56 57#include <machine/bus.h> 58 59#define PL110_VENDOR_ARM926PXP 1 60 61#define CLCD_MODE_RGB888 0x0 62#define CLCD_MODE_RGB555 0x01 63#define CLCD_MODE_RBG565 0x02 64#define CLCD_MODE_RGB565 0x03 65 66#define CLCDC_TIMING0 0x00 67#define CLCDC_TIMING1 0x04 68#define CLCDC_TIMING2 0x08 69#define CLCDC_TIMING3 0x0C 70#define CLCDC_TIMING3 0x0C 71#define CLCDC_UPBASE 0x10 72#define CLCDC_LPBASE 0x14 73#ifdef PL110_VENDOR_ARM926PXP 74#define CLCDC_CONTROL 0x18 75#define CLCDC_IMSC 0x1C 76#else 77#define CLCDC_IMSC 0x18 78#define CLCDC_CONTROL 0x1C 79#endif 80#define CONTROL_WATERMARK (1 << 16) 81#define CONTROL_VCOMP_VS (0 << 12) 82#define CONTROL_VCOMP_BP (1 << 12) 83#define CONTROL_VCOMP_SAV (2 << 12) 84#define CONTROL_VCOMP_FP (3 << 12) 85#define CONTROL_PWR (1 << 11) 86#define CONTROL_BEPO (1 << 10) 87#define CONTROL_BEBO (1 << 9) 88#define CONTROL_BGR (1 << 8) 89#define CONTROL_DUAL (1 << 7) 90#define CONTROL_MONO8 (1 << 6) 91#define CONTROL_TFT (1 << 5) 92#define CONTROL_BW (1 << 4) 93#define CONTROL_BPP1 (0x00 << 1) 94#define CONTROL_BPP2 (0x01 << 1) 95#define CONTROL_BPP4 (0x02 << 1) 96#define CONTROL_BPP8 (0x03 << 1) 97#define CONTROL_BPP16 (0x04 << 1) 98#define CONTROL_BPP24 (0x05 << 1) 99#define CONTROL_EN (1 << 0) 100#define CLCDC_RIS 0x20 101#define CLCDC_MIS 0x24 102#define INTR_MBERR (1 << 4) 103#define INTR_VCOMP (1 << 3) 104#define INTR_LNB (1 << 2) 105#define INTR_FUF (1 << 1) 106#define CLCDC_ICR 0x28 107 108#ifdef DEBUG 109#define dprintf(fmt, args...) do { printf("%s(): ", __func__); \ 110 printf(fmt,##args); } while (0) 111#else 112#define dprintf(fmt, args...) 113#endif 114 115#define versatile_clcdc_read_4(sc, reg) \ 116 bus_read_4((sc)->mem_res, (reg)) 117#define versatile_clcdc_write_4(sc, reg, val) \ 118 bus_write_4((sc)->mem_res, (reg), (val)) 119 120struct versatile_clcdc_softc { 121 struct resource* mem_res; 122 123 struct mtx mtx; 124 125 int width; 126 int height; 127 int mode; 128 129 bus_dma_tag_t dma_tag; 130 bus_dmamap_t dma_map; 131 bus_addr_t fb_phys; 132 uint8_t *fb_base; 133 134}; 135 136struct video_adapter_softc { 137 /* Videoadpater part */ 138 video_adapter_t va; 139 int console; 140 141 intptr_t fb_addr; 142 unsigned int fb_size; 143 144 unsigned int height; 145 unsigned int width; 146 unsigned int depth; 147 unsigned int stride; 148 149 unsigned int xmargin; 150 unsigned int ymargin; 151 152 unsigned char *font; 153 int initialized; 154}; 155 156struct argb { 157 uint8_t a; 158 uint8_t r; 159 uint8_t g; 160 uint8_t b; 161}; 162 163static struct argb versatilefb_palette[16] = { 164 {0x00, 0x00, 0x00, 0x00}, 165 {0x00, 0x00, 0x00, 0xaa}, 166 {0x00, 0x00, 0xaa, 0x00}, 167 {0x00, 0x00, 0xaa, 0xaa}, 168 {0x00, 0xaa, 0x00, 0x00}, 169 {0x00, 0xaa, 0x00, 0xaa}, 170 {0x00, 0xaa, 0x55, 0x00}, 171 {0x00, 0xaa, 0xaa, 0xaa}, 172 {0x00, 0x55, 0x55, 0x55}, 173 {0x00, 0x55, 0x55, 0xff}, 174 {0x00, 0x55, 0xff, 0x55}, 175 {0x00, 0x55, 0xff, 0xff}, 176 {0x00, 0xff, 0x55, 0x55}, 177 {0x00, 0xff, 0x55, 0xff}, 178 {0x00, 0xff, 0xff, 0x55}, 179 {0x00, 0xff, 0xff, 0xff} 180}; 181 182/* mouse pointer from dev/syscons/scgfbrndr.c */ 183static u_char mouse_pointer[16] = { 184 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 185 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 186}; 187 188#define FB_WIDTH 640 189#define FB_HEIGHT 480 190#define FB_DEPTH 16 191 192#define VERSATILE_FONT_HEIGHT 16 193 194static struct video_adapter_softc va_softc; 195 196static int versatilefb_configure(int); 197static void versatilefb_update_margins(video_adapter_t *adp); 198 199static void 200versatile_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) 201{ 202 bus_addr_t *addr; 203 204 if (err) 205 return; 206 207 addr = (bus_addr_t*)arg; 208 *addr = segs[0].ds_addr; 209} 210 211static int 212versatile_clcdc_probe(device_t dev) 213{ 214 215 if (!ofw_bus_status_okay(dev)) 216 return (ENXIO); 217 218 if (ofw_bus_is_compatible(dev, "arm,pl110")) { 219 device_set_desc(dev, "PL110 CLCD controller"); 220 return (BUS_PROBE_DEFAULT); 221 } 222 223 return (ENXIO); 224} 225 226static int 227versatile_clcdc_attach(device_t dev) 228{ 229 struct versatile_clcdc_softc *sc = device_get_softc(dev); 230 struct video_adapter_softc *va_sc = &va_softc; 231 int err, rid; 232 uint32_t reg; 233 int clcdid; 234 int dma_size; 235 236 /* Request memory resources */ 237 rid = 0; 238 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 239 if (sc->mem_res == NULL) { 240 device_printf(dev, "could not allocate memory resources\n"); 241 return (ENXIO); 242 } 243 244 err = versatile_scm_reg_read_4(SCM_CLCD, ®); 245 if (err) { 246 device_printf(dev, "failed to read SCM register\n"); 247 goto fail; 248 } 249 clcdid = (reg >> SCM_CLCD_CLCDID_SHIFT) & SCM_CLCD_CLCDID_MASK; 250 switch (clcdid) { 251 case 31: 252 device_printf(dev, "QEMU VGA 640x480\n"); 253 sc->width = 640; 254 sc->height = 480; 255 break; 256 default: 257 device_printf(dev, "Unsupported: %d\n", clcdid); 258 goto fail; 259 } 260 261 reg &= ~SCM_CLCD_LCD_MODE_MASK; 262 reg |= CLCD_MODE_RGB565; 263 sc->mode = CLCD_MODE_RGB565; 264 versatile_scm_reg_write_4(SCM_CLCD, reg); 265 dma_size = sc->width*sc->height*2; 266 267 /* 268 * Power on LCD 269 */ 270 reg |= SCM_CLCD_PWR3V5VSWITCH | SCM_CLCD_NLCDIOON; 271 versatile_scm_reg_write_4(SCM_CLCD, reg); 272 273 /* 274 * XXX: hardcoded timing for VGA. For other modes/panels 275 * we need to keep table of timing register values 276 */ 277 /* 278 * XXX: set SYS_OSC1 279 */ 280 versatile_clcdc_write_4(sc, CLCDC_TIMING0, 0x3F1F3F9C); 281 versatile_clcdc_write_4(sc, CLCDC_TIMING1, 0x090B61DF); 282 versatile_clcdc_write_4(sc, CLCDC_TIMING2, 0x067F1800); 283 /* XXX: timing 3? */ 284 285 /* 286 * Now allocate framebuffer memory 287 */ 288 err = bus_dma_tag_create( 289 bus_get_dma_tag(dev), 290 4, 0, /* alignment, boundary */ 291 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 292 BUS_SPACE_MAXADDR, /* highaddr */ 293 NULL, NULL, /* filter, filterarg */ 294 dma_size, 1, /* maxsize, nsegments */ 295 dma_size, 0, /* maxsegsize, flags */ 296 NULL, NULL, /* lockfunc, lockarg */ 297 &sc->dma_tag); 298 299 err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_base, 300 0, &sc->dma_map); 301 if (err) { 302 device_printf(dev, "cannot allocate framebuffer\n"); 303 goto fail; 304 } 305 306 err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_base, 307 dma_size, versatile_fb_dmamap_cb, &sc->fb_phys, BUS_DMA_NOWAIT); 308 309 if (err) { 310 device_printf(dev, "cannot load DMA map\n"); 311 goto fail; 312 } 313 314 /* Make sure it's blank */ 315 memset(sc->fb_base, 0x00, dma_size); 316 317 versatile_clcdc_write_4(sc, CLCDC_UPBASE, sc->fb_phys); 318 319 err = (sc_attach_unit(device_get_unit(dev), 320 device_get_flags(dev) | SC_AUTODETECT_KBD)); 321 322 if (err) { 323 device_printf(dev, "failed to attach syscons\n"); 324 goto fail; 325 } 326 327 /* 328 * XXX: hardcoded for VGA 329 */ 330 reg = CONTROL_VCOMP_BP | CONTROL_TFT | CONTROL_BGR | CONTROL_EN; 331 reg |= CONTROL_BPP16; 332 versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); 333 DELAY(20); 334 reg |= CONTROL_PWR; 335 versatile_clcdc_write_4(sc, CLCDC_CONTROL, reg); 336 337 va_sc->fb_addr = (vm_offset_t)sc->fb_base; 338 va_sc->fb_size = dma_size; 339 va_sc->width = sc->width; 340 va_sc->height = sc->height; 341 va_sc->depth = 16; 342 va_sc->stride = sc->width * 2; 343 versatilefb_update_margins(&va_sc->va); 344 345 return (0); 346 347fail: 348 if (sc->fb_base) 349 bus_dmamem_free(sc->dma_tag, sc->fb_base, sc->dma_map); 350 if (sc->dma_tag) 351 bus_dma_tag_destroy(sc->dma_tag); 352 return (err); 353} 354 355static device_method_t versatile_clcdc_methods[] = { 356 DEVMETHOD(device_probe, versatile_clcdc_probe), 357 DEVMETHOD(device_attach, versatile_clcdc_attach), 358 359 DEVMETHOD_END 360}; 361 362static driver_t versatile_clcdc_driver = { 363 "clcdc", 364 versatile_clcdc_methods, 365 sizeof(struct versatile_clcdc_softc), 366}; 367 368static devclass_t versatile_clcdc_devclass; 369 370DRIVER_MODULE(versatile_clcdc, simplebus, versatile_clcdc_driver, versatile_clcdc_devclass, 0, 0); 371 372/* 373 * Video driver routines and glue. 374 */ 375static vi_probe_t versatilefb_probe; 376static vi_init_t versatilefb_init; 377static vi_get_info_t versatilefb_get_info; 378static vi_query_mode_t versatilefb_query_mode; 379static vi_set_mode_t versatilefb_set_mode; 380static vi_save_font_t versatilefb_save_font; 381static vi_load_font_t versatilefb_load_font; 382static vi_show_font_t versatilefb_show_font; 383static vi_save_palette_t versatilefb_save_palette; 384static vi_load_palette_t versatilefb_load_palette; 385static vi_set_border_t versatilefb_set_border; 386static vi_save_state_t versatilefb_save_state; 387static vi_load_state_t versatilefb_load_state; 388static vi_set_win_org_t versatilefb_set_win_org; 389static vi_read_hw_cursor_t versatilefb_read_hw_cursor; 390static vi_set_hw_cursor_t versatilefb_set_hw_cursor; 391static vi_set_hw_cursor_shape_t versatilefb_set_hw_cursor_shape; 392static vi_blank_display_t versatilefb_blank_display; 393static vi_mmap_t versatilefb_mmap; 394static vi_ioctl_t versatilefb_ioctl; 395static vi_clear_t versatilefb_clear; 396static vi_fill_rect_t versatilefb_fill_rect; 397static vi_bitblt_t versatilefb_bitblt; 398static vi_diag_t versatilefb_diag; 399static vi_save_cursor_palette_t versatilefb_save_cursor_palette; 400static vi_load_cursor_palette_t versatilefb_load_cursor_palette; 401static vi_copy_t versatilefb_copy; 402static vi_putp_t versatilefb_putp; 403static vi_putc_t versatilefb_putc; 404static vi_puts_t versatilefb_puts; 405static vi_putm_t versatilefb_putm; 406 407static video_switch_t versatilefbvidsw = { 408 .probe = versatilefb_probe, 409 .init = versatilefb_init, 410 .get_info = versatilefb_get_info, 411 .query_mode = versatilefb_query_mode, 412 .set_mode = versatilefb_set_mode, 413 .save_font = versatilefb_save_font, 414 .load_font = versatilefb_load_font, 415 .show_font = versatilefb_show_font, 416 .save_palette = versatilefb_save_palette, 417 .load_palette = versatilefb_load_palette, 418 .set_border = versatilefb_set_border, 419 .save_state = versatilefb_save_state, 420 .load_state = versatilefb_load_state, 421 .set_win_org = versatilefb_set_win_org, 422 .read_hw_cursor = versatilefb_read_hw_cursor, 423 .set_hw_cursor = versatilefb_set_hw_cursor, 424 .set_hw_cursor_shape = versatilefb_set_hw_cursor_shape, 425 .blank_display = versatilefb_blank_display, 426 .mmap = versatilefb_mmap, 427 .ioctl = versatilefb_ioctl, 428 .clear = versatilefb_clear, 429 .fill_rect = versatilefb_fill_rect, 430 .bitblt = versatilefb_bitblt, 431 .diag = versatilefb_diag, 432 .save_cursor_palette = versatilefb_save_cursor_palette, 433 .load_cursor_palette = versatilefb_load_cursor_palette, 434 .copy = versatilefb_copy, 435 .putp = versatilefb_putp, 436 .putc = versatilefb_putc, 437 .puts = versatilefb_puts, 438 .putm = versatilefb_putm, 439}; 440 441VIDEO_DRIVER(versatilefb, versatilefbvidsw, versatilefb_configure); 442 443static vr_init_t clcdr_init; 444static vr_clear_t clcdr_clear; 445static vr_draw_border_t clcdr_draw_border; 446static vr_draw_t clcdr_draw; 447static vr_set_cursor_t clcdr_set_cursor; 448static vr_draw_cursor_t clcdr_draw_cursor; 449static vr_blink_cursor_t clcdr_blink_cursor; 450static vr_set_mouse_t clcdr_set_mouse; 451static vr_draw_mouse_t clcdr_draw_mouse; 452 453/* 454 * We use our own renderer; this is because we must emulate a hardware 455 * cursor. 456 */ 457static sc_rndr_sw_t clcdrend = { 458 clcdr_init, 459 clcdr_clear, 460 clcdr_draw_border, 461 clcdr_draw, 462 clcdr_set_cursor, 463 clcdr_draw_cursor, 464 clcdr_blink_cursor, 465 clcdr_set_mouse, 466 clcdr_draw_mouse 467}; 468 469RENDERER(versatilefb, 0, clcdrend, gfb_set); 470RENDERER_MODULE(versatilefb, gfb_set); 471 472static void 473clcdr_init(scr_stat* scp) 474{ 475} 476 477static void 478clcdr_clear(scr_stat* scp, int c, int attr) 479{ 480} 481 482static void 483clcdr_draw_border(scr_stat* scp, int color) 484{ 485} 486 487static void 488clcdr_draw(scr_stat* scp, int from, int count, int flip) 489{ 490 video_adapter_t* adp = scp->sc->adp; 491 int i, c, a; 492 493 if (!flip) { 494 /* Normal printing */ 495 vidd_puts(adp, from, (uint16_t*)sc_vtb_pointer(&scp->vtb, from), count); 496 } else { 497 /* This is for selections and such: invert the color attribute */ 498 for (i = count; i-- > 0; ++from) { 499 c = sc_vtb_getc(&scp->vtb, from); 500 a = sc_vtb_geta(&scp->vtb, from) >> 8; 501 vidd_putc(adp, from, c, (a >> 4) | ((a & 0xf) << 4)); 502 } 503 } 504} 505 506static void 507clcdr_set_cursor(scr_stat* scp, int base, int height, int blink) 508{ 509} 510 511static void 512clcdr_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip) 513{ 514 video_adapter_t* adp = scp->sc->adp; 515 struct video_adapter_softc *sc; 516 int row, col; 517 uint8_t *addr; 518 int i,j; 519 520 sc = (struct video_adapter_softc *)adp; 521 522 if (scp->curs_attr.height <= 0) 523 return; 524 525 if (sc->fb_addr == 0) 526 return; 527 528 if (off >= adp->va_info.vi_width * adp->va_info.vi_height) 529 return; 530 531 /* calculate the coordinates in the video buffer */ 532 row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 533 col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 534 535 addr = (uint8_t *)sc->fb_addr 536 + (row + sc->ymargin)*(sc->stride) 537 + (sc->depth/8) * (col + sc->xmargin); 538 539 /* our cursor consists of simply inverting the char under it */ 540 for (i = 0; i < adp->va_info.vi_cheight; i++) { 541 for (j = 0; j < adp->va_info.vi_cwidth; j++) { 542 543 addr[2*j] ^= 0xff; 544 addr[2*j + 1] ^= 0xff; 545 } 546 547 addr += sc->stride; 548 } 549} 550 551static void 552clcdr_blink_cursor(scr_stat* scp, int at, int flip) 553{ 554} 555 556static void 557clcdr_set_mouse(scr_stat* scp) 558{ 559} 560 561static void 562clcdr_draw_mouse(scr_stat* scp, int x, int y, int on) 563{ 564 vidd_putm(scp->sc->adp, x, y, mouse_pointer, 0xffffffff, 16, 8); 565 566} 567 568static uint16_t versatilefb_static_window[ROW*COL]; 569extern u_char dflt_font_16[]; 570 571/* 572 * Update videoadapter settings after changing resolution 573 */ 574static void 575versatilefb_update_margins(video_adapter_t *adp) 576{ 577 struct video_adapter_softc *sc; 578 video_info_t *vi; 579 580 sc = (struct video_adapter_softc *)adp; 581 vi = &adp->va_info; 582 583 sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 584 sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 585} 586 587static int 588versatilefb_configure(int flags) 589{ 590 struct video_adapter_softc *va_sc; 591 592 va_sc = &va_softc; 593 594 if (va_sc->initialized) 595 return (0); 596 597 va_sc->width = FB_WIDTH; 598 va_sc->height = FB_HEIGHT; 599 va_sc->depth = FB_DEPTH; 600 601 versatilefb_init(0, &va_sc->va, 0); 602 603 va_sc->initialized = 1; 604 605 return (0); 606} 607 608static int 609versatilefb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 610{ 611 612 return (0); 613} 614 615static int 616versatilefb_init(int unit, video_adapter_t *adp, int flags) 617{ 618 struct video_adapter_softc *sc; 619 video_info_t *vi; 620 621 sc = (struct video_adapter_softc *)adp; 622 vi = &adp->va_info; 623 624 vid_init_struct(adp, "versatilefb", -1, unit); 625 626 sc->font = dflt_font_16; 627 vi->vi_cheight = VERSATILE_FONT_HEIGHT; 628 vi->vi_cwidth = 8; 629 630 vi->vi_width = sc->width/8; 631 vi->vi_height = sc->height/vi->vi_cheight; 632 633 /* 634 * Clamp width/height to syscons maximums 635 */ 636 if (vi->vi_width > COL) 637 vi->vi_width = COL; 638 if (vi->vi_height > ROW) 639 vi->vi_height = ROW; 640 641 sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2; 642 sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2; 643 644 adp->va_window = (vm_offset_t) versatilefb_static_window; 645 adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */; 646 647 vid_register(&sc->va); 648 649 return (0); 650} 651 652static int 653versatilefb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 654{ 655 bcopy(&adp->va_info, info, sizeof(*info)); 656 return (0); 657} 658 659static int 660versatilefb_query_mode(video_adapter_t *adp, video_info_t *info) 661{ 662 return (0); 663} 664 665static int 666versatilefb_set_mode(video_adapter_t *adp, int mode) 667{ 668 return (0); 669} 670 671static int 672versatilefb_save_font(video_adapter_t *adp, int page, int size, int width, 673 u_char *data, int c, int count) 674{ 675 return (0); 676} 677 678static int 679versatilefb_load_font(video_adapter_t *adp, int page, int size, int width, 680 u_char *data, int c, int count) 681{ 682 struct video_adapter_softc *sc = (struct video_adapter_softc *)adp; 683 684 sc->font = data; 685 686 return (0); 687} 688 689static int 690versatilefb_show_font(video_adapter_t *adp, int page) 691{ 692 return (0); 693} 694 695static int 696versatilefb_save_palette(video_adapter_t *adp, u_char *palette) 697{ 698 return (0); 699} 700 701static int 702versatilefb_load_palette(video_adapter_t *adp, u_char *palette) 703{ 704 return (0); 705} 706 707static int 708versatilefb_set_border(video_adapter_t *adp, int border) 709{ 710 return (versatilefb_blank_display(adp, border)); 711} 712 713static int 714versatilefb_save_state(video_adapter_t *adp, void *p, size_t size) 715{ 716 return (0); 717} 718 719static int 720versatilefb_load_state(video_adapter_t *adp, void *p) 721{ 722 return (0); 723} 724 725static int 726versatilefb_set_win_org(video_adapter_t *adp, off_t offset) 727{ 728 return (0); 729} 730 731static int 732versatilefb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 733{ 734 *col = *row = 0; 735 736 return (0); 737} 738 739static int 740versatilefb_set_hw_cursor(video_adapter_t *adp, int col, int row) 741{ 742 743 return (0); 744} 745 746static int 747versatilefb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 748 int celsize, int blink) 749{ 750 return (0); 751} 752 753static int 754versatilefb_blank_display(video_adapter_t *adp, int mode) 755{ 756 757 struct video_adapter_softc *sc; 758 759 sc = (struct video_adapter_softc *)adp; 760 if (sc && sc->fb_addr) 761 memset((void*)sc->fb_addr, 0, sc->fb_size); 762 763 return (0); 764} 765 766static int 767versatilefb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 768 int prot, vm_memattr_t *memattr) 769{ 770 struct video_adapter_softc *sc; 771 772 sc = (struct video_adapter_softc *)adp; 773 774 /* 775 * This might be a legacy VGA mem request: if so, just point it at the 776 * framebuffer, since it shouldn't be touched 777 */ 778 if (offset < sc->stride*sc->height) { 779 *paddr = sc->fb_addr + offset; 780 return (0); 781 } 782 783 return (EINVAL); 784} 785 786static int 787versatilefb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 788{ 789 790 return (0); 791} 792 793static int 794versatilefb_clear(video_adapter_t *adp) 795{ 796 797 return (versatilefb_blank_display(adp, 0)); 798} 799 800static int 801versatilefb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 802{ 803 804 return (0); 805} 806 807static int 808versatilefb_bitblt(video_adapter_t *adp, ...) 809{ 810 811 return (0); 812} 813 814static int 815versatilefb_diag(video_adapter_t *adp, int level) 816{ 817 818 return (0); 819} 820 821static int 822versatilefb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 823{ 824 825 return (0); 826} 827 828static int 829versatilefb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 830{ 831 832 return (0); 833} 834 835static int 836versatilefb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 837{ 838 839 return (0); 840} 841 842static int 843versatilefb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 844 int size, int bpp, int bit_ltor, int byte_ltor) 845{ 846 847 return (0); 848} 849 850static int 851versatilefb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 852{ 853 struct video_adapter_softc *sc; 854 int row; 855 int col; 856 int i, j, k; 857 uint8_t *addr; 858 u_char *p; 859 uint8_t fg, bg, color; 860 uint16_t rgb; 861 862 sc = (struct video_adapter_softc *)adp; 863 864 if (sc->fb_addr == 0) 865 return (0); 866 867 if (off >= adp->va_info.vi_width * adp->va_info.vi_height) 868 return (0); 869 870 row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 871 col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; 872 p = sc->font + c*VERSATILE_FONT_HEIGHT; 873 addr = (uint8_t *)sc->fb_addr 874 + (row + sc->ymargin)*(sc->stride) 875 + (sc->depth/8) * (col + sc->xmargin); 876 877 fg = a & 0xf ; 878 bg = (a >> 4) & 0xf; 879 880 for (i = 0; i < VERSATILE_FONT_HEIGHT; i++) { 881 for (j = 0, k = 7; j < 8; j++, k--) { 882 if ((p[i] & (1 << k)) == 0) 883 color = bg; 884 else 885 color = fg; 886 887 switch (sc->depth) { 888 case 16: 889 rgb = (versatilefb_palette[color].r >> 3) << 11; 890 rgb |= (versatilefb_palette[color].g >> 2) << 5; 891 rgb |= (versatilefb_palette[color].b >> 3); 892 addr[2*j] = rgb & 0xff; 893 addr[2*j + 1] = (rgb >> 8) & 0xff; 894 default: 895 /* Not supported yet */ 896 break; 897 } 898 } 899 900 addr += (sc->stride); 901 } 902 903 return (0); 904} 905 906static int 907versatilefb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 908{ 909 int i; 910 911 for (i = 0; i < len; i++) 912 versatilefb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 913 914 return (0); 915} 916 917static int 918versatilefb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 919 uint32_t pixel_mask, int size, int width) 920{ 921 922 return (0); 923} 924