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

Cache object: 37f16a5fdcd796e4a2fac3bcbf2cd69a


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