Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci one step closer to graphics acceleration:



details:   https://anonhg.NetBSD.org/src/rev/76ae1a297b13
branches:  trunk
changeset: 790293:76ae1a297b13
user:      macallan <macallan%NetBSD.org@localhost>
date:      Wed Oct 02 16:35:38 2013 +0000

description:
one step closer to graphics acceleration:
- probe and report actual amount of video memory
- add DMA machinery to feed commands to the graphics processor
- adapt a whole bunch of magic number initialization from xf86-video-nv, now
  the chip actually reads commands from a buffer in video memory

diffstat:

 sys/dev/pci/gffb.c |  290 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 270 insertions(+), 20 deletions(-)

diffs (truncated from 378 to 300 lines):

diff -r dc44bb9c6753 -r 76ae1a297b13 sys/dev/pci/gffb.c
--- a/sys/dev/pci/gffb.c        Wed Oct 02 16:32:40 2013 +0000
+++ b/sys/dev/pci/gffb.c        Wed Oct 02 16:35:38 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gffb.c,v 1.1 2013/09/18 14:30:45 macallan Exp $        */
+/*     $NetBSD: gffb.c,v 1.2 2013/10/02 16:35:38 macallan Exp $        */
 
 /*
  * Copyright (c) 2007, 2012 Michael Lorenz
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gffb.c,v 1.1 2013/09/18 14:30:45 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gffb.c,v 1.2 2013/10/02 16:35:38 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -40,6 +40,7 @@
 #include <sys/malloc.h>
 #include <sys/lwp.h>
 #include <sys/kauth.h>
+#include <sys/atomic.h>
 
 #include <dev/videomode/videomode.h>
 
@@ -81,6 +82,7 @@
        bus_addr_t sc_fb, sc_reg;
        bus_size_t sc_fbsize, sc_regsize;
        uint8_t *sc_fbaddr;
+       size_t sc_vramsize;
 
        int sc_width, sc_height, sc_depth, sc_stride;
        int sc_locked;
@@ -93,6 +95,7 @@
        u_char sc_cmap_red[256];
        u_char sc_cmap_green[256];
        u_char sc_cmap_blue[256];
+       int sc_put, sc_current, sc_free;
        glyphcache sc_gc;
 };
 
@@ -115,6 +118,8 @@
 
 static void    gffb_init(struct gffb_softc *);
 
+static void    gffb_make_room(struct gffb_softc *, int);
+
 #if notyet
 static void    gffb_flush_engine(struct gffb_softc *);
 static void    gffb_rectfill(struct gffb_softc *, int, int, int, int,
@@ -242,8 +247,16 @@
            &gffb_accessops);
        sc->vd.init_screen = gffb_init_screen;
 
+       sc->sc_vramsize = bus_space_read_4(sc->sc_memt, sc->sc_regh,
+           GFFB_VRAM) & 0xfff00000;
+
+       printf("vram: %d MB\n", sc->sc_vramsize >> 20);
+       printf("put: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT));
+       printf("get: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET));
        /* init engine here */
        gffb_init(sc);
+       printf("put: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT));
+       printf("get: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET));
 
        ri = &sc->sc_console_screen.scr_ri;
 
@@ -262,7 +275,7 @@
                gffb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
                    ri->ri_devcmap[(defattr >> 16) & 0xff]);
 #else
-               memset(sc->sc_fbaddr,
+               memset(sc->sc_fbaddr + 0x2000,
                    ri->ri_devcmap[(defattr >> 16) & 0xff],
                    sc->sc_height * sc->sc_stride);
 #endif
@@ -406,8 +419,8 @@
 
        /* 'regular' framebuffer mmap()ing */
        if (offset < sc->sc_fbsize) {
-               pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot,
-                   BUS_SPACE_MAP_LINEAR);
+               pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset + 0x2000,
+                   0, prot, BUS_SPACE_MAP_LINEAR);
                return pa;
        }
 
@@ -466,7 +479,7 @@
        ri->ri_width = sc->sc_width;
        ri->ri_height = sc->sc_height;
        ri->ri_stride = sc->sc_stride;
-       ri->ri_bits = sc->sc_fbaddr;
+       ri->ri_bits = sc->sc_fbaddr + 0x2000;
        ri->ri_flg = RI_CENTER;
        if (sc->sc_depth == 8)
                ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA;
@@ -594,29 +607,266 @@
        return 0;
 }
 
