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