1 /* $NetBSD: lcd.c,v 1.2 2018/09/03 16:29:24 riastradh Exp $ */ 2 /* OpenBSD: lcd.c,v 1.2 2007/07/20 22:13:45 kettenis Exp */ 3 4 /* 5 * Copyright (c) 2007 Mark Kettenis 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/device.h> 22 #include <sys/kernel.h> 23 #include <sys/systm.h> 24 #include <sys/callout.h> 25 26 #include <machine/autoconf.h> 27 #include <sys/bus.h> 28 #include <machine/cpu.h> 29 #include <machine/pdc.h> 30 31 #define LCD_CLS 0x01 32 #define LCD_HOME 0x02 33 #define LCD_LOCATE(X, Y) (((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f)) 34 35 struct lcd_softc { 36 device_t sc_dv; 37 38 bus_space_tag_t sc_iot; 39 bus_space_handle_t sc_cmdh, sc_datah; 40 41 u_int sc_delay; 42 uint8_t sc_heartbeat[3]; 43 44 struct callout sc_to; 45 int sc_on; 46 struct blink_lcd sc_blink; 47 }; 48 49 int lcd_match(device_t, cfdata_t, void *); 50 void lcd_attach(device_t, device_t, void *); 51 52 CFATTACH_DECL_NEW(lcd, sizeof(struct lcd_softc), lcd_match, 53 lcd_attach, NULL, NULL); 54 55 void lcd_write(struct lcd_softc *, const char *); 56 void lcd_blink(void *, int); 57 void lcd_blink_finish(void *); 58 59 int 60 lcd_match(device_t parent, cfdata_t match, void *aux) 61 { 62 struct confargs *ca = aux; 63 64 if (strcmp(ca->ca_name, "lcd") == 0) 65 return 1; 66 67 return 0; 68 } 69 70 void 71 lcd_attach(device_t parent, device_t self, void *aux) 72 { 73 struct lcd_softc *sc = device_private(self); 74 struct confargs *ca = aux; 75 struct pdc_chassis_lcd *pdc_lcd = &ca->ca_pcl; 76 int i; 77 78 sc->sc_dv = self; 79 sc->sc_iot = ca->ca_iot; 80 81 if (bus_space_map(sc->sc_iot, pdc_lcd->cmd_addr, 1, 0, &sc->sc_cmdh)) { 82 aprint_error(": can't map cmd register\n"); 83 return; 84 } 85 86 if (bus_space_map(sc->sc_iot, pdc_lcd->data_addr, 1, 0, 87 &sc->sc_datah)) { 88 aprint_error(": can't map data register\n"); 89 bus_space_unmap(sc->sc_iot, sc->sc_cmdh, 1); 90 return; 91 } 92 93 aprint_normal(": model %d\n", pdc_lcd->model); 94 95 sc->sc_delay = pdc_lcd->delay; 96 for (i = 0; i < 3; i++) 97 sc->sc_heartbeat[i] = pdc_lcd->heartbeat[i]; 98 99 bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_CLS); 100 delay(100 * sc->sc_delay); 101 102 bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, LCD_LOCATE(0, 0)); 103 delay(sc->sc_delay); 104 lcd_write(sc, "NetBSD/" MACHINE); 105 106 callout_init(&sc->sc_to, 0); 107 callout_setfunc(&sc->sc_to, lcd_blink_finish, sc); 108 109 sc->sc_blink.bl_func = lcd_blink; 110 sc->sc_blink.bl_arg = sc; 111 blink_lcd_register(&sc->sc_blink); 112 } 113 114 void 115 lcd_write(struct lcd_softc *sc, const char *str) 116 { 117 while (*str) { 118 bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, *str++); 119 delay(sc->sc_delay); 120 } 121 } 122 123 void 124 lcd_blink(void *v, int on) 125 { 126 struct lcd_softc *sc = v; 127 128 sc->sc_on = on; 129 bus_space_write_1(sc->sc_iot, sc->sc_cmdh, 0, sc->sc_heartbeat[0]); 130 callout_schedule(&sc->sc_to, uimax(1, (sc->sc_delay * hz) / 1000000)); 131 } 132 133 void 134 lcd_blink_finish(void *v) 135 { 136 struct lcd_softc *sc = v; 137 uint8_t data; 138 139 if (sc->sc_on) 140 data = sc->sc_heartbeat[1]; 141 else 142 data = sc->sc_heartbeat[2]; 143 144 bus_space_write_1(sc->sc_iot, sc->sc_datah, 0, data); 145 } 146