xref: /netbsd-src/sys/dev/hpc/bivideo.c (revision 86c307248f84cb113ddd7597e82b97bcf315b5bb)
1*86c30724Sandvar /*	$NetBSD: bivideo.c,v 1.37 2022/05/28 10:36:23 andvar Exp $	*/
2659f65e0Such 
3659f65e0Such /*-
4edde743dSuch  * Copyright (c) 1999-2001
5659f65e0Such  *         Shin Takemura and PocketBSD Project. All rights reserved.
6659f65e0Such  *
7659f65e0Such  * Redistribution and use in source and binary forms, with or without
8659f65e0Such  * modification, are permitted provided that the following conditions
9659f65e0Such  * are met:
10659f65e0Such  * 1. Redistributions of source code must retain the above copyright
11659f65e0Such  *    notice, this list of conditions and the following disclaimer.
12659f65e0Such  * 2. Redistributions in binary form must reproduce the above copyright
13659f65e0Such  *    notice, this list of conditions and the following disclaimer in the
14659f65e0Such  *    documentation and/or other materials provided with the distribution.
15659f65e0Such  * 3. All advertising materials mentioning features or use of this software
16659f65e0Such  *    must display the following acknowledgement:
17659f65e0Such  *	This product includes software developed by the PocketBSD project
18659f65e0Such  *	and its contributors.
19659f65e0Such  * 4. Neither the name of the project nor the names of its contributors
20659f65e0Such  *    may be used to endorse or promote products derived from this software
21659f65e0Such  *    without specific prior written permission.
22659f65e0Such  *
23659f65e0Such  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24659f65e0Such  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25659f65e0Such  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26659f65e0Such  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27659f65e0Such  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28659f65e0Such  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29659f65e0Such  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30659f65e0Such  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31659f65e0Such  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32659f65e0Such  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33659f65e0Such  * SUCH DAMAGE.
34659f65e0Such  *
35659f65e0Such  */
36b84f53efSlukem 
37b84f53efSlukem #include <sys/cdefs.h>
38*86c30724Sandvar __KERNEL_RCSID(0, "$NetBSD: bivideo.c,v 1.37 2022/05/28 10:36:23 andvar Exp $");
39b84f53efSlukem 
409eddf385Speter #ifdef _KERNEL_OPT
419eddf385Speter #include "opt_hpcfb.h"
429eddf385Speter #endif
43659f65e0Such 
44659f65e0Such #include <sys/param.h>
45659f65e0Such #include <sys/systm.h>
46659f65e0Such #include <sys/device.h>
47659f65e0Such #include <sys/buf.h>
48659f65e0Such #include <sys/ioctl.h>
49659f65e0Such #include <sys/reboot.h>
50659f65e0Such 
51a2a38285Sad #include <sys/bus.h>
52659f65e0Such #include <machine/autoconf.h>
53659f65e0Such #include <machine/bootinfo.h>
54659f65e0Such #include <machine/config_hook.h>
55659f65e0Such 
56659f65e0Such #include <dev/wscons/wsconsio.h>
57659f65e0Such #include <dev/wscons/wsdisplayvar.h>
58659f65e0Such 
59659f65e0Such #include <dev/rasops/rasops.h>
60659f65e0Such 
61659f65e0Such #include <dev/hpc/hpcfbvar.h>
62659f65e0Such #include <dev/hpc/hpcfbio.h>
63659f65e0Such #include <dev/hpc/bivideovar.h>
64659f65e0Such #include <dev/hpc/hpccmapvar.h>
65659f65e0Such 
669eddf385Speter #ifdef FBDEBUG
679eddf385Speter #define VPRINTF(arg)	do { if (bootverbose) printf arg; } while (0)
689eddf385Speter #else
699eddf385Speter #define VPRINTF(arg)	/* nothing */
709eddf385Speter #endif
71659f65e0Such 
72659f65e0Such /*
73659f65e0Such  *  global variables
74659f65e0Such  */
75659f65e0Such int bivideo_dont_attach = 0;
76659f65e0Such 
77659f65e0Such /*
78659f65e0Such  *  function prototypes
79659f65e0Such  */
80529e91fcScegger int	bivideomatch(device_t, cfdata_t, void *);
81529e91fcScegger void	bivideoattach(device_t, device_t, void *);
8253524e44Schristos int	bivideo_ioctl(void *, u_long, void *, int, struct lwp *);
83edde743dSuch paddr_t	bivideo_mmap(void *, off_t, int);
84659f65e0Such 
85659f65e0Such struct bivideo_softc {
86659f65e0Such 	struct hpcfb_fbconf	sc_fbconf;
87659f65e0Such 	struct hpcfb_dspconf	sc_dspconf;
88659f65e0Such 	int			sc_powerstate;
89659f65e0Such #define PWRSTAT_SUSPEND		(1<<0)
9080214041Ssato #define PWRSTAT_VIDEOOFF	(1<<1)
9180214041Ssato #define PWRSTAT_LCD		(1<<2)
9280214041Ssato #define PWRSTAT_BACKLIGHT	(1<<3)
93659f65e0Such #define PWRSTAT_ALL		(0xffffffff)
946c5da9bdSsato 	int			sc_lcd_inited;
956c5da9bdSsato #define BACKLIGHT_INITED	(1<<0)
966c5da9bdSsato #define BRIGHTNESS_INITED	(1<<1)
976c5da9bdSsato #define CONTRAST_INITED		(1<<2)
98b8e5bc56Ssato 	int			sc_brightness;
99b8e5bc56Ssato 	int			sc_brightness_save;
100b8e5bc56Ssato 	int			sc_max_brightness;
101b8e5bc56Ssato 	int			sc_contrast;
102b8e5bc56Ssato 	int			sc_max_contrast;
103b8e5bc56Ssato 
104659f65e0Such };
105b8e5bc56Ssato 
106edde743dSuch static int bivideo_init(struct hpcfb_fbconf *);
107edde743dSuch static void bivideo_power(int, void *);
108edde743dSuch static void bivideo_update_powerstate(struct bivideo_softc *, int);
109f928eeabStsutsui static bool bivideo_suspend(device_t, const pmf_qual_t *);
110f928eeabStsutsui static bool bivideo_resume(device_t, const pmf_qual_t *);
1116c5da9bdSsato void	bivideo_init_backlight(struct bivideo_softc *, int);
1126c5da9bdSsato void	bivideo_init_brightness(struct bivideo_softc *, int);
1136c5da9bdSsato void	bivideo_init_contrast(struct bivideo_softc *, int);
114b8e5bc56Ssato void	bivideo_set_brightness(struct bivideo_softc *, int);
115b8e5bc56Ssato void	bivideo_set_contrast(struct bivideo_softc *, int);
116659f65e0Such 
117edde743dSuch #if defined __mips__ || defined __sh__ || defined __arm__
118edde743dSuch #define __BTOP(x)		((paddr_t)(x) >> PGSHIFT)
119edde743dSuch #define __PTOB(x)		((paddr_t)(x) << PGSHIFT)
120edde743dSuch #else
121edde743dSuch #error "define btop, ptob."
122edde743dSuch #endif
123659f65e0Such 
124659f65e0Such /*
125659f65e0Such  *  static variables
126659f65e0Such  */
127cbab9cadSchs CFATTACH_DECL_NEW(bivideo, sizeof(struct bivideo_softc),
128c9b3657cSthorpej     bivideomatch, bivideoattach, NULL, NULL);
1299d4a6407Sthorpej 
130659f65e0Such struct hpcfb_accessops bivideo_ha = {
131659f65e0Such 	bivideo_ioctl, bivideo_mmap
132659f65e0Such };
133659f65e0Such 
134659f65e0Such static int console_flag = 0;
135659f65e0Such static int attach_flag = 0;
136659f65e0Such 
137659f65e0Such /*
138659f65e0Such  *  function bodies
139659f65e0Such  */
140659f65e0Such int
bivideomatch(device_t parent,cfdata_t match,void * aux)141529e91fcScegger bivideomatch(device_t parent, cfdata_t match, void *aux)
142659f65e0Such {
143659f65e0Such 	struct mainbus_attach_args *ma = aux;
144659f65e0Such 
145659f65e0Such 	if (bivideo_dont_attach ||
146d1ad2ac4Sthorpej 	    strcmp(ma->ma_name, match->cf_name))
147659f65e0Such 		return 0;
148659f65e0Such 
149659f65e0Such 	return (1);
150659f65e0Such }
151659f65e0Such 
152659f65e0Such void
bivideoattach(device_t parent,device_t self,void * aux)153529e91fcScegger bivideoattach(device_t parent, device_t self, void *aux)
154659f65e0Such {
15592c7bba3Sthorpej 	struct bivideo_softc *sc = device_private(self);
156659f65e0Such 	struct hpcfb_attach_args ha;
157659f65e0Such 
158659f65e0Such 	if (attach_flag) {
159659f65e0Such 		panic("%s(%d): bivideo attached twice", __FILE__, __LINE__);
160659f65e0Such 	}
161659f65e0Such 	attach_flag = 1;
162659f65e0Such 
163659f65e0Such 	printf(": ");
164659f65e0Such 	if (bivideo_init(&sc->sc_fbconf) != 0) {
165659f65e0Such 		/* just return so that hpcfb will not be attached */
166659f65e0Such 		return;
167659f65e0Such 	}
168659f65e0Such 
169659f65e0Such 	printf("pseudo video controller");
170659f65e0Such 	if (console_flag) {
171659f65e0Such 		printf(", console");
172659f65e0Such 	}
173659f65e0Such 	printf("\n");
174659f65e0Such 	printf("%s: framebuffer address: 0x%08lx\n",
175cbab9cadSchs 		device_xname(self), (u_long)bootinfo->fb_addr);
176659f65e0Such 
177659f65e0Such 	/* Add a suspend hook to power saving */
178659f65e0Such 	sc->sc_powerstate = 0;
179f928eeabStsutsui 	if (!pmf_device_register(self, bivideo_suspend, bivideo_resume))
180f928eeabStsutsui 		aprint_error_dev(self, "unable to establish power handler\n");
181659f65e0Such 
182b8e5bc56Ssato 	/* initialize backlight brightness and lcd contrast */
1836c5da9bdSsato 	sc->sc_lcd_inited = 0;
1846c5da9bdSsato 	bivideo_init_brightness(sc, 1);
1856c5da9bdSsato 	bivideo_init_contrast(sc, 1);
1866c5da9bdSsato 	bivideo_init_backlight(sc, 1);
187b8e5bc56Ssato 
188659f65e0Such 	ha.ha_console = console_flag;
189659f65e0Such 	ha.ha_accessops = &bivideo_ha;
190659f65e0Such 	ha.ha_accessctx = sc;
191659f65e0Such 	ha.ha_curfbconf = 0;
192659f65e0Such 	ha.ha_nfbconf = 1;
193659f65e0Such 	ha.ha_fbconflist = &sc->sc_fbconf;
194659f65e0Such 	ha.ha_curdspconf = 0;
195659f65e0Such 	ha.ha_ndspconf = 1;
196659f65e0Such 	ha.ha_dspconflist = &sc->sc_dspconf;
197659f65e0Such 
198c7fb772bSthorpej 	config_found(self, &ha, hpcfbprint, CFARGS_NONE);
199659f65e0Such }
200659f65e0Such 
201659f65e0Such int
bivideo_getcnfb(struct hpcfb_fbconf * fb)202edde743dSuch bivideo_getcnfb(struct hpcfb_fbconf *fb)
203659f65e0Such {
204659f65e0Such 	console_flag = 1;
205659f65e0Such 
206659f65e0Such 	return bivideo_init(fb);
207659f65e0Such }
208659f65e0Such 
209659f65e0Such static int
bivideo_init(struct hpcfb_fbconf * fb)210edde743dSuch bivideo_init(struct hpcfb_fbconf *fb)
211659f65e0Such {
212659f65e0Such 	/*
213659f65e0Such 	 * get fb settings from bootinfo
214659f65e0Such 	 */
215659f65e0Such 	if (bootinfo == NULL ||
216659f65e0Such 	    bootinfo->fb_addr == 0 ||
217659f65e0Such 	    bootinfo->fb_line_bytes == 0 ||
218659f65e0Such 	    bootinfo->fb_width == 0 ||
219659f65e0Such 	    bootinfo->fb_height == 0) {
220e267c67bStoshii 		printf("no frame buffer information.\n");
221659f65e0Such 		return (-1);
222659f65e0Such 	}
223659f65e0Such 
224659f65e0Such 	/* zero fill */
22535836fceStoshii 	memset(fb, 0, sizeof(*fb));
226659f65e0Such 
227659f65e0Such 	fb->hf_conf_index	= 0;	/* configuration index		*/
228659f65e0Such 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
229659f65e0Such 	strcpy(fb->hf_name, "built-in video");
230659f65e0Such 					/* frame buffer name		*/
231659f65e0Such 	strcpy(fb->hf_conf_name, "default");
232659f65e0Such 					/* configuration name		*/
233659f65e0Such 	fb->hf_height		= bootinfo->fb_height;
234659f65e0Such 	fb->hf_width		= bootinfo->fb_width;
235659f65e0Such 	fb->hf_baseaddr		= (u_long)bootinfo->fb_addr;
236659f65e0Such 	fb->hf_offset		= (u_long)bootinfo->fb_addr -
237edde743dSuch 				      __PTOB(__BTOP(bootinfo->fb_addr));
238659f65e0Such 					/* frame buffer start offset   	*/
239659f65e0Such 	fb->hf_bytes_per_line	= bootinfo->fb_line_bytes;
240659f65e0Such 	fb->hf_nplanes		= 1;
241659f65e0Such 	fb->hf_bytes_per_plane	= bootinfo->fb_height *
242659f65e0Such 					bootinfo->fb_line_bytes;
243659f65e0Such 
244659f65e0Such 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
245659f65e0Such 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
246659f65e0Such 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
247659f65e0Such 
248659f65e0Such 	switch (bootinfo->fb_type) {
249659f65e0Such 		/*
250659f65e0Such 		 * gray scale
251659f65e0Such 		 */
252659f65e0Such 	case BIFB_D2_M2L_3:
253659f65e0Such 	case BIFB_D2_M2L_3x2:
254659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
255659f65e0Such 		/* fall through */
256659f65e0Such 	case BIFB_D2_M2L_0:
257659f65e0Such 	case BIFB_D2_M2L_0x2:
258659f65e0Such 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
259659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
260659f65e0Such 		fb->hf_pack_width = 8;
261659f65e0Such 		fb->hf_pixels_per_pack = 4;
262659f65e0Such 		fb->hf_pixel_width = 2;
263659f65e0Such 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
264659f65e0Such 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
265659f65e0Such 		break;
266659f65e0Such 
267659f65e0Such 	case BIFB_D4_M2L_F:
268659f65e0Such 	case BIFB_D4_M2L_Fx2:
269659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
270659f65e0Such 		/* fall through */
271659f65e0Such 	case BIFB_D4_M2L_0:
272659f65e0Such 	case BIFB_D4_M2L_0x2:
273659f65e0Such 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
274659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
275659f65e0Such 		fb->hf_pack_width = 8;
276659f65e0Such 		fb->hf_pixels_per_pack = 2;
277659f65e0Such 		fb->hf_pixel_width = 4;
278659f65e0Such 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
279659f65e0Such 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
280659f65e0Such 		break;
281659f65e0Such 
282659f65e0Such 		/*
283659f65e0Such 		 * indexed color
284659f65e0Such 		 */
285659f65e0Such 	case BIFB_D8_FF:
286659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
287659f65e0Such 		/* fall through */
288659f65e0Such 	case BIFB_D8_00:
289659f65e0Such 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
290659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
291659f65e0Such 		fb->hf_pack_width = 8;
292659f65e0Such 		fb->hf_pixels_per_pack = 1;
293659f65e0Such 		fb->hf_pixel_width = 8;
294659f65e0Such 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
295659f65e0Such 		fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
296659f65e0Such 		break;
297659f65e0Such 
298659f65e0Such 		/*
299659f65e0Such 		 * RGB color
300659f65e0Such 		 */
301659f65e0Such 	case BIFB_D16_FFFF:
302659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
303659f65e0Such 		/* fall through */
304659f65e0Such 	case BIFB_D16_0000:
305659f65e0Such 		fb->hf_class = HPCFB_CLASS_RGBCOLOR;
306659f65e0Such 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
30764b6b76aStakemura #if BYTE_ORDER == LITTLE_ENDIAN
30864b6b76aStakemura 		fb->hf_order_flags = HPCFB_REVORDER_BYTE;
309659f65e0Such #endif
310659f65e0Such 		fb->hf_pack_width = 16;
311659f65e0Such 		fb->hf_pixels_per_pack = 1;
312659f65e0Such 		fb->hf_pixel_width = 16;
313659f65e0Such 
314659f65e0Such 		fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
315659f65e0Such 		fb->hf_u.hf_rgb.hf_flags = 0;	/* reserved for future use */
316659f65e0Such 
317659f65e0Such 		fb->hf_u.hf_rgb.hf_red_width = 5;
318659f65e0Such 		fb->hf_u.hf_rgb.hf_red_shift = 11;
319659f65e0Such 		fb->hf_u.hf_rgb.hf_green_width = 6;
320659f65e0Such 		fb->hf_u.hf_rgb.hf_green_shift = 5;
321659f65e0Such 		fb->hf_u.hf_rgb.hf_blue_width = 5;
322659f65e0Such 		fb->hf_u.hf_rgb.hf_blue_shift = 0;
323659f65e0Such 		fb->hf_u.hf_rgb.hf_alpha_width = 0;
324659f65e0Such 		fb->hf_u.hf_rgb.hf_alpha_shift = 0;
325659f65e0Such 		break;
326659f65e0Such 
327659f65e0Such 	default:
328659f65e0Such 		printf("unsupported type %d.\n", bootinfo->fb_type);
329659f65e0Such 		return (-1);
330659f65e0Such 		break;
331659f65e0Such 	}
332659f65e0Such 
333659f65e0Such 	return (0); /* no error */
334659f65e0Such }
335659f65e0Such 
336659f65e0Such static void
bivideo_power(int why,void * arg)337edde743dSuch bivideo_power(int why, void *arg)
338659f65e0Such {
339659f65e0Such 	struct bivideo_softc *sc = arg;
340659f65e0Such 
341659f65e0Such 	switch (why) {
342659f65e0Such 	case PWR_SUSPEND:
343659f65e0Such 	case PWR_STANDBY:
344659f65e0Such 		sc->sc_powerstate |= PWRSTAT_SUSPEND;
345659f65e0Such 		bivideo_update_powerstate(sc, PWRSTAT_ALL);
346659f65e0Such 		break;
347659f65e0Such 	case PWR_RESUME:
348659f65e0Such 		sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
349659f65e0Such 		bivideo_update_powerstate(sc, PWRSTAT_ALL);
350659f65e0Such 		break;
351659f65e0Such 	}
352659f65e0Such }
353659f65e0Such 
354659f65e0Such static void
bivideo_update_powerstate(struct bivideo_softc * sc,int updates)355edde743dSuch bivideo_update_powerstate(struct bivideo_softc *sc, int updates)
356659f65e0Such {
357659f65e0Such 	if (updates & PWRSTAT_LCD)
358659f65e0Such 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
359659f65e0Such 		    CONFIG_HOOK_POWERCONTROL_LCD,
36080214041Ssato 		    (void*)!(sc->sc_powerstate &
36180214041Ssato 				(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
362659f65e0Such 
363659f65e0Such 	if (updates & PWRSTAT_BACKLIGHT)
364659f65e0Such 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
365659f65e0Such 		    CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
36680214041Ssato 		    (void*)(!(sc->sc_powerstate &
36780214041Ssato 				(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
368659f65e0Such 			     (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
369659f65e0Such }
370659f65e0Such 
371f928eeabStsutsui static bool
bivideo_suspend(device_t self,const pmf_qual_t * qual)372f928eeabStsutsui bivideo_suspend(device_t self, const pmf_qual_t *qual)
373f928eeabStsutsui {
374f928eeabStsutsui 	struct bivideo_softc *sc = device_private(self);
375f928eeabStsutsui 
376f928eeabStsutsui 	bivideo_power(PWR_SUSPEND, sc);
377f928eeabStsutsui 	return true;
378f928eeabStsutsui }
379f928eeabStsutsui 
380f928eeabStsutsui static bool
bivideo_resume(device_t self,const pmf_qual_t * qual)381f928eeabStsutsui bivideo_resume(device_t self, const pmf_qual_t *qual)
382f928eeabStsutsui {
383f928eeabStsutsui 	struct bivideo_softc *sc = device_private(self);
384f928eeabStsutsui 
385f928eeabStsutsui 	bivideo_power(PWR_RESUME, sc);
386f928eeabStsutsui 	return true;
387f928eeabStsutsui }
388f928eeabStsutsui 
389659f65e0Such int
bivideo_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)39053524e44Schristos bivideo_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
391659f65e0Such {
392659f65e0Such 	struct bivideo_softc *sc = (struct bivideo_softc *)v;
393659f65e0Such 	struct hpcfb_fbconf *fbconf;
394659f65e0Such 	struct hpcfb_dspconf *dspconf;
395659f65e0Such 	struct wsdisplay_cmap *cmap;
396659f65e0Such 	struct wsdisplay_param *dispparam;
397e07f0b93Schs 	int error;
398659f65e0Such 
399659f65e0Such 	switch (cmd) {
400659f65e0Such 	case WSDISPLAYIO_GETCMAP:
401659f65e0Such 		cmap = (struct wsdisplay_cmap *)data;
402659f65e0Such 
403659f65e0Such 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
404659f65e0Such 		    sc->sc_fbconf.hf_pack_width != 8 ||
4054b70fd12Sspz 		    cmap->index >= 256 ||
4064b70fd12Sspz 		    cmap->count > 256 - cmap->index)
407659f65e0Such 			return (EINVAL);
408659f65e0Such 
409e07f0b93Schs 		error = copyout(&bivideo_cmap_r[cmap->index], cmap->red,
410e07f0b93Schs 				cmap->count);
411e07f0b93Schs 		if (error)
412e07f0b93Schs 			return error;
413e07f0b93Schs 		error = copyout(&bivideo_cmap_g[cmap->index], cmap->green,
414e07f0b93Schs 				cmap->count);
415e07f0b93Schs 		if (error)
416e07f0b93Schs 			return error;
417e07f0b93Schs 		error = copyout(&bivideo_cmap_b[cmap->index], cmap->blue,
418e07f0b93Schs 				cmap->count);
419e07f0b93Schs 		return error;
420659f65e0Such 
421659f65e0Such 	case WSDISPLAYIO_PUTCMAP:
422659f65e0Such 		/*
423659f65e0Such 		 * This driver can't set color map.
424659f65e0Such 		 */
425659f65e0Such 		return (EINVAL);
426659f65e0Such 
42780214041Ssato 	case WSDISPLAYIO_SVIDEO:
42880214041Ssato 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
42980214041Ssato 			sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
43080214041Ssato 		else
43180214041Ssato 			sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
43280214041Ssato 		bivideo_update_powerstate(sc, PWRSTAT_ALL);
43380214041Ssato 		return 0;
43480214041Ssato 
43580214041Ssato 	case WSDISPLAYIO_GVIDEO:
43680214041Ssato 		*(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
43780214041Ssato 				WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
43880214041Ssato 		return 0;
43980214041Ssato 
440b8e5bc56Ssato 
441659f65e0Such 	case WSDISPLAYIO_GETPARAM:
442659f65e0Such 		dispparam = (struct wsdisplay_param*)data;
443659f65e0Such 		switch (dispparam->param) {
444659f65e0Such 		case WSDISPLAYIO_PARAM_BACKLIGHT:
4456c5da9bdSsato 			VPRINTF(("bivideo_ioctl: GET:BACKLIGHT\n"));
4466c5da9bdSsato 			bivideo_init_brightness(sc, 0);
4476c5da9bdSsato 			bivideo_init_backlight(sc, 0);
4486c5da9bdSsato 			VPRINTF(("bivideo_ioctl: GET:(real)BACKLIGHT %d\n",
4496c5da9bdSsato 				 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0));
450659f65e0Such 			dispparam->min = 0;
451659f65e0Such 			dispparam->max = 1;
452b8e5bc56Ssato 			if (sc->sc_max_brightness > 0)
453b8e5bc56Ssato 				dispparam->curval = sc->sc_brightness > 0? 1: 0;
454b8e5bc56Ssato 			else
455659f65e0Such 				dispparam->curval =
456659f65e0Such 				    (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0;
4576c5da9bdSsato 			VPRINTF(("bivideo_ioctl: GET:BACKLIGHT:%d(%s)\n",
4586c5da9bdSsato 				dispparam->curval,
4596c5da9bdSsato 				sc->sc_max_brightness > 0? "brightness": "light"));
460b8e5bc56Ssato 			return 0;
461659f65e0Such 			break;
462659f65e0Such 		case WSDISPLAYIO_PARAM_CONTRAST:
4636c5da9bdSsato 			VPRINTF(("bivideo_ioctl: GET:CONTRAST\n"));
4646c5da9bdSsato 			bivideo_init_contrast(sc, 0);
465b8e5bc56Ssato 			if (sc->sc_max_contrast > 0) {
466b8e5bc56Ssato 				dispparam->min = 0;
467b8e5bc56Ssato 				dispparam->max = sc->sc_max_contrast;
468b8e5bc56Ssato 				dispparam->curval = sc->sc_contrast;
4696c5da9bdSsato 				VPRINTF(("bivideo_ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast));
470b8e5bc56Ssato 				return 0;
471b8e5bc56Ssato 			} else {
4726c5da9bdSsato 				VPRINTF(("bivideo_ioctl: GET:CONTRAST EINVAL\n"));
473659f65e0Such 				return (EINVAL);
474b8e5bc56Ssato 			}
475b8e5bc56Ssato 			break;
476659f65e0Such 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
4776c5da9bdSsato 			VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS\n"));
4786c5da9bdSsato 			bivideo_init_brightness(sc, 0);
479b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) {
480b8e5bc56Ssato 				dispparam->min = 0;
481b8e5bc56Ssato 				dispparam->max = sc->sc_max_brightness;
482b8e5bc56Ssato 				dispparam->curval = sc->sc_brightness;
4836c5da9bdSsato 				VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness));
484b8e5bc56Ssato 				return 0;
485b8e5bc56Ssato 			} else {
4866c5da9bdSsato 				VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS EINVAL\n"));
487b8e5bc56Ssato 				return (EINVAL);
488b8e5bc56Ssato 			}
489659f65e0Such 			return (EINVAL);
490659f65e0Such 		default:
491659f65e0Such 			return (EINVAL);
492659f65e0Such 		}
493659f65e0Such 		return (0);
494659f65e0Such 
495659f65e0Such 	case WSDISPLAYIO_SETPARAM:
496659f65e0Such 		dispparam = (struct wsdisplay_param*)data;
497659f65e0Such 		switch (dispparam->param) {
498659f65e0Such 		case WSDISPLAYIO_PARAM_BACKLIGHT:
4996c5da9bdSsato 			VPRINTF(("bivideo_ioctl: SET:BACKLIGHT\n"));
500659f65e0Such 			if (dispparam->curval < 0 ||
501659f65e0Such 			    1 < dispparam->curval)
502659f65e0Such 				return (EINVAL);
5036c5da9bdSsato 			bivideo_init_brightness(sc, 0);
5046c5da9bdSsato 			VPRINTF(("bivideo_ioctl: SET:max brightness=%d\n", sc->sc_max_brightness));
505b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) { /* dimmer */
506b8e5bc56Ssato 				if (dispparam->curval == 0){
507b8e5bc56Ssato 					sc->sc_brightness_save = sc->sc_brightness;
508b8e5bc56Ssato 					bivideo_set_brightness(sc, 0);	/* min */
509b8e5bc56Ssato 				} else {
510b8e5bc56Ssato 					if (sc->sc_brightness_save == 0)
511b8e5bc56Ssato 						sc->sc_brightness_save = sc->sc_max_brightness;
512b8e5bc56Ssato 					bivideo_set_brightness(sc, sc->sc_brightness_save);
513b8e5bc56Ssato 				}
5146c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:brightness=%d\n", sc->sc_brightness));
515b8e5bc56Ssato 			} else { /* off */
516659f65e0Such 				if (dispparam->curval == 0)
517659f65e0Such 					sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
518659f65e0Such 				else
519659f65e0Such 					sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
5206c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:powerstate %d\n",
521b8e5bc56Ssato 						(sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
522659f65e0Such 				bivideo_update_powerstate(sc, PWRSTAT_BACKLIGHT);
5236c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:%d\n",
524659f65e0Such 					(sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
525b8e5bc56Ssato 			}
526b8e5bc56Ssato 			return 0;
527659f65e0Such 			break;
528659f65e0Such 		case WSDISPLAYIO_PARAM_CONTRAST:
5296c5da9bdSsato 			VPRINTF(("bivideo_ioctl: SET:CONTRAST\n"));
5306c5da9bdSsato 			bivideo_init_contrast(sc, 0);
531b8e5bc56Ssato 			if (dispparam->curval < 0 ||
532b8e5bc56Ssato 			    sc->sc_max_contrast < dispparam->curval)
533659f65e0Such 				return (EINVAL);
534b8e5bc56Ssato 			if (sc->sc_max_contrast > 0) {
5354072b525She #ifdef FBDEBUG
536b8e5bc56Ssato 				int org = sc->sc_contrast;
5374072b525She #endif
538b8e5bc56Ssato 				bivideo_set_contrast(sc, dispparam->curval);
5396c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast));
540b8e5bc56Ssato 				return 0;
541b8e5bc56Ssato 			} else {
5426c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:CONTRAST EINVAL\n"));
543b8e5bc56Ssato 				return (EINVAL);
544b8e5bc56Ssato 			}
545b8e5bc56Ssato 			break;
546659f65e0Such 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
5476c5da9bdSsato 			VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS\n"));
5486c5da9bdSsato 			bivideo_init_brightness(sc, 0);
549b8e5bc56Ssato 			if (dispparam->curval < 0 ||
550b8e5bc56Ssato 			    sc->sc_max_brightness < dispparam->curval)
551659f65e0Such 				return (EINVAL);
552b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) {
5534072b525She #ifdef FBDEBUG
554b8e5bc56Ssato 				int org = sc->sc_brightness;
5554072b525She #endif
556b8e5bc56Ssato 				bivideo_set_brightness(sc, dispparam->curval);
5576c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness));
558b8e5bc56Ssato 				return 0;
559b8e5bc56Ssato 			} else {
5606c5da9bdSsato 				VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS EINVAL\n"));
561b8e5bc56Ssato 				return (EINVAL);
562b8e5bc56Ssato 			}
563b8e5bc56Ssato 			break;
564659f65e0Such 		default:
565659f65e0Such 			return (EINVAL);
566659f65e0Such 		}
567659f65e0Such 		return (0);
568659f65e0Such 
569659f65e0Such 	case HPCFBIO_GCONF:
570659f65e0Such 		fbconf = (struct hpcfb_fbconf *)data;
571659f65e0Such 		if (fbconf->hf_conf_index != 0 &&
572659f65e0Such 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
573659f65e0Such 			return (EINVAL);
574659f65e0Such 		}
575659f65e0Such 		*fbconf = sc->sc_fbconf;	/* structure assignment */
576659f65e0Such 		return (0);
577659f65e0Such 	case HPCFBIO_SCONF:
578659f65e0Such 		fbconf = (struct hpcfb_fbconf *)data;
579659f65e0Such 		if (fbconf->hf_conf_index != 0 &&
580659f65e0Such 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
581659f65e0Such 			return (EINVAL);
582659f65e0Such 		}
583659f65e0Such 		/*
584964859d8Sabs 		 * nothing to do because we have only one configuration
585659f65e0Such 		 */
586659f65e0Such 		return (0);
587659f65e0Such 	case HPCFBIO_GDSPCONF:
588659f65e0Such 		dspconf = (struct hpcfb_dspconf *)data;
589659f65e0Such 		if ((dspconf->hd_unit_index != 0 &&
590659f65e0Such 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
591659f65e0Such 		    (dspconf->hd_conf_index != 0 &&
592659f65e0Such 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
593659f65e0Such 			return (EINVAL);
594659f65e0Such 		}
595659f65e0Such 		*dspconf = sc->sc_dspconf;	/* structure assignment */
596659f65e0Such 		return (0);
597659f65e0Such 	case HPCFBIO_SDSPCONF:
598659f65e0Such 		dspconf = (struct hpcfb_dspconf *)data;
599659f65e0Such 		if ((dspconf->hd_unit_index != 0 &&
600659f65e0Such 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
601659f65e0Such 		    (dspconf->hd_conf_index != 0 &&
602659f65e0Such 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
603659f65e0Such 			return (EINVAL);
604659f65e0Such 		}
605659f65e0Such 		/*
606659f65e0Such 		 * nothing to do
607964859d8Sabs 		 * because we have only one unit and one configuration
608659f65e0Such 		 */
609659f65e0Such 		return (0);
610659f65e0Such 	case HPCFBIO_GOP:
611659f65e0Such 	case HPCFBIO_SOP:
612659f65e0Such 		/*
613*86c30724Sandvar 		 * currently not implemented...
614659f65e0Such 		 */
615659f65e0Such 		return (EINVAL);
616659f65e0Such 	}
617659f65e0Such 
61831144d99Satatat 	return (EPASSTHROUGH);
619659f65e0Such }
620659f65e0Such 
621659f65e0Such paddr_t
bivideo_mmap(void * ctx,off_t offset,int prot)622edde743dSuch bivideo_mmap(void *ctx, off_t offset, int prot)
623659f65e0Such {
624659f65e0Such 	struct bivideo_softc *sc = (struct bivideo_softc *)ctx;
625659f65e0Such 
626659f65e0Such 	if (offset < 0 ||
627659f65e0Such 	    (sc->sc_fbconf.hf_bytes_per_plane +
628659f65e0Such 		sc->sc_fbconf.hf_offset) <  offset)
629659f65e0Such 		return -1;
630659f65e0Such 
631edde743dSuch 	return __BTOP((u_long)bootinfo->fb_addr + offset);
632659f65e0Such }
633b8e5bc56Ssato 
6346c5da9bdSsato 
635b8e5bc56Ssato void
bivideo_init_backlight(struct bivideo_softc * sc,int inattach)6366c5da9bdSsato bivideo_init_backlight(struct bivideo_softc *sc, int inattach)
637b8e5bc56Ssato {
638b8e5bc56Ssato 	int val = -1;
639b8e5bc56Ssato 
6406c5da9bdSsato 	if (sc->sc_lcd_inited&BACKLIGHT_INITED)
6416c5da9bdSsato 		return;
6426c5da9bdSsato 
643b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
644b8e5bc56Ssato 	     CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
6456c5da9bdSsato 		/* we can get real light state */
6466c5da9bdSsato 		VPRINTF(("bivideo_init_backlight: real backlight=%d\n", val));
647b8e5bc56Ssato 		if (val == 0)
648b8e5bc56Ssato 			sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
649b8e5bc56Ssato 		else
650b8e5bc56Ssato 			sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
6516c5da9bdSsato 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
6526c5da9bdSsato 	} else if (inattach) {
6536c5da9bdSsato 		/*
6546c5da9bdSsato 		   we cannot get real light state in attach time
6556c5da9bdSsato 		   because light device not yet attached.
6566c5da9bdSsato 		   we will retry in !inattach.
6576c5da9bdSsato 		   temporary assume light is on.
6586c5da9bdSsato 		 */
659ee1d25e7Ssato 		sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
6606c5da9bdSsato 	} else {
6616c5da9bdSsato 		/* we cannot get real light state, so work by myself state */
6626c5da9bdSsato 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
6636c5da9bdSsato 	}
664b8e5bc56Ssato }
665b8e5bc56Ssato 
666b8e5bc56Ssato void
bivideo_init_brightness(struct bivideo_softc * sc,int inattach)6676c5da9bdSsato bivideo_init_brightness(struct bivideo_softc *sc, int inattach)
668b8e5bc56Ssato {
669b8e5bc56Ssato 	int val = -1;
670b8e5bc56Ssato 
6716c5da9bdSsato 	if (sc->sc_lcd_inited&BRIGHTNESS_INITED)
6726c5da9bdSsato 		return;
6736c5da9bdSsato 
6746c5da9bdSsato 	VPRINTF(("bivideo_init_brightness\n"));
675b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
676b8e5bc56Ssato 	     CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
6776c5da9bdSsato 		/* we can get real brightness max */
6786c5da9bdSsato 		VPRINTF(("bivideo_init_brightness: real brightness max=%d\n", val));
679b8e5bc56Ssato 		sc->sc_max_brightness = val;
6806c5da9bdSsato 		val = -1;
6816c5da9bdSsato 		if (config_hook_call(CONFIG_HOOK_GET,
6826c5da9bdSsato 		     CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
6836c5da9bdSsato 			/* we can get real brightness */
6846c5da9bdSsato 			VPRINTF(("bivideo_init_brightness: real brightness=%d\n", val));
6856c5da9bdSsato 			sc->sc_brightness_save = sc->sc_brightness = val;
6866c5da9bdSsato 		} else {
6876c5da9bdSsato 			sc->sc_brightness_save =
6886c5da9bdSsato 			sc->sc_brightness = sc->sc_max_brightness;
689b8e5bc56Ssato 		}
6906c5da9bdSsato 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
6916c5da9bdSsato 	} else if (inattach) {
6926c5da9bdSsato 		/*
6936c5da9bdSsato 		   we cannot get real brightness in attach time
6946c5da9bdSsato 		   because brightness device not yet attached.
6956c5da9bdSsato 		   we will retry in !inattach.
6966c5da9bdSsato 		 */
6976c5da9bdSsato 		sc->sc_max_brightness = -1;
6986c5da9bdSsato 		sc->sc_brightness = -1;
6996c5da9bdSsato 		sc->sc_brightness_save = -1;
7006c5da9bdSsato 	} else {
7016c5da9bdSsato 		/* we cannot get real brightness */
7026c5da9bdSsato 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
7036c5da9bdSsato 	}
7046c5da9bdSsato 
705b8e5bc56Ssato 	return;
706b8e5bc56Ssato }
707b8e5bc56Ssato 
708b8e5bc56Ssato void
bivideo_init_contrast(struct bivideo_softc * sc,int inattach)7096c5da9bdSsato bivideo_init_contrast(struct bivideo_softc *sc, int inattach)
710b8e5bc56Ssato {
711b8e5bc56Ssato 	int val = -1;
712b8e5bc56Ssato 
7136c5da9bdSsato 	if (sc->sc_lcd_inited&CONTRAST_INITED)
7146c5da9bdSsato 		return;
7156c5da9bdSsato 
7166c5da9bdSsato 	VPRINTF(("bivideo_init_contrast\n"));
717b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
718b8e5bc56Ssato 	     CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
7196c5da9bdSsato 		/* we can get real contrast max */
7206c5da9bdSsato 		VPRINTF(("bivideo_init_contrast: real contrast max=%d\n", val));
721b8e5bc56Ssato 		sc->sc_max_contrast = val;
7226c5da9bdSsato 		val = -1;
7236c5da9bdSsato 		if (config_hook_call(CONFIG_HOOK_GET,
7246c5da9bdSsato 		     CONFIG_HOOK_CONTRAST, &val) != -1) {
7256c5da9bdSsato 			/* we can get real contrast */
7266c5da9bdSsato 			VPRINTF(("bivideo_init_contrast: real contrast=%d\n", val));
7276c5da9bdSsato 			sc->sc_contrast = val;
7286c5da9bdSsato 		} else {
7296c5da9bdSsato 			sc->sc_contrast = sc->sc_max_contrast;
730b8e5bc56Ssato 		}
7316c5da9bdSsato 		sc->sc_lcd_inited |= CONTRAST_INITED;
7326c5da9bdSsato 	} else if (inattach) {
7336c5da9bdSsato 		/*
7346c5da9bdSsato 		   we cannot get real contrast in attach time
7356c5da9bdSsato 		   because contrast device not yet attached.
7366c5da9bdSsato 		   we will retry in !inattach.
7376c5da9bdSsato 		 */
7386c5da9bdSsato 		sc->sc_max_contrast = -1;
7396c5da9bdSsato 		sc->sc_contrast = -1;
7406c5da9bdSsato 	} else {
7416c5da9bdSsato 		/* we cannot get real contrast */
7426c5da9bdSsato 		sc->sc_lcd_inited |= CONTRAST_INITED;
7436c5da9bdSsato 	}
7446c5da9bdSsato 
745b8e5bc56Ssato 	return;
746b8e5bc56Ssato }
747b8e5bc56Ssato 
748b8e5bc56Ssato void
bivideo_set_brightness(struct bivideo_softc * sc,int val)749b8e5bc56Ssato bivideo_set_brightness(struct bivideo_softc *sc, int val)
750b8e5bc56Ssato {
751b8e5bc56Ssato 	sc->sc_brightness = val;
752b8e5bc56Ssato 
753b8e5bc56Ssato 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
754b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
755b8e5bc56Ssato 	     CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
756b8e5bc56Ssato 		sc->sc_brightness = val;
757b8e5bc56Ssato 	}
758b8e5bc56Ssato }
759b8e5bc56Ssato 
760b8e5bc56Ssato void
bivideo_set_contrast(struct bivideo_softc * sc,int val)761b8e5bc56Ssato bivideo_set_contrast(struct bivideo_softc *sc, int val)
762b8e5bc56Ssato {
763b8e5bc56Ssato 	sc->sc_contrast = val;
764b8e5bc56Ssato 
765b8e5bc56Ssato 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
766b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
767b8e5bc56Ssato 	     CONFIG_HOOK_CONTRAST, &val) != -1) {
768b8e5bc56Ssato 		sc->sc_contrast = val;
769b8e5bc56Ssato 	}
770b8e5bc56Ssato }
771