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