xref: /netbsd/sys/arch/arm/iomd/vidc20config.c (revision c4a72b64)
1 /*	$NetBSD: vidc20config.c,v 1.15 2002/10/01 12:09:49 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 
51 __KERNEL_RCSID(0, "$NetBSD: vidc20config.c,v 1.15 2002/10/01 12:09:49 reinoud Exp $");
52 
53 #include <sys/types.h>
54 #include <sys/param.h>
55 #include <arm/iomd/vidc.h>
56 #include <arm/arm32/katelib.h>
57 #include <machine/bootconfig.h>
58 #include <machine/intr.h>
59 
60 #include <sys/systm.h>
61 #include <sys/device.h>
62 #include <uvm/uvm_extern.h>
63 
64 #include <arm/iomd/iomdreg.h>
65 #include <arm/iomd/iomdvar.h>
66 #include <arm/iomd/vidc20config.h>
67 
68 
69 /*
70  * A structure containing ALL the information required to restore
71  * the VIDC20 to any given state.  ALL vidc transactions should
72  * go through these procedures, which record the vidc's state.
73  * it may be an idea to set the permissions of the vidc base address
74  * so we get a fault, so the fault routine can record the state but
75  * I guess that's not really necessary for the time being, since we
76  * can make the kernel more secure later on.  Also, it is possible
77  * to write a routine to allow 'reading' of the vidc registers.
78  */
79 
80 static struct vidc_state vidc_lookup = {
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           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,
86           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,
87           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,
88           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
89 	},
90 
91 	VIDC_PALREG,
92 	VIDC_BCOL,
93 	VIDC_CP1 ,
94 	VIDC_CP2,
95 	VIDC_CP3,
96 	VIDC_HCR,
97 	VIDC_HSWR,
98 	VIDC_HBSR,
99 	VIDC_HDSR,
100 	VIDC_HDER,
101 	VIDC_HBER,
102 	VIDC_HCSR,
103 	VIDC_HIR,
104 	VIDC_VCR,
105 	VIDC_VSWR,
106 	VIDC_VBSR,
107 	VIDC_VDSR,
108 	VIDC_VDER,
109 	VIDC_VBER,
110 	VIDC_VCSR,
111 	VIDC_VCER,
112 	VIDC_EREG,
113 	VIDC_FSYNREG,
114 	VIDC_CONREG,
115 	VIDC_DCTL
116 };
117 
118 struct vidc_state vidc_current[1];
119 
120 
121 /*
122  * XXX global display variables XXX ... should be a structure
123  */
124 static int cold_init = 0;		/* flags initialisation */
125 extern videomemory_t videomemory;
126 
127 static struct vidc_mode  vidc_initialmode;
128 static struct vidc_mode *vidc_currentmode;
129 
130 unsigned int dispstart;
131 unsigned int dispsize;
132 unsigned int dispbase;
133 unsigned int dispend;
134 unsigned int ptov;
135 unsigned int vmem_base;
136 unsigned int phys_base;
137 unsigned int transfersize;
138 
139 
140 /* cursor stuff */
141 char *cursor_normal;
142 char *cursor_transparent;
143 int   p_cursor_normal;
144 int   p_cursor_transparent;
145 int   cursor_width;
146 int   cursor_height;
147 
148 
149 /*
150  * VIDC mode definitions
151  * generated from RISC OS mode definition file by an `awk' script
152  */
153 extern struct vidc_mode vidcmodes[];
154 
155 
156 /*
157  * configuration printing
158  *
159  */
160 
161 void
162 vidcvideo_printdetails(void)
163 {
164         printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000),
165             videomemory.vidm_size / 1024,
166             (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM");
167 }
168 
169 
170 /*
171  * Common functions to directly access VIDC registers
172  */
173 int
174 vidcvideo_write(reg, value)
175 	u_int reg;
176 	int value;
177 {
178 	int counter;
179 
180 	int *current;
181 	int *tab;
182 
183 	tab 	= (int *)&vidc_lookup;
184 	current = (int *)vidc_current;
185 
186 
187 	/*
188 	 * OK, the VIDC_PALETTE register is handled differently
189 	 * to the others on the VIDC, so take that into account here
190 	 */
191 	if (reg==VIDC_PALREG) {
192 		vidc_current->palreg = 0;
193 		WriteWord(vidc_base, reg | value);
194 		return 0;
195 	}
196 
197 	if (reg==VIDC_PALETTE) {
198 		WriteWord(vidc_base, reg | value);
199 		vidc_current->palette[vidc_current->palreg] = value;
200 		vidc_current->palreg++;
201 		vidc_current->palreg = vidc_current->palreg & 0xff;
202 		return 0;
203 	}
204 
205 	/*
206 	 * Undefine SAFER if you wish to speed things up (a little)
207 	 * although this means the function will assume things abou
208 	 * the structure of vidc_state. i.e. the first 256 words are
209 	 * the palette array
210 	 */
211 
212 #define SAFER
213 
214 #ifdef 	SAFER
215 #define INITVALUE 0
216 #else
217 #define INITVALUE 256
218 #endif
219 
220 	for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) {
221 		if ( reg==tab[counter] ) {
222 			WriteWord ( vidc_base, reg | value );
223 			current[counter] = value;
224 			return 0;
225 		}
226 	}
227 	return -1;
228 }
229 
230 
231 void
232 vidcvideo_setpalette(vidc)
233 	struct vidc_state *vidc;
234 {
235 	int counter = 0;
236 
237 	vidcvideo_write(VIDC_PALREG, 0x00000000);
238 	for (counter = 0; counter <= 255; counter++)
239 		vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]);
240 }
241 
242 
243 void
244 vidcvideo_setstate(vidc)
245 	struct vidc_state *vidc;
246 {
247 	vidcvideo_write ( VIDC_PALREG,		vidc->palreg 	);
248 	vidcvideo_write ( VIDC_BCOL,		vidc->bcol	);
249 	vidcvideo_write ( VIDC_CP1,		vidc->cp1	);
250 	vidcvideo_write ( VIDC_CP2,		vidc->cp2	);
251 	vidcvideo_write ( VIDC_CP3,		vidc->cp3	);
252 	vidcvideo_write ( VIDC_HCR,		vidc->hcr	);
253 	vidcvideo_write ( VIDC_HSWR,		vidc->hswr	);
254 	vidcvideo_write ( VIDC_HBSR,		vidc->hbsr	);
255 	vidcvideo_write ( VIDC_HDSR,		vidc->hdsr	);
256 	vidcvideo_write ( VIDC_HDER,		vidc->hder	);
257 	vidcvideo_write ( VIDC_HBER,		vidc->hber	);
258 	vidcvideo_write ( VIDC_HCSR,		vidc->hcsr	);
259 	vidcvideo_write ( VIDC_HIR,		vidc->hir	);
260 	vidcvideo_write ( VIDC_VCR,		vidc->vcr	);
261 	vidcvideo_write ( VIDC_VSWR,		vidc->vswr	);
262 	vidcvideo_write ( VIDC_VBSR,		vidc->vbsr	);
263 	vidcvideo_write ( VIDC_VDSR,		vidc->vdsr	);
264 	vidcvideo_write ( VIDC_VDER,		vidc->vder	);
265 	vidcvideo_write ( VIDC_VBER,		vidc->vber	);
266 	vidcvideo_write ( VIDC_VCSR,		vidc->vcsr	);
267 	vidcvideo_write ( VIDC_VCER,		vidc->vcer	);
268 /*
269  * Right, dunno what to set these to yet, but let's keep RiscOS's
270  * ones for now, until the time is right to finish this code
271  */
272 
273 /*	vidcvideo_write ( VIDC_EREG,		vidc->ereg	);	*/
274 /*	vidcvideo_write ( VIDC_FSYNREG,	vidc->fsynreg	);	*/
275 /*	vidcvideo_write ( VIDC_CONREG,	vidc->conreg	);	*/
276 /*	vidcvideo_write ( VIDC_DCTL,		vidc->dctl	);	*/
277 
278 	vidcvideo_setpalette(vidc);
279 }
280 
281 
282 void
283 vidcvideo_getstate(vidc)
284 	struct vidc_state *vidc;
285 {
286 	*vidc = *vidc_current;
287 }
288 
289 
290 void
291 vidcvideo_getmode(mode)
292 	struct vidc_mode *mode;
293 {
294 	*mode = *vidc_currentmode;
295 }
296 
297 
298 static int
299 vidcvideo_coldinit(void)
300 {
301 	int found;
302 	int loop;
303 
304 	/* Blank out the cursor */
305 
306 	vidcvideo_write(VIDC_CP1, 0x0);
307 	vidcvideo_write(VIDC_CP2, 0x0);
308 	vidcvideo_write(VIDC_CP3, 0x0);
309 
310 	/* Try to determine the current mode */
311 	vidc_initialmode.hder     = bootconfig.width+1;
312 	vidc_initialmode.vder     = bootconfig.height+1;
313 	vidc_initialmode.log2_bpp = bootconfig.log2_bpp;
314 
315 	dispbase = vmem_base = dispstart = videomemory.vidm_vbase;
316 	phys_base = videomemory.vidm_pbase;
317 
318 	/* Nut - should be using videomemory.vidm_size - mark */
319 	if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) {
320 		dispsize = videomemory.vidm_size;
321 		transfersize = 16;
322 	} else {
323 		dispsize = bootconfig.vram[0].pages * NBPG;
324 		transfersize = dispsize >> 10;
325 	};
326 
327 	ptov = dispbase - phys_base;
328 
329 	dispend = dispstart+dispsize;
330 
331 	/* try to find the current mode from the bootloader in my table */
332 	vidc_currentmode = &vidcmodes[0];
333 	loop = 0;
334 	found = 0;
335 	while (vidcmodes[loop].pixel_rate != 0) {
336   		if (vidcmodes[loop].hder == (bootconfig.width + 1)
337   		    && vidcmodes[loop].vder == (bootconfig.height + 1)
338 		    && vidcmodes[loop].frame_rate == bootconfig.framerate) {
339 			vidc_currentmode = &vidcmodes[loop];
340 			found = 1;
341 		}
342 		++loop;
343 	}
344 
345 	/* if not found choose first mode but dont be picky on the framerate */
346 	if (!found) {
347 		vidc_currentmode = &vidcmodes[0];
348 		loop = 0;
349 		found = 0;
350 
351 		while (vidcmodes[loop].pixel_rate != 0) {
352 			if (vidcmodes[loop].hder == (bootconfig.width + 1)
353  			    && vidcmodes[loop].vder == (bootconfig.height + 1)) {
354  				vidc_currentmode = &vidcmodes[loop];
355  				found = 1;
356  			}
357  			++loop;
358  		}
359 	}
360 
361 	vidc_currentmode->log2_bpp = bootconfig.log2_bpp;
362 
363 	dispstart = dispbase;
364 	dispend = dispstart+dispsize;
365 
366 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
367 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
368 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
369 	return 0;
370 }
371 
372 
373 /* simple function to abstract vidc variables ; returns virt start address of screen */
374 /* XXX asumption that video memory is mapped in twice */
375 void *vidcvideo_hwscroll(int bytes) {
376 	dispstart += bytes;
377 	if (dispstart >= dispbase + dispsize) dispstart -= dispsize;
378 	if (dispstart <  dispbase)            dispstart += dispsize;
379 	dispend = dispstart+dispsize;
380 
381 	/* return the start of the bit map of the screen (left top) */
382 	return (void *) dispstart;
383 }
384 
385 
386 /* reset the HW scroll to be at the start for the benefit of f.e. X */
387 void *vidcvideo_hwscroll_reset(void) {
388 	void *cookie = (void *) dispstart;
389 
390 	dispstart = dispbase;
391 	dispend = dispstart + dispsize;
392 	return cookie;
393 }
394 
395 
396 /* put HW scroll back to where it was */
397 void *vidcvideo_hwscroll_back(void *cookie) {
398 	dispstart = (int) cookie;
399 	dispend = dispstart + dispsize;
400 	return cookie;
401 }
402 
403 
404 /* this function is to be called perferably at vsync */
405 void vidcvideo_progr_scroll(void) {
406 	IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
407 	IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
408 	IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
409 }
410 
411 
412 /*
413  * Select a new mode by reprogramming the VIDC chip
414  * XXX this part is known not to work for 32bpp
415  */
416 
417 struct vidc_mode newmode;
418 
419 static const int bpp_mask_table[] = {
420 	0,  /* 1bpp */
421 	1,  /* 2bpp */
422 	2,  /* 4bpp */
423 	3,  /* 8bpp */
424 	4,  /* 16bpp */
425 	6   /* 32bpp */
426 };
427 
428 
429 void
430 vidcvideo_setmode(struct vidc_mode *mode)
431 {
432 	register int acc;
433 	int bpp_mask;
434         int ereg;
435 	int best_r, best_v;
436 	int least_error;
437 	int r, v, f;
438 
439 	/*
440 	 * Find out what bit mask we need to or with the vidc20 control register
441 	 * in order to generate the desired number of bits per pixel.
442 	 * log_bpp is log base 2 of the number of bits per pixel.
443 	 */
444 
445 	bpp_mask = bpp_mask_table[mode->log2_bpp];
446 
447 	newmode = *mode;
448 	vidc_currentmode = &newmode;
449 
450 	least_error = INT_MAX;
451 	best_r = 0; best_v = 0;
452 
453 	for (v = 63; v > 0; v--) {
454 		for (r = 63; r > 0; r--) {
455 			f = ((v * vidc_fref) /1000) / r;
456 			if (least_error >=
457 			    abs(f - vidc_currentmode->pixel_rate)) {
458 				least_error =
459 				    abs(f - vidc_currentmode->pixel_rate);
460 				best_r = r;
461 				best_v = v;
462 			}
463 		}
464 	}
465 
466 	if (best_r > 63) best_r=63;
467 	if (best_v > 63) best_v=63;
468 	if (best_r < 1)  best_r= 1;
469 	if (best_v < 1)  best_v= 1;
470 
471 	vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0);
472 
473 	acc=0;
474 	acc+=vidc_currentmode->hswr;	vidcvideo_write(VIDC_HSWR, (acc - 8 ) & (~1));
475 	acc+=vidc_currentmode->hbsr;	vidcvideo_write(VIDC_HBSR, (acc - 12) & (~1));
476 	acc+=vidc_currentmode->hdsr;	vidcvideo_write(VIDC_HDSR, (acc - 18) & (~1));
477 	acc+=vidc_currentmode->hder;	vidcvideo_write(VIDC_HDER, (acc - 18) & (~1));
478 	acc+=vidc_currentmode->hber;	vidcvideo_write(VIDC_HBER, (acc - 12) & (~1));
479 	acc+=vidc_currentmode->hcr;	vidcvideo_write(VIDC_HCR,  (acc - 8 ) & (~3));
480 
481 	acc=0;
482 	acc+=vidc_currentmode->vswr;	vidcvideo_write(VIDC_VSWR, (acc - 1));
483 	acc+=vidc_currentmode->vbsr;	vidcvideo_write(VIDC_VBSR, (acc - 1));
484 	acc+=vidc_currentmode->vdsr;	vidcvideo_write(VIDC_VDSR, (acc - 1));
485 	acc+=vidc_currentmode->vder;	vidcvideo_write(VIDC_VDER, (acc - 1));
486 	acc+=vidc_currentmode->vber;	vidcvideo_write(VIDC_VBER, (acc - 1));
487 	acc+=vidc_currentmode->vcr;	vidcvideo_write(VIDC_VCR,  (acc - 1));
488 
489 	IOMD_WRITE_WORD(IOMD_FSIZE, vidc_currentmode->vcr
490 	    + vidc_currentmode->vswr
491 	    + vidc_currentmode->vber
492 	    + vidc_currentmode->vbsr - 1);
493 
494 	if (dispsize <= 1024*1024)
495 		vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
496 	else
497 		vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12);
498 
499 	ereg = 1<<12;
500 	if (vidc_currentmode->sync_pol & 0x01)
501 		ereg |= 1<<16;
502 	if (vidc_currentmode->sync_pol & 0x02)
503 		ereg |= 1<<18;
504 	vidcvideo_write(VIDC_EREG, ereg);
505 	if (dispsize > 1024*1024) {
506 		if (vidc_currentmode->hder >= 800)
507  			vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
508 		else
509 			vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
510 	} else {
511 		vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
512 	}
513 }
514 
515 
516 #if 0
517 /* not used for now */
518 void
519 vidcvideo_set_display_base(base)
520 	u_int base;
521 {
522 	dispstart = dispstart-dispbase + base;
523 	dispbase = vmem_base = base;
524 	dispend = base + dispsize;
525 	ptov = dispbase - phys_base;
526 }
527 #endif
528 
529 
530 /*
531  * Main initialisation routine for now
532  */
533 
534 static int cursor_init = 0;
535 
536 int
537 vidcvideo_init(void)
538 {
539 	vidcvideo_coldinit();
540 	if (cold_init && (cursor_init == 0))
541 		/*	vidcvideo_flash_go() */;
542 
543 	/* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */
544 	vidcvideo_setmode(vidc_currentmode);
545 	vidcvideo_blank(0);			/* display on */
546 
547 	vidcvideo_stdpalette();
548 
549 	if (cold_init == 0) {
550 		vidcvideo_write(VIDC_CP1, 0x0);
551 		vidcvideo_write(VIDC_CP2, 0x0);
552 		vidcvideo_write(VIDC_CP3, 0x0);
553 	} else {
554 		vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT);
555 	};
556 
557 	cold_init=1;
558 	return 0;
559 }
560 
561 
562 /* reinitialise the vidcvideo */
563 void
564 vidcvideo_reinit()
565 {
566 	vidcvideo_coldinit();
567 	vidcvideo_setmode(vidc_currentmode);
568 }
569 
570 
571 int
572 vidcvideo_cursor_init(int width, int height)
573 {
574 	static char *cursor_data = NULL;
575 	int counter;
576 	int line;
577 	paddr_t pa;
578 
579 	cursor_width  = width;
580 	cursor_height = height;
581 
582 	if (!cursor_data) {
583 		/* Allocate cursor memory first time round */
584 		cursor_data = (char *)uvm_km_zalloc(kernel_map, NBPG);
585 		if (!cursor_data)
586 			panic("Cannot allocate memory for hardware cursor");
587 		(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa);
588 		IOMD_WRITE_WORD(IOMD_CURSINIT, pa);
589 	}
590 
591 	/* Blank the cursor while initialising it's sprite */
592 
593 	vidcvideo_write ( VIDC_CP1, 0x0 );
594 	vidcvideo_write ( VIDC_CP2, 0x0 );
595 	vidcvideo_write ( VIDC_CP3, 0x0 );
596 
597  	cursor_normal       = cursor_data;
598 	cursor_transparent  = cursor_data + (height * width);
599 
600  	cursor_transparent += 32;					/* ALIGN */
601 	cursor_transparent = (char *)((int)cursor_transparent & (~31) );
602 
603 	for ( line = 0; line<height; ++ line )
604 	{
605 	    for ( counter=0; counter<width/4;counter++ )
606 		cursor_normal[line * width + counter]=0x55;		/* why 0x55 ? */
607 	    for ( ; counter<8; counter++ )
608 		cursor_normal[line * width + counter]=0;
609 	}
610 
611 	for ( line = 0; line<height; ++ line )
612 	{
613 	    for ( counter=0; counter<width/4;counter++ )
614 		cursor_transparent[line * width + counter]=0x00;
615 	    for ( ; counter<8; counter++ )
616 		cursor_transparent[line * width + counter]=0;
617 	}
618 
619 
620 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal,
621 	    (paddr_t *)&p_cursor_normal);
622 	(void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent,
623 	    (paddr_t *)&p_cursor_transparent);
624 
625 	memset ( cursor_normal, 0x55, width*height );			/* white? */
626 	memset ( cursor_transparent, 0x00, width*height );		/* to see the diffence */
627 
628 	/* Ok, now program the cursor; should be blank */
629 	vidcvideo_enablecursor(0);
630 
631         return 0;
632 }
633 
634 
635 void
636 vidcvideo_updatecursor(xcur, ycur)
637 	int xcur, ycur;
638 {
639 	int frontporch = vidc_currentmode->hswr + vidc_currentmode->hbsr + vidc_currentmode->hdsr;
640 	int topporch   = vidc_currentmode->vswr + vidc_currentmode->vbsr + vidc_currentmode->vdsr;
641 
642 	vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur);
643 	vidcvideo_write(VIDC_VCSR, topporch   -2  + (ycur+1)-2 + 3 - cursor_height);
644 	vidcvideo_write(VIDC_VCER, topporch   -2  + (ycur+3)+2 + 3 );
645 	return;
646 }
647 
648 
649 void
650 vidcvideo_enablecursor(on)
651 	int on;
652 {
653 	if (on) {
654 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal);
655 	} else {
656 		IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent);
657 	};
658 	vidcvideo_write ( VIDC_CP1, 0xffffff );		/* enable */
659 
660 	return;
661 }
662 
663 
664 void
665 vidcvideo_stdpalette()
666 {
667 	int i;
668 
669 	switch (vidc_currentmode->log2_bpp) {
670 	case 0: /* 1 bpp */
671 	case 1: /* 2 bpp */
672 	case 2: /* 4 bpp */
673 	case 3: /* 8 bpp */
674 		vidcvideo_write(VIDC_PALREG, 0x00000000);
675 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0,   0));
676 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0,   0));
677 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255,   0));
678 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255,   0));
679 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0,   0, 255));
680 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255,   0, 255));
681 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(  0, 255, 255));
682 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
683 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
684 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
685 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
686 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
687 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
688 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
689 		vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
690 		break;
691 	case 4: /* 16 bpp */
692 		/*
693 		 * The use of the palette in 16-bit modes is quite
694 		 * fun.  Comments in linux/drivers/video/acornfb.c
695 		 * imply that it goes something like this:
696 		 *
697 		 * red   = LUT[pixel[7:0]].red
698 		 * green = LUT[pixel[11:4]].green
699 		 * blue  = LUT[pixel[15:8]].blue
700 		 *
701 		 * We use 6:5:5 R:G:B cos that's what Xarm32VIDC wants.
702 		 */
703 #define RBITS 6
704 #define GBITS 5
705 #define BBITS 5
706 		vidcvideo_write(VIDC_PALREG, 0x00000000);
707 		for (i = 0; i < 256; i++) {
708 			int r, g, b;
709 
710 			r = i & ((1 << RBITS) - 1);
711 			g = (i >> (RBITS - 4)) & ((1 << GBITS) - 1);
712 			b = (i >> (RBITS + GBITS - 8)) & ((1 << BBITS) - 1);
713 			vidcvideo_write(VIDC_PALETTE,
714 			    VIDC_COL(r << (8 - RBITS) | r >> (2 * RBITS - 8),
715 				g << (8 - GBITS) | g >> (2 * GBITS - 8),
716 				b << (8 - BBITS) | b >> (2 * BBITS - 8)));
717 		}
718 		break;
719 	case 5: /* 32 bpp */
720 		vidcvideo_write(VIDC_PALREG, 0x00000000);
721 		for (i = 0; i < 256; i++)
722 			vidcvideo_write(VIDC_PALETTE, VIDC_COL(i, i, i));
723 		break;
724 	}
725 
726 }
727 
728 int
729 vidcvideo_blank(video_off)
730 	int video_off;
731 {
732         int ereg;
733 
734 	ereg = 1<<12;
735 	if (vidc_currentmode->sync_pol & 0x01)
736 		ereg |= 1<<16;
737 	if (vidc_currentmode->sync_pol & 0x02)
738 		ereg |= 1<<18;
739 
740 	if (!video_off) {
741     		vidcvideo_write(VIDC_EREG, ereg);
742 	} else {
743 		vidcvideo_write(VIDC_EREG, 0);
744 	};
745 	return 0;
746 }
747 
748 /* end of vidc20config.c */
749