[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MQ-200 driver



井上@ASAHI-NET です。

MQ-200 ドライバの高速化ですが、とりあえず動く物が出来たので、patch を
投げてみます。

NetBSD 1.5BETA2 wscons 用です。

command FIFO は空きができるまでじっと待つ超手抜き版です。
cat /usr/share/misc/termcap は シグマリオンで 45 秒程度です。

# 先日、一桁になるとか吹いたような気がしますが、結局、文字描画に関して
# は、時間的には、ほとんど効果がないみたいです。

FIFO 待ちループの最大値は 4000 回位でした。
---
井上義也

--- mq200var.h.org	Tue Nov 28 23:17:16 2000
+++ mq200var.h	Sun Dec  3 00:31:42 2000
@@ -1,4 +1,5 @@
 /*	$NetBSD: mq200var.h,v 1.1.2.1 2000/08/06 03:56:42 takemura Exp $	*/
+/* modified by Y.Inoue */
 
 /*-
  * Copyright (c) 2000 Takemura Shin
@@ -38,6 +39,11 @@
 #include <arch/hpcmips/dev/hpcfbvar.h>
 #include <arch/hpcmips/dev/hpcfbio.h>
 
+struct coordinate {
+	u_int16_t x;
+	u_int16_t y;
+};
+
 struct mq200_softc {
 	struct device		sc_dev;
 	bus_addr_t		sc_baseaddr;
@@ -48,6 +54,7 @@
 	int			sc_powerstate;
 	struct hpcfb_fbconf	sc_fbconf;
 	struct hpcfb_dspconf	sc_dspconf;
+	struct coordinate       *sc_fontp;
 };
 
 int	mq200_probe	__P((bus_space_tag_t, bus_space_handle_t));
--- mq200.c.org	Tue Oct 17 08:53:40 2000
+++ mq200.c	Sun Dec  3 00:31:25 2000
@@ -1,4 +1,5 @@
 /*	$NetBSD: mq200.c,v 1.1.2.1 2000/08/06 03:56:41 takemura Exp $	*/
+/* modified by Y.Inoue */
 
 /*-
  * Copyright (c) 2000 Takemura Shin
@@ -33,6 +34,7 @@
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
 
 #include <vm/vm.h>
 
@@ -49,6 +51,14 @@
 #include <hpcmips/dev/mq200var.h>
 #include <hpcmips/dev/bivideovar.h>
 
+#define XXX_DEBUG
+#ifdef XXX_DEBUG
+static int resetcount = 0;
+static int loopcount = 0;
+#endif
+
+extern int hpcfb_accel;
+
 #define MQ200DEBUG
 #ifdef MQ200DEBUG
 #ifndef MQ200DEBUG_CONF
@@ -62,6 +72,11 @@
 #define DPRINTFN(n, arg) do { } while (0);
 #endif
 
+#define write_ge_reg(a,b) {\
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh,\
+	MQ200_GE + (a << 2), b);\
+}
+
 /*
  * function prototypes
  */
@@ -70,12 +85,25 @@
 static int	mq200_fbinit __P((struct hpcfb_fbconf *));
 static int	mq200_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
 static paddr_t	mq200_mmap __P((void *, off_t offset, int));
+static void	mq200_bitblit __P((void *, int, int, int, int, int, int));
+static void	mq200_cursor __P((void *, int, int, int, int, int));
+static void	mq200_erase __P((void *, int, int, int, int, int));
+static void	mq200_putchar __P((void *, int, int, struct wsdisplay_font *,
+				   int, int, u_int, int));
+static void	mq200_setclut __P((void *, struct rasops_info *));
+#ifdef XXX_DEBUG
+static int	mq200_xxx __P((struct mq200_softc *, struct hpcfb_dsp_op *));
+#endif
+static int	mq200_init_fontbuf __P((struct mq200_softc *,
+					struct wsdisplay_font *));
+static void	wait_cmd_FIFO __P((struct mq200_softc *, int));
 
 /*
  * static variables
  */
 struct hpcfb_accessops mq200_ha = {
-	mq200_ioctl, mq200_mmap
+	mq200_ioctl, mq200_mmap, NULL /* mq200_cursor */, mq200_bitblit, mq200_erase,
+	NULL /* mq200_putchar */, mq200_setclut
 };
 
 int
@@ -144,6 +172,8 @@
 
 	config_found(&sc->sc_dev, &ha, hpcfbprint);
 
+	mq200_ha.putchar = mq200_putchar;
+	mq200_ha.cursor = mq200_cursor;
 	/*
 	 * bivideo is no longer need
 	 */
@@ -216,7 +246,38 @@
 
 	return (0);
 }
