vrc4172pwm.c revision 1.4 1 /* $Id: vrc4172pwm.c,v 1.4 2000/12/29 15:54:17 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_530A,
93 &vrc4172pwm_mcr530_param},
94 { &platid_mask_MACH_NEC_MCR_SIGMARION,
95 &vrc4172pwm_mcr530_param},
96 { NULL, NULL}
97 };
98
99 struct vrc4172pwm_softc *this_pwm;
100
101 static inline void
102 vrc4172pwm_write(sc, port, val)
103 struct vrc4172pwm_softc *sc;
104 int port;
105 unsigned short val;
106 {
107 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
108 }
109
110 static inline unsigned short
111 vrc4172pwm_read(sc, port)
112 struct vrc4172pwm_softc *sc;
113 int port;
114 {
115 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
116 }
117
118 static int
119 vrc4172pwmprobe(parent, cf, aux)
120 struct device *parent;
121 struct cfdata *cf;
122 void *aux;
123 {
124 platid_mask_t mask;
125 struct vrip_attach_args *va = aux;
126 bus_space_handle_t ioh;
127 int data;
128 int ret = 0;
129
130 if (va->va_addr == VRIPCF_ADDR_DEFAULT)
131 return 0;
132
133 if (cf->cf_loc[NEWGPBUSIFCF_PLATFORM] == 0)
134 return 0;
135 if (cf->cf_loc[NEWGPBUSIFCF_PLATFORM] != -1) { /* if specify */
136 mask = PLATID_DEREF(cf->cf_loc[NEWGPBUSIFCF_PLATFORM]);
137 if (platid_match(&platid, &mask) == 0)
138 return 0;
139 }
140 if (bus_space_map(va->va_iot, va->va_addr, va->va_size, 0, &ioh)) {
141 return 0;
142 }
143 data = bus_space_read_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN);
144 bus_space_write_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN, 0xff);
145 if (bus_space_read_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN)
146 == VRC2_PWM_LCDEN_MASK) {
147 ret = 1;
148 }
149 bus_space_write_2(va->va_iot, ioh, VRC2_PWM_LCDDUTYEN, data);
150 bus_space_unmap(va->va_iot, ioh, va->va_size);
151
152 return ret;
153 }
154
155 static void
156 vrc4172pwmattach(parent, self, aux)
157 struct device *parent;
158 struct device *self;
159 void *aux;
160 {
161 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)self;
162 struct vrip_attach_args *va = aux;
163
164 bus_space_tag_t iot = va->va_iot;
165 bus_space_handle_t ioh;
166
167 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
168 printf(": can't map bus space\n");
169 return;
170 }
171
172 sc->sc_iot = iot;
173 sc->sc_ioh = ioh;
174
175 printf("\n");
176
177 VDUMPREG(sc);
178 /* basic setup */
179 sc->sc_pmhook = config_hook(CONFIG_HOOK_PMEVENT,
180 CONFIG_HOOK_PMEVENT_HARDPOWER,
181 CONFIG_HOOK_SHARE,
182 vrc4172pwm_pmevent, sc);
183 sc->sc_lcdhook = config_hook(CONFIG_HOOK_POWERCONTROL,
184 CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
185 CONFIG_HOOK_SHARE,
186 vrc4172pwm_event, sc);
187 sc->sc_getlcdhook = config_hook(CONFIG_HOOK_GET,
188 CONFIG_HOOK_POWER_LCDLIGHT,
189 CONFIG_HOOK_SHARE,
190 vrc4172pwm_event, sc);
191 sc->sc_sethook = config_hook(CONFIG_HOOK_SET,
192 CONFIG_HOOK_BRIGHTNESS,
193 CONFIG_HOOK_SHARE,
194 vrc4172pwm_event, sc);
195 sc->sc_gethook = config_hook(CONFIG_HOOK_GET,
196 CONFIG_HOOK_BRIGHTNESS,
197 CONFIG_HOOK_SHARE,
198 vrc4172pwm_event, sc);
199 sc->sc_getmaxhook = config_hook(CONFIG_HOOK_GET,
200 CONFIG_HOOK_BRIGHTNESS_MAX,
201 CONFIG_HOOK_SHARE,
202 vrc4172pwm_event, sc);
203
204 vrc4172pwm_init_brightness(sc);
205 this_pwm = sc;
206 }
207
208 /*
209 * get platform related brightness paramerters
210 */
211 struct vrc4172pwm_param *
212 vrc4172pwm_getparam()
213 {
214 struct platid_data *p;
215
216 if ((p = platid_search(&platid, vrc4172pwm_platid_param_table)))
217 return p->data;
218 return NULL;
219 }
220
221 /*
222 *
223 * Initialize PWM brightness parameters
224 *
225 */
226 void
227 vrc4172pwm_init_brightness(sc)
228 struct vrc4172pwm_softc *sc;
229 {
230 sc->sc_param = vrc4172pwm_getparam();
231 sc->sc_raw_freq = vrc4172pwm_read(sc, VRC2_PWM_LCDFREQ);
232 sc->sc_raw_duty = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTY);
233 sc->sc_brightness = vrc4172pwm_rawduty2brightness(sc);
234 }
235 /*
236 * backlight on/off
237 */
238 void
239 vrc4172pwm_light(sc, on)
240 struct vrc4172pwm_softc *sc;
241 int on;
242 {
243 if (on)
244 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTYEN, VRC2_PWM_LCD_EN);
245 else
246 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTYEN, VRC2_PWM_LCD_DIS);
247 }
248
249 /*
250 * get backlight on/off
251 */
252 inline int
253 vrc4172pwm_get_light(sc)
254 struct vrc4172pwm_softc *sc;
255 {
256 return vrc4172pwm_read(sc, VRC2_PWM_LCDDUTYEN);
257 }
258
259 /*
260 * set brightness
261 */
262 void
263 vrc4172pwm_set_brightness(sc, val)
264 struct vrc4172pwm_softc *sc;
265 int val;
266 {
267 int raw;
268
269 if (sc->sc_param == NULL)
270 return;
271 if (val > VRC2_PWM_MAX_BRIGHTNESS)
272 val = VRC2_PWM_MAX_BRIGHTNESS;
273 if (val > sc->sc_param->n_brightness)
274 val = sc->sc_param->n_brightness;
275 sc->sc_brightness = val;
276 raw = vrc4172pwm_brightness2rawduty(sc);
277 vrc4172pwm_write(sc, VRC2_PWM_LCDDUTY, raw);
278 }
279
280 /*
281 * get brightness
282 */
283 int
284 vrc4172pwm_get_brightness(sc)
285 struct vrc4172pwm_softc *sc;
286 {
287 if (sc->sc_param == NULL)
288 return VRC2_PWM_MAX_BRIGHTNESS;
289 return sc->sc_brightness;
290 }
291
292 /*
293 * PWM duty to brightness
294 */
295 int
296 vrc4172pwm_rawduty2brightness(sc)
297 struct vrc4172pwm_softc *sc;
298 {
299 int i;
300
301 if (sc->sc_param == NULL)
302 return VRC2_PWM_LCDDUTY_MASK;
303 for (i = 0; i < sc->sc_param->n_brightness; i++) {
304 if (sc->sc_raw_duty <= sc->sc_param->values[i])
305 break;
306 }
307 if (i >= sc->sc_param->n_brightness-1)
308 return sc->sc_param->n_brightness-1;
309 else
310 return i;
311
312 }
313
314 /*
315 * brightness to raw duty
316 */
317 int
318 vrc4172pwm_brightness2rawduty(sc)
319 struct vrc4172pwm_softc *sc;
320 {
321 if (sc->sc_param == NULL)
322 return VRC2_PWM_MAX_BRIGHTNESS;
323 return sc->sc_param->values[sc->sc_brightness];
324 }
325
326
327 /*
328 * PWM config hook events
329 *
330 */
331 int
332 vrc4172pwm_event(ctx, type, id, msg)
333 void *ctx;
334 int type;
335 long id;
336 void *msg;
337 {
338 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)ctx;
339 int why =(int)msg;
340
341 if (type == CONFIG_HOOK_POWERCONTROL
342 && id == CONFIG_HOOK_POWERCONTROL_LCDLIGHT) {
343 vrc4172pwm_light(sc, why);
344 } else if (type == CONFIG_HOOK_GET
345 && id == CONFIG_HOOK_POWER_LCDLIGHT) {
346 *(int *)msg = vrc4172pwm_get_light(sc);
347 } else if (type == CONFIG_HOOK_GET
348 && id == CONFIG_HOOK_BRIGHTNESS) {
349 *(int *)msg = vrc4172pwm_get_brightness(sc);
350 } else if (type == CONFIG_HOOK_GET
351 && id == CONFIG_HOOK_BRIGHTNESS_MAX) {
352 if (sc->sc_param == NULL)
353 *(int *)msg = VRC2_PWM_MAX_BRIGHTNESS;
354 else
355 *(int *)msg = sc->sc_param->n_brightness-1;
356 } else if (type == CONFIG_HOOK_SET
357 && id == CONFIG_HOOK_BRIGHTNESS) {
358 vrc4172pwm_set_brightness(sc, *(int *)msg);
359 } else
360 return 1;
361
362 return (0);
363 }
364
365
366 /*
367 * PWM config hook events
368 *
369 */
370 int
371 vrc4172pwm_pmevent(ctx, type, id, msg)
372 void *ctx;
373 int type;
374 long id;
375 void *msg;
376 {
377 struct vrc4172pwm_softc *sc = (struct vrc4172pwm_softc *)ctx;
378 int why =(int)msg;
379
380 if (type != CONFIG_HOOK_PMEVENT)
381 return 1;
382
383 switch (why) {
384 case PWR_STANDBY:
385 case PWR_SUSPEND:
386 vrc4172pwm_light(sc, 0);
387 break;
388 case PWR_RESUME:
389 vrc4172pwm_light(sc, 1);
390 break;
391 default:
392 return 1;
393 }
394
395 return (0);
396 }
397
398 /*
399 * dump pwm registers
400 */
401 void
402 vrc4172pwm_dumpreg(sc)
403 struct vrc4172pwm_softc *sc;
404 {
405 int en, freq, duty;
406
407 en = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTYEN);
408 freq = vrc4172pwm_read(sc, VRC2_PWM_LCDFREQ);
409 duty = vrc4172pwm_read(sc, VRC2_PWM_LCDDUTY);
410
411 printf("vrc4172pwm: lightenable = %d, freq = 0x%x, duty = 0x%x\n",
412 en, freq, duty);
413 }
414
415 /* end */
416