xref: /netbsd-src/sys/arch/hpcmips/dev/mq200subr.c (revision 8940d9f0eb788e61875261c89ef7061ea2e31bef)
1*8940d9f0Smsaitoh /*	$NetBSD: mq200subr.c,v 1.7 2019/08/21 04:17:40 msaitoh Exp $	*/
244e4c533Stakemura 
344e4c533Stakemura /*-
444e4c533Stakemura  * Copyright (c) 2001 TAKEMURA Shin
544e4c533Stakemura  * All rights reserved.
644e4c533Stakemura  *
744e4c533Stakemura  * Redistribution and use in source and binary forms, with or without
844e4c533Stakemura  * modification, are permitted provided that the following conditions
944e4c533Stakemura  * are met:
1044e4c533Stakemura  * 1. Redistributions of source code must retain the above copyright
1144e4c533Stakemura  *    notice, this list of conditions and the following disclaimer.
1244e4c533Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
1344e4c533Stakemura  *    notice, this list of conditions and the following disclaimer in the
1444e4c533Stakemura  *    documentation and/or other materials provided with the distribution.
1544e4c533Stakemura  * 3. The name of the author may not be used to endorse or promote products
1644e4c533Stakemura  *    derived from this software without specific prior written permission.
1744e4c533Stakemura  *
1844e4c533Stakemura  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1944e4c533Stakemura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2044e4c533Stakemura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2144e4c533Stakemura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2244e4c533Stakemura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2344e4c533Stakemura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2444e4c533Stakemura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2544e4c533Stakemura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2644e4c533Stakemura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2744e4c533Stakemura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2844e4c533Stakemura  * SUCH DAMAGE.
2944e4c533Stakemura  *
3044e4c533Stakemura  */
3144e4c533Stakemura 
3244e4c533Stakemura #ifdef _KERNEL
330c82163cSlukem #include <sys/cdefs.h>
34*8940d9f0Smsaitoh __KERNEL_RCSID(0, "$NetBSD: mq200subr.c,v 1.7 2019/08/21 04:17:40 msaitoh Exp $");
350c82163cSlukem 
3644e4c533Stakemura #include <sys/param.h>
3744e4c533Stakemura #include <sys/kernel.h>
3844e4c533Stakemura #include <sys/systm.h>
3944e4c533Stakemura #include <sys/device.h>
4044e4c533Stakemura #else
4144e4c533Stakemura #include <stdio.h>
4244e4c533Stakemura #endif
4344e4c533Stakemura #include <sys/types.h>
4444e4c533Stakemura 
4544e4c533Stakemura #include <machine/platid.h>
4644e4c533Stakemura #include <machine/platid_mask.h>
4744e4c533Stakemura 
4844e4c533Stakemura #include "opt_mq200.h"
4944e4c533Stakemura #include "mq200var.h"
5044e4c533Stakemura #include "mq200reg.h"
5144e4c533Stakemura #include "mq200priv.h"
5244e4c533Stakemura 
5344e4c533Stakemura #define ABS(a)	((a) < 0 ? -(a) : (a))
5444e4c533Stakemura 
5544e4c533Stakemura int mq200_depth_table[] = {
5644e4c533Stakemura 	[MQ200_GCC_1BPP] =		1,
5744e4c533Stakemura 	[MQ200_GCC_2BPP] =		2,
5844e4c533Stakemura 	[MQ200_GCC_4BPP] =		4,
5944e4c533Stakemura 	[MQ200_GCC_8BPP] =		8,
6044e4c533Stakemura 	[MQ200_GCC_16BPP] =		16,
6144e4c533Stakemura 	[MQ200_GCC_24BPP] =		32,
6244e4c533Stakemura 	[MQ200_GCC_ARGB888] =		32,
6344e4c533Stakemura 	[MQ200_GCC_ABGR888] =		32,
6444e4c533Stakemura 	[MQ200_GCC_16BPP_DIRECT] =	16,
6544e4c533Stakemura 	[MQ200_GCC_24BPP_DIRECT] =	32,
6644e4c533Stakemura 	[MQ200_GCC_ARGB888_DIRECT] =	32,
6744e4c533Stakemura 	[MQ200_GCC_ABGR888_DIRECT] =	32,
6844e4c533Stakemura };
6944e4c533Stakemura 
7044e4c533Stakemura struct mq200_crt_param mq200_crt_params[] = {
7144e4c533Stakemura 	[MQ200_CRT_640x480_60Hz] =
7244e4c533Stakemura 	{	640, 480, 25175,	/* width, height, dot clock */
7344e4c533Stakemura 		800,			/* HD Total */
7444e4c533Stakemura 		525,			/* VD Total */
7544e4c533Stakemura 		656, 752,		/* HS Start, HS End */
7644e4c533Stakemura 		490, 492,		/* VS Start, VS End */
7744e4c533Stakemura 		(MQ200_GC1CRTC_HSYNC_ACTVLOW |
7844e4c533Stakemura 		    MQ200_GC1CRTC_VSYNC_ACTVLOW |
7944e4c533Stakemura 		    MQ200_GC1CRTC_BLANK_PEDESTAL_EN),
8044e4c533Stakemura 	},
8144e4c533Stakemura 	[MQ200_CRT_800x600_60Hz] =
8244e4c533Stakemura 	{	800, 600, 40000,	/* width, height, dot clock */
8344e4c533Stakemura 		1054,			/* HD Total */
8444e4c533Stakemura 		628,			/* VD Total */
8544e4c533Stakemura 		839, 967,		/* HS Start, HS End */
8644e4c533Stakemura 		601, 605,		/* VS Start, VS End */
8744e4c533Stakemura 		MQ200_GC1CRTC_BLANK_PEDESTAL_EN,
8844e4c533Stakemura 	},
8944e4c533Stakemura 	[MQ200_CRT_1024x768_60Hz] =
9044e4c533Stakemura 	{	1024, 768, 65000,	/* width, height, dot clock */
9144e4c533Stakemura 		1344,			/* HD Total */
9244e4c533Stakemura 		806,			/* VD Total */
9344e4c533Stakemura 		1048,	1184,		/* HS Start, HS End */
9444e4c533Stakemura 		771,	777,		/* VS Start, VS End */
9544e4c533Stakemura 		(MQ200_GC1CRTC_HSYNC_ACTVLOW |
9644e4c533Stakemura 		    MQ200_GC1CRTC_VSYNC_ACTVLOW |
9744e4c533Stakemura 		    MQ200_GC1CRTC_BLANK_PEDESTAL_EN),
9844e4c533Stakemura 	},
9944e4c533Stakemura };
10044e4c533Stakemura 
10144e4c533Stakemura int mq200_crt_nparams = sizeof(mq200_crt_params)/sizeof(*mq200_crt_params);
10244e4c533Stakemura 
10344e4c533Stakemura /*
10444e4c533Stakemura  * get PLL setting register value for given frequency
10544e4c533Stakemura  */
106a09206fdStakemura int
mq200_pllparam(int reqout,u_int32_t * res)10744e4c533Stakemura mq200_pllparam(int reqout, u_int32_t *res)
10844e4c533Stakemura {
10944e4c533Stakemura 	int n, m, p, out;
11044e4c533Stakemura 	int ref = 12288;
11144e4c533Stakemura 	int bn, bm, bp, e;
11244e4c533Stakemura 
11344e4c533Stakemura 	e = ref;
114a09206fdStakemura 	bn = 0; bp = 0; bm = 0;
11544e4c533Stakemura 	for (p = 0; p <= 4; p++) {
11644e4c533Stakemura 		for (n = 0; n < (1<<5); n++) {
11744e4c533Stakemura 			m = (reqout * ((n + 1) << p)) / ref - 1;
11844e4c533Stakemura 			out = ref * (m + 1) / ((n + 1) << p);
11944e4c533Stakemura 			if (0xff < m)
12044e4c533Stakemura 				break;
12144e4c533Stakemura 			if (40 <= m &&
12244e4c533Stakemura 			    1000 <= ref/(n + 1) &&
12344e4c533Stakemura 			    170000 <= ref*(m+1)/(n+1) &&
12444e4c533Stakemura 			    ref*(m+1)/(n+1) <= 340000 &&
12544e4c533Stakemura 			    ABS(reqout - out) <= e) {
12644e4c533Stakemura 				e = ABS(reqout - out);
12744e4c533Stakemura 				bn = n;
12844e4c533Stakemura 				bm = m;
12944e4c533Stakemura 				bp = p;
13044e4c533Stakemura 			}
13144e4c533Stakemura 		}
13244e4c533Stakemura 	}
133a09206fdStakemura 	if (ref <= e)
134a09206fdStakemura 		return (-1);
13544e4c533Stakemura 
13644e4c533Stakemura #if 0
13744e4c533Stakemura 	out = ref * (bm + 1) / ((bn + 1) << bp);
13844e4c533Stakemura 	printf("PLL: %d.%03d x (%d+1) / (%d+1) / %d = %d.%03d\n",
13944e4c533Stakemura 	    ref / 1000, ref % 1000, bm, bn, (1<<bp),
14044e4c533Stakemura 	    out / 1000, out % 1000);
14144e4c533Stakemura #endif
14244e4c533Stakemura 	*res = ((bm << MQ200_PLL_M_SHIFT) |
14344e4c533Stakemura 		(bn << MQ200_PLL_N_SHIFT) |
14444e4c533Stakemura 		(bp << MQ200_PLL_P_SHIFT));
145a09206fdStakemura 
146a09206fdStakemura 	return (0);
14744e4c533Stakemura }
14844e4c533Stakemura 
14944e4c533Stakemura void
mq200_set_pll(struct mq200_softc * sc,int pll,int clock)15044e4c533Stakemura mq200_set_pll(struct mq200_softc *sc, int pll, int clock)
15144e4c533Stakemura {
15244e4c533Stakemura 	struct mq200_regctx *paramreg, *enreg;
15344e4c533Stakemura 	u_int32_t param, enbit;
15444e4c533Stakemura 
15544e4c533Stakemura 	switch (pll) {
15644e4c533Stakemura 	case MQ200_CLOCK_PLL1:
15744e4c533Stakemura 		paramreg = &sc->sc_regctxs[MQ200_I_PLL(1)];
15844e4c533Stakemura 		enreg = &sc->sc_regctxs[MQ200_I_DCMISC];
15944e4c533Stakemura 		enbit = MQ200_DCMISC_PLL1_ENABLE;
16044e4c533Stakemura 		break;
16144e4c533Stakemura 	case MQ200_CLOCK_PLL2:
16244e4c533Stakemura 		paramreg = &sc->sc_regctxs[MQ200_I_PLL(2)];
16344e4c533Stakemura 		enreg = &sc->sc_regctxs[MQ200_I_PMC];
16444e4c533Stakemura 		enbit = MQ200_PMC_PLL2_ENABLE;
16544e4c533Stakemura 		break;
16644e4c533Stakemura 	case MQ200_CLOCK_PLL3:
16744e4c533Stakemura 		paramreg = &sc->sc_regctxs[MQ200_I_PLL(3)];
16844e4c533Stakemura 		enreg = &sc->sc_regctxs[MQ200_I_PMC];
16944e4c533Stakemura 		enbit = MQ200_PMC_PLL3_ENABLE;
17044e4c533Stakemura 		break;
17144e4c533Stakemura 	default:
17244e4c533Stakemura 		printf("mq200: invalid PLL: %d\n", pll);
17344e4c533Stakemura 		return;
17444e4c533Stakemura 	}
17544e4c533Stakemura 	if (clock != 0 && clock != -1) {
17644e4c533Stakemura 		/* PLL Programming	*/
177a09206fdStakemura 		if (mq200_pllparam(clock, &param) != 0) {
178a09206fdStakemura 			printf("mq200: invalid clock rate: %s %d.%03dMHz\n",
179a09206fdStakemura 			    mq200_clknames[pll], clock/1000, clock%1000);
180a09206fdStakemura 			return;
181a09206fdStakemura 		}
18244e4c533Stakemura 		mq200_mod(sc, paramreg, MQ200_PLL_PARAM_MASK, param);
18344e4c533Stakemura 		/* enable PLL	*/
18444e4c533Stakemura 		mq200_on(sc, enreg, enbit);
18544e4c533Stakemura 	}
18644e4c533Stakemura 
18744e4c533Stakemura 	DPRINTF("%s %d.%03dMHz\n",
18844e4c533Stakemura 	    mq200_clknames[pll], clock/1000, clock%1000);
18944e4c533Stakemura }
19044e4c533Stakemura 
19144e4c533Stakemura void
mq200_setup_regctx(struct mq200_softc * sc)19244e4c533Stakemura mq200_setup_regctx(struct mq200_softc *sc)
19344e4c533Stakemura {
19444e4c533Stakemura 	int i;
19544e4c533Stakemura 	static int offsets[MQ200_I_MAX] = {
19644e4c533Stakemura 		[MQ200_I_DCMISC] =		MQ200_DCMISCR,
19744e4c533Stakemura 		[MQ200_I_PLL(2)] =		MQ200_PLL2R,
19844e4c533Stakemura 		[MQ200_I_PLL(3)] =		MQ200_PLL3R,
19944e4c533Stakemura 		[MQ200_I_PMC] =			MQ200_PMCR,
20044e4c533Stakemura 		[MQ200_I_MM01] =		MQ200_MMR(1),
20144e4c533Stakemura 		[MQ200_I_GCC(MQ200_GC1)] =	MQ200_GCCR(MQ200_GC1),
20244e4c533Stakemura 		[MQ200_I_GCC(MQ200_GC2)] =	MQ200_GCCR(MQ200_GC2),
20344e4c533Stakemura 	};
20444e4c533Stakemura 
20544e4c533Stakemura 	for (i = 0; i < sizeof(offsets)/sizeof(*offsets); i++) {
20644e4c533Stakemura 		if (offsets[i] == 0)
20744e4c533Stakemura #ifdef MQ200_DEBUG
208108ae856Stakemura 			if (i != MQ200_I_PMC)
2090f09ed48Sprovos 				panic("%s(%d): register context %d is empty",
21044e4c533Stakemura 				    __FILE__, __LINE__, i);
21144e4c533Stakemura #endif
21244e4c533Stakemura 		sc->sc_regctxs[i].offset = offsets[i];
21344e4c533Stakemura 	}
21444e4c533Stakemura }
21544e4c533Stakemura 
21644e4c533Stakemura void
mq200_setup(struct mq200_softc * sc)21744e4c533Stakemura mq200_setup(struct mq200_softc *sc)
21844e4c533Stakemura {
21944e4c533Stakemura 	const struct mq200_clock_setting *clock;
22044e4c533Stakemura 	const struct mq200_crt_param *crt;
22144e4c533Stakemura 
22244e4c533Stakemura 	clock = &sc->sc_md->md_clock_settings[sc->sc_flags & MQ200_SC_GC_MASK];
22344e4c533Stakemura 	crt = sc->sc_crt;
22444e4c533Stakemura 
22544e4c533Stakemura 	/* disable GC1 and GC2	*/
22644e4c533Stakemura 	//mq200_write(sc, MQ200_GCCR(MQ200_GC1), 0);
22744e4c533Stakemura 	mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC1)], 0);
22844e4c533Stakemura 	mq200_write(sc, MQ200_GC1CRTCR, 0);
22944e4c533Stakemura 	//mq200_write(sc, MQ200_GCCR(MQ200_GC2), 0);
23044e4c533Stakemura 	mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC2)], 0);
23144e4c533Stakemura 
23244e4c533Stakemura 	while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS)
23344e4c533Stakemura 	    /* busy wait */;
23444e4c533Stakemura 
23544e4c533Stakemura 	/*
23644e4c533Stakemura 	 * setup around clock
23744e4c533Stakemura 	 */
23844e4c533Stakemura 	/* setup eatch PLLs	*/
23944e4c533Stakemura 	mq200_set_pll(sc, MQ200_CLOCK_PLL1, clock->pll1);
24044e4c533Stakemura 	mq200_set_pll(sc, MQ200_CLOCK_PLL2, clock->pll2);
24144e4c533Stakemura 	mq200_set_pll(sc, MQ200_CLOCK_PLL3, clock->pll3);
24244e4c533Stakemura 	if (sc->sc_flags & MQ200_SC_GC1_ENABLE)
24344e4c533Stakemura 		mq200_set_pll(sc, clock->gc[MQ200_GC1], crt->clock);
24444e4c533Stakemura 
24544e4c533Stakemura 	/* setup MEMORY clock */
24644e4c533Stakemura 	if (clock->mem == MQ200_CLOCK_PLL2)
24744e4c533Stakemura 		mq200_on(sc, &sc->sc_regctxs[MQ200_I_MM01],
24844e4c533Stakemura 		    MQ200_MM01_CLK_PLL2);
24944e4c533Stakemura 	else
25044e4c533Stakemura 		mq200_off(sc, &sc->sc_regctxs[MQ200_I_MM01],
25144e4c533Stakemura 		    MQ200_MM01_CLK_PLL2);
25244e4c533Stakemura 	DPRINTF("MEM: PLL%d\n", (clock->mem == MQ200_CLOCK_PLL2)?2:1);
25344e4c533Stakemura 
25444e4c533Stakemura 	/* setup GE clock */
25544e4c533Stakemura 	mq200_mod(sc, &sc->sc_regctxs[MQ200_I_PMC],
25644e4c533Stakemura 	    MQ200_PMC_GE_CLK_MASK | MQ200_PMC_GE_ENABLE,
25744e4c533Stakemura 	    (clock->ge << MQ200_PMC_GE_CLK_SHIFT) | MQ200_PMC_GE_ENABLE);
25844e4c533Stakemura 	DPRINTF(" GE: PLL%d\n", clock->ge);
25944e4c533Stakemura 
26044e4c533Stakemura 	/*
261*8940d9f0Smsaitoh 	 * setup GC1	(CRT controller)
26244e4c533Stakemura 	 */
26344e4c533Stakemura 	if (sc->sc_flags & MQ200_SC_GC1_ENABLE) {
26444e4c533Stakemura 		/* GC03R	Horizontal Display Control	*/
26544e4c533Stakemura 		mq200_write(sc, MQ200_GCHDCR(MQ200_GC1),
26644e4c533Stakemura 		    (((u_int32_t)crt->hdtotal-2)<<MQ200_GC1HDC_TOTAL_SHIFT) |
26744e4c533Stakemura 		    ((u_int32_t)crt->width << MQ200_GCHDC_END_SHIFT));
26844e4c533Stakemura 
26944e4c533Stakemura 		/* GC03R	Vertical Display Control	*/
27044e4c533Stakemura 		mq200_write(sc, MQ200_GCVDCR(MQ200_GC1),
27144e4c533Stakemura 		    (((u_int32_t)crt->vdtotal-1)<<MQ200_GC1VDC_TOTAL_SHIFT) |
27244e4c533Stakemura 		    (((u_int32_t)crt->height - 1) << MQ200_GCVDC_END_SHIFT));
27344e4c533Stakemura 
27444e4c533Stakemura 		/* GC04R	Horizontal Sync Control		*/
27544e4c533Stakemura 		mq200_write(sc, MQ200_GCHSCR(MQ200_GC1),
27644e4c533Stakemura 		    ((u_int32_t)crt->hsstart << MQ200_GCHSC_START_SHIFT) |
27744e4c533Stakemura 		    ((u_int32_t)crt->hsend << MQ200_GCHSC_END_SHIFT));
27844e4c533Stakemura 
27944e4c533Stakemura 		/* GC05R	Vertical Sync Control		*/
28044e4c533Stakemura 		mq200_write(sc, MQ200_GCVSCR(MQ200_GC1),
28144e4c533Stakemura 		    ((u_int32_t)crt->vsstart << MQ200_GCVSC_START_SHIFT) |
28244e4c533Stakemura 		    ((u_int32_t)crt->vsend << MQ200_GCVSC_END_SHIFT));
28344e4c533Stakemura 
28444e4c533Stakemura 		/* GC00R	GC1 Control			*/
28544e4c533Stakemura 		//mq200_write(sc, MQ200_GCCR(MQ200_GC1),
28644e4c533Stakemura 		mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC1)],
28744e4c533Stakemura 		    (MQ200_GCC_ENABLE |
28844e4c533Stakemura 			(clock->gc[MQ200_GC1] << MQ200_GCC_RCLK_SHIFT) |
28944e4c533Stakemura 			MQ200_GCC_MCLK_FD_1 |
29044e4c533Stakemura 			(1 << MQ200_GCC_MCLK_SD_SHIFT)));
29144e4c533Stakemura 
29244e4c533Stakemura 		/* GC01R	CRT Control			*/
29344e4c533Stakemura 		mq200_write(sc, MQ200_GC1CRTCR,
29444e4c533Stakemura 		    MQ200_GC1CRTC_DACEN | crt->opt);
29544e4c533Stakemura 
29644e4c533Stakemura 		sc->sc_width[MQ200_GC1] = crt->width;
29744e4c533Stakemura 		sc->sc_height[MQ200_GC1] = crt->height;
29844e4c533Stakemura 
29944e4c533Stakemura 		DPRINTF("GC1: %s\n",
30044e4c533Stakemura 		    mq200_clknames[clock->gc[MQ200_GC1]]);
30144e4c533Stakemura 	}
30244e4c533Stakemura 
30344e4c533Stakemura 	while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS)
30444e4c533Stakemura 	    /* busy wait */;
30544e4c533Stakemura 
30644e4c533Stakemura 	/*
307*8940d9f0Smsaitoh 	 * setup GC2	(FP controller)
30844e4c533Stakemura 	 */
30944e4c533Stakemura 	if (sc->sc_flags & MQ200_SC_GC2_ENABLE) {
31044e4c533Stakemura 		//mq200_write(sc, MQ200_GCCR(MQ200_GC2),
31144e4c533Stakemura 		mq200_write2(sc, &sc->sc_regctxs[MQ200_I_GCC(MQ200_GC2)],
31244e4c533Stakemura 		    MQ200_GCC_ENABLE |
31344e4c533Stakemura 		    (clock->gc[MQ200_GC2] << MQ200_GCC_RCLK_SHIFT) |
31444e4c533Stakemura 		    MQ200_GCC_MCLK_FD_1 | (1 << MQ200_GCC_MCLK_SD_SHIFT));
31544e4c533Stakemura 		DPRINTF("GC2: %s\n",
31644e4c533Stakemura 		    mq200_clknames[clock->gc[MQ200_GC2]]);
31744e4c533Stakemura 	}
31844e4c533Stakemura 
31944e4c533Stakemura 	while (mq200_read(sc, MQ200_PMCR) & MQ200_PMC_SEQPROGRESS)
32044e4c533Stakemura 	    /* busy wait */;
32144e4c533Stakemura 
32244e4c533Stakemura 	/*
32344e4c533Stakemura 	 * disable unused PLLs
32444e4c533Stakemura 	 */
32544e4c533Stakemura 	if (clock->pll1 == 0) {
32644e4c533Stakemura 		DPRINTF("PLL1 disable\n");
32744e4c533Stakemura 		mq200_off(sc, &sc->sc_regctxs[MQ200_I_DCMISC],
32844e4c533Stakemura 		    MQ200_DCMISC_PLL1_ENABLE);
32944e4c533Stakemura 	}
33044e4c533Stakemura 	if (clock->pll2 == 0) {
33144e4c533Stakemura 		DPRINTF("PLL2 disable\n");
33244e4c533Stakemura 		mq200_off(sc, &sc->sc_regctxs[MQ200_I_PMC],
33344e4c533Stakemura 		    MQ200_PMC_PLL2_ENABLE);
33444e4c533Stakemura 	}
33544e4c533Stakemura 	if (clock->pll3 == 0) {
33644e4c533Stakemura 		DPRINTF("PLL3 disable\n");
33744e4c533Stakemura 		mq200_off(sc,  &sc->sc_regctxs[MQ200_I_PMC],
33844e4c533Stakemura 		    MQ200_PMC_PLL3_ENABLE);
33944e4c533Stakemura 	}
34044e4c533Stakemura }
34144e4c533Stakemura 
34244e4c533Stakemura void
mq200_win_enable(struct mq200_softc * sc,int gc,u_int32_t depth,u_int32_t start,int width,int height,int stride)34344e4c533Stakemura mq200_win_enable(struct mq200_softc *sc, int gc,
34444e4c533Stakemura     u_int32_t depth, u_int32_t start,
34544e4c533Stakemura     int width, int height, int stride)
34644e4c533Stakemura {
34744e4c533Stakemura 
34844e4c533Stakemura 	DPRINTF("enable window on GC%d: %dx%d(%dx%d)\n",
34944e4c533Stakemura 	    gc + 1, width, height,  sc->sc_width[gc], sc->sc_height[gc]);
35044e4c533Stakemura 
35144e4c533Stakemura 	if (sc->sc_width[gc] < width) {
35244e4c533Stakemura 		if (mq200_depth_table[depth])
35344e4c533Stakemura 			start += (height - sc->sc_height[gc]) *
35444e4c533Stakemura 			    mq200_depth_table[depth] / 8;
35544e4c533Stakemura 		width = sc->sc_width[gc];
35644e4c533Stakemura 	}
35744e4c533Stakemura 
35844e4c533Stakemura 	if (sc->sc_height[gc] < height) {
35944e4c533Stakemura 		start += (height - sc->sc_height[gc]) * stride;
36044e4c533Stakemura 		height = sc->sc_height[gc];
36144e4c533Stakemura 	}
36244e4c533Stakemura 
36344e4c533Stakemura 	/* GC08R	Window Horizontal Control	*/
36444e4c533Stakemura 	mq200_write(sc, MQ200_GCWHCR(gc),
36544e4c533Stakemura 	    (((u_int32_t)width - 1) << MQ200_GCWHC_WIDTH_SHIFT) |
36644e4c533Stakemura 	    ((sc->sc_width[gc] - width)/2));
36744e4c533Stakemura 
36844e4c533Stakemura 	/* GC09R	Window Vertical Control		*/
36944e4c533Stakemura 	mq200_write(sc, MQ200_GCWVCR(gc),
37044e4c533Stakemura 	    (((u_int32_t)height - 1) << MQ200_GCWVC_HEIGHT_SHIFT) |
37144e4c533Stakemura 	    ((sc->sc_height[gc] - height)/2));
37244e4c533Stakemura 
37344e4c533Stakemura 	/* GC00R	GC Control	*/
37444e4c533Stakemura 	mq200_mod(sc, &sc->sc_regctxs[MQ200_I_GCC(gc)],
37544e4c533Stakemura 	    (MQ200_GCC_WINEN | MQ200_GCC_DEPTH_MASK),
37644e4c533Stakemura 	    (MQ200_GCC_WINEN | (depth << MQ200_GCC_DEPTH_SHIFT)));
37744e4c533Stakemura }
37844e4c533Stakemura 
37944e4c533Stakemura void
mq200_win_disable(struct mq200_softc * sc,int gc)38044e4c533Stakemura mq200_win_disable(struct mq200_softc *sc, int gc)
38144e4c533Stakemura {
38244e4c533Stakemura 	/* GC00R	GC Control	*/
38344e4c533Stakemura 	mq200_off(sc, &sc->sc_regctxs[MQ200_I_GCC(gc)], MQ200_GCC_WINEN);
38444e4c533Stakemura }
385