Home | History | Annotate | Line # | Download | only in dev
fb_elb.c revision 1.1
      1 /*	$NetBSD: fb_elb.c,v 1.1 2003/03/11 10:57:57 hannken Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Juergen Hannken-Illjes.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *      This product includes software developed by the NetBSD
     21  *      Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/param.h>
     40 #include <sys/conf.h>
     41 #include <sys/device.h>
     42 #include <sys/ioctl.h>
     43 #include <sys/malloc.h>
     44 #include <sys/systm.h>
     45 
     46 #include <dev/wscons/wsconsio.h>
     47 #include <dev/wscons/wsdisplayvar.h>
     48 #include <dev/rasops/rasops.h>
     49 
     50 #include <machine/explora.h>
     51 #include <machine/bus.h>
     52 
     53 #include <evbppc/explora/dev/elbvar.h>
     54 
     55 #define FB_NPORTS		65536
     56 
     57 struct fb_dev {
     58 	void *fb_vram;
     59 	bus_space_tag_t fb_iot;
     60 	bus_space_handle_t fb_ioh;
     61 	struct rasops_info fb_ri;
     62 };
     63 
     64 struct fb_elb_softc {
     65 	struct device sc_dev;
     66 	struct fb_dev *sc_fb;
     67 	int sc_nscreens;
     68 };
     69 
     70 static int	fb_elb_probe(struct device *, struct cfdata *, void *);
     71 static void	fb_elb_attach(struct device *, struct device *, void *);
     72 void		fb_cnattach(bus_space_tag_t, bus_addr_t, void *);
     73 static void	fb_init(struct fb_dev *, int);
     74 static int	fb_ioctl(void *, u_long, caddr_t, int, struct proc *);
     75 static paddr_t	fb_mmap(void *, off_t, int);
     76 static int	fb_alloc_screen(void *, const struct wsscreen_descr *, void **,
     77                     int *, int *, long *);
     78 static void	fb_free_screen(void *, void *);
     79 static int	fb_show_screen(void *, void *, int, void (*)(void *, int, int),
     80                     void *);
     81 
     82 static void	s3_init(struct fb_dev *, int *, int *);
     83 
     84 static struct fb_dev console_dev;
     85 
     86 static struct wsdisplay_accessops accessops = {
     87 	fb_ioctl,
     88 	fb_mmap,
     89 	fb_alloc_screen,
     90 	fb_free_screen,
     91 	fb_show_screen,
     92 	NULL
     93 };
     94 
     95 static struct wsscreen_descr stdscreen = {
     96 	"std",
     97 	0, 0,
     98 	0,
     99 	0, 0,
    100 	0
    101 };
    102 
    103 static const struct wsscreen_descr *scrlist[] = {
    104 	&stdscreen
    105 };
    106 
    107 static struct wsscreen_list screenlist = {
    108 	sizeof(scrlist)/sizeof(scrlist[0]), scrlist
    109 };
    110 
    111 CFATTACH_DECL(fb_elb, sizeof(struct fb_elb_softc),
    112     fb_elb_probe, fb_elb_attach, NULL, NULL);
    113 
    114 static int
    115 fb_elb_probe(struct device *parent, struct cfdata *cf, void *aux)
    116 {
    117 	struct elb_attach_args *oaa = aux;
    118 
    119 	if (strcmp(oaa->elb_name, cf->cf_name) != 0)
    120 		return 0;
    121 
    122 	return (1);
    123 }
    124 
    125 static void
    126 fb_elb_attach(struct device *parent, struct device *self, void *aux)
    127 {
    128 	struct fb_elb_softc *sc = (void *)self;
    129 	struct elb_attach_args *eaa = aux;
    130 	struct wsemuldisplaydev_attach_args waa;
    131 	struct rasops_info *ri;
    132 	bus_space_handle_t ioh;
    133 	int is_console;
    134 
    135 	is_console = ((void *)eaa->elb_base == console_dev.fb_vram);
    136 
    137 	if (is_console) {
    138 		sc->sc_fb = &console_dev;
    139 	} else {
    140 		sc->sc_fb = malloc(sizeof(struct fb_dev), M_DEVBUF, M_WAITOK);
    141 		memset(sc->sc_fb, 0, sizeof(struct fb_dev));
    142 	}
    143 
    144 	sc->sc_fb->fb_iot = eaa->elb_bt;
    145 	bus_space_map(sc->sc_fb->fb_iot, eaa->elb_base, SIZE_FB,
    146 	    BUS_SPACE_MAP_LINEAR, &ioh);
    147 	sc->sc_fb->fb_vram = bus_space_vaddr(sc->sc_fb->fb_iot, ioh);
    148 	bus_space_map(sc->sc_fb->fb_iot, eaa->elb_base2, FB_NPORTS,
    149 	    0, &sc->sc_fb->fb_ioh);
    150 
    151 	fb_init(sc->sc_fb, !is_console);
    152 
    153 	ri = &sc->sc_fb->fb_ri;
    154 
    155 	printf(": %d x %d\n", ri->ri_rows, ri->ri_cols);
    156 
    157 	waa.console = is_console;
    158 	waa.scrdata = &screenlist;
    159 	waa.accessops = &accessops;
    160 	waa.accesscookie = sc;
    161 
    162 	config_found_sm(self, &waa, wsemuldisplaydevprint, NULL);
    163 }
    164 
    165 static void
    166 fb_init(struct fb_dev *fb, int full)
    167 {
    168 	struct rasops_info *ri = &fb->fb_ri;
    169 
    170 	if (full) {
    171 		s3_init(fb, &ri->ri_width, &ri->ri_height);
    172 		ri->ri_depth = 8;
    173 		ri->ri_stride = ri->ri_width;
    174 		ri->ri_bits = fb->fb_vram;
    175 		ri->ri_flg = RI_CENTER;
    176 
    177 		rasops_init(ri, 500, 500);
    178 	} else {
    179 		ri->ri_origbits = fb->fb_vram;	/*XXX*/
    180 		rasops_reconfig(ri, 500, 500);
    181 	}
    182 
    183 	stdscreen.nrows = ri->ri_rows;
    184 	stdscreen.ncols = ri->ri_cols;
    185 	stdscreen.textops = &ri->ri_ops;
    186 	stdscreen.capabilities = ri->ri_caps;
    187 }
    188 
    189 static int
    190 fb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    191 {
    192 	struct fb_elb_softc *sc = v;
    193 	struct rasops_info *ri = &sc->sc_fb->fb_ri;
    194 	struct wsdisplay_fbinfo *wdf;
    195 
    196 	switch (cmd) {
    197 	case WSDISPLAYIO_GTYPE:
    198 		*(int *)data = WSDISPLAY_TYPE_UNKNOWN;	/* XXX */
    199 		return(0);
    200 
    201 	case WSDISPLAYIO_GINFO:
    202 		wdf = (void *)data;
    203 		wdf->height = ri->ri_height;
    204 		wdf->width = ri->ri_width;
    205 		wdf->depth = ri->ri_depth;
    206 		wdf->cmsize = 16; /*XXX*/
    207 		return(0);
    208 
    209 	case WSDISPLAYIO_SVIDEO:
    210 	case WSDISPLAYIO_GETCMAP:
    211 	case WSDISPLAYIO_PUTCMAP:
    212 		break;
    213 	}
    214 
    215 	return(EPASSTHROUGH);
    216 }
    217 
    218 static paddr_t
    219 fb_mmap(void *v, off_t offset, int prot)
    220 {
    221 	return -1;
    222 }
    223 
    224 static int
    225 fb_alloc_screen(void *v, const struct wsscreen_descr *scrdesc, void **cookiep,
    226     int *ccolp, int *crowp, long *attrp)
    227 {
    228 	struct fb_elb_softc *sc = v;
    229 	struct rasops_info *ri = &sc->sc_fb->fb_ri;
    230 
    231 	if (sc->sc_nscreens > 0)
    232 		return ENOMEM;
    233 
    234 	*cookiep = ri;
    235 	*ccolp = *crowp = 0;
    236 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, attrp);
    237 	sc->sc_nscreens++;
    238 
    239 	return(0);
    240 }
    241 
    242 static void
    243 fb_free_screen(void *v, void *cookie)
    244 {
    245 	struct fb_elb_softc *sc = v;
    246 
    247 	if (sc->sc_fb == &console_dev)
    248 		panic("fb_free_screen: freeing console");
    249 
    250 	sc->sc_nscreens--;
    251 }
    252 
    253 static int
    254 fb_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
    255     void *cbarg)
    256 {
    257 	return(0);
    258 }
    259 
    260 void
    261 fb_cnattach(bus_space_tag_t iot, bus_addr_t iobase, void *vram)
    262 {
    263 	struct rasops_info *ri = &console_dev.fb_ri;
    264 	long defattr;
    265 
    266 	console_dev.fb_iot = iot;
    267 	console_dev.fb_ioh = iobase;
    268 	console_dev.fb_vram = vram;
    269 
    270 	fb_init(&console_dev, 1);
    271 
    272 	(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
    273 
    274 	wsdisplay_cnattach(&stdscreen, ri, 0, 0, defattr);
    275 }
    276 
    277 /*
    278  * S3 support routines
    279  */
    280 
    281 #define S3_CRTC_INDEX		0x83d4
    282 #define S3_CRTC_DATA		0x83d5
    283 
    284 #define S3_DAC_RD_INDEX		0x83c7
    285 #define S3_DAC_WR_INDEX		0x83c8
    286 #define S3_DAC_DATA		0x83c9
    287 
    288 #define CMAP_SIZE		256
    289 
    290 static u_int8_t default_cmap[] = {
    291 	/* black */		  0,   0,   0,
    292 	/* blue */		  0,   0, 192,
    293 	/* green */		  0, 192,   0,
    294 	/* cyan */		  0, 192, 192,
    295 	/* red */		192,   0,   0,
    296 	/* magenta */		192,   0, 192,
    297 	/* brown */		192, 192,   0,
    298 	/* lightgrey */		212, 208, 200,
    299 	/* darkgrey */		200, 192, 188,
    300 	/* lightblue */		  0,   0, 255,
    301 	/* lightgreen */	  0, 255,   0,
    302 	/* lightcyan */		  0, 255, 255,
    303 	/* lightred */		255,   0,   0,
    304 	/* lightmagenta */	255,   0, 255,
    305 	/* yellow */		255, 255,   0,
    306 	/* white */		255, 255, 255,
    307 };
    308 
    309 static void
    310 s3_init(struct fb_dev *fb, int *width, int *height)
    311 {
    312 	int i, j, w, h;
    313 	bus_space_tag_t iot = fb->fb_iot;
    314 	bus_space_handle_t ioh = fb->fb_ioh;
    315 
    316 	/* Initialize colormap */
    317 
    318 	bus_space_write_1(iot, ioh, S3_DAC_WR_INDEX, 0);
    319 
    320 	for (i = j = 0; i < CMAP_SIZE*3; i++) {
    321 		bus_space_write_1(iot, ioh, S3_DAC_DATA, default_cmap[j] >> 2);
    322 		j = (j+1) % sizeof(default_cmap)/sizeof(default_cmap[0]);
    323 	}
    324 
    325 	/* Retrieve frame buffer geometry */
    326 
    327 	bus_space_write_1(iot, ioh, S3_CRTC_INDEX, 1);
    328 	w = bus_space_read_1(iot, ioh, S3_CRTC_DATA);
    329 
    330 	bus_space_write_1(iot, ioh, S3_CRTC_INDEX, 18);
    331 	h = bus_space_read_1(iot, ioh, S3_CRTC_DATA);
    332 
    333 	bus_space_write_1(iot, ioh, S3_CRTC_INDEX, 7);
    334 	i = bus_space_read_1(iot, ioh, S3_CRTC_DATA);
    335 
    336 	h += (i << 7) & 0x100;
    337 	h += (i << 3) & 0x200;
    338 
    339 	*width = (w+1) << 3;
    340 	*height = h+1;
    341 }
    342