j720lcd.c revision 1.3.6.2 1 1.3.6.2 rpaulo /* $NetBSD: j720lcd.c,v 1.3.6.2 2006/09/09 02:39:38 rpaulo Exp $ */
2 1.3.6.2 rpaulo
3 1.3.6.2 rpaulo /*-
4 1.3.6.2 rpaulo * Copyright (c) 2006 The NetBSD Foundation, Inc.
5 1.3.6.2 rpaulo * All rights reserved.
6 1.3.6.2 rpaulo *
7 1.3.6.2 rpaulo * This code is derived from software contributed to The NetBSD Foundation
8 1.3.6.2 rpaulo * by IWAMOTO Toshihiro.
9 1.3.6.2 rpaulo *
10 1.3.6.2 rpaulo * Redistribution and use in source and binary forms, with or without
11 1.3.6.2 rpaulo * modification, are permitted provided that the following conditions
12 1.3.6.2 rpaulo * are met:
13 1.3.6.2 rpaulo * 1. Redistributions of source code must retain the above copyright
14 1.3.6.2 rpaulo * notice, this list of conditions and the following disclaimer.
15 1.3.6.2 rpaulo * 2. Redistributions in binary form must reproduce the above copyright
16 1.3.6.2 rpaulo * notice, this list of conditions and the following disclaimer in the
17 1.3.6.2 rpaulo * documentation and/or other materials provided with the distribution.
18 1.3.6.2 rpaulo * 3. All advertising materials mentioning features or use of this software
19 1.3.6.2 rpaulo * must display the following acknowledgement:
20 1.3.6.2 rpaulo * This product includes software developed by the NetBSD
21 1.3.6.2 rpaulo * Foundation, Inc. and its contributors.
22 1.3.6.2 rpaulo * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.3.6.2 rpaulo * contributors may be used to endorse or promote products derived
24 1.3.6.2 rpaulo * from this software without specific prior written permission.
25 1.3.6.2 rpaulo *
26 1.3.6.2 rpaulo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.3.6.2 rpaulo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.3.6.2 rpaulo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.3.6.2 rpaulo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.3.6.2 rpaulo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.3.6.2 rpaulo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.3.6.2 rpaulo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.3.6.2 rpaulo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.3.6.2 rpaulo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.3.6.2 rpaulo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.3.6.2 rpaulo * POSSIBILITY OF SUCH DAMAGE.
37 1.3.6.2 rpaulo */
38 1.3.6.2 rpaulo
39 1.3.6.2 rpaulo /* Jornada 720 LCD screen driver. */
40 1.3.6.2 rpaulo
41 1.3.6.2 rpaulo #include <sys/cdefs.h>
42 1.3.6.2 rpaulo __KERNEL_RCSID(0, "$NetBSD: j720lcd.c,v 1.3.6.2 2006/09/09 02:39:38 rpaulo Exp $");
43 1.3.6.2 rpaulo
44 1.3.6.2 rpaulo #include <sys/param.h>
45 1.3.6.2 rpaulo #include <sys/systm.h>
46 1.3.6.2 rpaulo #include <sys/device.h>
47 1.3.6.2 rpaulo #include <sys/kernel.h>
48 1.3.6.2 rpaulo
49 1.3.6.2 rpaulo #include <machine/config_hook.h>
50 1.3.6.2 rpaulo #include <machine/platid.h>
51 1.3.6.2 rpaulo #include <machine/platid_mask.h>
52 1.3.6.2 rpaulo
53 1.3.6.2 rpaulo #include <arm/sa11x0/sa11x0_var.h>
54 1.3.6.2 rpaulo #include <arm/sa11x0/sa11x0_gpioreg.h>
55 1.3.6.2 rpaulo #include <arm/sa11x0/sa11x0_ppcreg.h>
56 1.3.6.2 rpaulo #include <arm/sa11x0/sa11x0_sspreg.h>
57 1.3.6.2 rpaulo
58 1.3.6.2 rpaulo #include <hpcarm/dev/j720sspvar.h>
59 1.3.6.2 rpaulo #include <hpcarm/dev/sed1356var.h>
60 1.3.6.2 rpaulo
61 1.3.6.2 rpaulo #ifdef DEBUG
62 1.3.6.2 rpaulo #define DPRINTF(arg) printf arg
63 1.3.6.2 rpaulo #else
64 1.3.6.2 rpaulo #define DPRINTF(arg) /* nothing */
65 1.3.6.2 rpaulo #endif
66 1.3.6.2 rpaulo
67 1.3.6.2 rpaulo struct j720lcd_softc {
68 1.3.6.2 rpaulo struct device sc_dev;
69 1.3.6.2 rpaulo
70 1.3.6.2 rpaulo struct j720ssp_softc *sc_ssp;
71 1.3.6.2 rpaulo };
72 1.3.6.2 rpaulo
73 1.3.6.2 rpaulo static int j720lcd_match(struct device *, struct cfdata *, void *);
74 1.3.6.2 rpaulo static void j720lcd_attach(struct device *, struct device *, void *);
75 1.3.6.2 rpaulo
76 1.3.6.2 rpaulo static int j720lcd_param(void *, int, long, void *);
77 1.3.6.2 rpaulo int j720lcd_power(void *, int, long, void *);
78 1.3.6.2 rpaulo
79 1.3.6.2 rpaulo CFATTACH_DECL(j720lcd, sizeof(struct j720lcd_softc),
80 1.3.6.2 rpaulo j720lcd_match, j720lcd_attach, NULL, NULL);
81 1.3.6.2 rpaulo
82 1.3.6.2 rpaulo
83 1.3.6.2 rpaulo static int
84 1.3.6.2 rpaulo j720lcd_match(struct device *parent, struct cfdata *cf, void *aux)
85 1.3.6.2 rpaulo {
86 1.3.6.2 rpaulo
87 1.3.6.2 rpaulo if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX))
88 1.3.6.2 rpaulo return 0;
89 1.3.6.2 rpaulo if (strcmp(cf->cf_name, "j720lcd") != 0)
90 1.3.6.2 rpaulo return 0;
91 1.3.6.2 rpaulo
92 1.3.6.2 rpaulo return 1;
93 1.3.6.2 rpaulo }
94 1.3.6.2 rpaulo
95 1.3.6.2 rpaulo static void
96 1.3.6.2 rpaulo j720lcd_attach(struct device *parent, struct device *self, void *aux)
97 1.3.6.2 rpaulo {
98 1.3.6.2 rpaulo struct j720lcd_softc *sc = (struct j720lcd_softc *)self;
99 1.3.6.2 rpaulo int brightness, contrast;
100 1.3.6.2 rpaulo
101 1.3.6.2 rpaulo sc->sc_ssp = (struct j720ssp_softc *)parent;
102 1.3.6.2 rpaulo
103 1.3.6.2 rpaulo /* LCD brightness hooks. */
104 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS,
105 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
106 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS,
107 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
108 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX,
109 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
110 1.3.6.2 rpaulo
111 1.3.6.2 rpaulo /* LCD contrast hooks. */
112 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST,
113 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
114 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST,
115 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
116 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX,
117 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_param, sc);
118 1.3.6.2 rpaulo
119 1.3.6.2 rpaulo /* LCD power hook. */
120 1.3.6.2 rpaulo #if 0
121 1.3.6.2 rpaulo config_hook(CONFIG_HOOK_POWERCONTROL,
122 1.3.6.2 rpaulo CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
123 1.3.6.2 rpaulo CONFIG_HOOK_SHARE, j720lcd_power, sc);
124 1.3.6.2 rpaulo #endif
125 1.3.6.2 rpaulo
126 1.3.6.2 rpaulo /* Get default brightness/contrast values. */
127 1.3.6.2 rpaulo config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, &brightness);
128 1.3.6.2 rpaulo config_hook_call(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, &contrast);
129 1.3.6.2 rpaulo
130 1.3.6.2 rpaulo printf(": brightness %d, contrast %d\n", brightness, contrast);
131 1.3.6.2 rpaulo }
132 1.3.6.2 rpaulo
133 1.3.6.2 rpaulo static int
134 1.3.6.2 rpaulo j720lcd_param(void *ctx, int type, long id, void *msg)
135 1.3.6.2 rpaulo {
136 1.3.6.2 rpaulo struct j720lcd_softc *sc = ctx;
137 1.3.6.2 rpaulo struct j720ssp_softc *ssp = sc->sc_ssp;
138 1.3.6.2 rpaulo uint32_t data[2], len;
139 1.3.6.2 rpaulo const int maxval = 255;
140 1.3.6.2 rpaulo int i, s;
141 1.3.6.2 rpaulo
142 1.3.6.2 rpaulo switch (type) {
143 1.3.6.2 rpaulo case CONFIG_HOOK_GET:
144 1.3.6.2 rpaulo switch (id) {
145 1.3.6.2 rpaulo case CONFIG_HOOK_BRIGHTNESS_MAX:
146 1.3.6.2 rpaulo case CONFIG_HOOK_CONTRAST_MAX:
147 1.3.6.2 rpaulo *(int *)msg = maxval;
148 1.3.6.2 rpaulo return 1;
149 1.3.6.2 rpaulo case CONFIG_HOOK_BRIGHTNESS:
150 1.3.6.2 rpaulo data[0] = 0xd6;
151 1.3.6.2 rpaulo data[1] = 0x11;
152 1.3.6.2 rpaulo len = 2;
153 1.3.6.2 rpaulo break;
154 1.3.6.2 rpaulo case CONFIG_HOOK_CONTRAST:
155 1.3.6.2 rpaulo data[0] = 0xd4;
156 1.3.6.2 rpaulo data[1] = 0x11;
157 1.3.6.2 rpaulo len = 2;
158 1.3.6.2 rpaulo break;
159 1.3.6.2 rpaulo default:
160 1.3.6.2 rpaulo return 0;
161 1.3.6.2 rpaulo }
162 1.3.6.2 rpaulo break;
163 1.3.6.2 rpaulo
164 1.3.6.2 rpaulo case CONFIG_HOOK_SET:
165 1.3.6.2 rpaulo switch (id) {
166 1.3.6.2 rpaulo case CONFIG_HOOK_BRIGHTNESS:
167 1.3.6.2 rpaulo if (*(int *)msg >= 0) {
168 1.3.6.2 rpaulo data[0] = 0xd3;
169 1.3.6.2 rpaulo data[1] = maxval - *(int *)msg;
170 1.3.6.2 rpaulo len = 2;
171 1.3.6.2 rpaulo } else {
172 1.3.6.2 rpaulo /* XXX hack */
173 1.3.6.2 rpaulo data[0] = 0xdf;
174 1.3.6.2 rpaulo len = 1;
175 1.3.6.2 rpaulo }
176 1.3.6.2 rpaulo break;
177 1.3.6.2 rpaulo case CONFIG_HOOK_CONTRAST:
178 1.3.6.2 rpaulo data[0] = 0xd1;
179 1.3.6.2 rpaulo data[1] = maxval - *(int *)msg;
180 1.3.6.2 rpaulo len = 2;
181 1.3.6.2 rpaulo break;
182 1.3.6.2 rpaulo default:
183 1.3.6.2 rpaulo return 0;
184 1.3.6.2 rpaulo }
185 1.3.6.2 rpaulo break;
186 1.3.6.2 rpaulo
187 1.3.6.2 rpaulo default:
188 1.3.6.2 rpaulo return 0;
189 1.3.6.2 rpaulo }
190 1.3.6.2 rpaulo
191 1.3.6.2 rpaulo s = splbio();
192 1.3.6.2 rpaulo bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PCR, 0x2000000);
193 1.3.6.2 rpaulo
194 1.3.6.2 rpaulo for (i = 0; i < len; i++) {
195 1.3.6.2 rpaulo if (j720ssp_readwrite(ssp, 1, data[i], &data[i], 500) < 0)
196 1.3.6.2 rpaulo goto out;
197 1.3.6.2 rpaulo }
198 1.3.6.2 rpaulo bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000);
199 1.3.6.2 rpaulo splx(s);
200 1.3.6.2 rpaulo
201 1.3.6.2 rpaulo if (type == CONFIG_HOOK_SET)
202 1.3.6.2 rpaulo return 1;
203 1.3.6.2 rpaulo
204 1.3.6.2 rpaulo *(int *)msg = maxval - data[1];
205 1.3.6.2 rpaulo
206 1.3.6.2 rpaulo return 1;
207 1.3.6.2 rpaulo
208 1.3.6.2 rpaulo out:
209 1.3.6.2 rpaulo bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PSR, 0x2000000);
210 1.3.6.2 rpaulo
211 1.3.6.2 rpaulo /* reset SSP */
212 1.3.6.2 rpaulo bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x307);
213 1.3.6.2 rpaulo delay(100);
214 1.3.6.2 rpaulo bus_space_write_4(ssp->sc_iot, ssp->sc_ssph, SASSP_CR0, 0x387);
215 1.3.6.2 rpaulo
216 1.3.6.2 rpaulo splx(s);
217 1.3.6.2 rpaulo
218 1.3.6.2 rpaulo DPRINTF(("j720lcd_param: error %x %x\n", data[0], data[1]));
219 1.3.6.2 rpaulo return 0;
220 1.3.6.2 rpaulo
221 1.3.6.2 rpaulo }
222 1.3.6.2 rpaulo
223 1.3.6.2 rpaulo int
224 1.3.6.2 rpaulo j720lcd_power(void *ctx, int type, long id, void *msg)
225 1.3.6.2 rpaulo {
226 1.3.6.2 rpaulo struct sed1356_softc *sc = ctx;
227 1.3.6.2 rpaulo struct sa11x0_softc *psc = sc->sc_parent;
228 1.3.6.2 rpaulo uint32_t reg;
229 1.3.6.2 rpaulo int val;
230 1.3.6.2 rpaulo
231 1.3.6.2 rpaulo if (type != CONFIG_HOOK_POWERCONTROL ||
232 1.3.6.2 rpaulo id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT)
233 1.3.6.2 rpaulo return 0;
234 1.3.6.2 rpaulo
235 1.3.6.2 rpaulo sed1356_init_brightness(sc, 0);
236 1.3.6.2 rpaulo sed1356_init_contrast(sc, 0);
237 1.3.6.2 rpaulo
238 1.3.6.2 rpaulo if (msg) {
239 1.3.6.2 rpaulo bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0);
240 1.3.6.2 rpaulo
241 1.3.6.2 rpaulo reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
242 1.3.6.2 rpaulo reg |= 0x1;
243 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
244 1.3.6.2 rpaulo delay(50000);
245 1.3.6.2 rpaulo
246 1.3.6.2 rpaulo val = sc->sc_contrast;
247 1.3.6.2 rpaulo config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
248 1.3.6.2 rpaulo delay(100000);
249 1.3.6.2 rpaulo
250 1.3.6.2 rpaulo reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
251 1.3.6.2 rpaulo reg |= 0x4;
252 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
253 1.3.6.2 rpaulo
254 1.3.6.2 rpaulo val = sc->sc_brightness;
255 1.3.6.2 rpaulo config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
256 1.3.6.2 rpaulo
257 1.3.6.2 rpaulo reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
258 1.3.6.2 rpaulo reg |= 0x2;
259 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
260 1.3.6.2 rpaulo } else {
261 1.3.6.2 rpaulo reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
262 1.3.6.2 rpaulo reg &= ~0x2;
263 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
264 1.3.6.2 rpaulo reg &= ~0x4;
265 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
266 1.3.6.2 rpaulo delay(100000);
267 1.3.6.2 rpaulo
268 1.3.6.2 rpaulo val = -2;
269 1.3.6.2 rpaulo config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
270 1.3.6.2 rpaulo
271 1.3.6.2 rpaulo bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1);
272 1.3.6.2 rpaulo
273 1.3.6.2 rpaulo delay(100000);
274 1.3.6.2 rpaulo reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
275 1.3.6.2 rpaulo reg &= ~0x1;
276 1.3.6.2 rpaulo bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
277 1.3.6.2 rpaulo }
278 1.3.6.2 rpaulo
279 1.3.6.2 rpaulo return 1;
280 1.3.6.2 rpaulo }
281