Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / tc / cfb.c
bloba8dd40429f03ddde1766dd5d4c525477336cd18d
1 /* $NetBSD: cfb.c,v 1.56 2008/12/17 20:51:34 cegger Exp $ */
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cfb.c,v 1.56 2008/12/17 20:51:34 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/ioctl.h>
43 #include <sys/bus.h>
44 #include <sys/intr.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt459reg.h>
55 #include <uvm/uvm_extern.h>
57 #if defined(pmax)
58 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
59 #endif
61 #if defined(alpha)
62 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
63 #endif
66 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
67 * obscure register layout such as 2nd and 3rd Bt459 registers are
68 * adjacent each other in a word, i.e.,
69 * struct bt459triplet {
70 * struct {
71 * uint8_t u0;
72 * uint8_t u1;
73 * uint8_t u2;
74 * unsigned :8;
75 * } bt_lo;
76 * ...
77 * Although CX has single Bt459, 32bit R/W can be done w/o any trouble.
78 * struct bt459reg {
79 * uint32_t bt_lo;
80 * uint32_t bt_hi;
81 * uint32_t bt_reg;
82 * uint32_t bt_cmap;
83 * };
86 /* Bt459 hardware registers, memory-mapped in 32bit stride */
87 #define bt_lo 0x0
88 #define bt_hi 0x4
89 #define bt_reg 0x8
90 #define bt_cmap 0xc
92 #define REGWRITE32(p,i,v) do { \
93 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \
94 } while (0)
95 #define VDACSELECT(p,r) do { \
96 REGWRITE32(p, bt_lo, 0xff & (r)); \
97 REGWRITE32(p, bt_hi, 0x0f & ((r)>>8)); \
98 } while (0)
100 struct hwcmap256 {
101 #define CMAP_SIZE 256 /* 256 R/G/B entries */
102 uint8_t r[CMAP_SIZE];
103 uint8_t g[CMAP_SIZE];
104 uint8_t b[CMAP_SIZE];
107 struct hwcursor64 {
108 struct wsdisplay_curpos cc_pos;
109 struct wsdisplay_curpos cc_hot;
110 struct wsdisplay_curpos cc_size;
111 struct wsdisplay_curpos cc_magic;
112 #define CURSOR_MAX_SIZE 64
113 uint8_t cc_color[6];
114 uint64_t cc_image[CURSOR_MAX_SIZE];
115 uint64_t cc_mask[CURSOR_MAX_SIZE];
118 struct cfb_softc {
119 vaddr_t sc_vaddr;
120 size_t sc_size;
121 struct rasops_info *sc_ri;
122 struct hwcmap256 sc_cmap; /* software copy of colormap */
123 struct hwcursor64 sc_cursor; /* software copy of cursor */
124 int sc_blanked;
125 int sc_curenb; /* cursor sprite enabled */
126 int sc_changed; /* need update of hardware */
127 #define WSDISPLAY_CMAP_DOLUT 0x20
128 int nscreens;
131 #define CX_MAGIC_X 220
132 #define CX_MAGIC_Y 35
134 #define CX_FB_OFFSET 0x000000
135 #define CX_FB_SIZE 0x100000
136 #define CX_BT459_OFFSET 0x200000
137 #define CX_OFFSET_IREQ 0x300000 /* Interrupt req. control */
139 static int cfbmatch(device_t, cfdata_t, void *);
140 static void cfbattach(device_t, device_t, void *);
142 CFATTACH_DECL_NEW(cfb, sizeof(struct cfb_softc),
143 cfbmatch, cfbattach, NULL, NULL);
145 static void cfb_common_init(struct rasops_info *);
146 static struct rasops_info cfb_console_ri;
147 static tc_addr_t cfb_consaddr;
149 static struct wsscreen_descr cfb_stdscreen = {
150 "std", 0, 0,
151 0, /* textops */
152 0, 0,
153 WSSCREEN_REVERSE
156 static const struct wsscreen_descr *_cfb_scrlist[] = {
157 &cfb_stdscreen,
160 static const struct wsscreen_list cfb_screenlist = {
161 sizeof(_cfb_scrlist) / sizeof(struct wsscreen_descr *), _cfb_scrlist
164 static int cfbioctl(void *, void *, u_long, void *, int, struct lwp *);
165 static paddr_t cfbmmap(void *, void *, off_t, int);
167 static int cfb_alloc_screen(void *, const struct wsscreen_descr *,
168 void **, int *, int *, long *);
169 static void cfb_free_screen(void *, void *);
170 static int cfb_show_screen(void *, void *, int,
171 void (*) (void *, int, int), void *);
173 static const struct wsdisplay_accessops cfb_accessops = {
174 cfbioctl,
175 cfbmmap,
176 cfb_alloc_screen,
177 cfb_free_screen,
178 cfb_show_screen,
179 0 /* load_font */
182 int cfb_cnattach(tc_addr_t);
183 static int cfbintr(void *);
184 static void cfbhwinit(void *);
185 static void cfb_cmap_init(struct cfb_softc *);
187 static int get_cmap(struct cfb_softc *, struct wsdisplay_cmap *);
188 static int set_cmap(struct cfb_softc *, struct wsdisplay_cmap *);
189 static int set_cursor(struct cfb_softc *, struct wsdisplay_cursor *);
190 static int get_cursor(struct cfb_softc *, struct wsdisplay_cursor *);
191 static void set_curpos(struct cfb_softc *, struct wsdisplay_curpos *);
194 * Compose 2 bit/pixel cursor image. Bit order will be reversed.
195 * M M M M I I I I M I M I M I M I
196 * [ before ] [ after ]
197 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3
198 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7
200 static const uint8_t shuffle[256] = {
201 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
202 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
203 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
204 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
205 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
206 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
207 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
208 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
209 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
210 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
211 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
212 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
213 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
214 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
215 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
216 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
217 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
218 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
219 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
220 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
221 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
222 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
223 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
224 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
225 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
226 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
227 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
228 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
229 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
230 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
231 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
232 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
235 static int
236 cfbmatch(device_t parent, cfdata_t match, void *aux)
238 struct tc_attach_args *ta = aux;
240 if (strncmp("PMAG-BA ", ta->ta_modname, TC_ROM_LLEN) != 0)
241 return (0);
243 return (1);
246 static void
247 cfbattach(device_t parent, device_t self, void *aux)
249 struct cfb_softc *sc = device_private(self);
250 struct tc_attach_args *ta = aux;
251 struct rasops_info *ri;
252 struct wsemuldisplaydev_attach_args waa;
253 int console;
255 console = (ta->ta_addr == cfb_consaddr);
256 if (console) {
257 sc->sc_ri = ri = &cfb_console_ri;
258 sc->nscreens = 1;
260 else {
261 ri = malloc(sizeof(struct rasops_info),
262 M_DEVBUF, M_NOWAIT|M_ZERO);
263 if (ri == NULL) {
264 printf(": can't alloc memory\n");
265 return;
268 ri->ri_hw = (void *)ta->ta_addr;
269 cfb_common_init(ri);
270 sc->sc_ri = ri;
272 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
274 cfb_cmap_init(sc);
276 sc->sc_vaddr = ta->ta_addr;
277 sc->sc_cursor.cc_magic.x = CX_MAGIC_X;
278 sc->sc_cursor.cc_magic.y = CX_MAGIC_Y;
279 sc->sc_blanked = sc->sc_curenb = 0;
281 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, cfbintr, sc);
283 /* clear any pending interrupts */
284 *(volatile uint8_t *)((char *)ri->ri_hw + CX_OFFSET_IREQ) = 0;
286 waa.console = console;
287 waa.scrdata = &cfb_screenlist;
288 waa.accessops = &cfb_accessops;
289 waa.accesscookie = sc;
291 config_found(self, &waa, wsemuldisplaydevprint);
294 static void
295 cfb_cmap_init(struct cfb_softc *sc)
297 struct hwcmap256 *cm;
298 const uint8_t *p;
299 int index;
301 cm = &sc->sc_cmap;
302 p = rasops_cmap;
303 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
304 cm->r[index] = p[0];
305 cm->g[index] = p[1];
306 cm->b[index] = p[2];
310 static void
311 cfb_common_init(struct rasops_info *ri)
313 char *base;
314 int cookie;
316 base = (void *)ri->ri_hw;
318 /* initialize colormap and cursor hardware */
319 cfbhwinit(base);
321 ri->ri_flg = RI_CENTER;
322 ri->ri_depth = 8;
323 ri->ri_width = 1024;
324 ri->ri_height = 864;
325 ri->ri_stride = 1024;
326 ri->ri_bits = base + CX_FB_OFFSET;
328 /* clear the screen */
329 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
331 wsfont_init();
332 /* prefer 12 pixel wide font */
333 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
334 WSDISPLAY_FONTORDER_L2R);
335 if (cookie <= 0)
336 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
337 WSDISPLAY_FONTORDER_L2R);
338 if (cookie <= 0) {
339 printf("cfb: font table is empty\n");
340 return;
343 if (wsfont_lock(cookie, &ri->ri_font)) {
344 printf("cfb: couldn't lock font\n");
345 return;
347 ri->ri_wsfcookie = cookie;
349 rasops_init(ri, 34, 80);
351 /* XXX shouldn't be global */
352 cfb_stdscreen.nrows = ri->ri_rows;
353 cfb_stdscreen.ncols = ri->ri_cols;
354 cfb_stdscreen.textops = &ri->ri_ops;
355 cfb_stdscreen.capabilities = ri->ri_caps;
358 static int
359 cfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
361 struct cfb_softc *sc = v;
362 struct rasops_info *ri = sc->sc_ri;
363 int turnoff, s;
365 switch (cmd) {
366 case WSDISPLAYIO_GTYPE:
367 *(u_int *)data = WSDISPLAY_TYPE_CFB;
368 return (0);
370 case WSDISPLAYIO_GINFO:
371 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
372 wsd_fbip->height = ri->ri_height;
373 wsd_fbip->width = ri->ri_width;
374 wsd_fbip->depth = ri->ri_depth;
375 wsd_fbip->cmsize = CMAP_SIZE;
376 #undef fbt
377 return (0);
379 case WSDISPLAYIO_GETCMAP:
380 return get_cmap(sc, (struct wsdisplay_cmap *)data);
382 case WSDISPLAYIO_PUTCMAP:
383 return set_cmap(sc, (struct wsdisplay_cmap *)data);
385 case WSDISPLAYIO_SVIDEO:
386 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
387 if (sc->sc_blanked != turnoff) {
388 sc->sc_blanked = turnoff;
389 /* XXX later XXX */
391 return (0);
393 case WSDISPLAYIO_GVIDEO:
394 *(u_int *)data = sc->sc_blanked ?
395 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
396 return (0);
398 case WSDISPLAYIO_GCURPOS:
399 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
400 return (0);
402 case WSDISPLAYIO_SCURPOS:
403 s = spltty();
404 set_curpos(sc, (struct wsdisplay_curpos *)data);
405 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
406 splx(s);
407 return (0);
409 case WSDISPLAYIO_GCURMAX:
410 ((struct wsdisplay_curpos *)data)->x =
411 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
412 return (0);
414 case WSDISPLAYIO_GCURSOR:
415 return get_cursor(sc, (struct wsdisplay_cursor *)data);
417 case WSDISPLAYIO_SCURSOR:
418 return set_cursor(sc, (struct wsdisplay_cursor *)data);
420 case WSDISPLAYIO_SMODE:
421 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
422 s = spltty();
423 cfb_cmap_init(sc);
424 sc->sc_curenb = 0;
425 sc->sc_blanked = 0;
426 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
427 WSDISPLAY_CMAP_DOLUT);
428 splx(s);
430 return (0);
432 return EPASSTHROUGH;
435 paddr_t
436 cfbmmap(void *v, void *vs, off_t offset, int prot)
438 struct cfb_softc *sc = v;
440 if (offset >= CX_FB_SIZE || offset < 0)
441 return (-1);
442 return machine_btop(sc->sc_vaddr + CX_FB_OFFSET + offset);
445 static int
446 cfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
447 int *curxp, int *curyp, long *attrp)
449 struct cfb_softc *sc = v;
450 struct rasops_info *ri = sc->sc_ri;
451 long defattr;
453 if (sc->nscreens > 0)
454 return (ENOMEM);
456 *cookiep = ri; /* one and only for now */
457 *curxp = 0;
458 *curyp = 0;
459 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
460 *attrp = defattr;
461 sc->nscreens++;
462 return (0);
465 static void
466 cfb_free_screen(void *v, void *cookie)
468 struct cfb_softc *sc = v;
470 if (sc->sc_ri == &cfb_console_ri)
471 panic("cfb_free_screen: console");
473 sc->nscreens--;
476 static int
477 cfb_show_screen(void *v, void *cookie, int waitok,
478 void (*cb)(void *, int, int), void *cbarg)
481 return (0);
484 /* EXPORT */ int
485 cfb_cnattach(tc_addr_t addr)
487 struct rasops_info *ri;
488 long defattr;
490 ri = &cfb_console_ri;
491 ri->ri_hw = (void *)addr;
492 cfb_common_init(ri);
493 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
494 wsdisplay_cnattach(&cfb_stdscreen, ri, 0, 0, defattr);
495 cfb_consaddr = addr;
496 return(0);
499 static int
500 cfbintr(void *arg)
502 struct cfb_softc *sc = arg;
503 char *base, *vdac;
504 int v;
506 base = (void *)sc->sc_ri->ri_hw;
507 *(uint8_t *)(base + CX_OFFSET_IREQ) = 0;
508 if (sc->sc_changed == 0)
509 return (1);
511 vdac = base + CX_BT459_OFFSET;
512 v = sc->sc_changed;
513 if (v & WSDISPLAY_CURSOR_DOCUR) {
514 VDACSELECT(vdac, BT459_IREG_CCR);
515 REGWRITE32(vdac, bt_reg, (sc->sc_curenb) ? 0xc0 : 0x00);
517 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
518 int x, y;
520 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
521 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
523 x += sc->sc_cursor.cc_magic.x;
524 y += sc->sc_cursor.cc_magic.y;
526 VDACSELECT(vdac, BT459_IREG_CURSOR_X_LOW);
527 REGWRITE32(vdac, bt_reg, x);
528 REGWRITE32(vdac, bt_reg, x >> 8);
529 REGWRITE32(vdac, bt_reg, y);
530 REGWRITE32(vdac, bt_reg, y >> 8);
532 if (v & WSDISPLAY_CURSOR_DOCMAP) {
533 uint8_t *cp = sc->sc_cursor.cc_color;
535 VDACSELECT(vdac, BT459_IREG_CCOLOR_2);
536 REGWRITE32(vdac, bt_reg, cp[1]);
537 REGWRITE32(vdac, bt_reg, cp[3]);
538 REGWRITE32(vdac, bt_reg, cp[5]);
540 REGWRITE32(vdac, bt_reg, cp[0]);
541 REGWRITE32(vdac, bt_reg, cp[2]);
542 REGWRITE32(vdac, bt_reg, cp[4]);
544 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
545 uint8_t *ip, *mp, img, msk;
546 uint8_t u;
547 int bcnt;
549 ip = (uint8_t *)sc->sc_cursor.cc_image;
550 mp = (uint8_t *)sc->sc_cursor.cc_mask;
552 bcnt = 0;
553 VDACSELECT(vdac, BT459_IREG_CRAM_BASE+0);
554 /* 64 pixel scan line is consisted with 16 byte cursor ram */
555 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
556 /* pad right half 32 pixel when smaller than 33 */
557 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
558 REGWRITE32(vdac, bt_reg, 0);
559 REGWRITE32(vdac, bt_reg, 0);
561 else {
562 img = *ip++;
563 msk = *mp++;
564 img &= msk; /* cookie off image */
565 u = (msk & 0x0f) << 4 | (img & 0x0f);
566 REGWRITE32(vdac, bt_reg, shuffle[u]);
567 u = (msk & 0xf0) | (img & 0xf0) >> 4;
568 REGWRITE32(vdac, bt_reg, shuffle[u]);
570 bcnt += 2;
572 /* pad unoccupied scan lines */
573 while (bcnt < CURSOR_MAX_SIZE * 16) {
574 REGWRITE32(vdac, bt_reg, 0);
575 REGWRITE32(vdac, bt_reg, 0);
576 bcnt += 2;
579 if (v & WSDISPLAY_CMAP_DOLUT) {
580 struct hwcmap256 *cm = &sc->sc_cmap;
581 int index;
583 VDACSELECT(vdac, 0);
584 for (index = 0; index < CMAP_SIZE; index++) {
585 REGWRITE32(vdac, bt_cmap, cm->r[index]);
586 REGWRITE32(vdac, bt_cmap, cm->g[index]);
587 REGWRITE32(vdac, bt_cmap, cm->b[index]);
590 sc->sc_changed = 0;
591 return (1);
594 static void
595 cfbhwinit(void *cfbbase)
597 char *vdac = (char *)cfbbase + CX_BT459_OFFSET;
598 const uint8_t *p;
599 int i;
601 VDACSELECT(vdac, BT459_IREG_COMMAND_0);
602 REGWRITE32(vdac, bt_reg, 0x40); /* CMD0 */
603 REGWRITE32(vdac, bt_reg, 0x0); /* CMD1 */
604 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD2 */
605 REGWRITE32(vdac, bt_reg, 0xff); /* PRM */
606 REGWRITE32(vdac, bt_reg, 0); /* 205 */
607 REGWRITE32(vdac, bt_reg, 0x0); /* PBM */
608 REGWRITE32(vdac, bt_reg, 0); /* 207 */
609 REGWRITE32(vdac, bt_reg, 0x0); /* ORM */
610 REGWRITE32(vdac, bt_reg, 0x0); /* OBM */
611 REGWRITE32(vdac, bt_reg, 0x0); /* ILV */
612 REGWRITE32(vdac, bt_reg, 0x0); /* TEST */
614 VDACSELECT(vdac, BT459_IREG_CCR);
615 REGWRITE32(vdac, bt_reg, 0x0);
616 REGWRITE32(vdac, bt_reg, 0x0);
617 REGWRITE32(vdac, bt_reg, 0x0);
618 REGWRITE32(vdac, bt_reg, 0x0);
619 REGWRITE32(vdac, bt_reg, 0x0);
620 REGWRITE32(vdac, bt_reg, 0x0);
621 REGWRITE32(vdac, bt_reg, 0x0);
622 REGWRITE32(vdac, bt_reg, 0x0);
623 REGWRITE32(vdac, bt_reg, 0x0);
624 REGWRITE32(vdac, bt_reg, 0x0);
625 REGWRITE32(vdac, bt_reg, 0x0);
626 REGWRITE32(vdac, bt_reg, 0x0);
627 REGWRITE32(vdac, bt_reg, 0x0);
629 /* build sane colormap */
630 VDACSELECT(vdac, 0);
631 p = rasops_cmap;
632 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
633 REGWRITE32(vdac, bt_cmap, p[0]);
634 REGWRITE32(vdac, bt_cmap, p[1]);
635 REGWRITE32(vdac, bt_cmap, p[2]);
638 /* clear out cursor image */
639 VDACSELECT(vdac, BT459_IREG_CRAM_BASE);
640 for (i = 0; i < 1024; i++)
641 REGWRITE32(vdac, bt_reg, 0xff);
644 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
645 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
646 * image color. CCOLOR_1 will be never used.
648 VDACSELECT(vdac, BT459_IREG_CCOLOR_1);
649 REGWRITE32(vdac, bt_reg, 0xff);
650 REGWRITE32(vdac, bt_reg, 0xff);
651 REGWRITE32(vdac, bt_reg, 0xff);
653 REGWRITE32(vdac, bt_reg, 0);
654 REGWRITE32(vdac, bt_reg, 0);
655 REGWRITE32(vdac, bt_reg, 0);
657 REGWRITE32(vdac, bt_reg, 0xff);
658 REGWRITE32(vdac, bt_reg, 0xff);
659 REGWRITE32(vdac, bt_reg, 0xff);
662 static int
663 get_cmap(struct cfb_softc *sc, struct wsdisplay_cmap *p)
665 u_int index = p->index, count = p->count;
666 int error;
668 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
669 return (EINVAL);
671 error = copyout(&sc->sc_cmap.r[index], p->red, count);
672 if (error)
673 return error;
674 error = copyout(&sc->sc_cmap.g[index], p->green, count);
675 if (error)
676 return error;
677 error = copyout(&sc->sc_cmap.b[index], p->blue, count);
678 return error;
681 static int
682 set_cmap(struct cfb_softc *sc, struct wsdisplay_cmap *p)
684 struct hwcmap256 cmap;
685 u_int index = p->index, count = p->count;
686 int error, s;
688 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
689 return (EINVAL);
691 error = copyin(p->red, &cmap.r[index], count);
692 if (error)
693 return error;
694 error = copyin(p->green, &cmap.g[index], count);
695 if (error)
696 return error;
697 error = copyin(p->blue, &cmap.b[index], count);
698 if (error)
699 return error;
700 s = spltty();
701 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
702 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
703 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
704 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
705 splx(s);
706 return (0);
709 static int
710 set_cursor(struct cfb_softc *sc, struct wsdisplay_cursor *p)
712 #define cc (&sc->sc_cursor)
713 u_int v, index = 0, count = 0, icount = 0;
714 uint8_t r[2], g[2], b[2], image[512], mask[512];
715 int error, s;
717 v = p->which;
718 if (v & WSDISPLAY_CURSOR_DOCMAP) {
719 index = p->cmap.index;
720 count = p->cmap.count;
721 if (index >= 2 || (index + count) > 2)
722 return (EINVAL);
723 error = copyin(p->cmap.red, &r[index], count);
724 if (error)
725 return error;
726 error = copyin(p->cmap.green, &g[index], count);
727 if (error)
728 return error;
729 error = copyin(p->cmap.blue, &b[index], count);
730 if (error)
731 return error;
733 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
734 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
735 return (EINVAL);
736 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
737 error = copyin(p->image, image, icount);
738 if (error)
739 return error;
740 error = copyin(p->mask, mask, icount);
741 if (error)
742 return error;
745 s = spltty();
746 if (v & WSDISPLAY_CURSOR_DOCUR)
747 sc->sc_curenb = p->enable;
748 if (v & WSDISPLAY_CURSOR_DOPOS)
749 set_curpos(sc, &p->pos);
750 if (v & WSDISPLAY_CURSOR_DOHOT)
751 cc->cc_hot = p->hot;
752 if (v & WSDISPLAY_CURSOR_DOCMAP) {
753 memcpy(&cc->cc_color[index], &r[index], count);
754 memcpy(&cc->cc_color[index + 2], &g[index], count);
755 memcpy(&cc->cc_color[index + 4], &b[index], count);
757 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
758 cc->cc_size = p->size;
759 memset(cc->cc_image, 0, sizeof cc->cc_image);
760 memcpy(cc->cc_image, image, icount);
761 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
762 memcpy(cc->cc_mask, mask, icount);
764 sc->sc_changed |= v;
765 splx(s);
767 return (0);
768 #undef cc
771 static int
772 get_cursor(struct cfb_softc *sc, struct wsdisplay_cursor *p)
774 return (EPASSTHROUGH); /* XXX */
777 static void
778 set_curpos(struct cfb_softc *sc, struct wsdisplay_curpos *curpos)
780 struct rasops_info *ri = sc->sc_ri;
781 int x = curpos->x, y = curpos->y;
783 if (y < 0)
784 y = 0;
785 else if (y > ri->ri_height)
786 y = ri->ri_height;
787 if (x < 0)
788 x = 0;
789 else if (x > ri->ri_width)
790 x = ri->ri_width;
791 sc->sc_cursor.cc_pos.x = x;
792 sc->sc_cursor.cc_pos.y = y;