xref: /netbsd-src/sys/arch/hppa/dev/lcd.c (revision d1579b2d70337e1b895f03478838f880e450f6da)
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
lcd_match(device_t parent,cfdata_t match,void * aux)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
lcd_attach(device_t parent,device_t self,void * aux)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
lcd_write(struct lcd_softc * sc,const char * str)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
lcd_blink(void * v,int on)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
lcd_blink_finish(void * v)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