xref: /netbsd-src/sys/arch/arm/iomd/vidc20config.c (revision 7b6cdeb9a1cfd1ce9904096629eab0c043bb9008)
1*7b6cdeb9Sandvar /*	$NetBSD: vidc20config.c,v 1.37 2024/05/18 19:04:45 andvar Exp $	*/
27d4a1addSreinoud 
37d4a1addSreinoud /*
47d4a1addSreinoud  * Copyright (c) 2001 Reinoud Zandijk
57d4a1addSreinoud  * Copyright (c) 1996 Mark Brinicombe
67d4a1addSreinoud  * Copyright (c) 1996 Robert Black
77d4a1addSreinoud  * Copyright (c) 1994-1995 Melvyn Tang-Richardson
87d4a1addSreinoud  * Copyright (c) 1994-1995 RiscBSD kernel team
97d4a1addSreinoud  * All rights reserved.
107d4a1addSreinoud  *
117d4a1addSreinoud  * Redistribution and use in source and binary forms, with or without
127d4a1addSreinoud  * modification, are permitted provided that the following conditions
137d4a1addSreinoud  * are met:
147d4a1addSreinoud  * 1. Redistributions of source code must retain the above copyright
157d4a1addSreinoud  *    notice, this list of conditions and the following disclaimer.
167d4a1addSreinoud  * 2. Redistributions in binary form must reproduce the above copyright
177d4a1addSreinoud  *    notice, this list of conditions and the following disclaimer in the
187d4a1addSreinoud  *    documentation and/or other materials provided with the distribution.
197d4a1addSreinoud  * 3. All advertising materials mentioning features or use of this software
207d4a1addSreinoud  *    must display the following acknowledgement:
217d4a1addSreinoud  *	This product includes software developed by the RiscBSD kernel team
227d4a1addSreinoud  * 4. The name of the company nor the name of the author may be used to
237d4a1addSreinoud  *    endorse or promote products derived from this software without specific
247d4a1addSreinoud  *    prior written permission.
257d4a1addSreinoud  *
267d4a1addSreinoud  * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
277d4a1addSreinoud  * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
287d4a1addSreinoud  * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297d4a1addSreinoud  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
307d4a1addSreinoud  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317d4a1addSreinoud  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327d4a1addSreinoud  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337d4a1addSreinoud  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347d4a1addSreinoud  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357d4a1addSreinoud  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
367d4a1addSreinoud  * THE POSSIBILITY OF SUCH DAMAGE.
377d4a1addSreinoud  *
387d4a1addSreinoud  * NetBSD kernel project
397d4a1addSreinoud  *
407d4a1addSreinoud  * vidcvideo.c
417d4a1addSreinoud  *
427d4a1addSreinoud  * This file is the lower basis of the wscons driver for VIDC based ARM machines.
437d4a1addSreinoud  * It features the initialisation and all VIDC writing and keeps in internal state
447d4a1addSreinoud  * copy.
459f4a9600Sandvar  * Its currently set up as a library file and not as a device; it could be named
467d4a1addSreinoud  * vidcvideo0 eventually.
477d4a1addSreinoud  */
487d4a1addSreinoud 
497d4a1addSreinoud #include <sys/cdefs.h>
50c1f8e3aaSbjh21 
51*7b6cdeb9Sandvar __KERNEL_RCSID(0, "$NetBSD: vidc20config.c,v 1.37 2024/05/18 19:04:45 andvar Exp $");
52c1f8e3aaSbjh21 
537d4a1addSreinoud #include <sys/types.h>
547d4a1addSreinoud #include <sys/param.h>
557d4a1addSreinoud #include <arm/iomd/vidc.h>
567d4a1addSreinoud #include <machine/bootconfig.h>
5728466919Sthorpej #include <machine/intr.h>
587d4a1addSreinoud 
597d4a1addSreinoud #include <sys/systm.h>
607d4a1addSreinoud #include <sys/device.h>
617d4a1addSreinoud #include <uvm/uvm_extern.h>
627d4a1addSreinoud 
637d4a1addSreinoud #include <arm/iomd/iomdreg.h>
647d4a1addSreinoud #include <arm/iomd/iomdvar.h>
657d4a1addSreinoud #include <arm/iomd/vidc20config.h>
667d4a1addSreinoud 
6701e40549Sskrll #define WriteWord(a, b) \
6801e40549Sskrll *((volatile unsigned int *)(a)) = (b)
6901e40549Sskrll 
7001e40549Sskrll #define ReadWord(a) \
7101e40549Sskrll (*((volatile unsigned int *)(a)))
721a19ddabSreinoud 
737d4a1addSreinoud /*
747d4a1addSreinoud  * A structure containing ALL the information required to restore
757d4a1addSreinoud  * the VIDC20 to any given state.  ALL vidc transactions should
767d4a1addSreinoud  * go through these procedures, which record the vidc's state.
777d4a1addSreinoud  * it may be an idea to set the permissions of the vidc base address
787d4a1addSreinoud  * so we get a fault, so the fault routine can record the state but
797d4a1addSreinoud  * I guess that's not really necessary for the time being, since we
807d4a1addSreinoud  * can make the kernel more secure later on.  Also, it is possible
817d4a1addSreinoud  * to write a routine to allow 'reading' of the vidc registers.
827d4a1addSreinoud  */
837d4a1addSreinoud 
847d4a1addSreinoud static struct vidc_state vidc_lookup = {
857d4a1addSreinoud 	{ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
867d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
877d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
887d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
897d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
907d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
917d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
927d4a1addSreinoud           0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0
937d4a1addSreinoud 	},
947d4a1addSreinoud 
957d4a1addSreinoud 	VIDC_PALREG,
967d4a1addSreinoud 	VIDC_BCOL,
977d4a1addSreinoud 	VIDC_CP1 ,
987d4a1addSreinoud 	VIDC_CP2,
997d4a1addSreinoud 	VIDC_CP3,
1007d4a1addSreinoud 	VIDC_HCR,
1017d4a1addSreinoud 	VIDC_HSWR,
1027d4a1addSreinoud 	VIDC_HBSR,
1037d4a1addSreinoud 	VIDC_HDSR,
1047d4a1addSreinoud 	VIDC_HDER,
1057d4a1addSreinoud 	VIDC_HBER,
1067d4a1addSreinoud 	VIDC_HCSR,
1077d4a1addSreinoud 	VIDC_HIR,
1087d4a1addSreinoud 	VIDC_VCR,
1097d4a1addSreinoud 	VIDC_VSWR,
1107d4a1addSreinoud 	VIDC_VBSR,
1117d4a1addSreinoud 	VIDC_VDSR,
1127d4a1addSreinoud 	VIDC_VDER,
1137d4a1addSreinoud 	VIDC_VBER,
1147d4a1addSreinoud 	VIDC_VCSR,
1157d4a1addSreinoud 	VIDC_VCER,
1167d4a1addSreinoud 	VIDC_EREG,
1177d4a1addSreinoud 	VIDC_FSYNREG,
1187d4a1addSreinoud 	VIDC_CONREG,
1197d4a1addSreinoud 	VIDC_DCTL
1207d4a1addSreinoud };
1217d4a1addSreinoud 
1227d4a1addSreinoud struct vidc_state vidc_current[1];
1237d4a1addSreinoud 
1247d4a1addSreinoud 
1257d4a1addSreinoud /*
1267d4a1addSreinoud  * XXX global display variables XXX ... should be a structure
1277d4a1addSreinoud  */
1287d4a1addSreinoud static int cold_init = 0;		/* flags initialisation */
1297d4a1addSreinoud extern videomemory_t videomemory;
1307d4a1addSreinoud 
13172cec937Sbjh21 static struct vidc_mode vidc_currentmode;
1327d4a1addSreinoud 
1337d4a1addSreinoud unsigned int dispstart;
1347d4a1addSreinoud unsigned int dispsize;
1357d4a1addSreinoud unsigned int dispbase;
1367d4a1addSreinoud unsigned int dispend;
1377d4a1addSreinoud unsigned int ptov;
1387d4a1addSreinoud unsigned int vmem_base;
1397d4a1addSreinoud unsigned int phys_base;
1407d4a1addSreinoud unsigned int transfersize;
1417d4a1addSreinoud 
1427d4a1addSreinoud 
1437d4a1addSreinoud /* cursor stuff */
1447d4a1addSreinoud char *cursor_normal;
1457d4a1addSreinoud char *cursor_transparent;
1467d4a1addSreinoud int   p_cursor_normal;
1477d4a1addSreinoud int   p_cursor_transparent;
1487d4a1addSreinoud int   cursor_width;
1497d4a1addSreinoud int   cursor_height;
1507d4a1addSreinoud 
1517d4a1addSreinoud 
1527d4a1addSreinoud /*
1537d4a1addSreinoud  * VIDC mode definitions
1547d4a1addSreinoud  * generated from RISC OS mode definition file by an `awk' script
1557d4a1addSreinoud  */
15672cec937Sbjh21 extern const struct videomode vidc_videomode_list[];
15772cec937Sbjh21 extern const int vidc_videomode_count;
1587d4a1addSreinoud 
1597d4a1addSreinoud 
1607d4a1addSreinoud /*
1617d4a1addSreinoud  * configuration printing
1627d4a1addSreinoud  *
1637d4a1addSreinoud  */
1647d4a1addSreinoud 
1657d4a1addSreinoud void
vidcvideo_printdetails(void)1667d4a1addSreinoud vidcvideo_printdetails(void)
1677d4a1addSreinoud {
1687d4a1addSreinoud         printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000),
1697d4a1addSreinoud             videomemory.vidm_size / 1024,
1707d4a1addSreinoud             (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM");
1717d4a1addSreinoud }
1727d4a1addSreinoud 
1731a19ddabSreinoud 
1747d4a1addSreinoud /*
1757d4a1addSreinoud  * Common functions to directly access VIDC registers
1767d4a1addSreinoud  */
1777d4a1addSreinoud int
vidcvideo_write(u_int reg,int value)178758ec341Sbjh21 vidcvideo_write(u_int reg, int value)
1797d4a1addSreinoud {
1807d4a1addSreinoud 	int counter;
1817d4a1addSreinoud 
1827d4a1addSreinoud 	int *current;
1837d4a1addSreinoud 	int *tab;
1847d4a1addSreinoud 
1857d4a1addSreinoud 	tab 	= (int *)&vidc_lookup;
1867d4a1addSreinoud 	current = (int *)vidc_current;
1877d4a1addSreinoud 
1887d4a1addSreinoud 
1897d4a1addSreinoud 	/*
1907d4a1addSreinoud 	 * OK, the VIDC_PALETTE register is handled differently
1917d4a1addSreinoud 	 * to the others on the VIDC, so take that into account here
1927d4a1addSreinoud 	 */
1937d4a1addSreinoud 	if (reg == VIDC_PALREG) {
1947d4a1addSreinoud 		vidc_current->palreg = 0;
1957d4a1addSreinoud 		WriteWord(vidc_base, reg | value);
1967d4a1addSreinoud 		return 0;
1977d4a1addSreinoud 	}
1987d4a1addSreinoud 
1997d4a1addSreinoud 	if (reg == VIDC_PALETTE) {
2007d4a1addSreinoud 		WriteWord(vidc_base, reg | value);
2017d4a1addSreinoud 		vidc_current->palette[vidc_current->palreg] = value;
2027d4a1addSreinoud 		vidc_current->palreg++;
2037d4a1addSreinoud 		vidc_current->palreg = vidc_current->palreg & 0xff;
2047d4a1addSreinoud 		return 0;
2057d4a1addSreinoud 	}
2067d4a1addSreinoud 
2077d4a1addSreinoud 	/*
2087d4a1addSreinoud 	 * Undefine SAFER if you wish to speed things up (a little)
209*7b6cdeb9Sandvar 	 * although this means the function will assume things about
2107d4a1addSreinoud 	 * the structure of vidc_state. i.e. the first 256 words are
2117d4a1addSreinoud 	 * the palette array
2127d4a1addSreinoud 	 */
2137d4a1addSreinoud 
2147d4a1addSreinoud #define SAFER
2157d4a1addSreinoud 
2167d4a1addSreinoud #ifdef 	SAFER
2177d4a1addSreinoud #define INITVALUE 0
2187d4a1addSreinoud #else
2197d4a1addSreinoud #define INITVALUE 256
2207d4a1addSreinoud #endif
2217d4a1addSreinoud 
222758ec341Sbjh21 	for (counter = INITVALUE;
223758ec341Sbjh21 	     counter <= sizeof(struct vidc_state);
224758ec341Sbjh21 	     counter++) {
2257d4a1addSreinoud 		if (reg == tab[counter]) {
2267d4a1addSreinoud 			WriteWord ( vidc_base, reg | value );
2277d4a1addSreinoud 			current[counter] = value;
2287d4a1addSreinoud 			return 0;
2297d4a1addSreinoud 		}
2307d4a1addSreinoud 	}
2317d4a1addSreinoud 	return -1;
2327d4a1addSreinoud }
2337d4a1addSreinoud 
2347d4a1addSreinoud 
2357d4a1addSreinoud void
vidcvideo_setpalette(struct vidc_state * vidc)236758ec341Sbjh21 vidcvideo_setpalette(struct vidc_state *vidc)
2377d4a1addSreinoud {
2387d4a1addSreinoud 	int counter = 0;
2397d4a1addSreinoud 
2407d4a1addSreinoud 	vidcvideo_write(VIDC_PALREG, 0x00000000);
2417ba11c51Sreinoud 	for (counter = 0; counter <= 255; counter++)
2427d4a1addSreinoud 		vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]);
2437d4a1addSreinoud }
2447d4a1addSreinoud 
2457d4a1addSreinoud 
2467d4a1addSreinoud void
vidcvideo_setstate(struct vidc_state * vidc)247758ec341Sbjh21 vidcvideo_setstate(struct vidc_state *vidc)
2487d4a1addSreinoud {
2497d4a1addSreinoud 	vidcvideo_write ( VIDC_PALREG,		vidc->palreg 	);
2507d4a1addSreinoud 	vidcvideo_write ( VIDC_BCOL,		vidc->bcol	);
2517d4a1addSreinoud 	vidcvideo_write ( VIDC_CP1,		vidc->cp1	);
2527d4a1addSreinoud 	vidcvideo_write ( VIDC_CP2,		vidc->cp2	);
2537d4a1addSreinoud 	vidcvideo_write ( VIDC_CP3,		vidc->cp3	);
2547d4a1addSreinoud 	vidcvideo_write ( VIDC_HCR,		vidc->hcr	);
2557d4a1addSreinoud 	vidcvideo_write ( VIDC_HSWR,		vidc->hswr	);
2567d4a1addSreinoud 	vidcvideo_write ( VIDC_HBSR,		vidc->hbsr	);
2577d4a1addSreinoud 	vidcvideo_write ( VIDC_HDSR,		vidc->hdsr	);
2587d4a1addSreinoud 	vidcvideo_write ( VIDC_HDER,		vidc->hder	);
2597d4a1addSreinoud 	vidcvideo_write ( VIDC_HBER,		vidc->hber	);
2607d4a1addSreinoud 	vidcvideo_write ( VIDC_HCSR,		vidc->hcsr	);
2617d4a1addSreinoud 	vidcvideo_write ( VIDC_HIR,		vidc->hir	);
2627d4a1addSreinoud 	vidcvideo_write ( VIDC_VCR,		vidc->vcr	);
2637d4a1addSreinoud 	vidcvideo_write ( VIDC_VSWR,		vidc->vswr	);
2647d4a1addSreinoud 	vidcvideo_write ( VIDC_VBSR,		vidc->vbsr	);
2657d4a1addSreinoud 	vidcvideo_write ( VIDC_VDSR,		vidc->vdsr	);
2667d4a1addSreinoud 	vidcvideo_write ( VIDC_VDER,		vidc->vder	);
2677d4a1addSreinoud 	vidcvideo_write ( VIDC_VBER,		vidc->vber	);
2687d4a1addSreinoud 	vidcvideo_write ( VIDC_VCSR,		vidc->vcsr	);
2697d4a1addSreinoud 	vidcvideo_write ( VIDC_VCER,		vidc->vcer	);
2707d4a1addSreinoud /*
2717d4a1addSreinoud  * Right, dunno what to set these to yet, but let's keep RiscOS's
2727d4a1addSreinoud  * ones for now, until the time is right to finish this code
2737d4a1addSreinoud  */
2747d4a1addSreinoud 
2757d4a1addSreinoud /*	vidcvideo_write ( VIDC_EREG,		vidc->ereg	);	*/
2767d4a1addSreinoud /*	vidcvideo_write ( VIDC_FSYNREG,	vidc->fsynreg	);	*/
2777d4a1addSreinoud /*	vidcvideo_write ( VIDC_CONREG,	vidc->conreg	);	*/
2787d4a1addSreinoud /*	vidcvideo_write ( VIDC_DCTL,		vidc->dctl	);	*/
2797d4a1addSreinoud 
2807ba11c51Sreinoud 	vidcvideo_setpalette(vidc);
2817d4a1addSreinoud }
2827d4a1addSreinoud 
2837d4a1addSreinoud 
2847d4a1addSreinoud void
vidcvideo_getstate(struct vidc_state * vidc)285758ec341Sbjh21 vidcvideo_getstate(struct vidc_state *vidc)
2867d4a1addSreinoud {
287758ec341Sbjh21 
2887d4a1addSreinoud 	*vidc = *vidc_current;
2897d4a1addSreinoud }
2907d4a1addSreinoud 
2917d4a1addSreinoud 
2927d4a1addSreinoud void
vidcvideo_getmode(struct vidc_mode * mode)293758ec341Sbjh21 vidcvideo_getmode(struct vidc_mode *mode)
2947d4a1addSreinoud {
295758ec341Sbjh21 
29672cec937Sbjh21 	*mode = vidc_currentmode;
2977d4a1addSreinoud }
2987d4a1addSreinoud 
2997d4a1addSreinoud 
3007d4a1addSreinoud static int
vidcvideo_coldinit(void)3017d4a1addSreinoud vidcvideo_coldinit(void)
3027d4a1addSreinoud {
3039dc302feSbjh21 	struct videomode const *modes;
30463030ccaSbjh21 	unsigned besterror;
3059dc302feSbjh21 	int count;
30628d9a9e3Sbjh21 	int i;
3071e6fe5d0Sbjh21 	unsigned framerate;
3087d4a1addSreinoud 
3097d4a1addSreinoud 	/* Blank out the cursor */
3107d4a1addSreinoud 
3117d4a1addSreinoud 	vidcvideo_write(VIDC_CP1, 0x0);
3127d4a1addSreinoud 	vidcvideo_write(VIDC_CP2, 0x0);
3137d4a1addSreinoud 	vidcvideo_write(VIDC_CP3, 0x0);
3147d4a1addSreinoud 
3157d4a1addSreinoud 	dispbase = vmem_base = dispstart = videomemory.vidm_vbase;
3167d4a1addSreinoud 	phys_base = videomemory.vidm_pbase;
3177d4a1addSreinoud 
3187d4a1addSreinoud 	/* Nut - should be using videomemory.vidm_size - mark */
3197d4a1addSreinoud 	if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) {
3207d4a1addSreinoud 		dispsize = videomemory.vidm_size;
3217d4a1addSreinoud 		transfersize = 16;
3227d4a1addSreinoud 	} else {
32395281cabSthorpej 		dispsize = bootconfig.vram[0].pages * PAGE_SIZE;
3247d4a1addSreinoud 		transfersize = dispsize >> 10;
325758ec341Sbjh21 	}
3267d4a1addSreinoud 
3277d4a1addSreinoud 	ptov = dispbase - phys_base;
3287d4a1addSreinoud 
3297d4a1addSreinoud 	dispend = dispstart+dispsize;
3307d4a1addSreinoud 
3319dc302feSbjh21 	if (vidc_videomode_count > 0) {
3329dc302feSbjh21 		modes = vidc_videomode_list;
3339dc302feSbjh21 		count = vidc_videomode_count;
3349dc302feSbjh21 	} else {
3359dc302feSbjh21 		modes = videomode_list;
3369dc302feSbjh21 		count = videomode_count;
3379dc302feSbjh21 	}
3389dc302feSbjh21 
3397d4a1addSreinoud 	/* try to find the current mode from the bootloader in my table */
3409dc302feSbjh21 	vidc_currentmode.timings = modes[0];
34163030ccaSbjh21 	besterror = 1000000;
3429dc302feSbjh21 	for (i = 0; i < count; i++) {
343a296cdc1Sbjh21 		/* We don't support interlace or doublescan */
344a296cdc1Sbjh21 		if (modes[i].flags & (VID_INTERLACE | VID_DBLSCAN))
345a296cdc1Sbjh21 			continue;
3461e6fe5d0Sbjh21 		/*
3471e6fe5d0Sbjh21 		 * We jump through a few hoops here to ensure that we
3481e6fe5d0Sbjh21 		 * round roughly to the nearest integer without too
3491e6fe5d0Sbjh21 		 * much danger of overflow.
3501e6fe5d0Sbjh21 		 */
3519dc302feSbjh21 		framerate = (modes[i].dot_clock * 1000 /
3529dc302feSbjh21 		    modes[i].htotal * 2 / modes[i].vtotal + 1) / 2;
3539dc302feSbjh21   		if (modes[i].hdisplay == bootconfig.width + 1
3549dc302feSbjh21   		    && modes[i].vdisplay == bootconfig.height + 1
35563030ccaSbjh21 		    && abs(framerate - bootconfig.framerate) < besterror) {
3569dc302feSbjh21 			vidc_currentmode.timings = modes[i];
35763030ccaSbjh21 			besterror = abs(framerate - bootconfig.framerate);
3587d4a1addSreinoud 		}
3597d4a1addSreinoud 	}
3607d4a1addSreinoud 
36172cec937Sbjh21 	vidc_currentmode.log2_bpp = bootconfig.log2_bpp;
3627d4a1addSreinoud 
3637d4a1addSreinoud 	dispstart = dispbase;
3647d4a1addSreinoud 	dispend = dispstart+dispsize;
3657d4a1addSreinoud 
3667d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
3677d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
3687d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
3697d4a1addSreinoud 	return 0;
3707d4a1addSreinoud }
3717d4a1addSreinoud 
3727d4a1addSreinoud 
3737d4a1addSreinoud /* simple function to abstract vidc variables ; returns virt start address of screen */
374a136e22aSandvar /* XXX assumption that video memory is mapped in twice */
vidcvideo_hwscroll(int bytes)375758ec341Sbjh21 void *vidcvideo_hwscroll(int bytes)
376758ec341Sbjh21 {
377758ec341Sbjh21 
3787d4a1addSreinoud 	dispstart += bytes;
3797d4a1addSreinoud 	if (dispstart >= dispbase + dispsize) dispstart -= dispsize;
3807d4a1addSreinoud 	if (dispstart <  dispbase)            dispstart += dispsize;
3817d4a1addSreinoud 	dispend = dispstart+dispsize;
3827d4a1addSreinoud 
3837d4a1addSreinoud 	/* return the start of the bit map of the screen (left top) */
3847d4a1addSreinoud 	return (void *)dispstart;
3857d4a1addSreinoud }
3867d4a1addSreinoud 
3877d4a1addSreinoud 
3887d4a1addSreinoud /* reset the HW scroll to be at the start for the benefit of f.e. X */
vidcvideo_hwscroll_reset(void)389758ec341Sbjh21 void *vidcvideo_hwscroll_reset(void)
390758ec341Sbjh21 {
3917d4a1addSreinoud 	void *cookie = (void *)dispstart;
3927d4a1addSreinoud 
3937d4a1addSreinoud 	dispstart = dispbase;
3947d4a1addSreinoud 	dispend = dispstart + dispsize;
3957d4a1addSreinoud 	return cookie;
3967d4a1addSreinoud }
3977d4a1addSreinoud 
3987d4a1addSreinoud 
3997d4a1addSreinoud /* put HW scroll back to where it was */
vidcvideo_hwscroll_back(void * cookie)400758ec341Sbjh21 void *vidcvideo_hwscroll_back(void *cookie)
401758ec341Sbjh21 {
402758ec341Sbjh21 
4037d4a1addSreinoud 	dispstart = (int)cookie;
4047d4a1addSreinoud 	dispend = dispstart + dispsize;
4057d4a1addSreinoud 	return cookie;
4067d4a1addSreinoud }
4077d4a1addSreinoud 
4087d4a1addSreinoud 
4099f4a9600Sandvar /* this function is to be called preferably at vsync */
vidcvideo_progr_scroll(void)410758ec341Sbjh21 void vidcvideo_progr_scroll(void)
411758ec341Sbjh21 {
412758ec341Sbjh21 
4137d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
4147d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
4157d4a1addSreinoud 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
4167d4a1addSreinoud }
4177d4a1addSreinoud 
4187d4a1addSreinoud 
4197d4a1addSreinoud /*
4207d4a1addSreinoud  * Select a new mode by reprogramming the VIDC chip
4217d4a1addSreinoud  * XXX this part is known not to work for 32bpp
4227d4a1addSreinoud  */
4237d4a1addSreinoud 
4247d4a1addSreinoud struct vidc_mode newmode;
4257d4a1addSreinoud 
4267d4a1addSreinoud static const int bpp_mask_table[] = {
4277d4a1addSreinoud 	0,  /* 1bpp */
4287d4a1addSreinoud 	1,  /* 2bpp */
4297d4a1addSreinoud 	2,  /* 4bpp */
4307d4a1addSreinoud 	3,  /* 8bpp */
4317d4a1addSreinoud 	4,  /* 16bpp */
4327d4a1addSreinoud 	6   /* 32bpp */
4337d4a1addSreinoud };
4347d4a1addSreinoud 
4357d4a1addSreinoud 
4367d4a1addSreinoud void
vidcvideo_setmode(struct vidc_mode * mode)4377d4a1addSreinoud vidcvideo_setmode(struct vidc_mode *mode)
4387d4a1addSreinoud {
43928d9a9e3Sbjh21 	struct videomode *vm;
4407d4a1addSreinoud 	int bpp_mask;
4417d4a1addSreinoud         int ereg;
442eefdf030Sbjh21 	int best_r, best_v;
443eefdf030Sbjh21 	int least_error;
444eefdf030Sbjh21 	int r, v, f;
4457d4a1addSreinoud 
4467d4a1addSreinoud 	/*
447758ec341Sbjh21 	 * Find out what bit mask we need to or with the vidc20
448758ec341Sbjh21 	 * control register in order to generate the desired number of
449758ec341Sbjh21 	 * bits per pixel.  log_bpp is log base 2 of the number of
450758ec341Sbjh21 	 * bits per pixel.
4517d4a1addSreinoud 	 */
4527d4a1addSreinoud 
4537d4a1addSreinoud 	bpp_mask = bpp_mask_table[mode->log2_bpp];
4547d4a1addSreinoud 
45572cec937Sbjh21 	vidc_currentmode = *mode;
45672cec937Sbjh21 	vm = &vidc_currentmode.timings;
4577d4a1addSreinoud 
458eefdf030Sbjh21 	least_error = INT_MAX;
459eefdf030Sbjh21 	best_r = 0; best_v = 0;
4607d4a1addSreinoud 
461eefdf030Sbjh21 	for (v = 63; v > 0; v--) {
4627d4a1addSreinoud 		for (r = 63; r > 0; r--) {
4637d4a1addSreinoud 			f = ((v * vidc_fref) /1000) / r;
46428d9a9e3Sbjh21 			if (least_error >= abs(f - vm->dot_clock)) {
46528d9a9e3Sbjh21 				least_error =  abs(f - vm->dot_clock);
4667d4a1addSreinoud 				best_r = r;
4677d4a1addSreinoud 				best_v = v;
4687d4a1addSreinoud 			}
4697d4a1addSreinoud 		}
4707d4a1addSreinoud 	}
4717d4a1addSreinoud 
4727d4a1addSreinoud 	if (best_r > 63) best_r=63;
4737d4a1addSreinoud 	if (best_v > 63) best_v=63;
4747d4a1addSreinoud 	if (best_r < 1)  best_r= 1;
4757d4a1addSreinoud 	if (best_v < 1)  best_v= 1;
4767d4a1addSreinoud 
4777d4a1addSreinoud 	vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0);
478be3168abSreinoud 
47928d9a9e3Sbjh21 	/*
48028d9a9e3Sbjh21 	 * The translation from struct videomode to VIDC timings is made
48128d9a9e3Sbjh21 	 * fun by the fact that the VIDC counts from the start of the sync
48228d9a9e3Sbjh21 	 * pulse while struct videomode counts from the start of the display.
48328d9a9e3Sbjh21 	 */
48428d9a9e3Sbjh21 	vidcvideo_write(VIDC_HSWR, (vm->hsync_end - vm->hsync_start - 8) & ~1);
48528d9a9e3Sbjh21 	vidcvideo_write(VIDC_HBSR, (vm->htotal - vm->hsync_start - 12) & ~1);
48628d9a9e3Sbjh21 	vidcvideo_write(VIDC_HDSR, (vm->htotal - vm->hsync_start - 18) & ~1);
48728d9a9e3Sbjh21 	vidcvideo_write(VIDC_HDER,
48828d9a9e3Sbjh21 	    (vm->htotal - vm->hsync_start + vm->hdisplay - 18) & ~1);
48928d9a9e3Sbjh21 	vidcvideo_write(VIDC_HBER,
49028d9a9e3Sbjh21 	    (vm->htotal - vm->hsync_start + vm->hdisplay - 12) & ~1);
49128d9a9e3Sbjh21 	vidcvideo_write(VIDC_HCR, (vm->htotal - 8) & ~3);
4927d4a1addSreinoud 
49328d9a9e3Sbjh21 	vidcvideo_write(VIDC_VSWR, vm->vsync_end - vm->vsync_start - 1);
49428d9a9e3Sbjh21 	vidcvideo_write(VIDC_VBSR, vm->vtotal - vm->vsync_start - 1);
49528d9a9e3Sbjh21 	vidcvideo_write(VIDC_VDSR, vm->vtotal - vm->vsync_start - 1);
49628d9a9e3Sbjh21 	vidcvideo_write(VIDC_VDER,
49728d9a9e3Sbjh21 	    vm->vtotal - vm->vsync_start + vm->vdisplay - 1);
49828d9a9e3Sbjh21 	vidcvideo_write(VIDC_VBER,
49928d9a9e3Sbjh21 	    vm->vtotal - vm->vsync_start + vm->vdisplay - 1);
50028d9a9e3Sbjh21 	/* XXX VIDC20 data sheet say to subtract 2 */
50128d9a9e3Sbjh21 	vidcvideo_write(VIDC_VCR, vm->vtotal - 1);
5027d4a1addSreinoud 
503983692f3Sbjh21 	IOMD_WRITE_WORD(IOMD_FSIZE, vm->vtotal - vm->vdisplay - 1);
5047d4a1addSreinoud 
5057d4a1addSreinoud 	if (dispsize <= 1024*1024)
50628d9a9e3Sbjh21 		vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 1<<16 | 1<<12);
5077d4a1addSreinoud 	else
50828d9a9e3Sbjh21 		vidcvideo_write(VIDC_DCTL, vm->hdisplay>>2 | 3<<16 | 1<<12);
5097d4a1addSreinoud 
5107d4a1addSreinoud 	ereg = 1<<12;
51128d9a9e3Sbjh21 	if (vm->flags & VID_NHSYNC)
5127d4a1addSreinoud 		ereg |= 1<<16;
51328d9a9e3Sbjh21 	if (vm->flags & VID_NVSYNC)
5147d4a1addSreinoud 		ereg |= 1<<18;
5157d4a1addSreinoud 	vidcvideo_write(VIDC_EREG, ereg);
5161aeaeb0eSbjh21 
5171aeaeb0eSbjh21 	/*
5181aeaeb0eSbjh21 	 * Set the video FIFO preload value and bit depth.  Chapter 6
5191aeaeb0eSbjh21 	 * of the VIDC20 Data Sheet has full details of the FIFO
5201aeaeb0eSbjh21 	 * preload, but we don't do anything clever and just use the
5211aeaeb0eSbjh21 	 * largest possible value, which is 7 when the VIDC20 is in
5221aeaeb0eSbjh21 	 * 32-bit mode (0MB or 1MB VRAM) and 6 when it is in 64-bit
5231aeaeb0eSbjh21 	 * mode (2MB VRAM).
5241aeaeb0eSbjh21 	 */
5251aeaeb0eSbjh21 	if (dispsize > 1024*1024)
5267d4a1addSreinoud 		vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
5271aeaeb0eSbjh21 	else
5287d4a1addSreinoud 		vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
5297d4a1addSreinoud }
5307d4a1addSreinoud 
5317d4a1addSreinoud 
532c1f8e3aaSbjh21 #if 0
5337d4a1addSreinoud /* not used for now */
5347d4a1addSreinoud void
535454af1c0Sdsl vidcvideo_set_display_base(u_int base)
5367d4a1addSreinoud {
5377d4a1addSreinoud 	dispstart = dispstart-dispbase + base;
5387d4a1addSreinoud 	dispbase = vmem_base = base;
5397d4a1addSreinoud 	dispend = base + dispsize;
5407d4a1addSreinoud 	ptov = dispbase - phys_base;
5417d4a1addSreinoud }
542c1f8e3aaSbjh21 #endif
5437d4a1addSreinoud 
5447d4a1addSreinoud 
5457d4a1addSreinoud /*
5467d4a1addSreinoud  * Main initialisation routine for now
5477d4a1addSreinoud  */
5487d4a1addSreinoud 
5497d4a1addSreinoud static int cursor_init = 0;
5507d4a1addSreinoud 
5517d4a1addSreinoud int
vidcvideo_init(void)5527d4a1addSreinoud vidcvideo_init(void)
5537d4a1addSreinoud {
5547d4a1addSreinoud 	vidcvideo_coldinit();
5557d4a1addSreinoud 	if (cold_init && (cursor_init == 0))
5567d4a1addSreinoud 		/*	vidcvideo_flash_go() */;
5577d4a1addSreinoud 
5587d4a1addSreinoud 	/* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */
55972cec937Sbjh21 	vidcvideo_setmode(&vidc_currentmode);
5607d4a1addSreinoud 	vidcvideo_blank(0);			/* display on */
5617d4a1addSreinoud 
5621dda0b46Sbjh21 	vidcvideo_stdpalette();
5637d4a1addSreinoud 
5647d4a1addSreinoud 	if (cold_init == 0) {
5657d4a1addSreinoud 		vidcvideo_write(VIDC_CP1, 0x0);
5667d4a1addSreinoud 		vidcvideo_write(VIDC_CP2, 0x0);
5677d4a1addSreinoud 		vidcvideo_write(VIDC_CP3, 0x0);
568758ec341Sbjh21 	} else
5697d4a1addSreinoud 		vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT);
5707d4a1addSreinoud 
5717d4a1addSreinoud 	cold_init = 1;
5727d4a1addSreinoud 	return 0;
5737d4a1addSreinoud }
5747d4a1addSreinoud 
5757d4a1addSreinoud 
5767d4a1addSreinoud /* reinitialise the vidcvideo */
5777d4a1addSreinoud void
vidcvideo_reinit(void)578ebceae53Scegger vidcvideo_reinit(void)
5797d4a1addSreinoud {
580758ec341Sbjh21 
5817d4a1addSreinoud 	vidcvideo_coldinit();
58272cec937Sbjh21 	vidcvideo_setmode(&vidc_currentmode);
5837d4a1addSreinoud }
5847d4a1addSreinoud 
5857d4a1addSreinoud 
5867d4a1addSreinoud int
vidcvideo_cursor_init(int width,int height)5877d4a1addSreinoud vidcvideo_cursor_init(int width, int height)
5887d4a1addSreinoud {
5897d4a1addSreinoud 	static char *cursor_data = NULL;
5907d4a1addSreinoud 	int counter;
5917d4a1addSreinoud 	int line;
5927d4a1addSreinoud 	paddr_t pa;
5937d4a1addSreinoud 
5947d4a1addSreinoud 	cursor_width  = width;
5957d4a1addSreinoud 	cursor_height = height;
5967d4a1addSreinoud 
5977d4a1addSreinoud 	if (!cursor_data) {
5987d4a1addSreinoud 		/* Allocate cursor memory first time round */
5996b2d8b66Syamt 		cursor_data = (char *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
6006b2d8b66Syamt 		    UVM_KMF_WIRED | UVM_KMF_ZERO);
6017d4a1addSreinoud 		if (!cursor_data)
6020f09ed48Sprovos 			panic("Cannot allocate memory for hardware cursor");
6037d4a1addSreinoud 		(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa);
6047d4a1addSreinoud 		IOMD_WRITE_WORD(IOMD_CURSINIT, pa);
6057d4a1addSreinoud 	}
6067d4a1addSreinoud 
607f0a7346dSsnj 	/* Blank the cursor while initialising its sprite */
6087d4a1addSreinoud 
6097d4a1addSreinoud 	vidcvideo_write ( VIDC_CP1, 0x0 );
6107d4a1addSreinoud 	vidcvideo_write ( VIDC_CP2, 0x0 );
6117d4a1addSreinoud 	vidcvideo_write ( VIDC_CP3, 0x0 );
6127d4a1addSreinoud 
6137d4a1addSreinoud  	cursor_normal       = cursor_data;
6147d4a1addSreinoud 	cursor_transparent  = cursor_data + (height * width);
6157d4a1addSreinoud 
6167d4a1addSreinoud  	cursor_transparent += 32;					/* ALIGN */
6177d4a1addSreinoud 	cursor_transparent = (char *)((int)cursor_transparent & (~31) );
6187d4a1addSreinoud 
619758ec341Sbjh21 	for ( line = 0; line<height; ++line ) {
6207d4a1addSreinoud 		for ( counter=0; counter<width/4;counter++ )
6217d4a1addSreinoud 			cursor_normal[line * width + counter]=0x55;		/* why 0x55 ? */
6227d4a1addSreinoud 		for ( ; counter<8; counter++ )
6237d4a1addSreinoud 			cursor_normal[line * width + counter]=0;
6247d4a1addSreinoud 	}
6257d4a1addSreinoud 
626758ec341Sbjh21 	for ( line = 0; line<height; ++line ) {
6277d4a1addSreinoud 		for ( counter=0; counter<width/4;counter++ )
6287d4a1addSreinoud 			cursor_transparent[line * width + counter]=0x00;
6297d4a1addSreinoud 		for ( ; counter<8; counter++ )
6307d4a1addSreinoud 			cursor_transparent[line * width + counter]=0;
6317d4a1addSreinoud 	}
6327d4a1addSreinoud 
6337d4a1addSreinoud 
6347d4a1addSreinoud 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal,
635b9d20d13Smatt 	    (void *)&p_cursor_normal);
6367d4a1addSreinoud 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent,
637b9d20d13Smatt 	    (void *)&p_cursor_transparent);
6387d4a1addSreinoud 
6397d4a1addSreinoud 	memset(cursor_normal, 0x55, width*height);		/* white? */
6407d4a1addSreinoud 	memset(cursor_transparent, 0x00, width*height);/* to see the diffence */
6417d4a1addSreinoud 
6427d4a1addSreinoud 	/* Ok, now program the cursor; should be blank */
6437d4a1addSreinoud 	vidcvideo_enablecursor(0);
6447d4a1addSreinoud 
6457d4a1addSreinoud         return 0;
6467d4a1addSreinoud }
6477d4a1addSreinoud 
6487d4a1addSreinoud 
6497d4a1addSreinoud void
vidcvideo_updatecursor(int xcur,int ycur)650758ec341Sbjh21 vidcvideo_updatecursor(int xcur, int ycur)
6517d4a1addSreinoud {
65272cec937Sbjh21 	int frontporch = vidc_currentmode.timings.htotal -
65372cec937Sbjh21 	    vidc_currentmode.timings.hsync_start;
65472cec937Sbjh21 	int topporch   =  vidc_currentmode.timings.vtotal -
65572cec937Sbjh21 	    vidc_currentmode.timings.vsync_start;
6567d4a1addSreinoud 
6577d4a1addSreinoud 	vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur);
658758ec341Sbjh21 	vidcvideo_write(VIDC_VCSR, topporch   -2  + (ycur+1)-2 + 3 -
659758ec341Sbjh21 	    cursor_height);
6607d4a1addSreinoud 	vidcvideo_write(VIDC_VCER, topporch   -2  + (ycur+3)+2 + 3 );
6617d4a1addSreinoud }
6627d4a1addSreinoud 
6637d4a1addSreinoud 
6647d4a1addSreinoud void
vidcvideo_enablecursor(int on)665758ec341Sbjh21 vidcvideo_enablecursor(int on)
6667d4a1addSreinoud {
6677d4a1addSreinoud 
668758ec341Sbjh21 	if (on)
669758ec341Sbjh21 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal);
670758ec341Sbjh21 	else
671758ec341Sbjh21 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent);
672758ec341Sbjh21 	vidcvideo_write ( VIDC_CP1, 0xffffff );		/* enable */
6737d4a1addSreinoud }
6747d4a1addSreinoud 
6757d4a1addSreinoud 
6761dda0b46Sbjh21 void
vidcvideo_stdpalette(void)677ebceae53Scegger vidcvideo_stdpalette(void)
67805012290Sbjh21 {
6791dda0b46Sbjh21 	int i;
6801dda0b46Sbjh21 
68172cec937Sbjh21 	switch (vidc_currentmode.log2_bpp) {
6821dda0b46Sbjh21 	case 0: /* 1 bpp */
6831dda0b46Sbjh21 	case 1: /* 2 bpp */
6841dda0b46Sbjh21 	case 2: /* 4 bpp */
6851dda0b46Sbjh21 	case 3: /* 8 bpp */
68605012290Sbjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
68705012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
68805012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0,   0));
68905012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255,   0));
69005012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255,   0));
69105012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0, 255));
69205012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0, 255));
69305012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255, 255));
69405012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
69505012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
69605012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
69705012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
69805012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
69905012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
70005012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
70105012290Sbjh21 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
7021dda0b46Sbjh21 		break;
7031dda0b46Sbjh21 	case 4: /* 16 bpp */
7041dda0b46Sbjh21 		/*
7051dda0b46Sbjh21 		 * The use of the palette in 16-bit modes is quite
7061dda0b46Sbjh21 		 * fun.  Comments in linux/drivers/video/acornfb.c
7071dda0b46Sbjh21 		 * imply that it goes something like this:
7081dda0b46Sbjh21 		 *
7091dda0b46Sbjh21 		 * red   = LUT[pixel[7:0]].red
7101dda0b46Sbjh21 		 * green = LUT[pixel[11:4]].green
7111dda0b46Sbjh21 		 * blue  = LUT[pixel[15:8]].blue
7121dda0b46Sbjh21 		 *
713a7f52777Sbjh21 		 * We use 6:5:5 R:G:B cos that's what Xarm32VIDC wants.
7141dda0b46Sbjh21 		 */
715a7f52777Sbjh21 #define RBITS 6
716a7f52777Sbjh21 #define GBITS 5
717a7f52777Sbjh21 #define BBITS 5
7181dda0b46Sbjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
7191dda0b46Sbjh21 		for (i = 0; i < 256; i++) {
720a7f52777Sbjh21 			int r, g, b;
72105012290Sbjh21 
722a7f52777Sbjh21 			r = i & ((1 << RBITS) - 1);
723a7f52777Sbjh21 			g = (i >> (RBITS - 4)) & ((1 << GBITS) - 1);
724a7f52777Sbjh21 			b = (i >> (RBITS + GBITS - 8)) & ((1 << BBITS) - 1);
7251dda0b46Sbjh21 			vidcvideo_write(VIDC_PALETTE,
726a7f52777Sbjh21 			    VIDC_COL(r << (8 - RBITS) | r >> (2 * RBITS - 8),
727a7f52777Sbjh21 				g << (8 - GBITS) | g >> (2 * GBITS - 8),
728a7f52777Sbjh21 				b << (8 - BBITS) | b >> (2 * BBITS - 8)));
7291dda0b46Sbjh21 		}
7301dda0b46Sbjh21 		break;
7311dda0b46Sbjh21 	case 5: /* 32 bpp */
7321dda0b46Sbjh21 		vidcvideo_write(VIDC_PALREG, 0x00000000);
7331dda0b46Sbjh21 		for (i = 0; i < 256; i++)
7341dda0b46Sbjh21 			vidcvideo_write(VIDC_PALETTE, VIDC_COL(i, i, i));
7351dda0b46Sbjh21 		break;
7361dda0b46Sbjh21 	}
73705012290Sbjh21 }
73805012290Sbjh21 
73905012290Sbjh21 int
vidcvideo_blank(int video_off)740758ec341Sbjh21 vidcvideo_blank(int video_off)
7417d4a1addSreinoud {
7427d4a1addSreinoud         int ereg;
7437d4a1addSreinoud 
7447d4a1addSreinoud 	ereg = 1<<12;
74572cec937Sbjh21 	if (vidc_currentmode.timings.flags & VID_NHSYNC)
7467d4a1addSreinoud 		ereg |= 1<<16;
74772cec937Sbjh21 	if (vidc_currentmode.timings.flags & VID_NVSYNC)
7487d4a1addSreinoud 		ereg |= 1<<18;
7497d4a1addSreinoud 
750758ec341Sbjh21 	if (!video_off)
7517d4a1addSreinoud     		vidcvideo_write(VIDC_EREG, ereg);
752758ec341Sbjh21 	else
7537d4a1addSreinoud 		vidcvideo_write(VIDC_EREG, 0);
7547d4a1addSreinoud 	return 0;
7557d4a1addSreinoud }
7567d4a1addSreinoud 
7577d4a1addSreinoud /* end of vidc20config.c */
758