+#define _mask(i, x) (i & ((1<<(x)) - 1))
+
+#define MAX_IDLE_LOOP   0x7FFFFFFUL
+#define MQ200_GE_ENABLE	0x00000100UL    /* GE can be enabled */
+
+static void
+wait_cmd_FIFO(sc, a)
+struct mq200_softc *sc;
+int a;
+{
+	u_int32_t status, count = 0;
+
+	for (count = 0; count < MAX_IDLE_LOOP; count++) {
+		status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_CC + 1*4);
+		if (_mask(status, 5) >= a) {
+			if (count > loopcount)
+				loopcount = count;
+			return;
+		}
+	}
+
+	DPRINTF(("mq200: cmd fifo status %x\n", status & ((1 << 5) - 1)));
 
+	status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_PM);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MQ200_PM,
+			  status & ~MQ200_GE_ENABLE);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MQ200_PM,
+			  status | MQ200_GE_ENABLE);
+#ifdef XXX_DEBUG
+	resetcount++;
+#endif
+}
 
 static int
 mq200_fbinit(fb)
@@ -343,6 +404,9 @@
 	struct hpcfb_fbconf *fbconf;
 	struct hpcfb_dspconf *dspconf;
 	struct wsdisplay_cmap *cmap;
+#ifdef XXX_DEBUG
+	struct hpcfb_dsp_op *dsp_op;
+#endif
 
 	switch (cmd) {
 	case WSDISPLAYIO_GETCMAP:
@@ -420,6 +484,11 @@
 		 * curently not implemented...
 		 */
 		return (EINVAL);
+#ifdef XXX_DEBUG
+	case HPCFBIO_XXX:
+		dsp_op = (struct hpcfb_dsp_op *)data;
+		return (mq200_xxx(sc, dsp_op));
+#endif
 	}
 
 	return (ENOTTY);
@@ -437,4 +506,251 @@
 		return -1;
 
 	return mips_btop(sc->sc_baseaddr + offset);
