1 /* $NetBSD: vrc4172pwm.c,v 1.17.6.3 2004/09/21 13:16:13 skrll Exp $ */
4 * Copyright (c) 2000,2001 SATO Kazumi. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: vrc4172pwm.c,v 1.17.6.3 2004/09/21 13:16:13 skrll Exp $");
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/reboot.h>
36 #include <machine/bus.h>
37 #include <machine/config_hook.h>
38 #include <machine/platid.h>
39 #include <machine/platid_mask.h>
41 #include <hpcmips/vr/vr.h>
42 #include <hpcmips/vr/vripif.h>
43 #include <hpcmips/vr/vrc4172pwmvar.h>
44 #include <hpcmips/vr/vrc4172pwmreg.h>
49 #ifndef VRC2PWMDEBUG_CONF
50 #define VRC2PWMDEBUG_CONF 0
51 #endif /* VRC2PWMDEBUG_CONF */
52 int vrc4172pwmdebug
= VRC2PWMDEBUG_CONF
;
53 #define DPRINTF(arg) if (vrc4172pwmdebug) printf arg;
54 #define VPRINTF(arg) if (bootverbose||vrc4172pwmdebug) printf arg;
55 #define VDUMPREG(arg) if (bootverbose||vrc4172pwmdebug) vrc4172pwm_dumpreg(arg);
56 #else /* VRC2PWMDEBUG */
58 #define VPRINTF(arg) if (bootverbose) printf arg;
59 #define VDUMPREG(arg) if (bootverbose) vrc4172pwm_dumpreg(arg);
60 #endif /* VRC2PWMDEBUG */
62 static int vrc4172pwmprobe(struct device
*, struct cfdata
*, void *);
63 static void vrc4172pwmattach(struct device
*, struct device
*, void *);
65 static void vrc4172pwm_write(struct vrc4172pwm_softc
*, int, unsigned short);
66 static unsigned short vrc4172pwm_read(struct vrc4172pwm_softc
*, int);
68 static int vrc4172pwm_event(void *, int, long, void *);
69 static int vrc4172pwm_pmevent(void *, int, long, void *);
71 static void vrc4172pwm_dumpreg(struct vrc4172pwm_softc
*);
72 static void vrc4172pwm_init_brightness(struct vrc4172pwm_softc
*);
73 void vrc4172pwm_light(struct vrc4172pwm_softc
*, int);
74 int vrc4172pwm_get_light(struct vrc4172pwm_softc
*);
75 int vrc4172pwm_get_brightness(struct vrc4172pwm_softc
*);
76 void vrc4172pwm_set_brightness(struct vrc4172pwm_softc
*, int);
77 int vrc4172pwm_rawduty2brightness(struct vrc4172pwm_softc
*);
78 int vrc4172pwm_brightness2rawduty(struct vrc4172pwm_softc
*);
79 struct vrc4172pwm_param
* vrc4172pwm_getparam(void);
80 void vrc4172pwm_dumpreg(struct vrc4172pwm_softc
*);
82 CFATTACH_DECL(vrc4172pwm
, sizeof(struct vrc4172pwm_softc
),
83 vrc4172pwmprobe
, vrc4172pwmattach
, NULL
, NULL
);
86 * platform related parameters
88 struct vrc4172pwm_param vrc4172pwm_mcr520_param
= {
91 { 0x16, 0x1f, 0x24, 0x2a, 0x2f, 0x34, 0x3a, 0x3f }
94 struct vrc4172pwm_param vrc4172pwm_mcr530_param
= {
97 { 0x16, 0x1b, 0x20, 0x25, 0x2a, 0x30, 0x37, 0x3f }
100 struct vrc4172pwm_param vrc4172pwm_mcr700_param
= {
101 1, /* probe broken */
103 { 0x12, 0x15, 0x18, 0x1d, 0x24, 0x2d, 0x38, 0x3f }
106 struct vrc4172pwm_param vrc4172pwm_sigmarion_param
= {
109 { 0xe, 0x13, 0x18, 0x1c, 0x23, 0x29, 0x32, 0x3f }
113 struct platid_data vrc4172pwm_platid_param_table
[] = {
114 { &platid_mask_MACH_NEC_MCR_430
, &vrc4172pwm_mcr530_param
},
115 { &platid_mask_MACH_NEC_MCR_510
, &vrc4172pwm_mcr520_param
},
116 { &platid_mask_MACH_NEC_MCR_520
, &vrc4172pwm_mcr520_param
},
117 { &platid_mask_MACH_NEC_MCR_520A
, &vrc4172pwm_mcr520_param
},
118 { &platid_mask_MACH_NEC_MCR_530
, &vrc4172pwm_mcr530_param
},
119 { &platid_mask_MACH_NEC_MCR_530A
, &vrc4172pwm_mcr530_param
},
120 { &platid_mask_MACH_NEC_MCR_SIGMARION
, &vrc4172pwm_sigmarion_param
},
121 { &platid_mask_MACH_NEC_MCR_700
, &vrc4172pwm_mcr700_param
},
122 { &platid_mask_MACH_NEC_MCR_700A
, &vrc4172pwm_mcr700_param
},
123 { &platid_mask_MACH_NEC_MCR_730
, &vrc4172pwm_mcr700_param
},
124 { &platid_mask_MACH_NEC_MCR_730A
, &vrc4172pwm_mcr700_param
},
128 struct vrc4172pwm_softc
*this_pwm
;
131 vrc4172pwm_write(struct vrc4172pwm_softc
*sc
, int port
, unsigned short val
)
134 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, port
, val
);
137 static inline unsigned short
138 vrc4172pwm_read(struct vrc4172pwm_softc
*sc
, int port
)
141 return (bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, port
));
145 vrc4172pwmprobe(struct device
*parent
, struct cfdata
*cf
, void *aux
)
148 struct vrip_attach_args
*va
= aux
;
149 bus_space_handle_t ioh
;
150 #ifdef VRC4172PWM_BROKEN_PROBE
152 #else /* VRC4172PWM_BROKEN_PROBE */
154 #endif /* VRC4172PWM_BROKEN_PROBE */
157 struct vrc4172pwm_param
*param
;
160 if (va
->va_addr
== VRIPIFCF_ADDR_DEFAULT
)
163 if (cf
->cf_loc
[VRIPIFCF_PLATFORM
] == 0)
165 if (cf
->cf_loc
[VRIPIFCF_PLATFORM
] != -1) { /* if specify */
166 mask
= PLATID_DEREF(cf
->cf_loc
[VRIPIFCF_PLATFORM
]);
167 VPRINTF(("vrc4172pwmprobe: check platid\n"));
168 if (platid_match(&platid
, &mask
) == 0)
170 param
= vrc4172pwm_getparam();
171 if (param
!= NULL
&& param
->brokenprobe
)
175 if (bus_space_map(va
->va_iot
, va
->va_addr
, va
->va_size
, 0,
179 data
= bus_space_read_2(va
->va_iot
, ioh
, VRC2_PWM_LCDDUTYEN
);
180 bus_space_write_2(va
->va_iot
, ioh
, VRC2_PWM_LCDDUTYEN
, 0xff);
181 if ((data2
= bus_space_read_2(va
->va_iot
, ioh
,
182 VRC2_PWM_LCDDUTYEN
)) == VRC2_PWM_LCDEN_MASK
) {
183 VPRINTF(("vrc4172pwmprobe:"
184 " VRC2_PWM_LCDDUTYEN found\n"));
187 VPRINTF(("vrc4172pwmprobe: VRC2_PWM_LCDDUTYEN"
188 " not found org=%x, data=%x!=%x\n",
189 data
, data2
, VRC2_PWM_LCDEN_MASK
));
191 bus_space_write_2(va
->va_iot
, ioh
, VRC2_PWM_LCDDUTYEN
, data
);
192 bus_space_unmap(va
->va_iot
, ioh
, va
->va_size
);
195 VPRINTF(("vrc4172pwmprobe: return %d\n", ret
));
201 vrc4172pwmattach(struct device
*parent
, struct device
*self
, void *aux
)
203 struct vrc4172pwm_softc
*sc
= (struct vrc4172pwm_softc
*)self
;
204 struct vrip_attach_args
*va
= aux
;
206 bus_space_tag_t iot
= va
->va_iot
;
207 bus_space_handle_t ioh
;
209 if (bus_space_map(iot
, va
->va_addr
, 1, 0, &ioh
)) {
210 printf(": can't map bus space\n");
221 sc
->sc_pmhook
= config_hook(CONFIG_HOOK_PMEVENT
,
222 CONFIG_HOOK_PMEVENT_HARDPOWER
, CONFIG_HOOK_SHARE
,
223 vrc4172pwm_pmevent
, sc
);
224 sc
->sc_lcdhook
= config_hook(CONFIG_HOOK_POWERCONTROL
,
225 CONFIG_HOOK_POWERCONTROL_LCDLIGHT
, CONFIG_HOOK_SHARE
,
226 vrc4172pwm_event
, sc
);
227 sc
->sc_getlcdhook
= config_hook(CONFIG_HOOK_GET
,
228 CONFIG_HOOK_POWER_LCDLIGHT
, CONFIG_HOOK_SHARE
,
229 vrc4172pwm_event
, sc
);
230 sc
->sc_sethook
= config_hook(CONFIG_HOOK_SET
,
231 CONFIG_HOOK_BRIGHTNESS
, CONFIG_HOOK_SHARE
,
232 vrc4172pwm_event
, sc
);
233 sc
->sc_gethook
= config_hook(CONFIG_HOOK_GET
,
234 CONFIG_HOOK_BRIGHTNESS
, CONFIG_HOOK_SHARE
,
235 vrc4172pwm_event
, sc
);
236 sc
->sc_getmaxhook
= config_hook(CONFIG_HOOK_GET
,
237 CONFIG_HOOK_BRIGHTNESS_MAX
, CONFIG_HOOK_SHARE
,
238 vrc4172pwm_event
, sc
);
240 vrc4172pwm_init_brightness(sc
);
241 if (sc
->sc_param
== NULL
)
242 printf("vrc4172pwm: NO parameter found. DISABLE pwm control\n");
247 * get platform related brightness paramerters
249 struct vrc4172pwm_param
*
250 vrc4172pwm_getparam()
252 struct platid_data
*p
;
254 if ((p
= platid_search_data(&platid
, vrc4172pwm_platid_param_table
)))
262 * Initialize PWM brightness parameters
266 vrc4172pwm_init_brightness(struct vrc4172pwm_softc
*sc
)
268 sc
->sc_param
= vrc4172pwm_getparam();
269 sc
->sc_raw_freq
= vrc4172pwm_read(sc
, VRC2_PWM_LCDFREQ
);
270 sc
->sc_raw_duty
= vrc4172pwm_read(sc
, VRC2_PWM_LCDDUTY
);
271 sc
->sc_brightness
= vrc4172pwm_rawduty2brightness(sc
);
272 sc
->sc_light
= vrc4172pwm_get_light(sc
);
273 DPRINTF(("vrc4172pwm_init_brightness: param=0x%x, freq=0x%x,"
274 " duty=0x%x, blightness=%d light=%d\n", (int)sc
->sc_param
,
275 sc
->sc_raw_freq
, sc
->sc_raw_duty
, sc
->sc_brightness
,
282 vrc4172pwm_light(struct vrc4172pwm_softc
*sc
, int on
)
286 DPRINTF(("vrc4172pwm_light: %s\n", on
?"ON":"OFF"));
288 vrc4172pwm_set_brightness(sc
, sc
->sc_brightness
);
289 vrc4172pwm_write(sc
, VRC2_PWM_LCDDUTYEN
, VRC2_PWM_LCD_EN
);
291 brightness
= sc
->sc_brightness
; /* save */
292 vrc4172pwm_set_brightness(sc
, 0);
293 /* need this, break sc->sc_brightness */
294 sc
->sc_brightness
= brightness
; /* resume */
295 vrc4172pwm_write(sc
, VRC2_PWM_LCDDUTYEN
, VRC2_PWM_LCD_DIS
);
301 * get backlight on/off
304 vrc4172pwm_get_light(struct vrc4172pwm_softc
*sc
)
307 return (VRC2_PWM_LCDEN_MASK
&vrc4172pwm_read(sc
, VRC2_PWM_LCDDUTYEN
));
314 vrc4172pwm_set_brightness(struct vrc4172pwm_softc
*sc
, int val
)
318 if (sc
->sc_param
== NULL
)
322 if (val
> VRC2_PWM_MAX_BRIGHTNESS
)
323 val
= VRC2_PWM_MAX_BRIGHTNESS
;
324 if (val
> sc
->sc_param
->n_brightness
)
325 val
= sc
->sc_param
->n_brightness
;
326 sc
->sc_brightness
= val
;
327 raw
= vrc4172pwm_brightness2rawduty(sc
);
328 vrc4172pwm_write(sc
, VRC2_PWM_LCDDUTY
, raw
);
329 DPRINTF(("vrc4172pwm_set_brightness: val=%d raw=0x%x\n", val
, raw
));
336 vrc4172pwm_get_brightness(struct vrc4172pwm_softc
*sc
)
339 if (sc
->sc_param
== NULL
)
340 return (VRC2_PWM_MAX_BRIGHTNESS
);
342 return (sc
->sc_brightness
);
346 * PWM duty to brightness
349 vrc4172pwm_rawduty2brightness(struct vrc4172pwm_softc
*sc
)
353 if (sc
->sc_param
== NULL
)
354 return (VRC2_PWM_MAX_BRIGHTNESS
);
355 for (i
= 0; i
< sc
->sc_param
->n_brightness
; i
++) {
356 if (sc
->sc_raw_duty
<= sc
->sc_param
->bvalues
[i
])
359 if (i
>= sc
->sc_param
->n_brightness
-1)
360 return (sc
->sc_param
->n_brightness
-1);
367 * brightness to raw duty
370 vrc4172pwm_brightness2rawduty(struct vrc4172pwm_softc
*sc
)
373 if (sc
->sc_param
== NULL
)
374 return (VRC2_PWM_LCDDUTY_MASK
);
376 return (sc
->sc_param
->bvalues
[sc
->sc_brightness
]);
381 * PWM config hook events
385 vrc4172pwm_event(void *ctx
, int type
, long id
, void *msg
)
387 struct vrc4172pwm_softc
*sc
= (struct vrc4172pwm_softc
*)ctx
;
390 if (type
== CONFIG_HOOK_POWERCONTROL
391 && id
== CONFIG_HOOK_POWERCONTROL_LCDLIGHT
) {
392 DPRINTF(("vrc4172pwm:POWERCONTROL_LCDLIGHT: %d\n", why
));
393 vrc4172pwm_light(sc
, why
);
394 } else if (type
== CONFIG_HOOK_GET
395 && id
== CONFIG_HOOK_POWER_LCDLIGHT
) {
396 *(int *)msg
= vrc4172pwm_get_light(sc
);
397 DPRINTF(("vrc4172pwm:GET LCDLIGHT: %d\n", *(int *)msg
));
398 } else if (type
== CONFIG_HOOK_GET
399 && id
== CONFIG_HOOK_BRIGHTNESS
) {
400 *(int *)msg
= vrc4172pwm_get_brightness(sc
);
401 DPRINTF(("vrc4172pwm:GET BRIGHTNESS: %d\n", *(int *)msg
));
402 } else if (type
== CONFIG_HOOK_GET
403 && id
== CONFIG_HOOK_BRIGHTNESS_MAX
) {
404 if (sc
->sc_param
== NULL
)
405 *(int *)msg
= VRC2_PWM_MAX_BRIGHTNESS
;
407 *(int *)msg
= sc
->sc_param
->n_brightness
-1;
408 DPRINTF(("vrc4172pwm:GET MAX BRIGHTNESS: %d\n", *(int *)msg
));
409 } else if (type
== CONFIG_HOOK_SET
410 && id
== CONFIG_HOOK_BRIGHTNESS
) {
411 DPRINTF(("vrc4172pwm:SET BRIGHTNESS: %d\n", *(int *)msg
));
412 vrc4172pwm_set_brightness(sc
, *(int *)msg
);
414 DPRINTF(("vrc4172pwm:unknown event: type %d id %ld\n",
423 * PWM config hook events
427 vrc4172pwm_pmevent(void *ctx
, int type
, long id
, void *msg
)
429 struct vrc4172pwm_softc
*sc
= (struct vrc4172pwm_softc
*)ctx
;
432 if (type
!= CONFIG_HOOK_PMEVENT
)
438 sc
->sc_light_save
= sc
->sc_light
;
439 vrc4172pwm_light(sc
, 0);
442 vrc4172pwm_light(sc
, sc
->sc_light_save
);
455 vrc4172pwm_dumpreg(struct vrc4172pwm_softc
*sc
)
459 en
= vrc4172pwm_read(sc
, VRC2_PWM_LCDDUTYEN
);
460 freq
= vrc4172pwm_read(sc
, VRC2_PWM_LCDFREQ
);
461 duty
= vrc4172pwm_read(sc
, VRC2_PWM_LCDDUTY
);
463 printf("vrc4172pwm: dumpreg: lightenable = %d,"
464 " freq = 0x%x, duty = 0x%x\n", en
, freq
, duty
);