1239478Sadrian/*- 2239478Sadrian * Copyright (C) 2012 Margarida Gouveia 3239478Sadrian * Copyright (c) 2003 Peter Grehan 4239478Sadrian * All rights reserved. 5239478Sadrian * 6239478Sadrian * Redistribution and use in source and binary forms, with or without 7239478Sadrian * modification, are permitted provided that the following conditions 8239478Sadrian * are met: 9239478Sadrian * 1. Redistributions of source code must retain the above copyright 10239478Sadrian * notice, this list of conditions and the following disclaimer, 11239478Sadrian * without modification, immediately at the beginning of the file. 12239478Sadrian * 2. Redistributions in binary form must reproduce the above copyright 13239478Sadrian * notice, this list of conditions and the following disclaimer in the 14239478Sadrian * documentation and/or other materials provided with the distribution. 15239478Sadrian * 16239478Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17239478Sadrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18239478Sadrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19239478Sadrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20239478Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21239478Sadrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22239478Sadrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23239478Sadrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24239478Sadrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25239478Sadrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26239478Sadrian */ 27239478Sadrian#include <sys/cdefs.h> 28239478Sadrian__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/wii/wii_fb.c 249965 2013-04-27 01:57:45Z rpaulo $"); 29239478Sadrian 30239478Sadrian#include <sys/param.h> 31239478Sadrian#include <sys/systm.h> 32239478Sadrian#include <sys/module.h> 33239478Sadrian#include <sys/bus.h> 34239478Sadrian#include <sys/kernel.h> 35239478Sadrian#include <sys/sysctl.h> 36239478Sadrian#include <sys/limits.h> 37239478Sadrian#include <sys/conf.h> 38239478Sadrian#include <sys/cons.h> 39239478Sadrian#include <sys/proc.h> 40239478Sadrian#include <sys/fcntl.h> 41239478Sadrian#include <sys/malloc.h> 42239478Sadrian#include <sys/fbio.h> 43239478Sadrian#include <sys/consio.h> 44239478Sadrian 45239478Sadrian#include <vm/vm.h> 46239478Sadrian#include <vm/pmap.h> 47239478Sadrian 48239478Sadrian#include <machine/bus.h> 49239478Sadrian#include <machine/sc_machdep.h> 50239478Sadrian#include <machine/platform.h> 51239478Sadrian#include <machine/pmap.h> 52239478Sadrian 53239478Sadrian#include <sys/rman.h> 54239478Sadrian 55239478Sadrian#include <dev/fb/fbreg.h> 56239478Sadrian#include <dev/syscons/syscons.h> 57239478Sadrian 58239478Sadrian#include <powerpc/wii/wii_fbreg.h> 59239478Sadrian#include <powerpc/wii/wii_fbvar.h> 60239478Sadrian 61239478Sadrian/* 62239478Sadrian * Driver for the Nintendo Wii's framebuffer. Based on Linux's gcnfb.c. 63239478Sadrian */ 64239478Sadrian 65239478Sadrian/* 66239478Sadrian * Syscons glue. 67239478Sadrian */ 68239478Sadrianstatic int wiifb_scprobe(device_t); 69239478Sadrianstatic int wiifb_scattach(device_t); 70239478Sadrian 71239478Sadrianstatic device_method_t wiifb_sc_methods[] = { 72239478Sadrian DEVMETHOD(device_probe, wiifb_scprobe), 73239478Sadrian DEVMETHOD(device_attach, wiifb_scattach), 74239478Sadrian 75239478Sadrian DEVMETHOD_END 76239478Sadrian}; 77239478Sadrian 78239478Sadrianstatic driver_t wiifb_sc_driver = { 79239478Sadrian "wiifb", 80239478Sadrian wiifb_sc_methods, 81239478Sadrian sizeof(sc_softc_t), 82239478Sadrian}; 83239478Sadrian 84239478Sadrianstatic devclass_t sc_devclass; 85239478Sadrian 86239478SadrianDRIVER_MODULE(sc, wiibus, wiifb_sc_driver, sc_devclass, 0, 0); 87239478Sadrian 88239478Sadrianstatic int 89239478Sadrianwiifb_scprobe(device_t dev) 90239478Sadrian{ 91239478Sadrian int error; 92239478Sadrian 93239478Sadrian device_set_desc(dev, "Nintendo Wii frambuffer"); 94239478Sadrian 95239478Sadrian error = sc_probe_unit(device_get_unit(dev), 96239478Sadrian device_get_flags(dev) | SC_AUTODETECT_KBD); 97239478Sadrian if (error != 0) 98239478Sadrian return (error); 99239478Sadrian 100239478Sadrian /* This is a fake device, so make sure we added it ourselves */ 101239478Sadrian return (BUS_PROBE_NOWILDCARD); 102239478Sadrian} 103239478Sadrian 104239478Sadrianstatic int 105239478Sadrianwiifb_scattach(device_t dev) 106239478Sadrian{ 107239478Sadrian 108239478Sadrian return (sc_attach_unit(device_get_unit(dev), 109239478Sadrian device_get_flags(dev) | SC_AUTODETECT_KBD)); 110239478Sadrian} 111239478Sadrian 112239478Sadrian/* 113239478Sadrian * Video driver routines and glue. 114239478Sadrian */ 115239478Sadrianstatic void wiifb_reset_video(struct wiifb_softc *); 116239478Sadrianstatic void wiifb_enable_interrupts(struct wiifb_softc *); 117239478Sadrianstatic void wiifb_configure_tv_mode(struct wiifb_softc *); 118239478Sadrianstatic void wiifb_setup_framebuffer(struct wiifb_softc *); 119239478Sadrianstatic int wiifb_configure(int); 120239478Sadrianstatic vi_probe_t wiifb_probe; 121239478Sadrianstatic vi_init_t wiifb_init; 122239478Sadrianstatic vi_get_info_t wiifb_get_info; 123239478Sadrianstatic vi_query_mode_t wiifb_query_mode; 124239478Sadrianstatic vi_set_mode_t wiifb_set_mode; 125239478Sadrianstatic vi_save_font_t wiifb_save_font; 126239478Sadrianstatic vi_load_font_t wiifb_load_font; 127239478Sadrianstatic vi_show_font_t wiifb_show_font; 128239478Sadrianstatic vi_save_palette_t wiifb_save_palette; 129239478Sadrianstatic vi_load_palette_t wiifb_load_palette; 130239478Sadrianstatic vi_set_border_t wiifb_set_border; 131239478Sadrianstatic vi_save_state_t wiifb_save_state; 132239478Sadrianstatic vi_load_state_t wiifb_load_state; 133239478Sadrianstatic vi_set_win_org_t wiifb_set_win_org; 134239478Sadrianstatic vi_read_hw_cursor_t wiifb_read_hw_cursor; 135239478Sadrianstatic vi_set_hw_cursor_t wiifb_set_hw_cursor; 136239478Sadrianstatic vi_set_hw_cursor_shape_t wiifb_set_hw_cursor_shape; 137239478Sadrianstatic vi_blank_display_t wiifb_blank_display; 138239478Sadrianstatic vi_mmap_t wiifb_mmap; 139239478Sadrianstatic vi_ioctl_t wiifb_ioctl; 140239478Sadrianstatic vi_clear_t wiifb_clear; 141239478Sadrianstatic vi_fill_rect_t wiifb_fill_rect; 142239478Sadrianstatic vi_bitblt_t wiifb_bitblt; 143239478Sadrianstatic vi_diag_t wiifb_diag; 144239478Sadrianstatic vi_save_cursor_palette_t wiifb_save_cursor_palette; 145239478Sadrianstatic vi_load_cursor_palette_t wiifb_load_cursor_palette; 146239478Sadrianstatic vi_copy_t wiifb_copy; 147239478Sadrianstatic vi_putp_t wiifb_putp; 148239478Sadrianstatic vi_putc_t wiifb_putc; 149239478Sadrianstatic vi_puts_t wiifb_puts; 150239478Sadrianstatic vi_putm_t wiifb_putm; 151239478Sadrian 152239478Sadrianstatic video_switch_t wiifbvidsw = { 153239478Sadrian .probe = wiifb_probe, 154239478Sadrian .init = wiifb_init, 155239478Sadrian .get_info = wiifb_get_info, 156239478Sadrian .query_mode = wiifb_query_mode, 157239478Sadrian .set_mode = wiifb_set_mode, 158239478Sadrian .save_font = wiifb_save_font, 159239478Sadrian .load_font = wiifb_load_font, 160239478Sadrian .show_font = wiifb_show_font, 161239478Sadrian .save_palette = wiifb_save_palette, 162239478Sadrian .load_palette = wiifb_load_palette, 163239478Sadrian .set_border = wiifb_set_border, 164239478Sadrian .save_state = wiifb_save_state, 165239478Sadrian .load_state = wiifb_load_state, 166239478Sadrian .set_win_org = wiifb_set_win_org, 167239478Sadrian .read_hw_cursor = wiifb_read_hw_cursor, 168239478Sadrian .set_hw_cursor = wiifb_set_hw_cursor, 169239478Sadrian .set_hw_cursor_shape = wiifb_set_hw_cursor_shape, 170239478Sadrian .blank_display = wiifb_blank_display, 171239478Sadrian .mmap = wiifb_mmap, 172239478Sadrian .ioctl = wiifb_ioctl, 173239478Sadrian .clear = wiifb_clear, 174239478Sadrian .fill_rect = wiifb_fill_rect, 175239478Sadrian .bitblt = wiifb_bitblt, 176239478Sadrian .diag = wiifb_diag, 177239478Sadrian .save_cursor_palette = wiifb_save_cursor_palette, 178239478Sadrian .load_cursor_palette = wiifb_load_cursor_palette, 179239478Sadrian .copy = wiifb_copy, 180239478Sadrian .putp = wiifb_putp, 181239478Sadrian .putc = wiifb_putc, 182239478Sadrian .puts = wiifb_puts, 183239478Sadrian .putm = wiifb_putm, 184239478Sadrian}; 185239478Sadrian 186239478SadrianVIDEO_DRIVER(wiifb, wiifbvidsw, wiifb_configure); 187239478Sadrian 188239478Sadrianextern sc_rndr_sw_t txtrndrsw; 189239478SadrianRENDERER(wiifb, 0, txtrndrsw, gfb_set); 190239478SadrianRENDERER_MODULE(wiifb, gfb_set); 191239478Sadrian 192239478Sadrianstatic struct wiifb_softc wiifb_softc; 193239478Sadrianstatic uint16_t wiifb_static_window[ROW*COL]; 194239478Sadrianextern u_char dflt_font_8[]; 195239478Sadrian 196239478Sadrian/* 197239478Sadrian * Map the syscons colors to YUY2 (Y'UV422). 198239478Sadrian * Some colours are an approximation. 199239478Sadrian * 200239478Sadrian * The Wii has a 16 bit pixel, so each 32 bit DWORD encodes 201239478Sadrian * two pixels. The upper 16 bits is for pixel 0 (left hand pixel 202239478Sadrian * in a pair), the lower 16 bits is for pixel 1. 203239478Sadrian * 204239478Sadrian * For now, we're going to ignore that entirely and just use the 205239478Sadrian * lower 16 bits for each pixel. We'll take the upper value into 206239478Sadrian * account later. 207239478Sadrian */ 208239478Sadrianstatic uint32_t wiifb_cmap[16] = { 209239478Sadrian 0x00800080, /* Black */ 210239478Sadrian 0x1dff1d6b, /* Blue */ 211239478Sadrian 0x4b554b4a, /* Green */ 212239478Sadrian 0x80808080, /* Cyan */ 213239478Sadrian 0x4c544cff, /* Red */ 214239478Sadrian 0x3aaa34b5, /* Magenta */ 215239478Sadrian 0x7140718a, /* Brown */ 216239478Sadrian 0xff80ff80, /* White */ 217239478Sadrian 0x80808080, /* Gray */ 218239478Sadrian 0xc399c36a, /* Bright Blue */ 219239478Sadrian 0xd076d074, /* Bright Green */ 220239478Sadrian 0x80808080, /* Bright Cyan */ 221239478Sadrian 0x4c544cff, /* Bright Red */ 222239478Sadrian 0x3aaa34b5, /* Bright Magenta */ 223239478Sadrian 0xe100e194, /* Bright Yellow */ 224239478Sadrian 0xff80ff80 /* Bright White */ 225239478Sadrian}; 226239478Sadrian 227239478Sadrianstatic struct wiifb_mode_desc wiifb_modes[] = { 228239478Sadrian [WIIFB_MODE_NTSC_480i] = { 229239478Sadrian "NTSC 480i", 230239478Sadrian 640, 480, 231239478Sadrian 525, 232239478Sadrian WIIFB_MODE_FLAG_INTERLACED, 233239478Sadrian }, 234239478Sadrian [WIIFB_MODE_NTSC_480p] = { 235239478Sadrian "NTSC 480p", 236239478Sadrian 640, 480, 237239478Sadrian 525, 238239478Sadrian WIIFB_MODE_FLAG_PROGRESSIVE, 239239478Sadrian }, 240239478Sadrian [WIIFB_MODE_PAL_576i] = { 241239478Sadrian "PAL 576i (50Hz)", 242239478Sadrian 640, 574, 243239478Sadrian 625, 244239478Sadrian WIIFB_MODE_FLAG_INTERLACED, 245239478Sadrian }, 246239478Sadrian [WIIFB_MODE_PAL_480i] = { 247239478Sadrian "PAL 480i (60Hz)", 248239478Sadrian 640, 480, 249239478Sadrian 525, 250239478Sadrian WIIFB_MODE_FLAG_INTERLACED, 251239478Sadrian }, 252239478Sadrian [WIIFB_MODE_PAL_480p] = { 253239478Sadrian "PAL 480p", 254239478Sadrian 640, 480, 255239478Sadrian 525, 256239478Sadrian WIIFB_MODE_FLAG_PROGRESSIVE, 257239478Sadrian }, 258239478Sadrian}; 259239478Sadrian 260239478Sadrianstatic const uint32_t wiifb_filter_coeft[] = { 261239478Sadrian 0x1ae771f0, 0x0db4a574, 0x00c1188e, 0xc4c0cbe2, 0xfcecdecf, 262239478Sadrian 0x13130f08, 0x00080c0f 263239478Sadrian}; 264239478Sadrian 265239478Sadrianstatic __inline int 266239478Sadrianwiifb_background(uint8_t attr) 267239478Sadrian{ 268239478Sadrian 269239478Sadrian return (attr >> 4); 270239478Sadrian} 271239478Sadrian 272239478Sadrianstatic __inline int 273239478Sadrianwiifb_foreground(uint8_t attr) 274239478Sadrian{ 275239478Sadrian 276239478Sadrian return (attr & 0x0f); 277239478Sadrian} 278239478Sadrian 279239478Sadrianstatic void 280239478Sadrianwiifb_reset_video(struct wiifb_softc *sc) 281239478Sadrian{ 282239478Sadrian struct wiifb_dispcfg dc; 283239478Sadrian 284239478Sadrian wiifb_dispcfg_read(sc, &dc); 285239478Sadrian dc.dc_reset = 1; 286239478Sadrian wiifb_dispcfg_write(sc, &dc); 287239478Sadrian dc.dc_reset = 0; 288239478Sadrian wiifb_dispcfg_write(sc, &dc); 289239478Sadrian} 290239478Sadrian 291239478Sadrianstatic void 292239478Sadrianwiifb_enable_interrupts(struct wiifb_softc *sc) 293239478Sadrian{ 294239478Sadrian struct wiifb_dispint di; 295239478Sadrian 296239478Sadrian#ifdef notyet 297239478Sadrian /* 298239478Sadrian * Display Interrupt 0 299239478Sadrian */ 300239478Sadrian di.di_htiming = 1; 301239478Sadrian di.di_vtiming = 1; 302239478Sadrian di.di_enable = 1; 303239478Sadrian di.di_irq = 1; 304239478Sadrian wiifb_dispint_write(sc, 0, &di); 305239478Sadrian 306239478Sadrian /* 307239478Sadrian * Display Interrupt 1 308239478Sadrian */ 309239478Sadrian di.di_htiming = sc->sc_format == WIIFB_FORMAT_PAL ? 433 : 430; 310239478Sadrian di.di_vtiming = sc->sc_mode->fd_lines; 311239478Sadrian di.di_enable = 1; 312239478Sadrian di.di_irq = 1; 313239478Sadrian if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 314239478Sadrian di.di_vtiming /= 2; 315239478Sadrian wiifb_dispint_write(sc, 1, &di); 316239478Sadrian 317239478Sadrian /* 318239478Sadrian * Display Interrupts 2 and 3 are not used. 319239478Sadrian */ 320239478Sadrian memset(&di, 0, sizeof(di)); 321239478Sadrian wiifb_dispint_write(sc, 2, &di); 322239478Sadrian wiifb_dispint_write(sc, 3, &di); 323239478Sadrian#else 324239478Sadrian memset(&di, 0, sizeof(di)); 325239478Sadrian wiifb_dispint_write(sc, 0, &di); 326239478Sadrian wiifb_dispint_write(sc, 1, &di); 327239478Sadrian wiifb_dispint_write(sc, 2, &di); 328239478Sadrian wiifb_dispint_write(sc, 3, &di); 329239478Sadrian#endif 330239478Sadrian} 331239478Sadrian 332239478Sadrian/* 333239478Sadrian * Reference gcnfb.c for an in depth explanation. 334239478Sadrian * XXX only works with NTSC. 335239478Sadrian */ 336239478Sadrianstatic void 337239478Sadrianwiifb_configure_tv_mode(struct wiifb_softc *sc) 338239478Sadrian{ 339239478Sadrian struct wiifb_vtiming vt; 340239478Sadrian struct wiifb_hscaling hs; 341239478Sadrian struct wiifb_htiming0 ht0; 342239478Sadrian struct wiifb_htiming1 ht1; 343239478Sadrian struct wiifb_vtimingodd vto; 344239478Sadrian struct wiifb_vtimingeven vte; 345239478Sadrian struct wiifb_burstblankodd bbo; 346239478Sadrian struct wiifb_burstblankeven bbe; 347239478Sadrian struct wiifb_picconf pc; 348239478Sadrian struct wiifb_mode_desc *mode = sc->sc_mode; 349239478Sadrian unsigned int height = mode->fd_height; 350239478Sadrian unsigned int width = mode->fd_width; 351239478Sadrian unsigned int eqpulse, interlacebias, shift; 352239478Sadrian const unsigned int maxwidth = 714; 353239478Sadrian unsigned int hblanking = maxwidth - width; 354239478Sadrian unsigned int hmargin = hblanking / 2; 355239478Sadrian unsigned int A = 20 + hmargin, C = 60 + hblanking - hmargin; 356239478Sadrian unsigned int maxheight = 484; 357239478Sadrian unsigned int P = 2 * (20 - 10 + 1); 358239478Sadrian unsigned int Q = 1; 359239478Sadrian unsigned int vblanking = maxheight - height; 360239478Sadrian unsigned int vmargin = vblanking / 2; 361239478Sadrian unsigned int prb = vmargin; 362239478Sadrian unsigned int psb = vblanking - vmargin; 363239478Sadrian int i; 364239478Sadrian 365239478Sadrian /* 366239478Sadrian * Vertical timing. 367239478Sadrian */ 368239478Sadrian if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) { 369239478Sadrian vt.vt_actvideo = height / 2; 370239478Sadrian interlacebias = 1; 371239478Sadrian shift = 0; 372239478Sadrian } else { 373239478Sadrian vt.vt_actvideo = height; 374239478Sadrian interlacebias = 0; 375239478Sadrian shift = 1; 376239478Sadrian } 377239478Sadrian /* Lines of equalization */ 378239478Sadrian if (mode->fd_lines == 625) 379239478Sadrian eqpulse = 2 * 2.5; 380239478Sadrian else 381239478Sadrian eqpulse = 2 * 3; 382239478Sadrian vt.vt_eqpulse = eqpulse << shift; 383239478Sadrian wiifb_vtiming_write(sc, &vt); 384239478Sadrian 385239478Sadrian /* 386239478Sadrian * Horizontal timings. 387239478Sadrian */ 388239478Sadrian ht0.ht0_hlinew = 858 / 2; 389239478Sadrian ht1.ht1_hsyncw = 64; 390239478Sadrian ht0.ht0_hcolourstart = 71; 391239478Sadrian ht0.ht0_hcolourend = 71 + 34; 392239478Sadrian ht1.ht1_hblankstart = (858 / 2) - A; 393239478Sadrian ht1.ht1_hblankend = 64 + C; 394239478Sadrian wiifb_htiming0_write(sc, &ht0); 395239478Sadrian wiifb_htiming1_write(sc, &ht1); 396239478Sadrian 397239478Sadrian /* 398239478Sadrian * Vertical timing odd/even. 399239478Sadrian */ 400239478Sadrian if (vmargin & 1) { 401239478Sadrian vto.vto_preb = (P + interlacebias + prb) << shift; 402239478Sadrian vto.vto_postb = (Q - interlacebias + psb) << shift; 403239478Sadrian vte.vte_preb = (P + prb) << shift; 404239478Sadrian vte.vte_postb = (Q - psb) << shift; 405239478Sadrian } else { 406239478Sadrian /* XXX if this isn't 0, it doesn't work? */ 407239478Sadrian prb = 0; 408239478Sadrian psb = 0; 409239478Sadrian vte.vte_preb = (P + interlacebias + prb) << shift; 410239478Sadrian vte.vte_postb = (Q - interlacebias + psb) << shift; 411239478Sadrian vto.vto_preb = (P + prb) << shift; 412239478Sadrian vto.vto_postb = (Q - psb) << shift; 413239478Sadrian } 414239478Sadrian wiifb_vtimingodd_write(sc, &vto); 415239478Sadrian wiifb_vtimingeven_write(sc, &vte); 416239478Sadrian 417239478Sadrian /* 418239478Sadrian * Burst blanking odd/even interval. 419239478Sadrian */ 420239478Sadrian bbo.bbo_bs1 = 2 * (18 - 7 + 1); 421239478Sadrian bbe.bbe_bs2 = bbo.bbo_bs3 = bbe.bbe_bs4 = bbo.bbo_bs1; 422239478Sadrian bbo.bbo_be1 = 2 * (525 - 7 + 1); 423239478Sadrian bbe.bbe_be2 = bbo.bbo_be3 = bbe.bbe_be4 = bbo.bbo_be1; 424239478Sadrian wiifb_burstblankodd_write(sc, &bbo); 425239478Sadrian wiifb_burstblankeven_write(sc, &bbe); 426239478Sadrian 427239478Sadrian /* 428239478Sadrian * Picture configuration. 429239478Sadrian */ 430239478Sadrian pc.pc_strides = (mode->fd_width * 2) / 32; 431239478Sadrian if (mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 432239478Sadrian pc.pc_strides *= 2; 433239478Sadrian pc.pc_reads = (mode->fd_width * 2) / 32; 434239478Sadrian wiifb_picconf_write(sc, &pc); 435239478Sadrian 436239478Sadrian /* 437239478Sadrian * Horizontal scaling disabled. 438239478Sadrian */ 439239478Sadrian hs.hs_enable = 0; 440239478Sadrian hs.hs_step = 256; 441239478Sadrian wiifb_hscaling_write(sc, &hs); 442239478Sadrian 443239478Sadrian /* 444239478Sadrian * Filter coeficient table. 445239478Sadrian */ 446239478Sadrian for (i = 0; i < 7; i++) 447239478Sadrian wiifb_filtcoeft_write(sc, i, wiifb_filter_coeft[i]); 448239478Sadrian 449239478Sadrian /* 450239478Sadrian * Anti alias. 451239478Sadrian */ 452239478Sadrian wiifb_antialias_write(sc, 0x00ff0000); 453239478Sadrian 454239478Sadrian /* 455239478Sadrian * Video clock. 456239478Sadrian */ 457239478Sadrian wiifb_videoclk_write(sc, 458239478Sadrian mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED ? 0 : 1); 459239478Sadrian 460239478Sadrian /* 461239478Sadrian * Disable horizontal scaling width. 462239478Sadrian */ 463239478Sadrian wiifb_hscalingw_write(sc, mode->fd_width); 464239478Sadrian 465239478Sadrian /* 466239478Sadrian * DEBUG mode borders. Not used. 467239478Sadrian */ 468239478Sadrian wiifb_hborderend_write(sc, 0); 469239478Sadrian wiifb_hborderstart_write(sc, 0); 470239478Sadrian 471239478Sadrian /* 472239478Sadrian * XXX unknown registers. 473239478Sadrian */ 474239478Sadrian wiifb_unknown1_write(sc, 0x00ff); 475239478Sadrian wiifb_unknown2_write(sc, 0x00ff00ff); 476239478Sadrian wiifb_unknown3_write(sc, 0x00ff00ff); 477239478Sadrian} 478239478Sadrian 479239478Sadrianstatic void 480239478Sadrianwiifb_setup_framebuffer(struct wiifb_softc *sc) 481239478Sadrian{ 482239478Sadrian intptr_t addr = sc->sc_fb_addr; 483239478Sadrian struct wiifb_topfieldbasel tfbl; 484239478Sadrian struct wiifb_bottomfieldbasel bfbl; 485239478Sadrian struct wiifb_topfieldbaser tfbr; 486239478Sadrian struct wiifb_bottomfieldbaser bfbr; 487239478Sadrian 488239478Sadrian tfbl.tfbl_fbaddr = addr >> 5; 489239478Sadrian tfbl.tfbl_xoffset = (addr / 2) & 0xf; 490239478Sadrian tfbl.tfbl_pageoffbit = 1; 491239478Sadrian wiifb_topfieldbasel_write(sc, &tfbl); 492239478Sadrian 493239478Sadrian if (sc->sc_mode->fd_flags & WIIFB_MODE_FLAG_INTERLACED) 494239478Sadrian addr += sc->sc_mode->fd_width * 2; 495239478Sadrian bfbl.bfbl_fbaddr = addr >> 5; 496239478Sadrian bfbl.bfbl_xoffset = (addr / 2) & 0xf; 497239478Sadrian bfbl.bfbl_pageoffbit = 1; 498239478Sadrian wiifb_bottomfieldbasel_write(sc, &bfbl); 499239478Sadrian 500239478Sadrian /* 501239478Sadrian * Only used used for 3D. 502239478Sadrian */ 503239478Sadrian memset(&tfbr, 0, sizeof(tfbr)); 504239478Sadrian memset(&bfbr, 0, sizeof(bfbr)); 505239478Sadrian wiifb_topfieldbaser_write(sc, &tfbr); 506239478Sadrian wiifb_bottomfieldbaser_write(sc, &bfbr); 507239478Sadrian} 508239478Sadrian 509239478Sadrianstatic int 510239478Sadrianwiifb_configure(int flags) 511239478Sadrian{ 512239478Sadrian struct wiifb_softc *sc; 513239478Sadrian struct wiifb_dispcfg dc; 514239478Sadrian int progressive; 515239478Sadrian 516239478Sadrian sc = &wiifb_softc; 517249965Srpaulo if (sc->sc_initialized) { 518249965Srpaulo /* XXX We should instead use bus_space */ 519249965Srpaulo sc->sc_fb_addr = (intptr_t)pmap_mapdev(WIIFB_FB_ADDR, WIIFB_FB_LEN); 520249965Srpaulo sc->sc_reg_addr = (intptr_t)pmap_mapdev(WIIFB_REG_ADDR, WIIFB_REG_LEN); 521239478Sadrian return 0; 522249965Srpaulo } 523239478Sadrian 524239478Sadrian sc->sc_console = 1; 525239478Sadrian 526239478Sadrian sc->sc_fb_addr = WIIFB_FB_ADDR; 527239478Sadrian sc->sc_fb_size = WIIFB_FB_LEN; 528239478Sadrian 529239478Sadrian sc->sc_reg_addr = WIIFB_REG_ADDR; 530239478Sadrian sc->sc_reg_size = WIIFB_REG_LEN; 531239478Sadrian 532239478Sadrian wiifb_reset_video(sc); 533239478Sadrian wiifb_dispcfg_read(sc, &dc); 534239478Sadrian sc->sc_format = dc.dc_format; 535239478Sadrian sc->sc_component = wiifb_component_enabled(sc); 536239478Sadrian progressive = dc.dc_noninterlaced; 537239478Sadrian switch (sc->sc_format) { 538239478Sadrian case WIIFB_FORMAT_MPAL: 539239478Sadrian case WIIFB_FORMAT_DEBUG: 540239478Sadrian case WIIFB_FORMAT_NTSC: 541239478Sadrian sc->sc_mode = progressive ? 542239478Sadrian &wiifb_modes[WIIFB_MODE_NTSC_480p] : 543239478Sadrian &wiifb_modes[WIIFB_MODE_NTSC_480i]; 544239478Sadrian break; 545239478Sadrian case WIIFB_FORMAT_PAL: 546239478Sadrian sc->sc_mode = progressive ? 547239478Sadrian &wiifb_modes[WIIFB_MODE_PAL_480p] : 548239478Sadrian &wiifb_modes[WIIFB_MODE_PAL_480i]; 549239478Sadrian break; 550239478Sadrian } 551239478Sadrian sc->sc_height = sc->sc_mode->fd_height; 552239478Sadrian sc->sc_width = sc->sc_mode->fd_width; 553239478Sadrian /* Usually we multiply by 4, but I think this looks better. */ 554239478Sadrian sc->sc_stride = sc->sc_width * 2; 555239478Sadrian 556239478Sadrian wiifb_init(0, &sc->sc_va, 0); 557239478Sadrian 558239478Sadrian sc->sc_initialized = 1; 559239478Sadrian 560239478Sadrian return (0); 561239478Sadrian} 562239478Sadrian 563239478Sadrianstatic int 564239478Sadrianwiifb_probe(int unit, video_adapter_t **adp, void *arg, int flags) 565239478Sadrian{ 566239478Sadrian 567239478Sadrian return (0); 568239478Sadrian} 569239478Sadrian 570239478Sadrianstatic int 571239478Sadrianwiifb_init(int unit, video_adapter_t *adp, int flags) 572239478Sadrian{ 573239478Sadrian struct wiifb_softc *sc; 574239478Sadrian video_info_t *vi; 575239478Sadrian 576239478Sadrian sc = (struct wiifb_softc *)adp; 577239478Sadrian vi = &adp->va_info; 578239478Sadrian 579239478Sadrian vid_init_struct(adp, "wiifb", -1, unit); 580239478Sadrian 581239478Sadrian sc->sc_font = dflt_font_8; 582239478Sadrian vi->vi_cheight = WIIFB_FONT_HEIGHT; 583239478Sadrian vi->vi_width = sc->sc_width/8; 584239478Sadrian vi->vi_height = sc->sc_height/vi->vi_cheight; 585239478Sadrian vi->vi_cwidth = 8; 586239478Sadrian 587239478Sadrian /* 588239478Sadrian * Clamp width/height to syscons maximums 589239478Sadrian */ 590239478Sadrian if (vi->vi_width > COL) 591239478Sadrian vi->vi_width = COL; 592239478Sadrian if (vi->vi_height > ROW) 593239478Sadrian vi->vi_height = ROW; 594239478Sadrian 595239478Sadrian sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; 596239478Sadrian sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; 597239478Sadrian 598239478Sadrian adp->va_window = (vm_offset_t) wiifb_static_window; 599239478Sadrian /* XXX no colour support */ 600239478Sadrian adp->va_flags |= V_ADP_FONT | /*V_ADP_COLOR |*/ V_ADP_MODECHANGE; 601239478Sadrian 602239478Sadrian vid_register(&sc->sc_va); 603239478Sadrian 604239478Sadrian wiifb_configure_tv_mode(sc); 605239478Sadrian wiifb_setup_framebuffer(sc); 606239478Sadrian wiifb_enable_interrupts(sc); 607239478Sadrian wiifb_clear(adp); 608239478Sadrian 609239478Sadrian return (0); 610239478Sadrian} 611239478Sadrian 612239478Sadrianstatic int 613239478Sadrianwiifb_get_info(video_adapter_t *adp, int mode, video_info_t *info) 614239478Sadrian{ 615239478Sadrian 616239478Sadrian bcopy(&adp->va_info, info, sizeof(*info)); 617239478Sadrian return (0); 618239478Sadrian} 619239478Sadrian 620239478Sadrianstatic int 621239478Sadrianwiifb_query_mode(video_adapter_t *adp, video_info_t *info) 622239478Sadrian{ 623239478Sadrian 624239478Sadrian return (0); 625239478Sadrian} 626239478Sadrian 627239478Sadrianstatic int 628239478Sadrianwiifb_set_mode(video_adapter_t *adp, int mode) 629239478Sadrian{ 630239478Sadrian 631239478Sadrian return (0); 632239478Sadrian} 633239478Sadrian 634239478Sadrianstatic int 635239478Sadrianwiifb_save_font(video_adapter_t *adp, int page, int size, int width, 636239478Sadrian u_char *data, int c, int count) 637239478Sadrian{ 638239478Sadrian 639239478Sadrian return (0); 640239478Sadrian} 641239478Sadrian 642239478Sadrianstatic int 643239478Sadrianwiifb_load_font(video_adapter_t *adp, int page, int size, int width, 644239478Sadrian u_char *data, int c, int count) 645239478Sadrian{ 646239478Sadrian struct wiifb_softc *sc = (struct wiifb_softc *)adp; 647239478Sadrian 648239478Sadrian sc->sc_font = data; 649239478Sadrian 650239478Sadrian return (0); 651239478Sadrian} 652239478Sadrian 653239478Sadrianstatic int 654239478Sadrianwiifb_show_font(video_adapter_t *adp, int page) 655239478Sadrian{ 656239478Sadrian 657239478Sadrian return (0); 658239478Sadrian} 659239478Sadrian 660239478Sadrianstatic int 661239478Sadrianwiifb_save_palette(video_adapter_t *adp, u_char *palette) 662239478Sadrian{ 663239478Sadrian 664239478Sadrian return (0); 665239478Sadrian} 666239478Sadrian 667239478Sadrianstatic int 668239478Sadrianwiifb_load_palette(video_adapter_t *adp, u_char *palette) 669239478Sadrian{ 670239478Sadrian 671239478Sadrian return (0); 672239478Sadrian} 673239478Sadrian 674239478Sadrianstatic int 675239478Sadrianwiifb_set_border(video_adapter_t *adp, int border) 676239478Sadrian{ 677239478Sadrian 678239478Sadrian return (wiifb_blank_display(adp, border)); 679239478Sadrian} 680239478Sadrian 681239478Sadrianstatic int 682239478Sadrianwiifb_save_state(video_adapter_t *adp, void *p, size_t size) 683239478Sadrian{ 684239478Sadrian 685239478Sadrian return (0); 686239478Sadrian} 687239478Sadrian 688239478Sadrianstatic int 689239478Sadrianwiifb_load_state(video_adapter_t *adp, void *p) 690239478Sadrian{ 691239478Sadrian 692239478Sadrian return (0); 693239478Sadrian} 694239478Sadrian 695239478Sadrianstatic int 696239478Sadrianwiifb_set_win_org(video_adapter_t *adp, off_t offset) 697239478Sadrian{ 698239478Sadrian 699239478Sadrian return (0); 700239478Sadrian} 701239478Sadrian 702239478Sadrianstatic int 703239478Sadrianwiifb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 704239478Sadrian{ 705239478Sadrian 706239478Sadrian *col = *row = 0; 707239478Sadrian 708239478Sadrian return (0); 709239478Sadrian} 710239478Sadrian 711239478Sadrianstatic int 712239478Sadrianwiifb_set_hw_cursor(video_adapter_t *adp, int col, int row) 713239478Sadrian{ 714239478Sadrian 715239478Sadrian return (0); 716239478Sadrian} 717239478Sadrian 718239478Sadrianstatic int 719239478Sadrianwiifb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 720239478Sadrian int celsize, int blink) 721239478Sadrian{ 722239478Sadrian 723239478Sadrian return (0); 724239478Sadrian} 725239478Sadrian 726239478Sadrianstatic int 727239478Sadrianwiifb_blank_display(video_adapter_t *adp, int mode) 728239478Sadrian{ 729239478Sadrian struct wiifb_softc *sc = (struct wiifb_softc *)adp; 730239478Sadrian uint32_t *p; 731239478Sadrian 732239478Sadrian for (p = (uint32_t *)sc->sc_fb_addr; 733239478Sadrian p < (uint32_t *)(sc->sc_fb_addr + sc->sc_fb_size); 734239478Sadrian p++) 735239478Sadrian *p = wiifb_cmap[wiifb_background(SC_NORM_ATTR)]; 736239478Sadrian 737239478Sadrian return (0); 738239478Sadrian} 739239478Sadrian 740239478Sadrianstatic int 741239478Sadrianwiifb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 742239478Sadrian int prot, vm_memattr_t *memattr) 743239478Sadrian{ 744239478Sadrian struct wiifb_softc *sc; 745239478Sadrian 746239478Sadrian sc = (struct wiifb_softc *)adp; 747239478Sadrian 748239478Sadrian /* 749239478Sadrian * This might be a legacy VGA mem request: if so, just point it at the 750239478Sadrian * framebuffer, since it shouldn't be touched 751239478Sadrian */ 752239478Sadrian if (offset < sc->sc_stride*sc->sc_height) { 753239478Sadrian *paddr = sc->sc_fb_addr + offset; 754239478Sadrian return (0); 755239478Sadrian } 756239478Sadrian 757239478Sadrian return (EINVAL); 758239478Sadrian} 759239478Sadrian 760239478Sadrianstatic int 761239478Sadrianwiifb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) 762239478Sadrian{ 763239478Sadrian 764239478Sadrian return (0); 765239478Sadrian} 766239478Sadrian 767239478Sadrianstatic int 768239478Sadrianwiifb_clear(video_adapter_t *adp) 769239478Sadrian{ 770239478Sadrian 771239478Sadrian return (wiifb_blank_display(adp, 0)); 772239478Sadrian} 773239478Sadrian 774239478Sadrianstatic int 775239478Sadrianwiifb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 776239478Sadrian{ 777239478Sadrian 778239478Sadrian return (0); 779239478Sadrian} 780239478Sadrian 781239478Sadrianstatic int 782239478Sadrianwiifb_bitblt(video_adapter_t *adp, ...) 783239478Sadrian{ 784239478Sadrian 785239478Sadrian return (0); 786239478Sadrian} 787239478Sadrian 788239478Sadrianstatic int 789239478Sadrianwiifb_diag(video_adapter_t *adp, int level) 790239478Sadrian{ 791239478Sadrian 792239478Sadrian return (0); 793239478Sadrian} 794239478Sadrian 795239478Sadrianstatic int 796239478Sadrianwiifb_save_cursor_palette(video_adapter_t *adp, u_char *palette) 797239478Sadrian{ 798239478Sadrian 799239478Sadrian return (0); 800239478Sadrian} 801239478Sadrian 802239478Sadrianstatic int 803239478Sadrianwiifb_load_cursor_palette(video_adapter_t *adp, u_char *palette) 804239478Sadrian{ 805239478Sadrian 806239478Sadrian return (0); 807239478Sadrian} 808239478Sadrian 809239478Sadrianstatic int 810239478Sadrianwiifb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) 811239478Sadrian{ 812239478Sadrian 813239478Sadrian return (0); 814239478Sadrian} 815239478Sadrian 816239478Sadrianstatic int 817239478Sadrianwiifb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, 818239478Sadrian int size, int bpp, int bit_ltor, int byte_ltor) 819239478Sadrian{ 820239478Sadrian 821239478Sadrian return (0); 822239478Sadrian} 823239478Sadrian 824239478Sadrianstatic int 825239478Sadrianwiifb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) 826239478Sadrian{ 827239478Sadrian struct wiifb_softc *sc; 828239478Sadrian int row; 829239478Sadrian int col; 830239478Sadrian int i, j, k; 831239478Sadrian uint32_t *addr; 832239478Sadrian u_char *p; 833239478Sadrian uint32_t fg, bg; 834239478Sadrian unsigned long pixel[2]; 835239478Sadrian 836239478Sadrian sc = (struct wiifb_softc *)adp; 837239478Sadrian row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; 838239478Sadrian col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth / 2; 839239478Sadrian p = sc->sc_font + c*WIIFB_FONT_HEIGHT; 840239478Sadrian addr = (uint32_t *)sc->sc_fb_addr 841239478Sadrian + (row + sc->sc_ymargin)*(sc->sc_stride/4) 842239478Sadrian + col + sc->sc_xmargin; 843239478Sadrian 844239478Sadrian bg = wiifb_cmap[wiifb_background(a)]; 845239478Sadrian fg = wiifb_cmap[wiifb_foreground(a)]; 846239478Sadrian 847239478Sadrian for (i = 0; i < WIIFB_FONT_HEIGHT; i++) { 848239478Sadrian for (j = 0, k = 7; j < 4; j++, k--) { 849239478Sadrian if ((p[i] & (1 << k)) == 0) 850239478Sadrian pixel[0] = bg; 851239478Sadrian else 852239478Sadrian pixel[0] = fg; 853239478Sadrian k--; 854239478Sadrian if ((p[i] & (1 << k)) == 0) 855239478Sadrian pixel[1] = bg; 856239478Sadrian else 857239478Sadrian pixel[1] = fg; 858239478Sadrian 859239478Sadrian addr[j] = (pixel[0] & 0xffff00ff) | 860239478Sadrian (pixel[1] & 0x0000ff00); 861239478Sadrian } 862239478Sadrian addr += (sc->sc_stride/4); 863239478Sadrian } 864239478Sadrian 865239478Sadrian return (0); 866239478Sadrian} 867239478Sadrian 868239478Sadrianstatic int 869239478Sadrianwiifb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) 870239478Sadrian{ 871239478Sadrian int i; 872239478Sadrian 873239478Sadrian for (i = 0; i < len; i++) 874239478Sadrian wiifb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); 875239478Sadrian 876239478Sadrian return (0); 877239478Sadrian} 878239478Sadrian 879239478Sadrianstatic int 880239478Sadrianwiifb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, 881239478Sadrian uint32_t pixel_mask, int size, int width) 882239478Sadrian{ 883239478Sadrian 884239478Sadrian return (0); 885239478Sadrian} 886