1 /* $NetBSD: cgthree.c,v 1.25 2009/09/19 07:07:43 tsutsui Exp $ */
4 * Copyright (c) 1998 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 (cgthree) 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: cgthree.c,v 1.25 2009/09/19 07:07:43 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>
59 #include <dev/sun/btreg.h>
60 #include <dev/sun/btvar.h>
61 #include <dev/sun/cgthreereg.h>
62 #include <dev/sun/cgthreevar.h>
65 #include <dev/wscons/wsconsio.h>
66 #include <dev/wsfont/wsfont.h>
67 #include <dev/rasops/rasops.h>
69 #include "opt_wsemul.h"
74 static void cgthreeunblank(device_t
);
75 static void cgthreeloadcmap(struct cgthree_softc
*, int, int);
76 static void cgthree_set_video(struct cgthree_softc
*, int);
77 static int cgthree_get_video(struct cgthree_softc
*);
79 dev_type_open(cgthreeopen
);
80 dev_type_ioctl(cgthreeioctl
);
81 dev_type_mmap(cgthreemmap
);
83 const struct cdevsw cgthree_cdevsw
= {
84 cgthreeopen
, nullclose
, noread
, nowrite
, cgthreeioctl
,
85 nostop
, notty
, nopoll
, cgthreemmap
, nokqfilter
, D_OTHER
88 /* frame buffer generic driver */
89 static struct fbdriver cgthreefbdriver
= {
90 cgthreeunblank
, cgthreeopen
, nullclose
, cgthreeioctl
, nopoll
,
91 cgthreemmap
, nokqfilter
94 /* Video control parameters */
95 struct cg3_videoctrl
{
96 unsigned char sense
; /* Monitor sense value */
97 unsigned char vctrl
[12];
99 /* Missing entries: sense 0x10, 0x30, 0x50 */
100 { 0x40, /* this happens to be my 19'' 1152x900 gray-scale monitor */
101 {0xbb, 0x2b, 0x3, 0xb, 0xb3, 0x3, 0xaf, 0x2b, 0x2, 0xa, 0xff, 0x1}
103 { 0x00, /* default? must be last */
104 {0xbb, 0x2b, 0x3, 0xb, 0xb3, 0x3, 0xaf, 0x2b, 0x2, 0xa, 0xff, 0x1}
110 #error RASTERCONSOLE and wsdisplay are mutually exclusive
113 static void cg3_setup_palette(struct cgthree_softc
*);
115 struct wsscreen_descr cgthree_defaultscreen
= {
117 0, 0, /* will be filled in -- XXX shouldn't, it's global */
119 8, 16, /* font width/height */
120 WSSCREEN_WSCOLORS
, /* capabilities */
121 NULL
/* modecookie */
124 static int cgthree_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
125 static paddr_t
cgthree_mmap(void *, void *, off_t
, int);
126 static void cgthree_init_screen(void *, struct vcons_screen
*, int, long *);
128 int cgthree_putcmap(struct cgthree_softc
*, struct wsdisplay_cmap
*);
129 int cgthree_getcmap(struct cgthree_softc
*, struct wsdisplay_cmap
*);
131 struct wsdisplay_accessops cgthree_accessops
= {
134 NULL
, /* alloc_screen */
135 NULL
, /* free_screen */
136 NULL
, /* show_screen */
137 NULL
, /* load_font */
142 const struct wsscreen_descr
*_cgthree_scrlist
[] = {
143 &cgthree_defaultscreen
146 struct wsscreen_list cgthree_screenlist
= {
147 sizeof(_cgthree_scrlist
) / sizeof(struct wsscreen_descr
*),
152 extern const u_char rasops_cmap
[768];
154 static struct vcons_screen cg3_console_screen
;
155 #endif /* NWSDISPLAY > 0 */
158 cgthreeattach(struct cgthree_softc
*sc
, const char *name
, int isconsole
)
161 struct fbdevice
*fb
= &sc
->sc_fb
;
163 struct wsemuldisplaydev_attach_args aa
;
164 struct rasops_info
*ri
= &cg3_console_screen
.scr_ri
;
165 unsigned long defattr
;
167 volatile struct fbcontrol
*fbc
= sc
->sc_fbc
;
168 volatile struct bt_regs
*bt
= &fbc
->fbc_dac
;
170 fb
->fb_driver
= &cgthreefbdriver
;
171 fb
->fb_type
.fb_cmsize
= 256;
172 fb
->fb_type
.fb_size
= fb
->fb_type
.fb_height
* fb
->fb_linebytes
;
173 printf(": %s, %d x %d", name
,
174 fb
->fb_type
.fb_width
, fb
->fb_type
.fb_height
);
176 /* Transfer video magic to board, if it's not running */
177 if ((fbc
->fbc_ctrl
& FBC_TIMING
) == 0) {
178 int sense
= (fbc
->fbc_status
& FBS_MSENSE
);
179 /* Search table for video timings fitting this monitor */
180 for (i
= 0; i
< sizeof(cg3_videoctrl
)/sizeof(cg3_videoctrl
[0]);
183 if (sense
!= cg3_videoctrl
[i
].sense
)
186 printf(" setting video ctrl");
187 for (j
= 0; j
< 12; j
++)
188 fbc
->fbc_vcontrol
[j
] =
189 cg3_videoctrl
[i
].vctrl
[j
];
190 fbc
->fbc_ctrl
|= FBC_TIMING
;
195 /* make sure we are not blanked */
196 cgthree_set_video(sc
, 1);
200 printf(" (console)\n");
207 fb_attach(fb
, isconsole
);
210 sc
->sc_width
= fb
->fb_type
.fb_width
;
211 sc
->sc_stride
= fb
->fb_type
.fb_width
;
212 sc
->sc_height
= fb
->fb_type
.fb_height
;
214 /* setup rasops and so on for wsdisplay */
215 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
217 vcons_init(&sc
->vd
, sc
, &cgthree_defaultscreen
, &cgthree_accessops
);
218 sc
->vd
.init_screen
= cgthree_init_screen
;
221 /* we mess with cg3_console_screen only once */
222 vcons_init_screen(&sc
->vd
, &cg3_console_screen
, 1,
224 cg3_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
226 cgthree_defaultscreen
.textops
= &ri
->ri_ops
;
227 cgthree_defaultscreen
.capabilities
= ri
->ri_caps
;
228 cgthree_defaultscreen
.nrows
= ri
->ri_rows
;
229 cgthree_defaultscreen
.ncols
= ri
->ri_cols
;
230 sc
->vd
.active
= &cg3_console_screen
;
231 wsdisplay_cnattach(&cgthree_defaultscreen
, ri
, 0, 0, defattr
);
234 * we're not the console so we just clear the screen and don't
235 * set up any sort of text display
237 if (cgthree_defaultscreen
.textops
== NULL
) {
240 * we want the console settings to win, so we only
241 * touch anything when we find an untouched screen
242 * definition. In this case we fill it from fb to
243 * avoid problems in case no cgthree is the console
245 ri
= &sc
->sc_fb
.fb_rinfo
;
246 cgthree_defaultscreen
.textops
= &ri
->ri_ops
;
247 cgthree_defaultscreen
.capabilities
= ri
->ri_caps
;
248 cgthree_defaultscreen
.nrows
= ri
->ri_rows
;
249 cgthree_defaultscreen
.ncols
= ri
->ri_cols
;
253 /* Initialize the default color map. */
254 cg3_setup_palette(sc
);
256 aa
.scrdata
= &cgthree_screenlist
;
257 aa
.console
= isconsole
;
258 aa
.accessops
= &cgthree_accessops
;
259 aa
.accesscookie
= &sc
->vd
;
260 config_found(sc
->sc_dev
, &aa
, wsemuldisplaydevprint
);
262 /* Initialize the default color map. */
263 bt_initcmap(&sc
->sc_cmap
, 256);
264 cgthreeloadcmap(sc
, 0, 256);
271 cgthreeopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
273 int unit
= minor(dev
);
275 if (device_lookup(&cgthree_cd
, unit
) == NULL
)
281 cgthreeioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
283 struct cgthree_softc
*sc
= device_lookup_private(&cgthree_cd
,
291 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
295 fba
= (struct fbgattr
*)data
;
296 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
297 fba
->owner
= 0; /* XXX ??? */
298 fba
->fbtype
= sc
->sc_fb
.fb_type
;
299 fba
->sattr
.flags
= 0;
300 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
301 fba
->sattr
.dev_specific
[0] = -1;
302 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
303 fba
->emu_types
[1] = -1;
307 #define p ((struct fbcmap *)data)
308 return (bt_getcmap(p
, &sc
->sc_cmap
, 256, 1));
311 /* copy to software map */
312 error
= bt_putcmap(p
, &sc
->sc_cmap
, 256, 1);
315 /* now blast them into the chip */
316 /* XXX should use retrace interrupt */
317 cgthreeloadcmap(sc
, p
->index
, p
->count
);
322 *(int *)data
= cgthree_get_video(sc
);
326 cgthree_set_video(sc
, *(int *)data
);
336 * Undo the effect of an FBIOSVIDEO that turns the video off.
339 cgthreeunblank(device_t self
)
341 struct cgthree_softc
*sc
= device_private(self
);
343 cgthree_set_video(sc
, 1);
347 cgthree_set_video(struct cgthree_softc
*sc
, int enable
)
351 sc
->sc_fbc
->fbc_ctrl
|= FBC_VENAB
;
353 sc
->sc_fbc
->fbc_ctrl
&= ~FBC_VENAB
;
357 cgthree_get_video(struct cgthree_softc
*sc
)
360 return ((sc
->sc_fbc
->fbc_ctrl
& FBC_VENAB
) != 0);
364 * Load a subset of the current (new) colormap into the Brooktree DAC.
367 cgthreeloadcmap(struct cgthree_softc
*sc
, int start
, int ncolors
)
369 volatile struct bt_regs
*bt
;
373 ip
= &sc
->sc_cmap
.cm_chip
[BT_D4M3(start
)]; /* start/4 * 3 */
374 count
= BT_D4M3(start
+ ncolors
- 1) - BT_D4M3(start
) + 3;
375 bt
= &sc
->sc_fbc
->fbc_dac
;
376 bt
->bt_addr
= BT_D4M4(start
);
382 * Return the address that would map the given device at the given
383 * offset, allowing for the given protection, or return -1 for error.
385 * The cg3 is mapped starting at 256KB, for pseudo-compatibility with
386 * the cg4 (which had an overlay plane in the first 128K and an enable
387 * plane in the next 128K). X11 uses only 256k+ region but tries to
388 * map the whole thing, so we repeatedly map the first 256K to the
389 * first page of the color screen. If someone tries to use the overlay
390 * and enable regions, they will get a surprise....
392 * As well, mapping at an offset of 0x04000000 causes the cg3 to be
393 * mapped in flat mode without the cg4 emulation.
396 cgthreemmap(dev_t dev
, off_t off
, int prot
)
398 struct cgthree_softc
*sc
= device_lookup_private(&cgthree_cd
,
401 #define START (128*1024 + 128*1024)
402 #define NOOVERLAY (0x04000000)
405 panic("cgthreemmap");
408 if ((u_int
)off
>= NOOVERLAY
)
410 else if ((u_int
)off
>= START
)
415 if (off
>= sc
->sc_fb
.fb_type
.fb_size
)
418 return (bus_space_mmap(sc
->sc_bustag
,
419 sc
->sc_paddr
, CG3REG_MEM
+ off
,
420 prot
, BUS_SPACE_MAP_LINEAR
));
426 cg3_setup_palette(struct cgthree_softc
*sc
)
431 for (i
= 0; i
< 256; i
++) {
432 sc
->sc_cmap
.cm_map
[i
][0] = rasops_cmap
[j
];
434 sc
->sc_cmap
.cm_map
[i
][1] = rasops_cmap
[j
];
436 sc
->sc_cmap
.cm_map
[i
][2] = rasops_cmap
[j
];
439 cgthreeloadcmap(sc
, 0, 256);
443 cgthree_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
446 /* we'll probably need to add more stuff here */
447 struct vcons_data
*vd
= v
;
448 struct cgthree_softc
*sc
= vd
->cookie
;
449 struct wsdisplay_fbinfo
*wdf
;
450 struct rasops_info
*ri
= &sc
->sc_fb
.fb_rinfo
;
451 struct vcons_screen
*ms
= sc
->vd
.active
;
453 case WSDISPLAYIO_GTYPE
:
454 *(u_int
*)data
= WSDISPLAY_TYPE_SUNTCX
;
456 case WSDISPLAYIO_GINFO
:
458 wdf
->height
= ri
->ri_height
;
459 wdf
->width
= ri
->ri_width
;
460 wdf
->depth
= ri
->ri_depth
;
464 case WSDISPLAYIO_GETCMAP
:
465 return cgthree_getcmap(sc
,
466 (struct wsdisplay_cmap
*)data
);
467 case WSDISPLAYIO_PUTCMAP
:
468 return cgthree_putcmap(sc
,
469 (struct wsdisplay_cmap
*)data
);
471 case WSDISPLAYIO_SMODE
:
473 int new_mode
= *(int*)data
;
474 if (new_mode
!= sc
->sc_mode
)
476 sc
->sc_mode
= new_mode
;
477 if(new_mode
== WSDISPLAYIO_MODE_EMUL
)
479 cg3_setup_palette(sc
);
480 vcons_redraw_screen(ms
);
489 cgthree_mmap(void *v
, void *vs
, off_t offset
, int prot
)
491 /* I'm not at all sure this is the right thing to do */
492 return cgthreemmap(0, offset
, prot
); /* assume minor dev 0 for now */
496 cgthree_putcmap(struct cgthree_softc
*sc
, struct wsdisplay_cmap
*cm
)
498 u_int index
= cm
->index
;
499 u_int count
= cm
->count
;
501 if (index
>= 256 || count
> 256 || index
+ count
> 256)
504 for (i
= 0; i
< count
; i
++)
506 error
= copyin(&cm
->red
[i
],
507 &sc
->sc_cmap
.cm_map
[index
+ i
][0], 1);
510 error
= copyin(&cm
->green
[i
],
511 &sc
->sc_cmap
.cm_map
[index
+ i
][1],
515 error
= copyin(&cm
->blue
[i
],
516 &sc
->sc_cmap
.cm_map
[index
+ i
][2], 1);
520 cgthreeloadcmap(sc
, index
, count
);
526 cgthree_getcmap(struct cgthree_softc
*sc
, struct wsdisplay_cmap
*cm
)
528 u_int index
= cm
->index
;
529 u_int count
= cm
->count
;
532 if (index
>= 256 || count
> 256 || index
+ count
> 256)
535 for (i
= 0; i
< count
; i
++)
537 error
= copyout(&sc
->sc_cmap
.cm_map
[index
+ i
][0],
541 error
= copyout(&sc
->sc_cmap
.cm_map
[index
+ i
][1],
545 error
= copyout(&sc
->sc_cmap
.cm_map
[index
+ i
][2],
555 cgthree_init_screen(void *cookie
, struct vcons_screen
*scr
,
556 int existing
, long *defattr
)
558 struct cgthree_softc
*sc
= cookie
;
559 struct rasops_info
*ri
= &scr
->scr_ri
;
562 ri
->ri_width
= sc
->sc_width
;
563 ri
->ri_height
= sc
->sc_height
;
564 ri
->ri_stride
= sc
->sc_stride
;
565 ri
->ri_flg
= RI_CENTER
;
567 ri
->ri_bits
= sc
->sc_fb
.fb_pixels
;
569 memset(sc
->sc_fb
.fb_pixels
, (*defattr
>> 16) & 0xff,
570 sc
->sc_stride
* sc
->sc_height
);
571 rasops_init(ri
, sc
->sc_height
/8, sc
->sc_width
/8);
572 ri
->ri_caps
= WSSCREEN_WSCOLORS
| WSSCREEN_REVERSE
;
573 rasops_reconfig(ri
, sc
->sc_height
/ ri
->ri_font
->fontheight
,
574 sc
->sc_width
/ ri
->ri_font
->fontwidth
);
579 #endif /* NWSDISPLAY > 0 */