1 /* $NetBSD: hd44780_subr.c,v 1.19 2009/03/16 23:11:15 dsl Exp $ */
4 * Copyright (c) 2002 Dennis I. Chernoivanov
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
31 * Subroutines for Hitachi HD44870 style displays
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: hd44780_subr.c,v 1.19 2009/03/16 23:11:15 dsl Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/types.h>
43 #include <sys/ioccom.h>
45 #include <machine/autoconf.h>
49 #include <uvm/uvm_extern.h>
51 #include <dev/wscons/wsdisplayvar.h>
52 #include <dev/wscons/wsconsio.h>
53 #include <dev/wscons/wscons_callbacks.h>
55 #include <dev/ic/hd44780reg.h>
56 #include <dev/ic/hd44780var.h>
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 + \
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))
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 *);
80 const struct wsdisplay_emulops hlcd_emulops
= {
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 *);
99 const struct wsdisplay_accessops hlcd_accessops
= {
109 hlcd_cursor(void *id
, int on
, int row
, int col
)
111 struct hlcd_screen
*hdscr
= id
;
113 hdscr
->hlcd_curon
= on
;
114 hdscr
->hlcd_curx
= col
;
115 hdscr
->hlcd_cury
= row
;
119 hlcd_mapchar(void *id
, int uni
, unsigned int *index
)
131 hlcd_putchar(void *id
, int row
, int col
, u_int c
, long attr
)
133 struct hlcd_screen
*hdscr
= id
;
136 if (row
> 0 && (hdscr
->hlcd_sc
->sc_flags
& (HD_MULTILINE
|HD_MULTICHIP
)))
137 hdscr
->image
[hdscr
->hlcd_sc
->sc_cols
* row
+ col
] = c
;
139 hdscr
->image
[col
] = c
;
143 * copies columns inside a row.
146 hlcd_copycols(void *id
, int row
, int srccol
, int dstcol
, int ncols
)
148 struct hlcd_screen
*hdscr
= id
;
150 if ((dstcol
+ ncols
- 1) > hdscr
->hlcd_sc
->sc_cols
)
151 ncols
= hdscr
->hlcd_sc
->sc_cols
- srccol
;
153 if (row
> 0 && (hdscr
->hlcd_sc
->sc_flags
& (HD_MULTILINE
|HD_MULTICHIP
)))
154 memmove(&hdscr
->image
[hdscr
->hlcd_sc
->sc_cols
* row
+ dstcol
],
155 &hdscr
->image
[hdscr
->hlcd_sc
->sc_cols
* row
+ srccol
],
158 memmove(&hdscr
->image
[dstcol
], &hdscr
->image
[srccol
], ncols
);
163 * Erases a bunch of chars inside one row.
166 hlcd_erasecols(void *id
, int row
, int startcol
, int ncols
, long fillattr
)
168 struct hlcd_screen
*hdscr
= id
;
170 if ((startcol
+ ncols
) > hdscr
->hlcd_sc
->sc_cols
)
171 ncols
= hdscr
->hlcd_sc
->sc_cols
- startcol
;
173 if (row
> 0 && (hdscr
->hlcd_sc
->sc_flags
& (HD_MULTILINE
|HD_MULTICHIP
)))
174 memset(&hdscr
->image
[hdscr
->hlcd_sc
->sc_cols
* row
+ startcol
],
177 memset(&hdscr
->image
[startcol
], ' ', ncols
);
182 hlcd_copyrows(void *id
, int srcrow
, int dstrow
, int nrows
)
184 struct hlcd_screen
*hdscr
= id
;
185 int ncols
= hdscr
->hlcd_sc
->sc_cols
;
187 if (!(hdscr
->hlcd_sc
->sc_flags
& (HD_MULTILINE
|HD_MULTICHIP
)))
189 memmove(&hdscr
->image
[dstrow
* ncols
], &hdscr
->image
[srcrow
* ncols
],
194 hlcd_eraserows(void *id
, int startrow
, int nrows
, long fillattr
)
196 struct hlcd_screen
*hdscr
= id
;
197 int ncols
= hdscr
->hlcd_sc
->sc_cols
;
199 memset(&hdscr
->image
[startrow
* ncols
], ' ', ncols
* nrows
);
204 hlcd_allocattr(void *id
, int fg
, int bg
, int flags
, long *attrp
)
212 hlcd_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
216 case WSDISPLAYIO_GTYPE
:
217 *(u_int
*)data
= WSDISPLAY_TYPE_HDLCD
;
220 case WSDISPLAYIO_SVIDEO
:
223 case WSDISPLAYIO_GVIDEO
:
224 *(u_int
*)data
= WSDISPLAYIO_VIDEO_ON
;
234 hlcd_mmap(void *v
, void *vs
, off_t offset
, int prot
)
241 hlcd_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
,
242 int *curxp
, int *curyp
, long *defattrp
)
244 struct hlcd_screen
*hdscr
= v
, *new;
246 new = *cookiep
= malloc(sizeof(struct hlcd_screen
),
247 M_DEVBUF
, M_WAITOK
|M_ZERO
);
248 new->hlcd_sc
= hdscr
->hlcd_sc
;
249 new->image
= malloc(PAGE_SIZE
, M_DEVBUF
, M_WAITOK
);
250 memset(new->image
, ' ', PAGE_SIZE
);
251 *curxp
= *curyp
= *defattrp
= 0;
256 hlcd_free_screen(void *v
, void *cookie
)
261 hlcd_show_screen(void *v
, void *cookie
, int waitok
,
262 void (*cb
)(void *, int, int), void *cbarg
)
264 struct hlcd_screen
*hdscr
= v
;
266 hdscr
->hlcd_sc
->sc_curscr
= cookie
;
267 callout_schedule(&hdscr
->hlcd_sc
->redraw
, 1);
272 hlcd_updatechar(struct hd44780_chip
*sc
, int daddr
, int c
)
274 int curdaddr
, en
, chipdaddr
;
276 curdaddr
= COORD_TO_DADDR(sc
->sc_screen
.hlcd_curx
,
277 sc
->sc_screen
.hlcd_cury
);
278 en
= DADDR_TO_CHIPNO(daddr
);
279 chipdaddr
= DADDR_TO_CHIPDADDR(daddr
);
280 if (daddr
!= curdaddr
)
281 hd44780_ir_write(sc
, en
, cmd_ddramset(chipdaddr
));
283 hd44780_dr_write(sc
, en
, c
);
286 sc
->sc_screen
.hlcd_curx
= DADDR_TO_COL(daddr
);
287 sc
->sc_screen
.hlcd_cury
= DADDR_TO_ROW(daddr
);
291 hlcd_redraw(void *arg
)
293 struct hd44780_chip
*sc
= arg
;
294 int len
, crsridx
, startidx
, x
, y
;
296 uint8_t *img
, *curimg
;
298 if (sc
->sc_curscr
== NULL
)
301 if (sc
->sc_flags
& HD_MULTILINE
)
302 len
= 2 * sc
->sc_cols
;
306 if (sc
->sc_flags
& HD_MULTICHIP
)
309 x
= sc
->sc_screen
.hlcd_curx
;
310 y
= sc
->sc_screen
.hlcd_cury
;
311 old_en
= DADDR_TO_CHIPNO(COORD_TO_DADDR(x
, y
));
313 img
= sc
->sc_screen
.image
;
314 curimg
= sc
->sc_curscr
->image
;
316 COORD_TO_IDX(sc
->sc_screen
.hlcd_curx
, sc
->sc_screen
.hlcd_cury
);
318 if (img
[crsridx
] != curimg
[crsridx
]) {
319 hlcd_updatechar(sc
, IDX_TO_DADDR(crsridx
),
321 img
[crsridx
] = curimg
[crsridx
];
326 } while (crsridx
!= startidx
);
328 x
= sc
->sc_curscr
->hlcd_curx
;
329 y
= sc
->sc_curscr
->hlcd_cury
;
330 new_en
= DADDR_TO_CHIPNO(COORD_TO_DADDR(x
, y
));
332 if (sc
->sc_screen
.hlcd_curx
!= sc
->sc_curscr
->hlcd_curx
||
333 sc
->sc_screen
.hlcd_cury
!= sc
->sc_curscr
->hlcd_cury
) {
335 x
= sc
->sc_screen
.hlcd_curx
= sc
->sc_curscr
->hlcd_curx
;
336 y
= sc
->sc_screen
.hlcd_cury
= sc
->sc_curscr
->hlcd_cury
;
338 hd44780_ir_write(sc
, new_en
, cmd_ddramset(
339 DADDR_TO_CHIPDADDR(COORD_TO_DADDR(x
, y
))));
343 /* visible cursor switched to other chip */
344 if (old_en
!= new_en
&& sc
->sc_screen
.hlcd_curon
) {
345 hd44780_ir_write(sc
, old_en
, cmd_dispctl(1, 0, 0));
346 hd44780_ir_write(sc
, new_en
, cmd_dispctl(1, 1, 1));
349 if (sc
->sc_screen
.hlcd_curon
!= sc
->sc_curscr
->hlcd_curon
) {
350 sc
->sc_screen
.hlcd_curon
= sc
->sc_curscr
->hlcd_curon
;
351 if (sc
->sc_screen
.hlcd_curon
)
352 hd44780_ir_write(sc
, new_en
, cmd_dispctl(1, 1, 1));
354 hd44780_ir_write(sc
, new_en
, cmd_dispctl(1, 0, 0));
357 callout_schedule(&sc
->redraw
, 1);
362 * Finish device attach. sc_writereg, sc_readreg and sc_flags must be properly
363 * initialized prior to this call.
366 hd44780_attach_subr(struct hd44780_chip
*sc
)
370 /* Putc/getc are supposed to be set by platform-dependent code. */
371 if ((sc
->sc_writereg
== NULL
) || (sc
->sc_readreg
== NULL
))
374 /* Make sure that HD_MAX_CHARS is enough. */
375 if ((sc
->sc_flags
& HD_MULTILINE
) && (2 * sc
->sc_cols
> HD_MAX_CHARS
))
377 else if (sc
->sc_cols
> HD_MAX_CHARS
)
381 if ((sc
->sc_flags
& HD_UP
) == 0)
382 err
= hd44780_init(sc
);
384 aprint_error_dev(sc
->sc_dev
,
385 "LCD not responding or unconnected\n");
388 sc
->sc_screen
.hlcd_sc
= sc
;
390 sc
->sc_screen
.image
= malloc(PAGE_SIZE
, M_DEVBUF
, M_WAITOK
);
391 memset(sc
->sc_screen
.image
, ' ', PAGE_SIZE
);
392 sc
->sc_curscr
= NULL
;
394 callout_init(&sc
->redraw
, 0);
395 callout_setfunc(&sc
->redraw
, hlcd_redraw
, sc
);
398 int hd44780_init(struct hd44780_chip
*sc
)
402 ret
= hd44780_chipinit(sc
, 0);
403 if (ret
!= 0 || !(sc
->sc_flags
& HD_MULTICHIP
))
406 return hd44780_chipinit(sc
, 1);
410 * Initialize 4-bit or 8-bit connected device.
413 hd44780_chipinit(struct hd44780_chip
*sc
, uint32_t en
)
417 sc
->sc_flags
&= ~(HD_TIMEDOUT
|HD_UP
);
420 cmd
= cmd_init(sc
->sc_flags
& HD_8BIT
);
421 hd44780_ir_write(sc
, en
, cmd
);
422 delay(HD_TIMEOUT_LONG
);
423 hd44780_ir_write(sc
, en
, cmd
);
424 hd44780_ir_write(sc
, en
, cmd
);
427 sc
->sc_flags
& HD_8BIT
,
428 sc
->sc_flags
& HD_MULTILINE
,
429 sc
->sc_flags
& HD_BIGFONT
);
431 if ((sc
->sc_flags
& HD_8BIT
) == 0)
432 hd44780_ir_write(sc
, en
, cmd
);
434 sc
->sc_flags
|= HD_UP
;
436 hd44780_ir_write(sc
, en
, cmd
);
437 hd44780_ir_write(sc
, en
, cmd_dispctl(0, 0, 0));
438 hd44780_ir_write(sc
, en
, cmd_clear());
439 hd44780_ir_write(sc
, en
, cmd_modset(1, 0));
441 if (sc
->sc_flags
& HD_TIMEDOUT
) {
442 sc
->sc_flags
&= ~HD_UP
;
446 /* Turn display on and clear it. */
447 hd44780_ir_write(sc
, en
, cmd_clear());
448 hd44780_ir_write(sc
, en
, cmd_dispctl(1, 0, 0));
450 /* Attempt a simple probe for presence */
451 hd44780_ir_write(sc
, en
, cmd_ddramset(0x5));
452 hd44780_ir_write(sc
, en
, cmd_shift(0, 1));
453 hd44780_busy_wait(sc
, en
);
454 if ((dat
= hd44780_ir_read(sc
, en
) & 0x7f) != 0x6) {
456 sc
->sc_flags
&= ~HD_UP
;
459 hd44780_ir_write(sc
, en
, cmd_ddramset(0));
465 * Standard hd44780 ioctl() functions.
468 hd44780_ioctl_subr(struct hd44780_chip
*sc
, u_long cmd
, void *data
)
472 uint32_t en
= sc
->sc_curchip
;
474 #define hd44780_io() ((struct hd44780_io *)data)
475 #define hd44780_info() ((struct hd44780_info *)data)
476 #define hd44780_ctrl() ((struct hd44780_dispctl *)data)
481 hd44780_ir_write(sc
, en
, cmd_clear());
484 case HLCD_CURSOR_LEFT
:
485 /* Move the cursor one position to the left. */
486 hd44780_ir_write(sc
, en
, cmd_shift(0, 0));
489 case HLCD_CURSOR_RIGHT
:
490 /* Move the cursor one position to the right. */
491 hd44780_ir_write(sc
, en
, cmd_shift(0, 1));
495 /* Control the LCD. */
496 hd44780_ir_write(sc
, en
, cmd_dispctl(
497 hd44780_ctrl()->display_on
,
498 hd44780_ctrl()->cursor_on
,
499 hd44780_ctrl()->blink_on
));
503 /* Get LCD configuration. */
504 hd44780_info()->lines
505 = (sc
->sc_flags
& HD_MULTILINE
) ? 2 : 1;
506 if (sc
->sc_flags
& HD_MULTICHIP
)
507 hd44780_info()->lines
*= 2;
508 hd44780_info()->phys_rows
= sc
->sc_cols
;
509 hd44780_info()->virt_rows
= sc
->sc_vcols
;
510 hd44780_info()->is_wide
= sc
->sc_flags
& HD_8BIT
;
511 hd44780_info()->is_bigfont
= sc
->sc_flags
& HD_BIGFONT
;
512 hd44780_info()->kp_present
= sc
->sc_flags
& HD_KEYPAD
;
518 error
= hd44780_init(sc
);
521 case HLCD_GET_CURSOR_POS
:
522 /* Get the current cursor position. */
523 hd44780_io()->dat
= (hd44780_ir_read(sc
, en
) & 0x7f);
526 case HLCD_SET_CURSOR_POS
:
527 /* Set the cursor position. */
528 hd44780_ir_write(sc
, en
, cmd_ddramset(hd44780_io()->dat
));
532 /* Get the value at the current cursor position. */
533 tmp
= (hd44780_ir_read(sc
, en
) & 0x7f);
534 hd44780_ir_write(sc
, en
, cmd_ddramset(tmp
));
535 hd44780_io()->dat
= hd44780_dr_read(sc
, en
);
539 /* Set the character at the cursor position + advance cursor. */
540 hd44780_dr_write(sc
, en
, hd44780_io()->dat
);
543 case HLCD_SHIFT_LEFT
:
544 /* Shift display left. */
545 hd44780_ir_write(sc
, en
, cmd_shift(1, 0));
548 case HLCD_SHIFT_RIGHT
:
549 /* Shift display right. */
550 hd44780_ir_write(sc
, en
, cmd_shift(1, 1));
555 hd44780_ir_write(sc
, en
, cmd_rethome());
559 /* Write a string to the LCD virtual area. */
560 error
= hd44780_ddram_io(sc
, en
, hd44780_io(), HD_DDRAM_WRITE
);
564 /* Read LCD virtual area. */
565 error
= hd44780_ddram_io(sc
, en
, hd44780_io(), HD_DDRAM_READ
);
569 /* Write to the LCD visible area. */
570 hd44780_ddram_redraw(sc
, en
, hd44780_io());
573 case HLCD_WRITE_INST
:
574 /* Write raw instruction. */
575 hd44780_ir_write(sc
, en
, hd44780_io()->dat
);
578 case HLCD_WRITE_DATA
:
579 /* Write raw data. */
580 hd44780_dr_write(sc
, en
, hd44780_io()->dat
);
583 case HLCD_GET_CHIPNO
:
584 /* Get current chip 0 or 1 (top or bottom) */
585 *(uint8_t *)data
= sc
->sc_curchip
;
588 case HLCD_SET_CHIPNO
:
589 /* Set current chip 0 or 1 (top or bottom) */
590 sc
->sc_curchip
= *(uint8_t *)data
;
597 if (sc
->sc_flags
& HD_TIMEDOUT
)
604 * Read/write particular area of the LCD screen.
607 hd44780_ddram_io(struct hd44780_chip
*sc
, uint32_t en
, struct hd44780_io
*io
,
615 if (io
->dat
< sc
->sc_vcols
) {
616 hi
= HD_ROW1_ADDR
+ sc
->sc_vcols
;
617 addr
= HD_ROW1_ADDR
+ io
->dat
;
618 for (; (addr
< hi
) && (i
< io
->len
); addr
++, i
++) {
619 hd44780_ir_write(sc
, en
, cmd_ddramset(addr
));
620 if (dir
== HD_DDRAM_READ
)
621 io
->buf
[i
] = hd44780_dr_read(sc
, en
);
623 hd44780_dr_write(sc
, en
, io
->buf
[i
]);
626 if (io
->dat
< 2 * sc
->sc_vcols
) {
627 hi
= HD_ROW2_ADDR
+ sc
->sc_vcols
;
628 if (io
->dat
>= sc
->sc_vcols
)
629 addr
= HD_ROW2_ADDR
+ io
->dat
- sc
->sc_vcols
;
632 for (; (addr
< hi
) && (i
< io
->len
); addr
++, i
++) {
633 hd44780_ir_write(sc
, en
, cmd_ddramset(addr
));
634 if (dir
== HD_DDRAM_READ
)
635 io
->buf
[i
] = hd44780_dr_read(sc
, en
);
637 hd44780_dr_write(sc
, en
, io
->buf
[i
]);
648 * Write to the visible area of the display.
651 hd44780_ddram_redraw(struct hd44780_chip
*sc
, uint32_t en
,
652 struct hd44780_io
*io
)
656 hd44780_ir_write(sc
, en
, cmd_clear());
657 hd44780_ir_write(sc
, en
, cmd_rethome());
658 hd44780_ir_write(sc
, en
, cmd_ddramset(HD_ROW1_ADDR
));
659 for (i
= 0; (i
< io
->len
) && (i
< sc
->sc_cols
); i
++) {
660 hd44780_dr_write(sc
, en
, io
->buf
[i
]);
662 hd44780_ir_write(sc
, en
, cmd_ddramset(HD_ROW2_ADDR
));
663 for (; (i
< io
->len
); i
++)
664 hd44780_dr_write(sc
, en
, io
->buf
[i
]);
668 hd44780_busy_wait(struct hd44780_chip
*sc
, uint32_t en
)
672 if (sc
->sc_flags
& HD_TIMEDOUT
)
675 while (nloops
-- && (hd44780_ir_read(sc
, en
) & BUSY_FLAG
) == BUSY_FLAG
)
679 sc
->sc_flags
|= HD_TIMEDOUT
;
684 #if defined(HD44780_STD_WIDE)
686 * Standard 8-bit version of 'sc_writereg' (8-bit port, 8-bit access)
689 hd44780_writereg(struct hd44780_chip
*sc
, uint32_t en
, uint32_t reg
,
692 bus_space_tag_t iot
= sc
->sc_iot
;
693 bus_space_handle_t ioh
;
695 if (sc
->sc_dev_ok
== 0)
703 bus_space_write_1(iot
, ioh
, 0x00, cmd
);
704 delay(HD_TIMEOUT_NORMAL
);
708 * Standard 8-bit version of 'sc_readreg' (8-bit port, 8-bit access)
711 hd44780_readreg(struct hd44780_chip
*sc
, uint32_t en
, uint32_t reg
)
713 bus_space_tag_t iot
= sc
->sc_iot
;
714 bus_space_handle_t ioh
;
716 if (sc
->sc_dev_ok
== 0)
724 delay(HD_TIMEOUT_NORMAL
);
725 return bus_space_read_1(iot
, ioh
, 0x00);
727 #elif defined(HD44780_STD_SHORT)
729 * Standard 4-bit version of 'sc_writereg' (4-bit port, 8-bit access)
732 hd44780_writereg(struct hd44780_chip
*sc
, uint32_t en
, uint32_t reg
,
735 bus_space_tag_t iot
= sc
->sc_iot
;
736 bus_space_handle_t ioh
;
738 if (sc
->sc_dev_ok
== 0)
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
);
753 * Standard 4-bit version of 'sc_readreg' (4-bit port, 8-bit access)
756 hd44780_readreg(struct hd44780_chip
*sc
, uint32_t en
, uint32_t reg
)
758 bus_space_tag_t iot
= sc
->sc_iot
;
759 bus_space_handle_t ioh
;
762 if (sc
->sc_dev_ok
== 0)
770 rd
= bus_space_read_1(iot
, ioh
, 0x00);
771 dat
= (rd
& 0x0f) << 4;
772 rd
= bus_space_read_1(iot
, ioh
, 0x00);
773 return (dat
| (rd
& 0x0f));