vidcvideo.c revision 1.22 1 /* $NetBSD: vidcvideo.c,v 1.22 2006/04/12 19:38:22 jmmv Exp $ */
2
3 /*
4 * Copyright (c) 2001 Reinoud Zandijk
5 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Tohru Nishimura
18 * and Reinoud Zandijk for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Created vidcvideo.c from /dev/tc/cfb.c to fit the Acorn/ARM VIDC1 and VIDC20 chips
34 *
35 */
36
37 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
38
39 __KERNEL_RCSID(0, "$NetBSD: vidcvideo.c,v 1.22 2006/04/12 19:38:22 jmmv Exp $");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46 #include <sys/buf.h>
47 #include <sys/ioctl.h>
48
49 #include <arm/mainbus/mainbus.h>
50 #include <machine/bus.h>
51 #include <machine/intr.h>
52
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wsdisplayvar.h>
55
56 #include <dev/rasops/rasops.h>
57 #include <dev/wsfont/wsfont.h>
58
59 #include <uvm/uvm_extern.h>
60 #include <arm/arm32/pmap.h>
61 #include <arm/cpufunc.h>
62 #include <machine/intr.h>
63
64 /* for vidc_mode ... needs to be MI indepenent one day */
65 #include <arm/iomd/vidc.h>
66 #include <arm/iomd/vidc20config.h>
67 #include <arm/iomd/vidcvideo.h>
68 #include <machine/bootconfig.h>
69
70 /* FOR DEBUG */
71 extern videomemory_t videomemory;
72
73 struct hwcmap256 {
74 #define CMAP_SIZE 256 /* 256 R/G/B entries */
75 u_int8_t r[CMAP_SIZE];
76 u_int8_t g[CMAP_SIZE];
77 u_int8_t b[CMAP_SIZE];
78 };
79
80
81 /* XXX for CURSOR_MAX_WIDTH = 32 */
82 struct hwcursor32 {
83 struct wsdisplay_curpos cc_pos;
84 struct wsdisplay_curpos cc_hot;
85 struct wsdisplay_curpos cc_size;
86 struct wsdisplay_curpos cc_magic;
87 u_int8_t cc_color[6]; /* how many? */
88 u_int32_t cc_image[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT];
89 u_int32_t cc_mask[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT];
90 };
91
92
93 struct fb_devconfig {
94 vaddr_t dc_vaddr; /* memory space virtual base address */
95 paddr_t dc_paddr; /* memory space physical base address */
96 vsize_t dc_size; /* size of slot memory */
97 int dc_wid; /* width of frame buffer */
98 int dc_ht; /* height of frame buffer */
99 int dc_log2_depth; /* log2 of bits per pixel */
100 int dc_depth; /* depth, bits per pixel */
101 int dc_rowbytes; /* bytes in a FB scan line */
102 vaddr_t dc_videobase; /* base of flat frame buffer */
103 int dc_blanked; /* currently has video disabled */
104 void *dc_hwscroll_cookie; /* cookie for hardware scroll */
105
106 int dc_curenb; /* is cursor sprite enabled ? */
107 int dc_changed; /* need update of hardware */
108 int dc_writeback_delay; /* Screenarea write back vsync counter */
109 #define WSDISPLAY_CMAP_DOLUT 0x20
110 #define WSDISPLAY_VIDEO_ONOFF 0x40
111 #define WSDISPLAY_WB_COUNTER 0x80
112
113 struct hwcmap256 dc_cmap;/* software copy of colormap */
114 struct hwcursor32 dc_cursor;/* software copy of cursor */
115
116 struct vidc_mode mode_info;
117 struct rasops_info rinfo;
118
119 struct wsdisplay_emulops orig_ri_ops; /* Rasops functions for deligation */
120 };
121
122
123 struct vidcvideo_softc {
124 struct device sc_dev;
125 struct fb_devconfig *sc_dc; /* device configuration */
126 int nscreens; /* number of screens configured */
127 };
128
129
130 /* XXX has to go XXX */
131 #define CX_MAGIC_X 220
132 #define CX_MAGIC_Y 35
133 #define CX_FB_OFFSET 0x000000
134 #define CX_FB_SIZE 0x100000
135 #define CX_BT459_OFFSET 0x200000
136 #define CX_OFFSET_IREQ 0x300000 /* Interrupt req. control */
137 /* XXX till here XXX */
138
139
140 /* Function prototypes for glue */
141 static int vidcvideo_match __P((struct device *, struct cfdata *, void *));
142 static void vidcvideo_attach __P((struct device *, struct device *, void *));
143
144
145 /* config glue */
146 CFATTACH_DECL(vidcvideo, sizeof(struct vidcvideo_softc),
147 vidcvideo_match, vidcvideo_attach, NULL, NULL);
148
149 static struct fb_devconfig vidcvideo_console_dc;
150 static int vidcvideo_is_console;
151
152
153 static struct wsscreen_descr vidcvideo_stdscreen = {
154 "std", 0, 0,
155 0, /* textops */
156 0, 0,
157 WSSCREEN_REVERSE
158 };
159
160 static const struct wsscreen_descr *_vidcvideo_scrlist[] = {
161 &vidcvideo_stdscreen,
162 };
163
164 static const struct wsscreen_list vidcvideo_screenlist = {
165 sizeof(_vidcvideo_scrlist) / sizeof(struct wsscreen_descr *), _vidcvideo_scrlist
166 };
167
168 static int vidcvideoioctl __P((void *, void *, u_long, caddr_t, int,
169 struct lwp *));
170 static paddr_t vidcvideommap __P((void *, void *, off_t, int));
171
172 static int vidcvideo_alloc_screen __P((void *, const struct wsscreen_descr *,
173 void **, int *, int *, long *));
174 static void vidcvideo_free_screen __P((void *, void *));
175 static int vidcvideo_show_screen __P((void *, void *, int,
176 void (*) (void *, int, int), void *));
177
178 static const struct wsdisplay_accessops vidcvideo_accessops = {
179 vidcvideoioctl,
180 vidcvideommap,
181 vidcvideo_alloc_screen,
182 vidcvideo_free_screen,
183 vidcvideo_show_screen,
184 NULL, /* load_font */
185 NULL, /* pollc */
186 NULL, /* getwschar */
187 NULL /* putwschar */
188 };
189
190
191 /* Function prototypes */
192 int vidcvideo_cnattach __P((vaddr_t));
193 static void vidcvideo_colourmap_and_cursor_init __P((struct fb_devconfig *));
194
195 static int get_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *));
196 static int set_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *));
197 static int set_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *));
198 static int get_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *));
199 static void set_curpos __P((struct vidcvideo_softc *, struct wsdisplay_curpos *));
200 static void vidcvideo_getdevconfig __P((vaddr_t, struct fb_devconfig *));
201
202 static int vidcvideointr __P((void *));
203 static void vidcvideo_config_wscons __P((struct fb_devconfig *));
204
205
206 /* Acceleration function prototypes */
207 static void vv_copyrows __P((void *, int, int, int));
208 static void vv_eraserows __P((void *, int, int, long));
209 static void vv_putchar __P((void *c, int row, int col, u_int uc, long attr));
210
211
212 static int
213 vidcvideo_match(parent, match, aux)
214 struct device *parent;
215 struct cfdata *match;
216 void *aux;
217 {
218 /* Can't probe AFAIK ; how ? */
219 return (1);
220 }
221
222
223 static void
224 vidcvideo_getdevconfig(dense_addr, dc)
225 vaddr_t dense_addr;
226 struct fb_devconfig *dc;
227 {
228 dc->dc_vaddr = dense_addr;
229 (void) pmap_extract(pmap_kernel(), dc->dc_vaddr, &(dc->dc_paddr));
230
231 vidcvideo_getmode(&dc->mode_info);
232
233 dc->dc_wid = dc->mode_info.hder;
234 dc->dc_ht = dc->mode_info.vder;
235 dc->dc_log2_depth = dc->mode_info.log2_bpp;
236 dc->dc_depth = 1 << dc->dc_log2_depth;
237 dc->dc_videobase = dc->dc_vaddr;
238 dc->dc_blanked = 0;
239
240 /* this should/could be done somewhat more elegant! */
241 switch (dc->dc_depth) {
242 case 1:
243 dc->dc_rowbytes = dc->dc_wid / 8;
244 break;
245 case 2:
246 dc->dc_rowbytes = dc->dc_wid / 4;
247 break;
248 case 4:
249 dc->dc_rowbytes = dc->dc_wid / 2;
250 break;
251 case 8:
252 dc->dc_rowbytes = dc->dc_wid;
253 break;
254 case 16:
255 dc->dc_rowbytes = dc->dc_wid * 2;
256 break;
257 case 32:
258 dc->dc_rowbytes = dc->dc_wid * 4;
259 break;
260 default:
261 printf("Unknown colour depth %d ... what to do ?", dc->dc_depth);
262 break;
263 };
264
265 /* euhm... correct ? i.e. not complete VIDC memory */
266 dc->dc_size = dc->mode_info.vder * dc->dc_rowbytes;
267
268 /* initialize colormap and cursor resource */
269 vidcvideo_colourmap_and_cursor_init(dc);
270
271 dc->rinfo.ri_flg = 0; /* RI_CENTER; */
272 dc->rinfo.ri_depth = dc->dc_depth;
273 dc->rinfo.ri_bits = (void *) dc->dc_videobase;
274 dc->rinfo.ri_width = dc->dc_wid;
275 dc->rinfo.ri_height = dc->dc_ht;
276 dc->rinfo.ri_stride = dc->dc_rowbytes;
277 dc->rinfo.ri_hw = dc; /* link back */
278
279 /* intitialise miscelanious */
280 dc->dc_writeback_delay = 0;
281 }
282
283
284 static void
285 vidcvideo_config_wscons(dc)
286 struct fb_devconfig *dc;
287 {
288 int i, cookie, font_not_locked;
289
290 /* clear the screen ; why not a memset ? - it was this way so keep it for now */
291 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
292 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
293
294 wsfont_init();
295
296 /* prefer 8 pixel wide font */
297 cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_L2R,
298 WSDISPLAY_FONTORDER_L2R);
299 if (cookie <= 0)
300 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
301 WSDISPLAY_FONTORDER_L2R);
302
303 if (cookie < 0) {
304 /* Can I even print here ? */
305 printf("Font table empty! exiting\n");
306 return;
307 };
308
309 font_not_locked = wsfont_lock(cookie, &dc->rinfo.ri_font);
310
311 dc->rinfo.ri_wsfcookie = cookie;
312
313 rasops_init(&dc->rinfo,
314 dc->rinfo.ri_height / dc->rinfo.ri_font->fontheight,
315 dc->rinfo.ri_width / dc->rinfo.ri_font->fontwidth
316 );
317
318 /*
319 * Provide a hook for the acceleration functions and make a copy of the
320 * original rasops functions for passing on calls
321 */
322 dc->rinfo.ri_hw = dc;
323 memcpy(&(dc->orig_ri_ops), &(dc->rinfo.ri_ops), sizeof(struct wsdisplay_emulops));
324
325 /* add our accelerated functions */
326 dc->rinfo.ri_ops.eraserows = vv_eraserows;
327 dc->rinfo.ri_ops.copyrows = vv_copyrows;
328
329 /* add the extra activity measuring functions; they just delegate on */
330 dc->rinfo.ri_ops.putchar = vv_putchar;
331
332 /* XXX shouldn't be global */
333 vidcvideo_stdscreen.nrows = dc->rinfo.ri_rows;
334 vidcvideo_stdscreen.ncols = dc->rinfo.ri_cols;
335 vidcvideo_stdscreen.textops = &dc->rinfo.ri_ops;
336 vidcvideo_stdscreen.capabilities = dc->rinfo.ri_caps;
337
338 if (font_not_locked) {
339 printf(" warning ... couldn't lock font! ");
340 };
341 }
342
343
344 static void
345 vidcvideo_attach(parent, self, aux)
346 struct device *parent, *self;
347 void *aux;
348 {
349 struct vidcvideo_softc *sc = (struct vidcvideo_softc *)self;
350 struct fb_devconfig *dc;
351 struct wsemuldisplaydev_attach_args waa;
352 struct hwcmap256 *cm;
353 const u_int8_t *p;
354 long defattr;
355 int index;
356
357 vidcvideo_init();
358 if (sc->nscreens == 0) {
359 sc->sc_dc = &vidcvideo_console_dc;
360 if (!vidcvideo_is_console) {
361 printf(" : non console (no kbd yet) ");
362 vidcvideo_getdevconfig(videomemory.vidm_vbase, sc->sc_dc);
363 vidcvideo_config_wscons(sc->sc_dc);
364 (*sc->sc_dc->rinfo.ri_ops.allocattr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
365 };
366 sc->nscreens = 1;
367 } else {
368 printf(": allready attached ... can't cope with this\n");
369 return;
370 };
371
372 dc = sc->sc_dc;
373
374 vidcvideo_printdetails();
375 printf(": using %d x %d, %dbpp\n", dc->dc_wid, dc->dc_ht,
376 dc->dc_depth);
377
378 /* initialise rasops */
379 cm = &dc->dc_cmap;
380 p = rasops_cmap;
381 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
382 cm->r[index] = p[0];
383 cm->g[index] = p[1];
384 cm->b[index] = p[2];
385 }
386
387 /* what does these do ? */
388 dc->dc_cursor.cc_magic.x = CX_MAGIC_X;
389 dc->dc_cursor.cc_magic.y = CX_MAGIC_Y;
390
391 /* set up interrupt flags */
392 dc->dc_changed |= WSDISPLAY_CMAP_DOLUT;
393
394 /*
395 * Set up a link in the rasops structure to our device config
396 * for acceleration stuff
397 */
398 dc->rinfo.ri_hw = sc->sc_dc;
399
400 /* Establish an interrupt handler, and clear any pending interrupts */
401 intr_claim(IRQ_FLYBACK, IPL_TTY, "vblank", vidcvideointr, dc);
402
403 waa.console = (vidcvideo_is_console ? 1 : 0);
404 waa.scrdata = &vidcvideo_screenlist;
405 waa.accessops = &vidcvideo_accessops;
406 waa.accesscookie = sc;
407
408 config_found(self, &waa, wsemuldisplaydevprint);
409 }
410
411
412 static int
413 vidcvideoioctl(v, vs, cmd, data, flag, l)
414 void *v;
415 void *vs;
416 u_long cmd;
417 caddr_t data;
418 int flag;
419 struct lwp *l;
420 {
421 struct vidcvideo_softc *sc = v;
422 struct fb_devconfig *dc = sc->sc_dc;
423 int state;
424
425 switch (cmd) {
426 case WSDISPLAYIO_GTYPE:
427 *(u_int *)data = WSDISPLAY_TYPE_VIDC;
428 return (0);
429
430 case WSDISPLAYIO_GINFO:
431 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
432 wsd_fbip->height = dc->dc_ht;
433 wsd_fbip->width = dc->dc_wid;
434 wsd_fbip->depth = dc->dc_depth;
435 wsd_fbip->cmsize = CMAP_SIZE;
436 #undef fbt
437 return (0);
438
439 case WSDISPLAYIO_GETCMAP:
440 return get_cmap(sc, (struct wsdisplay_cmap *)data);
441
442 case WSDISPLAYIO_PUTCMAP:
443 return set_cmap(sc, (struct wsdisplay_cmap *)data);
444
445 case WSDISPLAYIO_SVIDEO:
446 state = *(int *)data;
447 dc->dc_blanked = (state == WSDISPLAYIO_VIDEO_OFF);
448 dc->dc_changed |= WSDISPLAY_VIDEO_ONOFF;
449 /* done on video blank */
450 return (0);
451
452 case WSDISPLAYIO_GVIDEO:
453 *(u_int *)data = dc->dc_blanked ?
454 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
455 return (0);
456
457 case WSDISPLAYIO_GCURPOS:
458 *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos;
459 return (0);
460
461 case WSDISPLAYIO_SCURPOS:
462 set_curpos(sc, (struct wsdisplay_curpos *)data);
463 dc->dc_changed |= WSDISPLAY_CURSOR_DOPOS;
464 return (0);
465
466 case WSDISPLAYIO_GCURMAX:
467 ((struct wsdisplay_curpos *)data)->x = CURSOR_MAX_WIDTH;
468 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_HEIGHT;
469 return (0);
470
471 case WSDISPLAYIO_GCURSOR:
472 return get_cursor(sc, (struct wsdisplay_cursor *)data);
473
474 case WSDISPLAYIO_SCURSOR:
475 return set_cursor(sc, (struct wsdisplay_cursor *)data);
476
477 case WSDISPLAYIO_SMODE:
478 state = *(int *)data;
479 if (state == WSDISPLAYIO_MODE_MAPPED) {
480 dc->dc_hwscroll_cookie = vidcvideo_hwscroll_reset();
481 };
482 if (state == WSDISPLAYIO_MODE_EMUL) {
483 vidcvideo_hwscroll_back(dc->dc_hwscroll_cookie);
484 };
485 vidcvideo_progr_scroll();
486
487 return (0);
488 }
489 return EPASSTHROUGH;
490 }
491
492
493 paddr_t
494 vidcvideommap(v, vs, offset, prot)
495 void *v;
496 void *vs;
497 off_t offset;
498 int prot;
499 {
500 struct vidcvideo_softc *sc = v;
501
502 if (offset >= sc->sc_dc->dc_size || offset < 0)
503 return (-1);
504
505 return arm_btop(sc->sc_dc->dc_paddr + offset);
506 }
507
508
509 static int
510 vidcvideo_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
511 void *v;
512 const struct wsscreen_descr *type;
513 void **cookiep;
514 int *curxp, *curyp;
515 long *attrp;
516 {
517 struct vidcvideo_softc *sc = v;
518 struct fb_devconfig *dc = sc->sc_dc;
519 long defattr;
520
521 /*
522 * One and just only one for now :( ... if the vidcconsole is not the
523 * console then this makes one wsconsole screen free for use !
524 */
525 if ((sc->nscreens > 1) || vidcvideo_is_console)
526 return (ENOMEM);
527
528 /* Add the screen to wscons to control */
529 *cookiep = &dc->rinfo;
530 *curxp = 0;
531 *curyp = 0;
532 vidcvideo_getdevconfig(videomemory.vidm_vbase, dc);
533 vidcvideo_config_wscons(dc);
534 (*dc->rinfo.ri_ops.allocattr)(&dc->rinfo, 0, 0, 0, &defattr);
535 *attrp = defattr;
536 sc->nscreens++;
537
538 return (0);
539 }
540
541
542 static void
543 vidcvideo_free_screen(v, cookie)
544 void *v;
545 void *cookie;
546 {
547 struct vidcvideo_softc *sc = v;
548
549 if (sc->sc_dc == &vidcvideo_console_dc)
550 panic("vidcvideo_free_screen: console");
551
552 sc->nscreens--;
553 }
554
555
556 static int
557 vidcvideo_show_screen(v, cookie, waitok, cb, cbarg)
558 void *v;
559 void *cookie;
560 int waitok;
561 void (*cb) __P((void *, int, int));
562 void *cbarg;
563 {
564
565 return (0);
566 }
567
568
569 /* EXPORT */ int
570 vidcvideo_cnattach(addr)
571 vaddr_t addr;
572 {
573 struct fb_devconfig *dcp = &vidcvideo_console_dc;
574 long defattr;
575
576 vidcvideo_init();
577 vidcvideo_getdevconfig(addr, dcp);
578 vidcvideo_config_wscons(dcp);
579 (*dcp->rinfo.ri_ops.allocattr)(&dcp->rinfo, 0, 0, 0, &defattr);
580 wsdisplay_cnattach(&vidcvideo_stdscreen, &dcp->rinfo, 0, 0, defattr);
581
582 vidcvideo_is_console = 1;
583 return(0);
584 }
585
586
587 static int
588 vidcvideointr(arg)
589 void *arg;
590 {
591 struct fb_devconfig *dc = arg;
592 int v, cleared = 0;
593
594 v = dc->dc_changed;
595 if (v == 0)
596 return (1);
597
598 if (v & WSDISPLAY_WB_COUNTER) {
599 dc->dc_writeback_delay--;
600 if (dc->dc_writeback_delay == 0) {
601 cpu_dcache_wb_range(dc->dc_vaddr, dc->dc_size);
602 cleared |= WSDISPLAY_WB_COUNTER;
603 };
604 }
605
606 if (v & WSDISPLAY_CMAP_DOLUT) {
607 struct hwcmap256 *cm = &dc->dc_cmap;
608 int index;
609
610 if (dc->dc_depth == 4) {
611 /* palette for 4 bpp is different from 8bpp */
612 vidcvideo_write(VIDC_PALREG, 0x00000000);
613 for (index=0; index < (1 << dc->dc_depth); index++)
614 vidcvideo_write(VIDC_PALETTE,
615 VIDC_COL(cm->r[index],
616 cm->g[index],
617 cm->b[index]));
618 ;
619 };
620
621 if (dc->dc_depth == 8) {
622 /* dunno what to do in more than 8bpp */
623 /* palettes only make sense in 8bpp and less modes on VIDC */
624 vidcvideo_write(VIDC_PALREG, 0x00000000);
625 for (index = 0; index < CMAP_SIZE; index++) {
626 vidcvideo_write(VIDC_PALETTE,
627 VIDC_COL(cm->r[index], cm->g[index], cm->b[index])
628 );
629 };
630 };
631 cleared |= WSDISPLAY_CMAP_DOLUT;
632 }
633
634 if (v & WSDISPLAY_VIDEO_ONOFF) {
635 vidcvideo_blank(dc->dc_blanked);
636 cleared |= WSDISPLAY_VIDEO_ONOFF;
637 };
638
639 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
640 int x, y;
641 x = dc->dc_cursor.cc_pos.x - dc->dc_cursor.cc_hot.x;
642 y = dc->dc_cursor.cc_pos.y - dc->dc_cursor.cc_hot.y;
643
644 vidcvideo_updatecursor(x, y);
645 cleared |= WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT;
646 };
647
648 if (v & WSDISPLAY_CURSOR_DOCUR) {
649 vidcvideo_enablecursor(dc->dc_curenb);
650 cleared |= WSDISPLAY_CURSOR_DOCUR;
651 };
652
653
654 #if 0 /* XXX snip XXX */
655 /* XXX kept here as an archive for now XXX */
656
657 vdac = vidcvideobase + CX_BT459_OFFSET;
658 v = sc->sc_changed;
659 if (v & WSDISPLAY_CURSOR_DOCUR) {
660 SELECT(vdac, BT459_IREG_CCR);
661 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
662 }
663 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
664 int x, y;
665
666 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
667 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
668
669 x += sc->sc_cursor.cc_magic.x;
670 y += sc->sc_cursor.cc_magic.y;
671
672 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
673 REG(vdac, bt_reg) = x; tc_wmb();
674 REG(vdac, bt_reg) = x >> 8; tc_wmb();
675 REG(vdac, bt_reg) = y; tc_wmb();
676 REG(vdac, bt_reg) = y >> 8; tc_wmb();
677 }
678 if (v & WSDISPLAY_CURSOR_DOCMAP) {
679 u_int8_t *cp = sc->sc_cursor.cc_color;
680
681 SELECT(vdac, BT459_IREG_CCOLOR_2);
682 REG(vdac, bt_reg) = cp[1]; tc_wmb();
683 REG(vdac, bt_reg) = cp[3]; tc_wmb();
684 REG(vdac, bt_reg) = cp[5]; tc_wmb();
685
686 REG(vdac, bt_reg) = cp[0]; tc_wmb();
687 REG(vdac, bt_reg) = cp[2]; tc_wmb();
688 REG(vdac, bt_reg) = cp[4]; tc_wmb();
689 }
690 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
691 u_int8_t *ip, *mp, img, msk;
692 u_int8_t u;
693 int bcnt;
694
695 ip = (u_int8_t *)sc->sc_cursor.cc_image;
696 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_HEIGHT);
697
698 bcnt = 0;
699 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
700 /* 64 pixel scan line is consisted with 16 byte cursor ram */
701 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
702 /* pad right half 32 pixel when smaller than 33 */
703 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
704 REG(vdac, bt_reg) = 0; tc_wmb();
705 REG(vdac, bt_reg) = 0; tc_wmb();
706 }
707 else {
708 img = *ip++;
709 msk = *mp++;
710 img &= msk; /* cookie off image */
711 u = (msk & 0x0f) << 4 | (img & 0x0f);
712 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
713 u = (msk & 0xf0) | (img & 0xf0) >> 4;
714 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
715 }
716 bcnt += 2;
717 }
718 /* pad unoccupied scan lines */
719 while (bcnt < CURSOR_MAX_HEIGHT * 16) {
720 REG(vdac, bt_reg) = 0; tc_wmb();
721 REG(vdac, bt_reg) = 0; tc_wmb();
722 bcnt += 2;
723 }
724 }
725 #endif /* XXX snip XXX */
726
727 dc->dc_changed ^= cleared;
728
729 return (1);
730 }
731
732
733 static u_char ri_col_data[6][6] = {
734 { 0, 0, 0, 0, 0, 0}, /* 1 bpp */
735 { 0, 0, 0, 0, 0, 0}, /* 2 bpp */
736 { 0, 0, 0, 0, 0, 0}, /* 4 bpp */
737 { 0, 0, 0, 0, 0, 0}, /* 8 bpp */
738 { 6, 5, 5, 0, 6, 11}, /* 16 bpp */
739 { 8, 8, 8, 0, 8, 16}, /* 32 bpp */
740 };
741
742 static void
743 vidcvideo_colourmap_and_cursor_init(dc)
744 struct fb_devconfig *dc;
745 {
746 struct rasops_info *ri = &dc->rinfo;
747 u_char *rgbdat;
748
749 /* Whatever we do later... just make sure we have a
750 * sane palette to start with
751 */
752 vidcvideo_stdpalette();
753
754 /* set up rgb bit pattern values for rasops_init */
755 rgbdat = ri_col_data[dc->dc_log2_depth];
756 ri->ri_rnum = rgbdat[0];
757 ri->ri_gnum = rgbdat[1];
758 ri->ri_bnum = rgbdat[2];
759 ri->ri_rpos = rgbdat[3];
760 ri->ri_gpos = rgbdat[4];
761 ri->ri_bpos = rgbdat[5];
762
763 }
764
765
766 static int
767 get_cmap(sc, p)
768 struct vidcvideo_softc *sc;
769 struct wsdisplay_cmap *p;
770 {
771 u_int index = p->index, count = p->count;
772 int error;
773
774 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
775 return (EINVAL);
776
777 error = copyout(&sc->sc_dc->dc_cmap.r[index], p->red, count);
778 if (error)
779 return error;
780 error = copyout(&sc->sc_dc->dc_cmap.g[index], p->green, count);
781 if (error)
782 return error;
783 error = copyout(&sc->sc_dc->dc_cmap.b[index], p->blue, count);
784 return error;
785 }
786
787
788 static int
789 set_cmap(sc, p)
790 struct vidcvideo_softc *sc;
791 struct wsdisplay_cmap *p;
792 {
793 struct fb_devconfig *dc = sc->sc_dc;
794 struct hwcmap256 cmap;
795 u_int index = p->index, count = p->count;
796 int error;
797
798 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
799 return (EINVAL);
800
801 error = copyin(p->red, &cmap.r[index], count);
802 if (error)
803 return error;
804 error = copyin(p->green, &cmap.g[index], count);
805 if (error)
806 return error;
807 error = copyin(p->blue, &cmap.b[index], count);
808 if (error)
809 return error;
810 memcpy(&dc->dc_cmap.r[index], &cmap.r[index], count);
811 memcpy(&dc->dc_cmap.g[index], &cmap.g[index], count);
812 memcpy(&dc->dc_cmap.b[index], &cmap.b[index], count);
813 dc->dc_changed |= WSDISPLAY_CMAP_DOLUT;
814 return (0);
815 }
816
817
818 static int
819 set_cursor(sc, p)
820 struct vidcvideo_softc *sc;
821 struct wsdisplay_cursor *p;
822 {
823 #define cc (&dc->dc_cursor)
824 struct fb_devconfig *dc = sc->sc_dc;
825 u_int v, index = 0, count = 0, icount = 0;
826 uint8_t r[2], g[2], b[2], image[512], mask[512];
827 int error;
828
829 /* XXX gcc does not detect identical conditions */
830 index = count = icount = 0;
831
832 v = p->which;
833 if (v & WSDISPLAY_CURSOR_DOCMAP) {
834 index = p->cmap.index;
835 count = p->cmap.count;
836 if (index >= CURSOR_MAX_COLOURS ||
837 (index + count) > CURSOR_MAX_COLOURS)
838 return (EINVAL);
839 error = copyin(p->cmap.red, &r[index], count);
840 if (error)
841 return error;
842 error = copyin(p->cmap.green, &g[index], count);
843 if (error)
844 return error;
845 error = copyin(p->cmap.blue, &b[index], count);
846 if (error)
847 return error;
848 }
849 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
850 if (p->size.x > CURSOR_MAX_WIDTH ||
851 p->size.y > CURSOR_MAX_HEIGHT)
852 return (EINVAL);
853 icount = sizeof(u_int32_t) * p->size.y;
854 error = copyin(p->image, &image, icount);
855 if (error)
856 return error;
857 error = copyin(p->mask, &mask, icount);
858 if (error)
859 return error;
860 }
861
862 if (v & WSDISPLAY_CURSOR_DOCUR)
863 dc->dc_curenb = p->enable;
864 if (v & WSDISPLAY_CURSOR_DOPOS)
865 set_curpos(sc, &p->pos);
866 if (v & WSDISPLAY_CURSOR_DOHOT)
867 cc->cc_hot = p->hot;
868 if (v & WSDISPLAY_CURSOR_DOCMAP) {
869 memcpy(&cc->cc_color[index], &r[index], count);
870 memcpy(&cc->cc_color[index + 2], &g[index], count);
871 memcpy(&cc->cc_color[index + 4], &b[index], count);
872 }
873 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
874 cc->cc_size = p->size;
875 memset(cc->cc_image, 0, sizeof cc->cc_image);
876 memcpy(cc->cc_image, image, icount);
877 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
878 memcpy(cc->cc_mask, mask, icount);
879 }
880 dc->dc_changed |= v;
881
882 return (0);
883 #undef cc
884 }
885
886
887 static int
888 get_cursor(sc, p)
889 struct vidcvideo_softc *sc;
890 struct wsdisplay_cursor *p;
891 {
892 return (EPASSTHROUGH); /* XXX */
893 }
894
895
896 static void
897 set_curpos(sc, curpos)
898 struct vidcvideo_softc *sc;
899 struct wsdisplay_curpos *curpos;
900 {
901 struct fb_devconfig *dc = sc->sc_dc;
902 int x = curpos->x, y = curpos->y;
903
904 if (y < 0)
905 y = 0;
906 else if (y > dc->dc_ht)
907 y = dc->dc_ht;
908 if (x < 0)
909 x = 0;
910 else if (x > dc->dc_wid)
911 x = dc->dc_wid;
912 dc->dc_cursor.cc_pos.x = x;
913 dc->dc_cursor.cc_pos.y = y;
914 }
915
916
917 static void vv_copyrows(id, srcrow, dstrow, nrows)
918 void *id;
919 int srcrow, dstrow, nrows;
920 {
921 struct rasops_info *ri = id;
922 int height, offset, size;
923 int scrollup, scrolldown;
924 unsigned char *src, *dst;
925
926 /* All movements are done in multiples of character heigths */
927 height = ri->ri_font->fontheight * nrows;
928 offset = (srcrow - dstrow) * ri->ri_yscale;
929 size = height * ri->ri_stride;
930
931 /* check if we are full screen scrolling */
932 scrollup = (srcrow + nrows >= ri->ri_rows);
933 scrolldown = (dstrow + nrows >= ri->ri_rows);
934
935 if ((scrollup || scrolldown) && (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM)) {
936 ri->ri_bits = vidcvideo_hwscroll(offset);
937 vidcvideo_progr_scroll(); /* sadistic ; shouldnt this be on vsync? */
938
939 /* wipe out remains of the screen if nessisary */
940 if (ri->ri_emuheight != ri->ri_height) vv_eraserows(id, ri->ri_rows, 1, 0);
941 return;
942 };
943
944 /* Else we just copy the area : we're braindead for now
945 * Note: we can't use hardware scrolling when the softc isnt known yet...
946 * if its not known we dont have interrupts and we can't change the display
947 * address reliable other than in a Vsync
948 */
949
950 src = ri->ri_bits + srcrow * ri->ri_font->fontheight * ri->ri_stride;
951 dst = ri->ri_bits + dstrow * ri->ri_font->fontheight * ri->ri_stride;
952
953 bcopy(src, dst, size);
954 }
955
956
957 static void vv_eraserows(id, startrow, nrows, attr)
958 void *id;
959 int startrow, nrows;
960 long attr;
961 {
962 struct rasops_info *ri = id;
963 int height;
964 unsigned char *src;
965
966 /* we're braindead for now */
967 height = ri->ri_font->fontheight * nrows * ri->ri_stride;
968
969 src = ri->ri_bits + startrow * ri->ri_font->fontheight * ri->ri_stride;
970
971 bzero(src, height);
972 }
973
974
975 static void vv_putchar(id, row, col, uc, attr)
976 void *id;
977 int row, col;
978 u_int uc;
979 long attr;
980 {
981 struct rasops_info *ri = id;
982 struct fb_devconfig *dc = (struct fb_devconfig *) (ri->ri_hw);
983
984 /* delay the write back operation of the screen area */
985 dc->dc_writeback_delay = SCREEN_WRITE_BACK_DELAY;
986 dc->dc_changed |= WSDISPLAY_WB_COUNTER;
987
988 /* just delegate */
989 dc->orig_ri_ops.putchar(id, row, col, uc, attr);
990 }
991