Home | History | Annotate | Line # | Download | only in dev
mq200.c revision 1.2.2.7
      1  1.2.2.7  bouyer /*	$NetBSD: mq200.c,v 1.2.2.7 2001/03/27 15:30:54 bouyer Exp $	*/
      2  1.2.2.2  bouyer 
      3  1.2.2.2  bouyer /*-
      4  1.2.2.7  bouyer  * Copyright (c) 2000, 2001 TAKEMURA Shin
      5  1.2.2.2  bouyer  * All rights reserved.
      6  1.2.2.2  bouyer  *
      7  1.2.2.2  bouyer  * Redistribution and use in source and binary forms, with or without
      8  1.2.2.2  bouyer  * modification, are permitted provided that the following conditions
      9  1.2.2.2  bouyer  * are met:
     10  1.2.2.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     11  1.2.2.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     12  1.2.2.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.2.2.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     14  1.2.2.2  bouyer  *    documentation and/or other materials provided with the distribution.
     15  1.2.2.2  bouyer  * 3. The name of the author may not be used to endorse or promote products
     16  1.2.2.2  bouyer  *    derived from this software without specific prior written permission.
     17  1.2.2.2  bouyer  *
     18  1.2.2.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     19  1.2.2.2  bouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  1.2.2.2  bouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  1.2.2.2  bouyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     22  1.2.2.2  bouyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  1.2.2.2  bouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  1.2.2.2  bouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  1.2.2.2  bouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  1.2.2.2  bouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  1.2.2.2  bouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  1.2.2.2  bouyer  * SUCH DAMAGE.
     29  1.2.2.2  bouyer  *
     30  1.2.2.2  bouyer  */
     31  1.2.2.2  bouyer 
     32  1.2.2.2  bouyer #include <sys/param.h>
     33  1.2.2.2  bouyer #include <sys/kernel.h>
     34  1.2.2.2  bouyer #include <sys/device.h>
     35  1.2.2.2  bouyer #include <sys/systm.h>
     36  1.2.2.2  bouyer #include <sys/reboot.h>
     37  1.2.2.2  bouyer 
     38  1.2.2.2  bouyer #include <uvm/uvm_extern.h>
     39  1.2.2.2  bouyer 
     40  1.2.2.2  bouyer #include <dev/wscons/wsconsio.h>
     41  1.2.2.2  bouyer 
     42  1.2.2.2  bouyer #include <machine/bootinfo.h>
     43  1.2.2.2  bouyer #include <machine/bus.h>
     44  1.2.2.2  bouyer #include <machine/autoconf.h>
     45  1.2.2.2  bouyer #include <machine/config_hook.h>
     46  1.2.2.2  bouyer #include <machine/platid.h>
     47  1.2.2.2  bouyer #include <machine/platid_mask.h>
     48  1.2.2.2  bouyer 
     49  1.2.2.7  bouyer #include "opt_mq200.h"
     50  1.2.2.2  bouyer #include <hpcmips/dev/mq200reg.h>
     51  1.2.2.2  bouyer #include <hpcmips/dev/mq200var.h>
     52  1.2.2.7  bouyer #include <hpcmips/dev/mq200priv.h>
     53  1.2.2.7  bouyer 
     54  1.2.2.2  bouyer #include "bivideo.h"
     55  1.2.2.2  bouyer #if NBIVIDEO > 0
     56  1.2.2.6  bouyer #include <dev/hpc/bivideovar.h>
     57  1.2.2.2  bouyer #endif
     58  1.2.2.2  bouyer 
     59  1.2.2.2  bouyer /*
     60  1.2.2.2  bouyer  * function prototypes
     61  1.2.2.2  bouyer  */
     62  1.2.2.2  bouyer static void	mq200_power __P((int, void *));
     63  1.2.2.2  bouyer static int	mq200_hardpower __P((void *, int, long, void *));
     64  1.2.2.2  bouyer static int	mq200_fbinit __P((struct hpcfb_fbconf *));
     65  1.2.2.2  bouyer static int	mq200_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
     66  1.2.2.2  bouyer static paddr_t	mq200_mmap __P((void *, off_t offset, int));
     67  1.2.2.6  bouyer static void	mq200_update_powerstate __P((struct mq200_softc *, int));
     68  1.2.2.7  bouyer void	mq200_init_backlight __P((struct mq200_softc *, int));
     69  1.2.2.7  bouyer void	mq200_init_brightness __P((struct mq200_softc *, int));
     70  1.2.2.7  bouyer void	mq200_init_contrast __P((struct mq200_softc *, int));
     71  1.2.2.6  bouyer void	mq200_set_brightness __P((struct mq200_softc *, int));
     72  1.2.2.6  bouyer void	mq200_set_contrast __P((struct mq200_softc *, int));
     73  1.2.2.2  bouyer 
     74  1.2.2.2  bouyer /*
     75  1.2.2.2  bouyer  * static variables
     76  1.2.2.2  bouyer  */
     77  1.2.2.2  bouyer struct hpcfb_accessops mq200_ha = {
     78  1.2.2.2  bouyer 	mq200_ioctl, mq200_mmap
     79  1.2.2.2  bouyer };
     80  1.2.2.2  bouyer 
     81  1.2.2.7  bouyer #ifdef MQ200_DEBUG
     82  1.2.2.7  bouyer int mq200_debug = MQ200DEBUG_CONF;
     83  1.2.2.7  bouyer #endif
     84  1.2.2.7  bouyer 
     85  1.2.2.2  bouyer int
     86  1.2.2.2  bouyer mq200_probe(iot, ioh)
     87  1.2.2.2  bouyer 	bus_space_tag_t iot;
     88  1.2.2.2  bouyer 	bus_space_handle_t ioh;
     89  1.2.2.2  bouyer {
     90  1.2.2.2  bouyer 	unsigned long regval;
     91  1.2.2.2  bouyer 
     92  1.2.2.2  bouyer #if NBIVIDEO > 0
     93  1.2.2.2  bouyer 	if (bivideo_dont_attach) /* some video driver already attached */
     94  1.2.2.2  bouyer 		return (0);
     95  1.2.2.2  bouyer #endif /* NBIVIDEO > 0 */
     96  1.2.2.2  bouyer 
     97  1.2.2.2  bouyer 	regval = bus_space_read_4(iot, ioh, MQ200_PC00R);
     98  1.2.2.7  bouyer 	VPRINTF("probe: vendor id=%04lx product id=%04lx\n",
     99  1.2.2.7  bouyer 		regval & 0xffff, (regval >> 16) & 0xffff);
    100  1.2.2.2  bouyer 	if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID))
    101  1.2.2.2  bouyer 		return (0);
    102  1.2.2.2  bouyer 
    103  1.2.2.2  bouyer 	return (1);
    104  1.2.2.2  bouyer }
    105  1.2.2.2  bouyer 
    106  1.2.2.2  bouyer void
    107  1.2.2.2  bouyer mq200_attach(sc)
    108  1.2.2.2  bouyer 	struct mq200_softc *sc;
    109  1.2.2.2  bouyer {
    110  1.2.2.2  bouyer 	unsigned long regval;
    111  1.2.2.2  bouyer 	struct hpcfb_attach_args ha;
    112  1.2.2.2  bouyer 	int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
    113  1.2.2.2  bouyer 
    114  1.2.2.6  bouyer 	printf(": ");
    115  1.2.2.6  bouyer 	if (mq200_fbinit(&sc->sc_fbconf) != 0) {
    116  1.2.2.6  bouyer 		/* just return so that hpcfb will not be attached */
    117  1.2.2.6  bouyer 		return;
    118  1.2.2.6  bouyer 	}
    119  1.2.2.6  bouyer 
    120  1.2.2.6  bouyer 	sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr;
    121  1.2.2.6  bouyer 	sc->sc_fbconf.hf_offset	= (u_long)sc->sc_fbconf.hf_baseaddr -
    122  1.2.2.6  bouyer 	    MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr)));
    123  1.2.2.7  bouyer 	DPRINTF("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr);
    124  1.2.2.7  bouyer 	DPRINTF("hf_offset=%lx\n", sc->sc_fbconf.hf_offset);
    125  1.2.2.2  bouyer 
    126  1.2.2.7  bouyer 	regval = mq200_read(sc, MQ200_PC08R);
    127  1.2.2.6  bouyer 	printf("MQ200 Rev.%02lx video controller", regval & 0xff);
    128  1.2.2.6  bouyer 	if (console) {
    129  1.2.2.6  bouyer 		printf(", console");
    130  1.2.2.6  bouyer 	}
    131  1.2.2.6  bouyer 	printf("\n");
    132  1.2.2.6  bouyer         printf("%s: framebuffer address: 0x%08lx\n",
    133  1.2.2.6  bouyer 		sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr);
    134  1.2.2.7  bouyer 
    135  1.2.2.7  bouyer 	/*
    136  1.2.2.7  bouyer 	 * setup registers
    137  1.2.2.7  bouyer 	 */
    138  1.2.2.7  bouyer 	sc->sc_flags = 0;
    139  1.2.2.7  bouyer 	sc->sc_baseclock = 12288;	/* 12.288 MHz */
    140  1.2.2.7  bouyer #ifdef MQ200_DEBUG
    141  1.2.2.7  bouyer 	if (bootverbose) {
    142  1.2.2.7  bouyer 		/* dump current setting	*/
    143  1.2.2.7  bouyer 		mq200_dump_all(sc);
    144  1.2.2.7  bouyer 		mq200_dump_pll(sc);
    145  1.2.2.7  bouyer 	}
    146  1.2.2.7  bouyer #endif
    147  1.2.2.7  bouyer 	mq200_setup_regctx(sc);
    148  1.2.2.7  bouyer 	mq200_mdsetup(sc);
    149  1.2.2.7  bouyer 	if (sc->sc_md) {
    150  1.2.2.7  bouyer 		if (sc->sc_md->md_flags & MQ200_MD_HAVEFP) {
    151  1.2.2.7  bouyer 			sc->sc_flags |= MQ200_SC_GC2_ENABLE;	/* FP	*/
    152  1.2.2.7  bouyer 		}
    153  1.2.2.7  bouyer #if MQ200_USECRT
    154  1.2.2.7  bouyer 		if (sc->sc_md->md_flags & MQ200_MD_HAVECRT) {
    155  1.2.2.7  bouyer 			int i;
    156  1.2.2.7  bouyer 			sc->sc_flags |= MQ200_SC_GC1_ENABLE;	/* CRT	*/
    157  1.2.2.7  bouyer 			for (i = 0; i < mq200_crt_nparams; i++) {
    158  1.2.2.7  bouyer 				sc->sc_crt = &mq200_crt_params[i];
    159  1.2.2.7  bouyer 				if (sc->sc_md->md_fp_width <=
    160  1.2.2.7  bouyer 				    mq200_crt_params[i].width &&
    161  1.2.2.7  bouyer 				    sc->sc_md->md_fp_height <=
    162  1.2.2.7  bouyer 				    mq200_crt_params[i].height)
    163  1.2.2.7  bouyer 					break;
    164  1.2.2.7  bouyer 			}
    165  1.2.2.7  bouyer 		}
    166  1.2.2.7  bouyer #endif
    167  1.2.2.7  bouyer 		mq200_setup(sc);
    168  1.2.2.7  bouyer 
    169  1.2.2.7  bouyer 		if (sc->sc_flags & MQ200_SC_GC2_ENABLE)	/* FP	*/
    170  1.2.2.7  bouyer 			mq200_win_enable(sc, MQ200_GC2, MQ200_GCC_16BPP_DIRECT,
    171  1.2.2.7  bouyer 			    0x00080100,
    172  1.2.2.7  bouyer 			    sc->sc_md->md_fp_width, sc->sc_md->md_fp_height,
    173  1.2.2.7  bouyer 			    1280);
    174  1.2.2.7  bouyer 		if (sc->sc_flags & MQ200_SC_GC1_ENABLE)	/* CRT	*/
    175  1.2.2.7  bouyer 			mq200_win_enable(sc, MQ200_GC1, MQ200_GCC_16BPP_DIRECT,
    176  1.2.2.7  bouyer 			    0x00080100,
    177  1.2.2.7  bouyer 			    sc->sc_md->md_fp_width, sc->sc_md->md_fp_height,
    178  1.2.2.7  bouyer 			    1280);
    179  1.2.2.7  bouyer 	}
    180  1.2.2.7  bouyer #ifdef MQ200_DEBUG
    181  1.2.2.7  bouyer 	if (sc->sc_md == NULL || bootverbose) {
    182  1.2.2.7  bouyer 		mq200_dump_pll(sc);
    183  1.2.2.7  bouyer 	}
    184  1.2.2.7  bouyer #endif
    185  1.2.2.6  bouyer 
    186  1.2.2.2  bouyer 	/* Add a power hook to power saving */
    187  1.2.2.6  bouyer 	sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
    188  1.2.2.2  bouyer 	sc->sc_powerhook = powerhook_establish(mq200_power, sc);
    189  1.2.2.2  bouyer 	if (sc->sc_powerhook == NULL)
    190  1.2.2.2  bouyer 		printf("%s: WARNING: unable to establish power hook\n",
    191  1.2.2.2  bouyer 			sc->sc_dev.dv_xname);
    192  1.2.2.2  bouyer 
    193  1.2.2.2  bouyer 	/* Add a hard power hook to power saving */
    194  1.2.2.2  bouyer 	sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT,
    195  1.2.2.2  bouyer 					   CONFIG_HOOK_PMEVENT_HARDPOWER,
    196  1.2.2.2  bouyer 					   CONFIG_HOOK_SHARE,
    197  1.2.2.2  bouyer 					   mq200_hardpower, sc);
    198  1.2.2.2  bouyer 	if (sc->sc_hardpowerhook == NULL)
    199  1.2.2.2  bouyer 		printf("%s: WARNING: unable to establish hard power hook\n",
    200  1.2.2.2  bouyer 			sc->sc_dev.dv_xname);
    201  1.2.2.2  bouyer 
    202  1.2.2.6  bouyer 	/* initialize backlight brightness and lcd contrast */
    203  1.2.2.7  bouyer 	sc->sc_lcd_inited = 0;
    204  1.2.2.7  bouyer 	mq200_init_brightness(sc, 1);
    205  1.2.2.7  bouyer 	mq200_init_contrast(sc, 1);
    206  1.2.2.7  bouyer 	mq200_init_backlight(sc, 1);
    207  1.2.2.2  bouyer 
    208  1.2.2.2  bouyer 	if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
    209  1.2.2.2  bouyer 		panic("mq200_attach: can't init fb console");
    210  1.2.2.2  bouyer 	}
    211  1.2.2.2  bouyer 
    212  1.2.2.2  bouyer 	ha.ha_console = console;
    213  1.2.2.2  bouyer 	ha.ha_accessops = &mq200_ha;
    214  1.2.2.2  bouyer 	ha.ha_accessctx = sc;
    215  1.2.2.2  bouyer 	ha.ha_curfbconf = 0;
    216  1.2.2.2  bouyer 	ha.ha_nfbconf = 1;
    217  1.2.2.2  bouyer 	ha.ha_fbconflist = &sc->sc_fbconf;
    218  1.2.2.2  bouyer 	ha.ha_curdspconf = 0;
    219  1.2.2.2  bouyer 	ha.ha_ndspconf = 1;
    220  1.2.2.2  bouyer 	ha.ha_dspconflist = &sc->sc_dspconf;
    221  1.2.2.2  bouyer 
    222  1.2.2.2  bouyer 	config_found(&sc->sc_dev, &ha, hpcfbprint);
    223  1.2.2.2  bouyer 
    224  1.2.2.2  bouyer #if NBIVIDEO > 0
    225  1.2.2.2  bouyer 	/*
    226  1.2.2.2  bouyer 	 * bivideo is no longer need
    227  1.2.2.2  bouyer 	 */
    228  1.2.2.2  bouyer 	bivideo_dont_attach = 1;
    229  1.2.2.2  bouyer #endif /* NBIVIDEO > 0 */
    230  1.2.2.2  bouyer }
    231  1.2.2.2  bouyer 
    232  1.2.2.6  bouyer static void
    233  1.2.2.6  bouyer mq200_update_powerstate(sc, updates)
    234  1.2.2.6  bouyer 	struct mq200_softc *sc;
    235  1.2.2.6  bouyer 	int updates;
    236  1.2.2.6  bouyer {
    237  1.2.2.6  bouyer 
    238  1.2.2.6  bouyer 	if (updates & PWRSTAT_LCD)
    239  1.2.2.6  bouyer 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
    240  1.2.2.6  bouyer 		    CONFIG_HOOK_POWERCONTROL_LCD,
    241  1.2.2.6  bouyer 		    (void*)!(sc->sc_powerstate &
    242  1.2.2.6  bouyer 				(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
    243  1.2.2.6  bouyer 
    244  1.2.2.6  bouyer 	if (updates & PWRSTAT_BACKLIGHT)
    245  1.2.2.6  bouyer 		config_hook_call(CONFIG_HOOK_POWERCONTROL,
    246  1.2.2.6  bouyer 		    CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
    247  1.2.2.6  bouyer 		    (void*)(!(sc->sc_powerstate &
    248  1.2.2.6  bouyer 				(PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
    249  1.2.2.6  bouyer 			     (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
    250  1.2.2.6  bouyer }
    251  1.2.2.6  bouyer 
    252  1.2.2.2  bouyer static void
    253  1.2.2.2  bouyer mq200_power(why, arg)
    254  1.2.2.2  bouyer 	int why;
    255  1.2.2.2  bouyer 	void *arg;
    256  1.2.2.2  bouyer {
    257  1.2.2.2  bouyer 	struct mq200_softc *sc = arg;
    258  1.2.2.2  bouyer 
    259  1.2.2.2  bouyer 	switch (why) {
    260  1.2.2.2  bouyer 	case PWR_SUSPEND:
    261  1.2.2.6  bouyer 		sc->sc_powerstate |= PWRSTAT_SUSPEND;
    262  1.2.2.6  bouyer 		mq200_update_powerstate(sc, PWRSTAT_ALL);
    263  1.2.2.2  bouyer 		break;
    264  1.2.2.2  bouyer 	case PWR_STANDBY:
    265  1.2.2.6  bouyer 		sc->sc_powerstate |= PWRSTAT_SUSPEND;
    266  1.2.2.6  bouyer 		mq200_update_powerstate(sc, PWRSTAT_ALL);
    267  1.2.2.2  bouyer 		break;
    268  1.2.2.2  bouyer 	case PWR_RESUME:
    269  1.2.2.6  bouyer 		sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
    270  1.2.2.6  bouyer 		mq200_update_powerstate(sc, PWRSTAT_ALL);
    271  1.2.2.2  bouyer 		break;
    272  1.2.2.2  bouyer 	}
    273  1.2.2.2  bouyer }
    274  1.2.2.2  bouyer 
    275  1.2.2.2  bouyer static int
    276  1.2.2.2  bouyer mq200_hardpower(ctx, type, id, msg)
    277  1.2.2.2  bouyer 	void *ctx;
    278  1.2.2.2  bouyer 	int type;
    279  1.2.2.2  bouyer 	long id;
    280  1.2.2.2  bouyer 	void *msg;
    281  1.2.2.2  bouyer {
    282  1.2.2.2  bouyer 	struct mq200_softc *sc = ctx;
    283  1.2.2.2  bouyer 	int why = (int)msg;
    284  1.2.2.2  bouyer 
    285  1.2.2.2  bouyer 	switch (why) {
    286  1.2.2.2  bouyer 	case PWR_SUSPEND:
    287  1.2.2.6  bouyer 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
    288  1.2.2.2  bouyer 		break;
    289  1.2.2.2  bouyer 	case PWR_STANDBY:
    290  1.2.2.6  bouyer 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
    291  1.2.2.2  bouyer 		break;
    292  1.2.2.2  bouyer 	case PWR_RESUME:
    293  1.2.2.6  bouyer 		sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
    294  1.2.2.2  bouyer 		break;
    295  1.2.2.2  bouyer 	}
    296  1.2.2.2  bouyer 
    297  1.2.2.2  bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
    298  1.2.2.6  bouyer 			  MQ200_PMCSR, sc->sc_mq200pwstate);
    299  1.2.2.2  bouyer 
    300  1.2.2.2  bouyer 	/*
    301  1.2.2.2  bouyer 	 * you should wait until the
    302  1.2.2.2  bouyer 	 * power state transit sequence will end.
    303  1.2.2.2  bouyer 	 */
    304  1.2.2.2  bouyer 	{
    305  1.2.2.2  bouyer 		unsigned long tmp;
    306  1.2.2.2  bouyer 		do {
    307  1.2.2.2  bouyer 			tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
    308  1.2.2.2  bouyer 					       MQ200_PMCSR);
    309  1.2.2.6  bouyer 		} while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3));
    310  1.2.2.2  bouyer 		delay(100000); /* XXX */
    311  1.2.2.2  bouyer 	}
    312  1.2.2.2  bouyer 
    313  1.2.2.2  bouyer 	return (0);
    314  1.2.2.2  bouyer }
    315  1.2.2.2  bouyer 
    316  1.2.2.2  bouyer 
    317  1.2.2.2  bouyer static int
    318  1.2.2.2  bouyer mq200_fbinit(fb)
    319  1.2.2.2  bouyer 	struct hpcfb_fbconf *fb;
    320  1.2.2.2  bouyer {
    321  1.2.2.2  bouyer 
    322  1.2.2.2  bouyer 	/*
    323  1.2.2.2  bouyer 	 * get fb settings from bootinfo
    324  1.2.2.2  bouyer 	 */
    325  1.2.2.2  bouyer 	if (bootinfo == NULL ||
    326  1.2.2.2  bouyer 	    bootinfo->fb_addr == 0 ||
    327  1.2.2.2  bouyer 	    bootinfo->fb_line_bytes == 0 ||
    328  1.2.2.2  bouyer 	    bootinfo->fb_width == 0 ||
    329  1.2.2.2  bouyer 	    bootinfo->fb_height == 0) {
    330  1.2.2.2  bouyer 		printf("no frame buffer infomation.\n");
    331  1.2.2.2  bouyer 		return (-1);
    332  1.2.2.2  bouyer 	}
    333  1.2.2.2  bouyer 
    334  1.2.2.2  bouyer 	/* zero fill */
    335  1.2.2.2  bouyer 	bzero(fb, sizeof(*fb));
    336  1.2.2.2  bouyer 
    337  1.2.2.2  bouyer 	fb->hf_conf_index	= 0;	/* configuration index		*/
    338  1.2.2.2  bouyer 	fb->hf_nconfs		= 1;   	/* how many configurations	*/
    339  1.2.2.2  bouyer 	strcpy(fb->hf_name, "built-in video");
    340  1.2.2.2  bouyer 					/* frame buffer name		*/
    341  1.2.2.2  bouyer 	strcpy(fb->hf_conf_name, "default");
    342  1.2.2.2  bouyer 					/* configuration name		*/
    343  1.2.2.2  bouyer 	fb->hf_height		= bootinfo->fb_height;
    344  1.2.2.2  bouyer 	fb->hf_width		= bootinfo->fb_width;
    345  1.2.2.2  bouyer 	fb->hf_baseaddr		= mips_ptob(mips_btop(bootinfo->fb_addr));
    346  1.2.2.2  bouyer 	fb->hf_offset		= (u_long)bootinfo->fb_addr - fb->hf_baseaddr;
    347  1.2.2.2  bouyer 					/* frame buffer start offset   	*/
    348  1.2.2.2  bouyer 	fb->hf_bytes_per_line	= bootinfo->fb_line_bytes;
    349  1.2.2.2  bouyer 	fb->hf_nplanes		= 1;
    350  1.2.2.2  bouyer 	fb->hf_bytes_per_plane	= bootinfo->fb_height *
    351  1.2.2.2  bouyer 					bootinfo->fb_line_bytes;
    352  1.2.2.2  bouyer 
    353  1.2.2.2  bouyer 	fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
    354  1.2.2.2  bouyer 	fb->hf_access_flags |= HPCFB_ACCESS_WORD;
    355  1.2.2.2  bouyer 	fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
    356  1.2.2.2  bouyer 
    357  1.2.2.2  bouyer 	switch (bootinfo->fb_type) {
    358  1.2.2.2  bouyer 		/*
    359  1.2.2.2  bouyer 		 * gray scale
    360  1.2.2.2  bouyer 		 */
    361  1.2.2.2  bouyer 	case BIFB_D2_M2L_3:
    362  1.2.2.2  bouyer 	case BIFB_D2_M2L_3x2:
    363  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
    364  1.2.2.2  bouyer 		/* fall through */
    365  1.2.2.2  bouyer 	case BIFB_D2_M2L_0:
    366  1.2.2.2  bouyer 	case BIFB_D2_M2L_0x2:
    367  1.2.2.2  bouyer 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
    368  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    369  1.2.2.2  bouyer 		fb->hf_pack_width = 8;
    370  1.2.2.2  bouyer 		fb->hf_pixels_per_pack = 4;
    371  1.2.2.2  bouyer 		fb->hf_pixel_width = 2;
    372  1.2.2.2  bouyer 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
    373  1.2.2.2  bouyer 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
    374  1.2.2.2  bouyer 		break;
    375  1.2.2.2  bouyer 
    376  1.2.2.5  bouyer 	case BIFB_D4_M2L_F:
    377  1.2.2.5  bouyer 	case BIFB_D4_M2L_Fx2:
    378  1.2.2.5  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
    379  1.2.2.5  bouyer 		/* fall through */
    380  1.2.2.5  bouyer 	case BIFB_D4_M2L_0:
    381  1.2.2.5  bouyer 	case BIFB_D4_M2L_0x2:
    382  1.2.2.5  bouyer 		fb->hf_class = HPCFB_CLASS_GRAYSCALE;
    383  1.2.2.5  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    384  1.2.2.5  bouyer 		fb->hf_pack_width = 8;
    385  1.2.2.5  bouyer 		fb->hf_pixels_per_pack = 2;
    386  1.2.2.5  bouyer 		fb->hf_pixel_width = 4;
    387  1.2.2.5  bouyer 		fb->hf_class_data_length = sizeof(struct hf_gray_tag);
    388  1.2.2.5  bouyer 		fb->hf_u.hf_gray.hf_flags = 0;	/* reserved for future use */
    389  1.2.2.5  bouyer 		break;
    390  1.2.2.5  bouyer 
    391  1.2.2.2  bouyer 		/*
    392  1.2.2.2  bouyer 		 * indexed color
    393  1.2.2.2  bouyer 		 */
    394  1.2.2.2  bouyer 	case BIFB_D8_FF:
    395  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
    396  1.2.2.2  bouyer 		/* fall through */
    397  1.2.2.2  bouyer 	case BIFB_D8_00:
    398  1.2.2.2  bouyer 		fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
    399  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    400  1.2.2.2  bouyer 		fb->hf_pack_width = 8;
    401  1.2.2.2  bouyer 		fb->hf_pixels_per_pack = 1;
    402  1.2.2.2  bouyer 		fb->hf_pixel_width = 8;
    403  1.2.2.2  bouyer 		fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
    404  1.2.2.2  bouyer 		fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
    405  1.2.2.2  bouyer 		break;
    406  1.2.2.2  bouyer 
    407  1.2.2.2  bouyer 		/*
    408  1.2.2.2  bouyer 		 * RGB color
    409  1.2.2.2  bouyer 		 */
    410  1.2.2.2  bouyer 	case BIFB_D16_FFFF:
    411  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
    412  1.2.2.2  bouyer 		/* fall through */
    413  1.2.2.2  bouyer 	case BIFB_D16_0000:
    414  1.2.2.2  bouyer 		fb->hf_class = HPCFB_CLASS_RGBCOLOR;
    415  1.2.2.2  bouyer 		fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
    416  1.2.2.2  bouyer #if BYTE_ORDER == LITTLE_ENDIAN
    417  1.2.2.2  bouyer 		fb->hf_swap_flags = HPCFB_SWAP_BYTE;
    418  1.2.2.2  bouyer #endif
    419  1.2.2.2  bouyer 		fb->hf_pack_width = 16;
    420  1.2.2.2  bouyer 		fb->hf_pixels_per_pack = 1;
    421  1.2.2.2  bouyer 		fb->hf_pixel_width = 16;
    422  1.2.2.2  bouyer 
    423  1.2.2.2  bouyer 		fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
    424  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_flags = 0;	/* reserved for future use */
    425  1.2.2.2  bouyer 
    426  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_red_width = 5;
    427  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_red_shift = 11;
    428  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_green_width = 6;
    429  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_green_shift = 5;
    430  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_blue_width = 5;
    431  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_blue_shift = 0;
    432  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_alpha_width = 0;
    433  1.2.2.2  bouyer 		fb->hf_u.hf_rgb.hf_alpha_shift = 0;
    434  1.2.2.2  bouyer 		break;
    435  1.2.2.2  bouyer 
    436  1.2.2.2  bouyer 	default:
    437  1.2.2.2  bouyer 		printf("unknown type (=%d).\n", bootinfo->fb_type);
    438  1.2.2.2  bouyer 		return (-1);
    439  1.2.2.2  bouyer 		break;
    440  1.2.2.2  bouyer 	}
    441  1.2.2.2  bouyer 
    442  1.2.2.2  bouyer 	return (0); /* no error */
    443  1.2.2.2  bouyer }
    444  1.2.2.2  bouyer 
    445  1.2.2.2  bouyer int
    446  1.2.2.2  bouyer mq200_ioctl(v, cmd, data, flag, p)
    447  1.2.2.2  bouyer 	void *v;
    448  1.2.2.2  bouyer 	u_long cmd;
    449  1.2.2.2  bouyer 	caddr_t data;
    450  1.2.2.2  bouyer 	int flag;
    451  1.2.2.2  bouyer 	struct proc *p;
    452  1.2.2.2  bouyer {
    453  1.2.2.2  bouyer 	struct mq200_softc *sc = (struct mq200_softc *)v;
    454  1.2.2.2  bouyer 	struct hpcfb_fbconf *fbconf;
    455  1.2.2.2  bouyer 	struct hpcfb_dspconf *dspconf;
    456  1.2.2.2  bouyer 	struct wsdisplay_cmap *cmap;
    457  1.2.2.4  bouyer 	struct wsdisplay_param *dispparam;
    458  1.2.2.2  bouyer 
    459  1.2.2.2  bouyer 	switch (cmd) {
    460  1.2.2.2  bouyer 	case WSDISPLAYIO_GETCMAP:
    461  1.2.2.2  bouyer 		cmap = (struct wsdisplay_cmap*)data;
    462  1.2.2.2  bouyer 
    463  1.2.2.2  bouyer 		if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
    464  1.2.2.2  bouyer 		    sc->sc_fbconf.hf_pack_width != 8 ||
    465  1.2.2.2  bouyer 		    256 <= cmap->index ||
    466  1.2.2.2  bouyer 		    256 < (cmap->index + cmap->count))
    467  1.2.2.2  bouyer 			return (EINVAL);
    468  1.2.2.2  bouyer 
    469  1.2.2.2  bouyer #if 0
    470  1.2.2.2  bouyer 		if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) ||
    471  1.2.2.2  bouyer 		    !uvm_useracc(cmap->green, cmap->count, B_WRITE) ||
    472  1.2.2.2  bouyer 		    !uvm_useracc(cmap->blue, cmap->count, B_WRITE))
    473  1.2.2.2  bouyer 			return (EFAULT);
    474  1.2.2.2  bouyer 
    475  1.2.2.2  bouyer 		copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count);
    476  1.2.2.2  bouyer 		copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count);
    477  1.2.2.2  bouyer 		copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count);
    478  1.2.2.2  bouyer #endif
    479  1.2.2.2  bouyer 
    480  1.2.2.2  bouyer 		return (0);
    481  1.2.2.2  bouyer 
    482  1.2.2.2  bouyer 	case WSDISPLAYIO_PUTCMAP:
    483  1.2.2.2  bouyer 		/*
    484  1.2.2.2  bouyer 		 * This driver can't set color map.
    485  1.2.2.2  bouyer 		 */
    486  1.2.2.2  bouyer 		return (EINVAL);
    487  1.2.2.6  bouyer 
    488  1.2.2.6  bouyer 	case WSDISPLAYIO_SVIDEO:
    489  1.2.2.6  bouyer 		if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
    490  1.2.2.6  bouyer 			sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
    491  1.2.2.6  bouyer 		else
    492  1.2.2.6  bouyer 			sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
    493  1.2.2.6  bouyer 		mq200_update_powerstate(sc, PWRSTAT_ALL);
    494  1.2.2.6  bouyer 		return 0;
    495  1.2.2.6  bouyer 
    496  1.2.2.6  bouyer 	case WSDISPLAYIO_GVIDEO:
    497  1.2.2.6  bouyer 		*(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
    498  1.2.2.6  bouyer 				WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
    499  1.2.2.6  bouyer 		return 0;
    500  1.2.2.2  bouyer 
    501  1.2.2.4  bouyer 	case WSDISPLAYIO_GETPARAM:
    502  1.2.2.4  bouyer 		dispparam = (struct wsdisplay_param*)data;
    503  1.2.2.4  bouyer 		switch (dispparam->param) {
    504  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_BACKLIGHT:
    505  1.2.2.7  bouyer 			VPRINTF("ioctl: GET:BACKLIGHT\n");
    506  1.2.2.7  bouyer 			mq200_init_brightness(sc, 0);
    507  1.2.2.7  bouyer 			mq200_init_backlight(sc, 0);
    508  1.2.2.7  bouyer 			VPRINTF("ioctl: GET:(real)BACKLIGHT %d\n",
    509  1.2.2.7  bouyer 				 (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0);
    510  1.2.2.6  bouyer 			dispparam->min = 0;
    511  1.2.2.6  bouyer 			dispparam->max = 1;
    512  1.2.2.6  bouyer 			if (sc->sc_max_brightness > 0)
    513  1.2.2.6  bouyer 				dispparam->curval = sc->sc_brightness > 0? 1: 0;
    514  1.2.2.6  bouyer 			else
    515  1.2.2.6  bouyer 				dispparam->curval =
    516  1.2.2.7  bouyer 				    (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0;
    517  1.2.2.7  bouyer 			VPRINTF("ioctl: GET:BACKLIGHT:%d(%s)\n",
    518  1.2.2.7  bouyer 				dispparam->curval,
    519  1.2.2.7  bouyer 				sc->sc_max_brightness > 0? "brightness": "light");
    520  1.2.2.6  bouyer 			return 0;
    521  1.2.2.6  bouyer 			break;
    522  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_CONTRAST:
    523  1.2.2.7  bouyer 			VPRINTF("ioctl: GET:CONTRAST\n");
    524  1.2.2.7  bouyer 			mq200_init_contrast(sc, 0);
    525  1.2.2.6  bouyer 			if (sc->sc_max_contrast > 0) {
    526  1.2.2.6  bouyer 				dispparam->min = 0;
    527  1.2.2.6  bouyer 				dispparam->max = sc->sc_max_contrast;
    528  1.2.2.6  bouyer 				dispparam->curval = sc->sc_contrast;
    529  1.2.2.7  bouyer 				VPRINTF("ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast);
    530  1.2.2.6  bouyer 				return 0;
    531  1.2.2.6  bouyer 			} else {
    532  1.2.2.7  bouyer 				VPRINTF("ioctl: GET:CONTRAST EINVAL\n");
    533  1.2.2.6  bouyer 				return (EINVAL);
    534  1.2.2.6  bouyer 			}
    535  1.2.2.6  bouyer 			break;
    536  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
    537  1.2.2.7  bouyer 			VPRINTF("ioctl: GET:BRIGHTNESS\n");
    538  1.2.2.7  bouyer 			mq200_init_brightness(sc, 0);
    539  1.2.2.6  bouyer 			if (sc->sc_max_brightness > 0) {
    540  1.2.2.6  bouyer 				dispparam->min = 0;
    541  1.2.2.6  bouyer 				dispparam->max = sc->sc_max_brightness;
    542  1.2.2.6  bouyer 				dispparam->curval = sc->sc_brightness;
    543  1.2.2.7  bouyer 				VPRINTF("ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness);
    544  1.2.2.6  bouyer 				return 0;
    545  1.2.2.6  bouyer 			} else {
    546  1.2.2.7  bouyer 				VPRINTF("ioctl: GET:BRIGHTNESS EINVAL\n");
    547  1.2.2.6  bouyer 				return (EINVAL);
    548  1.2.2.6  bouyer 			}
    549  1.2.2.4  bouyer 			return (EINVAL);
    550  1.2.2.4  bouyer 		default:
    551  1.2.2.4  bouyer 			return (EINVAL);
    552  1.2.2.4  bouyer 		}
    553  1.2.2.4  bouyer 		return (0);
    554  1.2.2.4  bouyer 
    555  1.2.2.4  bouyer 	case WSDISPLAYIO_SETPARAM:
    556  1.2.2.4  bouyer 		dispparam = (struct wsdisplay_param*)data;
    557  1.2.2.4  bouyer 		switch (dispparam->param) {
    558  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_BACKLIGHT:
    559  1.2.2.7  bouyer 			VPRINTF("ioctl: SET:BACKLIGHT\n");
    560  1.2.2.6  bouyer 			if (dispparam->curval < 0 ||
    561  1.2.2.6  bouyer 			    1 < dispparam->curval)
    562  1.2.2.6  bouyer 				return (EINVAL);
    563  1.2.2.7  bouyer 			mq200_init_brightness(sc, 0);
    564  1.2.2.7  bouyer 			VPRINTF("ioctl: SET:max brightness=%d\n", sc->sc_max_brightness);
    565  1.2.2.6  bouyer 			if (sc->sc_max_brightness > 0) { /* dimmer */
    566  1.2.2.6  bouyer 				if (dispparam->curval == 0){
    567  1.2.2.6  bouyer 					sc->sc_brightness_save = sc->sc_brightness;
    568  1.2.2.6  bouyer 					mq200_set_brightness(sc, 0);	/* min */
    569  1.2.2.6  bouyer 				} else {
    570  1.2.2.6  bouyer 					if (sc->sc_brightness_save == 0)
    571  1.2.2.6  bouyer 						sc->sc_brightness_save = sc->sc_max_brightness;
    572  1.2.2.6  bouyer 					mq200_set_brightness(sc, sc->sc_brightness_save);
    573  1.2.2.6  bouyer 				}
    574  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:BACKLIGHT: brightness=%d\n", sc->sc_brightness);
    575  1.2.2.6  bouyer 			} else { /* off */
    576  1.2.2.6  bouyer 				if (dispparam->curval == 0)
    577  1.2.2.6  bouyer 					sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
    578  1.2.2.6  bouyer 				else
    579  1.2.2.6  bouyer 					sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
    580  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:BACKLIGHT: powerstate %d\n",
    581  1.2.2.7  bouyer 						(sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0);
    582  1.2.2.6  bouyer 				mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT);
    583  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:BACKLIGHT:%d\n",
    584  1.2.2.7  bouyer 					(sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0);
    585  1.2.2.6  bouyer 			}
    586  1.2.2.6  bouyer 			return 0;
    587  1.2.2.6  bouyer 			break;
    588  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_CONTRAST:
    589  1.2.2.7  bouyer 			VPRINTF("ioctl: SET:CONTRAST\n");
    590  1.2.2.7  bouyer 			mq200_init_contrast(sc, 0);
    591  1.2.2.6  bouyer 			if (dispparam->curval < 0 ||
    592  1.2.2.6  bouyer 			    sc->sc_max_contrast < dispparam->curval)
    593  1.2.2.6  bouyer 				return (EINVAL);
    594  1.2.2.6  bouyer 			if (sc->sc_max_contrast > 0) {
    595  1.2.2.6  bouyer 				int org = sc->sc_contrast;
    596  1.2.2.6  bouyer 				mq200_set_contrast(sc, dispparam->curval);
    597  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast);
    598  1.2.2.7  bouyer 				VPRINTF("ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast);
    599  1.2.2.6  bouyer 				return 0;
    600  1.2.2.6  bouyer 			} else {
    601  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:CONTRAST EINVAL\n");
    602  1.2.2.6  bouyer 				return (EINVAL);
    603  1.2.2.6  bouyer 			}
    604  1.2.2.6  bouyer 			break;
    605  1.2.2.4  bouyer 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
    606  1.2.2.7  bouyer 			VPRINTF("ioctl: SET:BRIGHTNESS\n");
    607  1.2.2.7  bouyer 			mq200_init_brightness(sc, 0);
    608  1.2.2.6  bouyer 			if (dispparam->curval < 0 ||
    609  1.2.2.6  bouyer 			    sc->sc_max_brightness < dispparam->curval)
    610  1.2.2.6  bouyer 				return (EINVAL);
    611  1.2.2.6  bouyer 			if (sc->sc_max_brightness > 0) {
    612  1.2.2.6  bouyer 				int org = sc->sc_brightness;
    613  1.2.2.6  bouyer 				mq200_set_brightness(sc, dispparam->curval);
    614  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness);
    615  1.2.2.6  bouyer 				return 0;
    616  1.2.2.6  bouyer 			} else {
    617  1.2.2.7  bouyer 				VPRINTF("ioctl: SET:BRIGHTNESS EINVAL\n");
    618  1.2.2.6  bouyer 				return (EINVAL);
    619  1.2.2.6  bouyer 			}
    620  1.2.2.6  bouyer 			break;
    621  1.2.2.4  bouyer 		default:
    622  1.2.2.4  bouyer 			return (EINVAL);
    623  1.2.2.4  bouyer 		}
    624  1.2.2.4  bouyer 		return (0);
    625  1.2.2.4  bouyer 
    626  1.2.2.2  bouyer 	case HPCFBIO_GCONF:
    627  1.2.2.2  bouyer 		fbconf = (struct hpcfb_fbconf *)data;
    628  1.2.2.2  bouyer 		if (fbconf->hf_conf_index != 0 &&
    629  1.2.2.2  bouyer 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    630  1.2.2.2  bouyer 			return (EINVAL);
    631  1.2.2.2  bouyer 		}
    632  1.2.2.2  bouyer 		*fbconf = sc->sc_fbconf;	/* structure assignment */
    633  1.2.2.2  bouyer 		return (0);
    634  1.2.2.2  bouyer 	case HPCFBIO_SCONF:
    635  1.2.2.2  bouyer 		fbconf = (struct hpcfb_fbconf *)data;
    636  1.2.2.2  bouyer 		if (fbconf->hf_conf_index != 0 &&
    637  1.2.2.2  bouyer 		    fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
    638  1.2.2.2  bouyer 			return (EINVAL);
    639  1.2.2.2  bouyer 		}
    640  1.2.2.2  bouyer 		/*
    641  1.2.2.2  bouyer 		 * nothing to do because we have only one configration
    642  1.2.2.2  bouyer 		 */
    643  1.2.2.2  bouyer 		return (0);
    644  1.2.2.2  bouyer 	case HPCFBIO_GDSPCONF:
    645  1.2.2.2  bouyer 		dspconf = (struct hpcfb_dspconf *)data;
    646  1.2.2.2  bouyer 		if ((dspconf->hd_unit_index != 0 &&
    647  1.2.2.2  bouyer 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    648  1.2.2.2  bouyer 		    (dspconf->hd_conf_index != 0 &&
    649  1.2.2.2  bouyer 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    650  1.2.2.2  bouyer 			return (EINVAL);
    651  1.2.2.2  bouyer 		}
    652  1.2.2.2  bouyer 		*dspconf = sc->sc_dspconf;	/* structure assignment */
    653  1.2.2.2  bouyer 		return (0);
    654  1.2.2.2  bouyer 	case HPCFBIO_SDSPCONF:
    655  1.2.2.2  bouyer 		dspconf = (struct hpcfb_dspconf *)data;
    656  1.2.2.2  bouyer 		if ((dspconf->hd_unit_index != 0 &&
    657  1.2.2.2  bouyer 		     dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
    658  1.2.2.2  bouyer 		    (dspconf->hd_conf_index != 0 &&
    659  1.2.2.2  bouyer 		     dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
    660  1.2.2.2  bouyer 			return (EINVAL);
    661  1.2.2.2  bouyer 		}
    662  1.2.2.2  bouyer 		/*
    663  1.2.2.2  bouyer 		 * nothing to do
    664  1.2.2.2  bouyer 		 * because we have only one unit and one configration
    665  1.2.2.2  bouyer 		 */
    666  1.2.2.2  bouyer 		return (0);
    667  1.2.2.2  bouyer 	case HPCFBIO_GOP:
    668  1.2.2.2  bouyer 	case HPCFBIO_SOP:
    669  1.2.2.2  bouyer 		/*
    670  1.2.2.2  bouyer 		 * curently not implemented...
    671  1.2.2.2  bouyer 		 */
    672  1.2.2.2  bouyer 		return (EINVAL);
    673  1.2.2.2  bouyer 	}
    674  1.2.2.2  bouyer 
    675  1.2.2.2  bouyer 	return (ENOTTY);
    676  1.2.2.2  bouyer }
    677  1.2.2.2  bouyer 
    678  1.2.2.2  bouyer paddr_t
    679  1.2.2.2  bouyer mq200_mmap(ctx, offset, prot)
    680  1.2.2.2  bouyer 	void *ctx;
    681  1.2.2.2  bouyer 	off_t offset;
    682  1.2.2.2  bouyer 	int prot;
    683  1.2.2.2  bouyer {
    684  1.2.2.2  bouyer 	struct mq200_softc *sc = (struct mq200_softc *)ctx;
    685  1.2.2.2  bouyer 
    686  1.2.2.3  bouyer 	if (offset < 0 || MQ200_MAPSIZE <= offset)
    687  1.2.2.2  bouyer 		return -1;
    688  1.2.2.2  bouyer 
    689  1.2.2.3  bouyer 	return mips_btop(sc->sc_baseaddr + offset);
    690  1.2.2.2  bouyer }
    691  1.2.2.6  bouyer 
    692  1.2.2.6  bouyer 
    693  1.2.2.6  bouyer void
    694  1.2.2.7  bouyer mq200_init_backlight(sc, inattach)
    695  1.2.2.6  bouyer 	struct mq200_softc *sc;
    696  1.2.2.7  bouyer 	int inattach;
    697  1.2.2.6  bouyer {
    698  1.2.2.6  bouyer 	int val = -1;
    699  1.2.2.6  bouyer 
    700  1.2.2.7  bouyer 	if (sc->sc_lcd_inited&BACKLIGHT_INITED)
    701  1.2.2.7  bouyer 		return;
    702  1.2.2.7  bouyer 
    703  1.2.2.6  bouyer 	if (config_hook_call(CONFIG_HOOK_GET,
    704  1.2.2.6  bouyer 	     CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
    705  1.2.2.7  bouyer 		/* we can get real light state */
    706  1.2.2.7  bouyer 		VPRINTF("init_backlight: real backlight=%d\n", val);
    707  1.2.2.6  bouyer 		if (val == 0)
    708  1.2.2.6  bouyer 			sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
    709  1.2.2.6  bouyer 		else
    710  1.2.2.6  bouyer 			sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
    711  1.2.2.7  bouyer 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
    712  1.2.2.7  bouyer 	} else if (inattach) {
    713  1.2.2.7  bouyer 		/*
    714  1.2.2.7  bouyer 		   we cannot get real light state in attach time
    715  1.2.2.7  bouyer 		   because light device not yet attached.
    716  1.2.2.7  bouyer 		   we will retry in !inattach.
    717  1.2.2.7  bouyer 		   temporary assume light is on.
    718  1.2.2.7  bouyer 		 */
    719  1.2.2.6  bouyer 		sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
    720  1.2.2.7  bouyer 	} else {
    721  1.2.2.7  bouyer 		/* we cannot get real light state, so work by myself state */
    722  1.2.2.7  bouyer 		sc->sc_lcd_inited |= BACKLIGHT_INITED;
    723  1.2.2.7  bouyer 	}
    724  1.2.2.6  bouyer }
    725  1.2.2.6  bouyer 
    726  1.2.2.6  bouyer void
    727  1.2.2.7  bouyer mq200_init_brightness(sc, inattach)
    728  1.2.2.6  bouyer 	struct mq200_softc *sc;
    729  1.2.2.7  bouyer 	int inattach;
    730  1.2.2.6  bouyer {
    731  1.2.2.6  bouyer 	int val = -1;
    732  1.2.2.6  bouyer 
    733  1.2.2.7  bouyer 	if (sc->sc_lcd_inited&BRIGHTNESS_INITED)
    734  1.2.2.7  bouyer 		return;
    735  1.2.2.7  bouyer 
    736  1.2.2.7  bouyer 	VPRINTF("init_brightness\n");
    737  1.2.2.6  bouyer 	if (config_hook_call(CONFIG_HOOK_GET,
    738  1.2.2.6  bouyer 	     CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
    739  1.2.2.7  bouyer 		/* we can get real brightness max */
    740  1.2.2.7  bouyer 		VPRINTF("init_brightness: real brightness max=%d\n", val);
    741  1.2.2.6  bouyer 		sc->sc_max_brightness = val;
    742  1.2.2.7  bouyer 		val = -1;
    743  1.2.2.7  bouyer 		if (config_hook_call(CONFIG_HOOK_GET,
    744  1.2.2.7  bouyer 		     CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
    745  1.2.2.7  bouyer 			/* we can get real brightness */
    746  1.2.2.7  bouyer 			VPRINTF("init_brightness: real brightness=%d\n", val);
    747  1.2.2.7  bouyer 			sc->sc_brightness_save = sc->sc_brightness = val;
    748  1.2.2.7  bouyer 		} else {
    749  1.2.2.7  bouyer 			sc->sc_brightness_save =
    750  1.2.2.7  bouyer 			sc->sc_brightness = sc->sc_max_brightness;
    751  1.2.2.7  bouyer 		}
    752  1.2.2.7  bouyer 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
    753  1.2.2.7  bouyer 	} else if (inattach) {
    754  1.2.2.7  bouyer 		/*
    755  1.2.2.7  bouyer 		   we cannot get real brightness in attach time
    756  1.2.2.7  bouyer 		   because brightness device not yet attached.
    757  1.2.2.7  bouyer 		   we will retry in !inattach.
    758  1.2.2.7  bouyer 		 */
    759  1.2.2.7  bouyer 		sc->sc_max_brightness = -1;
    760  1.2.2.7  bouyer 		sc->sc_brightness = -1;
    761  1.2.2.7  bouyer 		sc->sc_brightness_save = -1;
    762  1.2.2.7  bouyer 	} else {
    763  1.2.2.7  bouyer 		/* we cannot get real brightness */
    764  1.2.2.7  bouyer 		sc->sc_lcd_inited |= BRIGHTNESS_INITED;
    765  1.2.2.6  bouyer 	}
    766  1.2.2.7  bouyer 
    767  1.2.2.6  bouyer 	return;
    768  1.2.2.6  bouyer }
    769  1.2.2.6  bouyer 
    770  1.2.2.6  bouyer 
    771  1.2.2.6  bouyer void
    772  1.2.2.7  bouyer mq200_init_contrast(sc, inattach)
    773  1.2.2.6  bouyer 	struct mq200_softc *sc;
    774  1.2.2.7  bouyer 	int inattach;
    775  1.2.2.6  bouyer {
    776  1.2.2.6  bouyer 	int val = -1;
    777  1.2.2.6  bouyer 
    778  1.2.2.7  bouyer 	if (sc->sc_lcd_inited&CONTRAST_INITED)
    779  1.2.2.7  bouyer 		return;
    780  1.2.2.7  bouyer 
    781  1.2.2.7  bouyer 	VPRINTF("init_contrast\n");
    782  1.2.2.6  bouyer 	if (config_hook_call(CONFIG_HOOK_GET,
    783  1.2.2.6  bouyer 	     CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
    784  1.2.2.7  bouyer 		/* we can get real contrast max */
    785  1.2.2.7  bouyer 		VPRINTF("init_contrast: real contrast max=%d\n", val);
    786  1.2.2.6  bouyer 		sc->sc_max_contrast = val;
    787  1.2.2.7  bouyer 		val = -1;
    788  1.2.2.7  bouyer 		if (config_hook_call(CONFIG_HOOK_GET,
    789  1.2.2.7  bouyer 		     CONFIG_HOOK_CONTRAST, &val) != -1) {
    790  1.2.2.7  bouyer 			/* we can get real contrast */
    791  1.2.2.7  bouyer 			VPRINTF("init_contrast: real contrast=%d\n", val);
    792  1.2.2.7  bouyer 			sc->sc_contrast = val;
    793  1.2.2.7  bouyer 		} else {
    794  1.2.2.7  bouyer 			sc->sc_contrast = sc->sc_max_contrast;
    795  1.2.2.7  bouyer 		}
    796  1.2.2.7  bouyer 		sc->sc_lcd_inited |= CONTRAST_INITED;
    797  1.2.2.7  bouyer 	} else if (inattach) {
    798  1.2.2.7  bouyer 		/*
    799  1.2.2.7  bouyer 		   we cannot get real contrast in attach time
    800  1.2.2.7  bouyer 		   because contrast device not yet attached.
    801  1.2.2.7  bouyer 		   we will retry in !inattach.
    802  1.2.2.7  bouyer 		 */
    803  1.2.2.7  bouyer 		sc->sc_max_contrast = -1;
    804  1.2.2.7  bouyer 		sc->sc_contrast = -1;
    805  1.2.2.7  bouyer 	} else {
    806  1.2.2.7  bouyer 		/* we cannot get real contrast */
    807  1.2.2.7  bouyer 		sc->sc_lcd_inited |= CONTRAST_INITED;
    808  1.2.2.6  bouyer 	}
    809  1.2.2.7  bouyer 
    810  1.2.2.6  bouyer 	return;
    811  1.2.2.6  bouyer }
    812  1.2.2.6  bouyer 
    813  1.2.2.7  bouyer 
    814  1.2.2.6  bouyer void
    815  1.2.2.6  bouyer mq200_set_brightness(sc, val)
    816  1.2.2.6  bouyer 	struct mq200_softc *sc;
    817  1.2.2.6  bouyer 	int val;
    818  1.2.2.6  bouyer {
    819  1.2.2.6  bouyer 	sc->sc_brightness = val;
    820  1.2.2.6  bouyer 
    821  1.2.2.6  bouyer 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
    822  1.2.2.6  bouyer 	if (config_hook_call(CONFIG_HOOK_GET,
    823  1.2.2.6  bouyer 	     CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
    824  1.2.2.6  bouyer 		sc->sc_brightness = val;
    825  1.2.2.6  bouyer 	}
    826  1.2.2.6  bouyer }
    827  1.2.2.6  bouyer 
    828  1.2.2.6  bouyer void
    829  1.2.2.6  bouyer mq200_set_contrast(sc, val)
    830  1.2.2.6  bouyer 	struct mq200_softc *sc;
    831  1.2.2.6  bouyer 	int val;
    832  1.2.2.6  bouyer {
    833  1.2.2.6  bouyer 	sc->sc_contrast = val;
    834  1.2.2.6  bouyer 
    835  1.2.2.6  bouyer 	config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
    836  1.2.2.6  bouyer 	if (config_hook_call(CONFIG_HOOK_GET,
    837  1.2.2.6  bouyer 	     CONFIG_HOOK_CONTRAST, &val) != -1) {
    838  1.2.2.6  bouyer 		sc->sc_contrast = val;
    839  1.2.2.6  bouyer 	}
    840  1.2.2.6  bouyer }
    841