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