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