--- a/drivers.m4
+++ b/drivers.m4
@@ -39,7 +39,7 @@ AC_ARG_WITH(
   [                        Newhaven, Noritake, NULL, Pertelian, PHAnderson,]
   [                        PICGraphic, picoLCD, picoLCDGraphic, PNG, PPM, RouterBoard,]
   [                        Sample, SamsungSPF, serdisplib, ShuttleVFD, SimpleLCD, st2205, T6963,]
-  [                        TeakLCM, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
+  [                        TeakLCM, TEW673GRU, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
   drivers=$withval,
   drivers=all
 )
@@ -107,6 +107,7 @@ for driver in $drivers; do
 	 SHUTTLEVFD="yes"
          SIMPLELCD="yes"
          T6963="yes"
+         TEW673GRU="yes"
          TeakLCM="yes"
          Trefon="yes"
          ULA200="yes"
@@ -260,6 +261,9 @@ for driver in $drivers; do
       TeakLCM)
          TeakLCM=$val
          ;;
+      TEW673GRU)
+         TEW673GRU=$val
+         ;;
       Trefon)
          Trefon=$val
          ;;
@@ -797,6 +801,18 @@ if test "$TeakLCM" = "yes"; then
    AC_DEFINE(WITH_TEAK_LCM,1,[TeakLCM driver])
 fi
 
+if test "$TEW673GRU" = "yes"; then
+   if test "$has_spidev" = "true"; then
+      GRAPHIC="yes"
+      TEXT="yes"
+      SPIDEV="yes"
+      DRIVERS="$DRIVERS drv_TEW673GRU.o"
+      AC_DEFINE(WITH_TEW673GRU,1,[TEW673GRU driver])
+   else
+      AC_MSG_WARN(linux/spi/spidev.h not found: TEW673GRU driver disabled)
+   fi
+fi
+
 if test "$Trefon" = "yes"; then
    if test "$has_usb" = "true"; then
       TEXT="yes"
--- a/drv.c
+++ b/drv.c
@@ -92,6 +92,7 @@ extern DRIVER drv_serdisplib;
 extern DRIVER drv_ShuttleVFD;
 extern DRIVER drv_SimpleLCD;
 extern DRIVER drv_T6963;
+extern DRIVER drv_TEW673GRU;
 extern DRIVER drv_TeakLCM;
 extern DRIVER drv_Trefon;
 extern DRIVER drv_ula200;
