1 /* $NetBSD: p9100.c,v 1.50 2009/09/19 11:58:06 tsutsui Exp $ */
4 * Copyright (c) 1998, 2005, 2006 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.
33 * color display (p9100) driver.
35 * Does not handle interrupts, even though they can occur.
37 * XXX should defer colormap updates to vertical retrace interrupts
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.50 2009/09/19 11:58:06 tsutsui Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/ioctl.h>
48 #include <sys/malloc.h>
54 #include <machine/autoconf.h>
56 #include <dev/sun/fbio.h>
57 #include <dev/sun/fbvar.h>
58 #include <dev/sun/btreg.h>
59 #include <dev/sun/btvar.h>
61 #include <dev/sbus/p9100reg.h>
63 #include <dev/sbus/sbusvar.h>
65 #include <dev/wscons/wsdisplayvar.h>
66 #include <dev/wscons/wsconsio.h>
67 #include <dev/wsfont/wsfont.h>
68 #include <dev/rasops/rasops.h>
70 #include <dev/wscons/wsdisplay_vconsvar.h>
72 #include "opt_wsemul.h"
73 #include "rasops_glue.h"
74 #include "opt_pnozz.h"
80 #include <machine/tctrl.h>
81 #include <sparc/dev/tctrlvar.h> /*XXX*/
85 #define DPRINTF aprint_normal
87 #define DPRINTF while (0) aprint_normal
91 short pc_enable
; /* cursor is enabled */
92 struct fbcurpos pc_pos
; /* position */
93 struct fbcurpos pc_hot
; /* hot-spot */
94 struct fbcurpos pc_size
; /* size of mask & image fields */
95 uint32_t pc_bits
[0x100]; /* space for mask & image bits */
96 unsigned char red
[3], green
[3];
97 unsigned char blue
[3]; /* cursor palette */
100 /* per-display variables */
102 device_t sc_dev
; /* base device */
103 struct fbdevice sc_fb
; /* frame buffer device */
105 bus_space_tag_t sc_bustag
;
107 bus_addr_t sc_ctl_paddr
; /* phys address description */
108 bus_size_t sc_ctl_psize
; /* for device mmap() */
109 bus_space_handle_t sc_ctl_memh
; /* bus space handle */
111 bus_addr_t sc_fb_paddr
; /* phys address description */
112 bus_size_t sc_fb_psize
; /* for device mmap() */
113 bus_space_handle_t sc_fb_memh
; /* bus space handle */
115 volatile uint32_t sc_junk
;
116 uint32_t sc_mono_width
; /* for setup_mono */
119 uint32_t sc_height
; /* panel width / height */
122 int sc_depthshift
; /* blitter works on bytes not pixels */
124 union bt_cmap sc_cmap
; /* Brooktree color map */
126 struct pnozz_cursor sc_cursor
;
129 int sc_video
, sc_powerstate
;
131 volatile uint32_t sc_last_offset
;
132 struct vcons_data vd
;
133 uint8_t sc_dac_power
;
137 static struct vcons_screen p9100_console_screen
;
139 extern const u_char rasops_cmap
[768];
141 struct wsscreen_descr p9100_defscreendesc
= {
149 const struct wsscreen_descr
*_p9100_scrlist
[] = {
150 &p9100_defscreendesc
,
151 /* XXX other formats, graphics screen? */
154 struct wsscreen_list p9100_screenlist
= {
155 sizeof(_p9100_scrlist
) / sizeof(struct wsscreen_descr
*),
159 /* autoconfiguration driver */
160 static int p9100_sbus_match(device_t
, cfdata_t
, void *);
161 static void p9100_sbus_attach(device_t
, device_t
, void *);
163 static void p9100unblank(device_t
);
165 CFATTACH_DECL_NEW(pnozz
, sizeof(struct p9100_softc
),
166 p9100_sbus_match
, p9100_sbus_attach
, NULL
, NULL
);
168 static dev_type_open(p9100open
);
169 static dev_type_ioctl(p9100ioctl
);
170 static dev_type_mmap(p9100mmap
);
172 const struct cdevsw pnozz_cdevsw
= {
173 p9100open
, nullclose
, noread
, nowrite
, p9100ioctl
,
174 nostop
, notty
, nopoll
, p9100mmap
, nokqfilter
,
177 /* frame buffer generic driver */
178 static struct fbdriver p9100fbdriver
= {
179 p9100unblank
, p9100open
, nullclose
, p9100ioctl
, nopoll
,
180 p9100mmap
, nokqfilter
183 static void p9100loadcmap(struct p9100_softc
*, int, int);
184 static void p9100_set_video(struct p9100_softc
*, int);
185 static int p9100_get_video(struct p9100_softc
*);
186 static uint32_t p9100_ctl_read_4(struct p9100_softc
*, bus_size_t
);
187 static void p9100_ctl_write_4(struct p9100_softc
*, bus_size_t
, uint32_t);
188 static uint8_t p9100_ramdac_read(struct p9100_softc
*, bus_size_t
);
189 static void p9100_ramdac_write(struct p9100_softc
*, bus_size_t
, uint8_t);
191 static uint8_t p9100_ramdac_read_ctl(struct p9100_softc
*, int);
192 static void p9100_ramdac_write_ctl(struct p9100_softc
*, int, uint8_t);
194 static void p9100_init_engine(struct p9100_softc
*);
195 static int p9100_set_depth(struct p9100_softc
*, int);
198 static void p9100_sync(struct p9100_softc
*);
199 static void p9100_bitblt(void *, int, int, int, int, int, int, uint32_t);
200 static void p9100_rectfill(void *, int, int, int, int, uint32_t);
201 static void p9100_clearscreen(struct p9100_softc
*);
203 static void p9100_setup_mono(struct p9100_softc
*, int, int, int, int,
205 static void p9100_feed_line(struct p9100_softc
*, int, uint8_t *);
206 static void p9100_set_color_reg(struct p9100_softc
*, int, int32_t);
208 static void p9100_copycols(void *, int, int, int, int);
209 static void p9100_erasecols(void *, int, int, int, long);
210 static void p9100_copyrows(void *, int, int, int);
211 static void p9100_eraserows(void *, int, int, long);
212 /*static int p9100_mapchar(void *, int, u_int *);*/
213 static void p9100_putchar(void *, int, int, u_int
, long);
214 static void p9100_cursor(void *, int, int, int);
215 static int p9100_allocattr(void *, int, int, int, long *);
217 static int p9100_putcmap(struct p9100_softc
*, struct wsdisplay_cmap
*);
218 static int p9100_getcmap(struct p9100_softc
*, struct wsdisplay_cmap
*);
219 static int p9100_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
220 static paddr_t
p9100_mmap(void *, void *, off_t
, int);
222 /*static int p9100_load_font(void *, void *, struct wsdisplay_font *);*/
224 static void p9100_init_screen(void *, struct vcons_screen
*, int,
228 static void p9100_init_cursor(struct p9100_softc
*);
230 static void p9100_set_fbcursor(struct p9100_softc
*);
231 static void p9100_setcursorcmap(struct p9100_softc
*);
232 static void p9100_loadcursor(struct p9100_softc
*);
235 static int p9100_intr(void *);
238 /* power management stuff */
239 static bool p9100_suspend(device_t
, pmf_qual_t
);
240 static bool p9100_resume(device_t
, pmf_qual_t
);
243 static void p9100_set_extvga(void *, int);
247 struct wsdisplay_accessops p9100_accessops
= {
250 NULL
, /* vcons_alloc_screen */
251 NULL
, /* vcons_free_screen */
252 NULL
, /* vcons_show_screen */
253 NULL
, /* load_font */
259 #define PNOZZ_LATCH(sc, off) if(sc->sc_last_offset == (off & 0xffffff80)) { \
260 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, \
262 sc->sc_last_offset = off & 0xffffff80; }
268 p9100_sbus_match(device_t parent
, cfdata_t cf
, void *aux
)
270 struct sbus_attach_args
*sa
= aux
;
272 if (strcmp("p9100", sa
->sa_name
) == 0)
279 * Attach a display. We need to notice if it is the console, too.
282 p9100_sbus_attach(device_t parent
, device_t self
, void *args
)
284 struct p9100_softc
*sc
= device_private(self
);
285 struct sbus_attach_args
*sa
= args
;
286 struct fbdevice
*fb
= &sc
->sc_fb
;
288 int node
= sa
->sa_node
;
293 struct wsemuldisplaydev_attach_args aa
;
294 struct rasops_info
*ri
;
295 unsigned long defattr
;
298 sc
->sc_last_offset
= 0xffffffff;
302 * When the ROM has mapped in a p9100 display, the address
303 * maps only the video RAM, so in any case we have to map the
304 * registers ourselves.
307 if (sa
->sa_npromvaddrs
!= 0)
308 fb
->fb_pixels
= (void *)sa
->sa_promvaddrs
[0];
310 /* Remember cookies for p9100_mmap() */
311 sc
->sc_bustag
= sa
->sa_bustag
;
313 sc
->sc_ctl_paddr
= sbus_bus_addr(sa
->sa_bustag
,
314 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
);
315 sc
->sc_ctl_psize
= 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/
317 sc
->sc_fb_paddr
= sbus_bus_addr(sa
->sa_bustag
,
318 sa
->sa_reg
[2].oa_space
, sa
->sa_reg
[2].oa_base
);
319 sc
->sc_fb_psize
= (bus_size_t
)sa
->sa_reg
[2].oa_size
;
321 if (sbus_bus_map(sc
->sc_bustag
,
322 sa
->sa_reg
[0].oa_space
,
323 sa
->sa_reg
[0].oa_base
,
325 * XXX for some reason the SBus resources don't cover
326 * all registers, so we just map what we need
329 0, &sc
->sc_ctl_memh
) != 0) {
330 printf("%s: cannot map control registers\n",
336 * we need to map the framebuffer even though we never write to it,
337 * thanks to some weirdness in the SPARCbook's SBus glue for the
338 * P9100 - all register accesses need to be 'latched in' whenever we
339 * go to another 0x80 aligned 'page' by reading the framebuffer at the
342 if (fb
->fb_pixels
== NULL
) {
343 if (sbus_bus_map(sc
->sc_bustag
,
344 sa
->sa_reg
[2].oa_space
,
345 sa
->sa_reg
[2].oa_base
,
347 BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
,
348 &sc
->sc_fb_memh
) != 0) {
349 printf("%s: cannot map framebuffer\n",
353 fb
->fb_pixels
= (char *)sc
->sc_fb_memh
;
355 sc
->sc_fb_memh
= (bus_space_handle_t
) fb
->fb_pixels
;
357 sc
->sc_width
= prom_getpropint(node
, "width", 800);
358 sc
->sc_height
= prom_getpropint(node
, "height", 600);
359 sc
->sc_depth
= prom_getpropint(node
, "depth", 8) >> 3;
361 sc
->sc_stride
= prom_getpropint(node
, "linebytes",
362 sc
->sc_width
* sc
->sc_depth
);
364 fb
->fb_driver
= &p9100fbdriver
;
365 fb
->fb_device
= sc
->sc_dev
;
366 fb
->fb_flags
= device_cfdata(sc
->sc_dev
)->cf_flags
& FB_USERMASK
;
367 #ifdef PNOZZ_EMUL_CG3
368 fb
->fb_type
.fb_type
= FBTYPE_SUN3COLOR
;
370 fb
->fb_type
.fb_type
= FBTYPE_P9100
;
372 fb
->fb_pixels
= NULL
;
374 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
376 isconsole
= fb_is_console(node
);
380 aprint_error_dev(self
, "fatal error: PROM didn't configure device\n");
385 fb
->fb_type
.fb_depth
= 8;
387 sc
->sc_depthshift
= 0;
389 /* check the RAMDAC */
390 ver
= p9100_ramdac_read_ctl(sc
, DAC_VERSION
);
392 p9100_init_engine(sc
);
393 p9100_set_depth(sc
, 8);
395 fb_setsize_obp(fb
, fb
->fb_type
.fb_depth
, sc
->sc_width
, sc
->sc_height
,
399 bus_intr_establish(sc
->sc_bustag
, sa
->sa_pri
, IPL_BIO
,
403 fb
->fb_type
.fb_cmsize
= prom_getpropint(node
, "cmsize", 256);
404 if ((1 << fb
->fb_type
.fb_depth
) != fb
->fb_type
.fb_cmsize
)
405 printf(", %d entry colormap", fb
->fb_type
.fb_cmsize
);
407 /* Initialize the default color map. */
409 for (i
= 0; i
< 256; i
++) {
410 sc
->sc_cmap
.cm_map
[i
][0] = rasops_cmap
[j
];
412 sc
->sc_cmap
.cm_map
[i
][1] = rasops_cmap
[j
];
414 sc
->sc_cmap
.cm_map
[i
][2] = rasops_cmap
[j
];
417 p9100loadcmap(sc
, 0, 256);
419 /* make sure we are not blanked */
421 p9100_set_video(sc
, 1);
423 /* register with power management */
425 sc
->sc_powerstate
= PWR_RESUME
;
426 if (!pmf_device_register(self
, p9100_suspend
, p9100_resume
)) {
427 panic("%s: could not register with PMF",
428 device_xname(sc
->sc_dev
));
432 printf(" (console)\n");
434 /*p9100loadcmap(sc, 255, 1);*/
443 vcons_init(&sc
->vd
, sc
, &p9100_defscreendesc
, &p9100_accessops
);
444 sc
->vd
.init_screen
= p9100_init_screen
;
446 vcons_init_screen(&sc
->vd
, &p9100_console_screen
, 1, &defattr
);
447 p9100_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
449 sc
->sc_bg
= (defattr
>> 16) & 0xff;
450 p9100_clearscreen(sc
);
452 ri
= &p9100_console_screen
.scr_ri
;
454 p9100_defscreendesc
.nrows
= ri
->ri_rows
;
455 p9100_defscreendesc
.ncols
= ri
->ri_cols
;
456 p9100_defscreendesc
.textops
= &ri
->ri_ops
;
457 p9100_defscreendesc
.capabilities
= ri
->ri_caps
;
460 wsdisplay_cnattach(&p9100_defscreendesc
, ri
, 0, 0, defattr
);
461 vcons_replay_msgbuf(&p9100_console_screen
);
464 aa
.console
= isconsole
;
465 aa
.scrdata
= &p9100_screenlist
;
466 aa
.accessops
= &p9100_accessops
;
467 aa
.accesscookie
= &sc
->vd
;
469 config_found(self
, &aa
, wsemuldisplaydevprint
);
471 fb
->fb_type
.fb_size
= fb
->fb_type
.fb_height
* fb
->fb_linebytes
;
472 printf("%s: rev %d / %x, %dx%d, depth %d mem %x\n",
474 (i
& 7), ver
, fb
->fb_type
.fb_width
, fb
->fb_type
.fb_height
,
475 fb
->fb_type
.fb_depth
, (unsigned int)sc
->sc_fb_psize
);
476 /* cursor sprite handling */
477 p9100_init_cursor(sc
);
480 fb_attach(fb
, isconsole
);
483 /* register callback for external monitor status change */
484 tadpole_register_callback(p9100_set_extvga
, sc
);
489 p9100open(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
491 int unit
= minor(dev
);
493 if (device_lookup(&pnozz_cd
, unit
) == NULL
)
499 p9100ioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
501 struct p9100_softc
*sc
= device_lookup_private(&pnozz_cd
, minor(dev
));
508 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
512 fba
= (struct fbgattr
*)data
;
513 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
514 fba
->owner
= 0; /* XXX ??? */
515 fba
->fbtype
= sc
->sc_fb
.fb_type
;
516 fba
->sattr
.flags
= 0;
517 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
518 fba
->sattr
.dev_specific
[0] = -1;
519 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
520 fba
->emu_types
[1] = -1;
524 #define p ((struct fbcmap *)data)
525 return (bt_getcmap(p
, &sc
->sc_cmap
, 256, 1));
528 /* copy to software map */
529 error
= bt_putcmap(p
, &sc
->sc_cmap
, 256, 1);
532 /* now blast them into the chip */
533 /* XXX should use retrace interrupt */
534 p9100loadcmap(sc
, p
->index
, p
->count
);
539 *(int *)data
= p9100_get_video(sc
);
543 p9100_set_video(sc
, *(int *)data
);
546 /* these are for both FBIOSCURSOR and FBIOGCURSOR */
547 #define p ((struct fbcursor *)data)
548 #define pc (&sc->sc_cursor)
551 p
->set
= FB_CUR_SETALL
; /* close enough, anyway */
552 p
->enable
= pc
->pc_enable
;
555 p
->size
= pc
->pc_size
;
557 if (p
->image
!= NULL
) {
558 error
= copyout(pc
->pc_bits
, p
->image
, 0x200);
561 error
= copyout(&pc
->pc_bits
[0x80], p
->mask
, 0x200);
568 if (p
->cmap
.red
!= NULL
) {
569 copyout(pc
->red
, p
->cmap
.red
, 3);
570 copyout(pc
->green
, p
->cmap
.green
, 3);
571 copyout(pc
->blue
, p
->cmap
.blue
, 3);
578 uint32_t image
[0x80], mask
[0x80];
579 uint8_t red
[3], green
[3], blue
[3];
582 if (v
& FB_CUR_SETCMAP
) {
583 error
= copyin(p
->cmap
.red
, red
, 3);
584 error
|= copyin(p
->cmap
.green
, green
, 3);
585 error
|= copyin(p
->cmap
.blue
, blue
, 3);
589 if (v
& FB_CUR_SETSHAPE
) {
590 if (p
->size
.x
> 64 || p
->size
.y
> 64)
592 memset(&mask
, 0, 0x200);
593 memset(&image
, 0, 0x200);
594 count
= p
->size
.y
* 8;
595 error
= copyin(p
->image
, image
, count
);
598 error
= copyin(p
->mask
, mask
, count
);
603 /* parameters are OK; do it */
604 if (v
& (FB_CUR_SETCUR
| FB_CUR_SETPOS
| FB_CUR_SETHOT
)) {
605 if (v
& FB_CUR_SETCUR
)
606 pc
->pc_enable
= p
->enable
;
607 if (v
& FB_CUR_SETPOS
)
609 if (v
& FB_CUR_SETHOT
)
611 p9100_set_fbcursor(sc
);
614 if (v
& FB_CUR_SETCMAP
) {
615 memcpy(pc
->red
, red
, 3);
616 memcpy(pc
->green
, green
, 3);
617 memcpy(pc
->blue
, blue
, 3);
618 p9100_setcursorcmap(sc
);
621 if (v
& FB_CUR_SETSHAPE
) {
622 memcpy(pc
->pc_bits
, image
, 0x200);
623 memcpy(&pc
->pc_bits
[0x80], mask
, 0x200);
624 p9100_loadcursor(sc
);
633 *(struct fbcurpos
*)data
= sc
->sc_cursor
.pc_pos
;
637 sc
->sc_cursor
.pc_pos
= *(struct fbcurpos
*)data
;
638 p9100_set_fbcursor(sc
);
642 /* max cursor size is 64x64 */
643 ((struct fbcurpos
*)data
)->x
= 64;
644 ((struct fbcurpos
*)data
)->y
= 64;
654 p9100_ctl_read_4(struct p9100_softc
*sc
, bus_size_t off
)
657 PNOZZ_LATCH(sc
, off
);
658 return bus_space_read_4(sc
->sc_bustag
, sc
->sc_ctl_memh
, off
);
662 p9100_ctl_write_4(struct p9100_softc
*sc
, bus_size_t off
, uint32_t v
)
665 PNOZZ_LATCH(sc
, off
);
666 bus_space_write_4(sc
->sc_bustag
, sc
->sc_ctl_memh
, off
, v
);
669 /* initialize the drawing engine */
671 p9100_init_engine(struct p9100_softc
*sc
)
673 /* reset clipping rectangles */
674 uint32_t rmax
= ((sc
->sc_width
& 0x3fff) << 16) |
675 (sc
->sc_height
& 0x3fff);
677 sc
->sc_last_offset
= 0xffffffff;
679 p9100_ctl_write_4(sc
, WINDOW_OFFSET
, 0);
680 p9100_ctl_write_4(sc
, WINDOW_MIN
, 0);
681 p9100_ctl_write_4(sc
, WINDOW_MAX
, rmax
);
682 p9100_ctl_write_4(sc
, BYTE_CLIP_MIN
, 0);
683 p9100_ctl_write_4(sc
, BYTE_CLIP_MAX
, rmax
);
684 p9100_ctl_write_4(sc
, DRAW_MODE
, 0);
685 p9100_ctl_write_4(sc
, PLANE_MASK
, 0xffffffff);
686 p9100_ctl_write_4(sc
, PATTERN0
, 0xffffffff);
687 p9100_ctl_write_4(sc
, PATTERN1
, 0xffffffff);
688 p9100_ctl_write_4(sc
, PATTERN2
, 0xffffffff);
689 p9100_ctl_write_4(sc
, PATTERN3
, 0xffffffff);
693 /* we only need these in the wsdisplay case */
696 /* wait until the engine is idle */
698 p9100_sync(struct p9100_softc
*sc
)
700 while((p9100_ctl_read_4(sc
, ENGINE_STATUS
) &
701 (ENGINE_BUSY
| BLITTER_BUSY
)) != 0);
705 p9100_set_color_reg(struct p9100_softc
*sc
, int reg
, int32_t col
)
712 out
= (col
<< 8) | col
;
716 out
= col
| (col
<< 16);
721 p9100_ctl_write_4(sc
, reg
, out
);
724 /* screen-to-screen blit */
726 p9100_bitblt(void *cookie
, int xs
, int ys
, int xd
, int yd
, int wi
,
727 int he
, uint32_t rop
)
729 struct p9100_softc
*sc
= cookie
;
730 uint32_t src
, dst
, srcw
, dstw
;
732 sc
->sc_last_offset
= 0xffffffff;
734 src
= ((xs
& 0x3fff) << 16) | (ys
& 0x3fff);
735 dst
= ((xd
& 0x3fff) << 16) | (yd
& 0x3fff);
736 srcw
= (((xs
+ wi
- 1) & 0x3fff) << 16) | ((ys
+ he
- 1) & 0x3fff);
737 dstw
= (((xd
+ wi
- 1) & 0x3fff) << 16) | ((yd
+ he
- 1) & 0x3fff);
741 p9100_ctl_write_4(sc
, RASTER_OP
, rop
);
743 p9100_ctl_write_4(sc
, ABS_XY0
, src
<< sc
->sc_depthshift
);
744 p9100_ctl_write_4(sc
, ABS_XY1
, srcw
<< sc
->sc_depthshift
);
745 p9100_ctl_write_4(sc
, ABS_XY2
, dst
<< sc
->sc_depthshift
);
746 p9100_ctl_write_4(sc
, ABS_XY3
, dstw
<< sc
->sc_depthshift
);
748 sc
->sc_junk
= p9100_ctl_read_4(sc
, COMMAND_BLIT
);
751 /* solid rectangle fill */
753 p9100_rectfill(void *cookie
, int xs
, int ys
, int wi
, int he
, uint32_t col
)
755 struct p9100_softc
*sc
= cookie
;
758 sc
->sc_last_offset
= 0xffffffff;
760 src
= ((xs
& 0x3fff) << 16) | (ys
& 0x3fff);
761 srcw
= (((xs
+ wi
) & 0x3fff) << 16) | ((ys
+ he
) & 0x3fff);
763 p9100_set_color_reg(sc
, FOREGROUND_COLOR
, col
);
764 p9100_set_color_reg(sc
, BACKGROUND_COLOR
, col
);
765 p9100_ctl_write_4(sc
, RASTER_OP
, ROP_PAT
);
766 p9100_ctl_write_4(sc
, COORD_INDEX
, 0);
767 p9100_ctl_write_4(sc
, RECT_RTW_XY
, src
);
768 p9100_ctl_write_4(sc
, RECT_RTW_XY
, srcw
);
769 sc
->sc_junk
= p9100_ctl_read_4(sc
, COMMAND_QUAD
);
772 /* setup for mono->colour expansion */
774 p9100_setup_mono(struct p9100_softc
*sc
, int x
, int y
, int wi
, int he
,
775 uint32_t fg
, uint32_t bg
)
778 sc
->sc_last_offset
= 0xffffffff;
782 * this doesn't make any sense to me either, but for some reason the
783 * chip applies the foreground colour to 0 pixels
786 p9100_set_color_reg(sc
,FOREGROUND_COLOR
,bg
);
787 p9100_set_color_reg(sc
,BACKGROUND_COLOR
,fg
);
789 p9100_ctl_write_4(sc
, RASTER_OP
, ROP_SRC
);
790 p9100_ctl_write_4(sc
, ABS_X0
, x
);
791 p9100_ctl_write_4(sc
, ABS_XY1
, (x
<< 16) | (y
& 0xFFFFL
));
792 p9100_ctl_write_4(sc
, ABS_X2
, (x
+ wi
));
793 p9100_ctl_write_4(sc
, ABS_Y3
, he
);
794 /* now feed the data into the chip */
795 sc
->sc_mono_width
= wi
;
798 /* write monochrome data to the screen through the blitter */
800 p9100_feed_line(struct p9100_softc
*sc
, int count
, uint8_t *data
)
803 uint32_t latch
= 0, bork
;
805 int to_go
= sc
->sc_mono_width
;
807 PNOZZ_LATCH(sc
, PIXEL_1
);
809 for (i
= 0; i
< count
; i
++) {
811 latch
|= (bork
<< shift
);
813 /* check how many bits are significant */
815 bus_space_write_4(sc
->sc_bustag
,
817 (PIXEL_1
+ (31 << 2)), latch
);
821 bus_space_write_4(sc
->sc_bustag
,
823 (PIXEL_1
+ ((to_go
- 1) << 2)), latch
);
832 p9100_ctl_write_4(sc
, (PIXEL_1
+ ((to_go
- 1) << 2)), latch
);
836 p9100_clearscreen(struct p9100_softc
*sc
)
839 p9100_rectfill(sc
, 0, 0, sc
->sc_width
, sc
->sc_height
, sc
->sc_bg
);
841 #endif /* NWSDISPLAY > 0 */
844 p9100_ramdac_read(struct p9100_softc
*sc
, bus_size_t off
)
847 sc
->sc_junk
= p9100_ctl_read_4(sc
, PWRUP_CNFG
);
848 return ((bus_space_read_4(sc
->sc_bustag
,
849 sc
->sc_ctl_memh
, off
) >> 16) & 0xff);
853 p9100_ramdac_write(struct p9100_softc
*sc
, bus_size_t off
, uint8_t v
)
856 sc
->sc_junk
= p9100_ctl_read_4(sc
, PWRUP_CNFG
);
857 bus_space_write_4(sc
->sc_bustag
, sc
->sc_ctl_memh
, off
,
858 ((uint32_t)v
) << 16);
862 p9100_ramdac_read_ctl(struct p9100_softc
*sc
, int off
)
864 p9100_ramdac_write(sc
, DAC_INDX_LO
, off
& 0xff);
865 p9100_ramdac_write(sc
, DAC_INDX_HI
, (off
& 0xff00) >> 8);
866 return p9100_ramdac_read(sc
, DAC_INDX_DATA
);
870 p9100_ramdac_write_ctl(struct p9100_softc
*sc
, int off
, uint8_t val
)
872 p9100_ramdac_write(sc
, DAC_INDX_LO
, off
& 0xff);
873 p9100_ramdac_write(sc
, DAC_INDX_HI
, (off
& 0xff00) >> 8);
874 p9100_ramdac_write(sc
, DAC_INDX_DATA
, val
);
878 * Undo the effect of an FBIOSVIDEO that turns the video off.
881 p9100unblank(device_t dev
)
883 struct p9100_softc
*sc
= device_private(dev
);
885 p9100_set_video(sc
, 1);
888 * Check if we're in terminal mode. If not force the console screen
889 * to front so we can see ddb, panic messages and so on
891 if (sc
->sc_mode
!= WSDISPLAYIO_MODE_EMUL
) {
892 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
893 if (sc
->vd
.active
!= &p9100_console_screen
) {
894 SCREEN_INVISIBLE(sc
->vd
.active
);
895 sc
->vd
.active
= &p9100_console_screen
;
896 SCREEN_VISIBLE(&p9100_console_screen
);
898 p9100_init_engine(sc
);
899 p9100_set_depth(sc
, 8);
900 vcons_redraw_screen(&p9100_console_screen
);
905 p9100_set_video(struct p9100_softc
*sc
, int enable
)
907 uint32_t v
= p9100_ctl_read_4(sc
, SCRN_RPNT_CTL_1
);
913 p9100_ctl_write_4(sc
, SCRN_RPNT_CTL_1
, v
);
915 /* Turn On/Off the TFT if we know how.
917 tadpole_set_video(enable
);
922 p9100_get_video(struct p9100_softc
*sc
)
924 return (p9100_ctl_read_4(sc
, SCRN_RPNT_CTL_1
) & VIDEO_ENABLED
) != 0;
928 p9100_suspend(device_t dev
, pmf_qual_t qual
)
930 struct p9100_softc
*sc
= device_private(dev
);
932 if (sc
->sc_powerstate
== PWR_SUSPEND
)
935 sc
->sc_video
= p9100_get_video(sc
);
936 sc
->sc_dac_power
= p9100_ramdac_read_ctl(sc
, DAC_POWER_MGT
);
937 p9100_ramdac_write_ctl(sc
, DAC_POWER_MGT
,
938 DAC_POWER_SCLK_DISABLE
|
939 DAC_POWER_DDOT_DISABLE
|
940 DAC_POWER_SYNC_DISABLE
|
941 DAC_POWER_ICLK_DISABLE
|
942 DAC_POWER_IPWR_DISABLE
);
943 p9100_set_video(sc
, 0);
944 sc
->sc_powerstate
= PWR_SUSPEND
;
949 p9100_resume(device_t dev
, pmf_qual_t qual
)
951 struct p9100_softc
*sc
= device_private(dev
);
953 if (sc
->sc_powerstate
== PWR_RESUME
)
956 p9100_ramdac_write_ctl(sc
, DAC_POWER_MGT
, sc
->sc_dac_power
);
957 p9100_set_video(sc
, sc
->sc_video
);
959 sc
->sc_powerstate
= PWR_RESUME
;
964 * Load a subset of the current (new) colormap into the IBM RAMDAC.
967 p9100loadcmap(struct p9100_softc
*sc
, int start
, int ncolors
)
970 sc
->sc_last_offset
= 0xffffffff;
972 p9100_ramdac_write(sc
, DAC_CMAP_WRIDX
, start
);
974 for (i
=0;i
<ncolors
;i
++) {
975 p9100_ramdac_write(sc
, DAC_CMAP_DATA
,
976 sc
->sc_cmap
.cm_map
[i
+ start
][0]);
977 p9100_ramdac_write(sc
, DAC_CMAP_DATA
,
978 sc
->sc_cmap
.cm_map
[i
+ start
][1]);
979 p9100_ramdac_write(sc
, DAC_CMAP_DATA
,
980 sc
->sc_cmap
.cm_map
[i
+ start
][2]);
985 * Return the address that would map the given device at the given
986 * offset, allowing for the given protection, or return -1 for error.
989 p9100mmap(dev_t dev
, off_t off
, int prot
)
991 struct p9100_softc
*sc
= device_lookup_private(&pnozz_cd
, minor(dev
));
998 #ifdef PNOZZ_EMUL_CG3
999 #define CG3_MMAP_OFFSET 0x04000000
1000 /* Make Xsun think we are a CG3 (SUN3COLOR)
1002 if (off
>= CG3_MMAP_OFFSET
&& off
< CG3_MMAP_OFFSET
+ sc
->sc_fb_psize
) {
1003 off
-= CG3_MMAP_OFFSET
;
1004 return (bus_space_mmap(sc
->sc_bustag
,
1008 BUS_SPACE_MAP_LINEAR
));
1012 if (off
>= sc
->sc_fb_psize
+ sc
->sc_ctl_psize
/* + sc->sc_cmd_psize*/)
1015 if (off
< sc
->sc_fb_psize
) {
1016 return (bus_space_mmap(sc
->sc_bustag
,
1020 BUS_SPACE_MAP_LINEAR
));
1023 off
-= sc
->sc_fb_psize
;
1024 if (off
< sc
->sc_ctl_psize
) {
1025 return (bus_space_mmap(sc
->sc_bustag
,
1029 BUS_SPACE_MAP_LINEAR
));
1039 p9100_cursor(void *cookie
, int on
, int row
, int col
)
1041 struct rasops_info
*ri
= cookie
;
1042 struct vcons_screen
*scr
= ri
->ri_hw
;
1043 struct p9100_softc
*sc
= scr
->scr_cookie
;
1046 wi
= ri
->ri_font
->fontwidth
;
1047 he
= ri
->ri_font
->fontheight
;
1049 if (ri
->ri_flg
& RI_CURSOR
) {
1050 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1051 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1052 p9100_bitblt(sc
, x
, y
, x
, y
, wi
, he
, ROP_SRC
^ 0xff);
1053 ri
->ri_flg
&= ~RI_CURSOR
;
1061 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
1062 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
1063 p9100_bitblt(sc
, x
, y
, x
, y
, wi
, he
, ROP_SRC
^ 0xff);
1064 ri
->ri_flg
|= RI_CURSOR
;
1070 p9100_mapchar(void *cookie
, int uni
, u_int
*index
)
1077 p9100_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
1079 struct rasops_info
*ri
= cookie
;
1080 struct vcons_screen
*scr
= ri
->ri_hw
;
1081 struct p9100_softc
*sc
= scr
->scr_cookie
;
1087 wi
= ri
->ri_font
->fontwidth
;
1088 he
= ri
->ri_font
->fontheight
;
1090 if (!CHAR_IN_FONT(c
, ri
->ri_font
))
1093 bg
= (u_char
)ri
->ri_devcmap
[(attr
>> 16) & 0xff];
1094 fg
= (u_char
)ri
->ri_devcmap
[(attr
>> 24) & 0xff];
1095 x
= ri
->ri_xorigin
+ col
* wi
;
1096 y
= ri
->ri_yorigin
+ row
* he
;
1099 p9100_rectfill(sc
, x
, y
, wi
, he
, bg
);
1101 uc
= c
-ri
->ri_font
->firstchar
;
1102 data
= (uint8_t *)ri
->ri_font
->data
+ uc
*
1105 p9100_setup_mono(sc
, x
, y
, wi
, 1, fg
, bg
);
1106 for (i
= 0; i
< he
; i
++) {
1107 p9100_feed_line(sc
, ri
->ri_font
->stride
,
1109 data
+= ri
->ri_font
->stride
;
1115 * wsdisplay_accessops
1119 p9100_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
1122 struct vcons_data
*vd
= v
;
1123 struct p9100_softc
*sc
= vd
->cookie
;
1124 struct wsdisplay_fbinfo
*wdf
;
1125 struct vcons_screen
*ms
= vd
->active
;
1128 case WSDISPLAYIO_GTYPE
:
1129 *(u_int
*)data
= WSDISPLAY_TYPE_SB_P9100
;
1133 case WSDISPLAYIO_GVIDEO
:
1134 *(int *)data
= p9100_get_video(sc
);
1137 case WSDISPLAYIO_SVIDEO
:
1139 p9100_set_video(sc
, *(int *)data
);
1142 case WSDISPLAYIO_GINFO
:
1144 wdf
->height
= ms
->scr_ri
.ri_height
;
1145 wdf
->width
= ms
->scr_ri
.ri_width
;
1146 wdf
->depth
= ms
->scr_ri
.ri_depth
;
1150 case WSDISPLAYIO_GETCMAP
:
1151 return p9100_getcmap(sc
, (struct wsdisplay_cmap
*)data
);
1153 case WSDISPLAYIO_PUTCMAP
:
1154 return p9100_putcmap(sc
, (struct wsdisplay_cmap
*)data
);
1156 case WSDISPLAYIO_SMODE
:
1158 int new_mode
= *(int*)data
;
1159 if (new_mode
!= sc
->sc_mode
)
1161 sc
->sc_mode
= new_mode
;
1162 if (new_mode
== WSDISPLAYIO_MODE_EMUL
)
1164 p9100_init_engine(sc
);
1165 p9100_set_depth(sc
, 8);
1166 p9100loadcmap(sc
, 0, 256);
1167 p9100_clearscreen(sc
);
1168 vcons_redraw_screen(ms
);
1173 return EPASSTHROUGH
;
1177 p9100_mmap(void *v
, void *vs
, off_t offset
, int prot
)
1179 struct vcons_data
*vd
= v
;
1180 struct p9100_softc
*sc
= vd
->cookie
;
1183 /* 'regular' framebuffer mmap()ing */
1184 if (offset
< sc
->sc_fb_psize
) {
1185 pa
= bus_space_mmap(sc
->sc_bustag
, sc
->sc_fb_paddr
+ offset
, 0,
1186 prot
, BUS_SPACE_MAP_LINEAR
);
1190 if ((offset
>= sc
->sc_fb_paddr
) && (offset
< (sc
->sc_fb_paddr
+
1191 sc
->sc_fb_psize
))) {
1192 pa
= bus_space_mmap(sc
->sc_bustag
, offset
, 0, prot
,
1193 BUS_SPACE_MAP_LINEAR
);
1197 if ((offset
>= sc
->sc_ctl_paddr
) && (offset
< (sc
->sc_ctl_paddr
+
1198 sc
->sc_ctl_psize
))) {
1199 pa
= bus_space_mmap(sc
->sc_bustag
, offset
, 0, prot
,
1200 BUS_SPACE_MAP_LINEAR
);
1208 p9100_init_screen(void *cookie
, struct vcons_screen
*scr
,
1209 int existing
, long *defattr
)
1211 struct p9100_softc
*sc
= cookie
;
1212 struct rasops_info
*ri
= &scr
->scr_ri
;
1214 ri
->ri_depth
= sc
->sc_depth
<< 3;
1215 ri
->ri_width
= sc
->sc_width
;
1216 ri
->ri_height
= sc
->sc_height
;
1217 ri
->ri_stride
= sc
->sc_stride
;
1218 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
1220 ri
->ri_bits
= bus_space_vaddr(sc
->sc_bustag
, sc
->sc_fb_memh
);
1222 DPRINTF("addr: %08lx\n",(ulong
)ri
->ri_bits
);
1224 rasops_init(ri
, sc
->sc_height
/8, sc
->sc_width
/8);
1225 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
1226 rasops_reconfig(ri
, sc
->sc_height
/ ri
->ri_font
->fontheight
,
1227 sc
->sc_width
/ ri
->ri_font
->fontwidth
);
1229 /* enable acceleration */
1230 ri
->ri_ops
.cursor
= p9100_cursor
;
1231 ri
->ri_ops
.copyrows
= p9100_copyrows
;
1232 ri
->ri_ops
.eraserows
= p9100_eraserows
;
1233 ri
->ri_ops
.copycols
= p9100_copycols
;
1234 ri
->ri_ops
.erasecols
= p9100_erasecols
;
1235 ri
->ri_ops
.putchar
= p9100_putchar
;
1236 ri
->ri_ops
.allocattr
= p9100_allocattr
;
1240 p9100_putcmap(struct p9100_softc
*sc
, struct wsdisplay_cmap
*cm
)
1242 u_int index
= cm
->index
;
1243 u_int count
= cm
->count
;
1245 u_char rbuf
[256], gbuf
[256], bbuf
[256];
1248 if (cm
->index
>= 256 || cm
->count
> 256 ||
1249 (cm
->index
+ cm
->count
) > 256)
1251 error
= copyin(cm
->red
, &rbuf
[index
], count
);
1254 error
= copyin(cm
->green
, &gbuf
[index
], count
);
1257 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
1265 for (i
= 0; i
< count
; i
++) {
1266 sc
->sc_cmap
.cm_map
[index
][0] = *r
;
1267 sc
->sc_cmap
.cm_map
[index
][1] = *g
;
1268 sc
->sc_cmap
.cm_map
[index
][2] = *b
;
1272 p9100loadcmap(sc
, 0, 256);
1277 p9100_getcmap(struct p9100_softc
*sc
, struct wsdisplay_cmap
*cm
)
1279 u_int index
= cm
->index
;
1280 u_int count
= cm
->count
;
1282 uint8_t red
[256], green
[256], blue
[256];
1284 if (index
>= 255 || count
> 256 || index
+ count
> 256)
1288 while (i
< (index
+ count
)) {
1289 red
[i
] = sc
->sc_cmap
.cm_map
[i
][0];
1290 green
[i
] = sc
->sc_cmap
.cm_map
[i
][1];
1291 blue
[i
] = sc
->sc_cmap
.cm_map
[i
][2];
1294 error
= copyout(&red
[index
], cm
->red
, count
);
1297 error
= copyout(&green
[index
], cm
->green
, count
);
1300 error
= copyout(&blue
[index
], cm
->blue
, count
);
1308 p9100_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
1310 struct rasops_info
*ri
= cookie
;
1311 struct vcons_screen
*scr
= ri
->ri_hw
;
1312 int32_t xs
, xd
, y
, width
, height
;
1314 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
1315 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
1316 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1317 width
= ri
->ri_font
->fontwidth
* ncols
;
1318 height
= ri
->ri_font
->fontheight
;
1319 p9100_bitblt(scr
->scr_cookie
, xs
, y
, xd
, y
, width
, height
, ROP_SRC
);
1323 p9100_erasecols(void *cookie
, int row
, int startcol
, int ncols
, long fillattr
)
1325 struct rasops_info
*ri
= cookie
;
1326 struct vcons_screen
*scr
= ri
->ri_hw
;
1327 int32_t x
, y
, width
, height
, bg
;
1329 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
1330 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1331 width
= ri
->ri_font
->fontwidth
* ncols
;
1332 height
= ri
->ri_font
->fontheight
;
1333 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
1334 p9100_rectfill(scr
->scr_cookie
, x
, y
, width
, height
, bg
);
1338 p9100_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
1340 struct rasops_info
*ri
= cookie
;
1341 struct vcons_screen
*scr
= ri
->ri_hw
;
1342 int32_t x
, ys
, yd
, width
, height
;
1345 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
1346 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
1347 width
= ri
->ri_emuwidth
;
1348 height
= ri
->ri_font
->fontheight
* nrows
;
1349 p9100_bitblt(scr
->scr_cookie
, x
, ys
, x
, yd
, width
, height
, ROP_SRC
);
1353 p9100_eraserows(void *cookie
, int row
, int nrows
, long fillattr
)
1355 struct rasops_info
*ri
= cookie
;
1356 struct vcons_screen
*scr
= ri
->ri_hw
;
1357 int32_t x
, y
, width
, height
, bg
;
1359 if ((row
== 0) && (nrows
== ri
->ri_rows
)) {
1361 width
= ri
->ri_width
;
1362 height
= ri
->ri_height
;
1365 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
1366 width
= ri
->ri_emuwidth
;
1367 height
= ri
->ri_font
->fontheight
* nrows
;
1369 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
1370 p9100_rectfill(scr
->scr_cookie
, x
, y
, width
, height
, bg
);
1375 p9100_allocattr(void *cookie
, int fg
, int bg
, int flags
, long *attrp
)
1377 if ((fg
== 0) && (bg
== 0))
1383 *attrp
= (fg
& 0xff) << 24 | (bg
& 0xff) << 16 | (flags
& 0xff);
1385 if (flags
& WSATTR_REVERSE
) {
1386 *attrp
= (bg
& 0xff) << 24 | (fg
& 0xff) << 16 |
1387 (flags
& 0xff) << 8;
1389 *attrp
= (fg
& 0xff) << 24 | (bg
& 0xff) << 16 |
1390 (flags
& 0xff) << 8;
1397 p9100_load_font(void *v
, void *cookie
, struct wsdisplay_font
*data
)
1404 #endif /* NWSDISPLAY > 0 */
1408 p9100_intr(void *arg
)
1410 /*p9100_softc *sc=arg;*/
1417 p9100_init_cursor(struct p9100_softc
*sc
)
1420 memset(&sc
->sc_cursor
, 0, sizeof(struct pnozz_cursor
));
1421 sc
->sc_cursor
.pc_size
.x
= 64;
1422 sc
->sc_cursor
.pc_size
.y
= 64;
1427 p9100_set_fbcursor(struct p9100_softc
*sc
)
1429 #ifdef PNOZZ_PARANOID
1432 s
= splhigh(); /* just in case... */
1434 sc
->sc_last_offset
= 0xffffffff;
1436 /* set position and hotspot */
1437 p9100_ramdac_write(sc
, DAC_INDX_CTL
, DAC_INDX_AUTOINCR
);
1438 p9100_ramdac_write(sc
, DAC_INDX_HI
, 0);
1439 p9100_ramdac_write(sc
, DAC_INDX_LO
, DAC_CURSOR_CTL
);
1440 if (sc
->sc_cursor
.pc_enable
) {
1441 p9100_ramdac_write(sc
, DAC_INDX_DATA
, DAC_CURSOR_X11
|
1444 p9100_ramdac_write(sc
, DAC_INDX_DATA
, DAC_CURSOR_OFF
);
1445 /* next two registers - x low, high, y low, high */
1446 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.pc_pos
.x
& 0xff);
1447 p9100_ramdac_write(sc
, DAC_INDX_DATA
, (sc
->sc_cursor
.pc_pos
.x
>> 8) &
1449 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.pc_pos
.y
& 0xff);
1450 p9100_ramdac_write(sc
, DAC_INDX_DATA
, (sc
->sc_cursor
.pc_pos
.y
>> 8) &
1453 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.pc_hot
.x
& 0xff);
1454 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.pc_hot
.y
& 0xff);
1456 #ifdef PNOZZ_PARANOID
1463 p9100_setcursorcmap(struct p9100_softc
*sc
)
1467 #ifdef PNOZZ_PARANOID
1469 s
= splhigh(); /* just in case... */
1471 sc
->sc_last_offset
= 0xffffffff;
1473 /* set cursor colours */
1474 p9100_ramdac_write(sc
, DAC_INDX_CTL
, DAC_INDX_AUTOINCR
);
1475 p9100_ramdac_write(sc
, DAC_INDX_HI
, 0);
1476 p9100_ramdac_write(sc
, DAC_INDX_LO
, DAC_CURSOR_COL_1
);
1478 for (i
= 0; i
< 3; i
++) {
1479 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.red
[i
]);
1480 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.green
[i
]);
1481 p9100_ramdac_write(sc
, DAC_INDX_DATA
, sc
->sc_cursor
.blue
[i
]);
1484 #ifdef PNOZZ_PARANOID
1490 p9100_loadcursor(struct p9100_softc
*sc
)
1492 uint32_t *image
, *mask
;
1493 uint32_t bit
, bbit
, im
, ma
;
1495 uint8_t latch1
, latch2
;
1497 #ifdef PNOZZ_PARANOID
1499 s
= splhigh(); /* just in case... */
1501 sc
->sc_last_offset
= 0xffffffff;
1503 /* set cursor shape */
1504 p9100_ramdac_write(sc
, DAC_INDX_CTL
, DAC_INDX_AUTOINCR
);
1505 p9100_ramdac_write(sc
, DAC_INDX_HI
, 1);
1506 p9100_ramdac_write(sc
, DAC_INDX_LO
, 0);
1508 image
= sc
->sc_cursor
.pc_bits
;
1509 mask
= &sc
->sc_cursor
.pc_bits
[0x80];
1511 for (i
= 0; i
< 0x80; i
++) {
1515 for (k
= 0; k
< 4; k
++) {
1518 for (j
= 0; j
< 4; j
++) {
1529 for (j
= 0; j
< 4; j
++) {
1538 p9100_ramdac_write(sc
, DAC_INDX_DATA
, latch1
);
1539 p9100_ramdac_write(sc
, DAC_INDX_DATA
, latch2
);
1542 #ifdef PNOZZ_DEBUG_CURSOR
1544 for (i
=0;i
<0x80;i
+=2)
1545 printf("%08x %08x\n", image
[i
], image
[i
+1]);
1547 for (i
=0;i
<0x80;i
+=2)
1548 printf("%08x %08x\n", mask
[i
], mask
[i
+1]);
1550 #ifdef PNOZZ_PARANOID
1557 p9100_set_extvga(void *cookie
, int status
)
1559 struct p9100_softc
*sc
= cookie
;
1560 #ifdef PNOZZ_PARANOID
1567 printf("%s: external VGA %s\n", device_xname(sc
->sc_dev
),
1568 status
? "on" : "off");
1571 sc
->sc_last_offset
= 0xffffffff;
1574 p9100_ramdac_write_ctl(sc
, DAC_POWER_MGT
,
1575 p9100_ramdac_read_ctl(sc
, DAC_POWER_MGT
) &
1576 ~DAC_POWER_IPWR_DISABLE
);
1578 p9100_ramdac_write_ctl(sc
, DAC_POWER_MGT
,
1579 p9100_ramdac_read_ctl(sc
, DAC_POWER_MGT
) |
1580 DAC_POWER_IPWR_DISABLE
);
1582 #ifdef PNOZZ_PARANOID
1586 #endif /* NTCTRL > 0 */
1589 upper_bit(uint32_t b
)
1591 uint32_t mask
=0x80000000;
1595 while ((mask
!= 0) && ((b
& mask
) == 0)) {
1603 p9100_set_depth(struct p9100_softc
*sc
, int depth
)
1606 uint32_t bits
, scr
, memctl
, mem
;
1607 int s0
, s1
, s2
, s3
, ps
, crtcline
;
1608 uint8_t pf
, mc3
, es
;
1612 sc
->sc_depthshift
= 0;
1616 es
= 0; /* no swapping */
1620 sc
->sc_depthshift
= 1;
1624 es
= 2; /* swap bytes in 16bit words */
1629 printf("We don't DO 24bit pixels dammit!\n");
1632 sc
->sc_depthshift
= 2;
1636 es
= 6; /* swap both half-words and bytes */
1640 aprint_error("%s: bogus colour depth (%d)\n",
1645 * this could be done a lot shorter and faster but then nobody would
1646 * understand what the hell we're doing here without getting a major
1647 * headache. Scanline size is encoded as 4 shift values, 3 of them 3 bits
1648 * wide, 16 << n for n>0, one 2 bits, 512 << n for n>0. n==0 means 0
1650 new_sls
= sc
->sc_width
<< sc
->sc_depthshift
;
1651 sc
->sc_stride
= new_sls
;
1653 s3
= upper_bit(bits
);
1659 s2
= upper_bit(bits
);
1665 s1
= upper_bit(bits
);
1671 s0
= upper_bit(bits
);
1679 DPRINTF("sls: %x sh: %d %d %d %d leftover: %x\n", new_sls
, s0
, s1
,
1683 * now let's put these values into the System Config Register. No need to
1684 * read it here since we (hopefully) just saved the content
1686 scr
= p9100_ctl_read_4(sc
, SYS_CONF
);
1687 scr
= (s0
<< SHIFT_0
) | (s1
<< SHIFT_1
) | (s2
<< SHIFT_2
) |
1688 (s3
<< SHIFT_3
) | (ps
<< PIXEL_SHIFT
) | (es
<< SWAP_SHIFT
);
1690 DPRINTF("new scr: %x DAC %x %x\n", scr
, pf
, mc3
);
1692 mem
= p9100_ctl_read_4(sc
, VID_MEM_CONFIG
);
1694 DPRINTF("old memctl: %08x\n", mem
);
1696 /* set shift and crtc clock */
1697 mem
&= ~(0x0000fc00);
1698 mem
|= (memctl
<< 10) | (memctl
<< 13);
1699 p9100_ctl_write_4(sc
, VID_MEM_CONFIG
, mem
);
1701 DPRINTF("new memctl: %08x\n", mem
);
1703 /* whack the engine... */
1704 p9100_ctl_write_4(sc
, SYS_CONF
, scr
);
1706 /* ok, whack the DAC */
1707 p9100_ramdac_write_ctl(sc
, DAC_MISC_1
, 0x11);
1708 p9100_ramdac_write_ctl(sc
, DAC_MISC_2
, 0x45);
1709 p9100_ramdac_write_ctl(sc
, DAC_MISC_3
, mc3
);
1711 * despite the 3GX manual saying otherwise we don't need to mess with
1712 * any clock dividers here
1714 p9100_ramdac_write_ctl(sc
, DAC_MISC_CLK
, 1);
1715 p9100_ramdac_write_ctl(sc
, 3, 0);
1716 p9100_ramdac_write_ctl(sc
, 4, 0);
1718 p9100_ramdac_write_ctl(sc
, DAC_POWER_MGT
, 0);
1719 p9100_ramdac_write_ctl(sc
, DAC_OPERATION
, 0);
1720 p9100_ramdac_write_ctl(sc
, DAC_PALETTE_CTRL
, 0);
1722 p9100_ramdac_write_ctl(sc
, DAC_PIXEL_FMT
, pf
);
1724 /* TODO: distinguish between 15 and 16 bit */
1725 p9100_ramdac_write_ctl(sc
, DAC_8BIT_CTRL
, 0);
1726 /* direct colour, linear, 565 */
1727 p9100_ramdac_write_ctl(sc
, DAC_16BIT_CTRL
, 0xc6);
1729 p9100_ramdac_write_ctl(sc
, DAC_32BIT_CTRL
, 3);
1731 /* From the 3GX manual. Needs magic number reduction */
1732 p9100_ramdac_write_ctl(sc
, 0x10, 2);
1733 p9100_ramdac_write_ctl(sc
, 0x11, 0);
1734 p9100_ramdac_write_ctl(sc
, 0x14, 5);
1735 p9100_ramdac_write_ctl(sc
, 0x08, 1);
1736 p9100_ramdac_write_ctl(sc
, 0x15, 5);
1737 p9100_ramdac_write_ctl(sc
, 0x16, 0x63);
1739 /* whack the CRTC */
1740 /* we always transfer 64bit in one go */
1741 crtcline
= sc
->sc_stride
>> 3;
1743 DPRINTF("crtcline: %d\n", crtcline
);
1745 p9100_ctl_write_4(sc
, VID_HTOTAL
, (24 << sc
->sc_depthshift
) + crtcline
);
1746 p9100_ctl_write_4(sc
, VID_HSRE
, 8 << sc
->sc_depthshift
);
1747 p9100_ctl_write_4(sc
, VID_HBRE
, 18 << sc
->sc_depthshift
);
1748 p9100_ctl_write_4(sc
, VID_HBFE
, (18 << sc
->sc_depthshift
) + crtcline
);
1753 sscr
= p9100_ctl_read_4(sc
, SYS_CONF
);
1754 printf("scr: %x\n", sscr
);