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