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