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