wii_fb.c revision 256281
1/*- 2 * Copyright (C) 2012 Margarida Gouveia 3 * Copyright (c) 2003 Peter Grehan 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer, 11 * without modification, immediately at the beginning of the file. 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 ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/powerpc/wii/wii_fb.c 249965 2013-04-27 01:57:45Z rpaulo $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/module.h> 33#include <sys/bus.h> 34#include <sys/kernel.h> 35#include <sys/sysctl.h> 36#include <sys/limits.h> 37#include <sys/conf.h> 38#include <sys/cons.h> 39#include <sys/proc.h> 40#include <sys/fcntl.h> 41#include <sys/malloc.h> 42#include <sys/fbio.h> 43#include <sys/consio.h> 44 45#include <vm/vm.h> 46#include <vm/pmap.h> 47 48#include <machine/bus.h> 49#include <machine/sc_machdep.h> 50#include <machine/platform.h> 51#include <machine/pmap.h> 52 53#include <sys/rman.h> 54 55#include <dev/fb/fbreg.h> 56#include <dev/syscons/syscons.h> 57 58#include <powerpc/wii/wii_fbreg.h> 59#include <powerpc/wii/wii_fbvar.h> 60 61/* 62 * Driver for the Nintendo Wii's framebuffer. Based on Linux's gcnfb.c. 63 */ 64 65/* 66 * Syscons glue. 67 */ 68static int wiifb_scprobe(device_t); 69static int wiifb_scattach(device_t); 70 71static device_method_t wiifb_sc_methods[] = { 72 DEVMETHOD(device_probe, wiifb_scprobe), 73 DEVMETHOD(device_attach, wiifb_scattach), 74 75 DEVMETHOD_END 76}; 77 78static driver_t wiifb_sc_driver = { 79 "wiifb", 80 wiifb_sc_methods, 81 sizeof(sc_softc_t), 82}; 83 84static devclass_t sc_devclass; 85 86DRIVER_MODULE(sc, wiibus, wiifb_sc_driver, sc_devclass, 0, 0); 87 88static int 89wiifb_scprobe(device_t dev) 90{ 91 int error; 92 93 device_set_desc(dev, "Nintendo Wii frambuffer"); 94 95 error = sc_probe_unit(device_get_unit(dev), 96 device_get_flags(dev) | SC_AUTODETECT_KBD); 97 if (error != 0) 98 return (error); 99 100 /* This is a fake device, so make sure we added it ourselves */ 101 return (BUS_PROBE_NOWILDCARD); 102} 103 104static int 105wiifb_scattach(device_t dev) 106{ 107 108 return (sc_attach_unit(device_get_unit(dev), 109 device_get_flags(dev) | SC_AUTODETECT_KBD)); 110} 111 112/* 113 * Video driver routines and glue. 114 */ 115static void wiifb_reset_video(struct wiifb_softc *); 116static void wiifb_enable_interrupts(struct wiifb_softc *); 117static void wiifb_configure_tv_mode(struct wiifb_softc *); 118static void wiifb_setup_framebuffer(struct wiifb_softc *); 119static int wiifb_configure(int); 120static vi_probe_t wiifb_probe; 121static vi_init_t wiifb_init; 122static vi_get_info_t wiifb_get_info; 123static vi_query_mode_t wiifb_query_mode; 124static vi_set_mode_t wiifb_set_mode; 125static vi_save_font_t wiifb_save_font; 126static vi_load_font_t wiifb_load_font; 127static vi_show_font_t wiifb_show_font; 128static vi_save_palette_t wiifb_save_palette; 129static vi_load_palette_t wiifb_load_palette; 130static vi_set_border_t wiifb_set_border; 131static vi_save_state_t wiifb_save_state; 132static vi_load_state_t wiifb_load_state; 133static vi_set_win_org_t wiifb_set_win_org; 134static vi_read_hw_cursor_t wiifb_read_hw_cursor; 135static vi_set_hw_cursor_t wiifb_set_hw_cursor; 136static vi_set_hw_cursor_shape_t wiifb_set_hw_cursor_shape; 137static vi_blank_display_t wiifb_blank_display; 138static vi_mmap_t wiifb_mmap; 139static vi_ioctl_t wiifb_ioctl; 140static vi_clear_t wiifb_clear; 141static vi_fill_rect_t wiifb_fill_rect; 142static vi_bitblt_t wiifb_bitblt; 143static vi_diag_t wiifb_diag; 144static vi_save_cursor_palette_t wiifb_save_cursor_palette; 145static vi_load_cursor_palette_t wiifb_load_cursor_palette; 146static vi_copy_t wiifb_copy; 147static vi_putp_t wiifb_putp; 148static vi_putc_t wiifb_putc; 149static vi_puts_t wiifb_puts; 150static vi_putm_t wiifb_putm; 151 152static video_switch_t wiifbvidsw = { 153 .probe = wiifb_probe, 154 .init = wiifb_init, 155 .get_info = wiifb_get_info, 156 .query_mode = wiifb_query_mode, 157 .set_mode = wiifb_set_mode, 158 .save_font = wiifb_save_font, 159 .load_font = wiifb_load_font, 160 .show_font = wiifb_show_font, 161 .save_palette = wiifb_save_palette, 162 .load_palette = wiifb_load_palette, 163 .set_border = wiifb_set_border, 164 .save_state = wiifb_save_state, 165 .load_state = wiifb_load_state, 166 .set_win_org = wiifb_set_win_org, 167 .read_hw_cursor = wiifb_read_hw_cursor, 168 .set_hw_cursor = wiifb_set_hw_cursor, 169 .set_hw_cursor_shape = wiifb_set_hw_cursor_shape, 170 .blank_display = wiifb_blank_display, 171 .mmap = wiifb_mmap, 172 .ioctl = wiifb_ioctl, 173 .clear = wiifb_clear, 174 .fill_rect = wiifb_fill_rect, 175 .bitblt = wiifb_bitblt, 176 .diag = wiifb_diag, 177 .save_cursor_palette = wiifb_save_cursor_palette, 178 .load_cursor_palette = wiifb_load_cursor_palette, 179 .copy = wiifb_copy, 180 .putp = wiifb_putp, 181 .putc = wiifb_putc, 182 .puts = wiifb_puts, 183 .putm = wiifb_putm, 184}; 185 186VIDEO_DRIVER(wiifb, wiifbvidsw, wiifb_configure); 187 188extern sc_rndr_sw_t txtrndrsw; 189RENDERER(wiifb, 0, txtrndrsw, gfb_set); 190RENDERER_MODULE(wiifb, gfb_set); 191 192static struct wiifb_softc wiifb_softc; 193static uint16_t wiifb_static_window[ROW*COL]; 194extern u_char dflt_font_8[]; 195 196/* 197 * Map the syscons colors to YUY2 (Y'UV422). 198 * Some colours are an approximation. 199 * 200 * The Wii has a 16 bit pixel, so each 32 bit DWORD encodes 201 * two pixels. The upper 16 bits is for pixel 0 (left hand pixel 202 * in a pair), the lower 16 bits is for pixel 1. 203 * 204 * For now, we're going to ignore that entirely and just use the 205 * lower 16 bits for each pixel. We'll take the upper value into 206 * account later. 207 */ 208static uint32_t wiifb_cmap[16] = { 209 0x00800080, /* Black */ 210 0x1dff1d6b, /* Blue */ 211 0x4b554b4a, /* Green */ 212 0x80808080, /* Cyan */ 213 0x4c544cff, /* Red */ 214 0x3aaa34b5, /* Magenta */ 215 0x7140718a, /* Brown */ 216 0xff80ff80, /* White */ 217 0x80808080, /* Gray */ 218 0xc399c36a, /* Bright Blue */ 219 0xd076d074, /* Bright Green */ 220 0x80808080, /* Bright Cyan */ 221 0x4c544cff, /* Bright Red */ 222 0x3aaa34b5, /* Bright Magenta */ 223 0xe100e194, /* Bright Yellow */ 224 0xff80ff80 /* Bright White */ 225}; 226 227static struct wiifb_mode_desc wiifb_modes[] = { 228 [WIIFB_MODE_NTSC_480i] = { 229 "NTSC 480i", 230 640, 480, 231 525, 232 WIIFB_MODE_FLAG_INTERLACED, 233 }, 234 [WIIFB_MODE_NTSC_480p] = { 235 "NTSC 480p", 236 640, 480, 237 525, 238 WIIFB_MODE_FLAG_PROGRESSIVE, 239 }, 240 [WIIFB_MODE_PAL_576i] = { 241 "PAL 576i (50Hz)", 242 640, 574, 243 625, 244 WIIFB_MODE_FLAG_INTERLACED, 245 }, 246 [WIIFB_MODE_PAL_480i] = { 247 "PAL 480i (60Hz)", 248 640, 480, 249 525, 250 WIIFB_MODE_FLAG_INTERLACED, 251 }, 252 [WIIFB_MODE_PAL_480p] = { 253 "PAL 480p", 254 640, 480, 255 525, 256 WIIFB_MODE_FLAG_PROGRESSIVE, 257 }, 258}; 259 260static const uint32_t wiifb_filter_coeft[] = { 261 0x1ae771f0, 0x0db4a574, 0x00c1188e, 0xc4c0cbe2, 0xfcecdecf, 262 0x13130f08, 0x00080c0f 263}; 264 265static __inline int 266wiifb_background(uint8_t attr) 267{ 268 269 return (attr >> 4); 270} 271 272static __inline int 273wiifb_foreground(uint8_t attr) 274{ 275 276 return (attr & 0x0f); 277} 278 279static void 280wiifb_reset_video(struct wiifb_softc *sc) 281{ 282 struct wiifb_dispcfg dc; 283 284 wiifb_dispcfg_read(sc, &dc); 285 dc.dc_reset = 1; 286 wiifb_dispcfg_write(sc, &dc); 287 dc.dc_reset = 0; 288 wiifb_dispcfg_write(sc, &dc); 289} 290 291static void 292wiifb_enable_interrupts(struct wiifb_softc *sc) 293{ 294 struct wiifb_dispint di; 295 296#ifdef notyet 297 /* 298 * Display Interrupt 0 299 */ 300 di.di_htiming = 1; 301 di.di_vtiming = 1; 302 di.di_enable = 1; 303 di.di_irq = 1; 304 wiifb_dispint_write(sc, 0, &di); 305 306 /* 307 * Display Interrupt 1 308 */ 309 di.di_htiming = sc->sc_format == WIIFB_FORMAT_PAL ? 433 : 430; 310 di.di_vtiming = sc->sc_mode->fd_lines; 311 di.di_enable = 1; 312 di.di_irq = 1; 313 if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 314 di.di_vtiming /= 2; 315 wiifb_dispint_write(sc, 1, &di); 316 317 /* 318 * Display Interrupts 2 and 3 are not used. 319 */ 320 memset(&di, 0, sizeof(di)); 321 wiifb_dispint_write(sc, 2, &di); 322 wiifb_dispint_write(sc, 3, &di); 323#else 324 memset(&di, 0, sizeof(di)); 325 wiifb_dispint_write(sc, 0, &di); 326 wiifb_dispint_write(sc, 1, &di); 327 wiifb_dispint_write(sc, 2, &di); 328 wiifb_dispint_write(sc, 3, &di); 329#endif 330} 331 332/* 333 * Reference gcnfb.c for an in depth explanation. 334 * XXX only works with NTSC. 335 */ 336static void 337wiifb_configure_tv_mode(struct wiifb_softc *sc) 338{ 339 struct wiifb_vtiming vt; 340 struct wiifb_hscaling hs; 341 struct wiifb_htiming0 ht0; 342 struct wiifb_htiming1 ht1; 343 struct wiifb_vtimingodd vto; 344 struct wiifb_vtimingeven vte; 345 struct wiifb_burstblankodd bbo; 346 struct wiifb_burstblankeven bbe; 347 struct wiifb_picconf pc; 348 struct wiifb_mode_desc *mode = sc->sc_mode; 349 unsigned int height = mode->fd_height; 350 unsigned int width = mode->fd_width; 351 unsigned int eqpulse, interlacebias, shift; 352 const unsigned int maxwidth = 714; 353 unsigned int hblanking = maxwidth - width; 354 unsigned int hmargin = hblanking / 2; 355 unsigned int A = 20 + hmargin, C = 60 + hblanking - hmargin; 356 unsigned int maxheight = 484; 357 unsigned int P = 2 * (20 - 10 + 1); 358 unsigned int Q = 1; 359 unsigned int vblanking = maxheight - height; 360 unsigned int vmargin = vblanking / 2; 361 unsigned int prb = vmargin; 362 unsigned int psb = vblanking - vmargin; 363 int i; 364 365 /* 366 * Vertical timing. 367 */ 368 if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) { 369 vt.vt_actvideo = height / 2; 370 interlacebias = 1; 371 shift = 0; 372 } else { 373 vt.vt_actvideo = height; 374 interlacebias = 0; 375 shift = 1; 376 } 377 /* Lines of equalization */ 378 if (mode->fd_lines == 625) 379 eqpulse = 2 * 2.5; 380 else 381 eqpulse = 2 * 3; 382 vt.vt_eqpulse = eqpulse << shift; 383 wiifb_vtiming_write(sc, &vt); 384 385 /* 386 * Horizontal timings. 387 */ 388 ht0.ht0_hlinew = 858 / 2; 389 ht1.ht1_hsyncw = 64; 390 ht0.ht0_hcolourstart = 71; 391 ht0.ht0_hcolourend = 71 + 34; 392 ht1.ht1_hblankstart = (858 / 2) - A; 393 ht1.ht1_hblankend = 64 + C; 394 wiifb_htiming0_write(sc, &ht0); 395 wiifb_htiming1_write(sc, &ht1); 396 397 /* 398 * Vertical timing odd/even. 399 */ 400 if (vmargin & 1) { 401 vto.vto_preb = (P + interlacebias + prb) << shift; 402 vto.vto_postb = (Q - interlacebias + psb) << shift; 403 vte.vte_preb = (P + prb) << shift; 404 vte.vte_postb = (Q - psb) << shift; 405 } else { 406 /* XXX if this isn't 0, it doesn't work? */ 407 prb = 0; 408 psb = 0; 409 vte.vte_preb = (P + interlacebias + prb) << shift; 410 vte.vte_postb = (Q - interlacebias + psb) << shift; 411 vto.vto_preb = (P + prb) << shift; 412 vto.vto_postb = (Q - psb) << shift; 413 } 414 wiifb_vtimingodd_write(sc, &vto); 415 wiifb_vtimingeven_write(sc, &vte); 416 417 /* 418 * Burst blanking odd/even interval. 419 */ 420 bbo.bbo_bs1 = 2 * (18 - 7 + 1); 421 bbe.bbe_bs2 = bbo.bbo_bs3 = bbe.bbe_bs4 = bbo.bbo_bs1; 422 bbo.bbo_be1 = 2 * (525 - 7 + 1); 423 bbe.bbe_be2 = bbo.bbo_be3 = bbe.bbe_be4 = bbo.bbo_be1; 424 wiifb_burstblankodd_write(sc, &bbo); 425 wiifb_burstblankeven_write(sc, &bbe); 426 427 /* 428 * Picture configuration. 429 */ 430 pc.pc_strides = (mode->fd_width * 2) / 32; 431 if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 432 pc.pc_strides *= 2; 433 pc.pc_reads = (mode->fd_width * 2) / 32; 434 wiifb_picconf_write(sc, &pc); 435 436 /* 437 * Horizontal scaling disabled. 438 */ 439 hs.hs_enable = 0; 440 hs.hs_step = 256; 441 wiifb_hscaling_write(sc, &hs); 442 443 /* 444 * Filter coeficient table. 445 */ 446 for (i = 0; i < 7; i++) 447 wiifb_filtcoeft_write(sc, i, wiifb_filter_coeft[i]); 448 449 /* 450 * Anti alias. 451 */ 452 wiifb_antialias_write(sc, 0x00ff0000); 453 454 /* 455 * Video clock. 456 */ 457 wiifb_videoclk_write(sc, 458 mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED ? 0 : 1); 459 460 /* 461 * Disable horizontal scaling width. 462 */ 463 wiifb_hscalingw_write(sc, mode->fd_width); 464 465 /* 466 * DEBUG mode borders. Not used. 467 */ 468 wiifb_hborderend_write(sc, 0); 469 wiifb_hborderstart_write(sc, 0); 470 471 /* 472 * XXX unknown registers. 473 */ 474 wiifb_unknown1_write(sc, 0x00ff); 475 wiifb_unknown2_write(sc, 0x00ff00ff); 476 wiifb_unknown3_write(sc, 0x00ff00ff); 477} 478 479static void 480wiifb_setup_framebuffer(struct wiifb_softc *sc) 481{ 482 intptr_t addr = sc->sc_fb_addr; 483 struct wiifb_topfieldbasel tfbl; 484 struct wiifb_bottomfieldbasel bfbl; 485 struct wiifb_topfieldbaser tfbr; 486 struct wiifb_bottomfieldbaser bfbr; 487 488 tfbl.tfbl_fbaddr = addr >> 5; 489 tfbl.tfbl_xoffset = (addr / 2) & 0xf; 490 tfbl.tfbl_pageoffbit = 1; 491 wiifb_topfieldbasel_write(sc, &tfbl); 492 493 if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 494 addr += sc->sc_mode->fd_width * 2; 495 bfbl.bfbl_fbaddr = addr >> 5; 496 bfbl.bfbl_xoffset = (addr / 2) & 0xf; 497 bfbl.bfbl_pageoffbit = 1; 498 wiifb_bottomfieldbasel_write(sc, &bfbl); 499 500 /* 501 * Only used used for 3D. 502 */ 503 memset(&tfbr, 0, sizeof(tfbr)); 504 memset(&bfbr, 0, sizeof(bfbr)); 505 wiifb_topfieldbaser_write(sc, &tfbr); 506 wiifb_bottomfieldbaser_write(sc, &bfbr); 507} 508 509static int 510wiifb_configure(int flags) 511{ 512 struct wiifb_softc *sc; 513 struct wiifb_dispcfg dc; 514 int progressive; 515 516 sc = &wiifb_softc; 517 if (sc->sc_initialized) { 518 /* XXX We should instead use bus_space */ 519 sc->sc_fb_addr = (intptr_t)pmap_mapdev(WIIFB_FB_ADDR, WIIFB_FB_LEN); 520 sc->sc_reg_addr = (intptr_t)pmap_mapdev(WIIFB_REG_ADDR, WIIFB_REG_LEN); 521 return 0; 522 } 523 524 sc->sc_console = 1; 525 526 sc->sc_fb_addr = WIIFB_FB_ADDR; 527 sc->sc_fb_size = WIIFB_FB_LEN; 528 529 sc->sc_reg_addr = WIIFB_REG_ADDR; 530 sc->sc_reg_size = WIIFB_REG_LEN; 531 532 wiifb_reset_video(sc); 533 wiifb_dispcfg_read(sc, &dc); 534 sc->sc_format = dc.dc_format; 535 sc->sc_component = wiifb_component_enabled(sc); 536 progressive = dc.dc_noninterlaced; 537 switch (sc->sc_format) { 538 case WIIFB_FORMAT_MPAL: 539 case WIIFB_FORMAT_DEBUG: 540 case WIIFB_FORMAT_NTSC: 541 sc->sc_mode = progressive ? 542 &wiifb_modes[WIIFB_MODE_NTSC_480p] : 543 &wiifb_modes[WIIFB_MODE_NTSC_480i]; 544 break; 545 case WIIFB_FORMAT_PAL: 546 sc->sc_mode = progressive ? 547 &wiifb_modes[WIIFB_MODE_PAL_480p] : 548 &wiifb_modes[WIIFB_MODE_PAL_480i]; 549 break; 550 } 551 sc->sc_height = sc->sc_mode->fd_height; 552 sc->sc_width = sc->sc_mode->fd_width; 553 /* Usually we multiply by 4, but I think this looks better. */ 554 sc->sc_stride = sc->sc_width * 2; 555 556 wiifb_init(0, &sc->sc_va, 0); 557 558 sc->sc_initialized = 1; 559 560 return (0); 561} 562 563static int 564wiifb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 565{ 566 567 return (0); 568} 569 570static int 571wiifb_init(int unit, video_adapter_t *adp, int flags) 572{ 573 struct wiifb_softc *sc; 574 video_info_t *vi; 575 576 sc = (struct wiifb_softc *)adp; 577 vi = &adp->va_info; 578 579 vid_init_struct(adp, "wiifb", -1, unit); 580 581 sc->sc_font = dflt_font_8; 582 vi->vi_cheight = WIIFB_FONT_HEIGHT; 583 vi->vi_width = sc->sc_width/8; 584 vi->vi_height = sc->sc_height/vi->vi_cheight; 585 vi->vi_cwidth = 8; 586 587 /* 588 * Clamp width/height to syscons maximums 589 */ 590 if (vi->vi_width > COL) 591 vi->vi_width = COL; 592 if (vi->vi_height > ROW) 593 vi->vi_height = ROW; 594 595 sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; 596 sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; 597 598 adp->va_window = (vm_offset_t) wiifb_static_window; 599 /* XXX no colour support */ 600 adp->va_flags |= V_ADP_FONT | /*V_ADP_COLOR |*/ V_ADP_MODECHANGE; 601 602 vid_register(&sc->sc_va); 603 604 wiifb_configure_tv_mode(sc); 605 wiifb_setup_framebuffer(sc); 606 wiifb_enable_interrupts(sc); 607 wiifb_clear(adp); 608 609 return (0); 610} 611 612static int 613wiifb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 614{ 615 616 bcopy(&adp->va_info, info, sizeof(*info)); 617 return (0); 618} 619 620static int 621wiifb_query_mode(video_adapter_t *adp, video_info_t *info) 622{ 623 624 return (0); 625} 626 627static int 628wiifb_set_mode(video_adapter_t *adp, int mode) 629{ 630 631 return (0); 632} 633 634static int 635wiifb_save_font(video_adapter_t *adp, int page, int size, int width, 636 u_char *data, int c, int count) 637{ 638 639 return (0); 640} 641 642static int 643wiifb_load_font(video_adapter_t *adp, int page, int size, int width, 644 u_char *data, int c, int count) 645{ 646 struct wiifb_softc *sc = (struct wiifb_softc *)adp; 647 648 sc->sc_font = data; 649 650 return (0); 651} 652 653static int 654wiifb_show_font(video_adapter_t *adp, int page) 655{ 656 657 return (0); 658} 659 660static int 661wiifb_save_palette(video_adapter_t *adp, u_char *palette) 662{ 663 664 return (0); 665} 666 667static int 668wiifb_load_palette(video_adapter_t *adp, u_char *palette) 669{ 670 671 return (0); 672} 673 674static int 675wiifb_set_border(video_adapter_t *adp, int border) 676{ 677 678 return (wiifb_blank_display(adp, border)); 679} 680 681static int 682wiifb_save_state(video_adapter_t *adp, void *p, size_t size) 683{ 684 685 return (0); 686} 687 688static int 689wiifb_load_state(video_adapter_t *adp, void *p) 690{ 691 692 return (0); 693} 694 695static int 696wiifb_set_win_org(video_adapter_t *adp, off_t offset) 697{ 698 699 return (0); 700} 701 702static int 703wiifb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 704{ 705 706 *col = *row = 0; 707 708 return (0); 709} 710 711static int 712wiifb_set_hw_cursor(video_adapter_t *adp, int col, int row) 713{ 714 715 return (0); 716} 717 718static int 719wiifb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 720 int celsize, int blink) 721{ 722 723 return (0); 724} 725 726static int 727wiifb_blank_display(video_adapter_t *adp, int mode) 728{ 729 struct wiifb_softc *sc = (struct wiifb_softc *)adp; 730 uint32_t *p; 731 732 for (p = (uint32_t *)sc->sc_fb_addr; 733 p < (uint32_t *)(sc->sc_fb_addr + sc->sc_fb_size); 734 p++) 735 *p = wiifb_cmap[wiifb_background(SC_NORM_ATTR)]; 736 737 return (0); 738} 739 740static int 741wiifb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 742 int prot, vm_memattr_t *memattr) 743{ 744 struct wiifb_softc *sc; 745 746 sc = (struct wiifb_softc *)adp; 747 748 /* 749 * This might be a legacy VGA mem request: if so, just point it at the 750 * framebuffer, since it shouldn't be touched 751 */ 752 if (offset < sc->sc_stride*sc->sc_height) { 753 *paddr = sc->sc_fb_addr + offset; 754 return (0); 755 } 756 757 return (EINVAL); 758} 759 760static int 761wiifb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 762{ 763 764 return (0); 765} 766 767static int 768wiifb_clear(video_adapter_t *adp) 769{ 770 771 return (wiifb_blank_display(adp, 0)); 772} 773 774static int 775wiifb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 776{ 777 778 return (0); 779} 780 781static int 782wiifb_bitblt(video_adapter_t *adp, ...) 783{ 784 785 return (0); 786} 787 788static int 789wiifb_diag(video_adapter_t *adp, int level) 790{ 791 792 return (0); 793} 794 795static int 796wiifb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 797{ 798 799 return (0); 800} 801 802static int 803wiifb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 804{ 805 806 return (0); 807} 808 809static int 810wiifb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 811{ 812 813 return (0); 814} 815 816static int 817wiifb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 818 int size, int bpp, int bit_ltor, int byte_ltor) 819{ 820 821 return (0); 822} 823 824static int 825wiifb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 826{ 827 struct wiifb_softc *sc; 828 int row; 829 int col; 830 int i, j, k; 831 uint32_t *addr; 832 u_char *p; 833 uint32_t fg, bg; 834 unsigned long pixel[2]; 835 836 sc = (struct wiifb_softc *)adp; 837 row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 838 col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth / 2; 839 p = sc->sc_font + c*WIIFB_FONT_HEIGHT; 840 addr = (uint32_t *)sc->sc_fb_addr 841 + (row + sc->sc_ymargin)*(sc->sc_stride/4) 842 + col + sc->sc_xmargin; 843 844 bg = wiifb_cmap[wiifb_background(a)]; 845 fg = wiifb_cmap[wiifb_foreground(a)]; 846 847 for (i = 0; i < WIIFB_FONT_HEIGHT; i++) { 848 for (j = 0, k = 7; j < 4; j++, k--) { 849 if ((p[i] & (1 << k)) == 0) 850 pixel[0] = bg; 851 else 852 pixel[0] = fg; 853 k--; 854 if ((p[i] & (1 << k)) == 0) 855 pixel[1] = bg; 856 else 857 pixel[1] = fg; 858 859 addr[j] = (pixel[0] & 0xffff00ff) | 860 (pixel[1] & 0x0000ff00); 861 } 862 addr += (sc->sc_stride/4); 863 } 864 865 return (0); 866} 867 868static int 869wiifb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 870{ 871 int i; 872 873 for (i = 0; i < len; i++) 874 wiifb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 875 876 return (0); 877} 878 879static int 880wiifb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 881 uint32_t pixel_mask, int size, int width) 882{ 883 884 return (0); 885} 886