172-add-TEW673GRU-driver.patch (12962B)
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 @@ -797,6 +801,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 @@ -581,6 +581,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'