+}
+
+#define  FBitBLT (2 << 8)
+
+static void
+mq200_erase(ctx, x, y, h, w, at)
+void *ctx;
+int x, y, h, w, at;
+{
+	struct mq200_softc *sc = ctx;
+	u_int32_t ge1, ge2;
+
+	ge1 = _mask(w, 12) | _mask(h, 12) << 16;
+	ge2 = _mask(x, 12) | _mask(y, 12) << 16;
+
+	wait_cmd_FIFO(sc, 4);
+
+	write_ge_reg(1, ge1);
+	write_ge_reg(2, ge2);
+	write_ge_reg(0x42, at);
+	write_ge_reg(0, (1 << 15) | (1 << 23) | FBitBLT);
+}
+
+static void
+mq200_bitblit(ctx, sx, sy, dx, dy, h, w)
+void *ctx;
+int sx, sy, dx, dy, h, w;
+{
+	struct mq200_softc *sc = ctx;
+	u_int32_t ge0, ge1, ge2, ge3;
+
+	ge0 = 0xcc | FBitBLT;
+	if (sx < dx) {
+		ge0 |= 1 << 11;
+		sx += w - 1;
+		dx += w - 1;
+	}
+	if (sy < dy){
+		ge0 |= 1 << 12;
+		sy += h - 1;
+		dy += h - 1;
+	}
+
+	ge3 = _mask(sx, 12) | _mask(sy, 12) << 16;
+	ge1 = _mask(w, 12) | _mask(h, 12) << 16;
+	ge2 = _mask(dx, 12) | _mask(dy, 12) << 16;
+
+	wait_cmd_FIFO(sc, 4);
+	
+	write_ge_reg(3, ge3);
+	write_ge_reg(1, ge1);
+	write_ge_reg(2, ge2);
+	write_ge_reg(0, ge0);
+}
+
+#ifdef XXX_DEBUG
+int
+mq200_xxx(sc, dsp_op)
+struct mq200_softc *sc;
+struct hpcfb_dsp_op *dsp_op;
+{
+	switch (dsp_op->op) {
+	case 1:
+		dsp_op->args[1] = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+				  dsp_op->args[0]);
+				  
+		break;
+	case 2:
+		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+				  dsp_op->args[0],
+				  dsp_op->args[1]);
+		break;
+	case 3:
+		dsp_op->args[0] = hpcfb_accel;
+		dsp_op->args[1] = resetcount;
+		dsp_op->args[2] = loopcount;
+		break;
+	case 4:
+		hpcfb_accel = dsp_op->args[0];
+		break;
+	default:
+		return (EINVAL);
+	}
+	return (0);
+}
+#endif
+
+void
+mq200_setclut(ctx, ri)
+void *ctx;
+struct rasops_info *ri;
+{
+	struct mq200_softc *sc = ctx;
+	int error;
+
+
+	error = mq200_init_fontbuf(sc, ri->ri_font);
+	if (error)
+		hpcfb_accel = 0;
+}
+
+void
+mq200_putchar(ctx, dx, dy, font, fg, bg, uc, attr)
+void *ctx;
+int dy, dx;
+struct wsdisplay_font *font;
+u_int uc;
+int fg, bg;
+int attr;
+{
+        struct mq200_softc *sc = ctx;
+ 	u_int32_t ge0;
+	int sx, sy;
+	int fi;
+#if 1
+	static int bfg = -1, bbg = -1;  
+#endif
+	
+	if (!font || !sc)
+		return;
+
+	fi = uc - font->firstchar;
+	if (fi < 0 || fi >= font->numchars) {
+		return;
+	}
+
+	sx = sc->sc_fontp[fi].x;
+	sy = sc->sc_fontp[fi].y;
+
+#define  FBitBLT (2 << 8)
+	ge0 = 0xcc | FBitBLT | (1 << 20) | (1 << 24) | (1 << 14);
+
+
+	if (fg != bfg || bg != bbg) {
+		wait_cmd_FIFO(sc, 7);
+		write_ge_reg(0x7, fg);
+		write_ge_reg(0x8, bg);
+		bfg = fg;
+		bbg = bg;
+	} else {
+		wait_cmd_FIFO(sc, 5);
+	}
+
+	write_ge_reg(0x9, (8 - font->fontwidth) << 25);
+	write_ge_reg(3, sx | (sy << 16));
+	write_ge_reg(1, font->fontwidth | (font->fontheight << 16));
+	write_ge_reg(2, dx | (dy << 16));
+	write_ge_reg(0, ge0);
+}
+
+
+int
+mq200_init_fontbuf(sc, f)
+	struct mq200_softc *sc;
+	struct wsdisplay_font *f;
+{
+	struct hpcfb_fbconf *fbconf = &sc->sc_fbconf;
+	u_char *sp;
+	bus_size_t dp;
+	u_int16_t y;
+	int numchars, count, i;
+	struct coordinate *font_c;
+	u_int32_t reg;
+
+	if (!f || f->fontwidth > 8) {
+		return (EINVAL);
+	}
+
+	font_c = (struct coordinate *)malloc(f->numchars * sizeof(struct coordinate), M_DEVBUF, M_WAITOK);
+	sc->sc_fontp = font_c;
+	if (!font_c)
+		return (ENOMEM);
+
+	/* init font buffer */
+	numchars = f->numchars;
+	count = 0;
+	y = fbconf->hf_height;
+	sp = f->data;
+	dp =  MQ200_FRAMEBUFFER + fbconf->hf_offset
+	  + fbconf->hf_bytes_per_line * y;
+	while (numchars >= (fbconf->hf_bytes_per_line >> 4)) {
+		bus_size_t _dp = dp;
+
+		for (i = 0; i < (fbconf->hf_bytes_per_line >> 4); i++) {
+			bus_space_write_region_1(sc->sc_iot, sc->sc_ioh,
+						_dp, sp, f->fontheight);
+			font_c[count].x = i << 3;
+			font_c[count].y = y;
+			count++;
+			_dp += 16;
+			sp += f->fontheight;
+		}
+		dp += fbconf->hf_bytes_per_line;
+		y++;
+		numchars -= fbconf->hf_bytes_per_line >> 4;
+	}
+	for (i = 0; i < numchars; i++) {
+		bus_space_write_region_1(sc->sc_iot, sc->sc_ioh,
+					 dp, sp, f->fontheight);
+		font_c[count].x = i << 3;
+		font_c[count].y = y;
+		count++;
+		dp += 16;
+		sp += f->fontheight;
+	}
+	sc->sc_fontp = font_c;
+
+	/* init hardware cursor */
+	dp = (dp + (1 << 10) - 1) & ~((1 << 10) - 1);
+	bus_space_set_region_4(sc->sc_iot, sc->sc_ioh,
+			       dp, 0xffffffff, 1024 >> 2);
+	reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_GC1 + 0x31*4);
+	
+	reg &= ~(((1 << 10) - 1)| (63 << 16)|(63 << 24));
+	reg |= (dp >> 10) | (64 - f->fontwidth) << 16 | (64 - f->fontheight) << 24;
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MQ200_GC1 + 0x31*4, reg);
+
+	return (0);
+}
+
+static void
+mq200_cursor(ctx, on, x, y, w, h)
+void *ctx;
+int on, x, y, w, h;
+{
+        struct mq200_softc *sc = ctx;
+	u_int32_t reg20, reg;
+	int status;
+
+	if (!sc)
+		return;
+        reg20 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_GC1 + 0x20*4);
+	status = reg20 & (1 << 8) ? 1 : 0;
+
+	if (on) {
+		reg20 |= 1 << 8;
+		reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+				       MQ200_GC1 + 0x30*4);
+		reg &= ~0xfff0fff;
+		reg |= _mask(x, 12) | _mask(y, 12) << 16;
+		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+				  MQ200_GC1 + 0x30*4, reg);
+	} else {
+		reg20 &= ~(1 << 8);
+	}
+	if (status != on)
+		bus_space_write_4(sc->sc_iot, sc->sc_ioh, MQ200_GC1 + 0x20*4, reg20);
 }
