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.6 2005/02/27 00:27:01 perry 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.6 2005/02/27 00:27:01 perry 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 <machine/intr.h>
   47 #include <machine/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) ? 1 : 0)
   61 #define IDX_TO_COL(idx)         (((idx) >= sc->sc_cols) ? \
   62                                 ((idx) - sc->sc_cols) : (idx))
   63 #define IDX_TO_DDADDR(idx)      ((IDX_TO_ROW((idx)) == 1) ? \
   64                                 (HD_ROW2_ADDR + IDX_TO_COL((idx))) : \
   65                                 (IDX_TO_COL((idx))))
   66 #define DADDR_TO_ROW(daddr)     (((daddr) >= HD_ROW2_ADDR) ? 1 : 0)
   67 #define DADDR_TO_COL(daddr)     ((DADDR_TO_ROW((daddr)) == 1) ? \
   68                                 ((daddr) - HD_ROW2_ADDR) : (daddr))
   69 
   70 static void     hlcd_cursor(void *, int, int, int);
   71 static int      hlcd_mapchar(void *, int, unsigned int *);
   72 static void     hlcd_putchar(void *, int, int, u_int, long);
   73 static void     hlcd_copycols(void *, int, int, int,int);
   74 static void     hlcd_erasecols(void *, int, int, int, long);
   75 static void     hlcd_copyrows(void *, int, int, int);
   76 static void     hlcd_eraserows(void *, int, int, long);
   77 static int      hlcd_allocattr(void *, int, int, int, long *);
   78 static void     hlcd_updatechar(struct hd44780_chip *, int, int);
   79 static void     hlcd_redraw(void *);
   80 
   81 const struct wsdisplay_emulops hlcd_emulops = {
   82         hlcd_cursor,
   83         hlcd_mapchar,
   84         hlcd_putchar,
   85         hlcd_copycols,
   86         hlcd_erasecols,
   87         hlcd_copyrows,
   88         hlcd_eraserows,
   89         hlcd_allocattr
   90 };
   91 
   92 static int      hlcd_ioctl(void *, u_long, caddr_t, int, struct proc *);
   93 static paddr_t  hlcd_mmap(void *, off_t, int);
   94 static int      hlcd_alloc_screen(void *, const struct wsscreen_descr *,
   95                     void **, int *, int *, long *);
   96 static void     hlcd_free_screen(void *, void *);
   97 static int      hlcd_show_screen(void *, void *, int,
   98                     void (*) (void *, int, int), void *);
   99 
  100 const struct wsdisplay_accessops hlcd_accessops = {
  101         hlcd_ioctl,
  102         hlcd_mmap,
  103         hlcd_alloc_screen,
  104         hlcd_free_screen,
  105         hlcd_show_screen,
  106         0 /* load_font */
  107 };
  108 
  109 static void
  110 hlcd_cursor(id, on, row, col)
  111         void *id;
  112         int on, row, col;
  113 {
  114         struct hlcd_screen *hdscr = id;
  115 
  116         hdscr->hlcd_curon = on;
  117         hdscr->hlcd_curx = col;
  118         hdscr->hlcd_cury = row;
  119 }
  120 
  121 static int
  122 hlcd_mapchar(id, uni, index)
  123         void *id;
  124         int uni;
  125         unsigned int *index;
  126 {
  127         if (uni < 256) {
  128                 *index = uni;
  129                 return (5);
  130         }
  131         *index = ' ';
  132         return (0);
  133 }
  134 
  135 static void
  136 hlcd_putchar(id, row, col, c, attr)
  137         void *id;
  138         int row, col;
  139         u_int c;
  140         long attr;
  141 {
  142         struct hlcd_screen *hdscr = id;
  143 
  144         c &= 0xff;
  145         if (row > 0 && (hdscr->hlcd_sc->sc_flags & HD_MULTILINE))
  146                 hdscr->image[hdscr->hlcd_sc->sc_cols * row + col] = c;
  147         else
  148                 hdscr->image[col] = c;
  149 }
  150 
  151 /*
  152  * copies columns inside a row.
  153  */
  154 static void
  155 hlcd_copycols(id, row, srccol, dstcol, ncols)
  156         void *id;
  157         int row, srccol, dstcol, ncols;
  158 {
  159         struct hlcd_screen *hdscr = id;
  160 
  161         if ((dstcol + ncols - 1) > hdscr->hlcd_sc->sc_cols)
  162                 ncols = hdscr->hlcd_sc->sc_cols - srccol;
  163 
  164         if (row > 0 && (hdscr->hlcd_sc->sc_flags & HD_MULTILINE))
  165                 bcopy(&hdscr->image[hdscr->hlcd_sc->sc_cols * row + srccol],
  166                     &hdscr->image[hdscr->hlcd_sc->sc_cols * row + dstcol], ncols);
  167         else
  168                 bcopy(&hdscr->image[srccol], &hdscr->image[dstcol], 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))
  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))
  203                 return;
  204         bcopy(&hdscr->image[srcrow * ncols], &hdscr->image[dstrow * 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, cmd, data, flag, p)
  233         void *v;
  234         u_long cmd;
  235         caddr_t data;
  236         int flag;
  237         struct proc *p;
  238 {
  239 
  240         switch (cmd) {
  241         case WSDISPLAYIO_GTYPE:
  242                 *(u_int *)data = WSDISPLAY_TYPE_HDLCD;
  243                 break;
  244 
  245         case WSDISPLAYIO_SVIDEO:
  246                 break;
  247 
  248         case WSDISPLAYIO_GVIDEO:
  249                 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
  250                 break;
  251 
  252         default:
  253                 return EPASSTHROUGH;
  254         }
  255         return 0;
  256 }
  257 
  258 static paddr_t
  259 hlcd_mmap(v, offset, prot)
  260         void *v;
  261         off_t offset;
  262         int prot;
  263 {
  264         return -1;
  265 }
  266 
  267 static int
  268 hlcd_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
  269         void *v;
  270         const struct wsscreen_descr *type;
  271         void **cookiep;
  272         int *curxp, *curyp;
  273         long *defattrp;
  274 {
  275         struct hlcd_screen *hdscr = v, *new;
  276 
  277         new = *cookiep = malloc(sizeof(struct hlcd_screen), M_DEVBUF, M_WAITOK);
  278         bzero(*cookiep, sizeof(struct hlcd_screen));
  279         new->hlcd_sc = hdscr->hlcd_sc;
  280         new->image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
  281         memset(new->image, ' ', PAGE_SIZE);
  282         *curxp = *curyp = *defattrp = 0;
  283         return 0;
  284 }
  285 
  286 static void
  287 hlcd_free_screen(v, cookie)
  288         void *v, *cookie;
  289 {
  290 }
  291 
  292 static int
  293 hlcd_show_screen(v, cookie, waitok, cb, cbarg)
  294         void *v, *cookie, *cbarg;
  295         int waitok;
  296         void (*cb)(void *, int, int);
  297 {
  298         struct hlcd_screen *hdscr = v;
  299 
  300         hdscr->hlcd_sc->sc_curscr = cookie;
  301         callout_schedule(&hdscr->hlcd_sc->redraw, 1);
  302         return (0);
  303 }
  304 
  305 static void
  306 hlcd_updatechar(sc, daddr, c)
  307         struct hd44780_chip *sc;
  308         int daddr, c;
  309 {
  310         int curdaddr;
  311 
  312         curdaddr = COORD_TO_DADDR(sc->sc_screen.hlcd_curx,
  313             sc->sc_screen.hlcd_cury);
  314         if (daddr != curdaddr)
  315                 hd44780_ir_write(sc, cmd_ddramset(daddr));
  316 
  317         hd44780_dr_write(sc, c);
  318 
  319         daddr++;
  320         sc->sc_screen.hlcd_curx = DADDR_TO_COL(daddr);
  321         sc->sc_screen.hlcd_cury = DADDR_TO_ROW(daddr);
  322 }
  323 
  324 static void
  325 hlcd_redraw(arg)
  326         void *arg;
  327 {
  328         struct hd44780_chip *sc = arg;
  329         int len, crsridx, startidx, x, y;
  330         u_char *img, *curimg;
  331 
  332         if (sc->sc_curscr == NULL)
  333                 return;
  334 
  335         if (sc->sc_flags & HD_MULTILINE)
  336                 len = 2 * sc->sc_cols;
  337         else
  338                 len = sc->sc_cols;
  339 
  340         img = sc->sc_screen.image;
  341         curimg = sc->sc_curscr->image;
  342         startidx = crsridx =
  343             COORD_TO_IDX(sc->sc_screen.hlcd_curx, sc->sc_screen.hlcd_cury);
  344         do {
  345                 if (img[crsridx] != curimg[crsridx]) {
  346                         hlcd_updatechar(sc, IDX_TO_DDADDR(crsridx),
  347                             curimg[crsridx]);
  348                         img[crsridx] = curimg[crsridx];
  349                 }
  350                 crsridx++;
  351                 if (crsridx == len)
  352                         crsridx = 0;
  353         } while (crsridx != startidx);
  354 
  355         if (sc->sc_screen.hlcd_curx != sc->sc_curscr->hlcd_curx ||
  356             sc->sc_screen.hlcd_cury != sc->sc_curscr->hlcd_cury) {
  357                 x = sc->sc_screen.hlcd_curx = sc->sc_curscr->hlcd_curx;
  358                 y = sc->sc_screen.hlcd_cury = sc->sc_curscr->hlcd_cury;
  359                 hd44780_ir_write(sc, cmd_ddramset(COORD_TO_DADDR(x, y)));
  360         }
  361 
  362         if (sc->sc_screen.hlcd_curon != sc->sc_curscr->hlcd_curon) {
  363                 sc->sc_screen.hlcd_curon = sc->sc_curscr->hlcd_curon;
  364                 if (sc->sc_screen.hlcd_curon)
  365                         hd44780_ir_write(sc, cmd_dispctl(1, 1, 1));
  366                 else
  367                         hd44780_ir_write(sc, cmd_dispctl(1, 0, 0));
  368         }
  369 
  370         callout_schedule(&sc->redraw, 1);
  371 }
  372 
  373 
  374 /*
  375  * Finish device attach. sc_writereg, sc_readreg and sc_flags must be properly
  376  * initialized prior to this call.
  377  */
  378 void
  379 hd44780_attach_subr(sc)
  380         struct hd44780_chip *sc;
  381 {
  382         int err = 0;
  383         /* Putc/getc are supposed to be set by platform-dependent code. */
  384         if ((sc->sc_writereg == NULL) || (sc->sc_readreg == NULL))
  385                 sc->sc_dev_ok = 0;
  386 
  387         /* Make sure that HD_MAX_CHARS is enough. */
  388         if ((sc->sc_flags & HD_MULTILINE) && (2 * sc->sc_cols > HD_MAX_CHARS))
  389                 sc->sc_dev_ok = 0;
  390         else if (sc->sc_cols > HD_MAX_CHARS)
  391                 sc->sc_dev_ok = 0;
  392 
  393         if (sc->sc_dev_ok) {
  394                 if ((sc->sc_flags & HD_UP) == 0)
  395                         err = hd44780_init(sc);
  396                 if (err != 0)
  397                         printf("%s: LCD not responding or unconnected\n", sc->sc_dev->dv_xname);
  398 
  399         }
  400 
  401         sc->sc_screen.hlcd_sc = sc;
  402 
  403         sc->sc_screen.image = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
  404         memset(sc->sc_screen.image, ' ', PAGE_SIZE);
  405         sc->sc_curscr = NULL;
  406         callout_init(&sc->redraw);
  407         callout_setfunc(&sc->redraw, hlcd_redraw, sc);
  408 }
  409 
  410 /*
  411  * Initialize 4-bit or 8-bit connected device.
  412  */
  413 int
  414 hd44780_init(sc)
  415         struct hd44780_chip *sc;
  416 {
  417         u_int8_t cmd, dat;
  418 
  419         sc->sc_flags &= ~(HD_TIMEDOUT|HD_UP);
  420         sc->sc_dev_ok = 1;
  421         cmd = cmd_init(sc->sc_flags & HD_8BIT);
  422         hd44780_ir_write(sc, cmd);
  423         delay(HD_TIMEOUT_LONG);
  424         hd44780_ir_write(sc, cmd);
  425         hd44780_ir_write(sc, cmd);
  426 
  427         cmd = cmd_funcset(
  428                         sc->sc_flags & HD_8BIT,
  429                         sc->sc_flags & HD_MULTILINE,
  430                         sc->sc_flags & HD_BIGFONT);
  431 
  432         if ((sc->sc_flags & HD_8BIT) == 0)
  433                 hd44780_ir_write(sc, cmd);
  434 
  435         sc->sc_flags |= HD_UP;
  436 
  437         hd44780_ir_write(sc, cmd);
  438         hd44780_ir_write(sc, cmd_dispctl(0, 0, 0));
  439         hd44780_ir_write(sc, cmd_clear());
  440         hd44780_ir_write(sc, cmd_modset(1, 0));
  441 
  442         if (sc->sc_flags & HD_TIMEDOUT) {
  443                 sc->sc_flags &= ~HD_UP;
  444                 return EIO;
  445         }
  446 
  447         /* Turn display on and clear it. */
  448         hd44780_ir_write(sc, cmd_clear());
  449         hd44780_ir_write(sc, cmd_dispctl(1, 0, 0));
  450 
  451         /* Attempt a simple probe for presence */
  452         hd44780_ir_write(sc, cmd_ddramset(0x5));
  453         hd44780_ir_write(sc, cmd_shift(0, 1));
  454         hd44780_busy_wait(sc);
  455         if ((dat = hd44780_ir_read(sc) & 0x7f) != 0x6) {
  456                 sc->sc_dev_ok = 0;
  457                 sc->sc_flags &= ~HD_UP;
  458                 return EIO;
  459         }
  460         hd44780_ir_write(sc, cmd_ddramset(0));
  461 
  462         return 0;
  463 }
  464 
  465 /*
  466  * Standard hd44780 ioctl() functions.
  467  */
  468 int
  469 hd44780_ioctl_subr(sc, cmd, data)
  470         struct hd44780_chip *sc;
  471         u_long cmd;
  472         caddr_t data;
  473 {
  474         u_int8_t tmp;
  475         int error = 0;
  476 
  477 #define hd44780_io()    ((struct hd44780_io *)data)
  478 #define hd44780_info()  ((struct hd44780_info*)data)
  479 #define hd44780_ctrl()  ((struct hd44780_dispctl*)data)
  480 
  481         switch (cmd) {
  482                 /* Clear the LCD. */
  483                 case HLCD_CLEAR:
  484                         hd44780_ir_write(sc, cmd_clear());
  485                         break;
  486 
  487                 /* Move the cursor one position to the left. */
  488                 case HLCD_CURSOR_LEFT:
  489                         hd44780_ir_write(sc, cmd_shift(0, 0));
  490                         break;
  491 
  492                 /* Move the cursor one position to the right. */
  493                 case HLCD_CURSOR_RIGHT:
  494                         hd44780_ir_write(sc, cmd_shift(0, 1));
  495                         break;
  496 
  497                 /* Control the LCD. */
  498                 case HLCD_DISPCTL:
  499                         hd44780_ir_write(sc, cmd_dispctl(
  500                                                 hd44780_ctrl()->display_on,
  501                                                 hd44780_ctrl()->cursor_on,
  502                                                 hd44780_ctrl()->blink_on));
  503                         break;
  504 
  505                 /* Get LCD configuration. */
  506                 case HLCD_GET_INFO:
  507                         hd44780_info()->lines
  508                                 = (sc->sc_flags & HD_MULTILINE) ? 2 : 1;
  509                         hd44780_info()->phys_rows = sc->sc_cols;
  510                         hd44780_info()->virt_rows = sc->sc_vcols;
  511                         hd44780_info()->is_wide = sc->sc_flags & HD_8BIT;
  512                         hd44780_info()->is_bigfont = sc->sc_flags & HD_BIGFONT;
  513                         hd44780_info()->kp_present = sc->sc_flags & HD_KEYPAD;
  514                         break;
  515 
  516 
  517                 /* Reset the LCD. */
  518                 case HLCD_RESET:
  519                         error = hd44780_init(sc);
  520                         break;
  521 
  522                 /* Get the current cursor position. */
  523                 case HLCD_GET_CURSOR_POS:
  524                         hd44780_io()->dat = (hd44780_ir_read(sc) & 0x7f);
  525                         break;
  526 
  527                 /* Set the cursor position. */
  528                 case HLCD_SET_CURSOR_POS:
  529                         hd44780_ir_write(sc, cmd_ddramset(hd44780_io()->dat));
  530                         break;
  531 
  532                 /* Get the value at the current cursor position. */
  533                 case HLCD_GETC:
  534                         tmp = (hd44780_ir_read(sc) & 0x7f);
  535                         hd44780_ir_write(sc, cmd_ddramset(tmp));
  536                         hd44780_io()->dat = hd44780_dr_read(sc);
  537                         break;
  538 
  539                 /* Set the character at the cursor position + advance cursor. */
  540                 case HLCD_PUTC:
  541                         hd44780_dr_write(sc, hd44780_io()->dat);
  542                         break;
  543 
  544                 /* Shift display left. */
  545                 case HLCD_SHIFT_LEFT:
  546                         hd44780_ir_write(sc, cmd_shift(1, 0));
  547                         break;
  548 
  549                 /* Shift display right. */
  550                 case HLCD_SHIFT_RIGHT:
  551                         hd44780_ir_write(sc, cmd_shift(1, 1));
  552                         break;
  553 
  554                 /* Return home. */
  555                 case HLCD_HOME:
  556                         hd44780_ir_write(sc, cmd_rethome());
  557                         break;
  558 
  559                 /* Write a string to the LCD virtual area. */
  560                 case HLCD_WRITE:
  561                         error = hd44780_ddram_io(sc, hd44780_io(), HD_DDRAM_WRITE);
  562                         break;
  563 
  564                 /* Read LCD virtual area. */
  565                 case HLCD_READ:
  566                         error = hd44780_ddram_io(sc, hd44780_io(), HD_DDRAM_READ);
  567                         break;
  568 
  569                 /* Write to the LCD visible area. */
  570                 case HLCD_REDRAW:
  571                         hd44780_ddram_redraw(sc, hd44780_io());
  572                         break;
  573 
  574                 /* Write raw instruction. */
  575                 case HLCD_WRITE_INST:
  576                         hd44780_ir_write(sc, hd44780_io()->dat);
  577                         break;
  578 
  579                 /* Write raw data. */
  580                 case HLCD_WRITE_DATA:
  581                         hd44780_dr_write(sc, hd44780_io()->dat);
  582                         break;
  583 
  584                 default:
  585                         error = EINVAL;
  586         }
  587 
  588         if (sc->sc_flags & HD_TIMEDOUT)
  589                 error = EIO;
  590 
  591         return error;
  592 }
  593 
  594 /*
  595  * Read/write particular area of the LCD screen.
  596  */
  597 int
  598 hd44780_ddram_io(sc, io, dir)
  599         struct hd44780_chip *sc;
  600         struct hd44780_io *io;
  601         u_char dir;
  602 {
  603         u_int8_t hi;
  604         u_int8_t addr;
  605 
  606         int error = 0;
  607         u_int8_t i = 0;
  608 
  609         if (io->dat < sc->sc_vcols) {
  610                 hi = HD_ROW1_ADDR + sc->sc_vcols;
  611                 addr = HD_ROW1_ADDR + io->dat;
  612                 for (; (addr < hi) && (i < io->len); addr++, i++) {
  613                         hd44780_ir_write(sc, cmd_ddramset(addr));
  614                         if (dir == HD_DDRAM_READ)
  615                                 io->buf[i] = hd44780_dr_read(sc);
  616                         else
  617                                 hd44780_dr_write(sc, io->buf[i]);
  618                 }
  619         }
  620         if (io->dat < 2 * sc->sc_vcols) {
  621                 hi = HD_ROW2_ADDR + sc->sc_vcols;
  622                 if (io->dat >= sc->sc_vcols)
  623                         addr = HD_ROW2_ADDR + io->dat - sc->sc_vcols;
  624                 else
  625                         addr = HD_ROW2_ADDR;
  626                 for (; (addr < hi) && (i < io->len); addr++, i++) {
  627                         hd44780_ir_write(sc, cmd_ddramset(addr));
  628                         if (dir == HD_DDRAM_READ)
  629                                 io->buf[i] = hd44780_dr_read(sc);
  630                         else
  631                                 hd44780_dr_write(sc, io->buf[i]);
  632                 }
  633                 if (i < io->len)
  634                         io->len = i;
  635         } else {
  636                 error = EINVAL;
  637         }
  638         return error;
  639 }
  640 
  641 /*
  642  * Write to the visible area of the display.
  643  */
  644 void
  645 hd44780_ddram_redraw(sc, io)
  646         struct hd44780_chip *sc;
  647         struct hd44780_io *io;
  648 {
  649         u_int8_t i;
  650 
  651         hd44780_ir_write(sc, cmd_clear());
  652         hd44780_ir_write(sc, cmd_rethome());
  653         for (i = 0; (i < io->len) && (i < sc->sc_cols); i++) {
  654                 hd44780_dr_write(sc, io->buf[i]);
  655         }
  656         hd44780_ir_write(sc, cmd_ddramset(HD_ROW2_ADDR));
  657         for (; (i < io->len); i++)
  658                 hd44780_dr_write(sc, io->buf[i]);
  659 }
  660 
  661 void
  662 hd44780_busy_wait(sc)
  663         struct hd44780_chip *sc;
  664 {
  665         int nloops = 100;
  666 
  667         if (sc->sc_flags & HD_TIMEDOUT)
  668                 return;
  669 
  670         while(nloops-- && (hd44780_ir_read(sc) & BUSY_FLAG) == BUSY_FLAG);
  671 
  672         if (nloops == 0) {
  673                 sc->sc_flags |= HD_TIMEDOUT;
  674                 sc->sc_dev_ok = 0;
  675         }
  676 }
  677 
  678 #if defined(HD44780_STD_WIDE)
  679 /*
  680  * Standard 8-bit version of 'sc_writereg' (8-bit port, 8-bit access)
  681  */
  682 void
  683 hd44780_writereg(sc, reg, cmd)
  684         struct hd44780_chip *sc;
  685         u_int32_t reg;
  686         u_int8_t cmd;
  687 {
  688         bus_space_tag_t iot = sc->sc_iot;
  689         bus_space_handle_t ioh;
  690 
  691         if (sc->sc_dev_ok == 0)
  692                 return;
  693 
  694         if (reg == 0)
  695                 ioh = sc->sc_ioir;
  696         else
  697                 ioh = sc->sc_iodr;
  698 
  699         bus_space_write_1(iot, ioh, 0x00, cmd);
  700         delay(HD_TIMEOUT_NORMAL);
  701 }
  702 
  703 /*
  704  * Standard 8-bit version of 'sc_readreg' (8-bit port, 8-bit access)
  705  */
  706 u_int8_t
  707 hd44780_readreg(sc, reg)
  708         struct hd44780_chip *sc;
  709         u_int32_t reg;
  710 {
  711         bus_space_tag_t iot = sc->sc_iot;
  712         bus_space_handle_t ioh;
  713 
  714         if (sc->sc_dev_ok == 0)
  715                 return;
  716 
  717         if (reg == 0)
  718                 ioh = sc->sc_ioir;
  719         else
  720                 ioh = sc->sc_iodr;
  721 
  722         delay(HD_TIMEOUT_NORMAL);
  723         return bus_space_read_1(iot, ioh, 0x00);
  724 }
  725 #elif defined(HD44780_STD_SHORT)
  726 /*
  727  * Standard 4-bit version of 'sc_writereg' (4-bit port, 8-bit access)
  728  */
  729 void
  730 hd44780_writereg(sc, reg, cmd)
  731         struct hd44780_chip *sc;
  732         u_int32_t reg;
  733         u_int8_t cmd;
  734 {
  735         bus_space_tag_t iot = sc->sc_iot;
  736         bus_space_handle_t ioh;
  737 
  738         if (sc->sc_dev_ok == 0)
  739                 return;
  740 
  741         if (reg == 0)
  742                 ioh = sc->sc_ioir;
  743         else
  744                 ioh = sc->sc_iodr;
  745 
  746         bus_space_write_1(iot, ioh, 0x00, hi_bits(cmd));
  747         if (sc->sc_flags & HD_UP)
  748                 bus_space_write_1(iot, ioh, 0x00, lo_bits(cmd));
  749         delay(HD_TIMEOUT_NORMAL);
  750 }
  751 
  752 /*
  753  * Standard 4-bit version of 'sc_readreg' (4-bit port, 8-bit access)
  754  */
  755 u_int8_t
  756 hd44780_readreg(sc, reg)
  757         struct hd44780_chip *sc;
  758         u_int32_t reg;
  759 {
  760         bus_space_tag_t iot = sc->sc_iot;
  761         bus_space_handle_t ioh;
  762         u_int8_t rd, dat;
  763 
  764         if (sc->sc_dev_ok == 0)
  765                 return;
  766 
  767         if (reg == 0)
  768                 ioh = sc->sc_ioir;
  769         else
  770                 ioh = sc->sc_iodr;
  771 
  772         rd = bus_space_read_1(iot, ioh, 0x00);
  773         dat = (rd & 0x0f) << 4;
  774         rd = bus_space_read_1(iot, ioh, 0x00);
  775         return (dat | (rd & 0x0f));
  776 }
  777 #endif

Cache object: 81ec7c4793c3165fed02d2583c8adc09


[ 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.