@@ -248,6 +249,9 @@ DRIVER *Driver[] = {
 #ifdef WITH_TEAK_LCM
     &drv_TeakLCM,
 #endif
+#ifdef WITH_TEW673GRU
+    &drv_TEW673GRU,
+#endif
 #ifdef WITH_TREFON
     &drv_Trefon,
 #endif
--- a/Makefile.am
+++ b/Makefile.am
@@ -119,6 +119,7 @@ drv_ShuttleVFD.c              \
 drv_SimpleLCD.c               \
 drv_T6963.c                   \
 drv_TeakLCM.c                 \
+drv_TEW673GRU.c               \
 drv_Trefon.c                  \
 drv_ula200.c                  \
 drv_USBHUB.c                  \
--- /dev/null
+++ b/drv_TEW673GRU.c
@@ -0,0 +1,457 @@
+/* $Id$
+ * $URL$
+ *
+ * TRENDnet TEW673GRU LCD4linux driver
+ *
+ * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * based on the Sample driver which is:
+ * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
+ * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ *
+ * This file is part of LCD4Linux.
+ *
+ * LCD4Linux is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * LCD4Linux is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * exported fuctions:
+ *
+ * struct DRIVER drv_TEW673GRU
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "debug.h"
+#include "cfg.h"
+#include "qprintf.h"
+#include "udelay.h"
+#include "plugin.h"
+#include "widget.h"
+#include "widget_text.h"
+#include "widget_icon.h"
+#include "widget_bar.h"
+#include "drv.h"
+
+#include "drv_generic_text.h"
+#include "drv_generic_graphic.h"
+#include "drv_generic_spidev.h"
+
+#ifdef WITH_DMALLOC
+#include <dmalloc.h>
+#endif
+
+#define TEW673GRU_NUM_COLS	220
+#define TEW673GRU_NUM_ROWS	176
+#define TEW673GRU_BPP		2	/* bytes per pixel */
+
+#define TEW673GRU_CMD_SIZE	9
+#define TEW673GRU_NUM_ROW_BYTES (TEW673GRU_NUM_COLS * TEW673GRU_BPP)
+
+enum {
+	CMD_SHOW_STRING		= 49,
+	CMD_SHOW_IMAGE_DIR	= 52,
+	CMD_SCREEN_COLOR	= 54,
+};
+
+static char Name[] = "TEW673GRU";
+
+static char *drv_TEW673GRU_FB;
+static long FB_SIZE;
+static int MODE;
+
+static unsigned int RGBAto16(RGBA rgb)
+{
+    return (((rgb.R >> 3) << 11) | ((rgb.G >> 2) << 5) | (rgb.B >> 3));
+}
+
+static unsigned char color_msb(unsigned int color)
+{
+    return color >> 8;
+}
+
+static unsigned char color_lsb(unsigned int color)
+{
+    return color & 0xff;
+}
+
+static void drv_TEW673GRU_hw_clear(const unsigned int color)
+{
+    unsigned char cmd[TEW673GRU_CMD_SIZE];
+    struct spi_ioc_transfer tr[1];
+
+    memset(tr, '\0', sizeof(tr));
+    memset(cmd, '\0', sizeof(cmd));
+
+    cmd[0] = CMD_SCREEN_COLOR;
+    cmd[7] = color_msb(color);
+    cmd[8] = color_lsb(color);
+
+    tr[0].tx_buf = (unsigned long) cmd;
+    tr[0].len = sizeof(cmd);
+
+    drv_generic_spidev_transfer(1, tr);
+}
+
+static void drv_TEW673GRU_hw_send_row(const int row, const int col, const char *data, const int width)
+{
+    unsigned char cmd[TEW673GRU_CMD_SIZE];
+    struct spi_ioc_transfer tr[2];
+    int datasize;
+
+    memset(tr, '\0', sizeof(tr));
+    memset(cmd, '\0', sizeof(cmd));
+
+    datasize =  width * TEW673GRU_BPP;
+
+    cmd[0] = CMD_SHOW_IMAGE_DIR;
+    cmd[1] = col;
+    cmd[2] = col + width;
+    cmd[3] = row;
+    cmd[4] = row;
+    cmd[5] = datasize >> 8;
+    cmd[6] = datasize & 0xff;
+
+    tr[0].tx_buf = (unsigned long) cmd;
+    tr[0].len = sizeof(cmd);
+    tr[1].tx_buf = (unsigned long) data;
+    tr[1].len = datasize;
+
+    drv_generic_spidev_transfer(2, tr);
+}
+
+static void drv_TEW673GRU_hw_write_string(const int row, const int col, const char *data, const int datasize)
+{
+    unsigned char cmd[TEW673GRU_CMD_SIZE];
+    struct spi_ioc_transfer tr[2];
+    unsigned char len;
+
+    memset(tr, '\0', sizeof(tr));
+    memset(cmd, '\0', sizeof(cmd));
+
+    len = datasize & 0xff;
+    cmd[0] = CMD_SHOW_STRING;
+    cmd[1] = col;
+    cmd[2] = col + (XRES * len);
+    cmd[3] = row;
+    cmd[4] = row + YRES;
+    cmd[7] = 0;
+    cmd[8] = len;
+
+    tr[0].tx_buf = (unsigned long) cmd;
+    tr[0].len = sizeof(cmd);
+    tr[1].tx_buf = (unsigned long) data;
+    tr[1].len = datasize;
+
+    drv_generic_spidev_transfer(2, tr);
+}
+
+static void drv_TEW673GRU_FB_set_pixel(const int col, const unsigned int color)
+{
+    int pos;
+
+    pos = col * TEW673GRU_BPP;
+    drv_TEW673GRU_FB[pos] = color_msb(color);
+    drv_TEW673GRU_FB[pos + 1] = color_lsb(color);
+}
+
+static void drv_TEW673GRU_blit(const int row, const int col, const int height, const int width)
+{
+    int r, c;
+
+    debug("%s: update area r:%d c:%d w:%d h:%d", Name, row, col, height, width);
+
+    for (r = row; r < row + height; r++) {
+	for (c = col; c < col + width; c++) {
+	    unsigned int color;
+	    RGBA rgb;
+
+	    rgb = drv_generic_graphic_rgb(r, c);
+	    color = RGBAto16(rgb);
+            drv_TEW673GRU_FB_set_pixel(c, color);
+	}
+
+	if (width) {
+	    char *data;
+
+	    data = &drv_TEW673GRU_FB[col * TEW673GRU_BPP];
+	    drv_TEW673GRU_hw_send_row(r, col, data, width);
+	    udelay(100 + width * 50);
+	}
+    }
+}
+
+static void drv_TEW673GRU_clear(RGBA rgba)
+{
+    unsigned int color;
+
+    color = RGBAto16(rgba);
+    drv_TEW673GRU_hw_clear(color);
+}
+
+static void drv_TEW673GRU_write(const int row, const int col, const char *data, const int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+	drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, " ", 1);
+	udelay(10000);
+	drv_TEW673GRU_hw_write_string(row * YRES, 2 + (col + i) * XRES, " ", 1);
+	udelay(10000);
+	drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, &data[i], 1);
+	udelay(10000);
+    }
+}
+
+static int drv_TEW673GRU_open(const char *section)
+{
+    int err;
+
+    err = drv_generic_spidev_open(section, Name);
+    if (err < 0)
+	return err;
+
+    return 0;
+}
+
+static int drv_TEW673GRU_close(void)
+{
+    drv_generic_spidev_close();
+    return 0;
+}
+
+static void drv_TEW673GRU_clear_screen(void)
+{
+    if (MODE) {
+	drv_generic_graphic_clear();
+    } else {
+	memset(drv_TEW673GRU_FB, ' ', FB_SIZE);
+	drv_TEW673GRU_hw_clear(0x0000);
+    }
+}
+
+static int drv_TEW673GRU_init_font(const char *section)
+{
+    char *font;
+    int ret = -1;
+
+    font = cfg_get(section, "Font", "6x8");
+    if (font == NULL) {
+	error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
+	goto out;
+    }
+
+    if (*font == '\0') {
+	error("%s: invalid '%s.Font' entry in %s", Name, section, cfg_source());
+	goto out_free;
+    }
+
+    XRES = -1;
+    YRES = -1;
+    if (sscanf(font, "%dx%d", &XRES, &YRES) != 2 ||
+	XRES < 1 ||
+	YRES < 1) {
+	error("%s: bad Font '%s' from %s", Name, font, cfg_source());
+	goto out_free;
+    }
+
+    if (XRES != 6 && YRES != 8) {
+	error("%s: bad Font '%s' from %s (only 6x8 at the moment)",
+	      Name, font, cfg_source());
+	goto out_free;
+    }
+
+    error("%s: font '%s' selected", Name, font);
+
+    ret = 0;
+
+out_free:
+    free(font);
+out:
+    return ret;
+}
+
+static int drv_TEW673GRU_start(const char *section)
+{
+    int ret;
+
+    DCOLS = TEW673GRU_NUM_COLS;
+    DROWS = TEW673GRU_NUM_ROWS;
+
+    if (MODE) {
+	ret = drv_TEW673GRU_init_font(section);
+	if (ret)
+	    goto err;
+
+	FB_SIZE = DCOLS * TEW673GRU_BPP;
+    } else {
+	XRES = 10;
+	YRES = 16;
+	DCOLS = DCOLS / XRES;
+	DROWS = DROWS / YRES;
+
+	FB_SIZE = DCOLS * DROWS;
+    }
+
+    if (FB_SIZE) {
+	drv_TEW673GRU_FB = malloc(FB_SIZE);
+	if (drv_TEW673GRU_FB == NULL) {
+	    error("%s: framebuffer could not be allocated", Name);
+	    goto err;
+	}
+    }
+
+    ret = drv_TEW673GRU_open(section);
+    if (ret < 0)
+        goto err_free;
+
+    if (MODE == 0)
+    	drv_TEW673GRU_clear_screen();
+
+    return 0;
+
+ err_free:
+    if (drv_TEW673GRU_FB)
+	free(drv_TEW673GRU_FB);
+ err:
+    return -1;
+}
+
+static int drv_TEW673GRU_greet(const char *msg1, const char *msg2)
+{
+    if (MODE)
+	return drv_generic_graphic_greet(msg1, msg2);
+
+    return drv_generic_text_greet(msg1, msg2);
+}
+
+
+/****************************************/
+/***        widget callbacks          ***/
+/****************************************/
+
+
+/* using drv_generic_text_draw(W) */
+/* using drv_generic_text_icon_draw(W) */
+/* using drv_generic_text_bar_draw(W) */
+/* using drv_generic_gpio_draw(W) */
+
+
+/****************************************/
+/***        exported functions        ***/
+/****************************************/
+
+int drv_TEW673GRU_list(void)
+{
+    printf("TEW673GRU driver");
+    return 0;
+}
+
+int drv_TEW673GRU_init(const char *section, const int quiet)
+{
+    WIDGET_CLASS wc;
+    int ret;
+
+    cfg_number(section, "Mode", 0, 0, 1, &MODE);
+
+    if (MODE) {
+	drv_generic_graphic_real_blit = drv_TEW673GRU_blit;
+	drv_generic_graphic_real_clear = drv_TEW673GRU_clear;
+    } else {
+	drv_generic_text_real_write = drv_TEW673GRU_write;
+    }
+
+    ret = drv_TEW673GRU_start(section);
+    if (ret)
+	return ret;
+
+    if (MODE) {
+	ret = drv_generic_graphic_init(section, Name);
+	if (ret)
+	    return ret;
+    } else {
+	ret = drv_generic_text_init(section, Name);
+	if (ret)
+	    return ret;
+
+	ret = drv_generic_text_icon_init();
+	if (ret != 0)
+	    return ret;
+
+	ret = drv_generic_text_bar_init(1);
+	if (ret != 0)
+	    return ret;
+
+	drv_generic_text_bar_add_segment(0, 0, 255, ' ');
+	drv_generic_text_bar_add_segment(255, 255, 255, '#');
+
+	wc = Widget_Text;
+	wc.draw = drv_generic_text_draw;
+	widget_register(&wc);
+
+	wc = Widget_Icon;
+	wc.draw = drv_generic_text_icon_draw;
+	widget_register(&wc);
+
+	wc = Widget_Bar;
+	wc.draw = drv_generic_text_bar_draw;
+	widget_register(&wc);
+    }
+
+    if (!quiet) {
+	char buffer[40];
+	qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
+	drv_TEW673GRU_greet(buffer, "www.openwrt.org");
+	sleep(3);
+	drv_TEW673GRU_clear_screen();
+    }
+
+    return 0;
+}
+
+int drv_TEW673GRU_quit(const int quiet)
+{
+
+    info("%s: shutting down.", Name);
+
+    drv_TEW673GRU_clear_screen();
+
+    if (!quiet)
+	drv_TEW673GRU_greet("goodbye!", NULL);
+
+    if (MODE)
+	drv_generic_graphic_quit();
+    else
+	drv_generic_text_quit();
+
+    debug("closing connection");
+    drv_TEW673GRU_close();
+
+    return (0);
+}
+
+DRIVER drv_TEW673GRU = {
+    .name = Name,
+    .list = drv_TEW673GRU_list,
+    .init = drv_TEW673GRU_init,
+    .quit = drv_TEW673GRU_quit,
+};
--- a/lcd4linux.conf.sample
+++ b/lcd4linux.conf.sample
@@ -581,6 +581,11 @@ Display FutabaVFD {
     }
 }
 
+Display TEW673GRU {
+    Driver       'TEW673GRU'
+    Font         '6x8'
+    Port         '/dev/spidev1.0'
+}
 
 #Plugin KVV {
 #    StationID '12_701'
