xref: /netbsd/sys/arch/hpcsh/dev/j6x0lcd.c (revision c7b2923b)
1*c7b2923bSuwe /*	$NetBSD: j6x0lcd.c,v 1.14 2009/04/05 02:23:00 uwe Exp $ */
2ef7c8200Suwe 
3ef7c8200Suwe /*
46b95067cSuwe  * 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*c7b2923bSuwe __KERNEL_RCSID(0, "$NetBSD: j6x0lcd.c,v 1.14 2009/04/05 02:23:00 uwe Exp $");
32ef7c8200Suwe 
33ef7c8200Suwe #include <sys/param.h>
34ef7c8200Suwe #include <sys/kernel.h>
35ef7c8200Suwe #include <sys/device.h>
36ef7c8200Suwe #include <sys/systm.h>
37ef7c8200Suwe 
38ef7c8200Suwe #include <machine/platid.h>
39ef7c8200Suwe #include <machine/platid_mask.h>
40ef7c8200Suwe 
41ef7c8200Suwe #include <machine/config_hook.h>
42ef7c8200Suwe 
43ef7c8200Suwe #include <sh3/dacreg.h>
44ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461var.h> /* XXX: for hd64461_reg_read_2 &c */
45ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461reg.h>
46ef7c8200Suwe #include <hpcsh/dev/hd64461/hd64461gpioreg.h>
47ef7c8200Suwe 
486b95067cSuwe #define arraysize(ary) (sizeof(ary) / sizeof(ary[0]))
496b95067cSuwe 
50ef7c8200Suwe 
51ef7c8200Suwe /*
52ef7c8200Suwe  * LCD power: controlled by pin 0 in HD64461 GPIO port B.
53ef7c8200Suwe  *   0 - power on
54ef7c8200Suwe  *   1 - power off
55ef7c8200Suwe  */
566b95067cSuwe #define HD64461_GPBDR_J6X0_LCD_OFF	0x01
57ef7c8200Suwe 
586b95067cSuwe #define HD64461_GPBCR_J6X0_LCD_OFF_MASK	0xfffc
596b95067cSuwe #define HD64461_GPBCR_J6X0_LCD_OFF_BITS	0x0001
60ef7c8200Suwe 
61ef7c8200Suwe 
62ef7c8200Suwe /*
63ef7c8200Suwe  * LCD brightness: controlled by DAC channel 0.  Larger channel values
64ef7c8200Suwe  * mean dimmer.  Values smaller (i.e. brighter) then 0x5e seems to
65ef7c8200Suwe  * result in no visible changes.
66ef7c8200Suwe  */
67ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_DA_MAX	0x5e
68ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_DA_MIN	0xff
69ef7c8200Suwe 
70ef7c8200Suwe #define J6X0LCD_DA_TO_BRIGHTNESS(da) \
71ef7c8200Suwe 	(J6X0LCD_BRIGHTNESS_DA_MIN - (da))
72ef7c8200Suwe 
73ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_TO_DA(br) \
74ef7c8200Suwe 	(J6X0LCD_BRIGHTNESS_DA_MIN - (br))
75ef7c8200Suwe 
76ef7c8200Suwe #define J6X0LCD_BRIGHTNESS_MAX \
77ef7c8200Suwe 	J6X0LCD_DA_TO_BRIGHTNESS(J6X0LCD_BRIGHTNESS_DA_MAX)
78ef7c8200Suwe 
79ef7c8200Suwe /* convenience macro to accesses DAC registers */
80ef7c8200Suwe #define DAC_(x)    (*((volatile uint8_t *)SH7709_DA ## x))
81ef7c8200Suwe 
82ef7c8200Suwe 
83ef7c8200Suwe /*
846b95067cSuwe  * LCD contrast in 680 is controlled by pins 6..3 of HD64461 GPIO
856b95067cSuwe  * port B.  6th pin is the least significant bit, 3rd pin is the most
866b95067cSuwe  * significant.  The bits are inverted: 0 = .1111...; 1 = .0111...;
876b95067cSuwe  * etc.  Larger values mean "blacker".
88ef7c8200Suwe  *
896b95067cSuwe  * The contrast value is programmed by setting bits in the data
906b95067cSuwe  * register to all ones, and changing the mode of the pins in the
916b95067cSuwe  * control register, setting logical "ones" to GPIO output mode (1),
926b95067cSuwe  * and switching "zeroes" to input mode (3).
93ef7c8200Suwe  */
946b95067cSuwe #define HD64461_GPBDR_J680_CONTRAST_BITS	0x78	/* set */
956b95067cSuwe #define HD64461_GPBCR_J680_CONTRAST_MASK	0xc03f
96ef7c8200Suwe 
976b95067cSuwe static const uint8_t j6x0lcd_contrast680_pins[] = { 6, 5, 4, 3 };
98ef7c8200Suwe 
996b95067cSuwe static const uint16_t j6x0lcd_contrast680_control_bits[] = {
100ef7c8200Suwe 	0x1540, 0x3540, 0x1d40, 0x3d40, 0x1740, 0x3740, 0x1f40, 0x3f40,
101ef7c8200Suwe 	0x15c0, 0x35c0, 0x1dc0, 0x3dc0, 0x17c0, 0x37c0, 0x1fc0, 0x3fc0
102ef7c8200Suwe };
103ef7c8200Suwe 
104ef7c8200Suwe 
1056b95067cSuwe /*
1066b95067cSuwe  * LCD contrast in 620lx is controlled by pins 7,6,3,4,5 of HD64461
1076b95067cSuwe  * GPIO port B (in the order from the least significant to the most
1086b95067cSuwe  * significant).  The bits are inverted: 0 = 11111...; 5 = 01110...;
1096b95067cSuwe  * etc.  Larger values mean "whiter".
1106b95067cSuwe  *
1116b95067cSuwe  * The contrast value is programmed by setting bits in the data
1126b95067cSuwe  * register to all zeroes, and changing the mode of the pins in the
1136b95067cSuwe  * control register, setting logical "ones" to GPIO output mode (1),
1146b95067cSuwe  * and switching "zeroes" to input mode (3).
1156b95067cSuwe  */
1166b95067cSuwe #define HD64461_GPBDR_J620LX_CONTRAST_BITS	0xf8	/* clear */
1176b95067cSuwe #define HD64461_GPBCR_J620LX_CONTRAST_MASK	0x003f
1186b95067cSuwe 
1196b95067cSuwe static const uint8_t j6x0lcd_contrast620lx_pins[] = { 7, 6, 3, 4, 5 };
1206b95067cSuwe 
1216b95067cSuwe static const uint16_t j6x0lcd_contrast620lx_control_bits[] = {
1226b95067cSuwe 	0xffc0, 0x7fc0, 0xdfc0, 0x5fc0, 0xff40, 0x7f40, 0xdf40, 0x5f40,
1236b95067cSuwe 	0xfdc0, 0x7dc0, 0xddc0, 0x5dc0, 0xfd40, 0x7d40, 0xdd40, 0x5d40,
1246b95067cSuwe 	0xf7c0, 0x77c0, 0xd7c0, 0x57c0, 0xf740, 0x7740, 0xd740, 0x5740,
1256b95067cSuwe 	0xf5c0, 0x75c0, 0xd5c0, 0x55c0, 0xf540, 0x7540, 0xd540, 0x5540
1266b95067cSuwe };
1276b95067cSuwe 
1286b95067cSuwe 
1296b95067cSuwe 
130ef7c8200Suwe struct j6x0lcd_softc {
131a0caab75Suwe 	device_t sc_dev;
132a0caab75Suwe 
133ef7c8200Suwe 	int sc_brightness;
134ef7c8200Suwe 	int sc_contrast;
1356b95067cSuwe 
1366b95067cSuwe 	int sc_contrast_max;
1376b95067cSuwe 	uint16_t sc_contrast_mask;
1386b95067cSuwe 	const uint16_t *sc_contrast_control_bits;
139ef7c8200Suwe };
140ef7c8200Suwe 
141a0caab75Suwe static int	j6x0lcd_match(device_t, cfdata_t, void *);
142a0caab75Suwe static void	j6x0lcd_attach(device_t, device_t, void *);
143ef7c8200Suwe 
144a0caab75Suwe CFATTACH_DECL_NEW(j6x0lcd, sizeof(struct j6x0lcd_softc),
145ef7c8200Suwe     j6x0lcd_match, j6x0lcd_attach, NULL, NULL);
146ef7c8200Suwe 
147ef7c8200Suwe 
148ef7c8200Suwe static int	j6x0lcd_param(void *, int, long, void *);
149ef7c8200Suwe static int	j6x0lcd_power(void *, int, long, void *);
150ef7c8200Suwe 
1516b95067cSuwe static int	j6x0lcd_contrast_raw(uint16_t, int, const uint8_t *);
1526b95067cSuwe static void	j6x0lcd_contrast_set(struct j6x0lcd_softc *, int);
1536b95067cSuwe 
1546b95067cSuwe 
155ef7c8200Suwe 
156ef7c8200Suwe static int
j6x0lcd_match(device_t parent,cfdata_t cf,void * aux)157a0caab75Suwe j6x0lcd_match(device_t parent, cfdata_t cf, void *aux)
158ef7c8200Suwe {
159ef7c8200Suwe 
160ef7c8200Suwe 	/*
1616b95067cSuwe 	 * XXX: platid_mask_MACH_HP_LX also matches 360LX.  It's not
1626b95067cSuwe 	 * confirmed whether touch panel in 360LX is connected this
1636b95067cSuwe 	 * way.  We may need to regroup platid masks.
164ef7c8200Suwe 	 */
1656b95067cSuwe 	if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)
1666b95067cSuwe 	    && !platid_match(&platid, &platid_mask_MACH_HP_LX))
167ef7c8200Suwe 		return (0);
168ef7c8200Suwe 
169a0caab75Suwe 	if (strcmp(cf->cf_name, "j6x0lcd") != 0)
170ef7c8200Suwe 		return (0);
171ef7c8200Suwe 
172ef7c8200Suwe 	return (1);
173ef7c8200Suwe }
174ef7c8200Suwe 
175ef7c8200Suwe 
176ef7c8200Suwe static void
j6x0lcd_attach(device_t parent,device_t self,void * aux)177a0caab75Suwe j6x0lcd_attach(device_t parent, device_t self, void *aux)
178ef7c8200Suwe {
179a0caab75Suwe 	struct j6x0lcd_softc *sc;
180ef7c8200Suwe 	uint16_t bcr, bdr;
181ef7c8200Suwe 	uint8_t dcr, ddr;
182ef7c8200Suwe 
183fd8017cbSuwe 	aprint_naive("\n");
184fd8017cbSuwe 
185a0caab75Suwe 	sc = device_private(self);
186a0caab75Suwe 	sc->sc_dev = self;
187a0caab75Suwe 
188ef7c8200Suwe 	/*
189ef7c8200Suwe 	 * Brightness is controlled by DAC channel 0.
190ef7c8200Suwe 	 */
191ef7c8200Suwe 	dcr = DAC_(CR);
192ef7c8200Suwe 	dcr &= ~SH7709_DACR_DAE; /* want to control each channel separately */
193ef7c8200Suwe 	dcr |= SH7709_DACR_DAOE0; /* enable channel 0 */
194ef7c8200Suwe 	DAC_(CR) = dcr;
195ef7c8200Suwe 
196ef7c8200Suwe 	ddr = DAC_(DR0);
197ef7c8200Suwe 	sc->sc_brightness = J6X0LCD_DA_TO_BRIGHTNESS(ddr);
198ef7c8200Suwe 
199ef7c8200Suwe 	/*
200ef7c8200Suwe 	 * Contrast and power are controlled by HD64461 GPIO port B.
201ef7c8200Suwe 	 */
202ef7c8200Suwe 	bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
203ef7c8200Suwe 	bdr = hd64461_reg_read_2(HD64461_GPBDR_REG16);
204ef7c8200Suwe 
2056b95067cSuwe 	/*
2066b95067cSuwe 	 * Make sure LCD is turned on.
2076b95067cSuwe 	 */
2086b95067cSuwe 	bcr &= HD64461_GPBCR_J6X0_LCD_OFF_MASK;
2096b95067cSuwe 	bcr |= HD64461_GPBCR_J6X0_LCD_OFF_BITS; /* output mode */
2106b95067cSuwe 
2116b95067cSuwe 	bdr &= ~HD64461_GPBDR_J6X0_LCD_OFF;
2126b95067cSuwe 
2136b95067cSuwe 	/*
2146b95067cSuwe 	 * 620LX and 680 have different contrast control.
2156b95067cSuwe 	 */
2166b95067cSuwe 	if (platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)) {
2176b95067cSuwe 		bdr |= HD64461_GPBDR_J680_CONTRAST_BITS;
2186b95067cSuwe 
2196b95067cSuwe 		sc->sc_contrast_mask =
2206b95067cSuwe 			HD64461_GPBCR_J680_CONTRAST_MASK;
2216b95067cSuwe 		sc->sc_contrast_control_bits =
2226b95067cSuwe 			j6x0lcd_contrast680_control_bits;
2236b95067cSuwe 		sc->sc_contrast_max =
2246b95067cSuwe 			arraysize(j6x0lcd_contrast680_control_bits) - 1;
2256b95067cSuwe 
2266b95067cSuwe 		sc->sc_contrast = sc->sc_contrast_max
2276b95067cSuwe 			- j6x0lcd_contrast_raw(bcr,
2286b95067cSuwe 				arraysize(j6x0lcd_contrast680_pins),
2296b95067cSuwe 				j6x0lcd_contrast680_pins);
2306b95067cSuwe 	} else {
2316b95067cSuwe 		bdr &= ~HD64461_GPBDR_J620LX_CONTRAST_BITS;
2326b95067cSuwe 
2336b95067cSuwe 		sc->sc_contrast_mask =
2346b95067cSuwe 			HD64461_GPBCR_J620LX_CONTRAST_MASK;
2356b95067cSuwe 		sc->sc_contrast_control_bits =
2366b95067cSuwe 			j6x0lcd_contrast620lx_control_bits;
2376b95067cSuwe 		sc->sc_contrast_max =
2386b95067cSuwe 			arraysize(j6x0lcd_contrast620lx_control_bits) - 1;
2396b95067cSuwe 
2406b95067cSuwe 		sc->sc_contrast =
2416b95067cSuwe 			j6x0lcd_contrast_raw(bcr,
2426b95067cSuwe 				arraysize(j6x0lcd_contrast620lx_pins),
2436b95067cSuwe 				j6x0lcd_contrast620lx_pins);
244ef7c8200Suwe 	}
245ef7c8200Suwe 
246ef7c8200Suwe 	hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
2476b95067cSuwe 	hd64461_reg_write_2(HD64461_GPBDR_REG16, bdr);
248ef7c8200Suwe 
249fd8017cbSuwe 	aprint_normal(": brightness %d, contrast %d\n",
250ef7c8200Suwe 		      sc->sc_brightness, sc->sc_contrast);
251ef7c8200Suwe 
252ef7c8200Suwe 
253ef7c8200Suwe 	/* LCD brightness hooks */
254ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX,
255ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
256ef7c8200Suwe 		    j6x0lcd_param, sc);
257ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS,
258ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
259ef7c8200Suwe 		    j6x0lcd_param, sc);
260ef7c8200Suwe 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS,
261ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
262ef7c8200Suwe 		    j6x0lcd_param, sc);
263ef7c8200Suwe 
264ef7c8200Suwe 	/* LCD contrast hooks */
265ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX,
266ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
267ef7c8200Suwe 		    j6x0lcd_param, sc);
268ef7c8200Suwe 	config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST,
269ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
270ef7c8200Suwe 		    j6x0lcd_param, sc);
271ef7c8200Suwe 	config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST,
272ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
273ef7c8200Suwe 		    j6x0lcd_param, sc);
274ef7c8200Suwe 
275ef7c8200Suwe 	/* LCD on/off hook */
276ef7c8200Suwe 	config_hook(CONFIG_HOOK_POWERCONTROL,
2779d8bb20eSuwe 		    CONFIG_HOOK_POWERCONTROL_LCD,
278ef7c8200Suwe 		    CONFIG_HOOK_SHARE,
279ef7c8200Suwe 		    j6x0lcd_power, sc);
280*c7b2923bSuwe 
281*c7b2923bSuwe 	/* XXX: TODO: don't rely on CONFIG_HOOK_POWERCONTROL_LCD */
282*c7b2923bSuwe 	if (!pmf_device_register(self, NULL, NULL))
283*c7b2923bSuwe 		aprint_error_dev(self, "unable to establish power handler\n");
284ef7c8200Suwe }
285ef7c8200Suwe 
286ef7c8200Suwe 
2876b95067cSuwe /*
2886b95067cSuwe  * Get raw contrast value programmed in GPIO port B control register.
2896b95067cSuwe  * Used only at attach time to get initial contrast.
2906b95067cSuwe  */
2916b95067cSuwe static int
j6x0lcd_contrast_raw(uint16_t bcr,int width,const uint8_t * pin)2926b95067cSuwe j6x0lcd_contrast_raw(uint16_t bcr, int width, const uint8_t *pin)
2936b95067cSuwe {
2946b95067cSuwe 	int contrast;
2956b95067cSuwe 	int bit;
2966b95067cSuwe 
2976b95067cSuwe 	contrast = 0;
2986b95067cSuwe 	for (bit = 0; bit < width; ++bit) {
299fb2feef0Suwe 		unsigned int c;
3006b95067cSuwe 
3016b95067cSuwe 		c = (bcr >> (pin[bit] << 1)) & 0x3;
302fb2feef0Suwe 		if (c == 1)	/* pin in output mode? */
303fb2feef0Suwe 			contrast |= (1 << bit);
3046b95067cSuwe 	}
3056b95067cSuwe 
3066b95067cSuwe 	return contrast;
3076b95067cSuwe }
3086b95067cSuwe 
3096b95067cSuwe 
3106b95067cSuwe /*
3116b95067cSuwe  * Set contrast by programming GPIO port B control register.
3126b95067cSuwe  * Data register has been initialized at attach time.
3136b95067cSuwe  */
3146b95067cSuwe static void
j6x0lcd_contrast_set(struct j6x0lcd_softc * sc,int contrast)3156b95067cSuwe j6x0lcd_contrast_set(struct j6x0lcd_softc *sc, int contrast)
3166b95067cSuwe {
3176b95067cSuwe 	uint16_t bcr;
3186b95067cSuwe 
3196b95067cSuwe 	sc->sc_contrast = contrast;
3206b95067cSuwe 
3216b95067cSuwe 	bcr = hd64461_reg_read_2(HD64461_GPBCR_REG16);
3226b95067cSuwe 
3236b95067cSuwe 	bcr &= sc->sc_contrast_mask;
3246b95067cSuwe 	bcr |= sc->sc_contrast_control_bits[contrast];
3256b95067cSuwe 
3266b95067cSuwe 	hd64461_reg_write_2(HD64461_GPBCR_REG16, bcr);
3276b95067cSuwe }
3286b95067cSuwe 
3296b95067cSuwe 
330ef7c8200Suwe static int
j6x0lcd_param(void * ctx,int type,long id,void * msg)331d5c16305Suwe j6x0lcd_param(void *ctx, int type, long id, 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:
3456b95067cSuwe 			*(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:
3656b95067cSuwe 			if (value > sc->sc_contrast_max)
3666b95067cSuwe 				value = sc->sc_contrast_max;
3676b95067cSuwe 			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
j6x0lcd_power(void * ctx,int type,long id,void * msg)387d5c16305Suwe j6x0lcd_power(void *ctx, int type, long id, void *msg)
388ef7c8200Suwe {
389ef7c8200Suwe 	int on;
390ef7c8200Suwe 	uint16_t r;
391ef7c8200Suwe 
392ef7c8200Suwe 	if (type != CONFIG_HOOK_POWERCONTROL
3939d8bb20eSuwe 	    || id != CONFIG_HOOK_POWERCONTROL_LCD)
394ef7c8200Suwe 		return (EINVAL);
395ef7c8200Suwe 
396ef7c8200Suwe 	on = (int)msg;
397ef7c8200Suwe 
398ef7c8200Suwe 	r = hd64461_reg_read_2(HD64461_GPBDR_REG16);
399ef7c8200Suwe 	if (on)
4006b95067cSuwe 		r &= ~HD64461_GPBDR_J6X0_LCD_OFF;
401ef7c8200Suwe 	else
4026b95067cSuwe 		r |= HD64461_GPBDR_J6X0_LCD_OFF;
403ef7c8200Suwe 	hd64461_reg_write_2(HD64461_GPBDR_REG16, r);
404ef7c8200Suwe 
405ef7c8200Suwe 	return (0);
406ef7c8200Suwe }
407