xref: /netbsd-src/sys/arch/hpcmips/dev/mq200.c (revision 9fc7748df384d0aa4517cdf63759daf4262ccba0)
1*9fc7748dSandvar /*	$NetBSD: mq200.c,v 1.36 2022/05/28 15:57:18 andvar Exp $	*/
2733c0414Stakemura 
3733c0414Stakemura /*-
444e4c533Stakemura  * Copyright (c) 2000, 2001 TAKEMURA Shin
5733c0414Stakemura  * All rights reserved.
6733c0414Stakemura  *
7733c0414Stakemura  * Redistribution and use in source and binary forms, with or without
8733c0414Stakemura  * modification, are permitted provided that the following conditions
9733c0414Stakemura  * are met:
10733c0414Stakemura  * 1. Redistributions of source code must retain the above copyright
11733c0414Stakemura  *    notice, this list of conditions and the following disclaimer.
12733c0414Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
13733c0414Stakemura  *    notice, this list of conditions and the following disclaimer in the
14733c0414Stakemura  *    documentation and/or other materials provided with the distribution.
15733c0414Stakemura  * 3. The name of the author may not be used to endorse or promote products
16733c0414Stakemura  *    derived from this software without specific prior written permission.
17733c0414Stakemura  *
18733c0414Stakemura  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19733c0414Stakemura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20733c0414Stakemura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21733c0414Stakemura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22733c0414Stakemura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23733c0414Stakemura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24733c0414Stakemura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25733c0414Stakemura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26733c0414Stakemura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27733c0414Stakemura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28733c0414Stakemura  * SUCH DAMAGE.
29733c0414Stakemura  *
30733c0414Stakemura  */
31733c0414Stakemura 
320c82163cSlukem #include <sys/cdefs.h>
33*9fc7748dSandvar __KERNEL_RCSID(0, "$NetBSD: mq200.c,v 1.36 2022/05/28 15:57:18 andvar Exp $");
340c82163cSlukem 
35733c0414Stakemura #include <sys/param.h>
3696b3e925Smatt #include <sys/bus.h>
37733c0414Stakemura #include <sys/device.h>
3896b3e925Smatt #include <sys/kernel.h>
39733c0414Stakemura #include <sys/systm.h>
4059de1603Ssato #include <sys/reboot.h>
41733c0414Stakemura 
42733c0414Stakemura #include <uvm/uvm_extern.h>
43733c0414Stakemura 
44733c0414Stakemura #include <dev/wscons/wsconsio.h>
45733c0414Stakemura 
4696b3e925Smatt #include <mips/locore.h>
4796b3e925Smatt 
48733c0414Stakemura #include <machine/bootinfo.h>
49733c0414Stakemura #include <machine/autoconf.h>
50733c0414Stakemura #include <machine/config_hook.h>
51733c0414Stakemura #include <machine/platid.h>
52733c0414Stakemura #include <machine/platid_mask.h>
53733c0414Stakemura 
5444e4c533Stakemura #include "opt_mq200.h"
55733c0414Stakemura #include <hpcmips/dev/mq200reg.h>
56733c0414Stakemura #include <hpcmips/dev/mq200var.h>
5744e4c533Stakemura #include <hpcmips/dev/mq200priv.h>
5844e4c533Stakemura 
5959de1603Ssato #include "bivideo.h"
6059de1603Ssato #if NBIVIDEO > 0
61659f65e0Such #include <dev/hpc/bivideovar.h>
6259de1603Ssato #endif
63733c0414Stakemura 
64733c0414Stakemura /*
65733c0414Stakemura  * function prototypes
66733c0414Stakemura  */
67961880b5Such static void	mq200_power(int, void *);
68961880b5Such static int	mq200_hardpower(void *, int, long, void *);
69961880b5Such static int	mq200_fbinit(struct hpcfb_fbconf *);
7053524e44Schristos static int	mq200_ioctl(void *, u_long, void *, int, struct lwp *);
71961880b5Such static paddr_t	mq200_mmap(void *, off_t offset, int);
72961880b5Such static void	mq200_update_powerstate(struct mq200_softc *, int);
73961880b5Such void	mq200_init_backlight(struct mq200_softc *, int);
74961880b5Such void	mq200_init_brightness(struct mq200_softc *, int);
75961880b5Such void	mq200_init_contrast(struct mq200_softc *, int);
76961880b5Such void	mq200_set_brightness(struct mq200_softc *, int);
77961880b5Such void	mq200_set_contrast(struct mq200_softc *, int);
78733c0414Stakemura 
79733c0414Stakemura /*
80733c0414Stakemura  * static variables
81733c0414Stakemura  */
82733c0414Stakemura struct hpcfb_accessops mq200_ha = {
83733c0414Stakemura 	mq200_ioctl, mq200_mmap
84733c0414Stakemura };
85733c0414Stakemura 
8644e4c533Stakemura #ifdef MQ200_DEBUG
8744e4c533Stakemura int mq200_debug = MQ200DEBUG_CONF;
8844e4c533Stakemura #endif
8944e4c533Stakemura 
90733c0414Stakemura int
mq200_probe(bus_space_tag_t iot,bus_space_handle_t ioh)91961880b5Such mq200_probe(bus_space_tag_t iot, bus_space_handle_t ioh)
92733c0414Stakemura {
93733c0414Stakemura 	unsigned long regval;
94733c0414Stakemura 
9559de1603Ssato #if NBIVIDEO > 0
9659de1603Ssato 	if (bivideo_dont_attach) /* some video driver already attached */
9759de1603Ssato 		return (0);
9859de1603Ssato #endif /* NBIVIDEO > 0 */
9959de1603Ssato 
100733c0414Stakemura 	regval = bus_space_read_4(iot, ioh, MQ200_PC00R);
10144e4c533Stakemura 	VPRINTF("probe: vendor id=%04lx product id=%04lx\n",
10244e4c533Stakemura 	    regval & 0xffff, (regval >> 16) & 0xffff);
103733c0414Stakemura 	if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID))
104733c0414Stakemura 		return (0);
105733c0414Stakemura 
106733c0414Stakemura 	return (1);
107733c0414Stakemura }
108733c0414Stakemura 
109733c0414Stakemura void
mq200_attach(struct mq200_softc * sc)110961880b5Such mq200_attach(struct mq200_softc *sc)
111733c0414Stakemura {
112733c0414Stakemura 	unsigned long regval;
113733c0414Stakemura 	struct hpcfb_attach_args ha;
114733c0414Stakemura 	int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
115733c0414Stakemura 
1166602ad15Ssato 	printf(": ");
1176602ad15Ssato 	if (mq200_fbinit(&sc->sc_fbconf) != 0) {
1186602ad15Ssato 		/* just return so that hpcfb will not be attached */
1196602ad15Ssato 		return;
1206602ad15Ssato 	}
1216602ad15Ssato 
1226602ad15Ssato 	sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr;
1236602ad15Ssato 	sc->sc_fbconf.hf_offset	= (u_long)sc->sc_fbconf.hf_baseaddr -
1246602ad15Ssato 	    MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr)));
12544e4c533Stakemura 	DPRINTF("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr);
12644e4c533Stakemura 	DPRINTF("hf_offset=%lx\n", sc->sc_fbconf.hf_offset);
1276602ad15Ssato 
12844e4c533Stakemura 	regval = mq200_read(sc, MQ200_PC08R);
1296602ad15Ssato 	printf("MQ200 Rev.%02lx video controller", regval & 0xff);
1306602ad15Ssato 	if (console) {
1316602ad15Ssato 		printf(", console");
1326602ad15Ssato 	}
1336602ad15Ssato 	printf("\n");
1346602ad15Ssato         printf("%s: framebuffer address: 0x%08lx\n",
135cbab9cadSchs 	    device_xname(sc->sc_dev), (u_long)bootinfo->fb_addr);
136733c0414Stakemura 
13744e4c533Stakemura 	/*
13844e4c533Stakemura 	 * setup registers
13944e4c533Stakemura 	 */
14044e4c533Stakemura 	sc->sc_flags = 0;
14144e4c533Stakemura 	sc->sc_baseclock = 12288;	/* 12.288 MHz */
14244e4c533Stakemura #ifdef MQ200_DEBUG
14344e4c533Stakemura 	if (bootverbose) {
14444e4c533Stakemura 		/* dump current setting	*/
14544e4c533Stakemura 		mq200_dump_all(sc);
14644e4c533Stakemura 		mq200_dump_pll(sc);
14744e4c533Stakemura 	}
14844e4c533Stakemura #endif
14944e4c533Stakemura 	mq200_setup_regctx(sc);
15044e4c533Stakemura 	mq200_mdsetup(sc);
15144e4c533Stakemura 	if (sc->sc_md) {
152ab452aefStakemura 		int mode;
153ab452aefStakemura 
154ab452aefStakemura 		switch (sc->sc_fbconf.hf_pixel_width) {
155ab452aefStakemura 		case  1:	mode = MQ200_GCC_1BPP;		break;
156ab452aefStakemura 		case  2:	mode = MQ200_GCC_2BPP;		break;
157ab452aefStakemura 		case  4:	mode = MQ200_GCC_4BPP;		break;
158ab452aefStakemura 		case  8:	mode = MQ200_GCC_8BPP;		break;
159ab452aefStakemura 		case 16:	mode = MQ200_GCC_16BPP_DIRECT;	break;
160ab452aefStakemura 		default:
161ab452aefStakemura 			printf("%s: %dbpp isn't supported\n",
162cbab9cadSchs 			    device_xname(sc->sc_dev), sc->sc_fbconf.hf_pixel_width);
163ab452aefStakemura 			return;
164ab452aefStakemura 		}
165ab452aefStakemura 
16644e4c533Stakemura 		if (sc->sc_md->md_flags & MQ200_MD_HAVEFP) {
16744e4c533Stakemura 			sc->sc_flags |= MQ200_SC_GC2_ENABLE;	/* FP	*/
16844e4c533Stakemura 		}
16944e4c533Stakemura #if MQ200_USECRT
17044e4c533Stakemura 		if (sc->sc_md->md_flags & MQ200_MD_HAVECRT) {
17144e4c533Stakemura 			int i;
17244e4c533Stakemura 			sc->sc_flags |= MQ200_SC_GC1_ENABLE;	/* CRT	*/
17344e4c533Stakemura 			for (i = 0; i < mq200_crt_nparams; i++) {
17444e4c533Stakemura 				sc->sc_crt = &mq200_crt_params[i];
17544e4c533Stakemura 				if (sc->sc_md->md_fp_width <=
17644e4c533Stakemura 				    mq200_crt_params[i].width &&
17744e4c533Stakemura 				    sc->sc_md->md_fp_height <=
17844e4c533Stakemura 				    mq200_crt_params[i].height)
17944e4c533Stakemura 					break;
18044e4c533Stakemura 			}
18144e4c533Stakemura 		}
18244e4c533Stakemura #endif
18344e4c533Stakemura 		mq200_setup(sc);
18444e4c533Stakemura 
18544e4c533Stakemura 		if (sc->sc_flags & MQ200_SC_GC2_ENABLE)	/* FP	*/
186ab452aefStakemura 			mq200_win_enable(sc, MQ200_GC2, mode,
187ab452aefStakemura 			    sc->sc_fbconf.hf_baseaddr,
188ab452aefStakemura 			    sc->sc_fbconf.hf_width, sc->sc_fbconf.hf_height,
189ab452aefStakemura 			    sc->sc_fbconf.hf_bytes_per_plane);
19044e4c533Stakemura 		if (sc->sc_flags & MQ200_SC_GC1_ENABLE)	/* CRT	*/
191ab452aefStakemura 			mq200_win_enable(sc, MQ200_GC1, mode,
192ab452aefStakemura 			    sc->sc_fbconf.hf_baseaddr,
193ab452aefStakemura 			    sc->sc_fbconf.hf_width, sc->sc_fbconf.hf_height,
194ab452aefStakemura 			    sc->sc_fbconf.hf_bytes_per_plane);
19544e4c533Stakemura 	}
19644e4c533Stakemura #ifdef MQ200_DEBUG
19744e4c533Stakemura 	if (sc->sc_md == NULL || bootverbose) {
19844e4c533Stakemura 		mq200_dump_pll(sc);
19944e4c533Stakemura 	}
20044e4c533Stakemura #endif
20144e4c533Stakemura 
202733c0414Stakemura 	/* Add a power hook to power saving */
203b8e5bc56Ssato 	sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
204cbab9cadSchs 	sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev),
205f135e0d6Sjmcneill 	    mq200_power, sc);
206733c0414Stakemura 	if (sc->sc_powerhook == NULL)
207733c0414Stakemura 		printf("%s: WARNING: unable to establish power hook\n",
208cbab9cadSchs 		    device_xname(sc->sc_dev));
209733c0414Stakemura 
210733c0414Stakemura 	/* Add a hard power hook to power saving */
211733c0414Stakemura 	sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT,
212733c0414Stakemura 	    CONFIG_HOOK_PMEVENT_HARDPOWER,
213733c0414Stakemura 	    CONFIG_HOOK_SHARE,
214733c0414Stakemura 	    mq200_hardpower, sc);
215733c0414Stakemura 	if (sc->sc_hardpowerhook == NULL)
216733c0414Stakemura 		printf("%s: WARNING: unable to establish hard power hook\n",
217cbab9cadSchs 		    device_xname(sc->sc_dev));
218733c0414Stakemura 
219b8e5bc56Ssato 	/* initialize backlight brightness and lcd contrast */
2206c5da9bdSsato 	sc->sc_lcd_inited = 0;
2216c5da9bdSsato 	mq200_init_brightness(sc, 1);
2226c5da9bdSsato 	mq200_init_contrast(sc, 1);
2236c5da9bdSsato 	mq200_init_backlight(sc, 1);
224b8e5bc56Ssato 
225733c0414Stakemura 	if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
226733c0414Stakemura 		panic("mq200_attach: can't init fb console");
227733c0414Stakemura 	}
228733c0414Stakemura 
229733c0414Stakemura 	ha.ha_console = console;
230733c0414Stakemura 	ha.ha_accessops = &mq200_ha;
231733c0414Stakemura 	ha.ha_accessctx = sc;
232733c0414Stakemura 	ha.ha_curfbconf = 0;
233733c0414Stakemura 	ha.ha_nfbconf = 1;
234733c0414Stakemura 	ha.ha_fbconflist = &sc->sc_fbconf;
235733c0414Stakemura 	ha.ha_curdspconf = 0;
236733c0414Stakemura 	ha.ha_ndspconf = 1;
237733c0414Stakemura 	ha.ha_dspconflist = &sc->sc_dspconf;
238733c0414Stakemura 
239c7fb772bSthorpej 	config_found(sc->sc_dev, &ha, hpcfbprint, CFARGS_NONE);
240733c0414Stakemura 
24159de1603Ssato #if NBIVIDEO > 0
242733c0414Stakemura 	/*
243733c0414Stakemura 	 * bivideo is no longer need
244733c0414Stakemura 	 */
245733c0414Stakemura 	bivideo_dont_attach = 1;
24659de1603Ssato #endif /* NBIVIDEO > 0 */
247733c0414Stakemura }
248733c0414Stakemura 
249733c0414Stakemura static void
mq200_update_powerstate(struct mq200_softc * sc,int updates)250961880b5Such mq200_update_powerstate(struct mq200_softc *sc, int updates)
251b8e5bc56Ssato {
252ee1d25e7Ssato 
253b8e5bc56Ssato 	if (updates & PWRSTAT_LCD)
254b8e5bc56Ssato 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
255b8e5bc56Ssato 		    CONFIG_HOOK_POWERCONTROL_LCD,
25680214041Ssato 		    (void*)!(sc->sc_powerstate &
25780214041Ssato 			(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
258b8e5bc56Ssato 
259b8e5bc56Ssato 	if (updates & PWRSTAT_BACKLIGHT)
260b8e5bc56Ssato 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
261b8e5bc56Ssato 		    CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
26280214041Ssato 		    (void*)(!(sc->sc_powerstate &
26380214041Ssato 			(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
264b8e5bc56Ssato 			(sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
265b8e5bc56Ssato }
266b8e5bc56Ssato 
267b8e5bc56Ssato static void
mq200_power(int why,void * arg)268961880b5Such mq200_power(int why, void *arg)
269733c0414Stakemura {
270733c0414Stakemura 	struct mq200_softc *sc = arg;
271733c0414Stakemura 
272733c0414Stakemura 	switch (why) {
273733c0414Stakemura 	case PWR_SUSPEND:
274b8e5bc56Ssato 		sc->sc_powerstate |= PWRSTAT_SUSPEND;
275b8e5bc56Ssato 		mq200_update_powerstate(sc, PWRSTAT_ALL);
276733c0414Stakemura 		break;
277733c0414Stakemura 	case PWR_STANDBY:
278b8e5bc56Ssato 		sc->sc_powerstate |= PWRSTAT_SUSPEND;
279b8e5bc56Ssato 		mq200_update_powerstate(sc, PWRSTAT_ALL);
280733c0414Stakemura 		break;
281733c0414Stakemura 	case PWR_RESUME:
282b8e5bc56Ssato 		sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
283b8e5bc56Ssato 		mq200_update_powerstate(sc, PWRSTAT_ALL);
284733c0414Stakemura 		break;
285733c0414Stakemura 	}
286733c0414Stakemura }
287733c0414Stakemura 
288733c0414Stakemura static int
mq200_hardpower(void * ctx,int type,long id,void * msg)289961880b5Such mq200_hardpower(void *ctx, int type, long id, void *msg)
290733c0414Stakemura {
291733c0414Stakemura 	struct mq200_softc *sc = ctx;
292733c0414Stakemura 	int why = (int)msg;
293733c0414Stakemura 
294733c0414Stakemura 	switch (why) {
295733c0414Stakemura 	case PWR_SUSPEND:
296b8e5bc56Ssato 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
297733c0414Stakemura 		break;
298733c0414Stakemura 	case PWR_STANDBY:
299b8e5bc56Ssato 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
300733c0414Stakemura 		break;
301733c0414Stakemura 	case PWR_RESUME:
302b8e5bc56Ssato 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
303733c0414Stakemura 		break;
304733c0414Stakemura 	}
305733c0414Stakemura 
306733c0414Stakemura 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
307b8e5bc56Ssato 	    MQ200_PMCSR, sc->sc_mq200pwstate);
308733c0414Stakemura 
309733c0414Stakemura 	/*
310733c0414Stakemura 	 * you should wait until the
311733c0414Stakemura 	 * power state transit sequence will end.
312733c0414Stakemura 	 */
313733c0414Stakemura 	{
314733c0414Stakemura 		unsigned long tmp;
315733c0414Stakemura 		do {
316733c0414Stakemura 			tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
317733c0414Stakemura 			    MQ200_PMCSR);
318b8e5bc56Ssato 		} while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3));
319733c0414Stakemura 		delay(100000); /* XXX */
320733c0414Stakemura 	}
321733c0414Stakemura 
322733c0414Stakemura 	return (0);
323733c0414Stakemura }
324733c0414Stakemura 
325733c0414Stakemura 
326733c0414Stakemura static int
mq200_fbinit(struct hpcfb_fbconf * fb)327961880b5Such mq200_fbinit(struct hpcfb_fbconf *fb)
328733c0414Stakemura {
329733c0414Stakemura 
330733c0414Stakemura 	/*
331733c0414Stakemura 	 * get fb settings from bootinfo
332733c0414Stakemura 	 */
333733c0414Stakemura 	if (bootinfo == NULL ||
334733c0414Stakemura 	    bootinfo->fb_addr == 0 ||
335733c0414Stakemura 	    bootinfo->fb_line_bytes == 0 ||
336733c0414Stakemura 	    bootinfo->fb_width == 0 ||
337733c0414Stakemura 	    bootinfo->fb_height == 0) {
338e267c67bStoshii 		printf("no frame buffer information.\n");
339733c0414Stakemura 		return (-1);
340733c0414Stakemura 	}
341733c0414Stakemura 
342733c0414Stakemura 	/* zero fill */
343c363a9cbScegger 	memset(fb, 0, sizeof(*fb));
344733c0414Stakemura 
345733c0414Stakemura 	fb->hf_conf_index	= 0;	/* configuration index		*/
346733c0414Stakemura 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
347733c0414Stakemura 	strcpy(fb->hf_name, "built-in video");
348733c0414Stakemura 					/* frame buffer name		*/
349733c0414Stakemura 	strcpy(fb->hf_conf_name, "default");
350733c0414Stakemura 					/* configuration name		*/
351733c0414Stakemura 	fb->hf_height		= bootinfo->fb_height;
352733c0414Stakemura 	fb->hf_width		= bootinfo->fb_width;
353733c0414Stakemura 	fb->hf_baseaddr		= mips_ptob(mips_btop(bootinfo->fb_addr));
354733c0414Stakemura 	fb->hf_offset		= (u_long)bootinfo->fb_addr - fb->hf_baseaddr;
355733c0414Stakemura 					/* frame buffer start offset   	*/
356733c0414Stakemura 	fb->hf_bytes_per_line	= bootinfo->fb_line_bytes;
357733c0414Stakemura 	fb->hf_nplanes		= 1;
358733c0414Stakemura 	fb->hf_bytes_per_plane	= bootinfo->fb_height *
359733c0414Stakemura 	    bootinfo->fb_line_bytes;
360733c0414Stakemura 
361733c0414Stakemura 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
362733c0414Stakemura 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
363733c0414Stakemura 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
364733c0414Stakemura 
365733c0414Stakemura 	switch (bootinfo->fb_type) {
366733c0414Stakemura 		/*
367ab452aefStakemura 		 * monochrome
368ab452aefStakemura 		 */
369ab452aefStakemura 	case BIFB_D1_M2L_1:
370ab452aefStakemura 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
371ab452aefStakemura 		/* fall through */
372ab452aefStakemura 	case BIFB_D1_M2L_0:
373ab452aefStakemura 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
374ab452aefStakemura 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
375ab452aefStakemura 		fb->hf_pack_width = 8;
376ab452aefStakemura 		fb->hf_pixels_per_pack = 8;
377ab452aefStakemura 		fb->hf_pixel_width = 1;
378ab452aefStakemura 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
379ab452aefStakemura 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
380ab452aefStakemura 		break;
381ab452aefStakemura 
382ab452aefStakemura 		/*
383733c0414Stakemura 		 * gray scale
384733c0414Stakemura 		 */
385733c0414Stakemura 	case BIFB_D2_M2L_3:
386733c0414Stakemura 	case BIFB_D2_M2L_3x2:
387733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
388733c0414Stakemura 		/* fall through */
389733c0414Stakemura 	case BIFB_D2_M2L_0:
390733c0414Stakemura 	case BIFB_D2_M2L_0x2:
391733c0414Stakemura 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
392733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
393733c0414Stakemura 		fb->hf_pack_width = 8;
394733c0414Stakemura 		fb->hf_pixels_per_pack = 4;
395733c0414Stakemura 		fb->hf_pixel_width = 2;
396733c0414Stakemura 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
397733c0414Stakemura 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
398733c0414Stakemura 		break;
399733c0414Stakemura 
4009aa8ab92Stakemura 	case BIFB_D4_M2L_F:
4019aa8ab92Stakemura 	case BIFB_D4_M2L_Fx2:
4029aa8ab92Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
4039aa8ab92Stakemura 		/* fall through */
4049aa8ab92Stakemura 	case BIFB_D4_M2L_0:
4059aa8ab92Stakemura 	case BIFB_D4_M2L_0x2:
4069aa8ab92Stakemura 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
4079aa8ab92Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
4089aa8ab92Stakemura 		fb->hf_pack_width = 8;
4099aa8ab92Stakemura 		fb->hf_pixels_per_pack = 2;
4109aa8ab92Stakemura 		fb->hf_pixel_width = 4;
4119aa8ab92Stakemura 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
4129aa8ab92Stakemura 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
4139aa8ab92Stakemura 		break;
4149aa8ab92Stakemura 
415733c0414Stakemura 		/*
416733c0414Stakemura 		 * indexed color
417733c0414Stakemura 		 */
418733c0414Stakemura 	case BIFB_D8_FF:
419733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
420733c0414Stakemura 		/* fall through */
421733c0414Stakemura 	case BIFB_D8_00:
422733c0414Stakemura 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
423733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
424733c0414Stakemura 		fb->hf_pack_width = 8;
425733c0414Stakemura 		fb->hf_pixels_per_pack = 1;
426733c0414Stakemura 		fb->hf_pixel_width = 8;
427733c0414Stakemura 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
428733c0414Stakemura 		fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
429733c0414Stakemura 		break;
430733c0414Stakemura 
431733c0414Stakemura 		/*
432733c0414Stakemura 		 * RGB color
433733c0414Stakemura 		 */
434733c0414Stakemura 	case BIFB_D16_FFFF:
435733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
436733c0414Stakemura 		/* fall through */
437733c0414Stakemura 	case BIFB_D16_0000:
438733c0414Stakemura 		fb->hf_class = HPCFB_CLASS_RGBCOLOR;
439733c0414Stakemura 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
44064b6b76aStakemura 		fb->hf_order_flags = HPCFB_REVORDER_BYTE;
441733c0414Stakemura 		fb->hf_pack_width = 16;
442733c0414Stakemura 		fb->hf_pixels_per_pack = 1;
443733c0414Stakemura 		fb->hf_pixel_width = 16;
444733c0414Stakemura 
445733c0414Stakemura 		fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
446733c0414Stakemura 		fb->hf_u.hf_rgb.hf_flags = 0;	/* reserved for future use */
447733c0414Stakemura 
448733c0414Stakemura 		fb->hf_u.hf_rgb.hf_red_width = 5;
449733c0414Stakemura 		fb->hf_u.hf_rgb.hf_red_shift = 11;
450733c0414Stakemura 		fb->hf_u.hf_rgb.hf_green_width = 6;
451733c0414Stakemura 		fb->hf_u.hf_rgb.hf_green_shift = 5;
452733c0414Stakemura 		fb->hf_u.hf_rgb.hf_blue_width = 5;
453733c0414Stakemura 		fb->hf_u.hf_rgb.hf_blue_shift = 0;
454733c0414Stakemura 		fb->hf_u.hf_rgb.hf_alpha_width = 0;
455733c0414Stakemura 		fb->hf_u.hf_rgb.hf_alpha_shift = 0;
456733c0414Stakemura 		break;
457733c0414Stakemura 
458733c0414Stakemura 	default:
459733c0414Stakemura 		printf("unknown type (=%d).\n", bootinfo->fb_type);
460733c0414Stakemura 		return (-1);
461733c0414Stakemura 		break;
462733c0414Stakemura 	}
463733c0414Stakemura 
464733c0414Stakemura 	return (0); /* no error */
465733c0414Stakemura }
466733c0414Stakemura 
467733c0414Stakemura int
mq200_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)46882357f6dSdsl mq200_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
469733c0414Stakemura {
470733c0414Stakemura 	struct mq200_softc *sc = (struct mq200_softc *)v;
471733c0414Stakemura 	struct hpcfb_fbconf *fbconf;
472733c0414Stakemura 	struct hpcfb_dspconf *dspconf;
473733c0414Stakemura 	struct wsdisplay_cmap *cmap;
47437682e54Ssato 	struct wsdisplay_param *dispparam;
475733c0414Stakemura 
476733c0414Stakemura 	switch (cmd) {
477733c0414Stakemura 	case WSDISPLAYIO_GETCMAP:
478733c0414Stakemura 		cmap = (struct wsdisplay_cmap *)data;
479733c0414Stakemura 
480733c0414Stakemura 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
481733c0414Stakemura 		    sc->sc_fbconf.hf_pack_width != 8 ||
482733c0414Stakemura 		    256 <= cmap->index ||
4838e7a88a3Sitojun 		    256 - cmap->index < cmap->count)
484733c0414Stakemura 			return (EINVAL);
485733c0414Stakemura 
486e07f0b93Schs 		/*
487e07f0b93Schs 		 * This driver can't get color map.
488e07f0b93Schs 		 */
489e07f0b93Schs 		return (EINVAL);
490733c0414Stakemura 
491733c0414Stakemura 	case WSDISPLAYIO_PUTCMAP:
492733c0414Stakemura 		/*
493733c0414Stakemura 		 * This driver can't set color map.
494733c0414Stakemura 		 */
495733c0414Stakemura 		return (EINVAL);
496733c0414Stakemura 
49780214041Ssato 	case WSDISPLAYIO_SVIDEO:
49880214041Ssato 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
49980214041Ssato 			sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
50080214041Ssato 		else
50180214041Ssato 			sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
50280214041Ssato 		mq200_update_powerstate(sc, PWRSTAT_ALL);
50380214041Ssato 		return 0;
50480214041Ssato 
50580214041Ssato 	case WSDISPLAYIO_GVIDEO:
50680214041Ssato 		*(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
50780214041Ssato 		    WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
50880214041Ssato 		return 0;
50980214041Ssato 
51037682e54Ssato 	case WSDISPLAYIO_GETPARAM:
51137682e54Ssato 		dispparam = (struct wsdisplay_param*)data;
51237682e54Ssato 		switch (dispparam->param) {
51337682e54Ssato 		case WSDISPLAYIO_PARAM_BACKLIGHT:
5146c5da9bdSsato 			VPRINTF("ioctl: GET:BACKLIGHT\n");
5156c5da9bdSsato 			mq200_init_brightness(sc, 0);
5166c5da9bdSsato 			mq200_init_backlight(sc, 0);
5176c5da9bdSsato 			VPRINTF("ioctl: GET:(real)BACKLIGHT %d\n",
5186c5da9bdSsato 			    (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0);
519b8e5bc56Ssato 			dispparam->min = 0;
520b8e5bc56Ssato 			dispparam->max = 1;
521b8e5bc56Ssato 			if (sc->sc_max_brightness > 0)
522961880b5Such 				dispparam->curval = sc->sc_brightness > 0
523961880b5Such 				    ? 1: 0;
524b8e5bc56Ssato 			else
525b8e5bc56Ssato 				dispparam->curval =
526961880b5Such 				    (sc->sc_powerstate&PWRSTAT_BACKLIGHT)
527961880b5Such 				    ? 1: 0;
5286c5da9bdSsato 			VPRINTF("ioctl: GET:BACKLIGHT:%d(%s)\n",
5296c5da9bdSsato 			    dispparam->curval,
5306c5da9bdSsato 			    sc->sc_max_brightness > 0? "brightness": "light");
531b8e5bc56Ssato 			return 0;
532b8e5bc56Ssato 			break;
53337682e54Ssato 		case WSDISPLAYIO_PARAM_CONTRAST:
5346c5da9bdSsato 			VPRINTF("ioctl: GET:CONTRAST\n");
5356c5da9bdSsato 			mq200_init_contrast(sc, 0);
536b8e5bc56Ssato 			if (sc->sc_max_contrast > 0) {
537b8e5bc56Ssato 				dispparam->min = 0;
538b8e5bc56Ssato 				dispparam->max = sc->sc_max_contrast;
539b8e5bc56Ssato 				dispparam->curval = sc->sc_contrast;
540961880b5Such 				VPRINTF("ioctl: GET:CONTRAST"
541961880b5Such 				    " max=%d, current=%d\n",
542961880b5Such 				    sc->sc_max_contrast, sc->sc_contrast);
543b8e5bc56Ssato 				return 0;
544b8e5bc56Ssato 			} else {
5456c5da9bdSsato 				VPRINTF("ioctl: GET:CONTRAST EINVAL\n");
54637682e54Ssato 				return (EINVAL);
547b8e5bc56Ssato 			}
548b8e5bc56Ssato 			break;
54937682e54Ssato 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
5506c5da9bdSsato 			VPRINTF("ioctl: GET:BRIGHTNESS\n");
5516c5da9bdSsato 			mq200_init_brightness(sc, 0);
552b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) {
553b8e5bc56Ssato 				dispparam->min = 0;
554b8e5bc56Ssato 				dispparam->max = sc->sc_max_brightness;
555b8e5bc56Ssato 				dispparam->curval = sc->sc_brightness;
556961880b5Such 				VPRINTF("ioctl: GET:BRIGHTNESS"
557961880b5Such 				    " max=%d, current=%d\n",
558961880b5Such 				    sc->sc_max_brightness, sc->sc_brightness);
559b8e5bc56Ssato 				return 0;
560b8e5bc56Ssato 			} else {
5616c5da9bdSsato 				VPRINTF("ioctl: GET:BRIGHTNESS EINVAL\n");
562b8e5bc56Ssato 				return (EINVAL);
563b8e5bc56Ssato 			}
56437682e54Ssato 			return (EINVAL);
56537682e54Ssato 		default:
56637682e54Ssato 			return (EINVAL);
56737682e54Ssato 		}
56837682e54Ssato 		return (0);
56937682e54Ssato 
57037682e54Ssato 	case WSDISPLAYIO_SETPARAM:
57137682e54Ssato 		dispparam = (struct wsdisplay_param*)data;
57237682e54Ssato 		switch (dispparam->param) {
57337682e54Ssato 		case WSDISPLAYIO_PARAM_BACKLIGHT:
5746c5da9bdSsato 			VPRINTF("ioctl: SET:BACKLIGHT\n");
575b8e5bc56Ssato 			if (dispparam->curval < 0 ||
576b8e5bc56Ssato 			    1 < dispparam->curval)
57737682e54Ssato 				return (EINVAL);
5786c5da9bdSsato 			mq200_init_brightness(sc, 0);
579961880b5Such 			VPRINTF("ioctl: SET:max brightness=%d\n",
580961880b5Such 			    sc->sc_max_brightness);
581b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) { /* dimmer */
582b8e5bc56Ssato 				if (dispparam->curval == 0){
583961880b5Such 					sc->sc_brightness_save =
584961880b5Such 					    sc->sc_brightness;
585b8e5bc56Ssato 					mq200_set_brightness(sc, 0); /* min */
586b8e5bc56Ssato 				} else {
587b8e5bc56Ssato 					if (sc->sc_brightness_save == 0)
588961880b5Such 						sc->sc_brightness_save =
589961880b5Such 						    sc->sc_max_brightness;
590961880b5Such 					mq200_set_brightness(sc,
591961880b5Such 					    sc->sc_brightness_save);
592b8e5bc56Ssato 				}
593961880b5Such 				VPRINTF("ioctl: SET:BACKLIGHT:"
594961880b5Such 				    " brightness=%d\n", sc->sc_brightness);
595b8e5bc56Ssato 			} else { /* off */
596b8e5bc56Ssato 				if (dispparam->curval == 0)
597b8e5bc56Ssato 					sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
598b8e5bc56Ssato 				else
599b8e5bc56Ssato 					sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
600961880b5Such 				VPRINTF("ioctl: SET:BACKLIGHT:"
601961880b5Such 				    " powerstate %d\n",
602961880b5Such 				    (sc->sc_powerstate & PWRSTAT_BACKLIGHT)
603961880b5Such 				    ? 1 : 0);
604b8e5bc56Ssato 				mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT);
6056c5da9bdSsato 				VPRINTF("ioctl: SET:BACKLIGHT:%d\n",
606961880b5Such 				    (sc->sc_powerstate & PWRSTAT_BACKLIGHT)
607961880b5Such 				    ? 1 : 0);
608b8e5bc56Ssato 			}
609b8e5bc56Ssato 			return 0;
610b8e5bc56Ssato 			break;
61137682e54Ssato 		case WSDISPLAYIO_PARAM_CONTRAST:
6126c5da9bdSsato 			VPRINTF("ioctl: SET:CONTRAST\n");
6136c5da9bdSsato 			mq200_init_contrast(sc, 0);
614b8e5bc56Ssato 			if (dispparam->curval < 0 ||
615b8e5bc56Ssato 			    sc->sc_max_contrast < dispparam->curval)
61637682e54Ssato 				return (EINVAL);
617b8e5bc56Ssato 			if (sc->sc_max_contrast > 0) {
618b8e5bc56Ssato 				int org = sc->sc_contrast;
619b8e5bc56Ssato 				mq200_set_contrast(sc, dispparam->curval);
620961880b5Such 				VPRINTF("ioctl: SET:CONTRAST"
621961880b5Such 				    " org=%d, current=%d\n", org,
622961880b5Such 				    sc->sc_contrast);
623961880b5Such 				VPRINTF("ioctl: SETPARAM:"
624961880b5Such 				    " CONTRAST org=%d, current=%d\n", org,
625961880b5Such 				    sc->sc_contrast);
626b8e5bc56Ssato 				return 0;
627b8e5bc56Ssato 			} else {
6286c5da9bdSsato 				VPRINTF("ioctl: SET:CONTRAST EINVAL\n");
629b8e5bc56Ssato 				return (EINVAL);
630b8e5bc56Ssato 			}
631b8e5bc56Ssato 			break;
63237682e54Ssato 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
6336c5da9bdSsato 			VPRINTF("ioctl: SET:BRIGHTNESS\n");
6346c5da9bdSsato 			mq200_init_brightness(sc, 0);
635b8e5bc56Ssato 			if (dispparam->curval < 0 ||
636b8e5bc56Ssato 			    sc->sc_max_brightness < dispparam->curval)
63737682e54Ssato 				return (EINVAL);
638b8e5bc56Ssato 			if (sc->sc_max_brightness > 0) {
639b8e5bc56Ssato 				int org = sc->sc_brightness;
640b8e5bc56Ssato 				mq200_set_brightness(sc, dispparam->curval);
641961880b5Such 				VPRINTF("ioctl: SET:BRIGHTNESS"
642961880b5Such 				    " org=%d, current=%d\n", org,
643961880b5Such 				    sc->sc_brightness);
644b8e5bc56Ssato 				return 0;
645b8e5bc56Ssato 			} else {
6466c5da9bdSsato 				VPRINTF("ioctl: SET:BRIGHTNESS EINVAL\n");
647b8e5bc56Ssato 				return (EINVAL);
648b8e5bc56Ssato 			}
649b8e5bc56Ssato 			break;
65037682e54Ssato 		default:
65137682e54Ssato 			return (EINVAL);
65237682e54Ssato 		}
65337682e54Ssato 		return (0);
65437682e54Ssato 
655733c0414Stakemura 	case HPCFBIO_GCONF:
656733c0414Stakemura 		fbconf = (struct hpcfb_fbconf *)data;
657733c0414Stakemura 		if (fbconf->hf_conf_index != 0 &&
658733c0414Stakemura 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
659733c0414Stakemura 			return (EINVAL);
660733c0414Stakemura 		}
661733c0414Stakemura 		*fbconf = sc->sc_fbconf;	/* structure assignment */
662733c0414Stakemura 		return (0);
663733c0414Stakemura 	case HPCFBIO_SCONF:
664733c0414Stakemura 		fbconf = (struct hpcfb_fbconf *)data;
665733c0414Stakemura 		if (fbconf->hf_conf_index != 0 &&
666733c0414Stakemura 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
667733c0414Stakemura 			return (EINVAL);
668733c0414Stakemura 		}
669733c0414Stakemura 		/*
670964859d8Sabs 		 * nothing to do because we have only one configuration
671733c0414Stakemura 		 */
672733c0414Stakemura 		return (0);
673733c0414Stakemura 	case HPCFBIO_GDSPCONF:
674733c0414Stakemura 		dspconf = (struct hpcfb_dspconf *)data;
675733c0414Stakemura 		if ((dspconf->hd_unit_index != 0 &&
676733c0414Stakemura 		    dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
677733c0414Stakemura 		    (dspconf->hd_conf_index != 0 &&
678733c0414Stakemura 			dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
679733c0414Stakemura 			return (EINVAL);
680733c0414Stakemura 		}
681733c0414Stakemura 		*dspconf = sc->sc_dspconf;	/* structure assignment */
682733c0414Stakemura 		return (0);
683733c0414Stakemura 	case HPCFBIO_SDSPCONF:
684733c0414Stakemura 		dspconf = (struct hpcfb_dspconf *)data;
685733c0414Stakemura 		if ((dspconf->hd_unit_index != 0 &&
686733c0414Stakemura 		    dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
687733c0414Stakemura 		    (dspconf->hd_conf_index != 0 &&
688733c0414Stakemura 			dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
689733c0414Stakemura 			return (EINVAL);
690733c0414Stakemura 		}
691733c0414Stakemura 		/*
692733c0414Stakemura 		 * nothing to do
693964859d8Sabs 		 * because we have only one unit and one configuration
694733c0414Stakemura 		 */
695733c0414Stakemura 		return (0);
696733c0414Stakemura 	case HPCFBIO_GOP:
697733c0414Stakemura 	case HPCFBIO_SOP:
698733c0414Stakemura 		/*
699*9fc7748dSandvar 		 * currently not implemented...
700733c0414Stakemura 		 */
701733c0414Stakemura 		return (EINVAL);
702733c0414Stakemura 	}
703733c0414Stakemura 
70431144d99Satatat 	return (EPASSTHROUGH);
705733c0414Stakemura }
706733c0414Stakemura 
707733c0414Stakemura paddr_t
mq200_mmap(void * ctx,off_t offset,int prot)708961880b5Such mq200_mmap(void *ctx, off_t offset, int prot)
709733c0414Stakemura {
710733c0414Stakemura 	struct mq200_softc *sc = (struct mq200_softc *)ctx;
711733c0414Stakemura 
7125692823cStakemura 	if (offset < 0 || MQ200_MAPSIZE <= offset)
713733c0414Stakemura 		return -1;
714733c0414Stakemura 
7155692823cStakemura 	return mips_btop(sc->sc_baseaddr + offset);
716733c0414Stakemura }
717b8e5bc56Ssato 
718b8e5bc56Ssato 
719b8e5bc56Ssato void
mq200_init_backlight(struct mq200_softc * sc,int inattach)720961880b5Such mq200_init_backlight(struct mq200_softc *sc, int inattach)
721b8e5bc56Ssato {
722b8e5bc56Ssato 	int val = -1;
723b8e5bc56Ssato 
7246c5da9bdSsato 	if (sc->sc_lcd_inited&BACKLIGHT_INITED)
7256c5da9bdSsato 		return;
7266c5da9bdSsato 
727b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
728b8e5bc56Ssato 	    CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
7296c5da9bdSsato 		/* we can get real light state */
7306c5da9bdSsato 		VPRINTF("init_backlight: real backlight=%d\n", val);
731b8e5bc56Ssato 		if (val == 0)
732b8e5bc56Ssato 			sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
733b8e5bc56Ssato 		else
734b8e5bc56Ssato 			sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
7356c5da9bdSsato 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
7366c5da9bdSsato 	} else if (inattach) {
7376c5da9bdSsato 		/*
7386c5da9bdSsato 		   we cannot get real light state in attach time
7396c5da9bdSsato 		   because light device not yet attached.
7406c5da9bdSsato 		   we will retry in !inattach.
7416c5da9bdSsato 		   temporary assume light is on.
7426c5da9bdSsato 		*/
743ee1d25e7Ssato 		sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
7446c5da9bdSsato 	} else {
7456c5da9bdSsato 		/* we cannot get real light state, so work by myself state */
7466c5da9bdSsato 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
7476c5da9bdSsato 	}
748b8e5bc56Ssato }
749b8e5bc56Ssato 
750b8e5bc56Ssato void
mq200_init_brightness(struct mq200_softc * sc,int inattach)751961880b5Such mq200_init_brightness(struct mq200_softc *sc, int inattach)
752b8e5bc56Ssato {
753b8e5bc56Ssato 	int val = -1;
754b8e5bc56Ssato 
7556c5da9bdSsato 	if (sc->sc_lcd_inited&BRIGHTNESS_INITED)
7566c5da9bdSsato 		return;
7576c5da9bdSsato 
75844e4c533Stakemura 	VPRINTF("init_brightness\n");
759b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
7606c5da9bdSsato 	    CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
7616c5da9bdSsato 		/* we can get real brightness max */
7626c5da9bdSsato 		VPRINTF("init_brightness: real brightness max=%d\n", val);
7636c5da9bdSsato 		sc->sc_max_brightness = val;
764b8e5bc56Ssato 		val = -1;
765b8e5bc56Ssato 		if (config_hook_call(CONFIG_HOOK_GET,
7666c5da9bdSsato 		    CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
7676c5da9bdSsato 			/* we can get real brightness */
7686c5da9bdSsato 			VPRINTF("init_brightness: real brightness=%d\n", val);
7696c5da9bdSsato 			sc->sc_brightness_save = sc->sc_brightness = val;
7706c5da9bdSsato 		} else {
7716c5da9bdSsato 			sc->sc_brightness_save =
7726c5da9bdSsato 			    sc->sc_brightness = sc->sc_max_brightness;
773b8e5bc56Ssato 		}
7746c5da9bdSsato 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
7756c5da9bdSsato 	} else if (inattach) {
7766c5da9bdSsato 		/*
7776c5da9bdSsato 		   we cannot get real brightness in attach time
7786c5da9bdSsato 		   because brightness device not yet attached.
7796c5da9bdSsato 		   we will retry in !inattach.
7806c5da9bdSsato 		*/
7816c5da9bdSsato 		sc->sc_max_brightness = -1;
7826c5da9bdSsato 		sc->sc_brightness = -1;
7836c5da9bdSsato 		sc->sc_brightness_save = -1;
7846c5da9bdSsato 	} else {
7856c5da9bdSsato 		/* we cannot get real brightness */
7866c5da9bdSsato 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
7876c5da9bdSsato 	}
7886c5da9bdSsato 
789b8e5bc56Ssato 	return;
790b8e5bc56Ssato }
791b8e5bc56Ssato 
792b8e5bc56Ssato 
793b8e5bc56Ssato void
mq200_init_contrast(struct mq200_softc * sc,int inattach)794961880b5Such mq200_init_contrast(struct mq200_softc *sc, int inattach)
795b8e5bc56Ssato {
796b8e5bc56Ssato 	int val = -1;
797b8e5bc56Ssato 
7986c5da9bdSsato 	if (sc->sc_lcd_inited&CONTRAST_INITED)
7996c5da9bdSsato 		return;
8006c5da9bdSsato 
80144e4c533Stakemura 	VPRINTF("init_contrast\n");
802b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
8036c5da9bdSsato 	    CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
8046c5da9bdSsato 		/* we can get real contrast max */
8056c5da9bdSsato 		VPRINTF("init_contrast: real contrast max=%d\n", val);
8066c5da9bdSsato 		sc->sc_max_contrast = val;
807b8e5bc56Ssato 		val = -1;
808b8e5bc56Ssato 		if (config_hook_call(CONFIG_HOOK_GET,
8096c5da9bdSsato 		    CONFIG_HOOK_CONTRAST, &val) != -1) {
8106c5da9bdSsato 			/* we can get real contrast */
8116c5da9bdSsato 			VPRINTF("init_contrast: real contrast=%d\n", val);
8126c5da9bdSsato 			sc->sc_contrast = val;
8136c5da9bdSsato 		} else {
8146c5da9bdSsato 			sc->sc_contrast = sc->sc_max_contrast;
815b8e5bc56Ssato 		}
8166c5da9bdSsato 		sc->sc_lcd_inited |= CONTRAST_INITED;
8176c5da9bdSsato 	} else if (inattach) {
8186c5da9bdSsato 		/*
8196c5da9bdSsato 		   we cannot get real contrast in attach time
8206c5da9bdSsato 		   because contrast device not yet attached.
8216c5da9bdSsato 		   we will retry in !inattach.
8226c5da9bdSsato 		*/
8236c5da9bdSsato 		sc->sc_max_contrast = -1;
8246c5da9bdSsato 		sc->sc_contrast = -1;
8256c5da9bdSsato 	} else {
8266c5da9bdSsato 		/* we cannot get real contrast */
8276c5da9bdSsato 		sc->sc_lcd_inited |= CONTRAST_INITED;
8286c5da9bdSsato 	}
8296c5da9bdSsato 
830b8e5bc56Ssato 	return;
831b8e5bc56Ssato }
832b8e5bc56Ssato 
8336c5da9bdSsato 
834b8e5bc56Ssato void
mq200_set_brightness(struct mq200_softc * sc,int val)835961880b5Such mq200_set_brightness(struct mq200_softc *sc, int val)
836b8e5bc56Ssato {
837b8e5bc56Ssato 	sc->sc_brightness = val;
838b8e5bc56Ssato 
839b8e5bc56Ssato 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
840b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
841b8e5bc56Ssato 	    CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
842b8e5bc56Ssato 		sc->sc_brightness = val;
843b8e5bc56Ssato 	}
844b8e5bc56Ssato }
845b8e5bc56Ssato 
846b8e5bc56Ssato void
mq200_set_contrast(struct mq200_softc * sc,int val)847961880b5Such mq200_set_contrast(struct mq200_softc *sc, int val)
848b8e5bc56Ssato {
849b8e5bc56Ssato 	sc->sc_contrast = val;
850b8e5bc56Ssato 
851b8e5bc56Ssato 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
852b8e5bc56Ssato 	if (config_hook_call(CONFIG_HOOK_GET,
853b8e5bc56Ssato 	    CONFIG_HOOK_CONTRAST, &val) != -1) {
854b8e5bc56Ssato 		sc->sc_contrast = val;
855b8e5bc56Ssato 	}
856b8e5bc56Ssato }
857