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