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