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