wii_fb.c revision 239478
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: head/sys/powerpc/wii/wii_fb.c 239478 2012-08-21 06:31:26Z adrian $"); 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 return 0; 519 520 sc->sc_console = 1; 521 522 sc->sc_fb_addr = WIIFB_FB_ADDR; 523 sc->sc_fb_size = WIIFB_FB_LEN; 524 525 sc->sc_reg_addr = WIIFB_REG_ADDR; 526 sc->sc_reg_size = WIIFB_REG_LEN; 527 528 wiifb_reset_video(sc); 529 wiifb_dispcfg_read(sc, &dc); 530 sc->sc_format = dc.dc_format; 531 sc->sc_component = wiifb_component_enabled(sc); 532 progressive = dc.dc_noninterlaced; 533 switch (sc->sc_format) { 534 case WIIFB_FORMAT_MPAL: 535 case WIIFB_FORMAT_DEBUG: 536 case WIIFB_FORMAT_NTSC: 537 sc->sc_mode = progressive ? 538 &wiifb_modes[WIIFB_MODE_NTSC_480p] : 539 &wiifb_modes[WIIFB_MODE_NTSC_480i]; 540 break; 541 case WIIFB_FORMAT_PAL: 542 sc->sc_mode = progressive ? 543 &wiifb_modes[WIIFB_MODE_PAL_480p] : 544 &wiifb_modes[WIIFB_MODE_PAL_480i]; 545 break; 546 } 547 sc->sc_height = sc->sc_mode->fd_height; 548 sc->sc_width = sc->sc_mode->fd_width; 549 /* Usually we multiply by 4, but I think this looks better. */ 550 sc->sc_stride = sc->sc_width * 2; 551 552 wiifb_init(0, &sc->sc_va, 0); 553 554 sc->sc_initialized = 1; 555 556 return (0); 557} 558 559static int 560wiifb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 561{ 562 563 return (0); 564} 565 566static int 567wiifb_init(int unit, video_adapter_t *adp, int flags) 568{ 569 struct wiifb_softc *sc; 570 video_info_t *vi; 571 572 sc = (struct wiifb_softc *)adp; 573 vi = &adp->va_info; 574 575 vid_init_struct(adp, "wiifb", -1, unit); 576 577 sc->sc_font = dflt_font_8; 578 vi->vi_cheight = WIIFB_FONT_HEIGHT; 579 vi->vi_width = sc->sc_width/8; 580 vi->vi_height = sc->sc_height/vi->vi_cheight; 581 vi->vi_cwidth = 8; 582 583 /* 584 * Clamp width/height to syscons maximums 585 */ 586 if (vi->vi_width > COL) 587 vi->vi_width = COL; 588 if (vi->vi_height > ROW) 589 vi->vi_height = ROW; 590 591 sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; 592 sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; 593 594 adp->va_window = (vm_offset_t) wiifb_static_window; 595 /* XXX no colour support */ 596 adp->va_flags |= V_ADP_FONT | /*V_ADP_COLOR |*/ V_ADP_MODECHANGE; 597 598 vid_register(&sc->sc_va); 599 600 wiifb_configure_tv_mode(sc); 601 wiifb_setup_framebuffer(sc); 602 wiifb_enable_interrupts(sc); 603 wiifb_clear(adp); 604 605 return (0); 606} 607 608static int 609wiifb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 610{ 611 612 bcopy(&adp->va_info, info, sizeof(*info)); 613 return (0); 614} 615 616static int 617wiifb_query_mode(video_adapter_t *adp, video_info_t *info) 618{ 619 620 return (0); 621} 622 623static int 624wiifb_set_mode(video_adapter_t *adp, int mode) 625{ 626 627 return (0); 628} 629 630static int 631wiifb_save_font(video_adapter_t *adp, int page, int size, int width, 632 u_char *data, int c, int count) 633{ 634 635 return (0); 636} 637 638static int 639wiifb_load_font(video_adapter_t *adp, int page, int size, int width, 640 u_char *data, int c, int count) 641{ 642 struct wiifb_softc *sc = (struct wiifb_softc *)adp; 643 644 sc->sc_font = data; 645 646 return (0); 647} 648 649static int 650wiifb_show_font(video_adapter_t *adp, int page) 651{ 652 653 return (0); 654} 655 656static int 657wiifb_save_palette(video_adapter_t *adp, u_char *palette) 658{ 659 660 return (0); 661} 662 663static int 664wiifb_load_palette(video_adapter_t *adp, u_char *palette) 665{ 666 667 return (0); 668} 669 670static int 671wiifb_set_border(video_adapter_t *adp, int border) 672{ 673 674 return (wiifb_blank_display(adp, border)); 675} 676 677static int 678wiifb_save_state(video_adapter_t *adp, void *p, size_t size) 679{ 680 681 return (0); 682} 683 684static int 685wiifb_load_state(video_adapter_t *adp, void *p) 686{ 687 688 return (0); 689} 690 691static int 692wiifb_set_win_org(video_adapter_t *adp, off_t offset) 693{ 694 695 return (0); 696} 697 698static int 699wiifb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 700{ 701 702 *col = *row = 0; 703 704 return (0); 705} 706 707static int 708wiifb_set_hw_cursor(video_adapter_t *adp, int col, int row) 709{ 710 711 return (0); 712} 713 714static int 715wiifb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 716 int celsize, int blink) 717{ 718 719 return (0); 720} 721 722static int 723wiifb_blank_display(video_adapter_t *adp, int mode) 724{ 725 struct wiifb_softc *sc = (struct wiifb_softc *)adp; 726 uint32_t *p; 727 728 for (p = (uint32_t *)sc->sc_fb_addr; 729 p < (uint32_t *)(sc->sc_fb_addr + sc->sc_fb_size); 730 p++) 731 *p = wiifb_cmap[wiifb_background(SC_NORM_ATTR)]; 732 733 return (0); 734} 735 736static int 737wiifb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 738 int prot, vm_memattr_t *memattr) 739{ 740 struct wiifb_softc *sc; 741 742 sc = (struct wiifb_softc *)adp; 743 744 /* 745 * This might be a legacy VGA mem request: if so, just point it at the 746 * framebuffer, since it shouldn't be touched 747 */ 748 if (offset < sc->sc_stride*sc->sc_height) { 749 *paddr = sc->sc_fb_addr + offset; 750 return (0); 751 } 752 753 return (EINVAL); 754} 755 756static int 757wiifb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 758{ 759 760 return (0); 761} 762 763static int 764wiifb_clear(video_adapter_t *adp) 765{ 766 767 return (wiifb_blank_display(adp, 0)); 768} 769 770static int 771wiifb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 772{ 773 774 return (0); 775} 776 777static int 778wiifb_bitblt(video_adapter_t *adp, ...) 779{ 780 781 return (0); 782} 783 784static int 785wiifb_diag(video_adapter_t *adp, int level) 786{ 787 788 return (0); 789} 790 791static int 792wiifb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 793{ 794 795 return (0); 796} 797 798static int 799wiifb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 800{ 801 802 return (0); 803} 804 805static int 806wiifb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 807{ 808 809 return (0); 810} 811 812static int 813wiifb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 814 int size, int bpp, int bit_ltor, int byte_ltor) 815{ 816 817 return (0); 818} 819 820static int 821wiifb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 822{ 823 struct wiifb_softc *sc; 824 int row; 825 int col; 826 int i, j, k; 827 uint32_t *addr; 828 u_char *p; 829 uint32_t fg, bg; 830 unsigned long pixel[2]; 831 832 sc = (struct wiifb_softc *)adp; 833 row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 834 col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth / 2; 835 p = sc->sc_font + c*WIIFB_FONT_HEIGHT; 836 addr = (uint32_t *)sc->sc_fb_addr 837 + (row + sc->sc_ymargin)*(sc->sc_stride/4) 838 + col + sc->sc_xmargin; 839 840 bg = wiifb_cmap[wiifb_background(a)]; 841 fg = wiifb_cmap[wiifb_foreground(a)]; 842 843 for (i = 0; i < WIIFB_FONT_HEIGHT; i++) { 844 for (j = 0, k = 7; j < 4; j++, k--) { 845 if ((p[i] & (1 << k)) == 0) 846 pixel[0] = bg; 847 else 848 pixel[0] = fg; 849 k--; 850 if ((p[i] & (1 << k)) == 0) 851 pixel[1] = bg; 852 else 853 pixel[1] = fg; 854 855 addr[j] = (pixel[0] & 0xffff00ff) | 856 (pixel[1] & 0x0000ff00); 857 } 858 addr += (sc->sc_stride/4); 859 } 860 861 return (0); 862} 863 864static int 865wiifb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 866{ 867 int i; 868 869 for (i = 0; i < len; i++) 870 wiifb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 871 872 return (0); 873} 874 875static int 876wiifb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 877 uint32_t pixel_mask, int size, int width) 878{ 879 880 return (0); 881} 882