vidc20config.c revision 1.1 1 /* $NetBSD: vidc20config.c,v 1.1 2001/10/05 22:27:43 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 #ifdef RC7500
123 struct vfreq {
124 u_int frqcon;
125 int freq;
126 };
127
128 static struct vfreq vfreq[] = {
129 { VIDFREQ_25_18, 25175},
130 { VIDFREQ_25_18, 25180},
131 { VIDFREQ_28_32, 28320},
132 { VIDFREQ_31_50, 31500},
133 { VIDFREQ_36_00, 36000},
134 { VIDFREQ_40_00, 40000},
135 { VIDFREQ_44_90, 44900},
136 { VIDFREQ_50_00, 50000},
137 { VIDFREQ_65_00, 65000},
138 { VIDFREQ_72_00, 72000},
139 { VIDFREQ_75_00, 75000},
140 { VIDFREQ_77_00, 77000},
141 { VIDFREQ_80_00, 80000},
142 { VIDFREQ_94_50, 94500},
143 { VIDFREQ_110_0, 110000},
144 { VIDFREQ_120_0, 120000},
145 { VIDFREQ_130_0, 130000}
146 };
147
148 #define NFREQ (sizeof (vfreq) / sizeof(struct vfreq))
149 u_int vfreqcon = 0;
150 #else /* RC7500 */
151
152 struct fsyn {
153 int r, v, f;
154 };
155
156 static struct fsyn fsyn_pref[] = {
157 { 6, 2, 8000 },
158 { 4, 2, 12000 },
159 { 3, 2, 16000 },
160 { 2, 2, 24000 },
161 { 41, 43, 25171 },
162 { 50, 59, 28320 },
163 { 3, 4, 32000 },
164 { 2, 3, 36000 },
165 { 31, 58, 44903 },
166 { 12, 35, 70000 },
167 { 0, 0, 00000 }
168 };
169 #endif /* RC7500 */
170
171
172 /*
173 * XXX global display variables XXX ... should be a structure
174 */
175 static int cold_init = 0; /* flags initialisation */
176 extern videomemory_t videomemory;
177
178 static struct vidc_mode vidc_initialmode;
179 static struct vidc_mode *vidc_currentmode;
180
181 unsigned int dispstart;
182 unsigned int dispsize;
183 unsigned int dispbase;
184 unsigned int dispend;
185 unsigned int ptov;
186 unsigned int vmem_base;
187 unsigned int phys_base;
188 unsigned int transfersize;
189
190
191 /* cursor stuff */
192 char *cursor_normal;
193 char *cursor_transparent;
194 int p_cursor_normal;
195 int p_cursor_transparent;
196 int cursor_width;
197 int cursor_height;
198
199
200 /*
201 * VIDC mode definitions
202 * generated from RISC OS mode definition file by an `awk' script
203 */
204 extern struct vidc_mode vidcmodes[];
205
206
207 /*
208 * configuration printing
209 *
210 */
211
212 void
213 vidcvideo_printdetails(void)
214 {
215 printf(": refclk=%dMHz %dKB %s ", (vidc_fref / 1000000),
216 videomemory.vidm_size / 1024,
217 (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) ? "VRAM" : "DRAM");
218 }
219
220 /*
221 * Common functions to directly access VIDC registers
222 */
223 int
224 vidcvideo_write(reg, value)
225 u_int reg;
226 int value;
227 {
228 int counter;
229
230 int *current;
231 int *tab;
232
233 tab = (int *)&vidc_lookup;
234 current = (int *)vidc_current;
235
236
237 /*
238 * OK, the VIDC_PALETTE register is handled differently
239 * to the others on the VIDC, so take that into account here
240 */
241 if (reg==VIDC_PALREG) {
242 vidc_current->palreg = 0;
243 WriteWord(vidc_base, reg | value);
244 return 0;
245 }
246
247 if (reg==VIDC_PALETTE) {
248 WriteWord(vidc_base, reg | value);
249 vidc_current->palette[vidc_current->palreg] = value;
250 vidc_current->palreg++;
251 vidc_current->palreg = vidc_current->palreg & 0xff;
252 return 0;
253 }
254
255 /*
256 * Undefine SAFER if you wish to speed things up (a little)
257 * although this means the function will assume things abou
258 * the structure of vidc_state. i.e. the first 256 words are
259 * the palette array
260 */
261
262 #define SAFER
263
264 #ifdef SAFER
265 #define INITVALUE 0
266 #else
267 #define INITVALUE 256
268 #endif
269
270 for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) {
271 if ( reg==tab[counter] ) {
272 WriteWord ( vidc_base, reg | value );
273 current[counter] = value;
274 return 0;
275 }
276 }
277 return -1;
278 }
279
280
281 void
282 vidcvideo_setpalette(vidc)
283 struct vidc_state *vidc;
284 {
285 int counter = 0;
286
287 vidcvideo_write(VIDC_PALREG, 0x00000000);
288 for (counter = 0; counter < 255; counter++)
289 vidcvideo_write(VIDC_PALETTE, vidc->palette[counter]);
290 }
291
292
293 void
294 vidcvideo_setstate(vidc)
295 struct vidc_state *vidc;
296 {
297 vidcvideo_write ( VIDC_PALREG, vidc->palreg );
298 vidcvideo_write ( VIDC_BCOL, vidc->bcol );
299 vidcvideo_write ( VIDC_CP1, vidc->cp1 );
300 vidcvideo_write ( VIDC_CP2, vidc->cp2 );
301 vidcvideo_write ( VIDC_CP3, vidc->cp3 );
302 vidcvideo_write ( VIDC_HCR, vidc->hcr );
303 vidcvideo_write ( VIDC_HSWR, vidc->hswr );
304 vidcvideo_write ( VIDC_HBSR, vidc->hbsr );
305 vidcvideo_write ( VIDC_HDSR, vidc->hdsr );
306 vidcvideo_write ( VIDC_HDER, vidc->hder );
307 vidcvideo_write ( VIDC_HBER, vidc->hber );
308 vidcvideo_write ( VIDC_HCSR, vidc->hcsr );
309 vidcvideo_write ( VIDC_HIR, vidc->hir );
310 vidcvideo_write ( VIDC_VCR, vidc->vcr );
311 vidcvideo_write ( VIDC_VSWR, vidc->vswr );
312 vidcvideo_write ( VIDC_VBSR, vidc->vbsr );
313 vidcvideo_write ( VIDC_VDSR, vidc->vdsr );
314 vidcvideo_write ( VIDC_VDER, vidc->vder );
315 vidcvideo_write ( VIDC_VBER, vidc->vber );
316 vidcvideo_write ( VIDC_VCSR, vidc->vcsr );
317 vidcvideo_write ( VIDC_VCER, vidc->vcer );
318 /*
319 * Right, dunno what to set these to yet, but let's keep RiscOS's
320 * ones for now, until the time is right to finish this code
321 */
322
323 /* vidcvideo_write ( VIDC_EREG, vidc->ereg ); */
324 /* vidcvideo_write ( VIDC_FSYNREG, vidc->fsynreg ); */
325 /* vidcvideo_write ( VIDC_CONREG, vidc->conreg ); */
326 /* vidcvideo_write ( VIDC_DCTL, vidc->dctl ); */
327
328 }
329
330
331 void
332 vidcvideo_getstate(vidc)
333 struct vidc_state *vidc;
334 {
335 *vidc = *vidc_current;
336 }
337
338
339 void
340 vidcvideo_getmode(mode)
341 struct vidc_mode *mode;
342 {
343 *mode = *vidc_currentmode;
344 }
345
346
347 void
348 vidcvideo_stdpalette()
349 {
350 WriteWord(vidc_base, VIDC_PALREG | 0x00000000);
351 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL( 0, 0, 0));
352 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 0, 0));
353 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL( 0, 255, 0));
354 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 0));
355 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL( 0, 0, 255));
356 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 0, 255));
357 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL( 0, 255, 255));
358 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 255));
359 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 128, 128));
360 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 128, 128));
361 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 255, 128));
362 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 128));
363 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 128, 255));
364 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 128, 255));
365 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(128, 255, 255));
366 WriteWord(vidc_base, VIDC_PALETTE | VIDC_COL(255, 255, 255));
367 }
368
369
370 /* small inline mod function ... why here? */
371 static __inline int
372 mod(int n)
373 {
374 if (n < 0)
375 return(-n);
376 else
377 return(n);
378 }
379
380
381 static int
382 vidcvideo_coldinit(void)
383 {
384 int found;
385 int loop;
386
387 /* Blank out the cursor */
388
389 vidcvideo_write(VIDC_CP1, 0x0);
390 vidcvideo_write(VIDC_CP2, 0x0);
391 vidcvideo_write(VIDC_CP3, 0x0);
392
393 /* Try to determine the current mode */
394 vidc_initialmode.hder = bootconfig.width+1;
395 vidc_initialmode.vder = bootconfig.height+1;
396 vidc_initialmode.log2_bpp = bootconfig.log2_bpp;
397
398 dispbase = vmem_base = dispstart = videomemory.vidm_vbase;
399 phys_base = videomemory.vidm_pbase;
400
401 /* Nut - should be using videomemory.vidm_size - mark */
402 if (videomemory.vidm_type == VIDEOMEM_TYPE_DRAM) {
403 dispsize = videomemory.vidm_size;
404 transfersize = 16;
405 } else {
406 dispsize = bootconfig.vram[0].pages * NBPG;
407 transfersize = dispsize >> 10;
408 };
409
410 ptov = dispbase - phys_base;
411
412 dispend = dispstart+dispsize;
413
414 /* try to find the current mode from the bootloader in my table */
415 vidc_currentmode = &vidcmodes[0];
416 loop = 0;
417 found = 0;
418 while (vidcmodes[loop].pixel_rate != 0) {
419 if (vidcmodes[loop].hder == (bootconfig.width + 1)
420 && vidcmodes[loop].vder == (bootconfig.height + 1)
421 && vidcmodes[loop].frame_rate == bootconfig.framerate) {
422 vidc_currentmode = &vidcmodes[loop];
423 found = 1;
424 }
425 ++loop;
426 }
427
428 /* if not found choose first mode but dont be picky on the framerate */
429 if (!found) {
430 vidc_currentmode = &vidcmodes[0];
431 loop = 0;
432 found = 0;
433
434 while (vidcmodes[loop].pixel_rate != 0) {
435 if (vidcmodes[loop].hder == (bootconfig.width + 1)
436 && vidcmodes[loop].vder == (bootconfig.height + 1)) {
437 vidc_currentmode = &vidcmodes[loop];
438 found = 1;
439 }
440 ++loop;
441 }
442 }
443
444 vidc_currentmode->log2_bpp = bootconfig.log2_bpp;
445
446 dispstart = dispbase;
447 dispend = dispstart+dispsize;
448
449 IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
450 IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
451 IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
452 return 0;
453 }
454
455
456 /* simple function to abstract vidc variables ; returns virt start address of screen */
457 /* XXX asumption that video memory is mapped in twice */
458 void *vidcvideo_hwscroll(int bytes) {
459 dispstart += bytes;
460 if (dispstart >= dispbase + dispsize) dispstart -= dispsize;
461 if (dispstart < dispbase) dispstart += dispsize;
462 dispend = dispstart+dispsize;
463
464 /* return the start of the bit map of the screen (left top) */
465 return (void *) dispstart;
466 }
467
468
469 /* reset the HW scroll to be at the start for the benefit of f.e. X */
470 void *vidcvideo_hwscroll_reset(void) {
471 void *cookie = (void *) dispstart;
472
473 dispstart = dispbase;
474 dispend = dispstart + dispsize;
475 return cookie;
476 }
477
478
479 /* put HW scroll back to where it was */
480 void *vidcvideo_hwscroll_back(void *cookie) {
481 dispstart = (int) cookie;
482 dispend = dispstart + dispsize;
483 return cookie;
484 }
485
486
487 /* this function is to be called at vsync */
488 void vidcvideo_progr_scroll(void) {
489 IOMD_WRITE_WORD(IOMD_VIDINIT, dispstart-ptov);
490 IOMD_WRITE_WORD(IOMD_VIDSTART, dispstart-ptov);
491 IOMD_WRITE_WORD(IOMD_VIDEND, (dispend-transfersize)-ptov);
492 }
493
494
495 /*
496 * Select a new mode by reprogramming the VIDC chip
497 * XXX this part is known not to work for 32bpp
498 */
499
500 struct vidc_mode newmode;
501
502 static const int bpp_mask_table[] = {
503 0, /* 1bpp */
504 1, /* 2bpp */
505 2, /* 4bpp */
506 3, /* 8bpp */
507 4, /* 16bpp */
508 6 /* 32bpp */
509 };
510
511
512 void
513 vidcvideo_setmode(struct vidc_mode *mode)
514 {
515 register int acc;
516 int bpp_mask;
517 #ifndef RC7500
518 int ereg;
519
520 int best_r, best_v, best_match;
521 #endif
522
523 #ifdef NC
524 return;
525 #endif
526 /*
527 * Find out what bit mask we need to or with the vidc20 control register
528 * in order to generate the desired number of bits per pixel.
529 * log_bpp is log base 2 of the number of bits per pixel.
530 */
531
532 bpp_mask = bpp_mask_table[mode->log2_bpp];
533
534 newmode = *mode;
535 vidc_currentmode = &newmode;
536
537 #ifdef RC7500
538 {
539 int i;
540 int old, new;
541 u_int nfreq;
542
543 old = vfreq[0].freq;
544 nfreq = vfreq[0].frqcon;
545 for (i = 0; i < (NFREQ - 1); i++) {
546 new = vfreq[i].freq - mode->pixel_rate;
547 if (new < 0)
548 new = -new;
549 if (new < old) {
550 nfreq = vfreq[i].frqcon;
551 old = new;
552 }
553 if (new == 0)
554 break;
555 }
556 nfreq |= (vfreqcon & 0xf0);
557 vfreqcon = nfreq;
558 }
559 #else /* RC7500 */
560 /* Program the VCO Look-up to a preferred value before choosing one */
561 {
562 int least_error = mod(fsyn_pref[0].f - vidc_currentmode->pixel_rate);
563 int counter;
564 best_r = fsyn_pref[0].r;
565 best_match = fsyn_pref[0].f;
566 best_v = fsyn_pref[0].v;
567
568 /* Look up */
569 counter=0;
570 while (fsyn_pref[counter].r != 0) {
571 if (least_error > mod(fsyn_pref[counter].f - vidc_currentmode->pixel_rate)) {
572 best_match = fsyn_pref[counter].f;
573 least_error = mod(fsyn_pref[counter].f - vidc_currentmode->pixel_rate);
574 best_r = fsyn_pref[counter].r;
575 best_v = fsyn_pref[counter].v;
576 }
577 counter++;
578 }
579
580 if (least_error > 0) { /* Accuracy of 1000Hz */
581 int r, v, f;
582 for (v = 63; v > 0; v--)
583 for (r = 63; r > 0; r--) {
584 f = ((v * vidc_fref) /1000) / r;
585 if (least_error >= mod(f - vidc_currentmode->pixel_rate)) {
586 best_match = f;
587 least_error = mod(f - vidc_currentmode->pixel_rate);
588 best_r = r;
589 best_v = v;
590 }
591 }
592 }
593
594 if (best_r > 63) best_r=63;
595 if (best_v > 63) best_v=63;
596 if (best_r < 1) best_r= 1;
597 if (best_v < 1) best_v= 1;
598
599 }
600 #endif /* RC7500 */
601
602 #ifdef RC7500
603 outb(FREQCON, vfreqcon);
604 /*
605 * Need to program the control register first.
606 */
607 if (dispsize>1024*1024) {
608 if (vidc_currentmode->hder>=800)
609 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
610 else
611 vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
612 } else {
613 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
614 }
615
616 /*
617 * We don't use VIDC_FSYNREG. Program it low.
618 */
619 vidcvideo_write(VIDC_FSYNREG, 0x2020);
620 #else /* RC7500 */
621 vidcvideo_write(VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0);
622 #endif /* RC7500 */
623 acc=0;
624 acc+=vidc_currentmode->hswr; vidcvideo_write(VIDC_HSWR, (acc - 8 ) & (~1));
625 acc+=vidc_currentmode->hbsr; vidcvideo_write(VIDC_HBSR, (acc - 12) & (~1));
626 acc+=vidc_currentmode->hdsr; vidcvideo_write(VIDC_HDSR, (acc - 18) & (~1));
627 acc+=vidc_currentmode->hder; vidcvideo_write(VIDC_HDER, (acc - 18) & (~1));
628 acc+=vidc_currentmode->hber; vidcvideo_write(VIDC_HBER, (acc - 12) & (~1));
629 acc+=vidc_currentmode->hcr; vidcvideo_write(VIDC_HCR, (acc - 8 ) & (~3));
630
631 acc=0;
632 acc+=vidc_currentmode->vswr; vidcvideo_write(VIDC_VSWR, (acc - 1));
633 acc+=vidc_currentmode->vbsr; vidcvideo_write(VIDC_VBSR, (acc - 1));
634 acc+=vidc_currentmode->vdsr; vidcvideo_write(VIDC_VDSR, (acc - 1));
635 acc+=vidc_currentmode->vder; vidcvideo_write(VIDC_VDER, (acc - 1));
636 acc+=vidc_currentmode->vber; vidcvideo_write(VIDC_VBER, (acc - 1));
637 acc+=vidc_currentmode->vcr; vidcvideo_write(VIDC_VCR, (acc - 1));
638
639 #ifdef RC7500
640 vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
641 if (vidc_currentmode->hder>=800)
642 vidcvideo_write(VIDC_EREG, 0x41<<12);
643 else
644 vidcvideo_write(VIDC_EREG, 0x51<<12);
645 #else
646 IOMD_WRITE_WORD(IOMD_FSIZE, vidc_currentmode->vcr
647 + vidc_currentmode->vswr
648 + vidc_currentmode->vber
649 + vidc_currentmode->vbsr - 1);
650
651 if (dispsize <= 1024*1024)
652 vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12);
653 else
654 vidcvideo_write(VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12);
655
656 ereg = 1<<12;
657 if (vidc_currentmode->sync_pol & 0x01)
658 ereg |= 1<<16;
659 if (vidc_currentmode->sync_pol & 0x02)
660 ereg |= 1<<18;
661 vidcvideo_write(VIDC_EREG, ereg);
662 if (dispsize > 1024*1024) {
663 if (vidc_currentmode->hder >= 800)
664 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
665 else
666 vidcvideo_write(VIDC_CONREG, 6<<8 | bpp_mask<<5);
667 } else {
668 vidcvideo_write(VIDC_CONREG, 7<<8 | bpp_mask<<5);
669 }
670 #endif
671 }
672
673
674 /* not used for now */
675 void
676 vidcvideo_set_display_base(base)
677 u_int base;
678 {
679 dispstart = dispstart-dispbase + base;
680 dispbase = vmem_base = base;
681 dispend = base + dispsize;
682 ptov = dispbase - phys_base;
683 }
684
685
686 /*
687 * Main initialisation routine for now
688 */
689
690 static int cursor_init = 0;
691
692 int
693 vidcvideo_init(void)
694 {
695 vidcvideo_coldinit();
696 if (cold_init && (cursor_init == 0))
697 /* vidcvideo_flash_go() */;
698
699 /* setting a mode goes wrong in 32 bpp ... 8 and 16 seem OK */
700 vidcvideo_setmode(vidc_currentmode);
701 vidcvideo_blank(0); /* display on */
702
703 vidcvideo_textpalette();
704
705 if (cold_init == 0) {
706 vidcvideo_write(VIDC_CP1, 0x0);
707 vidcvideo_write(VIDC_CP2, 0x0);
708 vidcvideo_write(VIDC_CP3, 0x0);
709 } else {
710 vidcvideo_cursor_init(CURSOR_MAX_WIDTH, CURSOR_MAX_HEIGHT);
711 };
712
713 cold_init=1;
714 return 0;
715 }
716
717
718 /* reinitialise the vidcvideo */
719 void
720 vidcvideo_reinit()
721 {
722 vidcvideo_coldinit();
723 vidcvideo_setmode(vidc_currentmode);
724 }
725
726
727 paddr_t
728 vidcvideo_mmap(vc, offset, nprot)
729 struct vconsole *vc;
730 off_t offset;
731 int nprot;
732 {
733 if ((u_int)offset >= videomemory.vidm_size)
734 return (-1);
735 return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset))));
736 }
737
738
739 int
740 vidcvideo_cursor_init(int width, int height)
741 {
742 static char *cursor_data = NULL;
743 int counter;
744 int line;
745 paddr_t pa;
746
747 cursor_width = width;
748 cursor_height = height;
749
750 if (!cursor_data) {
751 /* Allocate cursor memory first time round */
752 cursor_data = (char *)uvm_km_zalloc(kernel_map, NBPG);
753 if (!cursor_data)
754 panic("Cannot allocate memory for hardware cursor\n");
755 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_data, &pa);
756 IOMD_WRITE_WORD(IOMD_CURSINIT, pa);
757 }
758
759 /* Blank the cursor while initialising it's sprite */
760
761 vidcvideo_write ( VIDC_CP1, 0x0 );
762 vidcvideo_write ( VIDC_CP2, 0x0 );
763 vidcvideo_write ( VIDC_CP3, 0x0 );
764
765 cursor_normal = cursor_data;
766 cursor_transparent = cursor_data + (height * width);
767
768 cursor_transparent += 32; /* ALIGN */
769 cursor_transparent = (char *)((int)cursor_transparent & (~31) );
770
771 for ( line = 0; line<height; ++ line )
772 {
773 for ( counter=0; counter<width/4;counter++ )
774 cursor_normal[line * width + counter]=0x55; /* why 0x55 ? */
775 for ( ; counter<8; counter++ )
776 cursor_normal[line * width + counter]=0;
777 }
778
779 for ( line = 0; line<height; ++ line )
780 {
781 for ( counter=0; counter<width/4;counter++ )
782 cursor_transparent[line * width + counter]=0x00;
783 for ( ; counter<8; counter++ )
784 cursor_transparent[line * width + counter]=0;
785 }
786
787
788 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_normal,
789 (paddr_t *)&p_cursor_normal);
790 (void) pmap_extract(pmap_kernel(), (vaddr_t)cursor_transparent,
791 (paddr_t *)&p_cursor_transparent);
792
793 memset ( cursor_normal, 0x55, width*height ); /* white? */
794 memset ( cursor_transparent, 0x00, width*height ); /* to see the diffence */
795
796 /* Ok, now program the cursor; should be blank */
797 vidcvideo_enablecursor(0);
798
799 return 0;
800 }
801
802
803 void
804 vidcvideo_updatecursor(xcur, ycur)
805 int xcur, ycur;
806 {
807 int frontporch = vidc_currentmode->hswr + vidc_currentmode->hbsr + vidc_currentmode->hdsr;
808 int topporch = vidc_currentmode->vswr + vidc_currentmode->vbsr + vidc_currentmode->vdsr;
809
810 vidcvideo_write(VIDC_HCSR, frontporch -17 + xcur);
811 vidcvideo_write(VIDC_VCSR, topporch -2 + (ycur+1)-2 + 3 - cursor_height);
812 vidcvideo_write(VIDC_VCER, topporch -2 + (ycur+3)+2 + 3 );
813 return;
814 }
815
816
817 void
818 vidcvideo_enablecursor(on)
819 int on;
820 {
821 if (on) {
822 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_normal);
823 } else {
824 IOMD_WRITE_WORD(IOMD_CURSINIT,p_cursor_transparent);
825 };
826 vidcvideo_write ( VIDC_CP1, 0xffffff ); /* enable */
827
828 return;
829 }
830
831
832 int
833 vidcvideo_textpalette()
834 {
835 vidcvideo_write(VIDC_PALREG, 0x00000000);
836 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0));
837 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 0));
838 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 0));
839 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 0));
840 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 0, 255));
841 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 0, 255));
842 vidcvideo_write(VIDC_PALETTE, VIDC_COL( 0, 255, 255));
843 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
844 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 128));
845 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 128));
846 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 255, 128));
847 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 128));
848 vidcvideo_write(VIDC_PALETTE, VIDC_COL(128, 128, 255));
849 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 128, 255));
850 vidcvideo_write(VIDC_PALETTE, VIDC_COL(255, 255, 255));
851
852 return 0;
853 }
854
855 int
856 vidcvideo_blank(video_off)
857 int video_off;
858 {
859 int ereg;
860
861 ereg = 1<<12;
862 if (vidc_currentmode->sync_pol & 0x01)
863 ereg |= 1<<16;
864 if (vidc_currentmode->sync_pol & 0x02)
865 ereg |= 1<<18;
866
867 if (!video_off) {
868 #ifdef RC7500
869 vidcvideo_write(VIDC_EREG, 0x51<<12);
870 #else
871 vidcvideo_write(VIDC_EREG, ereg);
872 #endif
873 } else {
874 vidcvideo_write(VIDC_EREG, 0);
875 };
876 return 0;
877 }
878
879 /* end of vidc20config.c */
880