/* $Id: jfb.c,v 1.1 2008/03/04 16:09:01 nbrk Exp $ */
/*
* Jornada framebuffer.
* 640x240 @16bpp
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wsfont/vt220l8x10.h>
#include <machine/bus.h>
#include <arm/sa11x0/sa11x0_reg.h>
#include <arm/sa11x0/sa11x0_var.h>
#include <jornada/dev/jfbreg.h>
#include "wsdisplay.h"
#define JFB_DFLTWIDTH 640
#define JFB_DFLTHEIGHT 240
#define JFB_DFLTBPP 16
struct jfb_softc {
struct device sc_dev;
bus_space_tag_t sc_bust;
bus_space_handle_t sc_bush;
uint8_t *sc_bits;
int sc_width;
int sc_height;
int sc_depth;
int sc_linebytes;
int sc_rows;
int sc_cols;
struct rasops_info sc_ri;
struct wsscreen_descr sc_wsd;
struct wsscreen_list sc_wsl;
struct wsscreen_descr *sc_scrlist[1];
};
int jfb_match(struct device *parent, void *cf, void *aux);
void jfb_attach(struct device *parent, struct device *self, void *aux);
void jfbfakecnattach(bus_addr_t addr);
void jfb_rasopsinit(struct jfb_softc *sc);
void jfb_setcmap(struct rasops_info *ri);
struct jfb_softc jfb_sc;
int jfb_initted = 0;
/* autoconf stuff */
struct cfattach jfb_ca = {
sizeof(struct jfb_softc), jfb_match, jfb_attach, NULL, NULL
};
struct cfdriver jfb_cd = {
NULL, "jfb", DV_DULL
};
int
jfb_match(struct device *parent, void *cf, void *aux)
{
return(1);
}
void
jfb_attach(struct device *parent, struct device *self, void *aux)
{
struct jfb_softc *sc = (void *)self;
struct saip_attach_args *saa = aux;
struct wsemuldisplaydev_attach_args waa;
sc->sc_bust = saa->sai_iot;
/* use bootstrap softc if it is already configured */
// if (jfb_initted)
// *sc = jfb_sc;
if (bus_space_map(sc->sc_bust, saa->sai_addr, JFB_SIZE , BUS_SPACE_MAP_LINEAR, &sc->sc_bush)) {
printf(": can't map i/o space\n");
return;
}
sc->sc_bits = (uint8_t *)sc->sc_bush;
/* TODO use flags for mode selection */
sc->sc_width = JFB_DFLTWIDTH;
sc->sc_height = JFB_DFLTHEIGHT;
sc->sc_depth = JFB_DFLTBPP;
sc->sc_linebytes = sc->sc_width * (sc->sc_depth / 8);
sc->sc_cols = 80;
sc->sc_rows = 24;
jfb_rasopsinit(sc);
printf(": Jornada framebuffer (%dx%d @%dbpp)\n", sc->sc_width, sc->sc_height, sc->sc_depth);
sc->sc_scrlist[0] = &sc->sc_wsd;
sc->sc_wsl.nscreens = 1;
sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
waa.scrdata = &sc->sc_wsl;
waa.accesscookie = sc;
waa.defaultscreens = 0;
config_found((struct device *)sc, &waa, wsemuldisplaydevprint);
return;
}
void
jfbfakecnattach(bus_addr_t addr)
{
struct jfb_softc *sc = &jfb_sc;
sc->sc_bits = (uint8_t *)addr;
if (jfb_initted == 0) {
/*
* First attachment.
* Initialize with defaults.
*/
/* clear the screen */
sc->sc_ri.ri_flg = RI_CLEAR | RI_FULLCLEAR;
sc->sc_width = JFB_DFLTWIDTH;
sc->sc_height = JFB_DFLTHEIGHT;
sc->sc_depth = JFB_DFLTBPP;
sc->sc_linebytes = sc->sc_width * (sc->sc_depth / 8);
sc->sc_cols = 80;
sc->sc_rows = 24;
/* set up rasops */
jfb_rasopsinit(sc);
jfb_initted = 1;
wsdisplay_cnattach(&sc->sc_wsd, &sc->sc_ri, 0, 0, 0);
} else {
/*
* Already attached.
* Tweak some settings and reconfigure rasops.
*/
/* reset ri_bits */
sc->sc_ri.ri_flg &= ~RI_CFGDONE;
sc->sc_ri.ri_bits = sc->sc_bits;
/* do not clear the screen */
sc->sc_ri.ri_flg &= ~RI_CLEAR;
rasops_reconfig(&sc->sc_ri, 160, 160);
}
}
void
jfb_rasopsinit(struct jfb_softc *sc)
{
struct rasops_info *ri = &sc->sc_ri;
struct wsscreen_descr *wsd = &sc->sc_wsd;
extern struct wsdisplay_font vt220l8x10;
ri->ri_hw = sc;
ri->ri_bits = sc->sc_bits;
/* claim minimal colour capabilities */
ri->ri_caps = WSSCREEN_WSCOLORS;
ri->ri_depth = sc->sc_depth;
ri->ri_width = sc->sc_width;
ri->ri_height = sc->sc_height;
ri->ri_stride = sc->sc_linebytes;
/* FIXME: see how colors are packed in 16bits/pixel ? */
ri->ri_rnum = 5;
ri->ri_gnum = 6;
ri->ri_bnum = 5;
ri->ri_rpos = 11;
ri->ri_gpos = 5;
ri->ri_bpos = 0;
ri->ri_font = &vt220l8x10;
/* XXX XXX please tell me why? */
/* rasops_init(ri, sc->sc_cols, sc->sc_rows); */
rasops_init(ri, 160, 160);
/* tune colours */
jfb_setcmap(ri);
/* initialize wsscreen_descr */
strlcpy(wsd->name, "std", sizeof(wsd->name));
wsd->ncols = sc->sc_cols;
wsd->nrows = sc->sc_rows;
wsd->capabilities = ri->ri_caps;
wsd->textops = &ri->ri_ops;
}
void
jfb_setcmap(struct rasops_info *ri)
{
/* more intensive white */
ri->ri_devcmap[WSCOL_WHITE] = 0xffff;
}