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