Module Name: src
Committed By: nat
Date: Mon Oct 17 20:04:48 UTC 2016
Modified Files:
src/sys/dev/usb: udl.c udl.h
Log Message:
Add a kthread to update display with framebuffer contents.
X11 will now work with wsfb(4).
OK christos@
To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/usb/udl.c
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/usb/udl.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/udl.c
diff -u src/sys/dev/usb/udl.c:1.15 src/sys/dev/usb/udl.c:1.16
--- src/sys/dev/usb/udl.c:1.15 Mon Oct 17 19:58:42 2016
+++ src/sys/dev/usb/udl.c Mon Oct 17 20:04:48 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udl.c,v 1.15 2016/10/17 19:58:42 nat Exp $ */
+/* $NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $ */
/*-
* Copyright (c) 2009 FUKAUMI Naoki.
@@ -53,7 +53,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.15 2016/10/17 19:58:42 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.16 2016/10/17 20:04:48 nat Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -61,6 +61,8 @@ __KERNEL_RCSID(0, "$NetBSD: udl.c,v 1.15
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kmem.h>
+#include <sys/kthread.h>
+#include <sys/condvar.h>
#include <uvm/uvm.h>
#include <sys/bus.h>
@@ -172,6 +174,7 @@ static uint16_t udl_lfsr(uint16_t);
static int udl_set_resolution(struct udl_softc *,
const struct videomode *);
static const struct videomode *udl_videomode_lookup(const char *);
+static void udl_update_thread(void *);
static inline void
udl_cmd_add_1(struct udl_softc *sc, uint8_t val)
@@ -468,6 +471,12 @@ udl_attach(device_t parent, device_t sel
config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
+
+ mutex_init(&sc->sc_thread_mtx, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->sc_thread_cv, "udlcv");
+ sc->sc_dying = false;
+ kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL,
+ udl_update_thread, sc, &sc->sc_thread, "udlupd");
}
static int
@@ -492,9 +501,6 @@ udl_detach(device_t self, int flags)
usbd_close_pipe(sc->sc_tx_pipeh);
}
- cv_destroy(&sc->sc_cv);
- mutex_destroy(&sc->sc_mtx);
-
/*
* Free Huffman table.
*/
@@ -504,6 +510,15 @@ udl_detach(device_t self, int flags)
* Free framebuffer memory.
*/
udl_fbmem_free(sc);
+
+ sc->sc_dying = true;
+ cv_broadcast(&sc->sc_thread_cv);
+ kthread_join(sc->sc_thread);
+
+ cv_destroy(&sc->sc_cv);
+ mutex_destroy(&sc->sc_mtx);
+ cv_destroy(&sc->sc_thread_cv);
+ mutex_destroy(&sc->sc_thread_mtx);
/*
* Detach wsdisplay.
@@ -637,6 +652,7 @@ udl_mmap(void *v, void *vs, off_t off, i
if (udl_fbmem_alloc(sc) != 0)
return -1;
+ cv_broadcast(&sc->sc_thread_cv);
vaddr = (vaddr_t)sc->sc_fbmem + off;
rv = pmap_extract(pmap_kernel(), vaddr, &paddr);
KASSERT(rv);
@@ -810,11 +826,24 @@ static int
udl_fbmem_alloc(struct udl_softc *sc)
{
+ mutex_enter(&sc->sc_thread_mtx);
if (sc->sc_fbmem == NULL) {
- sc->sc_fbmem = kmem_alloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
- if (sc->sc_fbmem == NULL)
+ sc->sc_fbmem = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+ if (sc->sc_fbmem == NULL) {
+ mutex_exit(&sc->sc_thread_mtx);
+ return -1;
+ }
+ }
+ if (sc->sc_fbmem_prev == NULL) {
+ sc->sc_fbmem_prev = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+ if (sc->sc_fbmem_prev == NULL) {
+ kmem_free(sc->sc_fbmem, UDL_FBMEM_SIZE(sc));
+ sc->sc_fbmem = NULL;
+ mutex_exit(&sc->sc_thread_mtx);
return -1;
+ }
}
+ mutex_exit(&sc->sc_thread_mtx);
return 0;
}
@@ -823,10 +852,16 @@ static void
udl_fbmem_free(struct udl_softc *sc)
{
+ mutex_enter(&sc->sc_thread_mtx);
if (sc->sc_fbmem != NULL) {
kmem_free(sc->sc_fbmem, UDL_FBMEM_SIZE(sc));
sc->sc_fbmem = NULL;
}
+ if (sc->sc_fbmem_prev != NULL) {
+ kmem_free(sc->sc_fbmem_prev, UDL_FBMEM_SIZE(sc));
+ sc->sc_fbmem_prev = NULL;
+ }
+ mutex_exit(&sc->sc_thread_mtx);
}
static int
@@ -1763,3 +1798,82 @@ udl_videomode_lookup(const char *name)
return NULL;
}
+
+static void
+udl_update_thread(void *v)
+{
+ struct udl_softc *sc = v;
+ int stride;
+#ifdef notyet
+ bool update = false;
+ int linecount, x, y;
+ uint16_t *fb, *fbcopy;
+ uint8_t *curfb;
+#else
+ uint16_t *fb;
+ int offs;
+#endif
+
+ mutex_enter(&sc->sc_thread_mtx);
+
+ for (;;) {
+ stride = min(sc->sc_width, UDL_CMD_WIDTH_MAX - 8);
+ if (sc->sc_dying == true) {
+ mutex_exit(&sc->sc_thread_mtx);
+ kthread_exit(0);
+ }
+
+ if (sc->sc_fbmem == NULL)
+ goto thread_wait;
+
+#ifdef notyet
+ curfb = kmem_zalloc(UDL_FBMEM_SIZE(sc), KM_SLEEP);
+ memcpy(curfb, sc->sc_fbmem, sc->sc_height * sc->sc_width * 2);
+ fb = (uint16_t *)curfb;
+ fbcopy = (uint16_t *)sc->sc_fbmem_prev;
+ for (y = 0; y < sc->sc_height; y++) {
+ linecount = 0;
+ update = false;
+ for (x = 0; x < sc->sc_width; x++) {
+ if (linecount >= stride) {
+ udl_draw_line(sc, &fb[y * sc->sc_width
+ + x - linecount], y * sc->sc_width
+ + x - linecount, linecount);
+ linecount = 0;
+ update = false;
+ }
+ if (fb[y * sc->sc_width + x] ^ fbcopy[y *
+ sc->sc_width + x]) {
+ update = true;
+ linecount ++;
+ } else if (update == true) {
+ udl_draw_line(sc, &fb[y * sc->sc_width
+ + x - linecount], y * sc->sc_width
+ + x - linecount, linecount);
+ linecount = 0;
+ update = false;
+ }
+ }
+ if (linecount) {
+ udl_draw_line(sc, &fb[y * sc->sc_width + x -
+ linecount], y * sc->sc_width + x -
+ linecount, linecount);
+ }
+ }
+ memcpy(sc->sc_fbmem_prev, curfb, sc->sc_height * sc->sc_width
+ * 2);
+ kmem_free(curfb, UDL_FBMEM_SIZE(sc));
+#else
+ fb = (uint16_t *)sc->sc_fbmem;
+ for (offs = 0; offs < sc->sc_height * sc->sc_width; offs += stride)
+ udl_draw_line(sc, &fb[offs], offs, stride);
+
+#endif
+
+ kpause("udlslp", false, (40 * hz)/1000 + 1, &sc->sc_thread_mtx);
+ continue;
+
+thread_wait:
+ cv_wait(&sc->sc_thread_cv, &sc->sc_thread_mtx);
+ }
+}
Index: src/sys/dev/usb/udl.h
diff -u src/sys/dev/usb/udl.h:1.2 src/sys/dev/usb/udl.h:1.3
--- src/sys/dev/usb/udl.h:1.2 Sat Apr 23 10:15:32 2016
+++ src/sys/dev/usb/udl.h Mon Oct 17 20:04:48 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: udl.h,v 1.2 2016/04/23 10:15:32 skrll Exp $ */
+/* $NetBSD: udl.h,v 1.3 2016/10/17 20:04:48 nat Exp $ */
/*-
* Copyright (c) 2009 FUKAUMI Naoki.
@@ -108,6 +108,7 @@ struct udl_softc {
uint8_t sc_nscreens;
uint8_t *sc_fbmem; /* framebuffer for X11 */
+ uint8_t *sc_fbmem_prev; /* prev. framebuffer */
#define UDL_FBMEM_SIZE(sc) \
((sc)->sc_width * (sc)->sc_height * ((sc)->sc_depth / 8))
@@ -115,6 +116,11 @@ struct udl_softc {
uint8_t *sc_huffman_base;
size_t sc_huffman_size;
+ kcondvar_t sc_thread_cv;
+ kmutex_t sc_thread_mtx;
+ bool sc_dying;
+ lwp_t *sc_thread;
+
kcondvar_t sc_cv;
kmutex_t sc_mtx;