--- hpcfbio.h.org	Sun Mar 12 14:04:46 2000
+++ hpcfbio.h	Sun Dec  3 00:30:56 2000
@@ -1,4 +1,5 @@
 /*	$NetBSD: hpcfbio.h,v 1.1 2000/03/12 05:04:46 takemura Exp $	*/
+/* modified by Y.Inoue */
 
 /*-
  * Copyright (c) 1999
@@ -37,6 +38,8 @@
 #ifndef H_HPCFBIO
 #define	H_HPCFBIO
 
+#define XXX_DEBUG
+ 
 #include <sys/types.h>
 #include <sys/ioccom.h>
 
@@ -236,5 +239,9 @@
 #define	HPCFBIO_SDSPCONF	_IOW('H', 3, struct hpcfb_dspconf)
 #define	HPCFBIO_GOP		_IOR('H', 4, struct hpcfb_dsp_op)
 #define	HPCFBIO_SOP		_IOWR('H', 5, struct hpcfb_dsp_op)
+
+#ifdef XXX_DEBUG
+#define	HPCFBIO_XXX		_IOWR('H', 6, struct hpcfb_dsp_op)
+#endif
 
 #endif /* H_HPCFBIO */
--- hpcfb.c.org	Tue Oct 17 08:53:40 2000
+++ hpcfb.c	Sun Dec  3 00:30:40 2000
@@ -1,4 +1,5 @@
 /*	$NetBSD: hpcfb.c,v 1.6.4.2 2000/08/06 04:18:21 takemura Exp $	*/
+/* modified by Y.Inoue */
 
 /*-
  * Copyright (c) 1999
@@ -82,6 +83,8 @@
 #define	DPRINTF(arg)
 #endif
 
+#define XXX_DEBUG
+
 #ifndef HPCFB_DISABLE
 #define HPCFB_HOOK
 #define HPCFB_TVRAM
@@ -98,6 +101,8 @@
 #endif
 #endif /* HPCFBRASOPS_DISABLE */
 
