[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);