+
+static void
+gffb_dma_kickoff(struct gffb_softc *sc)
+{
+       volatile uint8_t scratch;
+
+       if(sc->sc_current != sc->sc_put) {
+               sc->sc_put = sc->sc_current;
+               membar_sync();
+               scratch = *sc->sc_fbaddr;
+               bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_PUT,
+                   sc->sc_put);
+       }
+}
+
+static void
+gffb_dmanext(struct gffb_softc *sc, uint32_t data)
+{
+       bus_space_write_stream_4(sc->sc_memt, sc->sc_fbh, sc->sc_current, data);
+       sc->sc_current += 4;
+}
+
+static void
+gffb_dmastart(struct gffb_softc *sc, uint32_t tag, int size)
+{
+       if(sc->sc_free <= (size << 2))
+               gffb_make_room(sc, size);
+       gffb_dmanext(sc, ((size) << 18) | (tag));
+       sc->sc_free -= ((size + 1) << 2);
+}
+
+/*
+ * from xf86_video_nv/nv_xaa.c:
+ * There is a HW race condition with videoram command buffers.
+ * You can't jump to the location of your put offset.  We write put
+ * at the jump offset + SKIPS dwords with noop padding in between
+ * to solve this problem
+ */
+
+#define SKIPS  8
+
+static void 
+gffb_make_room(struct gffb_softc *sc, int size)
+{
+       uint32_t get;
+
+       size = (size + 1) << 2; /* slots -> offset */
+
+       while (sc->sc_free < size) {
+               get = bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET);
+
+               if (sc->sc_put >= get) {
+                       sc->sc_free = 0x2000 - sc->sc_current;
+                       if (sc->sc_free < size) {
+                               gffb_dmanext(sc, 0x20000000);
+                               if(get <= SKIPS) {
+                                       if (sc->sc_put <= SKIPS) {
+                                               /* corner case - will be idle */
+                                               bus_space_write_4(sc->sc_memt,
+                                                   sc->sc_regh, GFFB_FIFO_PUT,
+                                                   SKIPS + 1);
+                                       }
+                                       do {
+                                               get = bus_space_read_4(
+                                                   sc->sc_memt, sc->sc_regh,
+                                                   GFFB_FIFO_GET);
+                                       } while (get <= SKIPS);
+                               }
+                               bus_space_write_4(sc->sc_memt, sc->sc_regh,
+                                    GFFB_FIFO_PUT, SKIPS);
+                               sc->sc_current = sc->sc_put = SKIPS;
+                               sc->sc_free = get - (SKIPS + 1);
+                       }
+               } else
+                       sc->sc_free = get - sc->sc_current - 1;
+       }
+}
+
+static void
+gffb_sync(struct gffb_softc *sc)
+{
+       int bail;
+
+       bail = 100000;
+       while ((bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_FIFO_GET) !=
+           sc->sc_put) && (bail > 0)) {
+               bail--;
+               delay(1);
+       }
+       if (bail == 0) printf("DMA timed out\n");
+
+       bail = 100000;
+       while((bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_BUSY) != 0) &&
+           (bail > 0)) {
+               bail--;
+               delay(1);
+       }
+       if (bail == 0) printf("engine timed out\n");
+}
+
 static void
 gffb_init(struct gffb_softc *sc)
 {
-#ifdef GFFB_DEBUG
-       int i, j;
-
-       /* dump the RAMDAC1 register space */
-       for (i = 0; i < 0x2000; i+= 32) {
-               printf("%04x:", i);
-               for (j = 0; j < 32; j += 4) {
-                       printf(" %08x", bus_space_read_4(sc->sc_memt, sc->sc_regh, GFFB_RAMDAC1 + i + j));
-               }
-               printf("\n");
-       }
-#endif
+       int i;
 
        /* init display start */
        bus_space_write_4(sc->sc_memt, sc->sc_regh,
-           GFFB_CRTC0 + GFFB_DISPLAYSTART, 0);
+           GFFB_CRTC0 + GFFB_DISPLAYSTART, 0x2000);
        bus_space_write_4(sc->sc_memt, sc->sc_regh,
-           GFFB_CRTC1 + GFFB_DISPLAYSTART, 0);
+           GFFB_CRTC1 + GFFB_DISPLAYSTART, 0x2000);
        bus_space_write_1(sc->sc_memt, sc->sc_regh,
            GFFB_PDIO0 + GFFB_PEL_MASK, 0xff);
        bus_space_write_1(sc->sc_memt, sc->sc_regh,
            GFFB_PDIO1 + GFFB_PEL_MASK, 0xff);
+       
+       /* DMA stuff. A whole lot of magic number voodoo from xf86-video-nv */
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PMC + 0x140, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PMC + 0x200, 0xffff00ff);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PMC + 0x200, 0xffffffff);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PTIMER + 0x800, 8);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PTIMER + 0x840, 3);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PTIMER + 0x500, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PTIMER + 0x400, 0xffffffff);
+       for (i = 0; i < 8; i++) {
+               bus_space_write_4(sc->sc_memt, sc->sc_regh,
+                   GFFB_PMC + 0x240 + (i * 0x10), 0);
+               bus_space_write_4(sc->sc_memt, sc->sc_regh,
+                   GFFB_PMC + 0x244 + (i * 0x10), sc->sc_vramsize - 1);
+       }
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN, 0x80000010);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x04, 0x80011201);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x08, 0x80000011);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x0c, 0x80011202);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x10, 0x80000012);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x14, 0x80011203);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x18, 0x80000013);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x1c, 0x80011204);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x20, 0x80000014);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x24, 0x80011205);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x28, 0x80000015);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2c, 0x80011206);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x30, 0x80000016);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x34, 0x80011207);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x38, 0x80000017);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x3c, 0x80011208);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2000, 0x00003000);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2004, sc->sc_vramsize - 1);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2008, 0x00000002);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x200c, 0x00000002);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2010, 0x01008042);  /* different for nv40 */
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2014, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2018, 0x12001200);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x201c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2020, 0x01008043);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2024, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2028, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x202c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2030, 0x01008044);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2034, 0x00000002);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2038, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x203c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2040, 0x01008019);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2044, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2048, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x204c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2050, 0x0100a05c);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2054, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2058, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x205c, 0);
+       /* XXX 0x0100805f if !WaitVSynvPossible */
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2060, 0x0100809f);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2064, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2068, 0x12001200);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x206c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2070, 0x0100804a);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2074, 0x00000002);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2078, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x207c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2080, 0x01018077);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2084, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2088, 0x12001200);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x208c, 0);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2090, 0x00003002);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2094, 0x00007fff);
+       bus_space_write_4(sc->sc_memt, sc->sc_regh, GFFB_PRAMIN + 0x2098, 0x00000002);  /* start of command buffer? */



Home | Main Index | Thread Index | Old Index