summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authormacallan <macallan@NetBSD.org>2009-11-18 21:59:38 +0000
committermacallan <macallan@NetBSD.org>2009-11-18 21:59:38 +0000
commit910612113d2e10c02674cf2bc15ca184b075ee30 (patch)
tree4838efa449514ac3762fe8e1c748141bcefb8a90 /sys/dev
parentc32688c3c22ec34687f2d7d147262c9b64863fcb (diff)
Make colour depths higher than 8bit work in X.
Now igsfb will switch to 16 or 32 bit colour when entering graphics mode, depending on available video memory and the given mode. While there re-initialize the colour map etc. when leaving graphics mode.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/igsfb.c18
-rw-r--r--sys/dev/ic/igsfb_subr.c76
-rw-r--r--sys/dev/ic/igsfbvar.h4
3 files changed, 77 insertions, 21 deletions
diff --git a/sys/dev/ic/igsfb.c b/sys/dev/ic/igsfb.c
index 97975a76420..61f17f81347 100644
--- a/sys/dev/ic/igsfb.c
+++ b/sys/dev/ic/igsfb.c
@@ -1,4 +1,4 @@
-/* $NetBSD: igsfb.c,v 1.46 2009/11/11 17:01:17 macallan Exp $ */
+/* $NetBSD: igsfb.c,v 1.47 2009/11/18 21:59:38 macallan Exp $ */
/*
* Copyright (c) 2002, 2003 Valeriy E. Ushakov
@@ -31,7 +31,7 @@
* Integraphics Systems IGA 168x and CyberPro series.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.46 2009/11/11 17:01:17 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.47 2009/11/18 21:59:38 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -201,7 +201,8 @@ igsfb_attach_subr(struct igsfb_softc *sc, int isconsole)
? "hardware bswap, " : "software bswap, "
: "",
dc->dc_width, dc->dc_height, dc->dc_depth);
-
+ printf("%s: using %dbpp for X\n", device_xname(&sc->sc_dev),
+ dc->dc_maxdepth);
ri = &dc->dc_console.scr_ri;
ri->ri_ops.eraserows(ri, 0, ri->ri_rows, defattr);
@@ -613,13 +614,13 @@ igsfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
#define wsd_fbip ((struct wsdisplay_fbinfo *)data)
wsd_fbip->height = dc->dc_height;
wsd_fbip->width = dc->dc_width;
- wsd_fbip->depth = dc->dc_depth;
+ wsd_fbip->depth = dc->dc_maxdepth;
wsd_fbip->cmsize = IGS_CMAP_SIZE;
#undef wsd_fbip
return 0;
case WSDISPLAYIO_LINEBYTES:
- *(int *)data = dc->dc_stride;
+ *(int *)data = dc->dc_width * (dc->dc_maxdepth >> 3);
return 0;
case WSDISPLAYIO_SMODE:
@@ -632,8 +633,14 @@ igsfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
igsfb_update_cursor(dc,
WSDISPLAY_CURSOR_DOCUR);
}
+ if ((dc->dc_mode != NULL) && (dc->dc_maxdepth != 8))
+ igsfb_set_mode(dc, dc->dc_mode,
+ dc->dc_maxdepth);
} else {
dc->dc_mapped = 0;
+ if ((dc->dc_mode != NULL) && (dc->dc_maxdepth != 8))
+ igsfb_set_mode(dc, dc->dc_mode, 8);
+ igsfb_init_cmap(dc);
/* reinit sprite for text cursor */
if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) {
igsfb_make_text_cursor(dc, dc->dc_vd.active);
@@ -1170,6 +1177,7 @@ igsfb_accel_wait(struct igsfb_devconfig *dc)
int timo = 100000;
uint8_t reg;
+ bus_space_write_1(t, h, IGS_COP_MAP_FMT_REG, (dc->dc_depth >> 3) - 1);
while (timo--) {
reg = bus_space_read_1(t, h, IGS_COP_CTL_REG);
if ((reg & IGS_COP_CTL_BUSY) == 0)
diff --git a/sys/dev/ic/igsfb_subr.c b/sys/dev/ic/igsfb_subr.c
index 47a0acfed50..6c8b90d9055 100644
--- a/sys/dev/ic/igsfb_subr.c
+++ b/sys/dev/ic/igsfb_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: igsfb_subr.c,v 1.11 2009/11/18 06:10:50 macallan Exp $ */
+/* $NetBSD: igsfb_subr.c,v 1.12 2009/11/18 21:59:38 macallan Exp $ */
/*
* Copyright (c) 2002 Valeriy E. Ushakov
@@ -32,7 +32,7 @@
* Integraphics Systems IGA 168x and CyberPro series.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igsfb_subr.c,v 1.11 2009/11/18 06:10:50 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igsfb_subr.c,v 1.12 2009/11/18 21:59:38 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -427,7 +427,7 @@ void
igsfb_hw_setup(struct igsfb_devconfig *dc)
{
const struct videomode *mode = NULL;
- int i;
+ int i, size, d;
igsfb_init_seq(dc);
igsfb_init_crtc(dc);
@@ -443,20 +443,36 @@ igsfb_hw_setup(struct igsfb_devconfig *dc)
}
if (i < videomode_count) {
+ size = videomode_list[i].hdisplay * videomode_list[i].vdisplay;
/* found a mode, now let's see if we can display it */
if ((videomode_list[i].dot_clock <= IGS_MAX_CLOCK) &&
(videomode_list[i].hdisplay <= 2048) &&
(videomode_list[i].hdisplay >= 320) &&
(videomode_list[i].vdisplay <= 2048) &&
- (videomode_list[i].vdisplay >= 200)) {
+ (videomode_list[i].vdisplay >= 200) &&
+ (size <= (dc->dc_memsz - 0x1000))) {
mode = &videomode_list[i];
+ /*
+ * now let's see which maximum depth we can support
+ * in that mode
+ */
+ d = (dc->dc_vmemsz - 0x1000) / size;
+ if (d >= 4) {
+ dc->dc_maxdepth = 32;
+ } else if (d >= 2) {
+ dc->dc_maxdepth = 16;
+ } else
+ dc->dc_maxdepth = 8;
}
}
+ dc->dc_mode = mode;
if (mode != NULL) {
igsfb_set_mode(dc, mode, 8);
- } else
+ } else {
igsfb_1024x768_8bpp_60Hz(dc);
+ dc->dc_maxdepth = 8;
+ }
igsfb_video_on(dc);
}
@@ -470,30 +486,32 @@ igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
int i, m, n, p, hoffset, bytes_per_pixel, memfetch;
int vsync_start, hsync_start, vsync_end, hsync_end;
int vblank_start, vblank_end, hblank_start, hblank_end;
- uint8_t vclk1, vclk2, vclk3, overflow;
+ int croffset;
+ uint8_t vclk1, vclk2, vclk3, overflow, reg, seq_mode;
switch (depth) {
case 8:
- bytes_per_pixel = IGS_EXT_SEQ_8BPP;
+ seq_mode = IGS_EXT_SEQ_8BPP;
break;
case 15:
- bytes_per_pixel = IGS_EXT_SEQ_15BPP; /* 5-5-5 */
+ seq_mode = IGS_EXT_SEQ_15BPP; /* 5-5-5 */
break;
case 16:
- bytes_per_pixel = IGS_EXT_SEQ_16BPP; /* 5-6-5 */
+ seq_mode = IGS_EXT_SEQ_16BPP; /* 5-6-5 */
break;
case 24:
- bytes_per_pixel = IGS_EXT_SEQ_24BPP; /* 8-8-8 */
+ seq_mode = IGS_EXT_SEQ_24BPP; /* 8-8-8 */
break;
case 32:
- bytes_per_pixel = IGS_EXT_SEQ_32BPP;
+ seq_mode = IGS_EXT_SEQ_32BPP;
break;
default:
aprint_error("igsfb: unsupported depth (%d), reverting"
" to 8 bit\n", depth);
depth = 8;
- bytes_per_pixel = IGS_EXT_SEQ_8BPP;
+ seq_mode = IGS_EXT_SEQ_8BPP;
}
+ bytes_per_pixel = depth >> 3;
hoffset = (mode->hdisplay >> 3) * bytes_per_pixel;
memfetch = hoffset + 1;
@@ -503,6 +521,11 @@ igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
((mode->vsync_start & 0x400) >> 7) |
0x10;
+ /* RAMDAC address 2 select */
+ reg = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL);
+ igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
+ reg | IGS_EXT_SPRITE_DAC_PEL);
+
if (depth == 8) {
/* palette mode */
bus_space_write_1(dc->dc_iot, dc->dc_ioh, IGS_DAC_CMD, 0x06);
@@ -510,6 +533,10 @@ igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
/* bypass palette */
bus_space_write_1(dc->dc_iot, dc->dc_ioh, IGS_DAC_CMD, 0x16);
}
+ /* restore */
+ igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, reg);
+
+ bus_space_write_1(iot, ioh, IGS_PEL_MASK, 0xff);
igs_crtc_write(iot, ioh, 0x11, 0x00); /* write enable CRTC 0..7 */
@@ -593,11 +620,10 @@ igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
igsfb_freq_latch(dc);
igs_ext_write(iot, ioh, IGS_EXT_VOVFL, overflow);
- igs_ext_write(iot, ioh, IGS_EXT_SEQ_MISC, bytes_per_pixel);
+ igs_ext_write(iot, ioh, IGS_EXT_SEQ_MISC, seq_mode);
igs_ext_write(iot, ioh, 0x14, memfetch & 0xff);
igs_ext_write(iot, ioh, 0x15,
((memfetch & 0x300) >> 8) | ((hoffset & 0x300) >> 4));
- igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, 0x00);
/* finally set the dot clock */
igsfb_calc_pll(mode->dot_clock, &m, &n, &p, 2047, 255, 7, IGS_MIN_VCO);
@@ -613,10 +639,30 @@ igsfb_set_mode(struct igsfb_devconfig *dc, const struct videomode *mode,
igsfb_freq_latch(dc);
DPRINTF("clock: %d\n", IGS_CLOCK(m, n, p));
+ if (dc->dc_id > 0x2000) {
+ /* we have a blitter, so configure it as well */
+ bus_space_write_1(dc->dc_iot, dc->dc_coph, IGS_COP_MAP_FMT_REG,
+ bytes_per_pixel - 1);
+ bus_space_write_2(dc->dc_iot, dc->dc_coph,
+ IGS_COP_SRC_MAP_WIDTH_REG, dc->dc_width - 1);
+ bus_space_write_2(dc->dc_iot, dc->dc_coph,
+ IGS_COP_DST_MAP_WIDTH_REG, dc->dc_width - 1);
+ }
+
+ /* re-init the cursor data address too */
+ croffset = dc->dc_vmemsz - IGS_CURSOR_DATA_SIZE;
+ croffset >>= 10; /* bytes -> kilobytes */
+ igs_ext_write(dc->dc_iot, dc->dc_ioh,
+ IGS_EXT_SPRITE_DATA_LO, croffset & 0xff);
+ igs_ext_write(dc->dc_iot, dc->dc_ioh,
+ IGS_EXT_SPRITE_DATA_HI, (croffset >> 8) & 0xf);
+
dc->dc_width = mode->hdisplay;
dc->dc_height = mode->vdisplay;
dc->dc_depth = depth;
- dc->dc_stride = dc->dc_width * bytes_per_pixel;
+ dc->dc_stride = dc->dc_width * (depth >> 3);
+
+ igsfb_video_on(dc);
}
diff --git a/sys/dev/ic/igsfbvar.h b/sys/dev/ic/igsfbvar.h
index 9f90d18aad8..76007566ae9 100644
--- a/sys/dev/ic/igsfbvar.h
+++ b/sys/dev/ic/igsfbvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: igsfbvar.h,v 1.18 2009/11/11 17:01:17 macallan Exp $ */
+/* $NetBSD: igsfbvar.h,v 1.19 2009/11/18 21:59:38 macallan Exp $ */
/*
* Copyright (c) 2002, 2003 Valeriy E. Ushakov
@@ -78,6 +78,8 @@ struct igsfb_devconfig {
/* resolution */
int dc_width, dc_height, dc_depth, dc_stride;
+ int dc_maxdepth;
+ const struct videomode *dc_mode;
char dc_modestring[128];