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