1 /* $NetBSD: cgfourteen.c,v 1.61 2009/07/14 20:57:22 apb Exp $ */
5 * The President and Fellows of Harvard College. All rights reserved.
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
9 * This software was developed by the Computer Systems Engineering group
10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11 * contributed to Berkeley.
13 * All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Harvard University.
16 * This product includes software developed by the University of
17 * California, Lawrence Berkeley Laboratory.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * California, Berkeley and its contributors.
31 * This product includes software developed by Harvard University and
33 * 4. Neither the name of the University nor the names of its contributors
34 * may be used to endorse or promote products derived from this software
35 * without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp
51 * NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp
55 * Driver for Campus-II on-board mbus-based video (cgfourteen).
56 * Provides minimum emulation of a Sun cgthree 8-bit framebuffer to
59 * Does not handle interrupts, even though they can occur.
61 * XXX should defer colormap updates to vertical retrace interrupts
65 * The following is for debugging only; it opens up a security hole
66 * enabled by allowing any user to map the control registers for the
67 * cg14 into their space.
72 * The following enables 24-bit operation: when opened, the framebuffer
73 * will switch to 24-bit mode (actually 32-bit mode), and provide a
74 * simple cg8 emulation.
78 #include <sys/param.h>
79 #include <sys/systm.h>
81 #include <sys/device.h>
82 #include <sys/ioctl.h>
83 #include <sys/malloc.h>
88 #include <dev/pci/pciio.h>
90 #include <uvm/uvm_extern.h>
92 #include <dev/sun/fbio.h>
93 #include <machine/autoconf.h>
94 #include <machine/pmap.h>
95 #include <dev/sun/fbvar.h>
96 #include <machine/cpu.h>
97 #include <dev/sbus/sbusvar.h>
99 #include "wsdisplay.h"
100 #include <dev/wscons/wsconsio.h>
101 #include <dev/wsfont/wsfont.h>
102 #include <dev/rasops/rasops.h>
104 #include <dev/wscons/wsdisplay_vconsvar.h>
106 #include <sparc/dev/cgfourteenreg.h>
107 #include <sparc/dev/cgfourteenvar.h>
109 #include "opt_wsemul.h"
111 /* autoconfiguration driver */
112 static int cgfourteenmatch(device_t
, struct cfdata
*, void *);
113 static void cgfourteenattach(device_t
, device_t
, void *);
114 static void cgfourteenunblank(device_t
);
116 CFATTACH_DECL_NEW(cgfourteen
, sizeof(struct cgfourteen_softc
),
117 cgfourteenmatch
, cgfourteenattach
, NULL
, NULL
);
119 extern struct cfdriver cgfourteen_cd
;
121 dev_type_open(cgfourteenopen
);
122 dev_type_close(cgfourteenclose
);
123 dev_type_ioctl(cgfourteenioctl
);
124 dev_type_mmap(cgfourteenmmap
);
125 dev_type_poll(cgfourteenpoll
);
127 const struct cdevsw cgfourteen_cdevsw
= {
128 cgfourteenopen
, cgfourteenclose
, noread
, nowrite
, cgfourteenioctl
,
129 nostop
, notty
, cgfourteenpoll
, cgfourteenmmap
, nokqfilter
,
132 /* frame buffer generic driver */
133 static struct fbdriver cgfourteenfbdriver
= {
134 cgfourteenunblank
, cgfourteenopen
, cgfourteenclose
, cgfourteenioctl
,
135 cgfourteenpoll
, cgfourteenmmap
, nokqfilter
138 extern struct tty
*fbconstty
;
140 static void cg14_set_video(struct cgfourteen_softc
*, int);
141 static int cg14_get_video(struct cgfourteen_softc
*);
142 static int cg14_get_cmap(struct fbcmap
*, union cg14cmap
*, int);
143 static int cg14_put_cmap(struct fbcmap
*, union cg14cmap
*, int);
144 static void cg14_load_hwcmap(struct cgfourteen_softc
*, int, int);
145 static void cg14_init(struct cgfourteen_softc
*);
146 static void cg14_reset(struct cgfourteen_softc
*);
149 static void cg14_setup_wsdisplay(struct cgfourteen_softc
*, int);
150 static void cg14_init_cmap(struct cgfourteen_softc
*);
151 static int cg14_putcmap(struct cgfourteen_softc
*, struct wsdisplay_cmap
*);
152 static int cg14_getcmap(struct cgfourteen_softc
*, struct wsdisplay_cmap
*);
153 static void cg14_set_depth(struct cgfourteen_softc
*, int);
154 static void cg14_move_cursor(struct cgfourteen_softc
*, int, int);
155 static int cg14_do_cursor(struct cgfourteen_softc
*,
156 struct wsdisplay_cursor
*);
159 #if defined(RASTERCONSOLE) && (NWSDISPLAY > 0)
160 #error "You can't have it both ways - either RASTERCONSOLE or wsdisplay"
164 * Match a cgfourteen.
167 cgfourteenmatch(device_t parent
, struct cfdata
*cf
, void *aux
)
169 union obio_attach_args
*uoba
= aux
;
170 struct sbus_attach_args
*sa
= &uoba
->uoba_sbus
;
173 * The cgfourteen is a local-bus video adaptor, accessed directly
174 * via the processor, and not through device space or an external
175 * bus. Thus we look _only_ at the obio bus.
176 * Additionally, these things exist only on the Sun4m.
179 if (uoba
->uoba_isobio4
!= 0 || !CPU_ISSUN4M
)
182 /* Check driver name */
183 return (strcmp(cf
->cf_name
, sa
->sa_name
) == 0);
187 * Set COLOUR_OFFSET to the offset of the video RAM. This is to provide
188 * space for faked overlay junk for the cg8 emulation.
190 * As it happens, this value is correct for both cg3 and cg8 emulation!
192 #define COLOUR_OFFSET (256*1024)
195 static void cg14_set_rcons_luts(struct cgfourteen_softc
*sc
)
199 for (i
=0;i
<CG14_CLUT_SIZE
;i
++) sc
->sc_xlut
->xlut_lut
[i
] = 0x22;
200 for (i
=0;i
<CG14_CLUT_SIZE
;i
++) sc
->sc_clut2
->clut_lut
[i
] = 0x00ffffff;
201 sc
->sc_clut2
->clut_lut
[0] = 0x00ffffff;
202 sc
->sc_clut2
->clut_lut
[255] = 0;
204 #endif /* RASTERCONSOLE */
207 static int cg14_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
208 static paddr_t
cg14_mmap(void *, void *, off_t
, int);
209 static void cg14_init_screen(void *, struct vcons_screen
*, int, long *);
212 struct wsdisplay_accessops cg14_accessops
= {
215 NULL
, /* alloc_screen */
216 NULL
, /* free_screen */
217 NULL
, /* show_screen */
218 NULL
, /* load_font */
225 * Attach a display. We need to notice if it is the console, too.
228 cgfourteenattach(device_t parent
, device_t self
, void *aux
)
230 union obio_attach_args
*uoba
= aux
;
231 struct sbus_attach_args
*sa
= &uoba
->uoba_sbus
;
232 struct cgfourteen_softc
*sc
= device_private(self
);
233 struct fbdevice
*fb
= &sc
->sc_fb
;
234 bus_space_handle_t bh
;
236 volatile uint32_t *lut
;
237 int i
, isconsole
, items
;
238 uint32_t fbva
[2] = {0, 0};
239 uint32_t *ptr
= fbva
;
245 /* Remember cookies for cgfourteenmmap() */
246 sc
->sc_bustag
= sa
->sa_bustag
;
248 fb
->fb_driver
= &cgfourteenfbdriver
;
249 fb
->fb_device
= sc
->sc_dev
;
250 /* Mask out invalid flags from the user. */
251 fb
->fb_flags
= device_cfdata(sc
->sc_dev
)->cf_flags
& FB_USERMASK
;
254 * We're emulating a cg3/8, so represent ourselves as one
257 fb
->fb_type
.fb_type
= FBTYPE_MEMCOLOR
;
258 fb
->fb_type
.fb_depth
= 32;
260 fb
->fb_type
.fb_type
= FBTYPE_SUN3COLOR
;
261 fb
->fb_type
.fb_depth
= 8;
263 fb_setsize_obp(fb
, sc
->sc_fb
.fb_type
.fb_depth
, 1152, 900, node
);
264 ramsize
= roundup(fb
->fb_type
.fb_height
* fb
->fb_linebytes
, NBPG
);
266 fb
->fb_type
.fb_cmsize
= CG14_CLUT_SIZE
;
267 fb
->fb_type
.fb_size
= ramsize
+ COLOUR_OFFSET
;
269 if (sa
->sa_nreg
< 2) {
270 printf("%s: only %d register sets\n",
271 self
->dv_xname
, sa
->sa_nreg
);
274 memcpy(sc
->sc_physadr
, sa
->sa_reg
,
275 sa
->sa_nreg
* sizeof(struct sbus_reg
));
277 sc
->sc_vramsize
= sc
->sc_physadr
[CG14_PXL_IDX
].sbr_size
;
279 printf(": %d MB VRAM", (uint32_t)(sc
->sc_vramsize
>> 20));
281 * Now map in the 8 useful pages of registers
283 if (sa
->sa_size
< 0x10000) {
285 printf("warning: can't find all cgfourteen registers...\n");
287 sa
->sa_size
= 0x10000;
289 if (sbus_bus_map(sa
->sa_bustag
, sa
->sa_slot
,
292 0 /*BUS_SPACE_MAP_LINEAR*/,
294 printf("%s: cannot map control registers\n", self
->dv_xname
);
299 sc
->sc_ctl
= (struct cg14ctl
*) (bh
);
300 sc
->sc_hwc
= (struct cg14curs
*) (bh
+ CG14_OFFSET_CURS
);
301 sc
->sc_dac
= (struct cg14dac
*) (bh
+ CG14_OFFSET_DAC
);
302 sc
->sc_xlut
= (struct cg14xlut
*) (bh
+ CG14_OFFSET_XLUT
);
303 sc
->sc_clut1
= (struct cg14clut
*) (bh
+ CG14_OFFSET_CLUT1
);
304 sc
->sc_clut2
= (struct cg14clut
*) (bh
+ CG14_OFFSET_CLUT2
);
305 sc
->sc_clut3
= (struct cg14clut
*) (bh
+ CG14_OFFSET_CLUT3
);
306 sc
->sc_clutincr
= (u_int
*) (bh
+ CG14_OFFSET_CLUTINCR
);
309 * Let the user know that we're here
312 printf(": cgeight emulated at %dx%dx24bpp",
313 fb
->fb_type
.fb_width
, fb
->fb_type
.fb_height
);
315 printf(": cgthree emulated at %dx%dx8bpp",
316 fb
->fb_type
.fb_width
, fb
->fb_type
.fb_height
);
321 cg14_set_video(sc
, 1);
324 * Grab the initial colormap
326 lut
= sc
->sc_clut1
->clut_lut
;
327 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++)
328 sc
->sc_cmap
.cm_chip
[i
] = lut
[i
];
330 /* See if we're the console */
331 isconsole
= fb_is_console(node
);
333 #if defined(RASTERCONSOLE)
335 printf(" (console)\n");
336 /* *sbus*_bus_map? but that's how we map the regs... */
337 if (sbus_bus_map( sc
->sc_bustag
,
338 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_slot
,
339 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_offset
+
341 1152 * 900, BUS_SPACE_MAP_LINEAR
,
343 printf("%s: cannot map pixels\n",
344 device_xname(sc
->sc_dev
));
347 sc
->sc_rcfb
= sc
->sc_fb
;
348 sc
->sc_rcfb
.fb_type
.fb_type
= FBTYPE_SUN3COLOR
;
349 sc
->sc_rcfb
.fb_type
.fb_depth
= 8;
350 sc
->sc_rcfb
.fb_linebytes
= 1152;
351 sc
->sc_rcfb
.fb_type
.fb_size
= roundup(1152*900,NBPG
);
352 sc
->sc_rcfb
.fb_pixels
= (void *)bh
;
354 printf("vram at %p\n",(void *)bh
);
355 /* XXX should use actual screen size */
357 for (i
= 0; i
< ramsize
; i
++)
358 ((unsigned char *)bh
)[i
] = 0;
359 fbrcons_init(&sc
->sc_rcfb
);
360 cg14_set_rcons_luts(sc
);
361 sc
->sc_ctl
->ctl_mctl
= CG14_MCTL_ENABLEVID
|
362 CG14_MCTL_PIXMODE_32
| CG14_MCTL_POWERCTL
;
368 prom_getprop(sa
->sa_node
, "address", 4, &items
, &ptr
);
370 if (sbus_bus_map( sc
->sc_bustag
,
371 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_slot
,
372 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_offset
,
373 ramsize
, BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
,
375 printf("%s: cannot map pixels\n",
376 device_xname(sc
->sc_dev
));
379 sc
->sc_fb
.fb_pixels
= bus_space_vaddr(sc
->sc_bustag
, bh
);
381 sc
->sc_fb
.fb_pixels
= (void *)fbva
[1];
384 sc
->sc_shadowfb
= kmem_alloc(ramsize
, KM_NOSLEEP
);
387 printf(" (console)\n");
392 cg14_setup_wsdisplay(sc
, isconsole
);
395 /* Attach to /dev/fb */
396 fb_attach(&sc
->sc_fb
, isconsole
);
400 * Keep track of the number of opens made. In the 24-bit driver, we need to
401 * switch to 24-bit mode on the first open, and switch back to 8-bit on
402 * the last close. This kind of nonsense is needed to give screenblank
403 * a fighting chance of working.
407 cgfourteenopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
409 struct cgfourteen_softc
*sc
;
412 sc
= device_lookup_private(&cgfourteen_cd
, minor(dev
));
415 oldopens
= sc
->sc_opens
++;
417 /* Setup the cg14 as we want it, and save the original PROM state */
418 if (oldopens
== 0) /* first open only, to make screenblank work */
425 cgfourteenclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
427 struct cgfourteen_softc
*sc
=
428 device_lookup_private(&cgfourteen_cd
, minor(dev
));
431 opens
= --sc
->sc_opens
;
432 if (sc
->sc_opens
< 0)
433 opens
= sc
->sc_opens
= 0;
436 * Restore video state to make the PROM happy, on last close.
445 cgfourteenioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
447 struct cgfourteen_softc
*sc
=
448 device_lookup_private(&cgfourteen_cd
, minor(dev
));
455 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
459 fba
= (struct fbgattr
*)data
;
460 fba
->real_type
= FBTYPE_MDICOLOR
;
461 fba
->owner
= 0; /* XXX ??? */
462 fba
->fbtype
= sc
->sc_fb
.fb_type
;
463 fba
->sattr
.flags
= 0;
464 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
465 fba
->sattr
.dev_specific
[0] = -1;
466 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
467 fba
->emu_types
[1] = -1;
471 return(cg14_get_cmap((struct fbcmap
*)data
, &sc
->sc_cmap
,
475 /* copy to software map */
476 #define p ((struct fbcmap *)data)
478 p
->index
&= 0xffffff;
480 error
= cg14_put_cmap(p
, &sc
->sc_cmap
, CG14_CLUT_SIZE
);
483 /* now blast them into the chip */
484 /* XXX should use retrace interrupt */
485 cg14_load_hwcmap(sc
, p
->index
, p
->count
);
490 *(int *)data
= cg14_get_video(sc
);
494 cg14_set_video(sc
, *(int *)data
);
504 * Undo the effect of an FBIOSVIDEO that turns the video off.
507 cgfourteenunblank(device_t dev
)
509 struct cgfourteen_softc
*sc
= device_private(dev
);
511 cg14_set_video(sc
, 1);
513 if (sc
->sc_mode
!= WSDISPLAYIO_MODE_EMUL
) {
514 cg14_set_depth(sc
, 8);
516 vcons_redraw_screen(sc
->sc_vd
.active
);
517 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
523 * Return the address that would map the given device at the given
524 * offset, allowing for the given protection, or return -1 for error.
526 * Since we're pretending to be a cg8, we put the main video RAM at the
527 * same place the cg8 does, at offset 256k. The cg8 has an enable
528 * plane in the 256k space; our "enable" plane works differently. We
529 * can't emulate the enable plane very well, but all X uses it for is
530 * to clear it at startup - so we map the first page of video RAM over
531 * and over to fill that 256k space. We also map some other views of
532 * the video RAM space.
534 * Our memory map thus looks like
536 * mmap range space base offset
537 * 00000000-00040000 vram 0 (multi-mapped - see above)
538 * 00040000-00434800 vram 00000000
539 * 01000000-01400000 vram 01000000
540 * 02000000-02200000 vram 02000000
541 * 02800000-02a00000 vram 02800000
542 * 03000000-03100000 vram 03000000
543 * 03400000-03500000 vram 03400000
544 * 03800000-03900000 vram 03800000
545 * 03c00000-03d00000 vram 03c00000
546 * 10000000-10010000 regs 00000000 (only if CG14_MAP_REGS)
549 cgfourteenmmap(dev_t dev
, off_t off
, int prot
)
551 struct cgfourteen_softc
*sc
=
552 device_lookup_private(&cgfourteen_cd
, minor(dev
));
555 panic("cgfourteenmmap");
560 #if defined(CG14_MAP_REGS) /* XXX: security hole */
562 * Map the control registers into user space. Should only be
563 * used for debugging!
565 if ((u_int
)off
>= 0x10000000 && (u_int
)off
< 0x10000000 + 16*4096) {
567 return (bus_space_mmap(sc
->sc_bustag
,
568 BUS_ADDR(sc
->sc_physadr
[CG14_CTL_IDX
].sbr_slot
,
569 sc
->sc_physadr
[CG14_CTL_IDX
].sbr_offset
),
570 off
, prot
, BUS_SPACE_MAP_LINEAR
));
574 if (off
< COLOUR_OFFSET
)
576 else if (off
< COLOUR_OFFSET
+(1152*900*4))
577 off
-= COLOUR_OFFSET
;
580 case 0x010: case 0x011: case 0x012: case 0x013:
581 case 0x020: case 0x021:
582 case 0x028: case 0x029:
593 return (bus_space_mmap(sc
->sc_bustag
,
594 BUS_ADDR(sc
->sc_physadr
[CG14_PXL_IDX
].sbr_slot
,
595 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_offset
),
596 off
, prot
, BUS_SPACE_MAP_LINEAR
));
600 cgfourteenpoll(dev_t dev
, int events
, struct lwp
*l
)
603 return (seltrue(dev
, events
, l
));
607 * Miscellaneous helper functions
610 /* Initialize the framebuffer, storing away useful state for later reset */
612 cg14_init(struct cgfourteen_softc
*sc
)
614 volatile uint32_t *clut
;
615 volatile uint8_t *xlut
;
619 * We stash away the following to restore on close:
621 * color look-up table 1 (sc->sc_saveclut)
622 * x look-up table (sc->sc_savexlut)
623 * control register (sc->sc_savectl)
624 * cursor control register (sc->sc_savehwc)
626 sc
->sc_savectl
= sc
->sc_ctl
->ctl_mctl
;
627 sc
->sc_savehwc
= sc
->sc_hwc
->curs_ctl
;
629 clut
= (volatile uint32_t *) sc
->sc_clut1
->clut_lut
;
630 xlut
= (volatile uint8_t *) sc
->sc_xlut
->xlut_lut
;
631 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++) {
632 sc
->sc_saveclut
.cm_chip
[i
] = clut
[i
];
633 sc
->sc_savexlut
[i
] = xlut
[i
];
638 * Enable the video, and put in 24 bit mode.
640 sc
->sc_ctl
->ctl_mctl
= CG14_MCTL_ENABLEVID
| CG14_MCTL_PIXMODE_32
|
644 * Zero the xlut to enable direct-color mode
646 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++)
647 sc
->sc_xlut
->xlut_lut
[i
] = 0;
650 * Enable the video and put it in 8 bit mode
652 sc
->sc_ctl
->ctl_mctl
= CG14_MCTL_ENABLEVID
| CG14_MCTL_PIXMODE_8
|
658 /* Restore the state saved on cg14_init */
659 cg14_reset(struct cgfourteen_softc
*sc
)
661 volatile uint32_t *clut
;
662 volatile uint8_t *xlut
;
666 * We restore the following, saved in cg14_init:
668 * color look-up table 1 (sc->sc_saveclut)
669 * x look-up table (sc->sc_savexlut)
670 * control register (sc->sc_savectl)
671 * cursor control register (sc->sc_savehwc)
673 * Note that we don't touch the video enable bits in the
674 * control register; otherwise, screenblank wouldn't work.
676 sc
->sc_ctl
->ctl_mctl
= (sc
->sc_ctl
->ctl_mctl
& (CG14_MCTL_ENABLEVID
|
677 CG14_MCTL_POWERCTL
)) |
678 (sc
->sc_savectl
& ~(CG14_MCTL_ENABLEVID
|
679 CG14_MCTL_POWERCTL
));
680 sc
->sc_hwc
->curs_ctl
= sc
->sc_savehwc
;
682 clut
= sc
->sc_clut1
->clut_lut
;
683 xlut
= sc
->sc_xlut
->xlut_lut
;
684 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++) {
685 clut
[i
] = sc
->sc_saveclut
.cm_chip
[i
];
686 xlut
[i
] = sc
->sc_savexlut
[i
];
690 /* Enable/disable video display; power down monitor if DPMS-capable */
692 cg14_set_video(struct cgfourteen_softc
*sc
, int enable
)
695 * We can only use DPMS to power down the display if the chip revision
699 if ((sc
->sc_ctl
->ctl_rsr
& CG14_RSR_REVMASK
) > 0)
700 sc
->sc_ctl
->ctl_mctl
|= (CG14_MCTL_ENABLEVID
|
703 sc
->sc_ctl
->ctl_mctl
|= CG14_MCTL_ENABLEVID
;
705 if ((sc
->sc_ctl
->ctl_rsr
& CG14_RSR_REVMASK
) > 0)
706 sc
->sc_ctl
->ctl_mctl
&= ~(CG14_MCTL_ENABLEVID
|
709 sc
->sc_ctl
->ctl_mctl
&= ~CG14_MCTL_ENABLEVID
;
713 /* Get status of video display */
715 cg14_get_video(struct cgfourteen_softc
*sc
)
717 return ((sc
->sc_ctl
->ctl_mctl
& CG14_MCTL_ENABLEVID
) != 0);
720 /* Read the software shadow colormap */
722 cg14_get_cmap(struct fbcmap
*p
, union cg14cmap
*cm
, int cmsize
)
724 u_int i
, start
, count
;
730 if (start
>= cmsize
|| count
> cmsize
- start
)
733 for (cp
= &cm
->cm_map
[start
][0], i
= 0; i
< count
; cp
+= 4, i
++) {
734 error
= copyout(&cp
[3], &p
->red
[i
], 1);
737 error
= copyout(&cp
[2], &p
->green
[i
], 1);
740 error
= copyout(&cp
[1], &p
->blue
[i
], 1);
747 /* Write the software shadow colormap */
749 cg14_put_cmap(struct fbcmap
*p
, union cg14cmap
*cm
, int cmsize
)
751 u_int i
, start
, count
;
758 if (start
>= cmsize
|| count
> cmsize
- start
)
761 memcpy(&cmap
, &cm
->cm_map
, sizeof cmap
);
762 for (cp
= &cmap
[start
][0], i
= 0; i
< count
; cp
+= 4, i
++) {
763 error
= copyin(&p
->red
[i
], &cp
[3], 1);
766 error
= copyin(&p
->green
[i
], &cp
[2], 1);
769 error
= copyin(&p
->blue
[i
], &cp
[1], 1);
772 cp
[0] = 0; /* no alpha channel */
774 memcpy(&cm
->cm_map
, &cmap
, sizeof cmap
);
779 cg14_load_hwcmap(struct cgfourteen_softc
*sc
, int start
, int ncolors
)
781 /* XXX switch to auto-increment, and on retrace intr */
783 /* Setup pointers to source and dest */
784 uint32_t *colp
= &sc
->sc_cmap
.cm_chip
[start
];
785 volatile uint32_t *lutp
= &sc
->sc_clut1
->clut_lut
[start
];
788 while (--ncolors
>= 0)
794 cg14_setup_wsdisplay(struct cgfourteen_softc
*sc
, int is_cons
)
796 struct wsemuldisplaydev_attach_args aa
;
797 struct rasops_info
*ri
;
800 sc
->sc_defaultscreen_descr
= (struct wsscreen_descr
){
805 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
808 sc
->sc_screens
[0] = &sc
->sc_defaultscreen_descr
;
809 sc
->sc_screenlist
= (struct wsscreen_list
){1, sc
->sc_screens
};
810 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
811 vcons_init(&sc
->sc_vd
, sc
, &sc
->sc_defaultscreen_descr
,
813 sc
->sc_vd
.init_screen
= cg14_init_screen
;
815 ri
= &sc
->sc_console_screen
.scr_ri
;
818 vcons_init_screen(&sc
->sc_vd
, &sc
->sc_console_screen
, 1,
821 /* clear the screen with the default background colour */
822 memset(sc
->sc_fb
.fb_pixels
,
823 (defattr
>> 16) & 0xff,
824 ri
->ri_stride
* ri
->ri_height
);
825 if (sc
->sc_shadowfb
!= NULL
)
826 memset(sc
->sc_shadowfb
,
827 (defattr
>> 16) & 0xff,
828 ri
->ri_stride
* ri
->ri_height
);
829 sc
->sc_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
831 sc
->sc_defaultscreen_descr
.textops
= &ri
->ri_ops
;
832 sc
->sc_defaultscreen_descr
.capabilities
= ri
->ri_caps
;
833 sc
->sc_defaultscreen_descr
.nrows
= ri
->ri_rows
;
834 sc
->sc_defaultscreen_descr
.ncols
= ri
->ri_cols
;
835 wsdisplay_cnattach(&sc
->sc_defaultscreen_descr
, ri
, 0, 0,
837 vcons_replay_msgbuf(&sc
->sc_console_screen
);
840 * since we're not the console we can postpone the rest
841 * until someone actually allocates a screen for us
847 aa
.console
= is_cons
;
848 aa
.scrdata
= &sc
->sc_screenlist
;
849 aa
.accessops
= &cg14_accessops
;
850 aa
.accesscookie
= &sc
->sc_vd
;
852 config_found(sc
->sc_dev
, &aa
, wsemuldisplaydevprint
);
856 cg14_init_cmap(struct cgfourteen_softc
*sc
)
860 for (i
= 0; i
< 256; i
++) {
862 sc
->sc_cmap
.cm_map
[i
][3] = rasops_cmap
[j
];
863 sc
->sc_cmap
.cm_map
[i
][2] = rasops_cmap
[j
+ 1];
864 sc
->sc_cmap
.cm_map
[i
][1] = rasops_cmap
[j
+ 2];
867 cg14_load_hwcmap(sc
, 0, 256);
871 cg14_putcmap(struct cgfourteen_softc
*sc
, struct wsdisplay_cmap
*cm
)
873 u_int index
= cm
->index
;
874 u_int count
= cm
->count
;
876 u_char rbuf
[256], gbuf
[256], bbuf
[256];
878 if (cm
->index
>= 256 || cm
->count
> 256 ||
879 (cm
->index
+ cm
->count
) > 256)
881 error
= copyin(cm
->red
, &rbuf
[index
], count
);
884 error
= copyin(cm
->green
, &gbuf
[index
], count
);
887 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
891 for (i
= 0; i
< count
; i
++) {
892 sc
->sc_cmap
.cm_map
[index
][3] = rbuf
[index
];
893 sc
->sc_cmap
.cm_map
[index
][2] = gbuf
[index
];
894 sc
->sc_cmap
.cm_map
[index
][1] = bbuf
[index
];
898 cg14_load_hwcmap(sc
, 0, 256);
903 cg14_getcmap(struct cgfourteen_softc
*sc
, struct wsdisplay_cmap
*cm
)
905 uint8_t rbuf
[256], gbuf
[256], bbuf
[256];
906 u_int index
= cm
->index
;
907 u_int count
= cm
->count
;
910 if (index
>= 255 || count
> 256 || index
+ count
> 256)
914 for (i
= 0; i
< count
; i
++) {
915 rbuf
[i
] = sc
->sc_cmap
.cm_map
[index
][3];
916 gbuf
[i
] = sc
->sc_cmap
.cm_map
[index
][2];
917 bbuf
[i
] = sc
->sc_cmap
.cm_map
[index
][1];
921 error
= copyout(rbuf
, cm
->red
, count
);
924 error
= copyout(gbuf
, cm
->green
, count
);
927 error
= copyout(bbuf
, cm
->blue
, count
);
934 cg14_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
937 struct vcons_data
*vd
= v
;
938 struct cgfourteen_softc
*sc
= vd
->cookie
;
939 struct wsdisplay_fbinfo
*wdf
;
940 struct vcons_screen
*ms
= vd
->active
;
944 case WSDISPLAYIO_GTYPE
:
945 *(uint32_t *)data
= WSDISPLAY_TYPE_SUNCG14
;
948 case WSDISPLAYIO_GINFO
:
950 wdf
->height
= ms
->scr_ri
.ri_height
;
951 wdf
->width
= ms
->scr_ri
.ri_width
;
956 case WSDISPLAYIO_GETCMAP
:
957 return cg14_getcmap(sc
,
958 (struct wsdisplay_cmap
*)data
);
960 case WSDISPLAYIO_PUTCMAP
:
961 return cg14_putcmap(sc
,
962 (struct wsdisplay_cmap
*)data
);
964 case WSDISPLAYIO_LINEBYTES
:
965 *(u_int
*)data
= ms
->scr_ri
.ri_stride
<< 2;
968 case WSDISPLAYIO_SMODE
:
970 int new_mode
= *(int*)data
;
971 if (new_mode
!= sc
->sc_mode
) {
972 sc
->sc_mode
= new_mode
;
973 if(new_mode
== WSDISPLAYIO_MODE_EMUL
) {
974 bus_space_write_1(sc
->sc_bustag
,
976 CG14_CURSOR_CONTROL
, 0);
977 cg14_set_depth(sc
, 8);
979 vcons_redraw_screen(ms
);
981 cg14_set_depth(sc
, 32);
986 case WSDISPLAYIO_SVIDEO
:
987 cg14_set_video(sc
, *(int *)data
);
989 case WSDISPLAYIO_GVIDEO
:
990 return cg14_get_video(sc
) ?
991 WSDISPLAYIO_VIDEO_ON
: WSDISPLAYIO_VIDEO_OFF
;
992 case WSDISPLAYIO_GCURPOS
:
994 struct wsdisplay_curpos
*cp
= (void *)data
;
996 cp
->x
= sc
->sc_cursor
.cc_pos
.x
;
997 cp
->y
= sc
->sc_cursor
.cc_pos
.y
;
1000 case WSDISPLAYIO_SCURPOS
:
1002 struct wsdisplay_curpos
*cp
= (void *)data
;
1004 cg14_move_cursor(sc
, cp
->x
, cp
->y
);
1007 case WSDISPLAYIO_GCURMAX
:
1009 struct wsdisplay_curpos
*cp
= (void *)data
;
1015 case WSDISPLAYIO_SCURSOR
:
1017 struct wsdisplay_cursor
*cursor
= (void *)data
;
1019 return cg14_do_cursor(sc
, cursor
);
1021 case PCI_IOC_CFGREAD
:
1022 case PCI_IOC_CFGWRITE
:
1026 return EPASSTHROUGH
;
1030 cg14_mmap(void *v
, void *vs
, off_t offset
, int prot
)
1032 struct vcons_data
*vd
= v
;
1033 struct cgfourteen_softc
*sc
= vd
->cookie
;
1035 /* allow mmap()ing the full framebuffer, not just what we use */
1036 if (offset
< sc
->sc_vramsize
)
1037 return bus_space_mmap(sc
->sc_bustag
,
1038 BUS_ADDR(sc
->sc_physadr
[CG14_PXL_IDX
].sbr_slot
,
1039 sc
->sc_physadr
[CG14_PXL_IDX
].sbr_offset
),
1040 offset
+ CG14_FB_CBGR
, prot
, BUS_SPACE_MAP_LINEAR
);
1046 cg14_init_screen(void *cookie
, struct vcons_screen
*scr
,
1047 int existing
, long *defattr
)
1049 struct cgfourteen_softc
*sc
= cookie
;
1050 struct rasops_info
*ri
= &scr
->scr_ri
;
1053 ri
->ri_width
= sc
->sc_fb
.fb_type
.fb_width
;
1054 ri
->ri_height
= sc
->sc_fb
.fb_type
.fb_height
;
1055 ri
->ri_stride
= ri
->ri_width
;
1056 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
1058 if (sc
->sc_shadowfb
!= NULL
) {
1059 ri
->ri_bits
= sc
->sc_shadowfb
;
1060 ri
->ri_hwbits
= (char *)sc
->sc_fb
.fb_pixels
;
1062 ri
->ri_bits
= (char *)sc
->sc_fb
.fb_pixels
;
1065 ri
->ri_flg
|= RI_CLEAR
;
1068 rasops_init(ri
, sc
->sc_fb
.fb_type
.fb_height
/ 8,
1069 sc
->sc_fb
.fb_type
.fb_width
/ 8);
1070 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
1073 sc
->sc_fb
.fb_type
.fb_height
/ ri
->ri_font
->fontheight
,
1074 sc
->sc_fb
.fb_type
.fb_width
/ ri
->ri_font
->fontwidth
);
1080 cg14_set_depth(struct cgfourteen_softc
*sc
, int depth
)
1084 if (sc
->sc_depth
== depth
)
1088 bus_space_write_1(sc
->sc_bustag
, sc
->sc_regh
,
1089 CG14_MCTL
, CG14_MCTL_ENABLEVID
|
1090 CG14_MCTL_PIXMODE_8
| CG14_MCTL_POWERCTL
);
1092 /* everything is CLUT1 */
1093 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++)
1094 sc
->sc_xlut
->xlut_lut
[i
] = 0;
1097 bus_space_write_1(sc
->sc_bustag
, sc
->sc_regh
,
1098 CG14_MCTL
, CG14_MCTL_ENABLEVID
|
1099 CG14_MCTL_PIXMODE_32
| CG14_MCTL_POWERCTL
);
1101 for (i
= 0; i
< CG14_CLUT_SIZE
; i
++)
1102 sc
->sc_xlut
->xlut_lut
[i
] = 0;
1105 printf("%s: can't change to depth %d\n",
1106 device_xname(sc
->sc_dev
), depth
);
1111 cg14_move_cursor(struct cgfourteen_softc
*sc
, int x
, int y
)
1115 sc
->sc_cursor
.cc_pos
.x
= x
;
1116 sc
->sc_cursor
.cc_pos
.y
= y
;
1117 pos
= ((sc
->sc_cursor
.cc_pos
.x
- sc
->sc_cursor
.cc_hot
.x
) << 16) |
1118 ((sc
->sc_cursor
.cc_pos
.y
- sc
->sc_cursor
.cc_hot
.y
) & 0xffff);
1119 bus_space_write_4(sc
->sc_bustag
, sc
->sc_regh
, CG14_CURSOR_X
, pos
);
1123 cg14_do_cursor(struct cgfourteen_softc
*sc
, struct wsdisplay_cursor
*cur
)
1125 if (cur
->which
& WSDISPLAY_CURSOR_DOCUR
) {
1127 bus_space_write_1(sc
->sc_bustag
, sc
->sc_regh
,
1128 CG14_CURSOR_CONTROL
, cur
->enable
? CG14_CRSR_ENABLE
: 0);
1130 if (cur
->which
& WSDISPLAY_CURSOR_DOHOT
) {
1132 sc
->sc_cursor
.cc_hot
.x
= cur
->hot
.x
;
1133 sc
->sc_cursor
.cc_hot
.y
= cur
->hot
.y
;
1134 cur
->which
|= WSDISPLAY_CURSOR_DOPOS
;
1136 if (cur
->which
& WSDISPLAY_CURSOR_DOPOS
) {
1138 cg14_move_cursor(sc
, cur
->pos
.x
, cur
->pos
.y
);
1140 if (cur
->which
& WSDISPLAY_CURSOR_DOCMAP
) {
1144 for (i
= 0; i
< min(cur
->cmap
.count
, 3); i
++) {
1145 val
= (cur
->cmap
.red
[i
] ) |
1146 (cur
->cmap
.green
[i
] << 8) |
1147 (cur
->cmap
.blue
[i
] << 16);
1148 bus_space_write_4(sc
->sc_bustag
, sc
->sc_regh
,
1149 CG14_CURSOR_COLOR1
+ ((i
+ cur
->cmap
.index
) << 2),
1153 if (cur
->which
& WSDISPLAY_CURSOR_DOSHAPE
) {
1154 uint32_t buffer
[32], latch
, tmp
;
1157 copyin(cur
->mask
, buffer
, 128);
1158 for (i
= 0; i
< 32; i
++) {
1160 tmp
= buffer
[i
] & 0x80808080;
1162 tmp
= buffer
[i
] & 0x40404040;
1164 tmp
= buffer
[i
] & 0x20202020;
1166 tmp
= buffer
[i
] & 0x10101010;
1168 tmp
= buffer
[i
] & 0x08080808;
1170 tmp
= buffer
[i
] & 0x04040404;
1172 tmp
= buffer
[i
] & 0x02020202;
1174 tmp
= buffer
[i
] & 0x01010101;
1176 bus_space_write_4(sc
->sc_bustag
, sc
->sc_regh
,
1177 CG14_CURSOR_PLANE0
+ (i
<< 2), latch
);
1179 copyin(cur
->image
, buffer
, 128);
1180 for (i
= 0; i
< 32; i
++) {
1182 tmp
= buffer
[i
] & 0x80808080;
1184 tmp
= buffer
[i
] & 0x40404040;
1186 tmp
= buffer
[i
] & 0x20202020;
1188 tmp
= buffer
[i
] & 0x10101010;
1190 tmp
= buffer
[i
] & 0x08080808;
1192 tmp
= buffer
[i
] & 0x04040404;
1194 tmp
= buffer
[i
] & 0x02020202;
1196 tmp
= buffer
[i
] & 0x01010101;
1198 bus_space_write_4(sc
->sc_bustag
, sc
->sc_regh
,
1199 CG14_CURSOR_PLANE1
+ (i
<< 2), latch
);