1 /* $NetBSD: xcfb.c,v 1.50 2009/05/12 14:47:04 cegger Exp $ */
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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: xcfb.c,v 1.50 2009/05/12 14:47:04 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>
41 #include <sys/ioctl.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/tc/ioasicreg.h>
54 #include <dev/ic/ims332reg.h>
55 #include <pmax/pmax/maxine.h>
57 #include <uvm/uvm_extern.h>
60 #define CMAP_SIZE 256 /* 256 R/G/B entries */
67 struct wsdisplay_curpos cc_pos
;
68 struct wsdisplay_curpos cc_hot
;
69 struct wsdisplay_curpos cc_size
;
70 struct wsdisplay_curpos cc_magic
; /* not used by PMAG-DV */
71 #define CURSOR_MAX_SIZE 64
73 uint64_t cc_image
[CURSOR_MAX_SIZE
];
74 uint64_t cc_mask
[CURSOR_MAX_SIZE
];
77 #define XCFB_FB_BASE (XINE_PHYS_CFB_START + 0x2000000)
78 #define XCFB_FB_SIZE 0x100000
80 #define IMS332_HIGH (IOASIC_SLOT_5_START)
81 #define IMS332_RLOW (IOASIC_SLOT_7_START)
82 #define IMS332_WLOW (IOASIC_SLOT_7_START + 0x20000)
87 struct rasops_info
*sc_ri
;
88 struct hwcmap256 sc_cmap
; /* software copy of colormap */
89 struct hwcursor64 sc_cursor
; /* software copy of cursor */
91 /* XXX MAXINE can take PMAG-DV vertical retrace interrupt XXX */
93 /* cursor coordinate is located at upper-left corner */
94 int sc_csr
; /* software copy of IMS332 CSR A */
97 static int xcfbmatch(device_t
, cfdata_t
, void *);
98 static void xcfbattach(device_t
, device_t
, void *);
100 CFATTACH_DECL_NEW(xcfb
, sizeof(struct xcfb_softc
),
101 xcfbmatch
, xcfbattach
, NULL
, NULL
);
103 static tc_addr_t xcfb_consaddr
;
104 static struct rasops_info xcfb_console_ri
;
105 static void xcfb_common_init(struct rasops_info
*);
106 static void xcfbhwinit(void *);
107 int xcfb_cnattach(void);
109 struct wsscreen_descr xcfb_stdscreen
= {
116 static const struct wsscreen_descr
*_xcfb_scrlist
[] = {
120 static const struct wsscreen_list xcfb_screenlist
= {
121 sizeof(_xcfb_scrlist
) / sizeof(struct wsscreen_descr
*), _xcfb_scrlist
124 static int xcfbioctl(void *, void *, u_long
, void *, int, struct lwp
*);
125 static paddr_t
xcfbmmap(void *, void *, off_t
, int);
127 static int xcfb_alloc_screen(void *, const struct wsscreen_descr
*,
128 void **, int *, int *, long *);
129 static void xcfb_free_screen(void *, void *);
130 static int xcfb_show_screen(void *, void *, int,
131 void (*) (void *, int, int), void *);
133 static const struct wsdisplay_accessops xcfb_accessops
= {
142 static int xcfbintr(void *);
143 static void xcfb_screenblank(struct xcfb_softc
*);
144 static void xcfb_cmap_init(struct xcfb_softc
*);
145 static int set_cmap(struct xcfb_softc
*, struct wsdisplay_cmap
*);
146 static int get_cmap(struct xcfb_softc
*, struct wsdisplay_cmap
*);
147 static int set_cursor(struct xcfb_softc
*, struct wsdisplay_cursor
*);
148 static int get_cursor(struct xcfb_softc
*, struct wsdisplay_cursor
*);
149 static void set_curpos(struct xcfb_softc
*, struct wsdisplay_curpos
*);
150 static void ims332_loadcmap(struct hwcmap256
*);
151 static void ims332_set_curpos(struct xcfb_softc
*);
152 static void ims332_load_curcmap(struct xcfb_softc
*);
153 static void ims332_load_curshape(struct xcfb_softc
*);
154 static void ims332_write_reg(int, uint32_t);
156 static uint32_t ims332_read_reg(int);
159 extern long ioasic_base
; /* XXX */
162 * Compose 2 bit/pixel cursor image.
163 * M M M M I I I I M I M I M I M I
164 * [ before ] [ after ]
165 * 3 2 1 0 3 2 1 0 3 3 2 2 1 1 0 0
166 * 7 6 5 4 7 6 5 4 7 7 6 6 5 5 4 4
168 static const uint8_t shuffle
[256] = {
169 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
170 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55,
171 0x02, 0x03, 0x06, 0x07, 0x12, 0x13, 0x16, 0x17,
172 0x42, 0x43, 0x46, 0x47, 0x52, 0x53, 0x56, 0x57,
173 0x08, 0x09, 0x0c, 0x0d, 0x18, 0x19, 0x1c, 0x1d,
174 0x48, 0x49, 0x4c, 0x4d, 0x58, 0x59, 0x5c, 0x5d,
175 0x0a, 0x0b, 0x0e, 0x0f, 0x1a, 0x1b, 0x1e, 0x1f,
176 0x4a, 0x4b, 0x4e, 0x4f, 0x5a, 0x5b, 0x5e, 0x5f,
177 0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35,
178 0x60, 0x61, 0x64, 0x65, 0x70, 0x71, 0x74, 0x75,
179 0x22, 0x23, 0x26, 0x27, 0x32, 0x33, 0x36, 0x37,
180 0x62, 0x63, 0x66, 0x67, 0x72, 0x73, 0x76, 0x77,
181 0x28, 0x29, 0x2c, 0x2d, 0x38, 0x39, 0x3c, 0x3d,
182 0x68, 0x69, 0x6c, 0x6d, 0x78, 0x79, 0x7c, 0x7d,
183 0x2a, 0x2b, 0x2e, 0x2f, 0x3a, 0x3b, 0x3e, 0x3f,
184 0x6a, 0x6b, 0x6e, 0x6f, 0x7a, 0x7b, 0x7e, 0x7f,
185 0x80, 0x81, 0x84, 0x85, 0x90, 0x91, 0x94, 0x95,
186 0xc0, 0xc1, 0xc4, 0xc5, 0xd0, 0xd1, 0xd4, 0xd5,
187 0x82, 0x83, 0x86, 0x87, 0x92, 0x93, 0x96, 0x97,
188 0xc2, 0xc3, 0xc6, 0xc7, 0xd2, 0xd3, 0xd6, 0xd7,
189 0x88, 0x89, 0x8c, 0x8d, 0x98, 0x99, 0x9c, 0x9d,
190 0xc8, 0xc9, 0xcc, 0xcd, 0xd8, 0xd9, 0xdc, 0xdd,
191 0x8a, 0x8b, 0x8e, 0x8f, 0x9a, 0x9b, 0x9e, 0x9f,
192 0xca, 0xcb, 0xce, 0xcf, 0xda, 0xdb, 0xde, 0xdf,
193 0xa0, 0xa1, 0xa4, 0xa5, 0xb0, 0xb1, 0xb4, 0xb5,
194 0xe0, 0xe1, 0xe4, 0xe5, 0xf0, 0xf1, 0xf4, 0xf5,
195 0xa2, 0xa3, 0xa6, 0xa7, 0xb2, 0xb3, 0xb6, 0xb7,
196 0xe2, 0xe3, 0xe6, 0xe7, 0xf2, 0xf3, 0xf6, 0xf7,
197 0xa8, 0xa9, 0xac, 0xad, 0xb8, 0xb9, 0xbc, 0xbd,
198 0xe8, 0xe9, 0xec, 0xed, 0xf8, 0xf9, 0xfc, 0xfd,
199 0xaa, 0xab, 0xae, 0xaf, 0xba, 0xbb, 0xbe, 0xbf,
200 0xea, 0xeb, 0xee, 0xef, 0xfa, 0xfb, 0xfe, 0xff,
204 xcfbmatch(device_t parent
, cfdata_t match
, void *aux
)
206 struct tc_attach_args
*ta
= aux
;
208 if (strncmp("PMAG-DV ", ta
->ta_modname
, TC_ROM_LLEN
) != 0)
215 xcfbattach(device_t parent
, device_t self
, void *aux
)
217 struct xcfb_softc
*sc
= device_private(self
);
218 struct tc_attach_args
*ta
= aux
;
219 struct rasops_info
*ri
;
220 struct wsemuldisplaydev_attach_args waa
;
223 console
= (ta
->ta_addr
== xcfb_consaddr
);
225 sc
->sc_ri
= ri
= &xcfb_console_ri
;
229 ri
= malloc(sizeof(struct rasops_info
), M_DEVBUF
, M_NOWAIT
);
231 printf(": can't alloc memory\n");
234 memset(ri
, 0, sizeof(struct rasops_info
));
236 ri
->ri_hw
= (void *)ioasic_base
;
237 xcfb_common_init(ri
);
240 printf(": %dx%d, %dbpp\n", ri
->ri_width
, ri
->ri_height
, ri
->ri_depth
);
244 sc
->sc_vaddr
= ta
->ta_addr
;
246 sc
->sc_csr
= IMS332_BPP_8
| IMS332_CSR_A_VTG_ENABLE
;
248 tc_intr_establish(parent
, ta
->ta_cookie
, IPL_TTY
, xcfbintr
, sc
);
250 waa
.console
= console
;
251 waa
.scrdata
= &xcfb_screenlist
;
252 waa
.accessops
= &xcfb_accessops
;
253 waa
.accesscookie
= sc
;
255 config_found(self
, &waa
, wsemuldisplaydevprint
);
259 xcfb_cmap_init(struct xcfb_softc
*sc
)
261 struct hwcmap256
*cm
;
267 for (index
= 0; index
< CMAP_SIZE
; index
++, p
+= 3) {
275 xcfb_common_init(struct rasops_info
*ri
)
279 /* initialize colormap and cursor hardware */
280 xcfbhwinit((void *)ri
->ri_hw
);
282 ri
->ri_flg
= RI_CENTER
;
286 ri
->ri_stride
= 1024;
287 ri
->ri_bits
= (void *)MIPS_PHYS_TO_KSEG1(XCFB_FB_BASE
);
289 /* clear the screen */
290 memset(ri
->ri_bits
, 0, ri
->ri_stride
* ri
->ri_height
);
293 /* prefer 12 pixel wide font */
294 cookie
= wsfont_find(NULL
, 12, 0, 0, WSDISPLAY_FONTORDER_L2R
,
295 WSDISPLAY_FONTORDER_L2R
);
297 cookie
= wsfont_find(NULL
, 0, 0, 0, WSDISPLAY_FONTORDER_L2R
,
298 WSDISPLAY_FONTORDER_L2R
);
300 printf("xcfb: font table is empty\n");
304 if (wsfont_lock(cookie
, &ri
->ri_font
)) {
305 printf("xcfb: couldn't lock font\n");
308 ri
->ri_wsfcookie
= cookie
;
310 rasops_init(ri
, 34, 80);
312 /* XXX shouldn't be global */
313 xcfb_stdscreen
.nrows
= ri
->ri_rows
;
314 xcfb_stdscreen
.ncols
= ri
->ri_cols
;
315 xcfb_stdscreen
.textops
= &ri
->ri_ops
;
316 xcfb_stdscreen
.capabilities
= ri
->ri_caps
;
322 struct rasops_info
*ri
;
325 ri
= &xcfb_console_ri
;
326 ri
->ri_hw
= (void *)ioasic_base
;
327 xcfb_common_init(ri
);
328 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
329 wsdisplay_cnattach(&xcfb_stdscreen
, ri
, 0, 0, defattr
);
330 xcfb_consaddr
= MIPS_PHYS_TO_KSEG1(XINE_PHYS_CFB_START
);
335 xcfbhwinit(void *base
)
337 volatile uint32_t *csr
;
341 csr
= (volatile uint32_t *)((char *)base
+ IOASIC_CSR
);
343 i
&= ~XINE_CSR_VDAC_ENABLE
;
346 i
|= XINE_CSR_VDAC_ENABLE
;
349 ims332_write_reg(IMS332_REG_BOOT
, 0x2c);
350 ims332_write_reg(IMS332_REG_CSR_A
,
351 IMS332_BPP_8
|IMS332_CSR_A_DISABLE_CURSOR
);
352 ims332_write_reg(IMS332_REG_HALF_SYNCH
, 0x10);
353 ims332_write_reg(IMS332_REG_BACK_PORCH
, 0x21);
354 ims332_write_reg(IMS332_REG_DISPLAY
, 0x100);
355 ims332_write_reg(IMS332_REG_SHORT_DIS
, 0x5d);
356 ims332_write_reg(IMS332_REG_BROAD_PULSE
, 0x9f);
357 ims332_write_reg(IMS332_REG_LINE_TIME
, 0x146);
358 ims332_write_reg(IMS332_REG_V_SYNC
, 0x0c);
359 ims332_write_reg(IMS332_REG_V_PRE_EQUALIZE
, 0x02);
360 ims332_write_reg(IMS332_REG_V_POST_EQUALIZE
, 0x02);
361 ims332_write_reg(IMS332_REG_V_BLANK
, 0x2a);
362 ims332_write_reg(IMS332_REG_V_DISPLAY
, 0x600);
363 ims332_write_reg(IMS332_REG_LINE_START
, 0x10);
364 ims332_write_reg(IMS332_REG_MEM_INIT
, 0x0a);
365 ims332_write_reg(IMS332_REG_COLOR_MASK
, 0xffffff);
366 ims332_write_reg(IMS332_REG_CSR_A
,
367 IMS332_BPP_8
|IMS332_CSR_A_VTG_ENABLE
);
369 /* build sane colormap */
371 for (i
= 0; i
< CMAP_SIZE
; i
++, p
+= 3) {
374 bgr
= p
[2] << 16 | p
[1] << 8 | p
[0];
375 ims332_write_reg(IMS332_REG_LUT_BASE
+ i
, bgr
);
378 /* clear out cursor image */
379 for (i
= 0; i
< 512; i
++)
380 ims332_write_reg(IMS332_REG_CURSOR_RAM
+ i
, 0);
383 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
384 * cursor image. LUT_1 for mask color, while LUT_2 for
385 * image color. LUT_0 will be never used.
387 ims332_write_reg(IMS332_REG_CURSOR_LUT_0
, 0);
388 ims332_write_reg(IMS332_REG_CURSOR_LUT_1
, 0xffffff);
389 ims332_write_reg(IMS332_REG_CURSOR_LUT_2
, 0xffffff);
393 xcfbioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
395 struct xcfb_softc
*sc
= v
;
396 struct rasops_info
*ri
= sc
->sc_ri
;
400 case WSDISPLAYIO_GTYPE
:
401 *(u_int
*)data
= WSDISPLAY_TYPE_XCFB
;
404 case WSDISPLAYIO_GINFO
:
405 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
406 wsd_fbip
->height
= ri
->ri_height
;
407 wsd_fbip
->width
= ri
->ri_width
;
408 wsd_fbip
->depth
= ri
->ri_depth
;
409 wsd_fbip
->cmsize
= CMAP_SIZE
;
413 case WSDISPLAYIO_GETCMAP
:
414 return get_cmap(sc
, (struct wsdisplay_cmap
*)data
);
416 case WSDISPLAYIO_PUTCMAP
:
417 error
= set_cmap(sc
, (struct wsdisplay_cmap
*)data
);
419 ims332_loadcmap(&sc
->sc_cmap
);
422 case WSDISPLAYIO_SVIDEO
:
423 turnoff
= *(int *)data
== WSDISPLAYIO_VIDEO_OFF
;
424 if (sc
->sc_blanked
!= turnoff
) {
425 sc
->sc_blanked
= turnoff
;
426 xcfb_screenblank(sc
);
430 case WSDISPLAYIO_GVIDEO
:
431 *(u_int
*)data
= sc
->sc_blanked
?
432 WSDISPLAYIO_VIDEO_OFF
: WSDISPLAYIO_VIDEO_ON
;
435 case WSDISPLAYIO_GCURPOS
:
436 *(struct wsdisplay_curpos
*)data
= sc
->sc_cursor
.cc_pos
;
439 case WSDISPLAYIO_SCURPOS
:
440 set_curpos(sc
, (struct wsdisplay_curpos
*)data
);
441 ims332_set_curpos(sc
);
444 case WSDISPLAYIO_GCURMAX
:
445 ((struct wsdisplay_curpos
*)data
)->x
=
446 ((struct wsdisplay_curpos
*)data
)->y
= CURSOR_MAX_SIZE
;
449 case WSDISPLAYIO_GCURSOR
:
450 return get_cursor(sc
, (struct wsdisplay_cursor
*)data
);
452 case WSDISPLAYIO_SCURSOR
:
453 return set_cursor(sc
, (struct wsdisplay_cursor
*)data
);
455 case WSDISPLAYIO_SMODE
:
456 if (*(int *)data
== WSDISPLAYIO_MODE_EMUL
) {
457 sc
->sc_csr
|= IMS332_CSR_A_DISABLE_CURSOR
;
458 ims332_write_reg(IMS332_REG_CSR_A
, sc
->sc_csr
);
460 ims332_loadcmap(&sc
->sc_cmap
);
462 xcfb_screenblank(sc
);
466 return (EPASSTHROUGH
);
470 xcfbmmap(void *v
, void *vs
, off_t offset
, int prot
)
473 if (offset
>= XCFB_FB_SIZE
|| offset
< 0)
475 return mips_btop(MIPS_KSEG1_TO_PHYS(XCFB_FB_BASE
+ offset
));
479 xcfb_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
,
480 int *curxp
, int *curyp
, long *attrp
)
482 struct xcfb_softc
*sc
= v
;
483 struct rasops_info
*ri
= sc
->sc_ri
;
486 if (sc
->nscreens
> 0)
489 *cookiep
= ri
; /* one and only for now */
492 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
499 xcfb_free_screen(void *v
, void *cookie
)
501 struct xcfb_softc
*sc
= v
;
503 if (sc
->sc_ri
== &xcfb_console_ri
)
504 panic("xcfb_free_screen: console");
510 xcfb_show_screen(void *v
, void *cookie
, int waitok
,
511 void (*cb
)(void *, int, int), void *cbarg
)
520 struct xcfb_softc
*sc
= v
;
523 intr
= (uint32_t *)((char *)sc
->sc_ri
->ri_hw
+ IOASIC_INTR
);
525 i
&= ~XINE_INTR_VINT
;
531 xcfb_screenblank(struct xcfb_softc
*sc
)
534 sc
->sc_csr
|= IMS332_CSR_A_FORCE_BLANK
;
536 sc
->sc_csr
&= ~IMS332_CSR_A_FORCE_BLANK
;
537 ims332_write_reg(IMS332_REG_CSR_A
, sc
->sc_csr
);
541 get_cmap(struct xcfb_softc
*sc
, struct wsdisplay_cmap
*p
)
543 u_int index
= p
->index
, count
= p
->count
;
546 if (index
>= CMAP_SIZE
|| count
> CMAP_SIZE
- index
)
549 error
= copyout(&sc
->sc_cmap
.r
[index
], p
->red
, count
);
552 error
= copyout(&sc
->sc_cmap
.g
[index
], p
->green
, count
);
555 error
= copyout(&sc
->sc_cmap
.b
[index
], p
->blue
, count
);
560 set_cmap(struct xcfb_softc
*sc
, struct wsdisplay_cmap
*p
)
562 struct hwcmap256 cmap
;
563 u_int index
= p
->index
, count
= p
->count
;
566 if (index
>= CMAP_SIZE
|| count
> CMAP_SIZE
- index
)
569 error
= copyin(p
->red
, &cmap
.r
[index
], count
);
572 error
= copyin(p
->green
, &cmap
.g
[index
], count
);
575 error
= copyin(p
->blue
, &cmap
.b
[index
], count
);
578 memcpy(&sc
->sc_cmap
.r
[index
], &cmap
.r
[index
], count
);
579 memcpy(&sc
->sc_cmap
.g
[index
], &cmap
.g
[index
], count
);
580 memcpy(&sc
->sc_cmap
.b
[index
], &cmap
.b
[index
], count
);
585 set_cursor(struct xcfb_softc
*sc
, struct wsdisplay_cursor
*p
)
587 #define cc (&sc->sc_cursor)
588 u_int v
, index
= 0, count
= 0, icount
= 0;
589 uint8_t r
[2], g
[2], b
[2], image
[512], mask
[512];
593 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
594 index
= p
->cmap
.index
;
595 count
= p
->cmap
.count
;
597 if (index
>= 2 || index
+ count
> 2)
599 error
= copyin(p
->cmap
.red
, &r
[index
], count
);
602 error
= copyin(p
->cmap
.green
, &g
[index
], count
);
605 error
= copyin(p
->cmap
.blue
, &b
[index
], count
);
609 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
610 if (p
->size
.x
> CURSOR_MAX_SIZE
|| p
->size
.y
> CURSOR_MAX_SIZE
)
612 icount
= ((p
->size
.x
< 33) ? 4 : 8) * p
->size
.y
;
613 error
= copyin(p
->image
, image
, icount
);
616 error
= copyin(p
->mask
, mask
, icount
);
621 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
622 memcpy(&cc
->cc_color
[index
], &r
[index
], count
);
623 memcpy(&cc
->cc_color
[index
+ 2], &g
[index
], count
);
624 memcpy(&cc
->cc_color
[index
+ 4], &b
[index
], count
);
625 ims332_load_curcmap(sc
);
627 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
628 cc
->cc_size
= p
->size
;
629 memset(cc
->cc_image
, 0, sizeof cc
->cc_image
);
630 memcpy(cc
->cc_image
, image
, icount
);
631 memset(cc
->cc_mask
, 0, sizeof cc
->cc_mask
);
632 memcpy(cc
->cc_mask
, mask
, icount
);
633 ims332_load_curshape(sc
);
635 if (v
& WSDISPLAY_CURSOR_DOCUR
) {
638 sc
->sc_csr
&= ~IMS332_CSR_A_DISABLE_CURSOR
;
640 sc
->sc_csr
|= IMS332_CSR_A_DISABLE_CURSOR
;
641 ims332_write_reg(IMS332_REG_CSR_A
, sc
->sc_csr
);
643 if (v
& WSDISPLAY_CURSOR_DOPOS
) {
644 set_curpos(sc
, &p
->pos
);
645 ims332_set_curpos(sc
);
653 get_cursor(struct xcfb_softc
*sc
, struct wsdisplay_cursor
*p
)
655 return (EPASSTHROUGH
); /* XXX */
659 set_curpos(struct xcfb_softc
*sc
, struct wsdisplay_curpos
*curpos
)
661 struct rasops_info
*ri
= sc
->sc_ri
;
662 int x
= curpos
->x
, y
= curpos
->y
;
666 else if (y
> ri
->ri_height
)
670 else if (x
> ri
->ri_width
)
672 sc
->sc_cursor
.cc_pos
.x
= x
;
673 sc
->sc_cursor
.cc_pos
.y
= y
;
677 ims332_loadcmap(struct hwcmap256
*cm
)
682 for (i
= 0; i
< CMAP_SIZE
; i
++) {
683 rgb
= cm
->b
[i
] << 16 | cm
->g
[i
] << 8 | cm
->r
[i
];
684 ims332_write_reg(IMS332_REG_LUT_BASE
+ i
, rgb
);
689 ims332_set_curpos(struct xcfb_softc
*sc
)
691 struct wsdisplay_curpos
*curpos
= &sc
->sc_cursor
.cc_pos
;
696 pos
= (curpos
->x
& 0xfff) << 12 | (curpos
->y
& 0xfff);
697 ims332_write_reg(IMS332_REG_CURSOR_LOC
, pos
);
702 ims332_load_curcmap(struct xcfb_softc
*sc
)
704 uint8_t *cp
= sc
->sc_cursor
.cc_color
;
707 /* cursor background */
708 rgb
= cp
[5] << 16 | cp
[3] << 8 | cp
[1];
709 ims332_write_reg(IMS332_REG_CURSOR_LUT_1
, rgb
);
711 /* cursor foreground */
712 rgb
= cp
[4] << 16 | cp
[2] << 8 | cp
[0];
713 ims332_write_reg(IMS332_REG_CURSOR_LUT_2
, rgb
);
717 ims332_load_curshape(struct xcfb_softc
*sc
)
719 u_int i
, img
, msk
, bits
;
722 ip
= (uint8_t *)sc
->sc_cursor
.cc_image
;
723 mp
= (uint8_t *)sc
->sc_cursor
.cc_mask
;
726 /* 64 pixel scan line is consisted with 8 halfword cursor ram */
727 while (i
< sc
->sc_cursor
.cc_size
.y
* 8) {
728 /* pad right half 32 pixel when smaller than 33 */
729 if ((i
& 0x4) && sc
->sc_cursor
.cc_size
.x
< 33)
734 img
&= msk
; /* cookie off image */
735 u
= (msk
& 0x0f) << 4 | (img
& 0x0f);
737 u
= (msk
& 0xf0) | (img
& 0xf0) >> 4;
738 bits
= (shuffle
[u
] << 8) | bits
;
740 ims332_write_reg(IMS332_REG_CURSOR_RAM
+ i
, bits
);
743 /* pad unoccupied scan lines */
744 while (i
< CURSOR_MAX_SIZE
* 8) {
745 ims332_write_reg(IMS332_REG_CURSOR_RAM
+ i
, 0);
751 ims332_write_reg(int regno
, uint32_t val
)
753 void *high8
= (void *)(ioasic_base
+ IMS332_HIGH
);
754 void *low16
= (void *)(ioasic_base
+ IMS332_WLOW
+ (regno
<< 4));
756 *(volatile uint16_t *)high8
= (val
& 0xff0000) >> 8;
757 *(volatile uint16_t *)low16
= val
;
762 ims332_read_reg(int regno
)
764 void *high8
= (void *)(ioasic_base
+ IMS332_HIGH
);
765 void *low16
= (void *)(ioasic_base
+ IMS332_RLOW
) + (regno
<< 4);
768 v1
= *(volatile uint16_t *)high8
;
769 v0
= *(volatile uint16_t *)low16
;
770 return (v1
& 0xff00) << 8 | v0
;