vrc4172pwm.c revision 1.6 1 /* $Id: vrc4172pwm.c,v 1.6 2001/02/16 12:31:46 sato Exp $ */
2
3 /*
4 * Copyright (c) 2000 SATO Kazumi. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/device.h>
31 #include <sys/reboot.h>
32
33 #include <machine/bus.h>
34 #include <machine/config_hook.h>
35 #include <machine/platid.h>
36 #include <machine/platid_mask.h>
37
38 #include <hpcmips/vr/vr.h>
39 #include <hpcmips/vr/vripvar.h>
40 #include <hpcmips/vr/vrc4172pwmvar.h>
41 #include <hpcmips/vr/vrc4172pwmreg.h>
42
43 #include "locators.h"
44
45 #ifdef VRC2PWMDEBUG
46 #ifndef VRC2PWMDEBUG_CONF
47 #define VRC2PWMDEBUG_CONF 0
48 #endif /* VRC2PWMDEBUG_CONF */
49 int vrc4172pwmdebug = VRC2PWMDEBUG_CONF;
50 #define DPRINTF(arg) if (vrc4172pwmdebug) printf arg;
51 #define VPRINTF(arg) if (bootverbose||vrc4172pwmdebug) printf arg;
52 #define VDUMPREG(arg) if (bootverbose||vrc4172pwmdebug) vrc4172pwm_dumpreg(arg);
53 #else /* VRC2PWMDEBUG */
54 #define DPRINTF(arg)
55 #define VPRINTF(arg) if (bootverbose) printf arg;
56 #define VDUMPREG(arg) if (bootverbose) vrc4172pwm_dumpreg(arg);
57 #endif /* VRC2PWMDEBUG */
58
59 static int vrc4172pwmprobe __P((struct device *, struct cfdata *, void *));
60 static void vrc4172pwmattach __P((struct device *, struct device *, void *));
61
62 static void vrc4172pwm_write __P((struct vrc4172pwm_softc *, int, unsigned short));
63 static unsigned short vrc4172pwm_read __P((struct vrc4172pwm_softc *, int));
64
65 static int vrc4172pwm_event __P((void *, int, long, void *));
66 static int vrc4172pwm_pmevent __P((void *, int, long, void *));
67
68 static void vrc4172pwm_dumpreg __P((struct vrc4172pwm_softc *));
69 static void vrc4172pwm_init_brightness __P((struct vrc4172pwm_softc *));
70 void vrc4172pwm_light __P((struct vrc4172pwm_softc *, int));
71 int vrc4172pwm_get_light __P((struct vrc4172pwm_softc *));
72 int vrc4172pwm_get_brightness __P((struct vrc4172pwm_softc *));
73 void vrc4172pwm_set_brightness __P((struct vrc4172pwm_softc *, int));
74 int vrc4172pwm_rawduty2brightness __P((struct vrc4172pwm_softc *));
75 int vrc4172pwm_brightness2rawduty __P((struct vrc4172pwm_softc *));
76 struct vrc4172pwm_param * vrc4172pwm_getparam __P((void));
77 void vrc4172pwm_dumpreg __P((struct vrc4172pwm_softc *));
78
79 struct cfattach vrc4172pwm_ca = {
80 sizeof(struct vrc4172pwm_softc), vrc4172pwmprobe, vrc4172pwmattach
81 };
82
83 /*
84 * platform related parameters
85 */
86 struct vrc4172pwm_param vrc4172pwm_mcr530_param = {
87 8,
88 { 0x16, 0x1b, 0x20, 0x25, 0x2a, 0x30, 0x37, 0x3f }
89 };
90
91 struct platid_data vrc4172pwm_platid_param_table[] = {
92 { &platid_mask_MACH_NEC_MCR_430,
93 &vrc4172pwm_mcr530_param},
94 { &platid_mask_MACH_NEC_MCR_530,
95 &vrc4172pwm_mcr530_param},
96 { &platid_mask_MACH_NEC_MCR_530A,
97 &vrc4172pwm_mcr530_param},
98 { &platid_mask_MACH_NEC_MCR_SIGMARION,
99 &vrc4172pwm_mcr530_param},
100 { NULL, NULL}
101 };
102
103 struct vrc4172pwm_softc *this_pwm;
104
105 static inline void
106 vrc4172pwm_write(sc, port, val)
107 struct vrc4172pwm_softc *sc;
108 int port;
109 unsigned short val;
110 {
111 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
112 }
113
114 static inline unsigned short
115 vrc4172pwm_read(sc, port)
116 struct vrc4172pwm_softc *sc;
117 int port;
118 {
119 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
120 }
121
122 static int
123 vrc4172pwmprobe(parent, cf, aux)
124 struct device *parent;
125 struct cfdata *cf;
126 void *aux;
127 {
128 platid_mask_t mask;
129 struct vrip_attach_args *va = aux;
130 bus_space_handle_t ioh;
131 int data;
132 int ret = 0;
133
134 if (va->va_addr == VRIPCF_ADDR_DEFAULT)
135 return 0;
136
137 if (cf->cf_loc[VRIPCF_PLATFORM] == 0)
138 return 0;
139 if (cf->cf_loc[VRIPCF_PLATFORM] != -1) { /* if specify */
140 mask = PLATID_DEREF(cf->cf_loc[VRIPCF_PLATFORM]);
141 DPRINTF(("vrc4172pwmprobe: check platid\n"));
142 if (platid_match(&platid, &mask) == 0)
143 return 0;
144 }
145 if (bus_space_map(va->va_iot, va->va_addr, va->va_size, 0, &ioh)) {
146 return 0;
147 }
148 data = bus_space_read_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN);
149 bus_space_write_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN, 0xff);
150 if (bus_space_read_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN)
151 == VRC2_PWM_LCDEN_MASK) {
152 DPRINTF(("vrc4172pwmprobe: VRC2_PWM_LCDDUTYEN found\n"));
153 ret = 1;
154 }
155 bus_space_write_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN, data);
156 bus_space_unmap(va->va_iot, ioh, va->va_size);
157
158 DPRINTF(("vrc4172pwmprobe: return %d\n", ret));
159 return ret;
160 }
161
162 static void
163 vrc4172pwmattach(parent, self, aux)
164 struct device *parent;
165 struct device *self;
166 void *aux;
167 {
168 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)self;
169 struct vrip_attach_args *va = aux;
170
171 bus_space_tag_t iot = va->va_iot;
172 bus_space_handle_t ioh;
173
174 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
175 printf(": can't map bus space\n");
176 return;
177 }
178
179 sc->sc_iot = iot;
180 sc->sc_ioh = ioh;
181
182 printf("\n");
183
184 VDUMPREG(sc);
185 /* basic setup */
186 sc->sc_pmhook = config_hook(CONFIG_HOOK_PMEVENT,
187 CONFIG_HOOK_PMEVENT_HARDPOWER,
188 CONFIG_HOOK_SHARE,
189 vrc4172pwm_pmevent, sc);
190 sc->sc_lcdhook = config_hook(CONFIG_HOOK_POWERCONTROL,
191 CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
192 CONFIG_HOOK_SHARE,
193 vrc4172pwm_event, sc);
194 sc->sc_getlcdhook = config_hook(CONFIG_HOOK_GET,
195 CONFIG_HOOK_POWER_LCDLIGHT,
196 CONFIG_HOOK_SHARE,
197 vrc4172pwm_event, sc);
198 sc->sc_sethook = config_hook(CONFIG_HOOK_SET,
199 CONFIG_HOOK_BRIGHTNESS,
200 CONFIG_HOOK_SHARE,
201 vrc4172pwm_event, sc);
202 sc->sc_gethook = config_hook(CONFIG_HOOK_GET,
203 CONFIG_HOOK_BRIGHTNESS,
204 CONFIG_HOOK_SHARE,
205 vrc4172pwm_event, sc);
206 sc->sc_getmaxhook = config_hook(CONFIG_HOOK_GET,
207 CONFIG_HOOK_BRIGHTNESS_MAX,
208 CONFIG_HOOK_SHARE,
209 vrc4172pwm_event, sc);
210
211 vrc4172pwm_init_brightness(sc);
212 this_pwm = sc;
213 }
214
215 /*
216 * get platform related brightness paramerters
217 */
218 struct vrc4172pwm_param *
219 vrc4172pwm_getparam()
220 {
221 struct platid_data *p;
222
223 if ((p = platid_search(&platid, vrc4172pwm_platid_param_table)))
224 return p->data;
225 return NULL;
226 }
227
228 /*
229 *
230 * Initialize PWM brightness parameters
231 *
232 */
233 void
234 vrc4172pwm_init_brightness(sc)
235 struct vrc4172pwm_softc *sc;
236 {
237 sc->sc_param = vrc4172pwm_getparam();
238 sc->sc_raw_freq = vrc4172pwm_read(sc, VRC2_PWM_LCDFREQ);
239 sc->sc_raw_duty = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTY);
240 sc->sc_brightness = vrc4172pwm_rawduty2brightness(sc);
241 DPRINTF(("vrc4172pwm_init_brightness: param=0x%x, freq=0x%x, duty=0x%x, blightness=%d\n", (int)sc->sc_param, sc->sc_raw_freq, sc->sc_raw_duty, sc->sc_brightness));
242 }
243 /*
244 * backlight on/off
245 */
246 void
247 vrc4172pwm_light(sc, on)
248 struct vrc4172pwm_softc *sc;
249 int on;
250 {
251 int brightness;
252
253 DPRINTF(("vrc4172pwm_light: %s\n", on?"ON":"OFF"));
254 if (on) {
255 vrc4172pwm_set_brightness(sc, sc->sc_brightness);
256 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTYEN, VRC2_PWM_LCD_EN);
257 } else {
258 brightness = sc->sc_brightness; /* save */
259 vrc4172pwm_set_brightness(sc, 0);
260 /* need this, break sc->sc_brightness */
261 sc->sc_brightness = brightness; /* resume */
262 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTYEN, VRC2_PWM_LCD_DIS);
263 }
264 }
265
266 /*
267 * get backlight on/off
268 */
269 inline int
270 vrc4172pwm_get_light(sc)
271 struct vrc4172pwm_softc *sc;
272 {
273 return vrc4172pwm_read(sc, VRC2_PWM_LCDDUTYEN);
274 }
275
276 /*
277 * set brightness
278 */
279 void
280 vrc4172pwm_set_brightness(sc, val)
281 struct vrc4172pwm_softc *sc;
282 int val;
283 {
284 int raw;
285
286 if (sc->sc_param == NULL)
287 return;
288 if (val < 0)
289 val = 0;
290 if (val > VRC2_PWM_MAX_BRIGHTNESS)
291 val = VRC2_PWM_MAX_BRIGHTNESS;
292 if (val > sc->sc_param->n_brightness)
293 val = sc->sc_param->n_brightness;
294 sc->sc_brightness = val;
295 raw = vrc4172pwm_brightness2rawduty(sc);
296 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTY, raw);
297 DPRINTF(("vrc4172pwm_set_brightness: val=%d raw=0x%x\n", val, raw));
298 }
299
300 /*
301 * get brightness
302 */
303 int
304 vrc4172pwm_get_brightness(sc)
305 struct vrc4172pwm_softc *sc;
306 {
307 if (sc->sc_param == NULL)
308 return VRC2_PWM_MAX_BRIGHTNESS;
309 return sc->sc_brightness;
310 }
311
312 /*
313 * PWM duty to brightness
314 */
315 int
316 vrc4172pwm_rawduty2brightness(sc)
317 struct vrc4172pwm_softc *sc;
318 {
319 int i;
320
321 if (sc->sc_param == NULL)
322 return VRC2_PWM_MAX_BRIGHTNESS;
323 for (i = 0; i < sc->sc_param->n_brightness; i++) {
324 if (sc->sc_raw_duty <= sc->sc_param->values[i])
325 break;
326 }
327 if (i >= sc->sc_param->n_brightness-1)
328 return sc->sc_param->n_brightness-1;
329 else
330 return i;
331
332 }
333
334 /*
335 * brightness to raw duty
336 */
337 int
338 vrc4172pwm_brightness2rawduty(sc)
339 struct vrc4172pwm_softc *sc;
340 {
341 if (sc->sc_param == NULL)
342 return VRC2_PWM_LCDDUTY_MASK;
343 return sc->sc_param->values[sc->sc_brightness];
344 }
345
346
347 /*
348 * PWM config hook events
349 *
350 */
351 int
352 vrc4172pwm_event(ctx, type, id, msg)
353 void *ctx;
354 int type;
355 long id;
356 void *msg;
357 {
358 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)ctx;
359 int why =(int)msg;
360
361 if (type == CONFIG_HOOK_POWERCONTROL
362 && id == CONFIG_HOOK_POWERCONTROL_LCDLIGHT) {
363 VPRINTF(("vrc4172pwm:POWERCONTROL_LCDLIGHT: %d\n", why));
364 vrc4172pwm_light(sc, why);
365 } else if (type == CONFIG_HOOK_GET
366 && id == CONFIG_HOOK_POWER_LCDLIGHT) {
367 *(int *)msg = vrc4172pwm_get_light(sc);
368 VPRINTF(("vrc4172pwm:GET LCDLIGHT: %d\n", *(int *)msg));
369 } else if (type == CONFIG_HOOK_GET
370 && id == CONFIG_HOOK_BRIGHTNESS) {
371 *(int *)msg = vrc4172pwm_get_brightness(sc);
372 VPRINTF(("vrc4172pwm:GET BRIGHTNESS: %d\n", *(int *)msg));
373 } else if (type == CONFIG_HOOK_GET
374 && id == CONFIG_HOOK_BRIGHTNESS_MAX) {
375 if (sc->sc_param == NULL)
376 *(int *)msg = VRC2_PWM_MAX_BRIGHTNESS;
377 else
378 *(int *)msg = sc->sc_param->n_brightness-1;
379 VPRINTF(("vrc4172pwm:GET MAX BRIGHTNESS: %d\n", *(int *)msg));
380 } else if (type == CONFIG_HOOK_SET
381 && id == CONFIG_HOOK_BRIGHTNESS) {
382 VPRINTF(("vrc4172pwm:SET BRIGHTNESS: %d\n", *(int *)msg));
383 vrc4172pwm_set_brightness(sc, *(int *)msg);
384 } else {
385 VPRINTF(("vrc4172pwm:unknown event: type %d id %ld\n", type, id));
386 return 1;
387 }
388
389 return (0);
390 }
391
392
393 /*
394 * PWM config hook events
395 *
396 */
397 int
398 vrc4172pwm_pmevent(ctx, type, id, msg)
399 void *ctx;
400 int type;
401 long id;
402 void *msg;
403 {
404 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)ctx;
405 int why =(int)msg;
406
407 if (type != CONFIG_HOOK_PMEVENT)
408 return 1;
409
410 switch (why) {
411 case PWR_STANDBY:
412 case PWR_SUSPEND:
413 vrc4172pwm_light(sc, 0);
414 break;
415 case PWR_RESUME:
416 vrc4172pwm_light(sc, 1);
417 break;
418 default:
419 return 1;
420 }
421
422 return (0);
423 }
424
425 /*
426 * dump pwm registers
427 */
428 void
429 vrc4172pwm_dumpreg(sc)
430 struct vrc4172pwm_softc *sc;
431 {
432 int en, freq, duty;
433
434 en = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTYEN);
435 freq = vrc4172pwm_read(sc, VRC2_PWM_LCDFREQ);
436 duty = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTY);
437
438 printf("vrc4172pwm: dumpreg: lightenable = %d, freq = 0x%x, duty = 0x%x\n",
439 en, freq, duty);
440 }
441
442 /* end */
443