The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/hd44780_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $NetBSD: hd44780_subr.c,v 1.15 2008/04/10 09:05:53 he Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002 Dennis I. Chernoivanov
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Subroutines for Hitachi HD44870 style displays
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: hd44780_subr.c,v 1.15 2008/04/10 09:05:53 he Exp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/conf.h>
   40 #include <sys/kernel.h>
   41 #include <sys/malloc.h>
   42 #include <sys/types.h>
   43 #include <sys/ioccom.h>
   44 
   45 #include <machine/autoconf.h>
   46 #include <sys/intr.h>
   47 #include <sys/bus.h>
   48 
   49 #include <uvm/uvm_extern.h>
   50 
   51 #include <dev/wscons/wsdisplayvar.h>
   52 #include <dev/wscons/wsconsio.h>
   53 #include <dev/wscons/wscons_callbacks.h>
   54 
   55 #include <dev/ic/hd44780reg.h>
   56 #include <dev/ic/hd44780var.h>
   57 
   58 #define COORD_TO_IDX(x, y)      ((y) * sc->sc_cols + (x))
   59 #define COORD_TO_DADDR(x, y)    ((y) * HD_ROW2_ADDR + (x))
   60 #define IDX_TO_ROW(idx)         ((idx) / sc->sc_cols)
   61 #define IDX_TO_COL(idx)         ((idx) % sc->sc_cols)
   62 #define IDX_TO_DADDR(idx)       (IDX_TO_ROW((idx)) * HD_ROW2_ADDR + \
   63                                 IDX_TO_COL((idx)))
   64 #define DADDR_TO_ROW(daddr)     ((daddr) / HD_ROW2_ADDR)
   65 #define DADDR_TO_COL(daddr)     ((daddr) % HD_ROW2_ADDR)
   66 #define DADDR_TO_CHIPDADDR(daddr)       ((daddr) % (HD_ROW2_ADDR * 2))
   67 #define DADDR_TO_CHIPNO(daddr)  ((daddr) / (HD_ROW2_ADDR * 2))
   68 
   69 static void     hlcd_cursor(void *, int, int, int);
   70 static int      hlcd_mapchar(void *, int, unsigned int *);
   71 static void     hlcd_putchar(void *, int, int, u_int, long);
   72 static void     hlcd_copycols(void *, int, int, int,int);
   73 static void     hlcd_erasecols(void *, int, int, int, long);
   74 static void     hlcd_copyrows(void *, int, int, int);
   75 static void     hlcd_eraserows(void *, int, int, long);
   76 static int      hlcd_allocattr(void *, int, int, int, long *);
   77 static void     hlcd_updatechar(struct hd44780_chip *, int, int);
   78 static void     hlcd_redraw(void *);
   79 
   80 const struct wsdisplay_emulops hlcd_emulops = {
   81         hlcd_cursor,
   82         hlcd_mapchar,
   83         hlcd_putchar,
   84         hlcd_copycols,
   85         hlcd_erasecols,
   86         hlcd_copyrows,
   87         hlcd_eraserows,
   88         hlcd_allocattr
   89 };
   90 
   91 static int      hlcd_ioctl(void *, void *, u_long, void *, int, struct lwp *);
   92 static paddr_t  hlcd_mmap(void *, void *, off_t, int);
   93 static int      hlcd_alloc_screen(void *, const struct wsscreen_descr *,
   94                     void **, int *, int *, long *);
   95 static void     hlcd_free_screen(void *, void *);
   96 static int      hlcd_show_screen(void *, void *, int,
   97                     void (*) (void *, int, int), void *);
   98 
   99 const struct wsdisplay_accessops hlcd_accessops = {
  100         hlcd_ioctl,
  101         hlcd_mmap,
  102         hlcd_alloc_screen,
  103         hlcd_free_screen,
  104         hlcd_show_screen,
  105         0 /* load_font */
  106 };
  107 
  108 static void
  109 hlcd_cursor(id, on, row, col)
  110         void *id;
  111         int on, row, col;
  112 {
  113         struct hlcd_screen *hdscr = id;
  114 
  115         hdscr->hlcd_curon = on;
  116         hdscr->hlcd_curx = col;
  117         hdscr->hlcd_cury = row;
  118 }
  119 
  120 static int
  121 hlcd_mapchar(id, uni, index)
  122         void *id;
  123         int uni;
  124         unsigned int *index;
  125 {
  126         if (uni < 256) {
  127                 *index = uni;
  128                 return (5);
  129         }
  130         *index = ' ';
  131         return (0);
  132 }
  133 
  134 static void
  135 hlcd_putchar(id, row, col, c, attr)
  136         void *id;
  137         int row, col;
  138         u_int c;
  139         long attr;
  140 {
  141         struct hlcd_screen *hdscr = id;
  142 
  143         c &= 0xff;
  144         if (row > 0 && (hdscr->hlcd_sc->sc_flags & (HD_MULTILINE|HD_MULTICHIP)))
  145                 hdscr->image[hdscr->hlcd_sc->sc_cols * row + col] = c;
  146         else
  147                 hdscr->image[col] = c;
  148 }
  149 
  150 /*
  151  * copies columns inside a row.
  152  */
  153 static void
  154 hlcd_copycols(id, row, srccol, dstcol, ncols)
  155         void *id;
  156         int row, srccol, dstcol, ncols;
  157 {
  158         struct hlcd_screen *hdscr = id;
  159 
  160         if ((dstcol + ncols - 1) > hdscr->hlcd_sc->sc_cols)
  161                 ncols = hdscr->hlcd_sc->sc_cols - srccol;
  162 
  163         if (row > 0 && (hdscr->hlcd_sc->sc_flags & (HD_MULTILINE|HD_MULTICHIP)))
  164                 memmove(&hdscr->image[hdscr->hlcd_sc->sc_cols * row + dstcol],
  165                     &hdscr->image[hdscr->hlcd_sc->sc_cols * row + srccol],
  166                     ncols);
  167         else
  168                 memmove(&hdscr->image[dstcol], &hdscr->image[srccol], ncols);
  169 }
  170 
  171 
  172 /*
  173  * Erases a bunch of chars inside one row.
  174  */
  175 static void
  176 hlcd_erasecols(id, row, startcol, ncols, fillattr)
  177         void *id;
  178         int row, startcol, ncols;
  179         long fillattr;
  180 {
  181         struct hlcd_screen *hdscr = id;
  182 
  183         if ((startcol + ncols) > hdscr->hlcd_sc->sc_cols)
  184                 ncols = hdscr->hlcd_sc->sc_cols - startcol;
  185 
  186         if (row > 0 && (hdscr->hlcd_sc->sc_flags & (HD_MULTILINE|HD_MULTICHIP)))
  187                 memset(&hdscr->image[hdscr->hlcd_sc->sc_cols * row + startcol],
  188                     ' ', ncols);
  189         else
  190                 memset(&hdscr->image[startcol], ' ', ncols);
  191 }
  192 
  193 
  194 static void
  195 hlcd_copyrows(id, srcrow, dstrow, nrows)
  196         void *id;
  197         int srcrow, dstrow, nrows;
  198 {
  199         struct hlcd_screen *hdscr = id;
  200         int ncols = hdscr->hlcd_sc->sc_cols;
  201 
  202         if (!(hdscr->hlcd_sc->sc_flags & (HD_MULTILINE|HD_MULTICHIP)))
  203                 return;
  204         memmove(&hdscr->image[dstrow * ncols], &hdscr->image[srcrow * ncols],
  205             nrows * ncols);
  206 }
  207 
  208 static void
  209 hlcd_eraserows(id, startrow, nrows, fillattr)
  210         void *id;
  211         int startrow, nrows;
  212         long fillattr;
  213 {
  214         struct hlcd_screen *hdscr = id;
  215         int ncols = hdscr->hlcd_sc->sc_cols;
  216 
  217         memset(&hdscr->image[startrow * ncols], ' ', ncols * nrows);
  218 }
  219 
  220 
  221 static int
  222 hlcd_allocattr(id, fg, bg, flags, attrp)
  223         void *id;
  224         int fg, bg, flags;
  225         long *attrp;
  226 {
  227         *attrp = flags;
  228         return 0;
  229 }
  230 
  231 static int
  232 hlcd_ioctl(v, vs, cmd, data, flag, l)
  233         void *v;
  234         void *vs;
  235         u_long cmd;
  236         void *data;
  237         int flag;
  238         struct lwp *l;
  239 {
  240 
  241         switch (cmd) {
  242         case WSDISPLAYIO_GTYPE:
  243                 *(u_int *)data = WSDISPLAY_TYPE_HDLCD;
  244                 break;
  245 
  246         case WSDISPLAYIO_SVIDEO:
  247                 break;
  248 
  249         case WSDISPLAYIO_GVIDEO:
  250                 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
  251                 break;
  252 
  253         default:
  254                 return EPASSTHROUGH;
  255         }
  256         return 0;
  257 }
  258 
  259 static paddr_t
  260 hlcd_mmap(v, vs, offset, prot)
  261         void *v;
  262         void *vs;
  263         off_t offset;
  264         int prot;
  265 {
  266         return -1;
  267 }
  268 
  269 static int
  270 hlcd_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
  271         void *v;
  272         const struct wsscreen_descr *type;
  273         void **cookiep;
  274         int *curxp, *curyp;
  275         long *defattrp;
  276 {
  277         struct hlcd_screen *hdscr = v, *new;
  278 
  279         new = *cookiep = malloc(sizeof(struct hlcd_screen), M_DEVBUF, M_WAITOK);
  280         bzero(*cookiep, sizeof(struct hlcd_screen));
  281         new->hlcd_sc = hdscr->hlcd_sc;
  282         new->image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
  283         memset(new->image, ' ', PAGE_SIZE);
  284         *curxp = *curyp = *defattrp = 0;
  285         return 0;
  286 }
  287 
  288 static void
  289 hlcd_free_screen(v, cookie)
  290         void *v, *cookie;
  291 {
  292 }
  293 
  294 static int
  295 hlcd_show_screen(v, cookie, waitok, cb, cbarg)
  296         void *v, *cookie, *cbarg;
  297         int waitok;
  298         void (*cb)(void *, int, int);
  299 {
  300         struct hlcd_screen *hdscr = v;
  301 
  302         hdscr->hlcd_sc->sc_curscr = cookie;
  303         callout_schedule(&hdscr->hlcd_sc->redraw, 1);
  304         return (0);
  305 }
  306 
  307 static void
  308 hlcd_updatechar(sc, daddr, c)
  309         struct hd44780_chip *sc;
  310         int daddr, c;
  311 {
  312         int curdaddr, en, chipdaddr;
  313 
  314         curdaddr = COORD_TO_DADDR(sc->sc_screen.hlcd_curx,
  315             sc->sc_screen.hlcd_cury);
  316         en = DADDR_TO_CHIPNO(daddr);
  317         chipdaddr = DADDR_TO_CHIPDADDR(daddr);
  318         if (daddr != curdaddr)
  319                 hd44780_ir_write(sc, en, cmd_ddramset(chipdaddr));
  320 
  321         hd44780_dr_write(sc, en, c);
  322 
  323         daddr++;
  324         sc->sc_screen.hlcd_curx = DADDR_TO_COL(daddr);
  325         sc->sc_screen.hlcd_cury = DADDR_TO_ROW(daddr);
  326 }
  327 
  328 static void
  329 hlcd_redraw(arg)
  330         void *arg;
  331 {
  332         struct hd44780_chip *sc = arg;
  333         int len, crsridx, startidx, x, y;
  334         int old_en, new_en;
  335         u_char *img, *curimg;
  336 
  337         if (sc->sc_curscr == NULL)
  338                 return;
  339 
  340         if (sc->sc_flags & HD_MULTILINE)
  341                 len = 2 * sc->sc_cols;
  342         else
  343                 len = sc->sc_cols;
  344 
  345         if (sc->sc_flags & HD_MULTICHIP)
  346                 len = len * 2;
  347 
  348         x = sc->sc_screen.hlcd_curx;
  349         y = sc->sc_screen.hlcd_cury;
  350         old_en = DADDR_TO_CHIPNO(COORD_TO_DADDR(x, y));
  351 
  352         img = sc->sc_screen.image;
  353         curimg = sc->sc_curscr->image;
  354         startidx = crsridx =
  355             COORD_TO_IDX(sc->sc_screen.hlcd_curx, sc->sc_screen.hlcd_cury);
  356         do {
  357                 if (img[crsridx] != curimg[crsridx]) {
  358                         hlcd_updatechar(sc, IDX_TO_DADDR(crsridx),
  359                             curimg[crsridx]);
  360                         img[crsridx] = curimg[crsridx];
  361                 }
  362                 crsridx++;
  363                 if (crsridx == len)
  364                         crsridx = 0;
  365         } while (crsridx != startidx);
  366 
  367         x = sc->sc_curscr->hlcd_curx;
  368         y = sc->sc_curscr->hlcd_cury;
  369         new_en = DADDR_TO_CHIPNO(COORD_TO_DADDR(x, y));
  370 
  371         if (sc->sc_screen.hlcd_curx != sc->sc_curscr->hlcd_curx ||
  372             sc->sc_screen.hlcd_cury != sc->sc_curscr->hlcd_cury) {
  373 
  374                 x = sc->sc_screen.hlcd_curx = sc->sc_curscr->hlcd_curx;
  375                 y = sc->sc_screen.hlcd_cury = sc->sc_curscr->hlcd_cury;
  376 
  377                 hd44780_ir_write(sc, new_en, cmd_ddramset(
  378                     DADDR_TO_CHIPDADDR(COORD_TO_DADDR(x, y))));
  379 
  380         }
  381 
  382         /* visible cursor switched to other chip */
  383         if (old_en != new_en && sc->sc_screen.hlcd_curon) {
  384                 hd44780_ir_write(sc, old_en, cmd_dispctl(1, 0, 0));
  385                 hd44780_ir_write(sc, new_en, cmd_dispctl(1, 1, 1));
  386         }
  387 
  388         if (sc->sc_screen.hlcd_curon != sc->sc_curscr->hlcd_curon) {
  389                 sc->sc_screen.hlcd_curon = sc->sc_curscr->hlcd_curon;
  390                 if (sc->sc_screen.hlcd_curon)
  391                         hd44780_ir_write(sc, new_en, cmd_dispctl(1, 1, 1));
  392                 else
  393                         hd44780_ir_write(sc, new_en, cmd_dispctl(1, 0, 0));
  394         }
  395 
  396         callout_schedule(&sc->redraw, 1);
  397 }
  398 
  399 
  400 /*
  401  * Finish device attach. sc_writereg, sc_readreg and sc_flags must be properly
  402  * initialized prior to this call.
  403  */
  404 void
  405 hd44780_attach_subr(sc)
  406         struct hd44780_chip *sc;
  407 {
  408         int err = 0;
  409         /* Putc/getc are supposed to be set by platform-dependent code. */
  410         if ((sc->sc_writereg == NULL) || (sc->sc_readreg == NULL))
  411                 sc->sc_dev_ok = 0;
  412 
  413         /* Make sure that HD_MAX_CHARS is enough. */
  414         if ((sc->sc_flags & HD_MULTILINE) && (2 * sc->sc_cols > HD_MAX_CHARS))
  415                 sc->sc_dev_ok = 0;
  416         else if (sc->sc_cols > HD_MAX_CHARS)
  417                 sc->sc_dev_ok = 0;
  418 
  419         if (sc->sc_dev_ok) {
  420                 if ((sc->sc_flags & HD_UP) == 0)
  421                         err = hd44780_init(sc);
  422                 if (err != 0)
  423                         aprint_error_dev(sc->sc_dev, "LCD not responding or unconnected\n");
  424 
  425         }
  426 
  427         sc->sc_screen.hlcd_sc = sc;
  428 
  429         sc->sc_screen.image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
  430         memset(sc->sc_screen.image, ' ', PAGE_SIZE);
  431         sc->sc_curscr = NULL;
  432         sc->sc_curchip = 0;
  433         callout_init(&sc->redraw, 0);
  434         callout_setfunc(&sc->redraw, hlcd_redraw, sc);
  435 }
  436 
  437 int hd44780_init(sc)
  438         struct hd44780_chip *sc;
  439 {
  440         int ret;
  441 
  442         ret = hd44780_chipinit(sc, 0);
  443         if (ret != 0 || !(sc->sc_flags & HD_MULTICHIP)) return ret;
  444         else return hd44780_chipinit(sc, 1);
  445 }
  446 
  447 /*
  448  * Initialize 4-bit or 8-bit connected device.
  449  */
  450 int
  451 hd44780_chipinit(sc, en)
  452         struct hd44780_chip *sc;
  453         u_int32_t en;
  454 {
  455         u_int8_t cmd, dat;
  456 
  457         sc->sc_flags &= ~(HD_TIMEDOUT|HD_UP);
  458         sc->sc_dev_ok = 1;
  459 
  460         cmd = cmd_init(sc->sc_flags & HD_8BIT);
  461         hd44780_ir_write(sc, en, cmd);
  462         delay(HD_TIMEOUT_LONG);
  463         hd44780_ir_write(sc, en, cmd);
  464         hd44780_ir_write(sc, en, cmd);
  465 
  466         cmd = cmd_funcset(
  467                         sc->sc_flags & HD_8BIT,
  468                         sc->sc_flags & HD_MULTILINE,
  469                         sc->sc_flags & HD_BIGFONT);
  470 
  471         if ((sc->sc_flags & HD_8BIT) == 0)
  472                 hd44780_ir_write(sc, en, cmd);
  473 
  474         sc->sc_flags |= HD_UP;
  475 
  476         hd44780_ir_write(sc, en, cmd);
  477         hd44780_ir_write(sc, en, cmd_dispctl(0, 0, 0));
  478         hd44780_ir_write(sc, en, cmd_clear());
  479         hd44780_ir_write(sc, en, cmd_modset(1, 0));
  480 
  481         if (sc->sc_flags & HD_TIMEDOUT) {
  482                 sc->sc_flags &= ~HD_UP;
  483                 return EIO;
  484         }
  485 
  486         /* Turn display on and clear it. */
  487         hd44780_ir_write(sc, en, cmd_clear());
  488         hd44780_ir_write(sc, en, cmd_dispctl(1, 0, 0));
  489 
  490         /* Attempt a simple probe for presence */
  491         hd44780_ir_write(sc, en, cmd_ddramset(0x5));
  492         hd44780_ir_write(sc, en, cmd_shift(0, 1));
  493         hd44780_busy_wait(sc, en);
  494         if ((dat = hd44780_ir_read(sc, en) & 0x7f) != 0x6) {
  495                 sc->sc_dev_ok = 0;
  496                 sc->sc_flags &= ~HD_UP;
  497                 return EIO;
  498         }
  499         hd44780_ir_write(sc, en, cmd_ddramset(0));
  500 
  501         return 0;
  502 }
  503 
  504 /*
  505  * Standard hd44780 ioctl() functions.
  506  */
  507 int
  508 hd44780_ioctl_subr(sc, cmd, data)
  509         struct hd44780_chip *sc;
  510         u_long cmd;
  511         void *data;
  512 {
  513         u_int8_t tmp;
  514         int error = 0;
  515         u_int32_t en = sc->sc_curchip;
  516 
  517 #define hd44780_io()    ((struct hd44780_io *)data)
  518 #define hd44780_info()  ((struct hd44780_info*)data)
  519 #define hd44780_ctrl()  ((struct hd44780_dispctl*)data)
  520 
  521         switch (cmd) {
  522                 /* Clear the LCD. */
  523                 case HLCD_CLEAR:
  524                         hd44780_ir_write(sc, en, cmd_clear());
  525                         break;
  526 
  527                 /* Move the cursor one position to the left. */
  528                 case HLCD_CURSOR_LEFT:
  529                         hd44780_ir_write(sc, en, cmd_shift(0, 0));
  530                         break;
  531 
  532                 /* Move the cursor one position to the right. */
  533                 case HLCD_CURSOR_RIGHT:
  534                         hd44780_ir_write(sc, en, cmd_shift(0, 1));
  535                         break;
  536 
  537                 /* Control the LCD. */
  538                 case HLCD_DISPCTL:
  539                         hd44780_ir_write(sc, en, cmd_dispctl(
  540                                                 hd44780_ctrl()->display_on,
  541                                                 hd44780_ctrl()->cursor_on,
  542                                                 hd44780_ctrl()->blink_on));
  543                         break;
  544 
  545                 /* Get LCD configuration. */
  546                 case HLCD_GET_INFO:
  547                         hd44780_info()->lines
  548                                 = (sc->sc_flags & HD_MULTILINE) ? 2 : 1;
  549                         if (sc->sc_flags & HD_MULTICHIP)
  550                                 hd44780_info()->lines *= 2;
  551                         hd44780_info()->phys_rows = sc->sc_cols;
  552                         hd44780_info()->virt_rows = sc->sc_vcols;
  553                         hd44780_info()->is_wide = sc->sc_flags & HD_8BIT;
  554                         hd44780_info()->is_bigfont = sc->sc_flags & HD_BIGFONT;
  555                         hd44780_info()->kp_present = sc->sc_flags & HD_KEYPAD;
  556                         break;
  557 
  558 
  559                 /* Reset the LCD. */
  560                 case HLCD_RESET:
  561                         error = hd44780_init(sc);
  562                         break;
  563 
  564                 /* Get the current cursor position. */
  565                 case HLCD_GET_CURSOR_POS:
  566                         hd44780_io()->dat = (hd44780_ir_read(sc, en) & 0x7f);
  567                         break;
  568 
  569                 /* Set the cursor position. */
  570                 case HLCD_SET_CURSOR_POS:
  571                         hd44780_ir_write(sc, en, cmd_ddramset(hd44780_io()->dat));
  572                         break;
  573 
  574                 /* Get the value at the current cursor position. */
  575                 case HLCD_GETC:
  576                         tmp = (hd44780_ir_read(sc, en) & 0x7f);
  577                         hd44780_ir_write(sc, en, cmd_ddramset(tmp));
  578                         hd44780_io()->dat = hd44780_dr_read(sc, en);
  579                         break;
  580 
  581                 /* Set the character at the cursor position + advance cursor. */
  582                 case HLCD_PUTC:
  583                         hd44780_dr_write(sc, en, hd44780_io()->dat);
  584                         break;
  585 
  586                 /* Shift display left. */
  587                 case HLCD_SHIFT_LEFT:
  588                         hd44780_ir_write(sc, en, cmd_shift(1, 0));
  589                         break;
  590 
  591                 /* Shift display right. */
  592                 case HLCD_SHIFT_RIGHT:
  593                         hd44780_ir_write(sc, en, cmd_shift(1, 1));
  594                         break;
  595 
  596                 /* Return home. */
  597                 case HLCD_HOME:
  598                         hd44780_ir_write(sc, en, cmd_rethome());
  599                         break;
  600 
  601                 /* Write a string to the LCD virtual area. */
  602                 case HLCD_WRITE:
  603                         error = hd44780_ddram_io(sc, en, hd44780_io(), HD_DDRAM_WRITE);
  604                         break;
  605 
  606                 /* Read LCD virtual area. */
  607                 case HLCD_READ:
  608                         error = hd44780_ddram_io(sc, en, hd44780_io(), HD_DDRAM_READ);
  609                         break;
  610 
  611                 /* Write to the LCD visible area. */
  612                 case HLCD_REDRAW:
  613                         hd44780_ddram_redraw(sc, en, hd44780_io());
  614                         break;
  615 
  616                 /* Write raw instruction. */
  617                 case HLCD_WRITE_INST:
  618                         hd44780_ir_write(sc, en, hd44780_io()->dat);
  619                         break;
  620 
  621                 /* Write raw data. */
  622                 case HLCD_WRITE_DATA:
  623                         hd44780_dr_write(sc, en, hd44780_io()->dat);
  624                         break;
  625 
  626                 /* Get current chip 0 or 1 (top or bottom) */
  627                 case HLCD_GET_CHIPNO:
  628                         *(u_int8_t *)data = sc->sc_curchip;
  629                         break;
  630 
  631                 /* Set current chip 0 or 1 (top or bottom) */
  632                 case HLCD_SET_CHIPNO:
  633                         sc->sc_curchip = *(u_int8_t *)data;
  634                         break;
  635 
  636                 default:
  637                         error = EINVAL;
  638         }
  639 
  640         if (sc->sc_flags & HD_TIMEDOUT)
  641                 error = EIO;
  642 
  643         return error;
  644 }
  645 
  646 /*
  647  * Read/write particular area of the LCD screen.
  648  */
  649 int
  650 hd44780_ddram_io(sc, en, io, dir)
  651         struct hd44780_chip *sc;
  652         u_int32_t en;
  653         struct hd44780_io *io;
  654         u_char dir;
  655 {
  656         u_int8_t hi;
  657         u_int8_t addr;
  658 
  659         int error = 0;
  660         u_int8_t i = 0;
  661 
  662         if (io->dat < sc->sc_vcols) {
  663                 hi = HD_ROW1_ADDR + sc->sc_vcols;
  664                 addr = HD_ROW1_ADDR + io->dat;
  665                 for (; (addr < hi) && (i < io->len); addr++, i++) {
  666                         hd44780_ir_write(sc, en, cmd_ddramset(addr));
  667                         if (dir == HD_DDRAM_READ)
  668                                 io->buf[i] = hd44780_dr_read(sc, en);
  669                         else
  670                                 hd44780_dr_write(sc, en, io->buf[i]);
  671                 }
  672         }
  673         if (io->dat < 2 * sc->sc_vcols) {
  674                 hi = HD_ROW2_ADDR + sc->sc_vcols;
  675                 if (io->dat >= sc->sc_vcols)
  676                         addr = HD_ROW2_ADDR + io->dat - sc->sc_vcols;
  677                 else
  678                         addr = HD_ROW2_ADDR;
  679                 for (; (addr < hi) && (i < io->len); addr++, i++) {
  680                         hd44780_ir_write(sc, en, cmd_ddramset(addr));
  681                         if (dir == HD_DDRAM_READ)
  682                                 io->buf[i] = hd44780_dr_read(sc, en);
  683                         else
  684                                 hd44780_dr_write(sc, en, io->buf[i]);
  685                 }
  686                 if (i < io->len)
  687                         io->len = i;
  688         } else {
  689                 error = EINVAL;
  690         }
  691         return error;
  692 }
  693 
  694 /*
  695  * Write to the visible area of the display.
  696  */
  697 void
  698 hd44780_ddram_redraw(sc, en, io)
  699         struct hd44780_chip *sc;
  700         u_int32_t en;
  701         struct hd44780_io *io;
  702 {
  703         u_int8_t i;
  704 
  705         hd44780_ir_write(sc, en, cmd_clear());
  706         hd44780_ir_write(sc, en, cmd_rethome());
  707         hd44780_ir_write(sc, en, cmd_ddramset(HD_ROW1_ADDR));
  708         for (i = 0; (i < io->len) && (i < sc->sc_cols); i++) {
  709                 hd44780_dr_write(sc, en, io->buf[i]);
  710         }
  711         hd44780_ir_write(sc, en, cmd_ddramset(HD_ROW2_ADDR));
  712         for (; (i < io->len); i++)
  713                 hd44780_dr_write(sc, en, io->buf[i]);
  714 }
  715 
  716 void
  717 hd44780_busy_wait(sc, en)
  718         struct hd44780_chip *sc;
  719         u_int32_t en;
  720 {
  721         int nloops = 100;
  722 
  723         if (sc->sc_flags & HD_TIMEDOUT)
  724                 return;
  725 
  726         while(nloops-- && (hd44780_ir_read(sc, en) & BUSY_FLAG) == BUSY_FLAG);
  727 
  728         if (nloops == 0) {
  729                 sc->sc_flags |= HD_TIMEDOUT;
  730                 sc->sc_dev_ok = 0;
  731         }
  732 }
  733 
  734 #if defined(HD44780_STD_WIDE)
  735 /*
  736  * Standard 8-bit version of 'sc_writereg' (8-bit port, 8-bit access)
  737  */
  738 void
  739 hd44780_writereg(sc, en, reg, cmd)
  740         struct hd44780_chip *sc;
  741         u_int32_t en, reg;
  742         u_int8_t cmd;
  743 {
  744         bus_space_tag_t iot = sc->sc_iot;
  745         bus_space_handle_t ioh;
  746 
  747         if (sc->sc_dev_ok == 0)
  748                 return;
  749 
  750         if (reg == 0)
  751                 ioh = sc->sc_ioir;
  752         else
  753                 ioh = sc->sc_iodr;
  754 
  755         bus_space_write_1(iot, ioh, 0x00, cmd);
  756         delay(HD_TIMEOUT_NORMAL);
  757 }
  758 
  759 /*
  760  * Standard 8-bit version of 'sc_readreg' (8-bit port, 8-bit access)
  761  */
  762 u_int8_t
  763 hd44780_readreg(sc, en, reg)
  764         struct hd44780_chip *sc;
  765         u_int32_t en, reg;
  766 {
  767         bus_space_tag_t iot = sc->sc_iot;
  768         bus_space_handle_t ioh;
  769 
  770         if (sc->sc_dev_ok == 0)
  771                 return;
  772 
  773         if (reg == 0)
  774                 ioh = sc->sc_ioir;
  775         else
  776                 ioh = sc->sc_iodr;
  777 
  778         delay(HD_TIMEOUT_NORMAL);
  779         return bus_space_read_1(iot, ioh, 0x00);
  780 }
  781 #elif defined(HD44780_STD_SHORT)
  782 /*
  783  * Standard 4-bit version of 'sc_writereg' (4-bit port, 8-bit access)
  784  */
  785 void
  786 hd44780_writereg(sc, en, reg, cmd)
  787         struct hd44780_chip *sc;
  788         u_int32_t en, reg;
  789         u_int8_t cmd;
  790 {
  791         bus_space_tag_t iot = sc->sc_iot;
  792         bus_space_handle_t ioh;
  793 
  794         if (sc->sc_dev_ok == 0)
  795                 return;
  796 
  797         if (reg == 0)
  798                 ioh = sc->sc_ioir;
  799         else
  800                 ioh = sc->sc_iodr;
  801 
  802         bus_space_write_1(iot, ioh, 0x00, hi_bits(cmd));
  803         if (sc->sc_flags & HD_UP)
  804                 bus_space_write_1(iot, ioh, 0x00, lo_bits(cmd));
  805         delay(HD_TIMEOUT_NORMAL);
  806 }
  807 
  808 /*
  809  * Standard 4-bit version of 'sc_readreg' (4-bit port, 8-bit access)
  810  */
  811 u_int8_t
  812 hd44780_readreg(sc, en, reg)
  813         struct hd44780_chip *sc;
  814         u_int32_t en, reg;
  815 {
  816         bus_space_tag_t iot = sc->sc_iot;
  817         bus_space_handle_t ioh;
  818         u_int8_t rd, dat;
  819 
  820         if (sc->sc_dev_ok == 0)
  821                 return;
  822 
  823         if (reg == 0)
  824                 ioh = sc->sc_ioir;
  825         else
  826                 ioh = sc->sc_iodr;
  827 
  828         rd = bus_space_read_1(iot, ioh, 0x00);
  829         dat = (rd & 0x0f) << 4;
  830         rd = bus_space_read_1(iot, ioh, 0x00);
  831         return (dat | (rd & 0x0f));
  832 }
  833 #endif

Cache object: a0afcde02f5ba5d792dbc082ff6df4ad


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.