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