Add WSDISPLAYIO_SETGFXMODE ioctl on LUNA's frame buffer.
authoraoyama <aoyama@openbsd.org>
Wed, 15 Jan 2014 11:13:53 +0000 (11:13 +0000)
committeraoyama <aoyama@openbsd.org>
Wed, 15 Jan 2014 11:13:53 +0000 (11:13 +0000)
This ioctl changes `pseudo' frame buffer depth, in order to use color
wscons and monochrome X server both.  Also need to some
luna88k-specific initialization in
xenocara/driver/xf86-video-wsfb/src/wsfb_driver.c.

sys/arch/luna88k/dev/lunafb.c

index 18b4f29..a0f594e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: lunafb.c,v 1.20 2014/01/03 13:48:25 aoyama Exp $ */
+/* $OpenBSD: lunafb.c,v 1.21 2014/01/15 11:13:53 aoyama Exp $ */
 /* $NetBSD: lunafb.c,v 1.7.6.1 2002/08/07 01:48:34 lukem Exp $ */
 
 /*-
@@ -159,6 +159,10 @@ int        omfb_show_screen(void *, void *, int, void (*) (void *, int, int),
            void *);
 int    omfb_load_font(void *, void *, struct wsdisplay_font *);
 int    omfb_list_font(void *, struct wsdisplay_font *);
+int    omfb_set_gfxmode(struct omfb_softc *, struct wsdisplay_gfx_mode *);
+
+void   omfb_set_default_cmap(struct om_hwdevconfig *);
+void   omfb_clear_framebuffer(struct om_hwdevconfig *);
 
 const struct wsdisplay_accessops omfb_accessops = {
        .ioctl = omfbioctl,
@@ -279,6 +283,9 @@ omfbioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
                *(u_int *)data = WSDISPLAYIO_DEPTH_1;
                break;
 
+        case WSDISPLAYIO_SETGFXMODE:
+                return omfb_set_gfxmode(sc, (struct wsdisplay_gfx_mode *)data);
+
        case WSDISPLAYIO_SVIDEO:
        case WSDISPLAYIO_GVIDEO:
                break;
@@ -404,7 +411,6 @@ omsetcmap(struct omfb_softc *sc, struct wsdisplay_cmap *p)
 void
 omfb_getdevconfig(paddr_t paddr, struct om_hwdevconfig *dc)
 {
-       int bpp, i;
        struct rasops_info *ri;
        union {
                struct { short h, v; } p;
@@ -434,67 +440,15 @@ omfb_getdevconfig(paddr_t paddr, struct om_hwdevconfig *dc)
                dc->dc_depth_checked = 1;
        }
 
-#if 1 /* XXX: Xorg mono server works only bpp == 1 for now */
-       switch (hwplanebits) {
-       case 8:
-               bpp = 8;
-               break;
-       default:
-       case 4:
-               bpp = 4;
-               break;
-       case 1:
-               bpp = 1;
-               break;
-       }
-#else
-       bpp = 1;
-#endif
        dc->dc_wid = 1280;
        dc->dc_ht = 1024;
-       dc->dc_depth = bpp;
+       dc->dc_depth = hwplanebits;
        dc->dc_rowbytes = 2048 / 8;
-       dc->dc_cmsize = (bpp == 1) ? 0 : 1 << bpp;
+       dc->dc_cmsize = (hwplanebits == 1) ? 0 : 1 << hwplanebits;
        dc->dc_videobase = paddr;
 
-       /* WHITE on BLACK */
-       if ((hwplanebits == 1) || (hwplanebits == 4)) {
-               struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
-
-               odac->bt_addr = 0;
-               for (i = 0; i < 16; i++) {
-                       odac->bt_cmap = dc->dc_cmap.r[i] = ansicmap[i].r;
-                       odac->bt_cmap = dc->dc_cmap.g[i] = ansicmap[i].g;
-                       odac->bt_cmap = dc->dc_cmap.b[i] = ansicmap[i].b;
-               }
-       } else if (hwplanebits == 8) {
-               struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
-
-               /*
-                * Initialize the Bt458.  When we write to control registers,
-                * the address is not incremented automatically. So we specify
-                * it ourselves for each control register.
-                */
-               ndac->bt_addr = 0x04;
-               ndac->bt_ctrl = 0xff; /* all planes will be read */
-               ndac->bt_addr = 0x05;
-               ndac->bt_ctrl = 0x00; /* all planes have non-blink */
-               ndac->bt_addr = 0x06;
-               ndac->bt_ctrl = 0x40; /* palette enabled, ovly plane disabled */
-               ndac->bt_addr = 0x07;
-               ndac->bt_ctrl = 0x00; /* no test mode */
-
-               /*
-                * Set ANSI 16 colors.  We only supports 4bpp console right
-                * now, repeat 16 colors in 256 colormap.
-                */
-               ndac->bt_addr = 0;
-               for (i = 0; i < 256; i++) {
-                       ndac->bt_cmap = dc->dc_cmap.r[i] = ansicmap[i % 16].r;
-                       ndac->bt_cmap = dc->dc_cmap.g[i] = ansicmap[i % 16].g;
-                       ndac->bt_cmap = dc->dc_cmap.b[i] = ansicmap[i % 16].b;
-               }
-       }
+       /* set default colormap */
+       omfb_set_default_cmap(dc);
 
        /* adjust h/v origin on screen */
        rfcnt.p.h = 7;
@@ -503,11 +457,7 @@ omfb_getdevconfig(paddr_t paddr, struct om_hwdevconfig *dc)
        *(volatile u_int32_t *)OMFB_RFCNT = rfcnt.u;
 
        /* clear the screen */
-       *(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;
-       ((volatile u_int32_t *)OMFB_ROPFUNC)[5] = ~0;   /* ROP copy */
-       for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
-               *((volatile u_int32_t *)dc->dc_videobase + i) = 0;
-       *(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;
+       omfb_clear_framebuffer(dc);
 
        /* initialize the raster */
        ri = &dc->dc_ri;
@@ -589,3 +539,140 @@ omfb_list_font(void *v, struct wsdisplay_font *font)
 
        return rasops_list_font(ri, font);
 }
+
+/*
+ * Change `pseudo' depth, set the default colormap, and clear frame buffer.
+ * Note: when called with depth == 0, change to the original hardware depth. 
+ */
+int
+omfb_set_gfxmode(struct omfb_softc *sc, struct wsdisplay_gfx_mode *wsd_gfxmode)
+{
+        /* LUNA's fb is fixed size */
+        if ((wsd_gfxmode->width != sc->sc_dc->dc_wid)
+                || (wsd_gfxmode->height != sc->sc_dc->dc_ht))
+                        return -1;
+
+       /* if depth == 0, set the original hardware depth */
+       if (wsd_gfxmode->depth == 0)
+               wsd_gfxmode->depth = hwplanebits;
+
+        switch (wsd_gfxmode->depth) {
+        case 1:
+               /* all frame buffer support this */
+               sc->sc_dc->dc_depth = 1;
+               sc->sc_dc->dc_cmsize = 0;
+                break;
+        case 4:
+               if ((hwplanebits == 4) || (hwplanebits == 8)) {
+                       sc->sc_dc->dc_depth = 4;
+                       sc->sc_dc->dc_cmsize = 16;
+                       break;
+               } else
+                       return -1;
+        case 8:
+               if (hwplanebits == 8) {
+                       sc->sc_dc->dc_depth = 8;
+                       sc->sc_dc->dc_cmsize = 256;
+                       break;
+               } else
+                       return -1;
+        default:
+                return -1;
+        }
+
+       omfb_set_default_cmap(sc->sc_dc);
+       omfb_clear_framebuffer(sc->sc_dc);
+
+        return 0;
+}
+
+/*
+ * Clear all planes of frame buffer
+ */
+void
+omfb_clear_framebuffer(struct om_hwdevconfig *dc)
+{
+       int i;
+
+       *(volatile u_int32_t *)OMFB_PLANEMASK = 0xff;   /* all planes */
+       ((volatile u_int32_t *)OMFB_ROPFUNC)[5] = ~0;   /* ROP copy */
+       for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
+               *((volatile u_int32_t *)dc->dc_videobase + i) = 0;
+       *(volatile u_int32_t *)OMFB_PLANEMASK = 0x01;   /* plane #0 only */
+}
+
+/*
+ * set default colormap; white on black for 1bpp, ANSI 16 colors for 4/8 bpp.
+ */
+void
+omfb_set_default_cmap(struct om_hwdevconfig *dc)
+{
+       int i;
+
+       if ((hwplanebits == 1) || (hwplanebits == 4)) {
+               struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
+
+               odac->bt_addr = 0;
+               if (dc->dc_depth == 1) {
+                       /* white on black */
+                       for (i = 0; i < 16; i++) {
+                               u_int8_t val = i % 2 ? 255 : 0;
+
+                               odac->bt_cmap = dc->dc_cmap.r[i] = val;
+                               odac->bt_cmap = dc->dc_cmap.g[i] = val;
+                               odac->bt_cmap = dc->dc_cmap.b[i] = val;
+                       }
+               } else {
+                       for (i = 0; i < 16; i++) {
+                       /* ANSI 16 colors */
+                               odac->bt_cmap = dc->dc_cmap.r[i]
+                                   = ansicmap[i].r;
+                               odac->bt_cmap = dc->dc_cmap.g[i]
+                                   = ansicmap[i].g;
+                               odac->bt_cmap = dc->dc_cmap.b[i]
+                                   = ansicmap[i].b;
+                       }
+               }
+       } else if (hwplanebits == 8) {
+               struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
+
+               /*
+                * Initialize the Bt458.  When we write to control registers,
+                * the address is not incremented automatically. So we specify
+                * it ourselves for each control register.
+                */
+               ndac->bt_addr = 0x04;
+               ndac->bt_ctrl = 0xff; /* all planes will be read */
+               ndac->bt_addr = 0x05;
+               ndac->bt_ctrl = 0x00; /* all planes have non-blink */
+               ndac->bt_addr = 0x06;
+               ndac->bt_ctrl = 0x40; /* palette enabled, ovly plane disabled */
+               ndac->bt_addr = 0x07;
+               ndac->bt_ctrl = 0x00; /* no test mode */
+
+               ndac->bt_addr = 0;
+               if (dc->dc_depth == 1) {
+                       /* white on black */
+                       for (i = 0; i < 256; i++) {
+                               u_int8_t val = i % 2 ? 255 : 0;
+
+                               ndac->bt_cmap = dc->dc_cmap.r[i] = val;
+                               ndac->bt_cmap = dc->dc_cmap.g[i] = val;
+                               ndac->bt_cmap = dc->dc_cmap.b[i] = val;
+                       }
+               } else {
+                       /*
+                        * Set ANSI 16 colors.  We only supports 4bpp console
+                        * right now, repeat 16 colors in 256 colormap.
+                        */
+                       for (i = 0; i < 256; i++) {
+                               ndac->bt_cmap = dc->dc_cmap.r[i]
+                                   = ansicmap[i % 16].r;
+                               ndac->bt_cmap = dc->dc_cmap.g[i]
+                                   = ansicmap[i % 16].g;
+                               ndac->bt_cmap = dc->dc_cmap.b[i]
+                                   = ansicmap[i % 16].b;
+                       }
+               }
+       }
+}