1 /* $NetBSD: agten.c,v 1.21 2009/09/17 16:28:12 tsutsui Exp $ */
4 * Copyright (c) 2007 Michael Lorenz
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: agten.c,v 1.21 2009/09/17 16:28:12 tsutsui Exp $");
33 * a driver for the Fujitsu AG-10e SBus framebuffer
35 * this thing is Frankenstein's Monster among graphics boards.
36 * it contains three graphics chips:
37 * a GLint - 24bit stuff, double-buffered
38 * an Imagine 128 which provides an 8bit overlay
39 * a Weitek P9100 which provides WIDs
40 * so here we need to mess only with the P9100 and the I128 - for X we just
41 * hide the overlay and let the Xserver mess with the GLint
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/device.h>
49 #include <sys/mutex.h>
50 #include <sys/ioctl.h>
51 #include <sys/kernel.h>
52 #include <sys/systm.h>
55 #include <dev/sun/fbio.h>
56 #include <dev/sun/fbvar.h>
57 #include <dev/sun/btreg.h>
58 #include <dev/sun/btvar.h>
61 #include <machine/autoconf.h>
63 #include <dev/sbus/sbusvar.h>
65 #include <dev/wscons/wsconsio.h>
66 #include <dev/wscons/wsdisplayvar.h>
67 #include <dev/rasops/rasops.h>
68 #include <dev/wsfont/wsfont.h>
70 #include <dev/wscons/wsdisplay_vconsvar.h>
72 #include <dev/sbus/p9100reg.h>
73 #include <dev/ic/ibm561reg.h>
74 #include <dev/ic/i128reg.h>
75 #include <dev/ic/i128var.h>
77 #include "opt_agten.h"
80 static int agten_match(device_t
, cfdata_t
, void *);
81 static void agten_attach(device_t
, device_t
, void *);
83 static int agten_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
84 static paddr_t
agten_mmap(void *, void *, off_t
, int);
85 static void agten_init_screen(void *, struct vcons_screen
*, int, long *);
88 device_t sc_dev
; /* base device */
89 struct fbdevice sc_fb
; /* frame buffer device */
91 struct vcons_screen sc_console_screen
;
92 struct wsscreen_descr sc_defaultscreen_descr
;
93 const struct wsscreen_descr
*sc_screens
[1];
94 struct wsscreen_list sc_screenlist
;
96 bus_space_tag_t sc_bustag
;
98 bus_space_handle_t sc_i128_fbh
;
99 bus_size_t sc_i128_fbsz
;
100 bus_space_handle_t sc_i128_regh
;
101 bus_space_handle_t sc_p9100_regh
;
102 bus_addr_t sc_glint_fb
;
103 bus_addr_t sc_glint_regs
;
104 uint32_t sc_glint_fbsz
;
107 uint32_t sc_height
; /* panel width / height */
113 int sc_video
; /* video output enabled */
115 /* some /dev/fb* stuff */
118 union bt_cmap sc_cmap
; /* Brooktree color map */
122 struct vcons_data vd
;
125 CFATTACH_DECL_NEW(agten
, sizeof(struct agten_softc
),
126 agten_match
, agten_attach
, NULL
, NULL
);
129 static int agten_putcmap(struct agten_softc
*, struct wsdisplay_cmap
*);
130 static int agten_getcmap(struct agten_softc
*, struct wsdisplay_cmap
*);
131 static int agten_putpalreg(struct agten_softc
*, uint8_t, uint8_t,
133 static void agten_init(struct agten_softc
*);
134 static void agten_gfx(struct agten_softc
*);
135 static void agten_set_video(struct agten_softc
*, int);
136 static int agten_get_video(struct agten_softc
*);
138 static void agten_copycols(void *, int, int, int, int);
139 static void agten_erasecols(void *, int, int, int, long);
140 static void agten_copyrows(void *, int, int, int);
141 static void agten_eraserows(void *, int, int, long);
143 static void agten_move_cursor(struct agten_softc
*, int, int);
144 static int agten_do_cursor(struct agten_softc
*sc
,
145 struct wsdisplay_cursor
*);
146 static int agten_do_sun_cursor(struct agten_softc
*sc
,
149 static uint16_t util_interleave(uint8_t, uint8_t);
150 static uint16_t util_interleave_lin(uint8_t, uint8_t);
152 extern const u_char rasops_cmap
[768];
154 struct wsdisplay_accessops agten_accessops
= {
157 NULL
, /* alloc_screen */
158 NULL
, /* free_screen */
159 NULL
, /* show_screen */
160 NULL
, /* load_font */
167 static int agten_fb_open(dev_t
, int, int, struct lwp
*);
168 static int agten_fb_close(dev_t
, int, int, struct lwp
*);
169 static int agten_fb_ioctl(dev_t
, u_long
, void *, int, struct lwp
*);
170 static paddr_t
agten_fb_mmap(dev_t
, off_t
, int);
171 static void agten_fb_unblank(device_t
);
173 static struct fbdriver agtenfbdriver
= {
174 agten_fb_unblank
, agten_fb_open
, agten_fb_close
, agten_fb_ioctl
,
175 nopoll
, agten_fb_mmap
, nokqfilter
179 agten_write_dac(struct agten_softc
*sc
, int reg
, uint8_t val
)
181 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
,
182 0x200 + (reg
<< 2), (uint32_t)val
<< 16);
186 agten_write_idx(struct agten_softc
*sc
, int offset
)
188 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
,
189 0x200 + (IBM561_ADDR_LOW
<< 2), (offset
& 0xff) << 16);
190 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
,
191 0x200 + (IBM561_ADDR_HIGH
<< 2), ((offset
>> 8) & 0xff) << 16);
195 agten_write_dac_10(struct agten_softc
*sc
, int reg
, uint16_t val
)
197 agten_write_dac(sc
, reg
, (val
>> 2) & 0xff);
198 agten_write_dac(sc
, reg
, (val
& 0x3) << 6);
202 agten_match(device_t dev
, cfdata_t cf
, void *aux
)
204 struct sbus_attach_args
*sa
= aux
;
206 if (strcmp("PFU,aga", sa
->sa_name
) == 0)
212 agten_attach(device_t parent
, device_t dev
, void *aux
)
214 struct agten_softc
*sc
= device_private(dev
);
215 struct sbus_attach_args
*sa
= aux
;
216 struct fbdevice
*fb
= &sc
->sc_fb
;
217 struct wsemuldisplaydev_attach_args aa
;
218 struct rasops_info
*ri
;
221 int node
= sa
->sa_node
;
225 sc
->sc_defaultscreen_descr
= (struct wsscreen_descr
){
230 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
233 sc
->sc_screens
[0] = &sc
->sc_defaultscreen_descr
;
234 sc
->sc_screenlist
= (struct wsscreen_list
){1, sc
->sc_screens
};
235 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
236 sc
->sc_fb_is_open
= 0;
238 sc
->sc_bustag
= sa
->sa_bustag
;
240 sc
->sc_width
= prom_getpropint(node
, "ffb_width", 1152);
241 sc
->sc_height
= prom_getpropint(node
, "ffb_height", 900);
242 sc
->sc_depth
= prom_getpropint(node
, "ffb_depth", 8);
243 sc
->sc_stride
= sc
->sc_width
* (sc
->sc_depth
>> 3);
245 reg
= prom_getpropint(node
, "i128_fb_physaddr", -1);
246 sc
->sc_i128_fbsz
= prom_getpropint(node
, "i128_fb_size", -1);
247 if (sbus_bus_map(sc
->sc_bustag
,
248 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
+ reg
,
249 sc
->sc_stride
* sc
->sc_height
,
250 BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
,
251 &sc
->sc_i128_fbh
) != 0) {
253 aprint_error_dev(dev
, "unable to map the framebuffer\n");
256 fb
->fb_pixels
= bus_space_vaddr(sc
->sc_bustag
, sc
->sc_i128_fbh
);
258 reg
= prom_getpropint(node
, "i128_reg_physaddr", -1);
259 if (sbus_bus_map(sc
->sc_bustag
,
260 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
+ reg
,
261 0x10000, 0, &sc
->sc_i128_regh
) != 0) {
263 aprint_error_dev(dev
, "unable to map I128 registers\n");
267 reg
= prom_getpropint(node
, "p9100_reg_physaddr", -1);
268 if (sbus_bus_map(sc
->sc_bustag
,
269 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
+ reg
,
270 0x8000, 0, &sc
->sc_p9100_regh
) != 0) {
272 aprint_error_dev(dev
, "unable to map P9100 registers\n");
276 reg
= prom_getpropint(node
, "glint_fb0_physaddr", -1);
277 sc
->sc_glint_fb
= sbus_bus_addr(sc
->sc_bustag
,
278 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
+ reg
);
279 sc
->sc_glint_fbsz
= prom_getpropint(node
, "glint_lb_size", -1);
280 reg
= prom_getpropint(node
, "glint_reg_physaddr", -1);
281 sc
->sc_glint_regs
= sbus_bus_addr(sc
->sc_bustag
,
282 sa
->sa_reg
[0].oa_space
, sa
->sa_reg
[0].oa_base
+ reg
);
285 bus_intr_establish(sc
->sc_bustag
, sa
->sa_pri
, IPL_BIO
,
289 printf(": %dx%d\n", sc
->sc_width
, sc
->sc_height
);
292 console
= fb_is_console(node
);
294 vcons_init(&sc
->vd
, sc
, &sc
->sc_defaultscreen_descr
,
296 sc
->vd
.init_screen
= agten_init_screen
;
298 ri
= &sc
->sc_console_screen
.scr_ri
;
301 vcons_init_screen(&sc
->vd
, &sc
->sc_console_screen
, 1,
303 sc
->sc_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
305 sc
->sc_defaultscreen_descr
.textops
= &ri
->ri_ops
;
306 sc
->sc_defaultscreen_descr
.capabilities
= ri
->ri_caps
;
307 sc
->sc_defaultscreen_descr
.nrows
= ri
->ri_rows
;
308 sc
->sc_defaultscreen_descr
.ncols
= ri
->ri_cols
;
309 wsdisplay_cnattach(&sc
->sc_defaultscreen_descr
, ri
, 0, 0,
311 i128_rectfill(sc
->sc_bustag
, sc
->sc_i128_regh
, 0, 0,
312 sc
->sc_width
, sc
->sc_height
,
313 ri
->ri_devcmap
[(defattr
>> 16) & 0xff]);
314 vcons_replay_msgbuf(&sc
->sc_console_screen
);
317 * since we're not the console we can postpone the rest
318 * until someone actually allocates a screen for us
322 /* Initialize the default color map. */
324 aa
.console
= console
;
325 aa
.scrdata
= &sc
->sc_screenlist
;
326 aa
.accessops
= &agten_accessops
;
327 aa
.accesscookie
= &sc
->vd
;
329 config_found(sc
->sc_dev
, &aa
, wsemuldisplaydevprint
);
331 fb
->fb_driver
= &agtenfbdriver
;
332 fb
->fb_device
= sc
->sc_dev
;
333 fb
->fb_flags
= device_cfdata(sc
->sc_dev
)->cf_flags
& FB_USERMASK
;
334 fb
->fb_type
.fb_type
= FBTYPE_AG10E
;
335 fb
->fb_type
.fb_cmsize
= 256; /* doesn't matter, we're always 24bit */
336 fb
->fb_type
.fb_size
= sc
->sc_glint_fbsz
;
337 fb
->fb_type
.fb_width
= sc
->sc_width
;
338 fb
->fb_type
.fb_height
= sc
->sc_height
;
339 fb
->fb_type
.fb_depth
= 32;
340 fb
->fb_linebytes
= sc
->sc_stride
<< 2;
341 fb_attach(fb
, console
);
342 agten_set_video(sc
, 1); /* make sure video's on */
346 agten_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
349 struct vcons_data
*vd
= v
;
350 struct agten_softc
*sc
= vd
->cookie
;
351 struct wsdisplay_fbinfo
*wdf
;
352 struct vcons_screen
*ms
= vd
->active
;
356 case WSDISPLAYIO_GTYPE
:
357 *(u_int
*)data
= WSDISPLAY_TYPE_AG10
;
360 case WSDISPLAYIO_GINFO
:
364 wdf
->height
= ms
->scr_ri
.ri_height
;
365 wdf
->width
= ms
->scr_ri
.ri_width
;
370 case WSDISPLAYIO_GVIDEO
:
371 *(int *)data
= sc
->sc_video
;
374 case WSDISPLAYIO_SVIDEO
:
375 agten_set_video(sc
, *(int *)data
);
378 case WSDISPLAYIO_GETCMAP
:
379 return agten_getcmap(sc
,
380 (struct wsdisplay_cmap
*)data
);
382 case WSDISPLAYIO_PUTCMAP
:
383 return agten_putcmap(sc
,
384 (struct wsdisplay_cmap
*)data
);
386 case WSDISPLAYIO_LINEBYTES
:
387 *(u_int
*)data
= sc
->sc_stride
<< 2;
390 case WSDISPLAYIO_SMODE
:
392 int new_mode
= *(int*)data
;
393 if (new_mode
!= sc
->sc_mode
) {
394 sc
->sc_mode
= new_mode
;
395 if(new_mode
== WSDISPLAYIO_MODE_EMUL
) {
397 vcons_redraw_screen(ms
);
405 case WSDISPLAYIO_GCURPOS
:
407 struct wsdisplay_curpos
*cp
= (void *)data
;
409 cp
->x
= sc
->sc_cursor_x
;
410 cp
->y
= sc
->sc_cursor_y
;
414 case WSDISPLAYIO_SCURPOS
:
416 struct wsdisplay_curpos
*cp
= (void *)data
;
418 agten_move_cursor(sc
, cp
->x
, cp
->y
);
422 case WSDISPLAYIO_GCURMAX
:
424 struct wsdisplay_curpos
*cp
= (void *)data
;
431 case WSDISPLAYIO_SCURSOR
:
433 struct wsdisplay_cursor
*cursor
= (void *)data
;
435 return agten_do_cursor(sc
, cursor
);
442 agten_mmap(void *v
, void *vs
, off_t offset
, int prot
)
444 struct vcons_data
*vd
= v
;
445 struct agten_softc
*sc
= vd
->cookie
;
447 if (offset
< sc
->sc_glint_fbsz
)
448 return bus_space_mmap(sc
->sc_bustag
, sc
->sc_glint_fb
, offset
,
449 prot
, BUS_SPACE_MAP_LINEAR
);
454 agten_init_screen(void *cookie
, struct vcons_screen
*scr
,
455 int existing
, long *defattr
)
457 struct agten_softc
*sc
= cookie
;
458 struct rasops_info
*ri
= &scr
->scr_ri
;
460 ri
->ri_depth
= sc
->sc_depth
;
461 ri
->ri_width
= sc
->sc_width
;
462 ri
->ri_height
= sc
->sc_height
;
463 ri
->ri_stride
= sc
->sc_stride
;
464 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
466 ri
->ri_bits
= (char *)sc
->sc_fb
.fb_pixels
;
469 ri
->ri_flg
|= RI_CLEAR
;
472 rasops_init(ri
, sc
->sc_height
/ 8, sc
->sc_width
/ 8);
473 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
475 rasops_reconfig(ri
, sc
->sc_height
/ ri
->ri_font
->fontheight
,
476 sc
->sc_width
/ ri
->ri_font
->fontwidth
);
479 ri
->ri_ops
.copyrows
= agten_copyrows
;
480 ri
->ri_ops
.eraserows
= agten_eraserows
;
481 ri
->ri_ops
.copycols
= agten_copycols
;
482 ri
->ri_ops
.erasecols
= agten_erasecols
;
487 agten_putcmap(struct agten_softc
*sc
, struct wsdisplay_cmap
*cm
)
489 u_int index
= cm
->index
;
490 u_int count
= cm
->count
;
492 u_char rbuf
[256], gbuf
[256], bbuf
[256];
495 if (cm
->index
>= 256 || cm
->count
> 256 ||
496 (cm
->index
+ cm
->count
) > 256)
498 error
= copyin(cm
->red
, &rbuf
[index
], count
);
501 error
= copyin(cm
->green
, &gbuf
[index
], count
);
504 error
= copyin(cm
->blue
, &bbuf
[index
], count
);
512 for (i
= 0; i
< count
; i
++) {
513 agten_putpalreg(sc
, index
, *r
, *g
, *b
);
521 agten_getcmap(struct agten_softc
*sc
, struct wsdisplay_cmap
*cm
)
523 u_int index
= cm
->index
;
524 u_int count
= cm
->count
;
526 uint8_t red
[256], green
[256], blue
[256];
528 if (index
>= 255 || count
> 256 || index
+ count
> 256)
532 while (i
< (index
+ count
)) {
533 red
[i
] = sc
->sc_cmap
.cm_map
[i
][0];
534 green
[i
] = sc
->sc_cmap
.cm_map
[i
][1];
535 blue
[i
] = sc
->sc_cmap
.cm_map
[i
][2];
538 error
= copyout(&red
[index
], cm
->red
, count
);
541 error
= copyout(&green
[index
], cm
->green
, count
);
544 error
= copyout(&blue
[index
], cm
->blue
, count
);
552 agten_putpalreg(struct agten_softc
*sc
, uint8_t idx
, uint8_t r
, uint8_t g
,
556 sc
->sc_cmap
.cm_map
[idx
][0] = r
;
557 sc
->sc_cmap
.cm_map
[idx
][1] = g
;
558 sc
->sc_cmap
.cm_map
[idx
][2] = b
;
559 agten_write_idx(sc
, IBM561_CMAP_TABLE
+ idx
);
560 agten_write_dac(sc
, IBM561_CMD_CMAP
, r
);
561 agten_write_dac(sc
, IBM561_CMD_CMAP
, g
);
562 agten_write_dac(sc
, IBM561_CMD_CMAP
, b
);
567 agten_init(struct agten_softc
*sc
)
571 volatile uint32_t junk
;
573 /* first we set up the colour map */
575 for (i
= 0; i
< 256; i
++) {
577 agten_putpalreg(sc
, i
, rasops_cmap
[j
], rasops_cmap
[j
+ 1],
582 /* then we set up a linear LUT for 24bit colour */
583 agten_write_idx(sc
, IBM561_CMAP_TABLE
+ 256);
584 for (i
= 0; i
< 256; i
++) {
585 agten_write_dac(sc
, IBM561_CMD_CMAP
, i
);
586 agten_write_dac(sc
, IBM561_CMD_CMAP
, i
);
587 agten_write_dac(sc
, IBM561_CMD_CMAP
, i
);
590 /* and the linear gamma maps */
591 agten_write_idx(sc
, IBM561_RED_GAMMA_TABLE
);
592 for (i
= 0; i
< 0x3ff; i
+= 4)
593 agten_write_dac_10(sc
, IBM561_CMD_GAMMA
, i
);
594 agten_write_idx(sc
, IBM561_GREEN_GAMMA_TABLE
);
595 for (i
= 0; i
< 0x3ff; i
+= 4)
596 agten_write_dac_10(sc
, IBM561_CMD_GAMMA
, i
);
597 agten_write_idx(sc
, IBM561_BLUE_GAMMA_TABLE
);
598 for (i
= 0; i
< 0x3ff; i
+= 4)
599 agten_write_dac_10(sc
, IBM561_CMD_GAMMA
, i
);
601 /* enable outputs, RGB mode */
602 agten_write_idx(sc
, IBM561_CONFIG_REG3
);
603 agten_write_dac(sc
, IBM561_CMD
, CR3_SERIAL_CLK_CTRL
| CR3_RGB
);
605 /* MUX 4:1 basic, 8bit overlay, 8bit WIDs */
606 agten_write_idx(sc
, IBM561_CONFIG_REG1
);
607 agten_write_dac(sc
, IBM561_CMD
, CR1_MODE_4_1_BASIC
| CR1_OVL_8BPP
|
610 /* use external clock, enable video output */
611 agten_write_idx(sc
, IBM561_CONFIG_REG2
);
612 agten_write_dac(sc
, IBM561_CMD
, CR2_ENABLE_CLC
| CR2_PLL_REF_SELECT
|
613 CR2_PIXEL_CLOCK_SELECT
| CR2_ENABLE_RGB_OUTPUT
);
615 /* now set up some window attributes */
618 * direct colour, 24 bit, transparency off, LUT from 0x100
619 * we need to use direct colour and a linear LUT because for some
620 * reason true color mode gives messed up colours
622 agten_write_idx(sc
, IBM561_FB_WINTYPE
);
623 agten_write_dac_10(sc
, IBM561_CMD_FB_WAT
, 0x100 | FB_PIXEL_24BIT
|
626 /* use gamma LUTs, no crosshair, 0 is transparent */
627 agten_write_idx(sc
, IBM561_AUXFB_WINTYPE
);
628 agten_write_dac(sc
, IBM561_CMD_FB_WAT
, 0x0);
630 /* overlay is 8 bit, opaque */
631 agten_write_idx(sc
, IBM561_OL_WINTYPE
);
632 agten_write_dac_10(sc
, IBM561_CMD_FB_WAT
, 0x00);
634 /* now we fill the WID fb with zeroes */
636 srcw
= sc
->sc_width
<< 16 | sc
->sc_height
;
637 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, FOREGROUND_COLOR
,
639 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, BACKGROUND_COLOR
,
641 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, RASTER_OP
, ROP_PAT
);
642 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, COORD_INDEX
, 0);
643 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, RECT_RTW_XY
, src
);
644 bus_space_write_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, RECT_RTW_XY
, srcw
);
645 junk
= bus_space_read_4(sc
->sc_bustag
, sc
->sc_p9100_regh
, COMMAND_QUAD
);
647 /* initialize the cursor registers */
649 /* initialize the Imagine 128 */
650 i128_init(sc
->sc_bustag
, sc
->sc_i128_regh
, sc
->sc_stride
, 8);
654 agten_gfx(struct agten_softc
*sc
)
656 /* enable overlay transparency on colour 0x00 */
657 agten_write_idx(sc
, IBM561_OL_WINTYPE
);
658 agten_write_dac_10(sc
, IBM561_CMD_FB_WAT
, OL_MODE_TRANSP_ENABLE
);
660 /* then blit the overlay full of 0x00 */
661 i128_rectfill(sc
->sc_bustag
, sc
->sc_i128_regh
, 0, 0, sc
->sc_width
,
664 /* ... so we can see the 24bit framebuffer */
668 agten_set_video(struct agten_softc
*sc
, int flag
)
671 CR2_ENABLE_CLC
| CR2_PLL_REF_SELECT
| CR2_PIXEL_CLOCK_SELECT
;
673 if (flag
== sc
->sc_video
)
676 agten_write_idx(sc
, IBM561_CONFIG_REG2
);
677 agten_write_dac(sc
, IBM561_CMD
, flag
? reg
| CR2_ENABLE_RGB_OUTPUT
:
684 agten_get_video(struct agten_softc
*sc
)
691 agten_copycols(void *cookie
, int row
, int srccol
, int dstcol
, int ncols
)
693 struct rasops_info
*ri
= cookie
;
694 struct vcons_screen
*scr
= ri
->ri_hw
;
695 struct agten_softc
*sc
= scr
->scr_cookie
;
696 int32_t xs
, xd
, y
, width
, height
;
698 xs
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* srccol
;
699 xd
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* dstcol
;
700 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
701 width
= ri
->ri_font
->fontwidth
* ncols
;
702 height
= ri
->ri_font
->fontheight
;
703 i128_bitblt(sc
->sc_bustag
, sc
->sc_i128_regh
, xs
, y
, xd
, y
, width
,
708 agten_erasecols(void *cookie
, int row
, int startcol
, int ncols
, long fillattr
)
710 struct rasops_info
*ri
= cookie
;
711 struct vcons_screen
*scr
= ri
->ri_hw
;
712 struct agten_softc
*sc
= scr
->scr_cookie
;
713 int32_t x
, y
, width
, height
, bg
;
715 x
= ri
->ri_xorigin
+ ri
->ri_font
->fontwidth
* startcol
;
716 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
717 width
= ri
->ri_font
->fontwidth
* ncols
;
718 height
= ri
->ri_font
->fontheight
;
719 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
720 i128_rectfill(sc
->sc_bustag
, sc
->sc_i128_regh
, x
, y
, width
, height
, bg
);
724 agten_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
726 struct rasops_info
*ri
= cookie
;
727 struct vcons_screen
*scr
= ri
->ri_hw
;
728 struct agten_softc
*sc
= scr
->scr_cookie
;
729 int32_t x
, ys
, yd
, width
, height
;
732 ys
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* srcrow
;
733 yd
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* dstrow
;
734 width
= ri
->ri_emuwidth
;
735 height
= ri
->ri_font
->fontheight
* nrows
;
736 i128_bitblt(sc
->sc_bustag
, sc
->sc_i128_regh
, x
, ys
, x
, yd
, width
,
741 agten_eraserows(void *cookie
, int row
, int nrows
, long fillattr
)
743 struct rasops_info
*ri
= cookie
;
744 struct vcons_screen
*scr
= ri
->ri_hw
;
745 struct agten_softc
*sc
= scr
->scr_cookie
;
746 int32_t x
, y
, width
, height
, bg
;
748 if ((row
== 0) && (nrows
== ri
->ri_rows
)) {
750 width
= ri
->ri_width
;
751 height
= ri
->ri_height
;
754 y
= ri
->ri_yorigin
+ ri
->ri_font
->fontheight
* row
;
755 width
= ri
->ri_emuwidth
;
756 height
= ri
->ri_font
->fontheight
* nrows
;
758 bg
= (uint32_t)ri
->ri_devcmap
[(fillattr
>> 16) & 0xff];
759 i128_rectfill(sc
->sc_bustag
, sc
->sc_i128_regh
, x
, y
, width
, height
, bg
);
763 agten_move_cursor(struct agten_softc
*sc
, int x
, int y
)
768 agten_write_idx(sc
, IBM561_CURSOR_X_REG
);
769 agten_write_dac(sc
, IBM561_CMD
, x
& 0xff);
770 agten_write_dac(sc
, IBM561_CMD
, (x
>> 8) & 0xff);
771 agten_write_dac(sc
, IBM561_CMD
, y
& 0xff);
772 agten_write_dac(sc
, IBM561_CMD
, (y
>> 8) & 0xff);
776 agten_do_cursor(struct agten_softc
*sc
, struct wsdisplay_cursor
*cur
)
778 if (cur
->which
& WSDISPLAY_CURSOR_DOCUR
) {
780 agten_write_idx(sc
, IBM561_CURS_CNTL_REG
);
781 agten_write_dac(sc
, IBM561_CMD
, cur
->enable
?
784 if (cur
->which
& WSDISPLAY_CURSOR_DOHOT
) {
786 agten_write_idx(sc
, IBM561_HOTSPOT_X_REG
);
787 agten_write_dac(sc
, IBM561_CMD
, cur
->hot
.x
);
788 agten_write_dac(sc
, IBM561_CMD
, cur
->hot
.y
);
790 if (cur
->which
& WSDISPLAY_CURSOR_DOPOS
) {
792 agten_move_cursor(sc
, cur
->pos
.x
, cur
->pos
.y
);
794 if (cur
->which
& WSDISPLAY_CURSOR_DOCMAP
) {
797 agten_write_idx(sc
, IBM561_CURSOR_LUT
+ cur
->cmap
.index
+ 2);
798 for (i
= 0; i
< cur
->cmap
.count
; i
++) {
799 agten_write_dac(sc
, IBM561_CMD_CMAP
, cur
->cmap
.red
[i
]);
800 agten_write_dac(sc
, IBM561_CMD_CMAP
,
802 agten_write_dac(sc
, IBM561_CMD_CMAP
, cur
->cmap
.blue
[i
]);
805 if (cur
->which
& WSDISPLAY_CURSOR_DOSHAPE
) {
809 agten_write_idx(sc
, IBM561_CURSOR_BITMAP
);
810 for (i
= 0; i
< 512; i
++) {
811 tmp
= util_interleave(cur
->mask
[i
], cur
->image
[i
]);
812 agten_write_dac(sc
, IBM561_CMD
, (tmp
>> 8) & 0xff);
813 agten_write_dac(sc
, IBM561_CMD
, tmp
& 0xff);
820 agten_do_sun_cursor(struct agten_softc
*sc
, struct fbcursor
*cur
)
822 if (cur
->set
& FB_CUR_SETCUR
) {
824 agten_write_idx(sc
, IBM561_CURS_CNTL_REG
);
825 agten_write_dac(sc
, IBM561_CMD
, cur
->enable
?
828 if (cur
->set
& FB_CUR_SETHOT
) {
830 agten_write_idx(sc
, IBM561_HOTSPOT_X_REG
);
831 agten_write_dac(sc
, IBM561_CMD
, cur
->hot
.x
);
832 agten_write_dac(sc
, IBM561_CMD
, cur
->hot
.y
);
834 if (cur
->set
& FB_CUR_SETPOS
) {
836 agten_move_cursor(sc
, cur
->pos
.x
, cur
->pos
.y
);
838 if (cur
->set
& FB_CUR_SETCMAP
) {
841 agten_write_idx(sc
, IBM561_CURSOR_LUT
+ cur
->cmap
.index
+ 2);
842 for (i
= 0; i
< cur
->cmap
.count
; i
++) {
843 agten_write_dac(sc
, IBM561_CMD_CMAP
, cur
->cmap
.red
[i
]);
844 agten_write_dac(sc
, IBM561_CMD_CMAP
,
846 agten_write_dac(sc
, IBM561_CMD_CMAP
, cur
->cmap
.blue
[i
]);
849 if (cur
->set
& FB_CUR_SETSHAPE
) {
853 agten_write_idx(sc
, IBM561_CURSOR_BITMAP
);
854 for (i
= 0; i
< 512; i
++) {
855 tmp
= util_interleave_lin(cur
->mask
[i
], cur
->image
[i
]);
856 agten_write_dac(sc
, IBM561_CMD
, (tmp
>> 8) & 0xff);
857 agten_write_dac(sc
, IBM561_CMD
, tmp
& 0xff);
864 util_interleave(uint8_t b1
, uint8_t b2
)
868 uint16_t mask
= 0x8000;
869 uint8_t mask8
= 0x01;
871 for (i
= 0; i
< 8; i
++) {
884 util_interleave_lin(uint8_t b1
, uint8_t b2
)
888 uint16_t mask
= 0x8000;
889 uint8_t mask8
= 0x80;
891 for (i
= 0; i
< 8; i
++) {
903 /* and now the /dev/fb* stuff */
905 agten_fb_unblank(device_t dev
)
907 struct agten_softc
*sc
= device_private(dev
);
910 agten_set_video(sc
, 1);
914 agten_fb_open(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
916 struct agten_softc
*sc
;
918 sc
= device_lookup_private(&agten_cd
, minor(dev
));
921 if (sc
->sc_fb_is_open
)
931 agten_fb_close(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
933 struct agten_softc
*sc
;
935 sc
= device_lookup_private(&agten_cd
, minor(dev
));
938 if (sc
->sc_fb_is_open
< 0)
939 sc
->sc_fb_is_open
= 0;
941 if (sc
->sc_fb_is_open
== 0) {
943 vcons_redraw_screen(sc
->vd
.active
);
950 agten_fb_ioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
952 struct agten_softc
*sc
= device_lookup_private(&agten_cd
, minor(dev
));
959 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
963 fba
= (struct fbgattr
*)data
;
964 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
965 fba
->owner
= 0; /* XXX ??? */
966 fba
->fbtype
= sc
->sc_fb
.fb_type
;
967 fba
->sattr
.flags
= 0;
968 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
969 fba
->sattr
.dev_specific
[0] = -1;
970 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
971 fba
->emu_types
[1] = -1;
975 #define p ((struct fbcmap *)data)
976 return (bt_getcmap(p
, &sc
->sc_cmap
, 256, 1));
979 /* copy to software map */
980 error
= bt_putcmap(p
, &sc
->sc_cmap
, 256, 1);
983 /* now blast them into the chip */
984 /* don't bother - we're 24bit */
989 *(int *)data
= agten_get_video(sc
);
993 agten_set_video(sc
, *(int *)data
);
996 /* these are for both FBIOSCURSOR and FBIOGCURSOR */
997 #define p ((struct fbcursor *)data)
998 #define pc (&sc->sc_cursor)
1001 /* does anyone use this ioctl?! */
1002 p
->set
= FB_CUR_SETALL
; /* close enough, anyway */
1004 p
->pos
.x
= sc
->sc_cursor_x
;
1005 p
->pos
.y
= sc
->sc_cursor_y
;
1011 agten_do_sun_cursor(sc
, p
);
1019 struct fbcurpos
*cp
= (struct fbcurpos
*)data
;
1020 cp
->x
= sc
->sc_cursor_x
;
1021 cp
->y
= sc
->sc_cursor_y
;
1027 struct fbcurpos
*cp
= (struct fbcurpos
*)data
;
1028 agten_move_cursor(sc
, cp
->x
, cp
->y
);
1033 /* max cursor size is 64x64 */
1034 ((struct fbcurpos
*)data
)->x
= 64;
1035 ((struct fbcurpos
*)data
)->y
= 64;
1045 agten_fb_mmap(dev_t dev
, off_t off
, int prot
)
1047 struct agten_softc
*sc
= device_lookup_private(&agten_cd
, minor(dev
));
1050 * mappings are subject to change
1051 * for now we put the framebuffer at offset 0 and the GLint registers
1052 * right after that. We may want to expose more register ranges and
1053 * probably will want to map the 2nd framebuffer as well
1059 if (off
>= sc
->sc_glint_fbsz
+ 0x10000)
1062 if (off
< sc
->sc_glint_fbsz
) {
1063 return (bus_space_mmap(sc
->sc_bustag
,
1067 BUS_SPACE_MAP_LINEAR
));
1070 off
-= sc
->sc_glint_fbsz
;
1071 if (off
< 0x10000) {
1072 return (bus_space_mmap(sc
->sc_bustag
,
1076 BUS_SPACE_MAP_LINEAR
));