diff --git a/sys/arch/dreamcast/dev/pvr.c b/sys/arch/dreamcast/dev/pvr.c index d0fa76c66801..fa128efdf47c 100644 --- a/sys/arch/dreamcast/dev/pvr.c +++ b/sys/arch/dreamcast/dev/pvr.c @@ -1,4 +1,4 @@ -/* $NetBSD: pvr.c,v 1.11 2002/03/24 18:21:23 uch Exp $ */ +/* $NetBSD: pvr.c,v 1.12 2002/05/03 04:42:08 thorpej Exp $ */ /*- * Copyright (c) 2001 Marcus Comstedt. @@ -65,7 +65,7 @@ #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pvr.c,v 1.11 2002/03/24 18:21:23 uch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pvr.c,v 1.12 2002/05/03 04:42:08 thorpej Exp $"); #include #include @@ -75,6 +75,7 @@ __KERNEL_RCSID(0, "$NetBSD: pvr.c,v 1.11 2002/03/24 18:21:23 uch Exp $"); #include #include +#include #include #include @@ -93,9 +94,76 @@ __KERNEL_RCSID(0, "$NetBSD: pvr.c,v 1.11 2002/03/24 18:21:23 uch Exp $"); #include "mkbd.h" +#define PVRREG_FBSTART 0x05000000 +#define PVRREG_REGSTART 0x005f8000 + +#define PVRREG_BRDCOLR 0x40 +#define BRDCOLR_BLUE(x) ((x) << 0) +#define BRDCOLR_GREEN(x) ((x) << 8) +#define BRDCOLR_RED(x) ((x) << 16) + +#define PVRREG_DIWMODE 0x44 +#define DIWMODE_DE (1U << 0) /* display enable */ +#define DIWMODE_SD (1U << 1) /* scan double enable */ +#define DIWMODE_COL(x) ((x) << 2) +#define DIWMODE_COL_RGB555 DIWMODE_COL(0) /* RGB555, 16-bit */ +#define DIWMODE_COL_RGB565 DIWMODE_COL(1) /* RGB565, 16-bit */ +#define DIWMODE_COL_RGB888 DIWMODE_COL(2) /* RGB888, 24-bit */ +#define DIWMODE_COL_ARGB888 DIWMODE_COL(3) /* RGB888, 32-bit */ +#define DIWMODE_C (1U << 23) /* 2x clock enable (VGA) */ + +#define PVRREG_DIWADDRL 0x50 + +#define PVRREG_DIWADDRS 0x54 + +#define PVRREG_DIWSIZE 0x5c +#define DIWSIZE_DPL(x) ((x) << 0) /* pixel data per line */ +#define DIWSIZE_LPF(x) ((x) << 10) /* lines per field */ +#define DIWSIZE_MODULO(x) ((x) << 20) /* words to skip + 1 */ + +#define PVRREG_RASEVTPOS 0xcc +#define RASEVTPOS_BOTTOM(x) ((x) << 0) +#define RASEVTPOS_TOP(x) ((x) << 16) + +#define PVRREG_SYNCCONF 0xd0 +#define SYNCCONF_VP (1U << 0) /* V-sync polarity */ +#define SYNCCONF_HP (1U << 1) /* H-sync polarity */ +#define SYNCCONF_I (1U << 4) /* interlace */ +#define SYNCCONF_BC(x) (1U << 6) /* broadcast standard */ +#define SYNCCONF_VO (1U << 8) /* video output enable */ + +#define PVRREG_BRDHORZ 0xd4 +#define BRDHORZ_STOP(x) ((x) << 0) +#define BRDHORZ_START(x) ((x) << 16) + +#define PVRREG_SYNCSIZE 0xd8 +#define SYNCSIZE_H(x) ((x) << 0) +#define SYNCSIZE_V(x) ((x) << 16) + +#define PVRREG_BRDVERT 0xdc +#define BRDVERT_STOP(x) ((x) << 0) +#define BRDVERT_START(x) ((x) << 16) + +#define PVRREG_DIWCONF 0xe8 +#define DIWCONF_LR (1U << 8) /* low-res */ +#define DIWCONF_MAGIC (22 << 16) + +#define PVRREG_DIWHSTRT 0xec + +#define PVRREG_DIWVSTRT 0xf0 +#define DIWVSTRT_V1(x) ((x) << 0) +#define DIWVSTRT_V2(x) ((x) << 16) + +#define PVR_REG_READ(dc, reg) \ + ((__volatile uint32_t *)(dc)->dc_regvaddr)[(reg) >> 2] +#define PVR_REG_WRITE(dc, reg, val) \ + ((__volatile uint32_t *)(dc)->dc_regvaddr)[(reg) >> 2] = (val) + struct fb_devconfig { vaddr_t dc_vaddr; /* framebuffer virtual address */ vaddr_t dc_paddr; /* framebuffer physical address */ + vaddr_t dc_regvaddr; /* registers virtual address */ + vaddr_t dc_regpaddr; /* registers physical address */ int dc_wid; /* width of frame buffer */ int dc_ht; /* height of frame buffer */ int dc_depth; /* depth, bits per pixel */ @@ -182,9 +250,12 @@ pvr_getdevconfig(struct fb_devconfig *dc) { int i, cookie; - dc->dc_paddr = 0x05000000; + dc->dc_paddr = PVRREG_FBSTART; dc->dc_vaddr = SH3_PHYS_TO_P2SEG(dc->dc_paddr); + dc->dc_regpaddr = PVRREG_REGSTART; + dc->dc_regvaddr = SH3_PHYS_TO_P2SEG(dc->dc_regpaddr); + dc->dc_wid = 640; dc->dc_ht = 480; dc->dc_depth = 16; @@ -398,6 +469,7 @@ pvr_check_cable(struct fb_devconfig *dc) static void pvr_check_tvsys(struct fb_devconfig *dc) { + /* XXX should use flashmem device when one exists */ dc->dc_tvsystem = (*(__volatile u_int8_t *)0xa021a004) & 3; } @@ -405,60 +477,111 @@ pvr_check_tvsys(struct fb_devconfig *dc) void pvrinit(struct fb_devconfig *dc) { - __volatile u_int32_t *pvr = (__volatile u_int32_t *) - SH3_PHYS_TO_P2SEG(0x005f8000); - int display_lines_per_field = 240; - int v_absolute_size = 525; - int h_absolute_size = 857; - int modulo = 1, voffset, hoffset = 164, border = (126 << 16) | 837; + int display_lines_per_field; + int v_absolute_size; + int h_absolute_size; + int vborder_start, vborder_stop; + int hborder_start, hborder_stop; + int modulo = 1, voffset, hoffset; pvr_check_cable(dc); pvr_check_tvsys(dc); - pvr[8/4] = 0; /* reset */ - pvr[0x40/4] = 0; /* black border */ + PVR_REG_WRITE(dc, 8, 0); /* reset */ + PVR_REG_WRITE(dc, PVRREG_BRDCOLR, 0); /* black border */ if (dc->dc_dispflags & PVR_VGAMODE) { - pvr[0x44/4] = 0x800004; /* 31kHz, RGB565 */ - pvr[0xd0/4] = 0x100; /* video output */ + v_absolute_size = 524; + h_absolute_size = 857; + display_lines_per_field = 480; + hoffset = 164; voffset = 36; + + hborder_start = 126; + hborder_stop = 837; + + vborder_start = 40; + vborder_stop = 444; /* XXX */ + + /* 31kHz, RGB565 */ + PVR_REG_WRITE(dc, PVRREG_DIWMODE, + DIWMODE_C | DIWMODE_COL_RGB565); + + /* video output */ + PVR_REG_WRITE(dc, PVRREG_SYNCCONF, SYNCCONF_VO); } else { - if(dc->dc_tvsystem & 1) { - /* 50 Hz */ - v_absolute_size = 625; + if (dc->dc_tvsystem & 1) { + /* 50 Hz PAL */ + v_absolute_size = 624; h_absolute_size = 863; + + display_lines_per_field = 240; hoffset = 174; - border = (116 << 16) | 843; + voffset = 18; + + hborder_start = 116; + hborder_stop = 843; + + vborder_start = 44; + vborder_stop = 536; /* XXX */ + } else { + /* 60 Hz NTSC */ + v_absolute_size = 524; + h_absolute_size = 857; + + display_lines_per_field = 240; + hoffset = 170; + voffset = 28; + + hborder_start = 126; + hborder_stop = 837; + + vborder_start = 18; + vborder_stop = 506; /* XXX */ } - pvr[0x44/4] = 0x000004; /* 15kHz, RGB565 */ - /* video output, PAL/NTSC, interlace */ - pvr[0xd0/4] = 0x110|(dc->dc_tvsystem<<6); + modulo += 640 * 2 / 4; /* interlace -> skip every other line */ - voffset = 18; + + /* 15kHz, RGB565 */ + PVR_REG_WRITE(dc, PVRREG_DIWMODE, + DIWMODE_COL_RGB565); + + /* video output, PAL/NTSC, interlace */ + PVR_REG_WRITE(dc, PVRREG_SYNCCONF, + SYNCCONF_VO | SYNCCONF_I | SYNCCONF_BC(dc->dc_tvsystem)); } - pvr[0x50/4] = 0; /* video base address, long field */ - pvr[0x54/4] = 640 * 2; /* video base address, short field */ + /* video base address, long field */ + PVR_REG_WRITE(dc, PVRREG_DIWADDRL, 0); - pvr[0x5c/4] = (modulo << 20) | ((display_lines_per_field - 1) << 10) | - (640 * 2 / 4 - 1); + /* video base address, short field */ + PVR_REG_WRITE(dc, PVRREG_DIWADDRS, 640 * 2); - voffset = (voffset << 16) | voffset; + /* video size */ + PVR_REG_WRITE(dc, PVRREG_DIWSIZE, DIWSIZE_MODULO(modulo) | + DIWSIZE_LPF(display_lines_per_field - 1) | + DIWSIZE_DPL(640 * 2 / 4 - 1)); - pvr[0xf0/4] = voffset; /* V start */ - pvr[0xdc/4] = voffset + display_lines_per_field;/* V border */ - pvr[0xec/4] = hoffset; /* H start */ - pvr[0xd8/4] = (v_absolute_size<<16) | h_absolute_size; /* HV counter */ - pvr[0xd4/4] = border; /* H border */ - pvr[0xe8/4] = 22 << 16; + PVR_REG_WRITE(dc, PVRREG_DIWVSTRT, /* V start */ + DIWVSTRT_V1(voffset) | DIWVSTRT_V2(voffset)); + PVR_REG_WRITE(dc, PVRREG_BRDVERT, /* V border */ + BRDVERT_START(vborder_start) | BRDVERT_STOP(vborder_stop)); + PVR_REG_WRITE(dc, PVRREG_DIWHSTRT, hoffset); /* H start */ + PVR_REG_WRITE(dc, PVRREG_SYNCSIZE, /* HV counter */ + SYNCSIZE_V(v_absolute_size) | SYNCSIZE_H(h_absolute_size)); + PVR_REG_WRITE(dc, PVRREG_BRDHORZ, /* H border */ + BRDHORZ_START(hborder_start) | BRDHORZ_STOP(hborder_stop)); + PVR_REG_WRITE(dc, PVRREG_DIWCONF, DIWCONF_MAGIC); /* RGB / composite */ *(__volatile u_int32_t *) SH3_PHYS_TO_P2SEG(0x00702c00) = ((dc->dc_dispflags & PVR_RGBMODE) ? 0 : 3) << 8; - pvr[0x44/4] |= 1; /* display on */ + /* display on */ + PVR_REG_WRITE(dc, PVRREG_DIWMODE, + PVR_REG_READ(dc, PVRREG_DIWMODE) | DIWMODE_DE); } /* Console support. */