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