From 44e4c53338975c9066987701cb88295c4d3e7a6e Mon Sep 17 00:00:00 2001 From: takemura Date: Sun, 25 Mar 2001 13:06:52 +0000 Subject: [PATCH] Add MQ200_USECRT option, which enables CRT output on MC/R530. This is kernel configuration option and you can't enable and disable CRT dynamically for now. --- sys/arch/hpcmips/conf/GENERIC | 6 +- sys/arch/hpcmips/conf/files.hpcmips | 6 +- sys/arch/hpcmips/dev/mq200.c | 137 ++++--- sys/arch/hpcmips/dev/mq200debug.c | 547 ++++++++++++++++++++++++++++ sys/arch/hpcmips/dev/mq200machdep.c | 233 ++++++++++++ sys/arch/hpcmips/dev/mq200priv.h | 156 ++++++++ sys/arch/hpcmips/dev/mq200reg.h | 28 +- sys/arch/hpcmips/dev/mq200subr.c | 371 +++++++++++++++++++ sys/arch/hpcmips/dev/mq200var.h | 24 +- 9 files changed, 1448 insertions(+), 60 deletions(-) create mode 100644 sys/arch/hpcmips/dev/mq200debug.c create mode 100644 sys/arch/hpcmips/dev/mq200machdep.c create mode 100644 sys/arch/hpcmips/dev/mq200priv.h create mode 100644 sys/arch/hpcmips/dev/mq200subr.c diff --git a/sys/arch/hpcmips/conf/GENERIC b/sys/arch/hpcmips/conf/GENERIC index 672c58bc061a..b2084f4e4ffe 100644 --- a/sys/arch/hpcmips/conf/GENERIC +++ b/sys/arch/hpcmips/conf/GENERIC @@ -2,11 +2,11 @@ # Distribution kernel (NEC VR based model) kernel config file # -# $NetBSD: GENERIC,v 1.82 2001/03/24 15:56:59 sato Exp $ +# $NetBSD: GENERIC,v 1.83 2001/03/25 13:06:52 takemura Exp $ # include "arch/hpcmips/conf/std.hpcmips" -#ident "GENERIC-$Revision: 1.82 $" +#ident "GENERIC-$Revision: 1.83 $" maxusers 8 @@ -127,6 +127,8 @@ vrdsu* at vrip? addr 0x0b0000e0 size 0x08 vrpiu* at vrip? addr 0x0b000120 size 0x1a0 intr 5 vrled* at vrip? addr 0x0b000240 size 0x10 intr 17 +options MQ200_DEBUG +#options MQ200_USECRT mqvideo0 at vrip? addr 0x0a000000 size 0x800000 # MQ200 video controller hpcfb* at mqvideo? diff --git a/sys/arch/hpcmips/conf/files.hpcmips b/sys/arch/hpcmips/conf/files.hpcmips index 78735da88991..c98590ad1b59 100644 --- a/sys/arch/hpcmips/conf/files.hpcmips +++ b/sys/arch/hpcmips/conf/files.hpcmips @@ -1,4 +1,4 @@ -# $NetBSD: files.hpcmips,v 1.52 2001/02/26 09:34:22 sato Exp $ +# $NetBSD: files.hpcmips,v 1.53 2001/03/25 13:06:53 takemura Exp $ # maxpartitions must be first item in files.${ARCH}. maxpartitions 8 @@ -149,10 +149,14 @@ file arch/hpcmips/vr/vrpiu.c vrpiu attach ohci at vrip with ohci_vrip file arch/hpcmips/dev/ohci_vrip.c ohci_vrip +defopt opt_mq200.h MQ200_DEBUG MQ200_USECRT device mqvideo: hpcfbif attach mqvideo at vrip with mqvideo_vrip file arch/hpcmips/vr/mq200_vrip.c mqvideo_vrip file arch/hpcmips/dev/mq200.c mqvideo +file arch/hpcmips/dev/mq200subr.c mqvideo +file arch/hpcmips/dev/mq200debug.c mqvideo +file arch/hpcmips/dev/mq200machdep.c mqvideo device ite8181video: hpcfbif attach ite8181video at vrip with ite8181video_vrip diff --git a/sys/arch/hpcmips/dev/mq200.c b/sys/arch/hpcmips/dev/mq200.c index fdcd598e0d7e..d319f17b1374 100644 --- a/sys/arch/hpcmips/dev/mq200.c +++ b/sys/arch/hpcmips/dev/mq200.c @@ -1,7 +1,7 @@ -/* $NetBSD: mq200.c,v 1.12 2001/03/12 08:54:26 sato Exp $ */ +/* $NetBSD: mq200.c,v 1.13 2001/03/25 13:06:53 takemura Exp $ */ /*- - * Copyright (c) 2000 Takemura Shin + * Copyright (c) 2000, 2001 TAKEMURA Shin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,30 +46,16 @@ #include #include +#include "opt_mq200.h" #include #include +#include + #include "bivideo.h" #if NBIVIDEO > 0 #include #endif -#define MQ200DEBUG -#ifdef MQ200DEBUG -#ifndef MQ200DEBUG_CONF -#define MQ200DEBUG_CONF 0 -#endif -int mq200_debug = MQ200DEBUG_CONF; -#define DPRINTF(arg) do { if (mq200_debug) printf arg; } while(0); -#define DPRINTFN(n, arg) do { if (mq200_debug > (n)) printf arg; } while (0); -#define VPRINTF(arg) do { if (bootverbose || mq200_debug) printf arg; } while(0); -#define VPRINTFN(n, arg) do { if (bootverbose || mq200_debug > (n)) printf arg; } while (0); -#else -#define DPRINTF(arg) do { } while (0); -#define DPRINTFN(n, arg) do { } while (0); -#define VPRINTF(arg) do { if (bootverbose) printf arg; } while(0); -#define VPRINTFN(n, arg) do { if (bootverbose) printf arg; } while (0); -#endif - /* * function prototypes */ @@ -92,6 +78,10 @@ struct hpcfb_accessops mq200_ha = { mq200_ioctl, mq200_mmap }; +#ifdef MQ200_DEBUG +int mq200_debug = MQ200DEBUG_CONF; +#endif + int mq200_probe(iot, ioh) bus_space_tag_t iot; @@ -105,8 +95,8 @@ mq200_probe(iot, ioh) #endif /* NBIVIDEO > 0 */ regval = bus_space_read_4(iot, ioh, MQ200_PC00R); - VPRINTF(("mq200 probe: vendor id=%04lx product id=%04lx\n", - regval & 0xffff, (regval >> 16) & 0xffff)); + VPRINTF("probe: vendor id=%04lx product id=%04lx\n", + regval & 0xffff, (regval >> 16) & 0xffff); if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID)) return (0); @@ -130,10 +120,10 @@ mq200_attach(sc) sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr; sc->sc_fbconf.hf_offset = (u_long)sc->sc_fbconf.hf_baseaddr - MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr))); - DPRINTF(("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr)); - DPRINTF(("hf_offset=%lx\n", sc->sc_fbconf.hf_offset)); + DPRINTF("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr); + DPRINTF("hf_offset=%lx\n", sc->sc_fbconf.hf_offset); - regval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_PC08R); + regval = mq200_read(sc, MQ200_PC08R); printf("MQ200 Rev.%02lx video controller", regval & 0xff); if (console) { printf(", console"); @@ -141,6 +131,57 @@ mq200_attach(sc) printf("\n"); printf("%s: framebuffer address: 0x%08lx\n", sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr); + + /* + * setup registers + */ + sc->sc_flags = 0; + sc->sc_baseclock = 12288; /* 12.288 MHz */ +#ifdef MQ200_DEBUG + if (bootverbose) { + /* dump current setting */ + mq200_dump_all(sc); + mq200_dump_pll(sc); + } +#endif + mq200_setup_regctx(sc); + mq200_mdsetup(sc); + if (sc->sc_md) { + if (sc->sc_md->md_flags & MQ200_MD_HAVEFP) { + sc->sc_flags |= MQ200_SC_GC2_ENABLE; /* FP */ + } +#if MQ200_USECRT + if (sc->sc_md->md_flags & MQ200_MD_HAVECRT) { + int i; + sc->sc_flags |= MQ200_SC_GC1_ENABLE; /* CRT */ + for (i = 0; i < mq200_crt_nparams; i++) { + sc->sc_crt = &mq200_crt_params[i]; + if (sc->sc_md->md_fp_width <= + mq200_crt_params[i].width && + sc->sc_md->md_fp_height <= + mq200_crt_params[i].height) + break; + } + } +#endif + mq200_setup(sc); + + if (sc->sc_flags & MQ200_SC_GC2_ENABLE) /* FP */ + mq200_win_enable(sc, MQ200_GC2, MQ200_GCC_16BPP_DIRECT, + 0x00080100, + sc->sc_md->md_fp_width, sc->sc_md->md_fp_height, + 1280); + if (sc->sc_flags & MQ200_SC_GC1_ENABLE) /* CRT */ + mq200_win_enable(sc, MQ200_GC1, MQ200_GCC_16BPP_DIRECT, + 0x00080100, + sc->sc_md->md_fp_width, sc->sc_md->md_fp_height, + 1280); + } +#ifdef MQ200_DEBUG + if (sc->sc_md == NULL || bootverbose) { + mq200_dump_pll(sc); + } +#endif /* Add a power hook to power saving */ sc->sc_mq200pwstate = MQ200_POWERSTATE_D0; @@ -462,7 +503,7 @@ mq200_ioctl(v, cmd, data, flag, p) dispparam = (struct wsdisplay_param*)data; switch (dispparam->param) { case WSDISPLAYIO_PARAM_BACKLIGHT: - VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT call\n")); + VPRINTF("ioctl: GETPARAM:BACKLIGHT call\n"); if (sc->sc_max_brightness == -1) mq200_init_brightness(sc); mq200_get_backlight(sc); @@ -473,37 +514,37 @@ mq200_ioctl(v, cmd, data, flag, p) else dispparam->curval = (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1 : 0; - VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT:%d\n", - dispparam->curval)); + VPRINTF("ioctl: GETPARAM:BACKLIGHT:%d\n", + dispparam->curval); return 0; break; case WSDISPLAYIO_PARAM_CONTRAST: - VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST call\n")); + VPRINTF("ioctl: GETPARAM:CONTRAST call\n"); if (sc->sc_max_contrast == -1) mq200_init_contrast(sc); if (sc->sc_max_contrast > 0) { dispparam->min = 0; dispparam->max = sc->sc_max_contrast; dispparam->curval = sc->sc_contrast; - VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast)); + VPRINTF("ioctl: GETPARAM:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast); return 0; } else { - VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST ret\n")); + VPRINTF("ioctl: GETPARAM:CONTRAST ret\n"); return (EINVAL); } break; case WSDISPLAYIO_PARAM_BRIGHTNESS: - VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS call\n")); + VPRINTF("ioctl: GETPARAM:BRIGHTNESS call\n"); if (sc->sc_max_brightness == -1) mq200_init_brightness(sc); if (sc->sc_max_brightness > 0) { dispparam->min = 0; dispparam->max = sc->sc_max_brightness; dispparam->curval = sc->sc_brightness; - VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness)); + VPRINTF("ioctl: GETPARAM:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness); return 0; } else { - VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS ret\n")); + VPRINTF("ioctl: GETPARAM:BRIGHTNESS ret\n"); return (EINVAL); } return (EINVAL); @@ -516,13 +557,13 @@ mq200_ioctl(v, cmd, data, flag, p) dispparam = (struct wsdisplay_param*)data; switch (dispparam->param) { case WSDISPLAYIO_PARAM_BACKLIGHT: - VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT call\n")); + VPRINTF("ioctl: SETPARAM:BACKLIGHT call\n"); if (dispparam->curval < 0 || 1 < dispparam->curval) return (EINVAL); if (sc->sc_max_brightness == -1) mq200_init_brightness(sc); - VPRINTF(("mq200_ioctl: SETPARAM:max brightness=%d\n", sc->sc_max_brightness)); + VPRINTF("ioctl: SETPARAM:max brightness=%d\n", sc->sc_max_brightness); if (sc->sc_max_brightness > 0) { /* dimmer */ if (dispparam->curval == 0){ sc->sc_brightness_save = sc->sc_brightness; @@ -532,22 +573,22 @@ mq200_ioctl(v, cmd, data, flag, p) sc->sc_brightness_save = sc->sc_max_brightness; mq200_set_brightness(sc, sc->sc_brightness_save); } - VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: brightness=%d\n", sc->sc_brightness)); + VPRINTF("ioctl: SETPARAM:BACKLIGHT: brightness=%d\n", sc->sc_brightness); } else { /* off */ if (dispparam->curval == 0) sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT; else sc->sc_powerstate |= PWRSTAT_BACKLIGHT; - VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: powerstate %d\n", - (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); + VPRINTF("ioctl: SETPARAM:BACKLIGHT: powerstate %d\n", + (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0); mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT); - VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT:%d\n", - (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0)); + VPRINTF("ioctl: SETPARAM:BACKLIGHT:%d\n", + (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0); } return 0; break; case WSDISPLAYIO_PARAM_CONTRAST: - VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST call\n")); + VPRINTF("ioctl: SETPARAM:CONTRAST call\n"); if (sc->sc_max_contrast == -1) mq200_init_contrast(sc); if (dispparam->curval < 0 || @@ -556,15 +597,15 @@ mq200_ioctl(v, cmd, data, flag, p) if (sc->sc_max_contrast > 0) { int org = sc->sc_contrast; mq200_set_contrast(sc, dispparam->curval); - VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast)); + VPRINTF("ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast); return 0; } else { - VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST ret\n")); + VPRINTF("ioctl: SETPARAM:CONTRAST ret\n"); return (EINVAL); } break; case WSDISPLAYIO_PARAM_BRIGHTNESS: - VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS call\n")); + VPRINTF("ioctl: SETPARAM:BRIGHTNESS call\n"); if (sc->sc_max_brightness == -1) mq200_init_brightness(sc); if (dispparam->curval < 0 || @@ -573,10 +614,10 @@ mq200_ioctl(v, cmd, data, flag, p) if (sc->sc_max_brightness > 0) { int org = sc->sc_brightness; mq200_set_brightness(sc, dispparam->curval); - VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness)); + VPRINTF("ioctl: SETPARAM:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness); return 0; } else { - VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS ret\n")); + VPRINTF("ioctl: SETPARAM:BRIGHTNESS ret\n"); return (EINVAL); } break; @@ -674,7 +715,7 @@ mq200_init_brightness(sc) { int val = -1; - VPRINTF(("mq200_init_brightness\n")); + VPRINTF("init_brightness\n"); if (config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, &val) != -1) { sc->sc_brightness_save = sc->sc_brightness = val; @@ -694,7 +735,7 @@ mq200_init_contrast(sc) { int val = -1; - VPRINTF(("mq200_init_contrast\n")); + VPRINTF("init_contrast\n"); if (config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, &val) != -1) { sc->sc_contrast = val; diff --git a/sys/arch/hpcmips/dev/mq200debug.c b/sys/arch/hpcmips/dev/mq200debug.c new file mode 100644 index 000000000000..e73e31f9d30a --- /dev/null +++ b/sys/arch/hpcmips/dev/mq200debug.c @@ -0,0 +1,547 @@ +/* $NetBSD: mq200debug.c,v 1.1 2001/03/25 13:06:53 takemura Exp $ */ + +/*- + * Copyright (c) 2001 TAKEMURA Shin + * 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. + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + */ + +#ifdef _KERNEL +#include +#include +#include +#include +#else +#include +#endif +#include + +#include +#include + +#include "opt_mq200.h" +#include "mq200var.h" +#include "mq200reg.h" +#include "mq200priv.h" + +#define ENABLE(b) ((b)?"enable":"disable") + +#ifdef MQ200_DEBUG + +char *mq200_clknames[] = { "BUS", "PLL1", "PLL2", "PLL3" }; + +void +mq200_dump_pll(struct mq200_softc *sc) +{ + int n, m; + u_int32_t reg, pm00r; + int clocks[4]; + int memclock, geclock; + static char *clknames[] = { "BUS", "PLL1", "PLL2", "PLL3" }; + static char *fd_names[] = { "1", "1.5", "2.5", "3.5", "4.5", "5.5", "6.5" }; + static int fd_vals[] = { 10, 15, 25, 35, 45, 55, 65 }; +#define FIXEDFLOAT1000(a) (a)/1000, (a)%1000 + + /* PM00R */ + pm00r = mq200_read(sc, MQ200_PMCR); + geclock = (pm00r&MQ200_PMC_GE_CLK_MASK)>>MQ200_PMC_GE_CLK_SHIFT; + + /* MM01R */ + reg = mq200_read(sc, MQ200_MMR(1)); + memclock = (reg & MQ200_MM01_CLK_PLL2) ? 2 : 1; + + /* bus clock */ + clocks[0] = 0; + + /* PLL1 */ + reg = mq200_read(sc, MQ200_DCMISCR); + m = ((reg & MQ200_PLL_M_MASK) >> MQ200_PLL_M_SHIFT) + 1; + n = ((((reg & MQ200_PLL_N_MASK) >> MQ200_PLL_N_SHIFT) + 1) | + ((pm00r & MQ200_PMC_PLL1_N) << MQ200_PMC_PLL1_N_SHIFT)); + n <<= ((reg & MQ200_PLL_P_MASK) >> MQ200_PLL_P_SHIFT); + printf(" PLL1:%3d.%03dMHz(0x%08x, %d.%03dMHzx%3d/%3d)\n", + FIXEDFLOAT1000(sc->sc_baseclock*m/n), + reg, FIXEDFLOAT1000(sc->sc_baseclock), m, n); + clocks[1] = sc->sc_baseclock*m/n; + + /* PLL2 */ + if (pm00r & MQ200_PMC_PLL2_ENABLE) { + reg = mq200_read(sc, MQ200_PLL2R); + m = ((reg & MQ200_PLL_M_MASK) >> MQ200_PLL_M_SHIFT) + 1; + n = ((((reg & MQ200_PLL_N_MASK) >> MQ200_PLL_N_SHIFT) +1) << + ((reg & MQ200_PLL_P_MASK) >> MQ200_PLL_P_SHIFT)); + clocks[2] = sc->sc_baseclock*m/n; + printf(" PLL2:%3d.%03dMHz(0x%08x, %d.%03dMHzx%3d/%3d)\n", + FIXEDFLOAT1000(sc->sc_baseclock*m/n), + reg, FIXEDFLOAT1000(sc->sc_baseclock), m, n); + } else { + printf(" PLL2: disable\n"); + clocks[2] = 0; + } + + /* PLL3 */ + if (pm00r & MQ200_PMC_PLL3_ENABLE) { + reg = mq200_read(sc, MQ200_PLL3R); + m = (((reg & MQ200_PLL_M_MASK) >> MQ200_PLL_M_SHIFT) + 1); + n = ((((reg & MQ200_PLL_N_MASK) >> MQ200_PLL_N_SHIFT) + 1) << + ((reg & MQ200_PLL_P_MASK) >> MQ200_PLL_P_SHIFT)); + clocks[3] = sc->sc_baseclock*m/n; + printf(" PLL3:%3d.%03dMHz(0x%08x, %d.%03dMHzx%3d/%3d)\n", + FIXEDFLOAT1000(sc->sc_baseclock*m/n), + reg, FIXEDFLOAT1000(sc->sc_baseclock), m, n); + } else { + printf(" PLL3: disable\n"); + clocks[3] = 0; + } + + printf(" MEM:%3d.%03dMHz(%s)\n", + FIXEDFLOAT1000(clocks[memclock]), + clknames[memclock]); + printf(" GE:%3d.%03dMHz(%s)\n", + FIXEDFLOAT1000(clocks[geclock]), + clknames[geclock]); + + /* GC1 */ + reg = mq200_read(sc, MQ200_GCCR(MQ200_GC1)); + if (reg & MQ200_GCC_ENABLE) { + int fd, sd, rc; + rc = (reg&MQ200_GCC_RCLK_MASK)>>MQ200_GCC_RCLK_SHIFT; + fd = (reg&MQ200_GCC_MCLK_FD_MASK)>>MQ200_GCC_MCLK_FD_SHIFT; + sd = (reg&MQ200_GCC_MCLK_SD_MASK)>>MQ200_GCC_MCLK_SD_SHIFT; + printf(" GC1:%3d.%03dMHz(%s/%s/%d)", + FIXEDFLOAT1000(clocks[rc]*10/fd_vals[fd]/sd), + clknames[rc], fd_names[fd], sd); + /* GC01R */ + reg = mq200_read(sc, MQ200_GC1CRTCR); + if (reg&MQ200_GC1CRTC_DACEN) + printf(", CRT"); + reg = mq200_read(sc, MQ200_FPCR); + if ((reg & MQ200_FPC_ENABLE) && !(reg & MQ200_FPC_GC2)) + printf(", LCD"); + printf("\n"); + } else { + printf(" GC1: disable\n"); + } + + /* GC2 */ + reg = mq200_read(sc, MQ200_GCCR(MQ200_GC2)); + if (reg & MQ200_GCC_ENABLE) { + int fd, sd, rc; + rc = (reg&MQ200_GCC_RCLK_MASK)>>MQ200_GCC_RCLK_SHIFT; + fd = (reg&MQ200_GCC_MCLK_FD_MASK)>>MQ200_GCC_MCLK_FD_SHIFT; + sd = (reg&MQ200_GCC_MCLK_SD_MASK)>>MQ200_GCC_MCLK_SD_SHIFT; + printf(" GC2:%3d.%03dMHz(%s/%s/%d)", + FIXEDFLOAT1000(clocks[rc]*10/fd_vals[fd]/sd), + clknames[rc], fd_names[fd], sd); + reg = mq200_read(sc, MQ200_FPCR); + if ((reg & MQ200_FPC_ENABLE) && (reg & MQ200_FPC_GC2)) + printf(", FP"); + printf("\n"); + } else { + printf(" GC2: disable\n"); + } +} + +struct { + char *name; + u_int32_t base; + int start, end; +} regs[] = { + { "GC", MQ200_GCR(0), 0x00, 0x13 }, + { "GC", MQ200_GCR(0), 0x20, 0x33 }, + { "FP", MQ200_FP, 0x00, 0x0f }, + { "CC", MQ200_CC, 0x00, 0x01 }, + { "PC", MQ200_PC, 0x00, 0x05 }, + { "MM", MQ200_MM, 0x00, 0x04 }, + { "DC", MQ200_DC, 0x00, 0x03 }, + { "PM", MQ200_PM, 0x00, 0x03 }, + { "PM", MQ200_PM, 0x06, 0x07 }, + { "IN", MQ200_IN, 0x00, 0x03 }, +}; + +char * +mq200_regname(struct mq200_softc *sc, int offset, char *buf, int bufsize) +{ + int i; + + for (i = 0; i < sizeof(regs)/sizeof(*regs); i++) + if (regs[i].base + regs[i].start * 4 <= offset && + offset <= regs[i].base + regs[i].end * 4) { + sprintf(buf, "%s%02XR", regs[i].name, + (offset - regs[i].base) / 4); + return (buf); + } + sprintf(buf, "OFFSET %02X", offset); + return (buf); +} + +void +mq200_dump_all(struct mq200_softc *sc) +{ + int i, j; + + for (i = 0; i < sizeof(regs)/sizeof(*regs); i++) + for (j = regs[i].start; j <= regs[i].end; j++) + printf("%s%02XR: %08x\n", + regs[i].name, j, + mq200_read(sc, regs[i].base + (j * 4))); +} + +void +mq200_write(struct mq200_softc *sc, int offset, u_int32_t data) +{ + int i; + char buf[32]; + + for (i = 0; i < MQ200_I_MAX; i++) { + if (sc->sc_regctxs[i].offset == offset) + printf("mq200_write: WARNING: raw access %s\n", + mq200_regname(sc, offset, buf, sizeof(buf))); + } + + mq200_writex(sc, offset, data); +} + +#if 0 +void +mq200_dump_gc(struct mq200_softc *sc, int gc) +{ + u_int32_t reg; + char *depth_names[] = { + "1bpp with CLUT", + "2bpp with CLUT", + "4bpp with CLUT", + "8bpp with CLUT", + "16bpp with CLUT", + "24bpp with CLUT", + "32bpp(RGB) with CLUT", + "32bpp(BGR) with CLUT", + "1bpp w/o CLUT", + "2bpp w/o CLUT", + "4bpp w/o CLUT", + "8bpp w/o CLUT", + "16bpp w/o CLUT", + "24bpp w/o CLUT", + "32bpp(RGB) w/o CLUT", + "32bpp(BGR) w/o CLUT", + }; + char *rc_names[] = { "BUS", "PLL1", "PLL2", "PLL3" }; + char *fd_names[] = { "1", "1.5", "2.5", "3.5", "4.5", "5.5", "6.5" }; + + /* + * GC00R Graphics Controller Control + */ + reg = mq200_read(sc, MQ200_GCCR(gc)); + printf("GC00R=0x%08x: ", reg); + printf("%s %s%s%s%s%s\n", + ENABLE(reg & MQ200_GCC_ENABLE), + (reg & MQ200_GCC_HCRESET)?"HC_reset ":"", + (reg & MQ200_GCC_VCRESET)?"VC_reset ":"", + (reg & MQ200_GCC_HCEN)?"cursor_enable ":"", + (reg & MQ200_GCC_TESTMODE0)?"test_mode0 ":"", + (reg & MQ200_GCC_TESTMODE1)?"test_mode1 ":""); + printf(" window: %s %s\n", + ENABLE(reg & MQ200_GCC_WINEN), + depth_names[(reg&MQ200_GCC_DEPTH_MASK)>>MQ200_GCC_DEPTH_SHIFT]); + printf(" altwin: %s %s\n", + ENABLE(reg & MQ200_GCC_ALTEN), + depth_names[(reg&MQ200_GCC_ALTDEPTH_MASK)>>MQ200_GCC_ALTDEPTH_SHIFT]); + printf(" clock: root_clock/first_div/second_div = %s/%s/%d\n", + rc_names[(reg&MQ200_GCC_RCLK_MASK)>>MQ200_GCC_RCLK_SHIFT], + fd_names[(reg&MQ200_GCC_MCLK_FD_MASK)>>MQ200_GCC_MCLK_FD_SHIFT], + (reg&MQ200_GCC_MCLK_SD_MASK)>>MQ200_GCC_MCLK_SD_SHIFT); + + if (gc == 0) { + /* + * GC01R Graphics Controller CRT Control + */ + reg = mq200_read(sc, MQ200_GC1CRTCR); + printf("GC01R=0x%08x:\n", reg); + printf(" CRT DAC: %s\n", + ENABLE(reg&MQ200_GC1CRTC_DACEN)); + + printf(" power down mode: H-sync="); + switch (reg & MQ200_GC1CRTC_HSYNC_PMMASK) { + case MQ200_GC1CRTC_HSYNC_PMNORMAL: + if (reg & MQ200_GC1CRTC_HSYNC_PMCLK) + printf("PMCLK"); + else + printf("LOW"); + break; + case MQ200_GC1CRTC_HSYNC_PMLOW: + printf("LOW"); + break; + case MQ200_GC1CRTC_HSYNC_PMHIGH: + printf("HIGH"); + break; + default: + printf("???"); + break; + } + + printf(" V-sync="); + switch (reg & MQ200_GC1CRTC_VSYNC_PMMASK) { + case MQ200_GC1CRTC_VSYNC_PMNORMAL: + if (reg & MQ200_GC1CRTC_VSYNC_PMCLK) + printf("PMCLK"); + else + printf("LOW"); + break; + case MQ200_GC1CRTC_VSYNC_PMLOW: + printf("LOW"); + break; + case MQ200_GC1CRTC_VSYNC_PMHIGH: + printf("HIGH"); + break; + default: + printf("???"); + break; + } + printf("\n"); + + printf(" sync active: H=%s V=%s\n", + (reg & MQ200_GC1CRTC_HSYNC_ACTVLOW)?"low":"high", + (reg & MQ200_GC1CRTC_VSYNC_ACTVLOW)?"low":"high"); + printf(" other: "); + if (reg & MQ200_GC1CRTC_SYNC_PEDESTAL_EN) + printf("Sync_pedestal "); + if (reg & MQ200_GC1CRTC_BLANK_PEDESTAL_EN) + printf("Blank_pedestal "); + if (reg & MQ200_GC1CRTC_COMPOSITE_SYNC_EN) + printf("Conposite_sync "); + if (reg & MQ200_GC1CRTC_VREF_EXTR) + printf("External_VREF "); + if (reg & MQ200_GC1CRTC_MONITOR_SENCE_EN) { + if (reg & MQ200_GC1CRTC_CONSTANT_OUTPUT_EN) + printf("Monitor_sence=%s%s%s/- ", + (reg & MQ200_GC1CRTC_BLUE_NOTLOADED)?"":"B", + (reg & MQ200_GC1CRTC_RED_NOTLOADED)?"":"R", + (reg & MQ200_GC1CRTC_GREEN_NOTLOADED)?"":"G"); + else + printf("Monitor_sence=%s%s%s/0x%02x ", + (reg & MQ200_GC1CRTC_BLUE_NOTLOADED)?"":"B", + (reg & MQ200_GC1CRTC_RED_NOTLOADED)?"":"R", + (reg & MQ200_GC1CRTC_GREEN_NOTLOADED)?"":"G", + (reg & MQ200_GC1CRTC_OUTPUT_LEVEL_MASK)>>MQ200_GC1CRTC_OUTPUT_LEVEL_SHIFT); + } + if (reg & MQ200_GC1CRTC_MONO) + printf("Mono_monitor "); + printf("\n"); + } + + /* + * GC02R Horizontal Display Control + */ + reg = mq200_read(sc, MQ200_GCHDCR(gc)); + if (gc == 0) { + printf("GC02R=0x%08x: Horizontal display total=%03d end=%03d\n", reg, + (reg&MQ200_GC1HDC_TOTAL_MASK)>>MQ200_GC1HDC_TOTAL_SHIFT, + (reg&MQ200_GCHDC_END_MASK)>>MQ200_GCHDC_END_SHIFT); + } else { + printf("GC02R=0x%08x: Horizontal display end=%03d\n", reg, + (reg&MQ200_GCHDC_END_MASK)>>MQ200_GCHDC_END_SHIFT); + } + + /* + * GC03R Vertical Display Control + */ + reg = mq200_read(sc, MQ200_GCVDCR(gc)); + if (gc == 0) { + printf("GC03R=0x%08x: Vertical display total=%03d end=%03d\n", reg, + (reg&MQ200_GC1VDC_TOTAL_MASK)>>MQ200_GC1VDC_TOTAL_SHIFT, + (reg&MQ200_GCVDC_END_MASK)>>MQ200_GCVDC_END_SHIFT); + } else { + printf("GC03R=0x%08x: Vertical display end=%03d\n", reg, + (reg&MQ200_GCVDC_END_MASK)>>MQ200_GCVDC_END_SHIFT); + } + + /* + * GC04R Horizontal Sync Control + */ + reg = mq200_read(sc, MQ200_GCHSCR(gc)); + printf("GC04R=0x%08x: Horizontal sync start=%03d end=%03d\n", reg, + (reg&MQ200_GCHSC_START_MASK)>>MQ200_GCHSC_START_SHIFT, + (reg&MQ200_GCHSC_END_MASK)>>MQ200_GCHSC_END_SHIFT); + + /* + * GC05R Vertical Sync Control + */ + reg = mq200_read(sc, MQ200_GCVSCR(gc)); + printf("GC05R=0x%08x: Vertical sync start=%03d end=%03d\n", reg, + (reg&MQ200_GCVSC_START_MASK)>>MQ200_GCVSC_START_SHIFT, + (reg&MQ200_GCVSC_END_MASK)>>MQ200_GCVSC_END_SHIFT); + + if (gc == 0) { + /* + * GC07R Vertical Display Count + */ + reg = mq200_read(sc, MQ200_GC1VDCNTR); + printf("GC07R=0x%08x: Vertical Display Count=%d\n", reg, + (reg&MQ200_GC1VDCNT_MASK)); + } + + /* + * GC08R Window Horizontal Control + */ + reg = mq200_read(sc, MQ200_GCWHCR(gc)); + printf("GC08R=0x%08x: Window Horizontal start=%03d width=%03d", + reg, + (reg&MQ200_GCWHC_START_MASK)>> MQ200_GCWHC_START_SHIFT, + (reg&MQ200_GCWHC_WIDTH_MASK)>> MQ200_GCWHC_WIDTH_SHIFT); + if (gc == 0) { + printf(" add=%03x", + (reg&MQ200_GC1WHC_ALD_MASK)>> MQ200_GC1WHC_ALD_SHIFT); + } + printf("\n"); + + /* + * GC09R Window Vertical Control + */ + reg = mq200_read(sc, MQ200_GCWVCR(gc)); + printf("GC09R=0x%08x: Window Vertical start=%03d hight=%03d\n", + reg, + (reg&MQ200_GCWVC_START_MASK)>> MQ200_GCWVC_START_SHIFT, + (reg&MQ200_GCWVC_HEIGHT_MASK)>> MQ200_GCWVC_HEIGHT_SHIFT); + + /* + * GC0AR Alternate Window Horizontal Control + */ + reg = mq200_read(sc, MQ200_GCAWHCR(gc)); + printf("GC0AR=0x%08x: Altwin Horizontal start=%03d width=%03d", + reg, + (reg&MQ200_GCAWHC_START_MASK)>> MQ200_GCAWHC_START_SHIFT, + (reg&MQ200_GCAWHC_WIDTH_MASK)>> MQ200_GCAWHC_WIDTH_SHIFT); + if (gc == 0) { + printf(" add=%03d", + (reg&MQ200_GC1AWHC_ALD_MASK)>> MQ200_GC1AWHC_ALD_SHIFT); + } + printf("\n"); + + /* + * GC0BR Alternate Window Vertical Control + */ + reg = mq200_read(sc, MQ200_GCAWVCR(gc)); + printf("GC0BR=0x%08x: Altwin Vertical start=%03d hight=%03d\n", + reg, + (reg&MQ200_GCAWVC_START_MASK)>> MQ200_GCAWVC_START_SHIFT, + (reg&MQ200_GCAWVC_HEIGHT_MASK)>> MQ200_GCAWVC_HEIGHT_SHIFT); + + /* + * GC0CR Window Start Address + */ + reg = mq200_read(sc, MQ200_GCWSAR(gc)); + printf("GC0CR=0x%08x: Window start address=0x%08x\n", + reg, (reg&MQ200_GCWSA_MASK)); + + /* + * GC0DR Alternate Window Start Address + */ + reg = mq200_read(sc, MQ200_GCAWSAR(gc)); + printf("GC0DR=0x%08x: Altwin start address=0x%08x palette_index=%02d\n", + reg, (reg&MQ200_GCAWSA_MASK), + (reg&MQ200_GCAWPI_MASK)>>MQ200_GCAWPI_SHIFT); + + /* + * GC0ER Windows Stride + */ + reg = mq200_read(sc, MQ200_GCWSTR(gc)); + printf("GC0ER=0x%08x: Stride window=%04d altwin=%04d\n", + reg, + (reg&MQ200_GCWST_MASK)>>MQ200_GCWST_SHIFT, + (reg&MQ200_GCAWST_MASK)>>MQ200_GCAWST_SHIFT); + + /* + * GC10R Hardware Cursor Position + */ + reg = mq200_read(sc, MQ200_GCHCPR(gc)); + printf("GC10R=0x%08x: Hardware Cursor Position %d,%d\n", + reg, + (reg&MQ200_GCHCP_HSTART_MASK)>>MQ200_GCHCP_HSTART_SHIFT, + (reg&MQ200_GCHCP_VSTART_MASK)>>MQ200_GCHCP_VSTART_SHIFT); + + /* + * GC11R Hardware Cursor Start Address and Offset + */ + reg = mq200_read(sc, MQ200_GCHCAOR(gc)); + printf("GC11R=0x%08x: Hardware Cursor Start Address and Offset\n", + reg); + + /* + * GC12R Hardware Cursor Foreground Color + */ + reg = mq200_read(sc, MQ200_GCHCFCR(gc)); + printf("GC12R=0x%08x: Hardware Cursor Foreground Color\n", reg); + + /* + * GC13R Hardware Cursor Background Color + */ + reg = mq200_read(sc, MQ200_GCHCBCR(gc)); + printf("GC13R=0x%08x: Hardware Cursor Background Color\n", reg); + +} + +void +mq200_dump_fp(struct mq200_softc *sc) +{ + u_int32_t reg; +#define I(type) ((type)>>MQ200_FPC_TYPE_SHIFT) + static char *panel_type_names[64] = { + [I(MQ200_FPC_TFT4MONO)] = "TFT 4bit mono", + [I(MQ200_FPC_TFT12)] = "TFT 12bit color", + [I(MQ200_FPC_SSTN4)] = "S-STN 4bit color", + [I(MQ200_FPC_DSTN8)] = "D-STN 8bit color", + [I(MQ200_FPC_TFT6MONO)] = "TFT 6bit mono", + [I(MQ200_FPC_TFT18)] = "TFT 18bit color", + [I(MQ200_FPC_SSTN8)] = "S-STN 8bit color", + [I(MQ200_FPC_DSTN16)] = "D-STN 16bit color", + [I(MQ200_FPC_TFT8MONO)] = "TFT 8bit mono", + [I(MQ200_FPC_TFT24)] = "TFT 24bit color", + [I(MQ200_FPC_SSTN12)] = "S-STN 12bit color", + [I(MQ200_FPC_DSTN24)] = "D-STN 24bit color", + [I(MQ200_FPC_SSTN16)] = "S-STN 16bit color", + [I(MQ200_FPC_SSTN24)] = "S-STN 24bit color", + }; + + reg = mq200_read(sc, MQ200_FPCR); + printf("FP00R=0x%08x: Flat Panel Control\n", reg); + printf(" %s, driven by %s, %s\n", + ENABLE(reg & MQ200_FPC_ENABLE), + (reg & MQ200_FPC_GC2) ? "GC2" : "GC1", + panel_type_names[(reg & MQ200_FPC_TYPE_MASK) >> MQ200_FPC_TYPE_SHIFT]); + reg = mq200_read(sc, MQ200_FPPCR); + printf("FP01R=0x%08x: Flat Panel Output Pin Control\n", reg); +} + +void +mq200_dump_dc(struct mq200_softc *sc) +{ + u_int32_t reg; + + reg = 0; +} +#endif /* 0 */ + +#endif /* MQ200_DEBUG */ diff --git a/sys/arch/hpcmips/dev/mq200machdep.c b/sys/arch/hpcmips/dev/mq200machdep.c new file mode 100644 index 000000000000..b7d8bec6a8ce --- /dev/null +++ b/sys/arch/hpcmips/dev/mq200machdep.c @@ -0,0 +1,233 @@ +/* $NetBSD: mq200machdep.c,v 1.1 2001/03/25 13:06:53 takemura Exp $ */ + +/*- + * Copyright (c) 2001 TAKEMURA Shin + * 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. + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + */ + +#ifdef _KERNEL +#include +#include +#include +#include +#else +#include +#endif +#include + +#include +#include + +#include "opt_mq200.h" +#include "mq200var.h" +#include "mq200reg.h" +#include "mq200priv.h" + +#if MQ200_SETUPREGS +#define OP_(n) (((n) << 2) | 1) +#define OP_END OP_(1) +#define OP_MASK OP_(2) +#define OP_LOADPLLPARAM OP_(3) +#define OP_LOADFROMREG OP_(4) +#define OP_STORETOREG OP_(5) +#define OP_LOADIMM OP_(6) +#define OP_OR OP_(7) + +static void mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops); + +static u_int32_t mcr530_init_ops[] = { + MQ200_PMCR, 0, /* power management control */ + MQ200_DCMISCR, MQ200_DCMISC_OSC_ENABLE | + MQ200_DCMISC_FASTPOWSEQ_DISABLE | + MQ200_DCMISC_OSCFREQ_12_25, + OP_END +}; +#endif /* MQ200_SETUPREGS */ + +static struct mq200_clock_setting mcr530_clocks[] = { + /* CRT: off FP: off */ + { + MQ200_CLOCK_PLL1, /* memory clock */ + MQ200_CLOCK_PLL1, /* graphics engine clock */ + { + 0, /* GC1(CRT) clock */ + 0, /* GC2(FP) clock */ + }, + 30000, /* PLL1 30MHz */ + 0, /* PLL2 disable */ + 0, /* PLL3 disable */ + }, + /* CRT: on FP: off */ + { + MQ200_CLOCK_PLL1, /* memory clock */ + MQ200_CLOCK_PLL2, /* graphics engine clock */ + { + MQ200_CLOCK_PLL3, /* GC1(CRT) clock */ + 0, /* GC2(FP) clock */ + }, + 83000, /* PLL1 83MHz */ + 30000, /* PLL2 30MHz */ + -1, /* PLL3 will be set by GC1 */ + }, + /* CRT: off FP: on */ + { + MQ200_CLOCK_PLL1, /* memory clock */ + MQ200_CLOCK_PLL2, /* graphics engine clock */ + { + 0, /* GC1(CRT) clock */ + MQ200_CLOCK_PLL2, /* GC2(FP) clock */ + }, + 30000, /* PLL1 30MHz */ + 18800, /* PLL2 18.8MHz */ + 0, /* PLL3 disable */ + }, + /* CRT: on FP: on */ + { + MQ200_CLOCK_PLL1, /* memory clock */ + MQ200_CLOCK_PLL2, /* graphics engine clock */ + { + MQ200_CLOCK_PLL3, /* GC1(CRT) clock */ + MQ200_CLOCK_PLL2, /* GC2(FP) clock */ + }, + 83000, /* PLL1 83MHz */ + 18800, /* PLL2 18.8MHz */ + -1, /* PLL3 will be set by GC1 */ + }, +}; + +static struct mq200_md_param machdep_params[] = { + { + &platid_mask_MACH_NEC_MCR_530, + 640, 240, /* flat panel size */ + 12288, /* base clock is 12.288 MHz */ + MQ200_MD_HAVECRT | MQ200_MD_HAVEFP, +#if MQ200_SETUPREGS + mcr530_init_ops, +#else + NULL, +#endif /* MQ200_SETUPREGS */ + mcr530_clocks, + /* DCMISC */ + MQ200_DCMISC_OSC_ENABLE | + MQ200_DCMISC_FASTPOWSEQ_DISABLE | + MQ200_DCMISC_OSCFREQ_12_25, + /* PMC */ + 0, + /* MM01 */ + MQ200_MM01_DRAM_AUTO_REFRESH_EN | + MQ200_MM01_GE_PB_EN | + MQ200_MM01_CPU_PB_EN | + MQ200_MM01_SLOW_REFRESH_EN | + (0x143e << MQ200_MM01_REFRESH_SHIFT), + }, +}; + +void +mq200_mdsetup(struct mq200_softc *sc) +{ + const struct mq200_md_param *mdp; + + sc->sc_md = NULL; + for (mdp = machdep_params; mdp->md_platform != NULL; mdp++) { + platid_mask_t mask; + mask = PLATID_DEREF(mdp->md_platform); + if (platid_match(&platid, &mask)) { + sc->sc_md = mdp; + break; + } + } + + if (sc->sc_md) { + sc->sc_width[MQ200_GC2] = mdp->md_fp_width; + sc->sc_height[MQ200_GC2] = mdp->md_fp_height; + sc->sc_baseclock = mdp->md_baseclock; + + sc->sc_regctxs[MQ200_I_DCMISC ].val = mdp->md_init_dcmisc; + sc->sc_regctxs[MQ200_I_PMC ].val = mdp->md_init_pmc; + sc->sc_regctxs[MQ200_I_MM01 ].val = mdp->md_init_mm01; + +#if MQ200_SETUPREGS + mq200_setupregs(sc, mdp->md_init_ops); +#endif + } +} + +#if MQ200_SETUPREGS +static void +mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops) +{ + u_int32_t reg, mask, accum; + + while (1) { + switch (ops[0] & 0x3) { + case 0: + if (mask == ~0) { + mq200_write(sc, ops[0], ops[1]); + } else { + reg = mq200_read(sc, ops[0]); + reg = (reg & ~mask) | (ops[1] & mask); + mq200_write(sc, ops[0], reg); + } + break; + case 1: + switch (ops[0]) { + case OP_END: + return; + case OP_MASK: + mask = ops[1]; + break; + case OP_LOADPLLPARAM: + mq200_pllparam(ops[1], &accum); + break; + case OP_LOADFROMREG: + reg = mq200_read(sc, ops[1]); + accum = (accum & ~mask) | (reg & mask); + break; + case OP_STORETOREG: + if (mask == ~0) { + mq200_write(sc, ops[1], accum); + } else { + reg = mq200_read(sc, ops[1]); + reg = (reg & ~mask) | (accum & mask); + mq200_write(sc, ops[1], reg); + } + break; + case OP_LOADIMM: + accum = (accum & ~mask) | (ops[1] & mask); + break; + case OP_OR: + accum = (accum | ops[1]); + break; + } + break; + } + if (ops[0] != OP_MASK) + mask = ~0; + ops += 2; + } +} +#endif /* MQ200_SETUPREGS */ diff --git a/sys/arch/hpcmips/dev/mq200priv.h b/sys/arch/hpcmips/dev/mq200priv.h new file mode 100644 index 000000000000..79ec33ea456c --- /dev/null +++ b/sys/arch/hpcmips/dev/mq200priv.h @@ -0,0 +1,156 @@ +/* $NetBSD: mq200priv.h,v 1.1 2001/03/25 13:06:53 takemura Exp $ */ + +/*- + * Copyright (c) 2001 TAKEMURA Shin + * 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. + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + */ + +struct mq200_crt_param { + u_int16_t width, height, clock; + u_int16_t hdtotal; + u_int16_t vdtotal; + u_int16_t hsstart, hsend; + u_int16_t vsstart, vsend; + u_int32_t opt; +}; +#define MQ200_CRT_640x480_60Hz 0 +#define MQ200_CRT_800x600_60Hz 1 +#define MQ200_CRT_1024x768_60Hz 2 + +struct mq200_clock_setting { + u_int8_t mem, ge, gc[2]; + int pll1, pll2, pll3; +}; + +struct mq200_md_param { + platid_t *md_platform; + short md_fp_width, md_fp_height; + int md_baseclock; + int md_flags; +#define MQ200_MD_HAVECRT (1<<0) +#define MQ200_MD_HAVEFP (1<<1) + u_int32_t *md_init_ops; + const struct mq200_clock_setting *md_clock_settings; + u_int32_t md_init_dcmisc; + u_int32_t md_init_pmc; + u_int32_t md_init_mm01; +}; + +extern struct mq200_crt_param mq200_crt_params[]; +extern int mq200_crt_nparams; +extern char *mq200_clknames[]; + +void mq200_pllparam(int reqout, u_int32_t *res); +void mq200_set_pll(struct mq200_softc *, int, int); +void mq200_setup_regctx(struct mq200_softc *sc); +void mq200_setup(struct mq200_softc *sc); +void mq200_win_enable(struct mq200_softc *sc, int gc, + u_int32_t depth, u_int32_t start, + int width, int height, int stride); +void mq200_win_disable(struct mq200_softc *sc, int gc); +void mq200_setupmd(struct mq200_softc *sc); +void mq200_mdsetup(struct mq200_softc *sc); + +void mq200_dump_gc(struct mq200_softc *sc, int gc); +void mq200_dump_fp(struct mq200_softc *sc); +void mq200_dump_dc(struct mq200_softc *sc); +void mq200_dump_pll(struct mq200_softc *sc); +void mq200_dump_all(struct mq200_softc *sc); +char* mq200_regname(struct mq200_softc *sc, int offset, char *buf, int size); + +#ifdef MQ200_DEBUG +#ifndef MQ200DEBUG_CONF +#define MQ200DEBUG_CONF 0 +#endif +extern int mq200_debug; +#define DPRINTF(fmt, args...) do { if (mq200_debug) printf("mq200: " fmt, ##args); } while(0) +#define VPRINTF(fmt, args...) do { if (bootverbose || mq200_debug) printf("mq200: " fmt, ##args); } while(0) +#else +#define DPRINTF(fmt, args...) do { } while (0) +#define VPRINTF(fmt, args...) do { if (bootverbose) printf("mq200: " fmt, ##args); } while(0) +#endif + +/* + * register access wrappers + */ +static inline void +mq200_writex(struct mq200_softc *sc, int offset, u_int32_t data) +{ +#ifdef _KERNEL + bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, data); +#else + *(volatile unsigned long*)(sc->sc_baseaddr + offset) = data; +#endif +} + +#ifdef MQ200_DEBUG +void +mq200_write(struct mq200_softc *sc, int offset, u_int32_t data); +#else +static inline void +mq200_write(struct mq200_softc *sc, int offset, u_int32_t data) +{ + mq200_writex(sc, offset, data); +} +#endif /* MQ200_DEBUG */ + +static inline void +mq200_write2(struct mq200_softc *sc, struct mq200_regctx *reg, u_int32_t data) +{ + reg->val = data; + mq200_writex(sc, reg->offset, reg->val); +} + +static inline u_int32_t +mq200_read(struct mq200_softc *sc, int offset) +{ +#ifdef _KERNEL + return bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset); +#else + return *(volatile unsigned long*)(sc->sc_baseaddr + offset); +#endif +} + +static inline void +mq200_mod(struct mq200_softc *sc, struct mq200_regctx *reg, u_int32_t mask, u_int32_t data) +{ + reg->val &= ~mask; + reg->val |= data; + mq200_writex(sc, reg->offset, reg->val); +} + +static inline void +mq200_on(struct mq200_softc *sc, struct mq200_regctx *reg, unsigned long data) +{ + mq200_mod(sc, reg, data, data); +} + +static inline void +mq200_off(struct mq200_softc *sc, struct mq200_regctx *reg, unsigned long data) +{ + mq200_mod(sc, reg, data, 0); +} diff --git a/sys/arch/hpcmips/dev/mq200reg.h b/sys/arch/hpcmips/dev/mq200reg.h index 09896e2e8fb7..05d610900fbf 100644 --- a/sys/arch/hpcmips/dev/mq200reg.h +++ b/sys/arch/hpcmips/dev/mq200reg.h @@ -1,7 +1,7 @@ -/* $NetBSD: mq200reg.h,v 1.5 2001/03/11 13:53:31 takemura Exp $ */ +/* $NetBSD: mq200reg.h,v 1.6 2001/03/25 13:06:53 takemura Exp $ */ /*- - * Copyright (c) 2000 Takemura Shin + * Copyright (c) 2000, 2001 TAKEMURA Shin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,11 +68,24 @@ */ #define MQ200_MMR(n) (MQ200_MM+(n)*4) # define MQ200_MM00_ENABLE (1<<0) -# define MQ200_MM00_RESET (1<<1) -# define MQ200_MM00_DRAM_RESET (1<<2) -# define MQ200_MM01_CLK_PLL1 (0<<0) -# define MQ200_MM01_CLK_BUS (1<<0) -# define MQ200_MM01_CLK_PLL2 (1<<0) +# define MQ200_MM00_RESET (1<<1) +# define MQ200_MM00_DRAM_RESET (1<<2) +# define MQ200_MM01_CLK_PLL1 (0<<0) +# define MQ200_MM01_CLK_BUS (1<<0) +# define MQ200_MM01_CLK_PLL2 (1<<0) +# define MQ200_MM01_SLOW_REFRESH_EN (1<<1) +# define MQ200_MM01_CPU_PB_EN (1<<2) +# define MQ200_MM01_GC1_PB_EN (1<<3) +# define MQ200_MM01_GC2_PB_EN (1<<4) +# define MQ200_MM01_STN_READ_PB_EN (1<<5) +# define MQ200_MM01_STN_WRITE_PB_EN (1<<6) +# define MQ200_MM01_GE_PB_EN (1<<7) + /* bits 11-8 is reserved */ +# define MQ200_MM01_REFRESH_SHIFT 12 +# define MQ200_MM01_REFRESH_MASK 0x03fff000 + /* bits 29 is reserved */ +# define MQ200_MM01_DRAM_AUTO_REFRESH_EN (1<<30) +# define MQ200_MM01_DRAM_STANDBY_EN (1<<31) /* * Interrupt Controller @@ -617,6 +630,7 @@ */ #define MQ200_PMCR (MQ200_PM + 0x00) # define MQ200_PMC_PLL1_N (1<<0) +# define MQ200_PMC_PLL1_N_SHIFT 5 # define MQ200_PMC_PLL2_ENABLE (1<<2) # define MQ200_PMC_PLL3_ENABLE (1<<3) # define MQ200_PMC_IMMEDIATELY (1<<5) diff --git a/sys/arch/hpcmips/dev/mq200subr.c b/sys/arch/hpcmips/dev/mq200subr.c new file mode 100644 index 000000000000..ac8e387ac397 --- /dev/null +++ b/sys/arch/hpcmips/dev/mq200subr.c @@ -0,0 +1,371 @@ +/* $NetBSD: mq200subr.c,v 1.1 2001/03/25 13:06:53 takemura Exp $ */ + +/*- + * Copyright (c) 2001 TAKEMURA Shin + * 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. + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + */ + +#ifdef _KERNEL +#include +#include +#include +#include +#else +#include +#endif +#include + +#include +#include + +#include "opt_mq200.h" +#include "mq200var.h" +#include "mq200reg.h" +#include "mq200priv.h" + +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +int mq200_depth_table[] = { + [MQ200_GCC_1BPP] = 1, + [MQ200_GCC_2BPP] = 2, + [MQ200_GCC_4BPP] = 4, + [MQ200_GCC_8BPP] = 8, + [MQ200_GCC_16BPP] = 16, + [MQ200_GCC_24BPP] = 32, + [MQ200_GCC_ARGB888] = 32, + [MQ200_GCC_ABGR888] = 32, + [MQ200_GCC_16BPP_DIRECT] = 16, + [MQ200_GCC_24BPP_DIRECT] = 32, + [MQ200_GCC_ARGB888_DIRECT] = 32, + [MQ200_GCC_ABGR888_DIRECT] = 32, +}; + +struct mq200_crt_param mq200_crt_params[] = { + [MQ200_CRT_640x480_60Hz] = + { 640, 480, 25175, /* width, height, dot clock */ + 800, /* HD Total */ + 525, /* VD Total */ + 656, 752, /* HS Start, HS End */ + 490, 492, /* VS Start, VS End */ + (MQ200_GC1CRTC_HSYNC_ACTVLOW | + MQ200_GC1CRTC_VSYNC_ACTVLOW | + MQ200_GC1CRTC_BLANK_PEDESTAL_EN), + }, + [MQ200_CRT_800x600_60Hz] = + { 800, 600, 40000, /* width, height, dot clock */ + 1054, /* HD Total */ + 628, /* VD Total */ + 839, 967, /* HS Start, HS End */ + 601, 605, /* VS Start, VS End */ + MQ200_GC1CRTC_BLANK_PEDESTAL_EN, + }, + [MQ200_CRT_1024x768_60Hz] = + { 1024, 768, 65000, /* width, height, dot clock */ + 1344, /* HD Total */ + 806, /* VD Total */ + 1048, 1184, /* HS Start, HS End */ + 771, 777, /* VS Start, VS End */ + (MQ200_GC1CRTC_HSYNC_ACTVLOW | + MQ200_GC1CRTC_VSYNC_ACTVLOW | + MQ200_GC1CRTC_BLANK_PEDESTAL_EN), + }, +}; + +int mq200_crt_nparams = sizeof(mq200_crt_params)/sizeof(*mq200_crt_params); + +/* + * get PLL setting register value for given frequency + */ +void +mq200_pllparam(int reqout, u_int32_t *res) +{ + int n, m, p, out; + int ref = 12288; + int bn, bm, bp, e; + + e = ref; + for (p = 0; p <= 4; p++) { + for (n = 0; n < (1<<5); n++) { + m = (reqout * ((n + 1) << p)) / ref - 1; + out = ref * (m + 1) / ((n + 1) << p); + if (0xff < m) + break; + if (40 <= m && + 1000 <= ref/(n + 1) && + 170000 <= ref*(m+1)/(n+1) && + ref*(m+1)/(n+1) <= 340000 && + ABS(reqout - out) <= e) { + e = ABS(reqout - out); + bn = n; + bm = m; + bp = p; + } + } + } + +#if 0 + out = ref * (bm + 1) / ((bn + 1) << bp); + printf("PLL: %d.%03d x (%d+1) / (%d+1) / %d = %d.%03d\n", + ref / 1000, ref % 1000, bm, bn, (1<sc_regctxs[MQ200_I_PLL(1)]; + enreg = &sc->sc_regctxs[MQ200_I_DCMISC]; + enbit = MQ200_DCMISC_PLL1_ENABLE; + break; + case MQ200_CLOCK_PLL2: + paramreg = &sc->sc_regctxs[MQ200_I_PLL(2)]; + enreg = &sc->sc_regctxs[MQ200_I_PMC]; + enbit = MQ200_PMC_PLL2_ENABLE; + break; + case MQ200_CLOCK_PLL3: + paramreg = &sc->sc_regctxs[MQ200_I_PLL(3)]; + enreg = &sc->sc_regctxs[MQ200_I_PMC]; + enbit = MQ200_PMC_PLL3_ENABLE; + break; + default: + printf("mq200: invalid PLL: %d\n", pll); + return; + } + if (clock != 0 && clock != -1) { + /* PLL Programming */ + mq200_pllparam(clock, ¶m); + mq200_mod(sc, paramreg, MQ200_PLL_PARAM_MASK, param); + /* enable PLL */ + mq200_on(sc, enreg, enbit); + } + + DPRINTF("%s %d.%03dMHz\n", + mq200_clknames[pll], clock/1000, clock%1000); +} + +void +mq200_setup_regctx(struct mq200_softc *sc) +{ + int i; + static int offsets[MQ200_I_MAX] = { + [MQ200_I_DCMISC] = MQ200_DCMISCR, + [MQ200_I_PLL(2)] = MQ200_PLL2R, + [MQ200_I_PLL(3)] = MQ200_PLL3R, + [MQ200_I_PMC] = MQ200_PMCR, + [MQ200_I_MM01] = MQ200_MMR(1), + [MQ200_I_GCC(MQ200_GC1)] = MQ200_GCCR(MQ200_GC1), + [MQ200_I_GCC(MQ200_GC2)] = MQ200_GCCR(MQ200_GC2), + }; + + for (i = 0; i < sizeof(offsets)/sizeof(*offsets); i++) { + if (offsets[i] == 0) +#ifdef MQ200_DEBUG + panic("%s(%d): register context %d is empty\n", + __FILE__, __LINE__, i); +#endif + sc->sc_regctxs[i].offset = offsets[i]; + } +} + +void +mq200_setup(struct mq200_softc *sc) +{ + const struct mq200_clock_setting *clock; + const struct mq200_crt_param *crt; + + clock = &sc->sc_md->md_clock_settings[sc->sc_flags & MQ200_SC_GC_MASK]; + crt = sc->sc_crt; + + /* disable GC1 and GC2 */ + //mq200_write(sc, MQ200_GCCR(MQ200_GC1), 0); + mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC1)], 0); + mq200_write(sc, MQ200_GC1CRTCR, 0); + //mq200_write(sc, MQ200_GCCR(MQ200_GC2), 0); + mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC2)], 0); + + while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS) + /* busy wait */; + + /* + * setup around clock + */ + /* setup eatch PLLs */ + mq200_set_pll(sc, MQ200_CLOCK_PLL1, clock->pll1); + mq200_set_pll(sc, MQ200_CLOCK_PLL2, clock->pll2); + mq200_set_pll(sc, MQ200_CLOCK_PLL3, clock->pll3); + if (sc->sc_flags & MQ200_SC_GC1_ENABLE) + mq200_set_pll(sc, clock->gc[MQ200_GC1], crt->clock); + + /* setup MEMORY clock */ + if (clock->mem == MQ200_CLOCK_PLL2) + mq200_on(sc, &sc->sc_regctxs[MQ200_I_MM01], + MQ200_MM01_CLK_PLL2); + else + mq200_off(sc, &sc->sc_regctxs[MQ200_I_MM01], + MQ200_MM01_CLK_PLL2); + DPRINTF("MEM: PLL%d\n", (clock->mem == MQ200_CLOCK_PLL2)?2:1); + + /* setup GE clock */ + mq200_mod(sc, &sc->sc_regctxs[MQ200_I_PMC], + MQ200_PMC_GE_CLK_MASK | MQ200_PMC_GE_ENABLE, + (clock->ge << MQ200_PMC_GE_CLK_SHIFT) | MQ200_PMC_GE_ENABLE); + DPRINTF(" GE: PLL%d\n", clock->ge); + + /* + * setup GC1 (CRT contoller) + */ + if (sc->sc_flags & MQ200_SC_GC1_ENABLE) { + /* GC03R Horizontal Display Control */ + mq200_write(sc, MQ200_GCHDCR(MQ200_GC1), + (((u_int32_t)crt->hdtotal-2)<width << MQ200_GCHDC_END_SHIFT)); + + /* GC03R Vertical Display Control */ + mq200_write(sc, MQ200_GCVDCR(MQ200_GC1), + (((u_int32_t)crt->vdtotal-1)<height - 1) << MQ200_GCVDC_END_SHIFT)); + + /* GC04R Horizontal Sync Control */ + mq200_write(sc, MQ200_GCHSCR(MQ200_GC1), + ((u_int32_t)crt->hsstart << MQ200_GCHSC_START_SHIFT) | + ((u_int32_t)crt->hsend << MQ200_GCHSC_END_SHIFT)); + + /* GC05R Vertical Sync Control */ + mq200_write(sc, MQ200_GCVSCR(MQ200_GC1), + ((u_int32_t)crt->vsstart << MQ200_GCVSC_START_SHIFT) | + ((u_int32_t)crt->vsend << MQ200_GCVSC_END_SHIFT)); + + /* GC00R GC1 Control */ + //mq200_write(sc, MQ200_GCCR(MQ200_GC1), + mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC1)], + (MQ200_GCC_ENABLE | + (clock->gc[MQ200_GC1] << MQ200_GCC_RCLK_SHIFT) | + MQ200_GCC_MCLK_FD_1 | + (1 << MQ200_GCC_MCLK_SD_SHIFT))); + + /* GC01R CRT Control */ + mq200_write(sc, MQ200_GC1CRTCR, + MQ200_GC1CRTC_DACEN | crt->opt); + + sc->sc_width[MQ200_GC1] = crt->width; + sc->sc_height[MQ200_GC1] = crt->height; + + DPRINTF("GC1: %s\n", + mq200_clknames[clock->gc[MQ200_GC1]]); + } + + while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS) + /* busy wait */; + + /* + * setup GC2 (FP contoller) + */ + if (sc->sc_flags & MQ200_SC_GC2_ENABLE) { + //mq200_write(sc, MQ200_GCCR(MQ200_GC2), + mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC2)], + MQ200_GCC_ENABLE | + (clock->gc[MQ200_GC2] << MQ200_GCC_RCLK_SHIFT) | + MQ200_GCC_MCLK_FD_1 | (1 << MQ200_GCC_MCLK_SD_SHIFT)); + DPRINTF("GC2: %s\n", + mq200_clknames[clock->gc[MQ200_GC2]]); + } + + while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS) + /* busy wait */; + + /* + * disable unused PLLs + */ + if (clock->pll1 == 0) { + DPRINTF("PLL1 disable\n"); + mq200_off(sc, &sc->sc_regctxs[MQ200_I_DCMISC], + MQ200_DCMISC_PLL1_ENABLE); + } + if (clock->pll2 == 0) { + DPRINTF("PLL2 disable\n"); + mq200_off(sc, &sc->sc_regctxs[MQ200_I_PMC], + MQ200_PMC_PLL2_ENABLE); + } + if (clock->pll3 == 0) { + DPRINTF("PLL3 disable\n"); + mq200_off(sc, &sc->sc_regctxs[MQ200_I_PMC], + MQ200_PMC_PLL3_ENABLE); + } +} + +void +mq200_win_enable(struct mq200_softc *sc, int gc, + u_int32_t depth, u_int32_t start, + int width, int height, int stride) +{ + + DPRINTF("enable window on GC%d: %dx%d(%dx%d)\n", + gc + 1, width, height, sc->sc_width[gc], sc->sc_height[gc]); + + if (sc->sc_width[gc] < width) { + if (mq200_depth_table[depth]) + start += (height - sc->sc_height[gc]) * + mq200_depth_table[depth] / 8; + width = sc->sc_width[gc]; + } + + if (sc->sc_height[gc] < height) { + start += (height - sc->sc_height[gc]) * stride; + height = sc->sc_height[gc]; + } + + /* GC08R Window Horizontal Control */ + mq200_write(sc, MQ200_GCWHCR(gc), + (((u_int32_t)width - 1) << MQ200_GCWHC_WIDTH_SHIFT) | + ((sc->sc_width[gc] - width)/2)); + + /* GC09R Window Vertical Control */ + mq200_write(sc, MQ200_GCWVCR(gc), + (((u_int32_t)height - 1) << MQ200_GCWVC_HEIGHT_SHIFT) | + ((sc->sc_height[gc] - height)/2)); + + /* GC00R GC Control */ + mq200_mod(sc, &sc->sc_regctxs[MQ200_I_GCC(gc)], + (MQ200_GCC_WINEN | MQ200_GCC_DEPTH_MASK), + (MQ200_GCC_WINEN | (depth << MQ200_GCC_DEPTH_SHIFT))); +} + +void +mq200_win_disable(struct mq200_softc *sc, int gc) +{ + /* GC00R GC Control */ + mq200_off(sc, &sc->sc_regctxs[MQ200_I_GCC(gc)], MQ200_GCC_WINEN); +} diff --git a/sys/arch/hpcmips/dev/mq200var.h b/sys/arch/hpcmips/dev/mq200var.h index 0ce980683c27..5fc3cc8caae7 100644 --- a/sys/arch/hpcmips/dev/mq200var.h +++ b/sys/arch/hpcmips/dev/mq200var.h @@ -1,7 +1,7 @@ -/* $NetBSD: mq200var.h,v 1.4 2001/03/09 08:54:19 sato Exp $ */ +/* $NetBSD: mq200var.h,v 1.5 2001/03/25 13:06:53 takemura Exp $ */ /*- - * Copyright (c) 2000 Takemura Shin + * Copyright (c) 2000, 2001 TAKEMURA Shin * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,6 +59,26 @@ struct mq200_softc { int sc_mq200pwstate; /* mq200 power state */ struct hpcfb_fbconf sc_fbconf; struct hpcfb_dspconf sc_dspconf; + + int sc_baseclock; +#define MQ200_SC_GC1_ENABLE (1<<0) /* XXX, You can't change this */ +#define MQ200_SC_GC2_ENABLE (1<<1) /* XXX, You can't change this */ +#define MQ200_SC_GC_MASK (MQ200_SC_GC1_ENABLE|MQ200_SC_GC2_ENABLE) + char sc_flags; + int sc_width[2], sc_height[2]; + const struct mq200_md_param *sc_md; + const struct mq200_crt_param *sc_crt; + +#define MQ200_I_DCMISC 0 +#define MQ200_I_PLL(n) (MQ200_I_DCMISC + (n) - 1) /* 1, 2 */ +#define MQ200_I_PMC 3 +#define MQ200_I_MM01 4 +#define MQ200_I_GCC(n) (5 + (n)) /* 5, 6 */ +#define MQ200_I_MAX 7 + struct mq200_regctx { + int offset; + u_int32_t val; + } sc_regctxs[MQ200_I_MAX]; }; int mq200_probe __P((bus_space_tag_t, bus_space_handle_t));