Home | History | Annotate | Line # | Download | only in iomd
vidc20config.c revision 1.2
      1 /*	$NetBSD: vidc20config.c,v 1.2 2001/10/17 23:28:20 reinoud Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2001 Reinoud Zandijk
      5  * Copyright (c) 1996 Mark Brinicombe
      6  * Copyright (c) 1996 Robert Black
      7  * Copyright (c) 1994-1995 Melvyn Tang-Richardson
      8  * Copyright (c) 1994-1995 RiscBSD kernel team
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the RiscBSD kernel team
     22  * 4. The name of the company nor the name of the author may be used to
     23  *    endorse or promote products derived from this software without specific
     24  *    prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE RISCBSD TEAM ``AS IS'' AND ANY EXPRESS
     27  * OR IMPLIED  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     28  * WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     36  * THE POSSIBILITY OF SUCH DAMAGE.
     37  *
     38  * NetBSD kernel project
     39  *
     40  * vidcvideo.c
     41  *
     42  * This file is the lower basis of the wscons driver for VIDC based ARM machines.
     43  * It features the initialisation and all VIDC writing and keeps in internal state
     44  * copy.
     45  * Its currenly set up as a library file and not as a device; it could be named
     46  * vidcvideo0 eventually.
     47  */
     48 
     49 #include <sys/cdefs.h>
     50 #include <sys/types.h>
     51 #include <sys/param.h>
     52 #include <arm/iomd/vidc.h>
     53 #include <machine/katelib.h>
     54 #include <machine/bootconfig.h>
     55 #include <machine/irqhandler.h>
     56 
     57 #include <sys/systm.h>
     58 #include <sys/device.h>
     59 #include <uvm/uvm_extern.h>
     60 
     61 #include <arm/iomd/iomdreg.h>
     62 #include <arm/iomd/iomdvar.h>
     63 #include <arm/iomd/vidc20config.h>
     64 
     65 /*
     66  * A structure containing ALL the information required to restore
     67  * the VIDC20 to any given state.  ALL vidc transactions should
     68  * go through these procedures, which record the vidc's state.
     69  * it may be an idea to set the permissions of the vidc base address
     70  * so we get a fault, so the fault routine can record the state but
     71  * I guess that's not really necessary for the time being, since we
     72  * can make the kernel more secure later on.  Also, it is possible
     73  * to write a routine to allow 'reading' of the vidc registers.
     74  */
     75 
     76 static struct vidc_state vidc_lookup = {
     77 	{ 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,
     78           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,
     79           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,
     80           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,
     81           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,
     82           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,
     83           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,
     84           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
     85 	},
     86 
     87 	VIDC_PALREG,
     88 	VIDC_BCOL,
     89 	VIDC_CP1 ,
     90 	VIDC_CP2,
     91 	VIDC_CP3,
     92 	VIDC_HCR,
     93 	VIDC_HSWR,
     94 	VIDC_HBSR,
     95 	VIDC_HDSR,
     96 	VIDC_HDER,
     97 	VIDC_HBER,
     98 	VIDC_HCSR,
     99 	VIDC_HIR,
    100 	VIDC_VCR,
    101 	VIDC_VSWR,
    102 	VIDC_VBSR,
    103 	VIDC_VDSR,
    104 	VIDC_VDER,
    105 	VIDC_VBER,
    106 	VIDC_VCSR,
    107 	VIDC_VCER,
    108 	VIDC_EREG,
    109 	VIDC_FSYNREG,
    110 	VIDC_CONREG,
    111 	VIDC_DCTL
    112 };
    113 
    114 struct vidc_state vidc_current[1];
    115 
    116 
    117 /*
    118  * Structures defining clock frequenties and their settings...
    119  * move to a constants header file ?
    120  */
    121 
    122 struct fsyn {
    123 	int r, v, f;
    124 };
    125 
    126 static struct fsyn fsyn_pref[] = {
    127 	{ 6,   2,  8000 },
    128 	{ 4,   2, 12000 },
    129 	{ 3,   2, 16000 },
    130 	{ 2,   2, 24000 },
    131 	{ 41, 43, 25171 },
    132 	{ 50, 59, 28320 },
    133 	{ 3,   4, 32000 },
    134 	{ 2,   3, 36000 },
    135 	{ 31, 58, 44903 },
    136 	{ 12, 35, 70000 },
    137 	{ 0,   0, 00000 }
    138 };
    139 
    140 
    141 /*
    142  * XXX global display variables XXX ... should be a structure
    143  */
    144 static int cold_init = 0;		/* flags initialisation */
    145 extern videomemory_t videomemory;
    146 
    147 static struct vidc_mode vidc_initialmode;
    148 static struct vidc_mode *vidc_currentmode;
    149 
    150 unsigned int dispstart;
    151 unsigned int dispsize;
    152 unsigned int dispbase;
    153 unsigned int dispend;
    154 unsigned int ptov;
    155 unsigned int vmem_base;
    156 unsigned int phys_base;
    157 unsigned int transfersize;
    158 
    159 
    160 /* cursor stuff */
    161 char *cursor_normal;
    162 char *cursor_transparent;
    163 int p_cursor_normal;
    164 int p_cursor_transparent;
    165 int cursor_width;
    166 int cursor_height;
    167 
    168 
    169 /*
    170  * VIDC mode definitions
    171  * generated from RISC OS mode definition file by an `awk' script
    172  */
    173 extern struct vidc_mode vidcmodes[];
    174 
    175 
    176 /*
    177  * configuration printing
    178  *
    179  */
    180 
    181 void
    182 vidcvideo_printdetails(void)
    183 {
    184         printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000),
    185             videomemory.vidm_size / 1024,
    186             (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM");
    187 }
    188 
    189 /*
    190  * Common functions to directly access VIDC registers
    191  */
    192 int
    193 vidcvideo_write(reg, value)
    194 	u_int reg;
    195 	int value;
    196 {
    197 	int counter;
    198 
    199 	int *current;
    200 	int *tab;
    201 
    202 	tab 	= (int *)&vidc_lookup;
    203 	current = (int *)vidc_current;
    204 
    205 
    206 	/*
    207 	 * OK, the VIDC_PALETTE register is handled differently
    208 	 * to the others on the VIDC, so take that into account here
    209 	 */
    210 	if (reg==VIDC_PALREG) {
    211 		vidc_current->palreg = 0;
    212 		WriteWord(vidc_base, reg | value);
    213 		return 0;
    214 	}
    215 
    216 	if (reg==VIDC_PALETTE) {
    217 		WriteWord(vidc_base, reg | value);
    218 		vidc_current->palette[vidc_current->palreg] = value;
    219 		vidc_current->palreg++;
    220 		vidc_current->palreg = vidc_current->palreg & 0xff;
    221 		return 0;
    222 	}
    223 
    224 	/*
    225 	 * Undefine SAFER if you wish to speed things up (a little)
    226 	 * although this means the function will assume things abou
    227 	 * the structure of vidc_state. i.e. the first 256 words are
    228 	 * the palette array
    229 	 */
    230 
    231 #define SAFER
    232 
    233 #ifdef 	SAFER
    234 #define INITVALUE 0
    235 #else
    236 #define INITVALUE 256
    237 #endif
    238 
    239 	for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) {
    240 		if ( reg==tab[counter] ) {
    241 			WriteWord ( vidc_base, reg | value );
    242 			current[counter] = value;
    243 			return 0;
    244 		}
    245 	}
    246 	return -1;
    247 }
    248 
    249 
    250 void
    251 vidcvideo_setpalette(vidc)
    252 	struct vidc_state *vidc;
    253 {
    254 	int counter = 0;
    255 
    256 	vidcvideo_write(VIDC_PALREG, 0x00000000);
    257 	for (counter = 0; counter < 255; counter++)
    258 		vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]);
    259 }
    260 
    261 
    262 void
    263 vidcvideo_setstate(vidc)
    264 	struct vidc_state *vidc;
    265 {
    266 	vidcvideo_write ( VIDC_PALREG,	vidc->palreg 	);
    267 	vidcvideo_write ( VIDC_BCOL,		vidc->bcol	);
    268 	vidcvideo_write ( VIDC_CP1,		vidc->cp1	);
    269 	vidcvideo_write ( VIDC_CP2,		vidc->cp2	);
    270 	vidcvideo_write ( VIDC_CP3,		vidc->cp3	);
    271 	vidcvideo_write ( VIDC_HCR,		vidc->hcr	);
    272 	vidcvideo_write ( VIDC_HSWR,		vidc->hswr	);
    273 	vidcvideo_write ( VIDC_HBSR,		vidc->hbsr	);
    274 	vidcvideo_write ( VIDC_HDSR,		vidc->hdsr	);
    275 	vidcvideo_write ( VIDC_HDER,		vidc->hder	);
    276 	vidcvideo_write ( VIDC_HBER,		vidc->hber	);
    277 	vidcvideo_write ( VIDC_HCSR,		vidc->hcsr	);
    278 	vidcvideo_write ( VIDC_HIR,		vidc->hir	);
    279 	vidcvideo_write ( VIDC_VCR,		vidc->vcr	);
    280 	vidcvideo_write ( VIDC_VSWR,		vidc->vswr	);
    281 	vidcvideo_write ( VIDC_VBSR,		vidc->vbsr	);
    282 	vidcvideo_write ( VIDC_VDSR,		vidc->vdsr	);
    283 	vidcvideo_write ( VIDC_VDER,		vidc->vder	);
    284 	vidcvideo_write ( VIDC_VBER,		vidc->vber	);
    285 	vidcvideo_write ( VIDC_VCSR,		vidc->vcsr	);
    286 	vidcvideo_write ( VIDC_VCER,		vidc->vcer	);
    287 /*
    288  * Right, dunno what to set these to yet, but let's keep RiscOS's
    289  * ones for now, until the time is right to finish this code
    290  */
    291 
    292 /*	vidcvideo_write ( VIDC_EREG,		vidc->ereg	);	*/
    293 /*	vidcvideo_write ( VIDC_FSYNREG,	vidc->fsynreg	);	*/
    294 /*	vidcvideo_write ( VIDC_CONREG,	vidc->conreg	);	*/
    295 /*	vidcvideo_write ( VIDC_DCTL,		vidc->dctl	);	*/
    296 
    297 }
    298 
    299 
    300 void
    301 vidcvideo_getstate(vidc)
    302 	struct vidc_state *vidc;
    303 {
    304 	*vidc = *vidc_current;
    305 }
    306 
    307 
    308 void
    309 vidcvideo_getmode(mode)
    310 	struct vidc_mode *mode;
    311 {
    312 	*mode = *vidc_currentmode;
    313 }
    314 
    315 
    316 void
    317 vidcvideo_stdpalette()
    318 {
    319         WriteWord(vidc_base, VIDC_PALREG | 0x00000000);
    320         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(  0,   0,   0));
    321         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255,   0,   0));
    322         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(  0, 255,   0));
    323         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255,   0));
    324         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(  0,   0, 255));
    325         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255,   0, 255));
    326         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(  0, 255, 255));
    327         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 255));
    328         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 128, 128));
    329         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 128, 128));
    330         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 255, 128));
    331         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 128));
    332         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 128, 255));
    333         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 128, 255));
    334         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 255, 255));
    335         WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 255));
    336 }
    337 
    338 
    339 /* small inline mod function ... why here? */
    340 static __inline int
    341 mod(int n)
    342 {
    343 	if (n < 0)
    344 		return(-n);
    345 	else
    346 		return(n);
    347 }
    348 
    349 
    350 static int
    351 vidcvideo_coldinit(void)
    352 {
    353 	int found;
    354 	int loop;
    355 
    356 	/* Blank out the cursor */
    357 
    358 	vidcvideo_write(VIDC_CP1, 0x0);
    359 	vidcvideo_write(VIDC_CP2, 0x0);
    360 	vidcvideo_write(VIDC_CP3, 0x0);
    361 
    362 	/* Try to determine the current mode */
    363 	vidc_initialmode.hder     = bootconfig.width+1;
    364 	vidc_initialmode.vder     = bootconfig.height+1;
    365 	vidc_initialmode.log2_bpp = bootconfig.log2_bpp;
    366 
    367 	dispbase = vmem_base = dispstart = videomemory.vidm_vbase;
    368 	phys_base = videomemory.vidm_pbase;
    369 
    370 	/* Nut - should be using videomemory.vidm_size - mark */
    371 	if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) {
    372 		dispsize = videomemory.vidm_size;
    373 		transfersize = 16;
    374 	} else {
    375 		dispsize = bootconfig.vram[0].pages * NBPG;
    376 		transfersize = dispsize >> 10;
    377 	};
    378 
    379 	ptov = dispbase - phys_base;
    380 
    381 	dispend = dispstart+dispsize;
    382 
    383 	/* try to find the current mode from the bootloader in my table */
    384 	vidc_currentmode = &vidcmodes[0];
    385 	loop = 0;
    386 	found = 0;
    387 	while (vidcmodes[loop].pixel_rate != 0) {
    388   		if (vidcmodes[loop].hder == (bootconfig.width + 1)
    389   		    && vidcmodes[loop].vder == (bootconfig.height + 1)
    390 		    && vidcmodes[loop].frame_rate == bootconfig.framerate) {
    391 			vidc_currentmode = &vidcmodes[loop];
    392 			found = 1;
    393 		}
    394 		++loop;
    395 	}
    396 
    397 	/* if not found choose first mode but dont be picky on the framerate */
    398 	if (!found) {
    399 		vidc_currentmode = &vidcmodes[0];
    400 		loop = 0;
    401 		found = 0;
    402 
    403 		while (vidcmodes[loop].pixel_rate != 0) {
    404 			if (vidcmodes[loop].hder == (bootconfig.width + 1)
    405  			    && vidcmodes[loop].vder == (bootconfig.height + 1)) {
    406  				vidc_currentmode = &vidcmodes[loop];
    407  				found = 1;
    408  			}
    409  			++loop;
    410  		}
    411 	}
    412 
    413 	vidc_currentmode->log2_bpp = bootconfig.log2_bpp;
    414 
    415 	dispstart = dispbase;
    416 	dispend = dispstart+dispsize;
    417 
    418 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
    419 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
    420 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
    421 	return 0;
    422 }
    423 
    424 
    425 /* simple function to abstract vidc variables ; returns virt start address of screen */
    426 /* XXX asumption that video memory is mapped in twice */
    427 void *vidcvideo_hwscroll(int bytes) {
    428 	dispstart += bytes;
    429 	if (dispstart >= dispbase + dispsize) dispstart -= dispsize;
    430 	if (dispstart <  dispbase)            dispstart += dispsize;
    431 	dispend = dispstart+dispsize;
    432 
    433 	/* return the start of the bit map of the screen (left top) */
    434 	return (void *) dispstart;
    435 }
    436 
    437 
    438 /* reset the HW scroll to be at the start for the benefit of f.e. X */
    439 void *vidcvideo_hwscroll_reset(void) {
    440 	void *cookie = (void *) dispstart;
    441 
    442 	dispstart = dispbase;
    443 	dispend = dispstart + dispsize;
    444 	return cookie;
    445 }
    446 
    447 
    448 /* put HW scroll back to where it was */
    449 void *vidcvideo_hwscroll_back(void *cookie) {
    450 	dispstart = (int) cookie;
    451 	dispend = dispstart + dispsize;
    452 	return cookie;
    453 }
    454 
    455 
    456 /* this function is to be called at vsync */
    457 void vidcvideo_progr_scroll(void) {
    458 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
    459 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
    460 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
    461 }
    462 
    463 
    464 /*
    465  * Select a new mode by reprogramming the VIDC chip
    466  * XXX this part is known not to work for 32bpp
    467  */
    468 
    469 struct vidc_mode newmode;
    470 
    471 static const int bpp_mask_table[] = {
    472 	0,  /* 1bpp */
    473 	1,  /* 2bpp */
    474 	2,  /* 4bpp */
    475 	3,  /* 8bpp */
    476 	4,  /* 16bpp */
    477 	6   /* 32bpp */
    478 };
    479 
    480 
    481 void
    482 vidcvideo_setmode(struct vidc_mode *mode)
    483 {
    484 	register int acc;
    485 	int bpp_mask;
    486         int ereg;
    487 	int best_r, best_v, best_match;
    488 
    489 #ifdef NC
    490 return;
    491 #endif
    492 	/*
    493 	 * Find out what bit mask we need to or with the vidc20 control register
    494 	 * in order to generate the desired number of bits per pixel.
    495 	 * log_bpp is log base 2 of the number of bits per pixel.
    496 	 */
    497 
    498 	bpp_mask = bpp_mask_table[mode->log2_bpp];
    499 
    500 	newmode = *mode;
    501 	vidc_currentmode = &newmode;
    502 
    503 	/* Program the VCO Look-up to a preferred value before choosing one */
    504 	{
    505 		int least_error = mod(fsyn_pref[0].f - vidc_currentmode->pixel_rate);
    506 		int counter;
    507 		best_r = fsyn_pref[0].r;
    508 		best_match = fsyn_pref[0].f;
    509 		best_v = fsyn_pref[0].v;
    510 
    511 		/* Look up */
    512 		counter=0;
    513 		while (fsyn_pref[counter].r != 0) {
    514 			if (least_error > mod(fsyn_pref[counter].f - vidc_currentmode->pixel_rate)) {
    515 				best_match = fsyn_pref[counter].f;
    516 				least_error = mod(fsyn_pref[counter].f - vidc_currentmode->pixel_rate);
    517 				best_r = fsyn_pref[counter].r;
    518 				best_v = fsyn_pref[counter].v;
    519 			}
    520 			counter++;
    521 		}
    522 
    523 		if (least_error > 0) { /* Accuracy of 1000Hz */
    524 			int r, v, f;
    525 			for (v = 63; v > 0; v--)
    526 				for (r = 63; r > 0; r--) {
    527 					f = ((v * vidc_fref) /1000) / r;
    528 					if (least_error >= mod(f - vidc_currentmode->pixel_rate)) {
    529 						best_match = f;
    530 						least_error = mod(f - vidc_currentmode->pixel_rate);
    531 						best_r = r;
    532 						best_v = v;
    533 					}
    534 				}
    535 		}
    536 
    537 		if (best_r > 63) best_r=63;
    538 		if (best_v > 63) best_v=63;
    539 		if (best_r < 1)  best_r= 1;
    540 		if (best_v < 1)  best_v= 1;
    541 
    542 	}
    543 
    544 	vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0);
    545 
    546 	acc=0;
    547 	acc+=vidc_currentmode->hswr;	vidcvideo_write(VIDC_HSWR, (acc - 8 ) & (~1));
    548 	acc+=vidc_currentmode->hbsr;	vidcvideo_write(VIDC_HBSR, (acc - 12) & (~1));
    549 	acc+=vidc_currentmode->hdsr;	vidcvideo_write(VIDC_HDSR, (acc - 18) & (~1));
    550 	acc+=vidc_currentmode->hder;	vidcvideo_write(VIDC_HDER, (acc - 18) & (~1));
    551 	acc+=vidc_currentmode->hber;	vidcvideo_write(VIDC_HBER, (acc - 12) & (~1));
    552 	acc+=vidc_currentmode->hcr;	vidcvideo_write(VIDC_HCR,  (acc - 8 ) & (~3));
    553 
    554 	acc=0;
    555 	acc+=vidc_currentmode->vswr;	vidcvideo_write(VIDC_VSWR, (acc - 1));
    556 	acc+=vidc_currentmode->vbsr;	vidcvideo_write(VIDC_VBSR, (acc - 1));
    557 	acc+=vidc_currentmode->vdsr;	vidcvideo_write(VIDC_VDSR, (acc - 1));
    558 	acc+=vidc_currentmode->vder;	vidcvideo_write(VIDC_VDER, (acc - 1));
    559 	acc+=vidc_currentmode->vber;	vidcvideo_write(VIDC_VBER, (acc - 1));
    560 	acc+=vidc_currentmode->vcr;	vidcvideo_write(VIDC_VCR,  (acc - 1));
    561 
    562 	IOMD_WRITE_WORD(IOMD_FSIZE, vidc_currentmode->vcr
    563 	    + vidc_currentmode->vswr
    564 	    + vidc_currentmode->vber
    565 	    + vidc_currentmode->vbsr - 1);
    566 
    567 	if (dispsize <= 1024*1024)
    568 		vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
    569 	else
    570 		vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12);
    571 
    572 	ereg = 1<<12;
    573 	if (vidc_currentmode->sync_pol & 0x01)
    574 		ereg |= 1<<16;
    575 	if (vidc_currentmode->sync_pol & 0x02)
    576 		ereg |= 1<<18;
    577 	vidcvideo_write(VIDC_EREG, ereg);
    578 	if (dispsize > 1024*1024) {
    579 		if (vidc_currentmode->hder >= 800)
    580  			vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
    581 		else
    582 			vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
    583 	} else {
    584 		vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
    585 	}
    586 }
    587 
    588 
    589 /* not used for now */
    590 void
    591 vidcvideo_set_display_base(base)
    592 	u_int base;
    593 {
    594 	dispstart = dispstart-dispbase + base;
    595 	dispbase = vmem_base = base;
    596 	dispend = base + dispsize;
    597 	ptov = dispbase - phys_base;
    598 }
    599 
    600 
    601 /*
    602  * Main initialisation routine for now
    603  */
    604 
    605 static int cursor_init = 0;
    606 
    607 int
    608 vidcvideo_init(void)
    609 {
    610 	vidcvideo_coldinit();
    611 	if (cold_init && (cursor_init == 0))
    612 		/*	vidcvideo_flash_go() */;
    613 
    614 	/* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */
    615 	vidcvideo_setmode(vidc_currentmode);
    616 	vidcvideo_blank(0);			/* display on */
    617 
    618 	vidcvideo_textpalette();
    619 
    620 	if (cold_init == 0) {
    621 		vidcvideo_write(VIDC_CP1, 0x0);
    622 		vidcvideo_write(VIDC_CP2, 0x0);
    623 		vidcvideo_write(VIDC_CP3, 0x0);
    624 	} else {
    625 		vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT);
    626 	};
    627 
    628 	cold_init=1;
    629 	return 0;
    630 }
    631 
    632 
    633 /* reinitialise the vidcvideo */
    634 void
    635 vidcvideo_reinit()
    636 {
    637 	vidcvideo_coldinit();
    638 	vidcvideo_setmode(vidc_currentmode);
    639 }
    640 
    641 
    642 paddr_t
    643 vidcvideo_mmap(vc, offset, nprot)
    644 	struct vconsole *vc;
    645 	off_t offset;
    646 	int nprot;
    647 {
    648 	if ((u_int)offset >= videomemory.vidm_size)
    649 		return (-1);
    650 	return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
    651 }
    652 
    653 
    654 int
    655 vidcvideo_cursor_init(int width, int height)
    656 {
    657 	static char *cursor_data = NULL;
    658 	int counter;
    659 	int line;
    660 	paddr_t pa;
    661 
    662 	cursor_width  = width;
    663 	cursor_height = height;
    664 
    665 	if (!cursor_data) {
    666 		/* Allocate cursor memory first time round */
    667 		cursor_data = (char *)uvm_km_zalloc(kernel_map, NBPG);
    668 		if (!cursor_data)
    669 			panic("Cannot allocate memory for hardware cursor\n");
    670 		(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa);
    671 		IOMD_WRITE_WORD(IOMD_CURSINIT, pa);
    672 	}
    673 
    674 	/* Blank the cursor while initialising it's sprite */
    675 
    676 	vidcvideo_write ( VIDC_CP1, 0x0 );
    677 	vidcvideo_write ( VIDC_CP2, 0x0 );
    678 	vidcvideo_write ( VIDC_CP3, 0x0 );
    679 
    680  	cursor_normal       = cursor_data;
    681 	cursor_transparent  = cursor_data + (height * width);
    682 
    683  	cursor_transparent += 32;					/* ALIGN */
    684 	cursor_transparent = (char *)((int)cursor_transparent & (~31) );
    685 
    686 	for ( line = 0; line<height; ++ line )
    687 	{
    688 	    for ( counter=0; counter<width/4;counter++ )
    689 		cursor_normal[line * width + counter]=0x55;		/* why 0x55 ? */
    690 	    for ( ; counter<8; counter++ )
    691 		cursor_normal[line * width + counter]=0;
    692 	}
    693 
    694 	for ( line = 0; line<height; ++ line )
    695 	{
    696 	    for ( counter=0; counter<width/4;counter++ )
    697 		cursor_transparent[line * width + counter]=0x00;
    698 	    for ( ; counter<8; counter++ )
    699 		cursor_transparent[line * width + counter]=0;
    700 	}
    701 
    702 
    703 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal,
    704 	    (paddr_t *)&p_cursor_normal);
    705 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent,
    706 	    (paddr_t *)&p_cursor_transparent);
    707 
    708 	memset ( cursor_normal, 0x55, width*height );			/* white? */
    709 	memset ( cursor_transparent, 0x00, width*height );		/* to see the diffence */
    710 
    711 	/* Ok, now program the cursor; should be blank */
    712 	vidcvideo_enablecursor(0);
    713 
    714         return 0;
    715 }
    716 
    717 
    718 void
    719 vidcvideo_updatecursor(xcur, ycur)
    720 	int xcur, ycur;
    721 {
    722 	int frontporch = vidc_currentmode->hswr + vidc_currentmode->hbsr + vidc_currentmode->hdsr;
    723 	int topporch   = vidc_currentmode->vswr + vidc_currentmode->vbsr + vidc_currentmode->vdsr;
    724 
    725 	vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur);
    726 	vidcvideo_write(VIDC_VCSR, topporch   -2  + (ycur+1)-2 + 3 - cursor_height);
    727 	vidcvideo_write(VIDC_VCER, topporch   -2  + (ycur+3)+2 + 3 );
    728 	return;
    729 }
    730 
    731 
    732 void
    733 vidcvideo_enablecursor(on)
    734 	int on;
    735 {
    736 	if (on) {
    737 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal);
    738 	} else {
    739 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent);
    740 	};
    741 	vidcvideo_write ( VIDC_CP1, 0xffffff );		/* enable */
    742 
    743 	return;
    744 }
    745 
    746 
    747 int
    748 vidcvideo_textpalette()
    749 {
    750 	vidcvideo_write(VIDC_PALREG, 0x00000000);
    751 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
    752 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0,   0));
    753 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255,   0));
    754 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255,   0));
    755 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0, 255));
    756 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0, 255));
    757 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255, 255));
    758 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
    759 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
    760 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
    761 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
    762 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
    763 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
    764 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
    765 	vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
    766 
    767 	return 0;
    768 }
    769 
    770 int
    771 vidcvideo_blank(video_off)
    772 	int video_off;
    773 {
    774         int ereg;
    775 
    776 	ereg = 1<<12;
    777 	if (vidc_currentmode->sync_pol & 0x01)
    778 		ereg |= 1<<16;
    779 	if (vidc_currentmode->sync_pol & 0x02)
    780 		ereg |= 1<<18;
    781 
    782 	if (!video_off) {
    783     		vidcvideo_write(VIDC_EREG, ereg);
    784 	} else {
    785 		vidcvideo_write(VIDC_EREG, 0);
    786 	};
    787 	return 0;
    788 }
    789 
    790 /* end of vidc20config.c */
    791