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