+int	hpcfb_accel = 1;
+
 #ifdef HPCFB_TVRAM
 struct hpcfb_vchar {
 	u_int c;
@@ -543,6 +548,9 @@
 	case HPCFBIO_SDSPCONF:
 	case HPCFBIO_GOP:
 	case HPCFBIO_SOP:
+#ifdef XXX_DEBUG
+	case HPCFBIO_XXX:
+#endif
 		return (*sc->sc_accessops->ioctl)(sc->sc_accessctx,
 						  cmd, data, flag, p);
 
@@ -767,11 +775,11 @@
 #endif /* HPCFB_TVRAM */
 
 #ifdef HPCFB_TVRAM
-	if (sc && sc->sc_accessops->cursor) {
-		xoff = col * ri->ri_xscale;
-		yoff = row * ri->ri_yscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->cursor) {
+		xoff = col * ri->ri_font->fontwidth;
+		yoff = row * ri->ri_font->fontheight;
 		curheight = ri->ri_font->fontheight;
-		curwidth = ri->ri_xscale;
+		curwidth = ri->ri_font->fontwidth;
 		(*sc->sc_accessops->cursor)(sc->sc_accessctx,
 				on, xoff, yoff, curwidth, curheight);
 	} else 
@@ -844,12 +852,12 @@
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 #endif /* HPCFB_TVRAM */
 #ifdef HPCFB_TVRAM
-	if (sc && sc->sc_accessops->putchar) {
-		yoff = row * ri->ri_yscale;
-		xoff =  col * ri->ri_xscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->putchar) {
+		xoff =  col * ri->ri_font->fontwidth;
+		yoff = row * ri->ri_font->fontheight;
 		fclr = ri->ri_devcmap[((u_int)attr >> 24) & 15];
 		uclr = ri->ri_devcmap[((u_int)attr >> 16) & 15];
-
+		font = ri->ri_font;
 		(*sc->sc_accessops->putchar)(sc->sc_accessctx,
 				xoff, yoff, font, fclr, uclr, uc, attr);
 	} else
@@ -899,13 +907,13 @@
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 #endif /* HPCFB_TVRAM */
 #ifdef HPCFB_TVRAM
-	if (sc && sc->sc_accessops->bitblit) {
-		srcxoff = srccol * ri->ri_xscale;
-		srcyoff = row * ri->ri_yscale;
-		dstxoff = dstcol * ri->ri_xscale;
-		dstyoff = row * ri->ri_yscale;
-		width = ncols * ri->ri_xscale;
-		height = ri->ri_yscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->bitblit) {
+		srcxoff = srccol * ri->ri_font->fontwidth;
+		srcyoff = row * ri->ri_font->fontheight;
+		dstxoff = dstcol * ri->ri_font->fontwidth;
+		dstyoff = row * ri->ri_font->fontheight;
+		width = ncols * ri->ri_font->fontwidth;
+		height = ri->ri_font->fontheight;
 		(*sc->sc_accessops->bitblit)(sc->sc_accessctx,
 			srcxoff, srcyoff, dstxoff, dstyoff, height, width);
 	} else
@@ -961,13 +969,14 @@
 #endif /* HPCFB_TVRAM */
 
 #ifdef HPCFB_TVRAM
-	if (sc && sc->sc_accessops->erase) {
-		xoff = startcol * ri->ri_xscale;
-		yoff = row * ri->ri_yscale;
-		width = ncols * ri->ri_xscale;
-		height = ri->ri_yscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->erase) {
+		xoff = startcol * ri->ri_font->fontwidth;
+		yoff = row * ri->ri_font->fontheight;
+		width = ncols * ri->ri_font->fontwidth;
+		height = ri->ri_font->fontheight;
 		(*sc->sc_accessops->erase)(sc->sc_accessctx,
-			xoff, yoff, height, width, attr);
+			xoff, yoff, height, width,
+			ri->ri_devcmap[(attr >> 16) & 0xf]);
 	} else 
 #endif /* HPCFB_TVRAM */
 		rasops_emul.erasecols(ri, row, startcol, ncols, attr);
@@ -1044,11 +1053,11 @@
 #endif /* HPCFB_TVRAM */
 
 #if defined(HPCFB_TVRAM) && defined(HPCFB_REDRAW)
-	if (sc && sc->sc_accessops->bitblit) {
-		srcyoff = src * ri->ri_yscale;
-		dstyoff = dst * ri->ri_yscale;
-		width = ri->ri_stride;
-		height = num * ri->ri_yscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->bitblit) {
+		srcyoff = src * ri->ri_font->fontheight;
+		dstyoff = dst * ri->ri_font->fontheight;
+		width = ri->ri_width;
+		height = num * ri->ri_font->fontheight;
 		(*sc->sc_accessops->bitblit)(sc->sc_accessctx,
 			0, srcyoff, 0, dstyoff, height, width);
 	} else
@@ -1108,12 +1117,13 @@
 	struct rasops_info *ri = (struct rasops_info *)cookie;
 #endif /* HPCFB_TVRAM */
 #ifdef HPCFB_TVRAM
-	if (sc && sc->sc_accessops->erase) {
-		yoff = row * ri->ri_yscale;
-		width = ri->ri_stride;
-		height = nrow * ri->ri_yscale;
+	if (hpcfb_accel && sc && sc->sc_accessops->erase) {
+		yoff = row * ri->ri_font->fontheight;
+		width = ri->ri_width;
+		height = nrow * ri->ri_font->fontheight;
 		(*sc->sc_accessops->erase)(sc->sc_accessctx,
-			0, yoff, height, width, attr);
+			0, yoff, height, width,
+			ri->ri_devcmap[(attr >> 16) & 0xf]);
 	} else 
 #endif /* HPCFB_TVRAM */
 		rasops_emul.eraserows(ri, row, nrow, attr);