xref: /netbsd/sys/arch/hpcsh/dev/j6x0lcd.c (revision 6b95067c)
1*6b95067cSuwe /*	$NetBSD: j6x0lcd.c,v 1.7 2005/08/03 22:25:17 uwe Exp $ */
2ef7c8200Suwe 
3ef7c8200Suwe /*
4*6b95067cSuwe  * Copyright (c) 2004, 2005 Valeriy E. Ushakov
5ef7c8200Suwe  * All rights reserved.
6ef7c8200Suwe  *
7ef7c8200Suwe  * Redistribution and use in source and binary forms, with or without
8ef7c8200Suwe  * modification, are permitted provided that the following conditions
9ef7c8200Suwe  * are met:
10ef7c8200Suwe  * 1. Redistributions of source code must retain the above copyright
11ef7c8200Suwe  *    notice, this list of conditions and the following disclaimer.
12ef7c8200Suwe  * 2. Redistributions in binary form must reproduce the above copyright
13ef7c8200Suwe  *    notice, this list of conditions and the following disclaimer in the
14ef7c8200Suwe  *    documentation and/or other materials provided with the distribution.
15ef7c8200Suwe  * 3. The name of the author may not be used to endorse or promote products
16ef7c8200Suwe  *    derived from this software without specific prior written permission
17ef7c8200Suwe  *
18ef7c8200Suwe  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19ef7c8200Suwe  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20ef7c8200Suwe  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21ef7c8200Suwe  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22ef7c8200Suwe  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23ef7c8200Suwe  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24ef7c8200Suwe  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25ef7c8200Suwe  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26ef7c8200Suwe  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27ef7c8200Suwe  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28ef7c8200Suwe  */
29ef7c8200Suwe 
30ef7c8200Suwe #include <sys/cdefs.h>
31*6b95067cSuwe __KERNEL_RCSID(0, "$NetBSD: j6x0lcd.c,v 1.7 2005/08/03 22:25:17 uwe Exp $");
32ef7c8200Suwe 
33ef7c8200Suwe #include <sys/param.h>
34ef7c8200Suwe #include <sys/kernel.h>
35ef7c8200Suwe #include <sys/device.h>
36ef7c8200Suwe #include <sys/systm.h>
37ef7c8200Suwe #ifdef GPROF
38ef7c8200Suwe #include <sys/gmon.h>
39ef7c8200Suwe #endif
40ef7c8200Suwe 
41ef7c8200Suwe #include <machine/platid.h>
42ef7c8200Suwe #include <machine/platid_mask.h>
43ef7c8200Suwe 
44ef7c8200Suwe #include <machine/config_hook.h>
45ef7c8200Suwe 
46ef7c8200Suwe #include <sh3/dacreg.h>
47ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461var.h> /* XXX: for hd64461_reg_read_2 &c */
48ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461reg.h>
49ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461gpioreg.h>
50ef7c8200Suwe 
51*6b95067cSuwe #define arraysize(ary) (sizeof(ary) / sizeof(ary[0]))
52*6b95067cSuwe 
53ef7c8200Suwe 
54ef7c8200Suwe /*
55ef7c8200Suwe  * LCD power: controlled by pin 0 in HD64461 GPIO port B.
56ef7c8200Suwe  *   0 - power on
57ef7c8200Suwe  *   1 - power off
58ef7c8200Suwe  */
59*6b95067cSuwe #define HD64461_GPBDR_J6X0_LCD_OFF	0x01
60ef7c8200Suwe 
61*6b95067cSuwe #define HD64461_GPBCR_J6X0_LCD_OFF_MASK	0xfffc
62*6b95067cSuwe #define HD64461_GPBCR_J6X0_LCD_OFF_BITS	0x0001
63ef7c8200Suwe 
64ef7c8200Suwe 
65ef7c8200Suwe /*
66ef7c8200Suwe  * LCD brightness: controlled by DAC channel 0.  Larger channel values
67ef7c8200Suwe  * mean dimmer.  Values smaller (i.e. brighter) then 0x5e seems to
68ef7c8200Suwe  * result in no visible changes.
69ef7c8200Suwe  */
70ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_DA_MAX	0x5e
71ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_DA_MIN	0xff
72ef7c8200Suwe 
73ef7c8200Suwe #define J6X0LCD_DA_TO_BRIGHTNESS(da) \
74ef7c8200Suwe 	(J6X0LCD_BRIGHTNESS_DA_MIN - (da))
75ef7c8200Suwe 
76ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_TO_DA(br) \
77ef7c8200Suwe 	(J6X0LCD_BRIGHTNESS_DA_MIN - (br))
78ef7c8200Suwe 
79ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_MAX \
80ef7c8200Suwe 	J6X0LCD_DA_TO_BRIGHTNESS(J6X0LCD_BRIGHTNESS_DA_MAX)
81ef7c8200Suwe 
82ef7c8200Suwe /* convenience macro to accesses DAC registers */
83ef7c8200Suwe #define DAC_(x)    (*((volatile uint8_t *)SH7709_DA ## x))
84ef7c8200Suwe 
85ef7c8200Suwe 
86ef7c8200Suwe /*
87*6b95067cSuwe  * LCD contrast in 680 is controlled by pins 6..3 of HD64461 GPIO
88*6b95067cSuwe  * port B.  6th pin is the least significant bit, 3rd pin is the most
89*6b95067cSuwe  * significant.  The bits are inverted: 0 = .1111...; 1 = .0111...;
90*6b95067cSuwe  * etc.  Larger values mean "blacker".
91ef7c8200Suwe  *
92*6b95067cSuwe  * The contrast value is programmed by setting bits in the data
93*6b95067cSuwe  * register to all ones, and changing the mode of the pins in the
94*6b95067cSuwe  * control register, setting logical "ones" to GPIO output mode (1),
95*6b95067cSuwe  * and switching "zeroes" to input mode (3).
96ef7c8200Suwe  */
97*6b95067cSuwe #define HD64461_GPBDR_J680_CONTRAST_BITS	0x78	/* set */
98*6b95067cSuwe #define HD64461_GPBCR_J680_CONTRAST_MASK	0xc03f
99ef7c8200Suwe 
100*6b95067cSuwe static const uint8_t j6x0lcd_contrast680_pins[] = { 6, 5, 4, 3 };
101ef7c8200Suwe 
102*6b95067cSuwe static const uint16_t j6x0lcd_contrast680_control_bits[] = {
103ef7c8200Suwe 	0x1540, 0x3540, 0x1d40, 0x3d40, 0x1740, 0x3740, 0x1f40, 0x3f40,
104ef7c8200Suwe 	0x15c0, 0x35c0, 0x1dc0, 0x3dc0, 0x17c0, 0x37c0, 0x1fc0, 0x3fc0
105ef7c8200Suwe };
106ef7c8200Suwe 
107ef7c8200Suwe 
108*6b95067cSuwe /*
109*6b95067cSuwe  * LCD contrast in 620lx is controlled by pins 7,6,3,4,5 of HD64461
110*6b95067cSuwe  * GPIO port B (in the order from the least significant to the most
111*6b95067cSuwe  * significant).  The bits are inverted: 0 = 11111...; 5 = 01110...;
112*6b95067cSuwe  * etc.  Larger values mean "whiter".
113*6b95067cSuwe  *
114*6b95067cSuwe  * The contrast value is programmed by setting bits in the data
115*6b95067cSuwe  * register to all zeroes, and changing the mode of the pins in the
116*6b95067cSuwe  * control register, setting logical "ones" to GPIO output mode (1),
117*6b95067cSuwe  * and switching "zeroes" to input mode (3).
118*6b95067cSuwe  */
119*6b95067cSuwe #define HD64461_GPBDR_J620LX_CONTRAST_BITS	0xf8	/* clear */
120*6b95067cSuwe #define HD64461_GPBCR_J620LX_CONTRAST_MASK	0x003f
121*6b95067cSuwe 
122*6b95067cSuwe static const uint8_t j6x0lcd_contrast620lx_pins[] = { 7, 6, 3, 4, 5 };
123*6b95067cSuwe 
124*6b95067cSuwe static const uint16_t j6x0lcd_contrast620lx_control_bits[] = {
125*6b95067cSuwe 	0xffc0, 0x7fc0, 0xdfc0, 0x5fc0, 0xff40, 0x7f40, 0xdf40, 0x5f40,
126*6b95067cSuwe 	0xfdc0, 0x7dc0, 0xddc0, 0x5dc0, 0xfd40, 0x7d40, 0xdd40, 0x5d40,
127*6b95067cSuwe 	0xf7c0, 0x77c0, 0xd7c0, 0x57c0, 0xf740, 0x7740, 0xd740, 0x5740,
128*6b95067cSuwe 	0xf5c0, 0x75c0, 0xd5c0, 0x55c0, 0xf540, 0x7540, 0xd540, 0x5540
129*6b95067cSuwe };
130*6b95067cSuwe 
131*6b95067cSuwe 
132*6b95067cSuwe 
133ef7c8200Suwe struct j6x0lcd_softc {
134ef7c8200Suwe 	struct device sc_dev;
135ef7c8200Suwe 	int sc_brightness;
136ef7c8200Suwe 	int sc_contrast;
137*6b95067cSuwe 
138*6b95067cSuwe 	int sc_contrast_max;
139*6b95067cSuwe 	uint16_t sc_contrast_mask;
140*6b95067cSuwe 	const uint16_t *sc_contrast_control_bits;
141ef7c8200Suwe };
142ef7c8200Suwe 
143ef7c8200Suwe static int	j6x0lcd_match(struct device *, struct cfdata *, void *);
144ef7c8200Suwe static void	j6x0lcd_attach(struct device *, struct device *, void *);
145ef7c8200Suwe 
146ef7c8200Suwe CFATTACH_DECL(j6x0lcd, sizeof(struct j6x0lcd_softc),
147ef7c8200Suwe     j6x0lcd_match, j6x0lcd_attach, NULL, NULL);
148ef7c8200Suwe 
149ef7c8200Suwe 
150ef7c8200Suwe static int	j6x0lcd_param(void *, int, long, void *);
151ef7c8200Suwe static int	j6x0lcd_power(void *, int, long, void *);
152ef7c8200Suwe 
153*6b95067cSuwe static int	j6x0lcd_contrast_raw(uint16_t, int, const uint8_t *);
154*6b95067cSuwe static void	j6x0lcd_contrast_set(struct j6x0lcd_softc *, int);
155*6b95067cSuwe 
156*6b95067cSuwe 
157ef7c8200Suwe 
158ef7c8200Suwe static int
159ef7c8200Suwe j6x0lcd_match(struct device *parent, struct cfdata *cfp, void *aux)
160ef7c8200Suwe {
161ef7c8200Suwe 
162ef7c8200Suwe 	/*
163*6b95067cSuwe 	 * XXX: platid_mask_MACH_HP_LX also matches 360LX.  It's not
164*6b95067cSuwe 	 * confirmed whether touch panel in 360LX is connected this
165*6b95067cSuwe 	 * way.  We may need to regroup platid masks.
166ef7c8200Suwe 	 */
167*6b95067cSuwe 	if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)
168*6b95067cSuwe 	    && !platid_match(&platid, &platid_mask_MACH_HP_LX))
169ef7c8200Suwe 		return (0);
170ef7c8200Suwe 
171ef7c8200Suwe 	if (strcmp(cfp->cf_name, "j6x0lcd") != 0)
172ef7c8200Suwe 		return (0);
173ef7c8200Suwe 
174ef7c8200Suwe 	return (1);
175ef7c8200Suwe }
176ef7c8200Suwe 
177ef7c8200Suwe 
178ef7c8200Suwe static void
179ef7c8200Suwe j6x0lcd_attach(struct device *parent, struct device *self, void *aux)
180ef7c8200Suwe {
181ef7c8200Suwe 	struct j6x0lcd_softc *sc = (struct j6x0lcd_softc *)self;
182ef7c8200Suwe 	uint16_t bcr, bdr;
183ef7c8200Suwe 	uint8_t dcr, ddr;
184ef7c8200Suwe 
185ef7c8200Suwe 	/*
186ef7c8200Suwe 	 * Brightness is controlled by DAC channel 0.
187ef7c8200Suwe 	 */
188ef7c8200Suwe 	dcr = DAC_(CR);
189ef7c8200Suwe 	dcr &= ~SH7709_DACR_DAE; /* want to control each channel separately */
190ef7c8200Suwe 	dcr |= SH7709_DACR_DAOE0; /* enable channel 0 */
191ef7c8200Suwe 	DAC_(CR) = dcr;
192ef7c8200Suwe 
193ef7c8200Suwe 	ddr = DAC_(DR0);
194ef7c8200Suwe 	sc->sc_brightness = J6X0LCD_DA_TO_BRIGHTNESS(ddr);
195ef7c8200Suwe 
196ef7c8200Suwe 	/*
197ef7c8200Suwe 	 * Contrast and power are controlled by HD64461 GPIO port B.
198ef7c8200Suwe 	 */
199ef7c8200Suwe 	bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
200ef7c8200Suwe 	bdr = hd64461_reg_read_2(HD64461_GPBDR_REG16);
201ef7c8200Suwe 
202*6b95067cSuwe 	/*
203*6b95067cSuwe 	 * Make sure LCD is turned on.
204*6b95067cSuwe 	 */
205*6b95067cSuwe 	bcr &= HD64461_GPBCR_J6X0_LCD_OFF_MASK;
206*6b95067cSuwe 	bcr |= HD64461_GPBCR_J6X0_LCD_OFF_BITS; /* output mode */
207*6b95067cSuwe 
208*6b95067cSuwe 	bdr &= ~HD64461_GPBDR_J6X0_LCD_OFF;
209*6b95067cSuwe 
210*6b95067cSuwe 	/*
211*6b95067cSuwe 	 * 620LX and 680 have different contrast control.
212*6b95067cSuwe 	 */
213*6b95067cSuwe 	if (platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)) {
214*6b95067cSuwe 		bdr |= HD64461_GPBDR_J680_CONTRAST_BITS;
215*6b95067cSuwe 
216*6b95067cSuwe 		sc->sc_contrast_mask =
217*6b95067cSuwe 			HD64461_GPBCR_J680_CONTRAST_MASK;
218*6b95067cSuwe 		sc->sc_contrast_control_bits =
219*6b95067cSuwe 			j6x0lcd_contrast680_control_bits;
220*6b95067cSuwe 		sc->sc_contrast_max =
221*6b95067cSuwe 			arraysize(j6x0lcd_contrast680_control_bits) - 1;
222*6b95067cSuwe 
223*6b95067cSuwe 		sc->sc_contrast = sc->sc_contrast_max
224*6b95067cSuwe 			- j6x0lcd_contrast_raw(bcr,
225*6b95067cSuwe 				arraysize(j6x0lcd_contrast680_pins),
226*6b95067cSuwe 				j6x0lcd_contrast680_pins);
227*6b95067cSuwe 	} else {
228*6b95067cSuwe 		bdr &= ~HD64461_GPBDR_J620LX_CONTRAST_BITS;
229*6b95067cSuwe 
230*6b95067cSuwe 		sc->sc_contrast_mask =
231*6b95067cSuwe 			HD64461_GPBCR_J620LX_CONTRAST_MASK;
232*6b95067cSuwe 		sc->sc_contrast_control_bits =
233*6b95067cSuwe 			j6x0lcd_contrast620lx_control_bits;
234*6b95067cSuwe 		sc->sc_contrast_max =
235*6b95067cSuwe 			arraysize(j6x0lcd_contrast620lx_control_bits) - 1;
236*6b95067cSuwe 
237*6b95067cSuwe 		sc->sc_contrast =
238*6b95067cSuwe 			j6x0lcd_contrast_raw(bcr,
239*6b95067cSuwe 				arraysize(j6x0lcd_contrast620lx_pins),
240*6b95067cSuwe 				j6x0lcd_contrast620lx_pins);
241ef7c8200Suwe 	}
242ef7c8200Suwe 
243ef7c8200Suwe 	hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
244*6b95067cSuwe 	hd64461_reg_write_2(HD64461_GPBDR_REG16, bdr);
245ef7c8200Suwe 
246ef7c8200Suwe 	printf(": brightness %d, contrast %d\n",
247ef7c8200Suwe 	       sc->sc_brightness, sc->sc_contrast);
248ef7c8200Suwe 
249ef7c8200Suwe 
250ef7c8200Suwe 	/* LCD brightness hooks */
251ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX,
252ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
253ef7c8200Suwe 		    j6x0lcd_param, sc);
254ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS,
255ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
256ef7c8200Suwe 		    j6x0lcd_param, sc);
257ef7c8200Suwe 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS,
258ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
259ef7c8200Suwe 		    j6x0lcd_param, sc);
260ef7c8200Suwe 
261ef7c8200Suwe 	/* LCD contrast hooks */
262ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX,
263ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
264ef7c8200Suwe 		    j6x0lcd_param, sc);
265ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST,
266ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
267ef7c8200Suwe 		    j6x0lcd_param, sc);
268ef7c8200Suwe 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST,
269ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
270ef7c8200Suwe 		    j6x0lcd_param, sc);
271ef7c8200Suwe 
272ef7c8200Suwe 	/* LCD on/off hook */
273ef7c8200Suwe 	config_hook(CONFIG_HOOK_POWERCONTROL,
2749d8bb20eSuwe 		    CONFIG_HOOK_POWERCONTROL_LCD,
275ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
276ef7c8200Suwe 		    j6x0lcd_power, sc);
277ef7c8200Suwe }
278ef7c8200Suwe 
279ef7c8200Suwe 
280*6b95067cSuwe /*
281*6b95067cSuwe  * Get raw contrast value programmed in GPIO port B control register.
282*6b95067cSuwe  * Used only at attach time to get initial contrast.
283*6b95067cSuwe  */
284*6b95067cSuwe static int
285*6b95067cSuwe j6x0lcd_contrast_raw(uint16_t bcr, int width, const uint8_t *pin)
286*6b95067cSuwe {
287*6b95067cSuwe 	int contrast;
288*6b95067cSuwe 	int bit;
289*6b95067cSuwe 
290*6b95067cSuwe 	contrast = 0;
291*6b95067cSuwe 	for (bit = 0; bit < width; ++bit) {
292*6b95067cSuwe 		unsigned int c, v;
293*6b95067cSuwe 
294*6b95067cSuwe 		c = (bcr >> (pin[bit] << 1)) & 0x3;
295*6b95067cSuwe 		if (c == 1)	/* output mode? */
296*6b95067cSuwe 			v = 1;
297*6b95067cSuwe 		else
298*6b95067cSuwe 			v = 0;
299*6b95067cSuwe 		contrast |= (v << bit);
300*6b95067cSuwe 	}
301*6b95067cSuwe 
302*6b95067cSuwe 	return contrast;
303*6b95067cSuwe }
304*6b95067cSuwe 
305*6b95067cSuwe 
306*6b95067cSuwe /*
307*6b95067cSuwe  * Set contrast by programming GPIO port B control register.
308*6b95067cSuwe  * Data register has been initialized at attach time.
309*6b95067cSuwe  */
310*6b95067cSuwe static void
311*6b95067cSuwe j6x0lcd_contrast_set(struct j6x0lcd_softc *sc, int contrast)
312*6b95067cSuwe {
313*6b95067cSuwe 	uint16_t bcr;
314*6b95067cSuwe 
315*6b95067cSuwe 	sc->sc_contrast = contrast;
316*6b95067cSuwe 
317*6b95067cSuwe 	bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
318*6b95067cSuwe 
319*6b95067cSuwe 	bcr &= sc->sc_contrast_mask;
320*6b95067cSuwe 	bcr |= sc->sc_contrast_control_bits[contrast];
321*6b95067cSuwe 
322*6b95067cSuwe 	hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
323*6b95067cSuwe }
324*6b95067cSuwe 
325*6b95067cSuwe 
326ef7c8200Suwe static int
327ef7c8200Suwe j6x0lcd_param(ctx, type, id, msg)
328ef7c8200Suwe 	void *ctx;
329ef7c8200Suwe 	int type;
330ef7c8200Suwe 	long id;
331ef7c8200Suwe 	void *msg;
332ef7c8200Suwe {
333ef7c8200Suwe 	struct j6x0lcd_softc *sc = ctx;
334ef7c8200Suwe 	int value;
335ef7c8200Suwe 	uint8_t dr;
336ef7c8200Suwe 
337ef7c8200Suwe 	switch (type) {
338ef7c8200Suwe 	case CONFIG_HOOK_GET:
339ef7c8200Suwe 		switch (id) {
340ef7c8200Suwe 		case CONFIG_HOOK_CONTRAST:
341ef7c8200Suwe 			*(int *)msg = sc->sc_contrast;
342ef7c8200Suwe 			return (0);
343ef7c8200Suwe 
344ef7c8200Suwe 		case CONFIG_HOOK_CONTRAST_MAX:
345*6b95067cSuwe 			*(int *)msg = sc->sc_contrast_max;
346ef7c8200Suwe 			return (0);
347ef7c8200Suwe 
348ef7c8200Suwe 		case CONFIG_HOOK_BRIGHTNESS:
349ef7c8200Suwe 			*(int *)msg = sc->sc_brightness;
350ef7c8200Suwe 			return (0);
351ef7c8200Suwe 
352ef7c8200Suwe 		case CONFIG_HOOK_BRIGHTNESS_MAX:
353ef7c8200Suwe 			*(int *)msg = J6X0LCD_BRIGHTNESS_MAX;
354ef7c8200Suwe 			return (0);
355ef7c8200Suwe 		}
356ef7c8200Suwe 		break;
357ef7c8200Suwe 
358ef7c8200Suwe 	case CONFIG_HOOK_SET:
359ef7c8200Suwe 		value = *(int *)msg;
360ef7c8200Suwe 		if (value < 0)
361ef7c8200Suwe 			value = 0;
362ef7c8200Suwe 
363ef7c8200Suwe 		switch (id) {
364ef7c8200Suwe 		case CONFIG_HOOK_CONTRAST:
365*6b95067cSuwe 			if (value > sc->sc_contrast_max)
366*6b95067cSuwe 				value = sc->sc_contrast_max;
367*6b95067cSuwe 			j6x0lcd_contrast_set(sc, value);
368ef7c8200Suwe 			return (0);
369ef7c8200Suwe 
370ef7c8200Suwe 		case CONFIG_HOOK_BRIGHTNESS:
371ef7c8200Suwe 			if (value > J6X0LCD_BRIGHTNESS_MAX)
372ef7c8200Suwe 				value = J6X0LCD_BRIGHTNESS_MAX;
373ef7c8200Suwe 			sc->sc_brightness = value;
374ef7c8200Suwe 
375ef7c8200Suwe 			dr = J6X0LCD_BRIGHTNESS_TO_DA(value);
376ef7c8200Suwe 			DAC_(DR0) = dr;
377ef7c8200Suwe 			return (0);
378ef7c8200Suwe 		}
379ef7c8200Suwe 		break;
380ef7c8200Suwe 	}
381ef7c8200Suwe 
382ef7c8200Suwe 	return (EINVAL);
383ef7c8200Suwe }
384ef7c8200Suwe 
385ef7c8200Suwe 
386ef7c8200Suwe static int
387ef7c8200Suwe j6x0lcd_power(ctx, type, id, msg)
388ef7c8200Suwe 	void *ctx;
389ef7c8200Suwe 	int type;
390ef7c8200Suwe 	long id;
391ef7c8200Suwe 	void *msg;
392ef7c8200Suwe {
393ef7c8200Suwe 	int on;
394ef7c8200Suwe 	uint16_t r;
395ef7c8200Suwe 
396ef7c8200Suwe 	if (type != CONFIG_HOOK_POWERCONTROL
3979d8bb20eSuwe 	    || id != CONFIG_HOOK_POWERCONTROL_LCD)
398ef7c8200Suwe 		return (EINVAL);
399ef7c8200Suwe 
400ef7c8200Suwe 	on = (int)msg;
401ef7c8200Suwe 
402ef7c8200Suwe 	r = hd64461_reg_read_2(HD64461_GPBDR_REG16);
403ef7c8200Suwe 	if (on)
404*6b95067cSuwe 		r &= ~HD64461_GPBDR_J6X0_LCD_OFF;
405ef7c8200Suwe 	else
406*6b95067cSuwe 		r |= HD64461_GPBDR_J6X0_LCD_OFF;
407ef7c8200Suwe 	hd64461_reg_write_2(HD64461_GPBDR_REG16, r);
408ef7c8200Suwe 
409ef7c8200Suwe 	return (0);
410ef7c8200Suwe }
411