Branch oldpackages for 14.07
[14.07/packages.git] / utils / lcd4linux / patches / 172-add-TEW673GRU-driver.patch
1 --- a/drivers.m4
2 +++ b/drivers.m4
3 @@ -39,7 +39,7 @@ AC_ARG_WITH(
4    [                        Newhaven, Noritake, NULL, Pertelian, PHAnderson,]
5    [                        PICGraphic, picoLCD, picoLCDGraphic, PNG, PPM, RouterBoard,]
6    [                        Sample, SamsungSPF, serdisplib, ShuttleVFD, SimpleLCD, st2205, T6963,]
7 -  [                        TeakLCM, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
8 +  [                        TeakLCM, TEW673GRU, Trefon, ULA200, USBHUB, USBLCD, VNC, WincorNixdorf, X11],
9    drivers=$withval,
10    drivers=all
11  )
12 @@ -107,6 +107,7 @@ for driver in $drivers; do
13          SHUTTLEVFD="yes"
14           SIMPLELCD="yes"
15           T6963="yes"
16 +         TEW673GRU="yes"
17           TeakLCM="yes"
18           Trefon="yes"
19           ULA200="yes"
20 @@ -260,6 +261,9 @@ for driver in $drivers; do
21        TeakLCM)
22           TeakLCM=$val
23           ;;
24 +      TEW673GRU)
25 +         TEW673GRU=$val
26 +         ;;
27        Trefon)
28           Trefon=$val
29           ;;
30 @@ -801,6 +805,18 @@ if test "$TeakLCM" = "yes"; then
31     AC_DEFINE(WITH_TEAK_LCM,1,[TeakLCM driver])
32  fi
33  
34 +if test "$TEW673GRU" = "yes"; then
35 +   if test "$has_spidev" = "true"; then
36 +      GRAPHIC="yes"
37 +      TEXT="yes"
38 +      SPIDEV="yes"
39 +      DRIVERS="$DRIVERS drv_TEW673GRU.o"
40 +      AC_DEFINE(WITH_TEW673GRU,1,[TEW673GRU driver])
41 +   else
42 +      AC_MSG_WARN(linux/spi/spidev.h not found: TEW673GRU driver disabled)
43 +   fi
44 +fi
45 +
46  if test "$Trefon" = "yes"; then
47     if test "$has_usb" = "true"; then
48        TEXT="yes"
49 --- a/drv.c
50 +++ b/drv.c
51 @@ -92,6 +92,7 @@ extern DRIVER drv_serdisplib;
52  extern DRIVER drv_ShuttleVFD;
53  extern DRIVER drv_SimpleLCD;
54  extern DRIVER drv_T6963;
55 +extern DRIVER drv_TEW673GRU;
56  extern DRIVER drv_TeakLCM;
57  extern DRIVER drv_Trefon;
58  extern DRIVER drv_ula200;
59 @@ -248,6 +249,9 @@ DRIVER *Driver[] = {
60  #ifdef WITH_TEAK_LCM
61      &drv_TeakLCM,
62  #endif
63 +#ifdef WITH_TEW673GRU
64 +    &drv_TEW673GRU,
65 +#endif
66  #ifdef WITH_TREFON
67      &drv_Trefon,
68  #endif
69 --- a/Makefile.am
70 +++ b/Makefile.am
71 @@ -119,6 +119,7 @@ drv_ShuttleVFD.c              \
72  drv_SimpleLCD.c               \
73  drv_T6963.c                   \
74  drv_TeakLCM.c                 \
75 +drv_TEW673GRU.c               \
76  drv_Trefon.c                  \
77  drv_ula200.c                  \
78  drv_USBHUB.c                  \
79 --- /dev/null
80 +++ b/drv_TEW673GRU.c
81 @@ -0,0 +1,457 @@
82 +/* $Id$
83 + * $URL$
84 + *
85 + * TRENDnet TEW673GRU LCD4linux driver
86 + *
87 + * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
88 + *
89 + * based on the Sample driver which is:
90 + * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
91 + * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
92 + *
93 + * This file is part of LCD4Linux.
94 + *
95 + * LCD4Linux is free software; you can redistribute it and/or modify
96 + * it under the terms of the GNU General Public License as published by
97 + * the Free Software Foundation; either version 2, or (at your option)
98 + * any later version.
99 + *
100 + * LCD4Linux is distributed in the hope that it will be useful,
101 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
102 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
103 + * GNU General Public License for more details.
104 + *
105 + * You should have received a copy of the GNU General Public License
106 + * along with this program; if not, write to the Free Software
107 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
108 + *
109 + */
110 +
111 +/*
112 + * exported fuctions:
113 + *
114 + * struct DRIVER drv_TEW673GRU
115 + */
116 +
117 +#include "config.h"
118 +
119 +#include <stdlib.h>
120 +#include <stdio.h>
121 +#include <unistd.h>
122 +#include <string.h>
123 +#include <errno.h>
124 +
125 +#include "debug.h"
126 +#include "cfg.h"
127 +#include "qprintf.h"
128 +#include "udelay.h"
129 +#include "plugin.h"
130 +#include "widget.h"
131 +#include "widget_text.h"
132 +#include "widget_icon.h"
133 +#include "widget_bar.h"
134 +#include "drv.h"
135 +
136 +#include "drv_generic_text.h"
137 +#include "drv_generic_graphic.h"
138 +#include "drv_generic_spidev.h"
139 +
140 +#ifdef WITH_DMALLOC
141 +#include <dmalloc.h>
142 +#endif
143 +
144 +#define TEW673GRU_NUM_COLS     220
145 +#define TEW673GRU_NUM_ROWS     176
146 +#define TEW673GRU_BPP          2       /* bytes per pixel */
147 +
148 +#define TEW673GRU_CMD_SIZE     9
149 +#define TEW673GRU_NUM_ROW_BYTES (TEW673GRU_NUM_COLS * TEW673GRU_BPP)
150 +
151 +enum {
152 +       CMD_SHOW_STRING         = 49,
153 +       CMD_SHOW_IMAGE_DIR      = 52,
154 +       CMD_SCREEN_COLOR        = 54,
155 +};
156 +
157 +static char Name[] = "TEW673GRU";
158 +
159 +static char *drv_TEW673GRU_FB;
160 +static long FB_SIZE;
161 +static int MODE;
162 +
163 +static unsigned int RGBAto16(RGBA rgb)
164 +{
165 +    return (((rgb.R >> 3) << 11) | ((rgb.G >> 2) << 5) | (rgb.B >> 3));
166 +}
167 +
168 +static unsigned char color_msb(unsigned int color)
169 +{
170 +    return color >> 8;
171 +}
172 +
173 +static unsigned char color_lsb(unsigned int color)
174 +{
175 +    return color & 0xff;
176 +}
177 +
178 +static void drv_TEW673GRU_hw_clear(const unsigned int color)
179 +{
180 +    unsigned char cmd[TEW673GRU_CMD_SIZE];
181 +    struct spi_ioc_transfer tr[1];
182 +
183 +    memset(tr, '\0', sizeof(tr));
184 +    memset(cmd, '\0', sizeof(cmd));
185 +
186 +    cmd[0] = CMD_SCREEN_COLOR;
187 +    cmd[7] = color_msb(color);
188 +    cmd[8] = color_lsb(color);
189 +
190 +    tr[0].tx_buf = (unsigned long) cmd;
191 +    tr[0].len = sizeof(cmd);
192 +
193 +    drv_generic_spidev_transfer(1, tr);
194 +}
195 +
196 +static void drv_TEW673GRU_hw_send_row(const int row, const int col, const char *data, const int width)
197 +{
198 +    unsigned char cmd[TEW673GRU_CMD_SIZE];
199 +    struct spi_ioc_transfer tr[2];
200 +    int datasize;
201 +
202 +    memset(tr, '\0', sizeof(tr));
203 +    memset(cmd, '\0', sizeof(cmd));
204 +
205 +    datasize =  width * TEW673GRU_BPP;
206 +
207 +    cmd[0] = CMD_SHOW_IMAGE_DIR;
208 +    cmd[1] = col;
209 +    cmd[2] = col + width;
210 +    cmd[3] = row;
211 +    cmd[4] = row;
212 +    cmd[5] = datasize >> 8;
213 +    cmd[6] = datasize & 0xff;
214 +
215 +    tr[0].tx_buf = (unsigned long) cmd;
216 +    tr[0].len = sizeof(cmd);
217 +    tr[1].tx_buf = (unsigned long) data;
218 +    tr[1].len = datasize;
219 +
220 +    drv_generic_spidev_transfer(2, tr);
221 +}
222 +
223 +static void drv_TEW673GRU_hw_write_string(const int row, const int col, const char *data, const int datasize)
224 +{
225 +    unsigned char cmd[TEW673GRU_CMD_SIZE];
226 +    struct spi_ioc_transfer tr[2];
227 +    unsigned char len;
228 +
229 +    memset(tr, '\0', sizeof(tr));
230 +    memset(cmd, '\0', sizeof(cmd));
231 +
232 +    len = datasize & 0xff;
233 +    cmd[0] = CMD_SHOW_STRING;
234 +    cmd[1] = col;
235 +    cmd[2] = col + (XRES * len);
236 +    cmd[3] = row;
237 +    cmd[4] = row + YRES;
238 +    cmd[7] = 0;
239 +    cmd[8] = len;
240 +
241 +    tr[0].tx_buf = (unsigned long) cmd;
242 +    tr[0].len = sizeof(cmd);
243 +    tr[1].tx_buf = (unsigned long) data;
244 +    tr[1].len = datasize;
245 +
246 +    drv_generic_spidev_transfer(2, tr);
247 +}
248 +
249 +static void drv_TEW673GRU_FB_set_pixel(const int col, const unsigned int color)
250 +{
251 +    int pos;
252 +
253 +    pos = col * TEW673GRU_BPP;
254 +    drv_TEW673GRU_FB[pos] = color_msb(color);
255 +    drv_TEW673GRU_FB[pos + 1] = color_lsb(color);
256 +}
257 +
258 +static void drv_TEW673GRU_blit(const int row, const int col, const int height, const int width)
259 +{
260 +    int r, c;
261 +
262 +    debug("%s: update area r:%d c:%d w:%d h:%d", Name, row, col, height, width);
263 +
264 +    for (r = row; r < row + height; r++) {
265 +       for (c = col; c < col + width; c++) {
266 +           unsigned int color;
267 +           RGBA rgb;
268 +
269 +           rgb = drv_generic_graphic_rgb(r, c);
270 +           color = RGBAto16(rgb);
271 +            drv_TEW673GRU_FB_set_pixel(c, color);
272 +       }
273 +
274 +       if (width) {
275 +           char *data;
276 +
277 +           data = &drv_TEW673GRU_FB[col * TEW673GRU_BPP];
278 +           drv_TEW673GRU_hw_send_row(r, col, data, width);
279 +           udelay(100 + width * 50);
280 +       }
281 +    }
282 +}
283 +
284 +static void drv_TEW673GRU_clear(RGBA rgba)
285 +{
286 +    unsigned int color;
287 +
288 +    color = RGBAto16(rgba);
289 +    drv_TEW673GRU_hw_clear(color);
290 +}
291 +
292 +static void drv_TEW673GRU_write(const int row, const int col, const char *data, const int len)
293 +{
294 +    int i;
295 +
296 +    for (i = 0; i < len; i++) {
297 +       drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, " ", 1);
298 +       udelay(10000);
299 +       drv_TEW673GRU_hw_write_string(row * YRES, 2 + (col + i) * XRES, " ", 1);
300 +       udelay(10000);
301 +       drv_TEW673GRU_hw_write_string(row * YRES, (col + i) * XRES, &data[i], 1);
302 +       udelay(10000);
303 +    }
304 +}
305 +
306 +static int drv_TEW673GRU_open(const char *section)
307 +{
308 +    int err;
309 +
310 +    err = drv_generic_spidev_open(section, Name);
311 +    if (err < 0)
312 +       return err;
313 +
314 +    return 0;
315 +}
316 +
317 +static int drv_TEW673GRU_close(void)
318 +{
319 +    drv_generic_spidev_close();
320 +    return 0;
321 +}
322 +
323 +static void drv_TEW673GRU_clear_screen(void)
324 +{
325 +    if (MODE) {
326 +       drv_generic_graphic_clear();
327 +    } else {
328 +       memset(drv_TEW673GRU_FB, ' ', FB_SIZE);
329 +       drv_TEW673GRU_hw_clear(0x0000);
330 +    }
331 +}
332 +
333 +static int drv_TEW673GRU_init_font(const char *section)
334 +{
335 +    char *font;
336 +    int ret = -1;
337 +
338 +    font = cfg_get(section, "Font", "6x8");
339 +    if (font == NULL) {
340 +       error("%s: no '%s.Font' entry from %s", Name, section, cfg_source());
341 +       goto out;
342 +    }
343 +
344 +    if (*font == '\0') {
345 +       error("%s: invalid '%s.Font' entry in %s", Name, section, cfg_source());
346 +       goto out_free;
347 +    }
348 +
349 +    XRES = -1;
350 +    YRES = -1;
351 +    if (sscanf(font, "%dx%d", &XRES, &YRES) != 2 ||
352 +       XRES < 1 ||
353 +       YRES < 1) {
354 +       error("%s: bad Font '%s' from %s", Name, font, cfg_source());
355 +       goto out_free;
356 +    }
357 +
358 +    if (XRES != 6 && YRES != 8) {
359 +       error("%s: bad Font '%s' from %s (only 6x8 at the moment)",
360 +             Name, font, cfg_source());
361 +       goto out_free;
362 +    }
363 +
364 +    error("%s: font '%s' selected", Name, font);
365 +
366 +    ret = 0;
367 +
368 +out_free:
369 +    free(font);
370 +out:
371 +    return ret;
372 +}
373 +
374 +static int drv_TEW673GRU_start(const char *section)
375 +{
376 +    int ret;
377 +
378 +    DCOLS = TEW673GRU_NUM_COLS;
379 +    DROWS = TEW673GRU_NUM_ROWS;
380 +
381 +    if (MODE) {
382 +       ret = drv_TEW673GRU_init_font(section);
383 +       if (ret)
384 +           goto err;
385 +
386 +       FB_SIZE = DCOLS * TEW673GRU_BPP;
387 +    } else {
388 +       XRES = 10;
389 +       YRES = 16;
390 +       DCOLS = DCOLS / XRES;
391 +       DROWS = DROWS / YRES;
392 +
393 +       FB_SIZE = DCOLS * DROWS;
394 +    }
395 +
396 +    if (FB_SIZE) {
397 +       drv_TEW673GRU_FB = malloc(FB_SIZE);
398 +       if (drv_TEW673GRU_FB == NULL) {
399 +           error("%s: framebuffer could not be allocated", Name);
400 +           goto err;
401 +       }
402 +    }
403 +
404 +    ret = drv_TEW673GRU_open(section);
405 +    if (ret < 0)
406 +        goto err_free;
407 +
408 +    if (MODE == 0)
409 +       drv_TEW673GRU_clear_screen();
410 +
411 +    return 0;
412 +
413 + err_free:
414 +    if (drv_TEW673GRU_FB)
415 +       free(drv_TEW673GRU_FB);
416 + err:
417 +    return -1;
418 +}
419 +
420 +static int drv_TEW673GRU_greet(const char *msg1, const char *msg2)
421 +{
422 +    if (MODE)
423 +       return drv_generic_graphic_greet(msg1, msg2);
424 +
425 +    return drv_generic_text_greet(msg1, msg2);
426 +}
427 +
428 +
429 +/****************************************/
430 +/***        widget callbacks          ***/
431 +/****************************************/
432 +
433 +
434 +/* using drv_generic_text_draw(W) */
435 +/* using drv_generic_text_icon_draw(W) */
436 +/* using drv_generic_text_bar_draw(W) */
437 +/* using drv_generic_gpio_draw(W) */
438 +
439 +
440 +/****************************************/
441 +/***        exported functions        ***/
442 +/****************************************/
443 +
444 +int drv_TEW673GRU_list(void)
445 +{
446 +    printf("TEW673GRU driver");
447 +    return 0;
448 +}
449 +
450 +int drv_TEW673GRU_init(const char *section, const int quiet)
451 +{
452 +    WIDGET_CLASS wc;
453 +    int ret;
454 +
455 +    cfg_number(section, "Mode", 0, 0, 1, &MODE);
456 +
457 +    if (MODE) {
458 +       drv_generic_graphic_real_blit = drv_TEW673GRU_blit;
459 +       drv_generic_graphic_real_clear = drv_TEW673GRU_clear;
460 +    } else {
461 +       drv_generic_text_real_write = drv_TEW673GRU_write;
462 +    }
463 +
464 +    ret = drv_TEW673GRU_start(section);
465 +    if (ret)
466 +       return ret;
467 +
468 +    if (MODE) {
469 +       ret = drv_generic_graphic_init(section, Name);
470 +       if (ret)
471 +           return ret;
472 +    } else {
473 +       ret = drv_generic_text_init(section, Name);
474 +       if (ret)
475 +           return ret;
476 +
477 +       ret = drv_generic_text_icon_init();
478 +       if (ret != 0)
479 +           return ret;
480 +
481 +       ret = drv_generic_text_bar_init(1);
482 +       if (ret != 0)
483 +           return ret;
484 +
485 +       drv_generic_text_bar_add_segment(0, 0, 255, ' ');
486 +       drv_generic_text_bar_add_segment(255, 255, 255, '#');
487 +
488 +       wc = Widget_Text;
489 +       wc.draw = drv_generic_text_draw;
490 +       widget_register(&wc);
491 +
492 +       wc = Widget_Icon;
493 +       wc.draw = drv_generic_text_icon_draw;
494 +       widget_register(&wc);
495 +
496 +       wc = Widget_Bar;
497 +       wc.draw = drv_generic_text_bar_draw;
498 +       widget_register(&wc);
499 +    }
500 +
501 +    if (!quiet) {
502 +       char buffer[40];
503 +       qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
504 +       drv_TEW673GRU_greet(buffer, "www.openwrt.org");
505 +       sleep(3);
506 +       drv_TEW673GRU_clear_screen();
507 +    }
508 +
509 +    return 0;
510 +}
511 +
512 +int drv_TEW673GRU_quit(const int quiet)
513 +{
514 +
515 +    info("%s: shutting down.", Name);
516 +
517 +    drv_TEW673GRU_clear_screen();
518 +
519 +    if (!quiet)
520 +       drv_TEW673GRU_greet("goodbye!", NULL);
521 +
522 +    if (MODE)
523 +       drv_generic_graphic_quit();
524 +    else
525 +       drv_generic_text_quit();
526 +
527 +    debug("closing connection");
528 +    drv_TEW673GRU_close();
529 +
530 +    return (0);
531 +}
532 +
533 +DRIVER drv_TEW673GRU = {
534 +    .name = Name,
535 +    .list = drv_TEW673GRU_list,
536 +    .init = drv_TEW673GRU_init,
537 +    .quit = drv_TEW673GRU_quit,
538 +};
539 --- a/lcd4linux.conf.sample
540 +++ b/lcd4linux.conf.sample
541 @@ -571,6 +571,11 @@ Display FutabaVFD {
542      }
543  }
544  
545 +Display TEW673GRU {
546 +    Driver       'TEW673GRU'
547 +    Font         '6x8'
548 +    Port         '/dev/spidev1.0'
549 +}
550  
551  #Plugin KVV {
552  #    StationID '12_701'