1*86c30724Sandvar /* $NetBSD: sed_saip.c,v 1.29 2022/05/28 10:36:22 andvar Exp $ */
276b3b49bStoshii
376b3b49bStoshii /*-
476b3b49bStoshii * Copyright (c) 1999-2001
576b3b49bStoshii * Shin Takemura and PocketBSD Project. All rights reserved.
676b3b49bStoshii *
776b3b49bStoshii * Redistribution and use in source and binary forms, with or without
876b3b49bStoshii * modification, are permitted provided that the following conditions
976b3b49bStoshii * are met:
1076b3b49bStoshii * 1. Redistributions of source code must retain the above copyright
1176b3b49bStoshii * notice, this list of conditions and the following disclaimer.
1276b3b49bStoshii * 2. Redistributions in binary form must reproduce the above copyright
1376b3b49bStoshii * notice, this list of conditions and the following disclaimer in the
1476b3b49bStoshii * documentation and/or other materials provided with the distribution.
1576b3b49bStoshii * 3. All advertising materials mentioning features or use of this software
1676b3b49bStoshii * must display the following acknowledgement:
1776b3b49bStoshii * This product includes software developed by the PocketBSD project
1876b3b49bStoshii * and its contributors.
1976b3b49bStoshii * 4. Neither the name of the project nor the names of its contributors
2076b3b49bStoshii * may be used to endorse or promote products derived from this software
2176b3b49bStoshii * without specific prior written permission.
2276b3b49bStoshii *
23d6a89fc1Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2476b3b49bStoshii * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2576b3b49bStoshii * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26d6a89fc1Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2776b3b49bStoshii * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2876b3b49bStoshii * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2976b3b49bStoshii * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3076b3b49bStoshii * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3176b3b49bStoshii * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3276b3b49bStoshii * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3376b3b49bStoshii * SUCH DAMAGE.
3476b3b49bStoshii */
3576b3b49bStoshii
3608716eaeSlukem #include <sys/cdefs.h>
37*86c30724Sandvar __KERNEL_RCSID(0, "$NetBSD: sed_saip.c,v 1.29 2022/05/28 10:36:22 andvar Exp $");
3808716eaeSlukem
3976b3b49bStoshii #include <sys/param.h>
4076b3b49bStoshii #include <sys/systm.h>
4176b3b49bStoshii #include <sys/device.h>
4276b3b49bStoshii #include <sys/buf.h>
4376b3b49bStoshii #include <sys/ioctl.h>
4476b3b49bStoshii #include <sys/reboot.h>
459edf49b0Sdyoung #include <sys/bus.h>
4676b3b49bStoshii
4776b3b49bStoshii #include <machine/bootinfo.h>
4876b3b49bStoshii #include <machine/config_hook.h>
49e671a13dStoshii #include <machine/platid.h>
50e671a13dStoshii #include <machine/platid_mask.h>
5176b3b49bStoshii
5276b3b49bStoshii #include <dev/wscons/wsconsio.h>
5376b3b49bStoshii #include <dev/wscons/wsdisplayvar.h>
5476b3b49bStoshii
5576b3b49bStoshii #include <dev/rasops/rasops.h>
5676b3b49bStoshii
5776b3b49bStoshii #include <dev/hpc/hpcfbvar.h>
5876b3b49bStoshii #include <dev/hpc/hpcfbio.h>
5976b3b49bStoshii #include <dev/hpc/hpccmapvar.h>
6076b3b49bStoshii
61724da0fdSpeter #include <hpcarm/dev/sed1356var.h>
62e671a13dStoshii
63103776feSpeter #ifdef SED_DEBUG
644c494f76Srjs #define VPRINTF(arg) do { if (bootverbose) aprint_normal arg; } while (0)
65103776feSpeter #else
66103776feSpeter #define VPRINTF(arg) /* nothing */
67103776feSpeter #endif
6876b3b49bStoshii
6976b3b49bStoshii /*
70724da0fdSpeter * Function prototypes.
7176b3b49bStoshii */
724c494f76Srjs static int sed1356_match(device_t, cfdata_t, void *);
734c494f76Srjs static void sed1356_attach(device_t, device_t, void *);
7453524e44Schristos static int sed1356_ioctl(void *, u_long, void *, int, struct lwp *);
75724da0fdSpeter static paddr_t sed1356_mmap(void *, off_t, int);
7676b3b49bStoshii
7776b3b49bStoshii static int sed1356_init(struct hpcfb_fbconf *);
7876b3b49bStoshii static void sed1356_power(int, void *);
7976b3b49bStoshii static void sed1356_update_powerstate(struct sed1356_softc *, int);
80724da0fdSpeter static void sed1356_init_backlight(struct sed1356_softc *, int);
81724da0fdSpeter static void sed1356_set_brightness(struct sed1356_softc *, int);
82724da0fdSpeter static void sed1356_set_contrast(struct sed1356_softc *, int);
8376b3b49bStoshii
8476b3b49bStoshii #if defined __mips__ || defined __sh__ || defined __arm__
8576b3b49bStoshii #define __BTOP(x) ((paddr_t)(x) >> PGSHIFT)
8676b3b49bStoshii #define __PTOB(x) ((paddr_t)(x) << PGSHIFT)
8776b3b49bStoshii #else
8876b3b49bStoshii #error "define btop, ptob."
8976b3b49bStoshii #endif
9076b3b49bStoshii
9176b3b49bStoshii /*
92724da0fdSpeter * External functions/variables.
93724da0fdSpeter */
94724da0fdSpeter extern struct cfdriver sed_cd;
95724da0fdSpeter extern struct bus_space sa11x0_bs_tag;
96724da0fdSpeter extern int j720lcd_power(void *, int, long, void *); /* XXX */
97724da0fdSpeter
98724da0fdSpeter /*
99724da0fdSpeter * Static variables.
10076b3b49bStoshii */
1014c494f76Srjs CFATTACH_DECL_NEW(sed, sizeof(struct sed1356_softc),
102724da0fdSpeter sed1356_match, sed1356_attach, NULL, NULL);
10376b3b49bStoshii struct hpcfb_accessops sed1356_ha = {
10476b3b49bStoshii sed1356_ioctl, sed1356_mmap
10576b3b49bStoshii };
10676b3b49bStoshii
10776b3b49bStoshii static int attach_flag = 0;
10876b3b49bStoshii
10976b3b49bStoshii /*
110724da0fdSpeter * Function bodies.
11176b3b49bStoshii */
112724da0fdSpeter static int
sed1356_match(device_t parent,cfdata_t match,void * aux)1134c494f76Srjs sed1356_match(device_t parent, cfdata_t match, void *aux)
11476b3b49bStoshii {
11576b3b49bStoshii
11676b3b49bStoshii /* XXX check version register */
11776b3b49bStoshii return 1;
11876b3b49bStoshii }
11976b3b49bStoshii
120724da0fdSpeter static void
sed1356_attach(device_t parent,device_t self,void * aux)1214c494f76Srjs sed1356_attach(device_t parent, device_t self, void *aux)
12276b3b49bStoshii {
1234c494f76Srjs struct sed1356_softc *sc = device_private(self);
12476b3b49bStoshii struct hpcfb_attach_args ha;
125f8c1bea1Stoshii int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
12676b3b49bStoshii
12776b3b49bStoshii if (attach_flag) {
12876b3b49bStoshii panic("%s(%d): sed1356 attached twice", __FILE__, __LINE__);
12976b3b49bStoshii }
13076b3b49bStoshii attach_flag = 1;
13176b3b49bStoshii
13276b3b49bStoshii if (sed1356_init(&sc->sc_fbconf) != 0) {
13376b3b49bStoshii /* just return so that hpcfb will not be attached */
13476b3b49bStoshii return;
13576b3b49bStoshii }
1364c494f76Srjs aprint_normal("\n");
13776b3b49bStoshii
1384c494f76Srjs sc->sc_dev = self;
139e671a13dStoshii sc->sc_iot = &sa11x0_bs_tag;
1404c494f76Srjs sc->sc_parent = device_private(parent);
141e671a13dStoshii if (bus_space_map(sc->sc_iot, (bus_addr_t)bootinfo->fb_addr & ~0x3fffff,
142e671a13dStoshii 0x200, 0, &sc->sc_regh)) {
1434c494f76Srjs aprint_normal_dev(self, "unable to map register\n");
144e671a13dStoshii return;
145e671a13dStoshii }
146e671a13dStoshii
1474c494f76Srjs aprint_normal_dev(self, "Epson SED1356");
148f8c1bea1Stoshii if (console) {
1494c494f76Srjs aprint_normal(", console");
15076b3b49bStoshii }
1514c494f76Srjs aprint_normal("\n");
1524c494f76Srjs aprint_normal_dev(self, "framebuffer address: 0x%08lx\n",
1534c494f76Srjs (u_long)bootinfo->fb_addr);
15476b3b49bStoshii
15576b3b49bStoshii /* Add a suspend hook to power saving */
15676b3b49bStoshii sc->sc_powerstate = 0;
157cbab9cadSchs sc->sc_powerhook = powerhook_establish(device_xname(self),
158f135e0d6Sjmcneill sed1356_power, sc);
15976b3b49bStoshii if (sc->sc_powerhook == NULL)
1604c494f76Srjs aprint_normal_dev(self, "WARNING: unable to establish power hook\n");
16176b3b49bStoshii
162724da0fdSpeter /* Initialize backlight brightness and lcd contrast */
16376b3b49bStoshii sc->sc_lcd_inited = 0;
16476b3b49bStoshii sed1356_init_brightness(sc, 1);
16576b3b49bStoshii sed1356_init_contrast(sc, 1);
16676b3b49bStoshii sed1356_init_backlight(sc, 1);
16776b3b49bStoshii
168f8c1bea1Stoshii if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0)
169724da0fdSpeter panic("sed1356_attach: cannot init fb console");
170f8c1bea1Stoshii
171f8c1bea1Stoshii ha.ha_console = console;
17276b3b49bStoshii ha.ha_accessops = &sed1356_ha;
17376b3b49bStoshii ha.ha_accessctx = sc;
17476b3b49bStoshii ha.ha_curfbconf = 0;
17576b3b49bStoshii ha.ha_nfbconf = 1;
17676b3b49bStoshii ha.ha_fbconflist = &sc->sc_fbconf;
17776b3b49bStoshii ha.ha_curdspconf = 0;
17876b3b49bStoshii ha.ha_ndspconf = 1;
17976b3b49bStoshii ha.ha_dspconflist = &sc->sc_dspconf;
18076b3b49bStoshii
181e671a13dStoshii /* XXX */
182e671a13dStoshii if (platid_match(&platid, &platid_mask_MACH_HP_JORNADA_7XX)) {
183e671a13dStoshii config_hook(CONFIG_HOOK_POWERCONTROL,
184e671a13dStoshii CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
185547e1f66Speter CONFIG_HOOK_SHARE, j720lcd_power, sc);
186e671a13dStoshii }
187e671a13dStoshii
188c7fb772bSthorpej config_found(self, &ha, hpcfbprint, CFARGS_NONE);
18976b3b49bStoshii }
19076b3b49bStoshii
19176b3b49bStoshii static int
sed1356_init(struct hpcfb_fbconf * fb)19276b3b49bStoshii sed1356_init(struct hpcfb_fbconf *fb)
19376b3b49bStoshii {
19476b3b49bStoshii /*
19576b3b49bStoshii * get fb settings from bootinfo
19676b3b49bStoshii */
19776b3b49bStoshii if (bootinfo == NULL ||
19876b3b49bStoshii bootinfo->fb_addr == 0 ||
19976b3b49bStoshii bootinfo->fb_line_bytes == 0 ||
20076b3b49bStoshii bootinfo->fb_width == 0 ||
20176b3b49bStoshii bootinfo->fb_height == 0) {
2024c494f76Srjs aprint_normal("no frame buffer information.\n");
203724da0fdSpeter return -1;
20476b3b49bStoshii }
20576b3b49bStoshii
20676b3b49bStoshii /* zero fill */
207cd3fb67fSichiro memset(fb, 0, sizeof(*fb));
20876b3b49bStoshii
20976b3b49bStoshii fb->hf_conf_index = 0; /* configuration index */
21076b3b49bStoshii fb->hf_nconfs = 1; /* how many configurations */
21176b3b49bStoshii strcpy(fb->hf_name, "built-in video");
21276b3b49bStoshii /* frame buffer name */
21376b3b49bStoshii strcpy(fb->hf_conf_name, "default");
21476b3b49bStoshii /* configuration name */
21576b3b49bStoshii fb->hf_height = bootinfo->fb_height;
21676b3b49bStoshii fb->hf_width = bootinfo->fb_width;
217e671a13dStoshii
21876b3b49bStoshii if (bus_space_map(&sa11x0_bs_tag, (bus_addr_t)bootinfo->fb_addr,
21976b3b49bStoshii bootinfo->fb_height * bootinfo->fb_line_bytes,
22076b3b49bStoshii 0, &fb->hf_baseaddr)) {
2214c494f76Srjs aprint_normal("unable to map framebuffer\n");
222724da0fdSpeter return -1;
22376b3b49bStoshii }
22476b3b49bStoshii fb->hf_offset = (u_long)bootinfo->fb_addr -
22576b3b49bStoshii __PTOB(__BTOP(bootinfo->fb_addr));
22676b3b49bStoshii /* frame buffer start offset */
22776b3b49bStoshii fb->hf_bytes_per_line = bootinfo->fb_line_bytes;
22876b3b49bStoshii fb->hf_nplanes = 1;
22976b3b49bStoshii fb->hf_bytes_per_plane = bootinfo->fb_height *
23076b3b49bStoshii bootinfo->fb_line_bytes;
23176b3b49bStoshii
23276b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
23376b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_WORD;
23476b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
23576b3b49bStoshii
23676b3b49bStoshii switch (bootinfo->fb_type) {
23776b3b49bStoshii /*
23876b3b49bStoshii * gray scale
23976b3b49bStoshii */
24076b3b49bStoshii case BIFB_D4_M2L_F:
24176b3b49bStoshii case BIFB_D4_M2L_Fx2:
24276b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
24376b3b49bStoshii /* fall through */
24476b3b49bStoshii case BIFB_D4_M2L_0:
24576b3b49bStoshii case BIFB_D4_M2L_0x2:
24676b3b49bStoshii fb->hf_class = HPCFB_CLASS_GRAYSCALE;
24776b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
24876b3b49bStoshii fb->hf_pack_width = 8;
24976b3b49bStoshii fb->hf_pixels_per_pack = 2;
25076b3b49bStoshii fb->hf_pixel_width = 4;
25176b3b49bStoshii fb->hf_class_data_length = sizeof(struct hf_gray_tag);
25276b3b49bStoshii fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
25376b3b49bStoshii break;
25476b3b49bStoshii
25576b3b49bStoshii /*
25676b3b49bStoshii * indexed color
25776b3b49bStoshii */
25876b3b49bStoshii case BIFB_D8_FF:
25976b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
26076b3b49bStoshii /* fall through */
26176b3b49bStoshii case BIFB_D8_00:
26276b3b49bStoshii fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
26376b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
26476b3b49bStoshii fb->hf_pack_width = 8;
26576b3b49bStoshii fb->hf_pixels_per_pack = 1;
26676b3b49bStoshii fb->hf_pixel_width = 8;
26776b3b49bStoshii fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
26876b3b49bStoshii fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
26976b3b49bStoshii break;
27076b3b49bStoshii
27176b3b49bStoshii /*
27276b3b49bStoshii * RGB color
27376b3b49bStoshii */
27476b3b49bStoshii case BIFB_D16_FFFF:
27576b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
27676b3b49bStoshii /* fall through */
27776b3b49bStoshii case BIFB_D16_0000:
27876b3b49bStoshii fb->hf_class = HPCFB_CLASS_RGBCOLOR;
27976b3b49bStoshii fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
28064b6b76aStakemura fb->hf_order_flags = HPCFB_REVORDER_BYTE;
28176b3b49bStoshii fb->hf_pack_width = 16;
28276b3b49bStoshii fb->hf_pixels_per_pack = 1;
28376b3b49bStoshii fb->hf_pixel_width = 16;
28476b3b49bStoshii
28576b3b49bStoshii fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
28676b3b49bStoshii fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */
28776b3b49bStoshii
28876b3b49bStoshii fb->hf_u.hf_rgb.hf_red_width = 5;
28976b3b49bStoshii fb->hf_u.hf_rgb.hf_red_shift = 11;
29076b3b49bStoshii fb->hf_u.hf_rgb.hf_green_width = 6;
29176b3b49bStoshii fb->hf_u.hf_rgb.hf_green_shift = 5;
29276b3b49bStoshii fb->hf_u.hf_rgb.hf_blue_width = 5;
29376b3b49bStoshii fb->hf_u.hf_rgb.hf_blue_shift = 0;
29476b3b49bStoshii fb->hf_u.hf_rgb.hf_alpha_width = 0;
29576b3b49bStoshii fb->hf_u.hf_rgb.hf_alpha_shift = 0;
29676b3b49bStoshii break;
29776b3b49bStoshii
29876b3b49bStoshii default:
2994c494f76Srjs aprint_normal("unsupported type %d.\n", bootinfo->fb_type);
300724da0fdSpeter return -1;
30176b3b49bStoshii }
30276b3b49bStoshii
303724da0fdSpeter return 0; /* no error */
30476b3b49bStoshii }
30576b3b49bStoshii
30676b3b49bStoshii static void
sed1356_power(int why,void * arg)30776b3b49bStoshii sed1356_power(int why, void *arg)
30876b3b49bStoshii {
30976b3b49bStoshii struct sed1356_softc *sc = arg;
31076b3b49bStoshii
31176b3b49bStoshii switch (why) {
31276b3b49bStoshii case PWR_SUSPEND:
31376b3b49bStoshii case PWR_STANDBY:
31476b3b49bStoshii sc->sc_powerstate |= PWRSTAT_SUSPEND;
31576b3b49bStoshii sed1356_update_powerstate(sc, PWRSTAT_ALL);
31676b3b49bStoshii break;
31776b3b49bStoshii case PWR_RESUME:
31876b3b49bStoshii sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
31976b3b49bStoshii sed1356_update_powerstate(sc, PWRSTAT_ALL);
32076b3b49bStoshii break;
32176b3b49bStoshii }
32276b3b49bStoshii }
32376b3b49bStoshii
32476b3b49bStoshii static void
sed1356_update_powerstate(struct sed1356_softc * sc,int updates)32576b3b49bStoshii sed1356_update_powerstate(struct sed1356_softc *sc, int updates)
32676b3b49bStoshii {
32776b3b49bStoshii if (updates & PWRSTAT_LCD)
32876b3b49bStoshii config_hook_call(CONFIG_HOOK_POWERCONTROL,
32976b3b49bStoshii CONFIG_HOOK_POWERCONTROL_LCD,
33076b3b49bStoshii (void *)!(sc->sc_powerstate &
33176b3b49bStoshii (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
33276b3b49bStoshii
33376b3b49bStoshii if (updates & PWRSTAT_BACKLIGHT)
33476b3b49bStoshii config_hook_call(CONFIG_HOOK_POWERCONTROL,
33576b3b49bStoshii CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
33676b3b49bStoshii (void *)(!(sc->sc_powerstate &
33776b3b49bStoshii (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
33876b3b49bStoshii (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
33976b3b49bStoshii }
34076b3b49bStoshii
341724da0fdSpeter static int
sed1356_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)34253524e44Schristos sed1356_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
34376b3b49bStoshii {
34476b3b49bStoshii struct sed1356_softc *sc = (struct sed1356_softc *)v;
34576b3b49bStoshii struct hpcfb_fbconf *fbconf;
34676b3b49bStoshii struct hpcfb_dspconf *dspconf;
34776b3b49bStoshii struct wsdisplay_param *dispparam;
34876b3b49bStoshii
34976b3b49bStoshii switch (cmd) {
35076b3b49bStoshii case WSDISPLAYIO_GETCMAP:
35176b3b49bStoshii case WSDISPLAYIO_PUTCMAP:
35276b3b49bStoshii /*
35376b3b49bStoshii * XXX should be able to handle color map in 4/8 bpp mode.
35476b3b49bStoshii */
355724da0fdSpeter return EINVAL;
35676b3b49bStoshii
35776b3b49bStoshii case WSDISPLAYIO_SVIDEO:
35876b3b49bStoshii if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
35976b3b49bStoshii sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
36076b3b49bStoshii else
36176b3b49bStoshii sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
36276b3b49bStoshii sed1356_update_powerstate(sc, PWRSTAT_ALL);
36376b3b49bStoshii return 0;
36476b3b49bStoshii
36576b3b49bStoshii case WSDISPLAYIO_GVIDEO:
36676b3b49bStoshii *(int *)data = (sc->sc_powerstate & PWRSTAT_VIDEOOFF) ?
36776b3b49bStoshii WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
36876b3b49bStoshii return 0;
36976b3b49bStoshii
37076b3b49bStoshii case WSDISPLAYIO_GETPARAM:
37176b3b49bStoshii dispparam = (struct wsdisplay_param *)data;
37276b3b49bStoshii switch (dispparam->param) {
37376b3b49bStoshii case WSDISPLAYIO_PARAM_BACKLIGHT:
37476b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:BACKLIGHT\n"));
37576b3b49bStoshii sed1356_init_brightness(sc, 0);
37676b3b49bStoshii sed1356_init_backlight(sc, 0);
37776b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:(real)BACKLIGHT %d\n",
37876b3b49bStoshii (sc->sc_powerstate & PWRSTAT_BACKLIGHT) ? 1: 0));
37976b3b49bStoshii dispparam->min = 0;
38076b3b49bStoshii dispparam->max = 1;
38176b3b49bStoshii if (sc->sc_max_brightness > 0)
382724da0fdSpeter dispparam->curval = (sc->sc_brightness > 0) ?
383724da0fdSpeter 1 : 0;
38476b3b49bStoshii else
38576b3b49bStoshii dispparam->curval =
386724da0fdSpeter (sc->sc_powerstate & PWRSTAT_BACKLIGHT) ?
387724da0fdSpeter 1 : 0;
38876b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:BACKLIGHT:%d(%s)\n",
389724da0fdSpeter dispparam->curval, (sc->sc_max_brightness > 0) ?
390724da0fdSpeter "brightness": "light"));
39176b3b49bStoshii return 0;
392724da0fdSpeter
39376b3b49bStoshii case WSDISPLAYIO_PARAM_CONTRAST:
39476b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:CONTRAST\n"));
39576b3b49bStoshii sed1356_init_contrast(sc, 0);
39676b3b49bStoshii if (sc->sc_max_contrast > 0) {
39776b3b49bStoshii dispparam->min = 0;
39876b3b49bStoshii dispparam->max = sc->sc_max_contrast;
39976b3b49bStoshii dispparam->curval = sc->sc_contrast;
400724da0fdSpeter VPRINTF(("sed1356_ioctl: GET:CONTRAST max=%d,"
401724da0fdSpeter " current=%d\n", sc->sc_max_contrast,
402724da0fdSpeter sc->sc_contrast));
40376b3b49bStoshii return 0;
40476b3b49bStoshii }
405724da0fdSpeter VPRINTF(("sed1356_ioctl: GET:CONTRAST EINVAL\n"));
406724da0fdSpeter return EINVAL;
407724da0fdSpeter
40876b3b49bStoshii case WSDISPLAYIO_PARAM_BRIGHTNESS:
40976b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:BRIGHTNESS\n"));
41076b3b49bStoshii sed1356_init_brightness(sc, 0);
41176b3b49bStoshii if (sc->sc_max_brightness > 0) {
41276b3b49bStoshii dispparam->min = 0;
41376b3b49bStoshii dispparam->max = sc->sc_max_brightness;
41476b3b49bStoshii dispparam->curval = sc->sc_brightness;
415724da0fdSpeter VPRINTF(("sed1356_ioctl: GET:BRIGHTNESS max=%d,"
416724da0fdSpeter " current=%d\n", sc->sc_max_brightness,
417724da0fdSpeter sc->sc_brightness));
41876b3b49bStoshii return 0;
419724da0fdSpeter }
42076b3b49bStoshii VPRINTF(("sed1356_ioctl: GET:BRIGHTNESS EINVAL\n"));
421724da0fdSpeter return EINVAL;
422724da0fdSpeter
42376b3b49bStoshii default:
424724da0fdSpeter return EINVAL;
42576b3b49bStoshii }
426724da0fdSpeter break;
42776b3b49bStoshii
42876b3b49bStoshii case WSDISPLAYIO_SETPARAM:
42976b3b49bStoshii dispparam = (struct wsdisplay_param*)data;
43076b3b49bStoshii switch (dispparam->param) {
43176b3b49bStoshii case WSDISPLAYIO_PARAM_BACKLIGHT:
43276b3b49bStoshii VPRINTF(("sed1356_ioctl: SET:BACKLIGHT\n"));
433724da0fdSpeter if (dispparam->curval < 0 || 1 < dispparam->curval)
434724da0fdSpeter return EINVAL;
43576b3b49bStoshii sed1356_init_brightness(sc, 0);
436724da0fdSpeter VPRINTF(("sed1356_ioctl: SET:max brightness=%d\n",
437724da0fdSpeter sc->sc_max_brightness));
43876b3b49bStoshii if (sc->sc_max_brightness > 0) { /* dimmer */
43976b3b49bStoshii if (dispparam->curval == 0){
440724da0fdSpeter sc->sc_brightness_save =
441724da0fdSpeter sc->sc_brightness;
44276b3b49bStoshii sed1356_set_brightness(sc, 0); /* min */
44376b3b49bStoshii } else {
44476b3b49bStoshii if (sc->sc_brightness_save == 0)
445724da0fdSpeter sc->sc_brightness_save =
446724da0fdSpeter sc->sc_max_brightness;
447724da0fdSpeter sed1356_set_brightness(sc,
448724da0fdSpeter sc->sc_brightness_save);
44976b3b49bStoshii }
450724da0fdSpeter VPRINTF(("sed1356_ioctl: SET:BACKLIGHT:"
451724da0fdSpeter "brightness=%d\n", sc->sc_brightness));
45276b3b49bStoshii } else { /* off */
45376b3b49bStoshii if (dispparam->curval == 0)
45476b3b49bStoshii sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
45576b3b49bStoshii else
45676b3b49bStoshii sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
457724da0fdSpeter VPRINTF(("sed1356_ioctl: SET:BACKLIGHT:"
458724da0fdSpeter "powerstate %d\n", (sc->sc_powerstate &
459724da0fdSpeter PWRSTAT_BACKLIGHT) ? 1 : 0));
46076b3b49bStoshii sed1356_update_powerstate(sc, PWRSTAT_BACKLIGHT);
46176b3b49bStoshii VPRINTF(("sed1356_ioctl: SET:BACKLIGHT:%d\n",
462724da0fdSpeter (sc->sc_powerstate & PWRSTAT_BACKLIGHT) ?
463724da0fdSpeter 1 : 0));
46476b3b49bStoshii }
46576b3b49bStoshii return 0;
466724da0fdSpeter
46776b3b49bStoshii case WSDISPLAYIO_PARAM_CONTRAST:
46876b3b49bStoshii VPRINTF(("sed1356_ioctl: SET:CONTRAST\n"));
46976b3b49bStoshii sed1356_init_contrast(sc, 0);
47076b3b49bStoshii if (dispparam->curval < 0 ||
47176b3b49bStoshii sc->sc_max_contrast < dispparam->curval)
472724da0fdSpeter return EINVAL;
47376b3b49bStoshii if (sc->sc_max_contrast > 0) {
474d6a89fc1Speter VPRINTF(("sed1356_ioctl: SET:CONTRAST org=%d",
475d6a89fc1Speter sc->sc_contrast));
47676b3b49bStoshii sed1356_set_contrast(sc, dispparam->curval);
477d6a89fc1Speter VPRINTF((", current=%d\n", sc->sc_contrast));
47876b3b49bStoshii return 0;
47976b3b49bStoshii }
480724da0fdSpeter VPRINTF(("sed1356_ioctl: SET:CONTRAST EINVAL\n"));
481724da0fdSpeter return EINVAL;
482724da0fdSpeter
48376b3b49bStoshii case WSDISPLAYIO_PARAM_BRIGHTNESS:
48476b3b49bStoshii VPRINTF(("sed1356_ioctl: SET:BRIGHTNESS\n"));
48576b3b49bStoshii sed1356_init_brightness(sc, 0);
48676b3b49bStoshii if (dispparam->curval < 0 ||
48776b3b49bStoshii sc->sc_max_brightness < dispparam->curval)
488724da0fdSpeter return EINVAL;
48976b3b49bStoshii if (sc->sc_max_brightness > 0) {
490d6a89fc1Speter VPRINTF(("sed1356_ioctl: SET:BRIGHTNESS org=%d",
491d6a89fc1Speter sc->sc_brightness));
49276b3b49bStoshii sed1356_set_brightness(sc, dispparam->curval);
493d6a89fc1Speter VPRINTF((", current=%d\n", sc->sc_brightness));
49476b3b49bStoshii return 0;
495724da0fdSpeter }
49676b3b49bStoshii VPRINTF(("sed1356_ioctl: SET:BRIGHTNESS EINVAL\n"));
497724da0fdSpeter return EINVAL;
498724da0fdSpeter
49976b3b49bStoshii default:
500724da0fdSpeter return EINVAL;
50176b3b49bStoshii }
502724da0fdSpeter return 0;
50376b3b49bStoshii
50476b3b49bStoshii case HPCFBIO_GCONF:
50576b3b49bStoshii fbconf = (struct hpcfb_fbconf *)data;
50676b3b49bStoshii if (fbconf->hf_conf_index != 0 &&
50776b3b49bStoshii fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
508724da0fdSpeter return EINVAL;
50976b3b49bStoshii }
51076b3b49bStoshii *fbconf = sc->sc_fbconf; /* structure assignment */
511724da0fdSpeter return 0;
51276b3b49bStoshii case HPCFBIO_SCONF:
51376b3b49bStoshii fbconf = (struct hpcfb_fbconf *)data;
51476b3b49bStoshii if (fbconf->hf_conf_index != 0 &&
51576b3b49bStoshii fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
516724da0fdSpeter return EINVAL;
51776b3b49bStoshii }
51876b3b49bStoshii /*
519964859d8Sabs * nothing to do because we have only one configuration
52076b3b49bStoshii */
521724da0fdSpeter return 0;
52276b3b49bStoshii case HPCFBIO_GDSPCONF:
52376b3b49bStoshii dspconf = (struct hpcfb_dspconf *)data;
52476b3b49bStoshii if ((dspconf->hd_unit_index != 0 &&
52576b3b49bStoshii dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
52676b3b49bStoshii (dspconf->hd_conf_index != 0 &&
52776b3b49bStoshii dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
528724da0fdSpeter return EINVAL;
52976b3b49bStoshii }
53076b3b49bStoshii *dspconf = sc->sc_dspconf; /* structure assignment */
531724da0fdSpeter return 0;
53276b3b49bStoshii case HPCFBIO_SDSPCONF:
53376b3b49bStoshii dspconf = (struct hpcfb_dspconf *)data;
53476b3b49bStoshii if ((dspconf->hd_unit_index != 0 &&
53576b3b49bStoshii dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
53676b3b49bStoshii (dspconf->hd_conf_index != 0 &&
53776b3b49bStoshii dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
538724da0fdSpeter return EINVAL;
53976b3b49bStoshii }
54076b3b49bStoshii /*
54176b3b49bStoshii * nothing to do
542964859d8Sabs * because we have only one unit and one configuration
54376b3b49bStoshii */
544724da0fdSpeter return 0;
54576b3b49bStoshii case HPCFBIO_GOP:
54676b3b49bStoshii case HPCFBIO_SOP:
54776b3b49bStoshii /*
548*86c30724Sandvar * currently not implemented...
54976b3b49bStoshii */
550724da0fdSpeter return EINVAL;
55176b3b49bStoshii }
55276b3b49bStoshii
553724da0fdSpeter return EPASSTHROUGH;
55476b3b49bStoshii }
55576b3b49bStoshii
556724da0fdSpeter static paddr_t
sed1356_mmap(void * ctx,off_t offset,int prot)55776b3b49bStoshii sed1356_mmap(void *ctx, off_t offset, int prot)
55876b3b49bStoshii {
55976b3b49bStoshii struct sed1356_softc *sc = (struct sed1356_softc *)ctx;
56076b3b49bStoshii
56176b3b49bStoshii if (offset < 0 ||
56276b3b49bStoshii (sc->sc_fbconf.hf_bytes_per_plane +
56376b3b49bStoshii sc->sc_fbconf.hf_offset) < offset)
56476b3b49bStoshii return -1;
56576b3b49bStoshii
56676b3b49bStoshii return __BTOP((u_long)bootinfo->fb_addr + offset);
56776b3b49bStoshii }
56876b3b49bStoshii
569724da0fdSpeter static void
sed1356_init_backlight(struct sed1356_softc * sc,int inattach)57076b3b49bStoshii sed1356_init_backlight(struct sed1356_softc *sc, int inattach)
57176b3b49bStoshii {
57276b3b49bStoshii int val = -1;
57376b3b49bStoshii
57476b3b49bStoshii if (sc->sc_lcd_inited & BACKLIGHT_INITED)
57576b3b49bStoshii return;
57676b3b49bStoshii
57776b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
57876b3b49bStoshii CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
57976b3b49bStoshii /* we can get real light state */
58076b3b49bStoshii VPRINTF(("sed1356_init_backlight: real backlight=%d\n", val));
58176b3b49bStoshii if (val == 0)
58276b3b49bStoshii sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
58376b3b49bStoshii else
58476b3b49bStoshii sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
58576b3b49bStoshii sc->sc_lcd_inited |= BACKLIGHT_INITED;
58676b3b49bStoshii } else if (inattach) {
58776b3b49bStoshii /*
58876b3b49bStoshii we cannot get real light state in attach time
58976b3b49bStoshii because light device not yet attached.
59076b3b49bStoshii we will retry in !inattach.
59176b3b49bStoshii temporary assume light is on.
59276b3b49bStoshii */
59376b3b49bStoshii sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
59476b3b49bStoshii } else {
59576b3b49bStoshii /* we cannot get real light state, so work by myself state */
59676b3b49bStoshii sc->sc_lcd_inited |= BACKLIGHT_INITED;
59776b3b49bStoshii }
59876b3b49bStoshii }
59976b3b49bStoshii
60076b3b49bStoshii void
sed1356_init_brightness(struct sed1356_softc * sc,int inattach)60176b3b49bStoshii sed1356_init_brightness(struct sed1356_softc *sc, int inattach)
60276b3b49bStoshii {
60376b3b49bStoshii int val = -1;
60476b3b49bStoshii
60576b3b49bStoshii if (sc->sc_lcd_inited & BRIGHTNESS_INITED)
60676b3b49bStoshii return;
60776b3b49bStoshii
60876b3b49bStoshii VPRINTF(("sed1356_init_brightness\n"));
60976b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
61076b3b49bStoshii CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
61176b3b49bStoshii /* we can get real brightness max */
612724da0fdSpeter VPRINTF(("sed1356_init_brightness: "
613724da0fdSpeter "real brightness max=%d\n", val));
61476b3b49bStoshii sc->sc_max_brightness = val;
61576b3b49bStoshii val = -1;
61676b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
61776b3b49bStoshii CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
61876b3b49bStoshii /* we can get real brightness */
619724da0fdSpeter VPRINTF(("sed1356_init_brightness: "
620724da0fdSpeter "real brightness=%d\n", val));
62176b3b49bStoshii sc->sc_brightness_save = sc->sc_brightness = val;
62276b3b49bStoshii } else {
62376b3b49bStoshii sc->sc_brightness_save =
62476b3b49bStoshii sc->sc_brightness = sc->sc_max_brightness;
62576b3b49bStoshii }
62676b3b49bStoshii sc->sc_lcd_inited |= BRIGHTNESS_INITED;
62776b3b49bStoshii } else if (inattach) {
62876b3b49bStoshii /*
629724da0fdSpeter * we cannot get real brightness in attach time
630724da0fdSpeter * because brightness device not yet attached.
631724da0fdSpeter * we will retry in !inattach.
63276b3b49bStoshii */
63376b3b49bStoshii sc->sc_max_brightness = -1;
63476b3b49bStoshii sc->sc_brightness = -1;
63576b3b49bStoshii sc->sc_brightness_save = -1;
63676b3b49bStoshii } else {
63776b3b49bStoshii /* we cannot get real brightness */
63876b3b49bStoshii sc->sc_lcd_inited |= BRIGHTNESS_INITED;
63976b3b49bStoshii }
64076b3b49bStoshii }
64176b3b49bStoshii
64276b3b49bStoshii void
sed1356_init_contrast(struct sed1356_softc * sc,int inattach)64376b3b49bStoshii sed1356_init_contrast(struct sed1356_softc *sc, int inattach)
64476b3b49bStoshii {
64576b3b49bStoshii int val = -1;
64676b3b49bStoshii
64776b3b49bStoshii if (sc->sc_lcd_inited & CONTRAST_INITED)
64876b3b49bStoshii return;
64976b3b49bStoshii
65076b3b49bStoshii VPRINTF(("sed1356_init_contrast\n"));
65176b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
65276b3b49bStoshii CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
65376b3b49bStoshii /* we can get real contrast max */
654724da0fdSpeter VPRINTF(("sed1356_init_contrast: "
655724da0fdSpeter "real contrast max=%d\n", val));
65676b3b49bStoshii sc->sc_max_contrast = val;
65776b3b49bStoshii val = -1;
65876b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
65976b3b49bStoshii CONFIG_HOOK_CONTRAST, &val) != -1) {
66076b3b49bStoshii /* we can get real contrast */
661724da0fdSpeter VPRINTF(("sed1356_init_contrast: "
662724da0fdSpeter "real contrast=%d\n", val));
66376b3b49bStoshii sc->sc_contrast = val;
66476b3b49bStoshii } else {
66576b3b49bStoshii sc->sc_contrast = sc->sc_max_contrast;
66676b3b49bStoshii }
66776b3b49bStoshii sc->sc_lcd_inited |= CONTRAST_INITED;
66876b3b49bStoshii } else if (inattach) {
66976b3b49bStoshii /*
670724da0fdSpeter * we cannot get real contrast in attach time
671724da0fdSpeter * because contrast device not yet attached.
672724da0fdSpeter * we will retry in !inattach.
67376b3b49bStoshii */
67476b3b49bStoshii sc->sc_max_contrast = -1;
67576b3b49bStoshii sc->sc_contrast = -1;
67676b3b49bStoshii } else {
67776b3b49bStoshii /* we cannot get real contrast */
67876b3b49bStoshii sc->sc_lcd_inited |= CONTRAST_INITED;
67976b3b49bStoshii }
68076b3b49bStoshii }
68176b3b49bStoshii
682724da0fdSpeter static void
sed1356_set_brightness(struct sed1356_softc * sc,int val)68376b3b49bStoshii sed1356_set_brightness(struct sed1356_softc *sc, int val)
68476b3b49bStoshii {
68576b3b49bStoshii sc->sc_brightness = val;
68676b3b49bStoshii
68776b3b49bStoshii config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
68876b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
68976b3b49bStoshii CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
69076b3b49bStoshii sc->sc_brightness = val;
69176b3b49bStoshii }
69276b3b49bStoshii }
69376b3b49bStoshii
694724da0fdSpeter static void
sed1356_set_contrast(struct sed1356_softc * sc,int val)69576b3b49bStoshii sed1356_set_contrast(struct sed1356_softc *sc, int val)
69676b3b49bStoshii {
69776b3b49bStoshii sc->sc_contrast = val;
69876b3b49bStoshii
69976b3b49bStoshii config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
70076b3b49bStoshii if (config_hook_call(CONFIG_HOOK_GET,
70176b3b49bStoshii CONFIG_HOOK_CONTRAST, &val) != -1) {
70276b3b49bStoshii sc->sc_contrast = val;
70376b3b49bStoshii }
70476b3b49bStoshii }
705547e1f66Speter
706547e1f66Speter void
sed1356_toggle_lcdlight(void)707547e1f66Speter sed1356_toggle_lcdlight(void)
708547e1f66Speter {
709cf990769Srafal struct sed1356_softc *sc = device_lookup_private(&sed_cd, 0);
710547e1f66Speter
711547e1f66Speter if (sc->sc_powerstate & PWRSTAT_VIDEOOFF)
712547e1f66Speter sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
713547e1f66Speter else
714547e1f66Speter sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
715547e1f66Speter
716547e1f66Speter sed1356_update_powerstate(sc, PWRSTAT_ALL);
717547e1f66Speter }
718