Module Name: src
Committed By: macallan
Date: Wed May 27 00:35:34 UTC 2009
Modified Files:
src/sys/dev/sbus: p9100.c
Log Message:
finally commit a lot of stuff that's been sitting in my source tree for
several ages:
- convert to device_t
- add support for programming colour depth and such, use it to reset the
console to something usable when we enter ddb or exit X etc.
- basic power management
TODO:
- convert to PMF
- get rid of rconsole code so we don't need to map the framebuffer
- power down the whole DAC when not in use
To generate a diff of this commit:
cvs rdiff -u -r1.43 -r1.44 src/sys/dev/sbus/p9100.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/sbus/p9100.c
diff -u src/sys/dev/sbus/p9100.c:1.43 src/sys/dev/sbus/p9100.c:1.44
--- src/sys/dev/sbus/p9100.c:1.43 Tue May 12 14:43:59 2009
+++ src/sys/dev/sbus/p9100.c Wed May 27 00:35:34 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: p9100.c,v 1.43 2009/05/12 14:43:59 cegger Exp $ */
+/* $NetBSD: p9100.c,v 1.44 2009/05/27 00:35:34 macallan Exp $ */
/*-
* Copyright (c) 1998, 2005, 2006 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.43 2009/05/12 14:43:59 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.44 2009/05/27 00:35:34 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -62,7 +62,7 @@
#include <dev/sbus/sbusvar.h>
-/*#include <dev/wscons/wsdisplayvar.h>*/
+#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wsfont/wsfont.h>
#include <dev/rasops/rasops.h>
@@ -78,6 +78,12 @@
#include <sparc/dev/tctrlvar.h>/*XXX*/
#endif
+#ifdef PNOZZ_DEBUG
+#define DPRINTF aprint_normal
+#else
+#define DPRINTF while (0) aprint_normal
+#endif
+
struct pnozz_cursor {
short pc_enable; /* cursor is enabled */
struct fbcurpos pc_pos; /* position */
@@ -90,7 +96,7 @@
/* per-display variables */
struct p9100_softc {
- struct device sc_dev; /* base device */
+ device_t sc_dev; /* base device */
struct sbusdev sc_sd; /* sbus device */
struct fbdevice sc_fb; /* frame buffer device */
@@ -100,10 +106,11 @@
bus_size_t sc_ctl_psize; /* for device mmap() */
bus_space_handle_t sc_ctl_memh; /* bus space handle */
+#if 0
bus_addr_t sc_cmd_paddr; /* phys address description */
bus_size_t sc_cmd_psize; /* for device mmap() */
bus_space_handle_t sc_cmd_memh; /* bus space handle */
-
+#endif
bus_addr_t sc_fb_paddr; /* phys address description */
bus_size_t sc_fb_psize; /* for device mmap() */
bus_space_handle_t sc_fb_memh; /* bus space handle */
@@ -111,10 +118,12 @@
volatile uint32_t sc_junk;
uint32_t sc_mono_width; /* for setup_mono */
- uint32_t sc_width;
- uint32_t sc_height; /* panel width / height */
- uint32_t sc_stride;
- uint32_t sc_depth;
+ uint32_t sc_width;
+ uint32_t sc_height; /* panel width / height */
+ uint32_t sc_stride;
+ uint32_t sc_depth;
+ int sc_depthshift; /* blitter works on bytes not pixels */
+
union bt_cmap sc_cmap; /* Brooktree color map */
struct pnozz_cursor sc_cursor;
@@ -155,7 +164,7 @@
static void p9100unblank(device_t);
static void p9100_shutdown(void *);
-CFATTACH_DECL(pnozz, sizeof(struct p9100_softc),
+CFATTACH_DECL_NEW(pnozz, sizeof(struct p9100_softc),
p9100_sbus_match, p9100_sbus_attach, NULL, NULL);
extern struct cfdriver pnozz_cd;
@@ -189,6 +198,7 @@
#endif
static void p9100_init_engine(struct p9100_softc *);
+static int p9100_set_depth(struct p9100_softc *, int);
#if NWSDISPLAY > 0
static void p9100_sync(struct p9100_softc *);
@@ -229,7 +239,9 @@
static void p9100_setcursorcmap(struct p9100_softc *);
static void p9100_loadcursor(struct p9100_softc *);
+#if 0
static int p9100_intr(void *);
+#endif
/* power management stuff */
static void p9100_power_hook(int, void *);
@@ -264,7 +276,9 @@
{
struct sbus_attach_args *sa = aux;
- return (strcmp("p9100", sa->sa_name) == 0);
+ if (strcmp("p9100", sa->sa_name) == 0)
+ return 100;
+ return 0;
}
@@ -278,7 +292,7 @@
struct sbus_attach_args *sa = args;
struct fbdevice *fb = &sc->sc_fb;
int isconsole;
- int node;
+ int node = sa->sa_node;
int i, j;
uint8_t ver;
@@ -289,24 +303,67 @@
#endif
sc->sc_last_offset = 0xffffffff;
+ sc->sc_dev = self;
+
+ /*
+ * When the ROM has mapped in a p9100 display, the address
+ * maps only the video RAM, so in any case we have to map the
+ * registers ourselves. We only need the video RAM if we are
+ * going to print characters via rconsole.
+ */
+
+ if (sa->sa_npromvaddrs != 0)
+ fb->fb_pixels = (void *)sa->sa_promvaddrs[0];
/* Remember cookies for p9100_mmap() */
sc->sc_bustag = sa->sa_bustag;
+
sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag,
sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/
- sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag,
- sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
- sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size;
-
sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag,
sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size;
+ if (sbus_bus_map(sc->sc_bustag,
+ sa->sa_reg[0].oa_space,
+ sa->sa_reg[0].oa_base,
+ /*
+ * XXX for some reason the SBus resources don't cover
+ * all registers, so we just map what we need
+ */
+ 0x8000,
+ 0, &sc->sc_ctl_memh) != 0) {
+ printf("%s: cannot map control registers\n",
+ self->dv_xname);
+ return;
+ }
+
+ if (fb->fb_pixels == NULL) {
+ if (sbus_bus_map(sc->sc_bustag,
+ sa->sa_reg[2].oa_space,
+ sa->sa_reg[2].oa_base,
+ sc->sc_fb_psize,
+ BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) {
+ printf("%s: cannot map framebuffer\n",
+ self->dv_xname);
+ return;
+ }
+ fb->fb_pixels = (char *)sc->sc_fb_memh;
+ } else {
+ sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
+ }
+ sc->sc_width = prom_getpropint(node, "width", 800);
+ sc->sc_height = prom_getpropint(node, "height", 600);
+ sc->sc_depth = prom_getpropint(node, "depth", 8) >> 3;
+
+ sc->sc_stride = prom_getpropint(node, "linebytes",
+ sc->sc_width * sc->sc_depth);
+
fb->fb_driver = &p9100fbdriver;
- fb->fb_device = &sc->sc_dev;
- fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK;
+ fb->fb_device = sc->sc_dev;
+ fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK;
#ifdef PNOZZ_EMUL_CG3
fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
#else
@@ -316,13 +373,14 @@
sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
- node = sa->sa_node;
isconsole = fb_is_console(node);
+#if 0
if (!isconsole) {
aprint_normal("\n");
aprint_error_dev(self, "fatal error: PROM didn't configure device\n");
return;
}
+#endif
/*
* When the ROM has mapped in a p9100 display, the address
@@ -360,48 +418,62 @@
sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
}
+#if 0
+ /*
+ * we set our own depth and OBP won't hand us anything else than 8 bit
+ * anyway
+ */
i = p9100_ctl_read_4(sc, 0x0004);
switch ((i >> 26) & 7) {
- case 5: fb->fb_type.fb_depth = 32; break;
- case 7: fb->fb_type.fb_depth = 24; break;
- case 3: fb->fb_type.fb_depth = 16; break;
- case 2: fb->fb_type.fb_depth = 8; break;
+ case 5:
+ fb->fb_type.fb_depth = 32;
+ sc->sc_depth = 4;
+ sc->sc_depthshift = 2;
+ break;
+ case 7:
+ fb->fb_type.fb_depth = 24;
+ /* bitch and moan */
+ break;
+ case 3:
+ fb->fb_type.fb_depth = 16;
+ sc->sc_depth = 2;
+ sc->sc_depthshift = 1;
+ break;
+ case 2:
+ fb->fb_type.fb_depth = 8;
+ sc->sc_depth = 1;
+ sc->sc_depthshift = 0;
+ break;
default: {
panic("pnozz: can't determine screen depth (0x%02x)", i);
}
}
- sc->sc_depth = (fb->fb_type.fb_depth >> 3);
-
- /* XXX for some reason I get a kernel trap with this */
- sc->sc_width = prom_getpropint(node, "width", 800);
- sc->sc_height = prom_getpropint(node, "height", 600);
-
- sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width *
- (fb->fb_type.fb_depth >> 3));
+#else
+ fb->fb_type.fb_depth = 8;
+ sc->sc_depth = 1;
+ sc->sc_depthshift = 0;
+#endif
/* check the RAMDAC */
ver = p9100_ramdac_read_ctl(sc, DAC_VERSION);
p9100_init_engine(sc);
-
+ p9100_set_depth(sc, 8);
+
fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height,
node);
- sbus_establish(&sc->sc_sd, &sc->sc_dev);
+ sbus_establish(&sc->sc_sd, sc->sc_dev);
+#if 0
bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO,
p9100_intr, sc);
-
- fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
- printf(": rev %d / %x, %dx%d, depth %d mem %x",
- (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height,
- fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize);
+#endif
fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256);
if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize)
printf(", %d entry colormap", fb->fb_type.fb_cmsize);
/* Initialize the default color map. */
- /*bt_initcmap(&sc->sc_cmap, 256);*/
j = 0;
for (i = 0; i < 256; i++) {
sc->sc_cmap.cm_map[i][0] = rasops_cmap[j];
@@ -419,7 +491,7 @@
if (shutdownhook_establish(p9100_shutdown, sc) == NULL) {
panic("%s: could not establish shutdown hook",
- device_xname(&sc->sc_dev));
+ device_xname(sc->sc_dev));
}
if (isconsole) {
@@ -461,6 +533,10 @@
config_found(self, &aa, wsemuldisplaydevprint);
#endif
+ fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
+ printf(": rev %d / %x, %dx%d, depth %d mem %x",
+ (i & 7), ver, fb->fb_type.fb_width, fb->fb_type.fb_height,
+ fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize);
/* cursor sprite handling */
p9100_init_cursor(sc);
@@ -470,7 +546,7 @@
/* register with power management */
sc->sc_video = 1;
sc->sc_powerstate = PWR_RESUME;
- powerhook_establish(device_xname(&sc->sc_dev), p9100_power_hook, sc);
+ powerhook_establish(device_xname(sc->sc_dev), p9100_power_hook, sc);
#if NTCTRL > 0
/* register callback for external monitor status change */
@@ -701,6 +777,7 @@
p9100_ctl_write_4(sc, PATTERN1, 0xffffffff);
p9100_ctl_write_4(sc, PATTERN2, 0xffffffff);
p9100_ctl_write_4(sc, PATTERN3, 0xffffffff);
+
}
/* we only need these in the wsdisplay case */
@@ -748,14 +825,16 @@
dst = ((xd & 0x3fff) << 16) | (yd & 0x3fff);
srcw = (((xs + wi - 1) & 0x3fff) << 16) | ((ys + he - 1) & 0x3fff);
dstw = (((xd + wi - 1) & 0x3fff) << 16) | ((yd + he - 1) & 0x3fff);
+
p9100_sync(sc);
+
p9100_ctl_write_4(sc, RASTER_OP, rop);
- p9100_ctl_write_4(sc, ABS_XY0, src);
+ p9100_ctl_write_4(sc, ABS_XY0, src << sc->sc_depthshift);
+ p9100_ctl_write_4(sc, ABS_XY1, srcw << sc->sc_depthshift);
+ p9100_ctl_write_4(sc, ABS_XY2, dst << sc->sc_depthshift);
+ p9100_ctl_write_4(sc, ABS_XY3, dstw << sc->sc_depthshift);
- p9100_ctl_write_4(sc, ABS_XY1, srcw);
- p9100_ctl_write_4(sc, ABS_XY2, dst);
- p9100_ctl_write_4(sc, ABS_XY3, dstw);
sc->sc_junk = p9100_ctl_read_4(sc, COMMAND_BLIT);
}
@@ -823,17 +902,15 @@
if (shift == 0) {
/* check how many bits are significant */
if (to_go > 31) {
- bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh,
+ bus_space_write_4(sc->sc_bustag,
+ sc->sc_ctl_memh,
(PIXEL_1 + (31 << 2)), latch);
- /*p9100_ctl_write_4(sc, (PIXEL_1 +
- (31 << 2)), latch);*/
to_go -= 32;
} else
{
- bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh,
+ bus_space_write_4(sc->sc_bustag,
+ sc->sc_ctl_memh,
(PIXEL_1 + ((to_go - 1) << 2)), latch);
- /*p9100_ctl_write_4(sc, (PIXEL_1 +
- ((to_go - 1) << 2)), latch);*/
to_go = 0;
}
latch = 0;
@@ -910,6 +987,8 @@
sc->vd.active = &p9100_console_screen;
SCREEN_VISIBLE(&p9100_console_screen);
}
+ p9100_init_engine(sc);
+ p9100_set_depth(sc, 8);
vcons_redraw_screen(&p9100_console_screen);
}
}
@@ -967,7 +1046,6 @@
p9100loadcmap(struct p9100_softc *sc, int start, int ncolors)
{
int i;
-
sc->sc_last_offset = 0xffffffff;
p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start);
@@ -1010,7 +1088,7 @@
}
#endif
- if (off >= sc->sc_fb_psize + sc->sc_ctl_psize + sc->sc_cmd_psize)
+ if (off >= sc->sc_fb_psize + sc->sc_ctl_psize/* + sc->sc_cmd_psize*/)
return (-1);
if (off < sc->sc_fb_psize) {
@@ -1020,6 +1098,7 @@
prot,
BUS_SPACE_MAP_LINEAR));
}
+
off -= sc->sc_fb_psize;
if (off < sc->sc_ctl_psize) {
return (bus_space_mmap(sc->sc_bustag,
@@ -1028,6 +1107,7 @@
prot,
BUS_SPACE_MAP_LINEAR));
}
+#if 0
off -= sc->sc_ctl_psize;
return (bus_space_mmap(sc->sc_bustag,
@@ -1035,6 +1115,8 @@
off,
prot,
BUS_SPACE_MAP_LINEAR));
+#endif
+ return EINVAL;
}
/* wscons stuff */
@@ -1057,8 +1139,10 @@
p9100_bitblt(sc, x, y, x, y, wi, he, ROP_SRC ^ 0xff);
ri->ri_flg &= ~RI_CURSOR;
}
+
ri->ri_crow = row;
ri->ri_ccol = col;
+
if (on)
{
x = ri->ri_ccol * wi + ri->ri_xorigin;
@@ -1092,10 +1176,12 @@
if (!CHAR_IN_FONT(c, ri->ri_font))
return;
+
bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff];
fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff];
x = ri->ri_xorigin + col * wi;
y = ri->ri_yorigin + row * he;
+
if (c == 0x20) {
p9100_rectfill(sc, x, y, wi, he, bg);
} else {
@@ -1109,7 +1195,6 @@
data);
data += ri->ri_font->stride;
}
- /*p9100_sync(sc);*/
}
}
@@ -1164,6 +1249,7 @@
if (new_mode == WSDISPLAYIO_MODE_EMUL)
{
p9100_init_engine(sc);
+ p9100_set_depth(sc, 8);
p9100loadcmap(sc, 0, 256);
p9100_clearscreen(sc);
vcons_redraw_screen(ms);
@@ -1220,9 +1306,8 @@
ri->ri_bits = bus_space_vaddr(sc->sc_bustag, sc->sc_fb_memh);
-#ifdef DEBUG_P9100
- printf("addr: %08lx\n",(ulong)ri->ri_bits);
-#endif
+ DPRINTF("addr: %08lx\n",(ulong)ri->ri_bits);
+
rasops_init(ri, sc->sc_height/8, sc->sc_width/8);
ri->ri_caps = WSSCREEN_WSCOLORS;
rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
@@ -1381,12 +1466,16 @@
fg = WS_DEFAULT_FG;
bg = WS_DEFAULT_BG;
}
+
+ *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | (flags & 0xff);
+
if (flags & WSATTR_REVERSE) {
*attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16 |
(flags & 0xff) << 8;
} else
*attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 |
(flags & 0xff) << 8;
+
return 0;
}
@@ -1401,13 +1490,15 @@
#endif /* NWSDISPLAY > 0 */
+#if 0
static int
p9100_intr(void *arg)
{
- /*p9100_softc *sc=arg;
- printf(".");*/
+ /*p9100_softc *sc=arg;*/
+ DPRINTF(".");
return 1;
}
+#endif
static void
p9100_init_cursor(struct p9100_softc *sc)
@@ -1535,7 +1626,7 @@
p9100_ramdac_write(sc, DAC_INDX_DATA, latch2);
}
}
-#ifdef DEBUG_CURSOR
+#ifdef PNOZZ_DEBUG_CURSOR
printf("image:\n");
for (i=0;i<0x80;i+=2)
printf("%08x %08x\n", image[i], image[i+1]);
@@ -1558,19 +1649,21 @@
s = splhigh();
#endif
-#ifdef DEBUG
- printf("%s: external VGA %s\n", device_xname(&sc->sc_dev),
+
+#ifdef PNOZZ_DEBUG
+ printf("%s: external VGA %s\n", device_xname(sc->sc_dev),
status ? "on" : "off");
#endif
+
sc->sc_last_offset = 0xffffffff;
if (status) {
- p9100_ramdac_write_ctl(sc, DAC_POWER,
- p9100_ramdac_read_ctl(sc, DAC_POWER) &
+ p9100_ramdac_write_ctl(sc, DAC_POWER_MGT,
+ p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) &
~DAC_POWER_IPWR_DISABLE);
} else {
- p9100_ramdac_write_ctl(sc, DAC_POWER,
- p9100_ramdac_read_ctl(sc, DAC_POWER) |
+ p9100_ramdac_write_ctl(sc, DAC_POWER_MGT,
+ p9100_ramdac_read_ctl(sc, DAC_POWER_MGT) |
DAC_POWER_IPWR_DISABLE);
}
#ifdef PNOZZ_PARANOID
@@ -1578,3 +1671,175 @@
#endif
}
#endif /* NTCTRL > 0 */
+
+static int
+upper_bit(uint32_t b)
+{
+ uint32_t mask=0x80000000;
+ int cnt = 31;
+ if (b == 0)
+ return -1;
+ while ((mask != 0) && ((b & mask) == 0)) {
+ mask = mask >> 1;
+ cnt--;
+ }
+ return cnt;
+}
+
+static int
+p9100_set_depth(struct p9100_softc *sc, int depth)
+{
+ int new_sls;
+ uint32_t bits, scr, memctl, mem;
+ int s0, s1, s2, s3, ps, crtcline;
+ uint8_t pf, mc3, es;
+
+ switch (depth) {
+ case 8:
+ sc->sc_depthshift = 0;
+ ps = 2;
+ pf = 3;
+ mc3 = 0;
+ es = 0; /* no swapping */
+ memctl = 3;
+ break;
+ case 16:
+ sc->sc_depthshift = 1;
+ ps = 3;
+ pf = 4;
+ mc3 = 0;
+ es = 2; /* swap bytes in 16bit words */
+ memctl = 2;
+ break;
+ case 24:
+ /* boo */
+ printf("We don't DO 24bit pixels dammit!\n");
+ return 0;
+ case 32:
+ sc->sc_depthshift = 2;
+ ps = 5;
+ pf = 6;
+ mc3 = 0;
+ es = 6; /* swap both half-words and bytes */
+ memctl = 1; /* 0 */
+ break;
+ default:
+ aprint_error("%s: bogus colour depth (%d)\n",
+ __func__, depth);
+ return FALSE;
+ }
+ /*
+ * this could be done a lot shorter and faster but then nobody would
+ * understand what the hell we're doing here without getting a major
+ * headache. Scanline size is encoded as 4 shift values, 3 of them 3 bits
+ * wide, 16 << n for n>0, one 2 bits, 512 << n for n>0. n==0 means 0
+ */
+ new_sls = sc->sc_width << sc->sc_depthshift;
+ sc->sc_stride = new_sls;
+ bits = new_sls;
+ s3 = upper_bit(bits);
+ if (s3 > 9) {
+ bits &= ~(1 << s3);
+ s3 -= 9;
+ } else
+ s3 = 0;
+ s2 = upper_bit(bits);
+ if (s2 > 0) {
+ bits &= ~(1 << s2);
+ s2 -= 4;
+ } else
+ s2 = 0;
+ s1 = upper_bit(bits);
+ if (s1 > 0) {
+ bits &= ~(1 << s1);
+ s1 -= 4;
+ } else
+ s1 = 0;
+ s0 = upper_bit(bits);
+ if (s0 > 0) {
+ bits &= ~(1 << s0);
+ s0 -= 4;
+ } else
+ s0 = 0;
+
+
+ DPRINTF("sls: %x sh: %d %d %d %d leftover: %x\n", new_sls, s0, s1,
+ s2, s3, bits);
+
+ /*
+ * now let's put these values into the System Config Register. No need to
+ * read it here since we (hopefully) just saved the content
+ */
+ scr = p9100_ctl_read_4(sc, SYS_CONF);
+ scr = (s0 << SHIFT_0) | (s1 << SHIFT_1) | (s2 << SHIFT_2) |
+ (s3 << SHIFT_3) | (ps << PIXEL_SHIFT) | (es << SWAP_SHIFT);
+
+ DPRINTF("new scr: %x DAC %x %x\n", scr, pf, mc3);
+
+ mem = p9100_ctl_read_4(sc, VID_MEM_CONFIG);
+
+ DPRINTF("old memctl: %08x\n", mem);
+
+ /* set shift and crtc clock */
+ mem &= ~(0x0000fc00);
+ mem |= (memctl << 10) | (memctl << 13);
+ p9100_ctl_write_4(sc, VID_MEM_CONFIG, mem);
+
+ DPRINTF("new memctl: %08x\n", mem);
+
+ /* whack the engine... */
+ p9100_ctl_write_4(sc, SYS_CONF, scr);
+
+ /* ok, whack the DAC */
+ p9100_ramdac_write_ctl(sc, DAC_MISC_1, 0x11);
+ p9100_ramdac_write_ctl(sc, DAC_MISC_2, 0x45);
+ p9100_ramdac_write_ctl(sc, DAC_MISC_3, mc3);
+ /*
+ * despite the 3GX manual saying otherwise we don't need to mess with
+ * any clock dividers here
+ */
+ p9100_ramdac_write_ctl(sc, DAC_MISC_CLK, 1);
+ p9100_ramdac_write_ctl(sc, 3, 0);
+ p9100_ramdac_write_ctl(sc, 4, 0);
+
+ p9100_ramdac_write_ctl(sc, DAC_POWER_MGT, 0);
+ p9100_ramdac_write_ctl(sc, DAC_OPERATION, 0);
+ p9100_ramdac_write_ctl(sc, DAC_PALETTE_CTRL, 0);
+
+ p9100_ramdac_write_ctl(sc, DAC_PIXEL_FMT, pf);
+
+ /* TODO: distinguish between 15 and 16 bit */
+ p9100_ramdac_write_ctl(sc, DAC_8BIT_CTRL, 0);
+ /* direct colour, linear, 565 */
+ p9100_ramdac_write_ctl(sc, DAC_16BIT_CTRL, 0xc6);
+ /* direct colour */
+ p9100_ramdac_write_ctl(sc, DAC_32BIT_CTRL, 3);
+
+ /* From the 3GX manual. Needs magic number reduction */
+ p9100_ramdac_write_ctl(sc, 0x10, 2);
+ p9100_ramdac_write_ctl(sc, 0x11, 0);
+ p9100_ramdac_write_ctl(sc, 0x14, 5);
+ p9100_ramdac_write_ctl(sc, 0x08, 1);
+ p9100_ramdac_write_ctl(sc, 0x15, 5);
+ p9100_ramdac_write_ctl(sc, 0x16, 0x63);
+
+ /* whack the CRTC */
+ /* we always transfer 64bit in one go */
+ crtcline = sc->sc_stride >> 3;
+
+ DPRINTF("crtcline: %d\n", crtcline);
+
+ p9100_ctl_write_4(sc, VID_HTOTAL, (24 << sc->sc_depthshift) + crtcline);
+ p9100_ctl_write_4(sc, VID_HSRE, 8 << sc->sc_depthshift);
+ p9100_ctl_write_4(sc, VID_HBRE, 18 << sc->sc_depthshift);
+ p9100_ctl_write_4(sc, VID_HBFE, (18 << sc->sc_depthshift) + crtcline);
+
+#ifdef PNOZZ_DEBUG
+ {
+ uint32_t sscr;
+ sscr = p9100_ctl_read_4(sc, SYS_CONF);
+ printf("scr: %x\n", sscr);
+ }
+#endif
+ return TRUE;
+}