1 /* $NetBSD: psh3lcd.c,v 1.4 2008/03/31 15:49:29 kiyohara Exp $ */
3 * Copyright (c) 2005 KIYOHARA Takashi
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 ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/device.h>
34 #include <sys/errno.h>
35 #include <sys/kernel.h>
36 #include <sys/systm.h>
37 #include <sys/callout.h>
39 #include <machine/platid.h>
40 #include <machine/platid_mask.h>
42 #include <machine/config_hook.h>
44 #include <sh3/pfcreg.h>
45 #include <hpcsh/dev/hd64461/hd64461var.h>
46 #include <hpcsh/dev/hd64461/hd64461reg.h>
47 #include <hpcsh/dev/hd64461/hd64461gpioreg.h>
51 * LCD contrast INC#: controlled by pin 0 in HD64461 GPIO port A.
52 * LCD contrast CS#: controlled by pin 1 in HD64461 GPIO port A.
53 * LCD contrast U/D#: controlled by pin 0 in SH7709 GPIO port D.
57 #define PSH3LCD_CONTRAST_INC 0x01
58 #define PSH3LCD_CONTRAST_CS 0x02
59 #define PSH3LCD_CONTRAST_UD 0x01
62 * LCD brightness: controled by HG71C105FE at AREA2.
63 * XXXX: That is custom IC. We don't know spec. X-<
65 #define PSH3LCD_BRIGHTNESS_REG0 0xaa000072
66 #define PSH3LCD_BRIGHTNESS_REG1 0xaa000150
67 #define PSH3LCD_BRIGHTNESS_REG2 0xaa000152
69 /* brightness control data */
70 static const struct psh3lcd_x0_bcd
{ /* 50PA, 30PA */
74 } psh3lcd_x0_bcd
[] = {
82 static const struct psh3lcd_xx0_bcd
{ /* 200JC */
85 } psh3lcd_xx0_bcd
[] = {
98 #define PSH3LCD_XX0_BRIGHTNESS_MAX 8
99 #define PSH3LCD_X0_BRIGHTNESS_MAX 4
101 #define PSH3LCD_CONTRAST_MAX 2 /* XXX */
102 #define PSH3LCD_CONTRAST 1
103 #define PSH3LCD_CONTRAST_UP 2
104 #define PSH3LCD_CONTRAST_DOWN 0
106 #define BCD_NO_MATCH (-1)
109 struct psh3lcd_softc
{
112 int sc_brightness_max
;
113 void (*sc_set_brightness
)(int);
116 static int psh3lcd_match(device_t
, struct cfdata
*, void *);
117 static void psh3lcd_attach(device_t
, device_t
, void *);
119 CFATTACH_DECL_NEW(psh3lcd
, sizeof(struct psh3lcd_softc
),
120 psh3lcd_match
, psh3lcd_attach
, NULL
, NULL
);
123 static inline int psh3lcd_x0_bcd_get(void);
124 static inline int psh3lcd_xx0_bcd_get(void);
125 static void psh3lcd_x0_set_brightness(int);
126 static void psh3lcd_xx0_set_brightness(int);
127 static void psh3lcd_set_contrast(int);
128 static int psh3lcd_param(void *, int, long, void *);
129 static int psh3lcd_power(void *, int, long, void *);
136 uint8_t bcr0
, bcr1
, bcr2
;
138 bcr0
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG0
);
139 bcr1
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG1
);
140 bcr2
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG2
);
142 for (i
= 0; psh3lcd_x0_bcd
[i
].reg0
!= 0; i
++)
143 if (bcr0
== psh3lcd_x0_bcd
[i
].reg0
&&
144 bcr1
== psh3lcd_x0_bcd
[i
].reg1
&&
145 bcr2
== psh3lcd_x0_bcd
[i
].reg2
)
147 if (psh3lcd_x0_bcd
[i
].reg0
== 0)
153 psh3lcd_xx0_bcd_get()
158 bcr1
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG1
);
159 bcr2
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG2
);
161 for (i
= 0; psh3lcd_xx0_bcd
[i
].reg1
!= 0; i
++)
162 if (bcr1
== psh3lcd_xx0_bcd
[i
].reg1
&&
163 bcr2
== psh3lcd_xx0_bcd
[i
].reg2
)
165 if (psh3lcd_xx0_bcd
[i
].reg1
== 0)
171 psh3lcd_xx0_set_brightness(int index
)
174 _reg_write_1(PSH3LCD_BRIGHTNESS_REG1
, psh3lcd_xx0_bcd
[index
].reg1
);
175 _reg_write_1(PSH3LCD_BRIGHTNESS_REG2
, psh3lcd_xx0_bcd
[index
].reg2
);
179 psh3lcd_x0_set_brightness(int index
)
182 _reg_write_1(PSH3LCD_BRIGHTNESS_REG0
, psh3lcd_x0_bcd
[index
].reg0
);
183 _reg_write_1(PSH3LCD_BRIGHTNESS_REG1
, psh3lcd_x0_bcd
[index
].reg1
);
184 _reg_write_1(PSH3LCD_BRIGHTNESS_REG2
, psh3lcd_x0_bcd
[index
].reg2
);
188 * contrast control function. controlled by IC (X9313W).
191 psh3lcd_set_contrast(int value
)
197 gpadr
= hd64461_reg_read_2(HD64461_GPADR_REG16
);
198 gpadr
&= ~PSH3LCD_CONTRAST_CS
;
199 hd64461_reg_write_2(HD64461_GPADR_REG16
, gpadr
);
203 pddr
= _reg_read_1(SH7709_PDDR
);
204 if (value
== PSH3LCD_CONTRAST_UP
)
205 pddr
|= PSH3LCD_CONTRAST_UD
;
206 else if (value
== PSH3LCD_CONTRAST_DOWN
)
207 pddr
&= ~PSH3LCD_CONTRAST_UD
;
208 _reg_write_1(SH7709_PDDR
, pddr
);
212 hd64461_reg_write_2(HD64461_GPADR_REG16
, gpadr
& ~PSH3LCD_CONTRAST_INC
);
214 hd64461_reg_write_2(HD64461_GPADR_REG16
, gpadr
);
218 gpadr
|= PSH3LCD_CONTRAST_CS
;
219 hd64461_reg_write_2(HD64461_GPADR_REG16
, gpadr
);
225 psh3lcd_match(device_t parent __unused
, struct cfdata
*cfp
, void *aux __unused
)
229 if (!platid_match(&platid
, &platid_mask_MACH_HITACHI_PERSONA
))
232 if (strcmp(cfp
->cf_name
, "psh3lcd") != 0)
235 bcr0
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG0
);
237 if (psh3lcd_xx0_bcd_get() == BCD_NO_MATCH
)
240 if (psh3lcd_x0_bcd_get() == BCD_NO_MATCH
)
249 psh3lcd_attach(device_t parent __unused
, device_t self
, void *aux __unused
)
251 struct psh3lcd_softc
*sc
= device_private(self
);
252 uint8_t bcr0
, bcr1
, bcr2
;
256 bcr0
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG0
);
257 bcr1
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG1
);
258 bcr2
= _reg_read_1(PSH3LCD_BRIGHTNESS_REG2
);
260 sc
->sc_set_brightness
= psh3lcd_xx0_set_brightness
;
261 sc
->sc_brightness
= psh3lcd_xx0_bcd_get();
262 sc
->sc_brightness_max
= PSH3LCD_XX0_BRIGHTNESS_MAX
;
264 sc
->sc_set_brightness
= psh3lcd_x0_set_brightness
;
265 sc
->sc_brightness
= psh3lcd_x0_bcd_get();
266 sc
->sc_brightness_max
= PSH3LCD_X0_BRIGHTNESS_MAX
;
269 aprint_normal(": brightness %d\n", sc
->sc_brightness
);
271 /* LCD contrast hooks */
272 config_hook(CONFIG_HOOK_GET
,
273 CONFIG_HOOK_CONTRAST_MAX
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
274 config_hook(CONFIG_HOOK_GET
,
275 CONFIG_HOOK_CONTRAST
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
276 config_hook(CONFIG_HOOK_SET
,
277 CONFIG_HOOK_CONTRAST
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
279 /* LCD brightness hooks */
280 config_hook(CONFIG_HOOK_GET
,
281 CONFIG_HOOK_BRIGHTNESS_MAX
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
282 config_hook(CONFIG_HOOK_GET
,
283 CONFIG_HOOK_BRIGHTNESS
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
284 config_hook(CONFIG_HOOK_SET
,
285 CONFIG_HOOK_BRIGHTNESS
, CONFIG_HOOK_SHARE
, psh3lcd_param
, sc
);
287 /* LCD on/off hook */
288 config_hook(CONFIG_HOOK_POWERCONTROL
,
289 CONFIG_HOOK_POWERCONTROL_LCD
, CONFIG_HOOK_SHARE
, psh3lcd_power
, sc
);
291 /* XXX: TODO: don't rely on CONFIG_HOOK_POWERCONTROL_LCD */
292 if (!pmf_device_register(self
, NULL
, NULL
))
293 aprint_error_dev(self
, "unable to establish power handler\n");
298 psh3lcd_param(void *ctx
, int type
, long id
, void *msg
)
300 struct psh3lcd_softc
*sc
= ctx
;
304 case CONFIG_HOOK_GET
:
306 case CONFIG_HOOK_CONTRAST
:
307 *(int *)msg
= PSH3LCD_CONTRAST
;
310 case CONFIG_HOOK_CONTRAST_MAX
:
311 *(int *)msg
= PSH3LCD_CONTRAST_MAX
;
314 case CONFIG_HOOK_BRIGHTNESS
:
315 *(int *)msg
= sc
->sc_brightness
;
318 case CONFIG_HOOK_BRIGHTNESS_MAX
:
319 *(int *)msg
= sc
->sc_brightness_max
;
324 case CONFIG_HOOK_SET
:
328 case CONFIG_HOOK_CONTRAST
:
329 if (value
!= PSH3LCD_CONTRAST_UP
&&
330 value
!= PSH3LCD_CONTRAST_DOWN
)
332 psh3lcd_set_contrast(value
);
335 case CONFIG_HOOK_BRIGHTNESS
:
338 if (value
> sc
->sc_brightness_max
)
339 value
= sc
->sc_brightness_max
;
340 sc
->sc_brightness
= value
;
341 sc
->sc_set_brightness(sc
->sc_brightness
);
352 psh3lcd_power(void *ctx
, int type
, long id
, void *msg
)
354 struct psh3lcd_softc
*sc
= ctx
;
357 if (type
!= CONFIG_HOOK_POWERCONTROL
||
358 id
!= CONFIG_HOOK_POWERCONTROL_LCD
)
363 sc
->sc_set_brightness(sc
->sc_brightness
);
365 sc
->sc_set_brightness(sc
->sc_brightness_max
+ 1);