31ec0f7a83
reach single user mode using a memory disk device as the file system. This port includes the framebuffer driver, the PIC driver, a platform driver and the GPIO driver. The IPC driver (to talk to IOS kernels) is not yet written but there's a placeholder for it. There are still some MMU problems and to get a working system you need to patch locore32.S. Since we haven't found the best way yet to address that problem, we're not committing those changes yet. The problem is related to the different BAT layout on the Wii and to the fact that the Homebrew loader doesn't clean up the special registers (including the 8 BATs) before passing control to us. You'll need a Wii with Homebrew loader and a TV that can do NTSC (for now). Submitted by: Margarida Gouveia
858 lines
19 KiB
C
858 lines
19 KiB
C
/*-
|
|
* Copyright (C) 2012 Margarida Gouveia
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer,
|
|
* without modification, immediately at the beginning of the file.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef _POWERPC_WII_WIIFB_H
|
|
#define _POWERPC_WII_WIIFB_H
|
|
|
|
#define WIIFB_FONT_HEIGHT 8
|
|
|
|
enum wiifb_format {
|
|
WIIFB_FORMAT_NTSC = 0,
|
|
WIIFB_FORMAT_PAL = 1,
|
|
WIIFB_FORMAT_MPAL = 2,
|
|
WIIFB_FORMAT_DEBUG = 3
|
|
};
|
|
|
|
enum wiifb_mode {
|
|
WIIFB_MODE_NTSC_480i = 0,
|
|
WIIFB_MODE_NTSC_480p = 1,
|
|
WIIFB_MODE_PAL_576i = 2,
|
|
WIIFB_MODE_PAL_480i = 3,
|
|
WIIFB_MODE_PAL_480p = 4
|
|
};
|
|
|
|
struct wiifb_mode_desc {
|
|
const char *fd_name;
|
|
unsigned int fd_width;
|
|
unsigned int fd_height;
|
|
unsigned int fd_lines;
|
|
uint8_t fd_flags;
|
|
#define WIIFB_MODE_FLAG_PROGRESSIVE 0x00
|
|
#define WIIFB_MODE_FLAG_INTERLACED 0x01
|
|
};
|
|
|
|
struct wiifb_softc {
|
|
video_adapter_t sc_va;
|
|
struct cdev *sc_si;
|
|
int sc_console;
|
|
|
|
intptr_t sc_reg_addr;
|
|
unsigned int sc_reg_size;
|
|
|
|
intptr_t sc_fb_addr;
|
|
unsigned int sc_fb_size;
|
|
|
|
unsigned int sc_height;
|
|
unsigned int sc_width;
|
|
unsigned int sc_stride;
|
|
|
|
unsigned int sc_xmargin;
|
|
unsigned int sc_ymargin;
|
|
|
|
boolean_t sc_component;
|
|
enum wiifb_format sc_format;
|
|
struct wiifb_mode_desc *sc_mode;
|
|
|
|
unsigned int sc_vtiming;
|
|
unsigned int sc_htiming;
|
|
|
|
unsigned char *sc_font;
|
|
int sc_initialized;
|
|
int sc_rrid;
|
|
};
|
|
|
|
/*
|
|
* Vertical timing
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_VTIMING 0x00
|
|
struct wiifb_vtiming {
|
|
uint8_t vt_eqpulse;
|
|
uint16_t vt_actvideo;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_vtiming_read(struct wiifb_softc *sc, struct wiifb_vtiming *vt)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMING);
|
|
|
|
vt->vt_eqpulse = *reg & 0xf;
|
|
vt->vt_actvideo = (*reg >> 4) & 0x3ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_vtiming_write(struct wiifb_softc *sc, struct wiifb_vtiming *vt)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMING);
|
|
|
|
*reg = ((vt->vt_actvideo & 0x3ff) << 4) |
|
|
(vt->vt_eqpulse & 0xf);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Display configuration
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_DISPCFG 0x02
|
|
struct wiifb_dispcfg {
|
|
uint8_t dc_enable;
|
|
uint8_t dc_reset;
|
|
uint8_t dc_noninterlaced;
|
|
uint8_t dc_3dmode;
|
|
uint8_t dc_latchenb0;
|
|
uint8_t dc_latchenb1;
|
|
enum wiifb_format dc_format;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_dispcfg_read(struct wiifb_softc *sc, struct wiifb_dispcfg *dc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DISPCFG);
|
|
|
|
dc->dc_enable = *reg & 0x1;
|
|
dc->dc_reset = (*reg >> 1) & 0x1;
|
|
dc->dc_noninterlaced = (*reg >> 2) & 0x1;
|
|
dc->dc_3dmode = (*reg >> 3) & 0x1;
|
|
dc->dc_latchenb0 = (*reg >> 4) & 0x3;
|
|
dc->dc_latchenb1 = (*reg >> 6) & 0x3;
|
|
dc->dc_format = (*reg >> 8) & 0x3;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_dispcfg_write(struct wiifb_softc *sc, struct wiifb_dispcfg *dc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DISPCFG);
|
|
|
|
*reg = ((dc->dc_format & 0x3) << 8) |
|
|
((dc->dc_latchenb1 & 0x3) << 6) |
|
|
((dc->dc_latchenb0 & 0x3) << 4) |
|
|
((dc->dc_3dmode & 0x1) << 3) |
|
|
((dc->dc_noninterlaced & 0x1) << 2) |
|
|
((dc->dc_reset & 0x1) << 1) |
|
|
(dc->dc_enable & 0x1);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Horizontal Timing 0
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_HTIMING0 0x04
|
|
struct wiifb_htiming0 {
|
|
uint16_t ht0_hlinew; /* half line width */
|
|
uint8_t ht0_hcolourend;
|
|
uint8_t ht0_hcolourstart;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_htiming0_read(struct wiifb_softc *sc, struct wiifb_htiming0 *ht0)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING0);
|
|
|
|
ht0->ht0_hlinew = *reg & 0x1ff;
|
|
ht0->ht0_hcolourend = (*reg >> 16) & 0x7f;
|
|
ht0->ht0_hcolourstart = (*reg >> 24) & 0x7f;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_htiming0_write(struct wiifb_softc *sc, struct wiifb_htiming0 *ht0)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING0);
|
|
|
|
*reg = ((ht0->ht0_hcolourstart & 0x7f) << 24) |
|
|
((ht0->ht0_hcolourend & 0x7f) << 16) |
|
|
(ht0->ht0_hlinew & 0x1ff);
|
|
powerpc_sync();
|
|
}
|
|
/*
|
|
* Horizontal Timing 1
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_HTIMING1 0x08
|
|
struct wiifb_htiming1 {
|
|
uint8_t ht1_hsyncw;
|
|
uint16_t ht1_hblankend;
|
|
uint16_t ht1_hblankstart;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_htiming1_read(struct wiifb_softc *sc, struct wiifb_htiming1 *ht1)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING1);
|
|
|
|
ht1->ht1_hsyncw = *reg & 0x7f;
|
|
ht1->ht1_hblankend = (*reg >> 7) & 0x3ff;
|
|
ht1->ht1_hblankstart = (*reg >> 17) & 0x3ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_htiming1_write(struct wiifb_softc *sc, struct wiifb_htiming1 *ht1)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_HTIMING1);
|
|
|
|
*reg = ((ht1->ht1_hblankstart & 0x3ff) << 17) |
|
|
((ht1->ht1_hblankend & 0x3ff) << 7) |
|
|
(ht1->ht1_hsyncw & 0x7f);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Vertical Timing Odd
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_VTIMINGODD 0x0c
|
|
struct wiifb_vtimingodd {
|
|
uint16_t vto_preb; /* pre blanking */
|
|
uint16_t vto_postb; /* post blanking */
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_vtimingodd_read(struct wiifb_softc *sc, struct wiifb_vtimingodd *vto)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGODD);
|
|
|
|
vto->vto_preb = *reg & 0x3ff;
|
|
vto->vto_postb = (*reg >> 16) & 0x3ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_vtimingodd_write(struct wiifb_softc *sc, struct wiifb_vtimingodd *vto)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGODD);
|
|
|
|
*reg = ((vto->vto_postb & 0x3ff) << 16) |
|
|
(vto->vto_preb & 0x3ff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Vertical Timing Even
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_VTIMINGEVEN 0x10
|
|
struct wiifb_vtimingeven {
|
|
uint16_t vte_preb; /* pre blanking */
|
|
uint16_t vte_postb; /* post blanking */
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_vtimingeven_read(struct wiifb_softc *sc, struct wiifb_vtimingeven *vte)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGEVEN);
|
|
|
|
vte->vte_preb = *reg & 0x3ff;
|
|
vte->vte_postb = (*reg >> 16) & 0x3ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_vtimingeven_write(struct wiifb_softc *sc, struct wiifb_vtimingeven *vte)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_VTIMINGEVEN);
|
|
|
|
*reg = ((vte->vte_postb & 0x3ff) << 16) |
|
|
(vte->vte_preb & 0x3ff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Burst Blanking Odd Interval
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_BURSTBLANKODD 0x14
|
|
struct wiifb_burstblankodd {
|
|
uint8_t bbo_bs1;
|
|
uint16_t bbo_be1;
|
|
uint8_t bbo_bs3;
|
|
uint16_t bbo_be3;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_burstblankodd_read(struct wiifb_softc *sc,
|
|
struct wiifb_burstblankodd *bbo)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKODD);
|
|
|
|
bbo->bbo_bs1 = *reg & 0x1f;
|
|
bbo->bbo_be1 = (*reg >> 5) & 0x7ff;
|
|
bbo->bbo_bs3 = (*reg >> 16) & 0x1f;
|
|
bbo->bbo_be3 = (*reg >> 21) & 0x7ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_burstblankodd_write(struct wiifb_softc *sc,
|
|
struct wiifb_burstblankodd *bbo)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKODD);
|
|
|
|
*reg = ((bbo->bbo_be3 & 0x7ff) << 21) |
|
|
((bbo->bbo_bs3 & 0x1f) << 16) |
|
|
((bbo->bbo_be1 & 0x7ff) << 5) |
|
|
(bbo->bbo_bs1 & 0x1f);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Burst Blanking Even Interval
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_BURSTBLANKEVEN 0x18
|
|
struct wiifb_burstblankeven {
|
|
uint8_t bbe_bs2;
|
|
uint16_t bbe_be2;
|
|
uint8_t bbe_bs4;
|
|
uint16_t bbe_be4;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_burstblankeven_read(struct wiifb_softc *sc,
|
|
struct wiifb_burstblankeven *bbe)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKEVEN);
|
|
|
|
bbe->bbe_bs2 = *reg & 0x1f;
|
|
bbe->bbe_be2 = (*reg >> 5) & 0x7ff;
|
|
bbe->bbe_bs4 = (*reg >> 16) & 0x1f;
|
|
bbe->bbe_be4 = (*reg >> 21) & 0x7ff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_burstblankeven_write(struct wiifb_softc *sc,
|
|
struct wiifb_burstblankeven *bbe)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BURSTBLANKEVEN);
|
|
|
|
*reg = ((bbe->bbe_be4 & 0x7ff) << 21) |
|
|
((bbe->bbe_bs4 & 0x1f) << 16) |
|
|
((bbe->bbe_be2 & 0x7ff) << 5) |
|
|
(bbe->bbe_bs2 & 0x1f);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Top Field Base Left
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_TOPFIELDBASEL 0x1c
|
|
struct wiifb_topfieldbasel {
|
|
uint32_t tfbl_fbaddr;
|
|
uint8_t tfbl_xoffset;
|
|
uint8_t tfbl_pageoffbit;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_topfieldbasel_read(struct wiifb_softc *sc,
|
|
struct wiifb_topfieldbasel *tfbl)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASEL);
|
|
|
|
tfbl->tfbl_fbaddr = *reg & 0xffffff;
|
|
tfbl->tfbl_xoffset = (*reg >> 24) & 0xf;
|
|
tfbl->tfbl_pageoffbit = (*reg >> 28) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_topfieldbasel_write(struct wiifb_softc *sc,
|
|
struct wiifb_topfieldbasel *tfbl)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASEL);
|
|
|
|
*reg = ((tfbl->tfbl_pageoffbit & 0x1) << 28) |
|
|
((tfbl->tfbl_xoffset & 0xf) << 24) |
|
|
(tfbl->tfbl_fbaddr & 0xffffff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Top Field Base Right
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_TOPFIELDBASER 0x20
|
|
struct wiifb_topfieldbaser {
|
|
uint32_t tfbr_fbaddr;
|
|
uint8_t tfbr_pageoffbit;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_topfieldbaser_read(struct wiifb_softc *sc,
|
|
struct wiifb_topfieldbaser *tfbr)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASER);
|
|
|
|
tfbr->tfbr_fbaddr = *reg & 0xffffff;
|
|
tfbr->tfbr_pageoffbit = (*reg >> 28) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_topfieldbaser_write(struct wiifb_softc *sc,
|
|
struct wiifb_topfieldbaser *tfbr)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_TOPFIELDBASER);
|
|
|
|
*reg = ((tfbr->tfbr_pageoffbit & 0x1) << 28) |
|
|
(tfbr->tfbr_fbaddr & 0xffffff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Bottom Field Base Left
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_BOTTOMFIELDBASEL 0x24
|
|
struct wiifb_bottomfieldbasel {
|
|
uint32_t bfbl_fbaddr;
|
|
uint8_t bfbl_xoffset;
|
|
uint8_t bfbl_pageoffbit;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_bottomfieldbasel_read(struct wiifb_softc *sc,
|
|
struct wiifb_bottomfieldbasel *bfbl)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASEL);
|
|
|
|
bfbl->bfbl_fbaddr = *reg & 0xffffff;
|
|
bfbl->bfbl_xoffset = (*reg >> 24) & 0xf;
|
|
bfbl->bfbl_pageoffbit = (*reg >> 28) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_bottomfieldbasel_write(struct wiifb_softc *sc,
|
|
struct wiifb_bottomfieldbasel *bfbl)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASEL);
|
|
|
|
*reg = ((bfbl->bfbl_pageoffbit & 0x1) << 28) |
|
|
((bfbl->bfbl_xoffset & 0xf) << 24) |
|
|
(bfbl->bfbl_fbaddr & 0xffffff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Bottom Field Base Right
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_BOTTOMFIELDBASER 0x28
|
|
struct wiifb_bottomfieldbaser {
|
|
uint32_t bfbr_fbaddr;
|
|
uint8_t bfbr_pageoffbit;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_bottomfieldbaser_read(struct wiifb_softc *sc,
|
|
struct wiifb_bottomfieldbaser *bfbr)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASER);
|
|
|
|
bfbr->bfbr_fbaddr = *reg & 0xffffff;
|
|
bfbr->bfbr_pageoffbit = (*reg >> 28) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_bottomfieldbaser_write(struct wiifb_softc *sc,
|
|
struct wiifb_bottomfieldbaser *bfbr)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_BOTTOMFIELDBASER);
|
|
|
|
*reg = ((bfbr->bfbr_pageoffbit & 0x1) << 28) |
|
|
(bfbr->bfbr_fbaddr & 0xffffff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Display Position Vertical
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_DISPPOSV 0x2c
|
|
static __inline uint16_t
|
|
wiifb_dispposv_read(struct wiifb_softc *sc)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSV);
|
|
|
|
return (*reg & 0x7ff);
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_dispposv_write(struct wiifb_softc *sc, uint16_t val)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSV);
|
|
|
|
*reg = val & 0x7ff;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Display Position Horizontal
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_DISPPOSH 0x2e
|
|
static __inline uint16_t
|
|
wiifb_dispposh_read(struct wiifb_softc *sc)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSH);
|
|
|
|
return (*reg & 0x7ff);
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_dispposh_write(struct wiifb_softc *sc, uint16_t val)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_DISPPOSH);
|
|
|
|
*reg = val & 0x7ff;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Display Interrupts.
|
|
* There are 4 display interrupt registers, all 32 bit.
|
|
*/
|
|
#define WIIFB_REG_DISPINT0 0x30
|
|
#define WIIFB_REG_DISPINT1 0x34
|
|
#define WIIFB_REG_DISPINT2 0x38
|
|
#define WIIFB_REG_DISPINT3 0x3c
|
|
struct wiifb_dispint {
|
|
uint16_t di_htiming;
|
|
uint16_t di_vtiming;
|
|
uint8_t di_enable;
|
|
uint8_t di_irq;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_dispint_read(struct wiifb_softc *sc, int regno, struct wiifb_dispint *di)
|
|
{
|
|
volatile uint32_t *reg = (uint32_t *)(sc->sc_reg_addr +
|
|
WIIFB_REG_DISPINT0 + regno * 4);
|
|
|
|
di->di_htiming = *reg & 0x3ff;
|
|
di->di_vtiming = (*reg >> 16) & 0x3ff;
|
|
di->di_enable = (*reg >> 28) & 0x1;
|
|
di->di_irq = (*reg >> 31) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_dispint_write(struct wiifb_softc *sc, int regno, struct wiifb_dispint *di)
|
|
{
|
|
volatile uint32_t *reg = (uint32_t *)(sc->sc_reg_addr +
|
|
WIIFB_REG_DISPINT0 + regno * 4);
|
|
|
|
*reg = ((di->di_irq & 0x1) << 31) |
|
|
((di->di_enable & 0x1) << 28) |
|
|
((di->di_vtiming & 0x3ff) << 16) |
|
|
(di->di_htiming & 0x3ff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Display Latch 0
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_DISPLAYTCH0 0x40
|
|
|
|
/*
|
|
* Display Latch 1
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_DISPLAYTCH1 0x44
|
|
|
|
/*
|
|
* Picture Configuration
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_PICCONF 0x48
|
|
struct wiifb_picconf {
|
|
uint8_t pc_strides; /* strides per line (words) */
|
|
uint8_t pc_reads; /* reads per line (words */
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_picconf_read(struct wiifb_softc *sc, struct wiifb_picconf *pc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_PICCONF);
|
|
|
|
pc->pc_strides = *reg & 0xff;
|
|
pc->pc_reads = (*reg >> 8) & 0xff;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_picconf_write(struct wiifb_softc *sc, struct wiifb_picconf *pc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_PICCONF);
|
|
|
|
*reg = ((pc->pc_reads & 0xff) << 8) |
|
|
(pc->pc_strides & 0xff);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Horizontal Scaling
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_HSCALING 0x4a
|
|
struct wiifb_hscaling {
|
|
uint16_t hs_step;
|
|
uint8_t hs_enable;
|
|
};
|
|
|
|
static __inline void
|
|
wiifb_hscaling_read(struct wiifb_softc *sc, struct wiifb_hscaling *hs)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALING);
|
|
|
|
hs->hs_step = *reg & 0x1ff;
|
|
hs->hs_enable = (*reg >> 12) & 0x1;
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_hscaling_write(struct wiifb_softc *sc, struct wiifb_hscaling *hs)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALING);
|
|
|
|
*reg = ((hs->hs_step & 0x1ff) << 12) |
|
|
(hs->hs_enable & 0x1);
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Filter Coeficient Table 0-6
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_FILTCOEFT0 0x4c
|
|
#define WIIFB_REG_FILTCOEFT1 0x50
|
|
#define WIIFB_REG_FILTCOEFT2 0x54
|
|
#define WIIFB_REG_FILTCOEFT3 0x58
|
|
#define WIIFB_REG_FILTCOEFT4 0x5c
|
|
#define WIIFB_REG_FILTCOEFT5 0x60
|
|
#define WIIFB_REG_FILTCOEFT6 0x64
|
|
static __inline void
|
|
wiifb_filtcoeft_write(struct wiifb_softc *sc, unsigned int regno,
|
|
uint32_t coeft)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_FILTCOEFT0 + 4 * regno);
|
|
|
|
*reg = coeft;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Anti-aliasing
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_ANTIALIAS 0x68
|
|
static __inline void
|
|
wiifb_antialias_write(struct wiifb_softc *sc, uint32_t antialias)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_ANTIALIAS);
|
|
|
|
*reg = antialias;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Video Clock
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_VIDEOCLK 0x6c
|
|
static __inline uint8_t
|
|
wiifb_videoclk_read(struct wiifb_softc *sc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VIDEOCLK);
|
|
|
|
return (*reg & 0x1);
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_videoclk_write(struct wiifb_softc *sc, uint16_t clk54mhz)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_VIDEOCLK);
|
|
|
|
*reg = clk54mhz & 0x1;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* DTV Status
|
|
* 16 bit
|
|
*
|
|
* DTV is another name for the Component Cable output.
|
|
*/
|
|
#define WIIFB_REG_DTVSTATUS 0x6e
|
|
static __inline uint16_t
|
|
wiifb_dtvstatus_read(struct wiifb_softc *sc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_DTVSTATUS);
|
|
|
|
return (*reg & 0x1);
|
|
}
|
|
|
|
static __inline uint16_t
|
|
wiifb_component_enabled(struct wiifb_softc *sc)
|
|
{
|
|
|
|
return wiifb_dtvstatus_read(sc);
|
|
}
|
|
|
|
/*
|
|
* Horizontal Scaling Width
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_HSCALINGW 0x70
|
|
static __inline uint16_t
|
|
wiifb_hscalingw_read(struct wiifb_softc *sc)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALINGW);
|
|
|
|
return (*reg & 0x3ff);
|
|
}
|
|
|
|
static __inline void
|
|
wiifb_hscalingw_write(struct wiifb_softc *sc, uint16_t width)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HSCALINGW);
|
|
|
|
*reg = width & 0x3ff;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Horizontal Border End
|
|
* For debug mode only. Not used by this driver.
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_HBORDEREND 0x72
|
|
static __inline void
|
|
wiifb_hborderend_write(struct wiifb_softc *sc, uint16_t border)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HBORDEREND);
|
|
|
|
*reg = border;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Horizontal Border Start
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_HBORDERSTART 0x74
|
|
static __inline void
|
|
wiifb_hborderstart_write(struct wiifb_softc *sc, uint16_t border)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_HBORDERSTART);
|
|
|
|
*reg = border;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Unknown register
|
|
* 16 bit
|
|
*/
|
|
#define WIIFB_REG_UNKNOWN1 0x76
|
|
static __inline void
|
|
wiifb_unknown1_write(struct wiifb_softc *sc, uint16_t unknown)
|
|
{
|
|
volatile uint16_t *reg =
|
|
(uint16_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN1);
|
|
|
|
*reg = unknown;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Unknown register
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_UNKNOWN2 0x78
|
|
static __inline void
|
|
wiifb_unknown2_write(struct wiifb_softc *sc, uint32_t unknown)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN2);
|
|
|
|
*reg = unknown;
|
|
powerpc_sync();
|
|
}
|
|
|
|
/*
|
|
* Unknown register
|
|
* 32 bit
|
|
*/
|
|
#define WIIFB_REG_UNKNOWN3 0x7c
|
|
static __inline void
|
|
wiifb_unknown3_write(struct wiifb_softc *sc, uint32_t unknown)
|
|
{
|
|
volatile uint32_t *reg =
|
|
(uint32_t *)(sc->sc_reg_addr + WIIFB_REG_UNKNOWN3);
|
|
|
|
*reg = unknown;
|
|
powerpc_sync();
|
|
}
|
|
|
|
#endif /* _POWERPC_WII_WIIFB_H */
|