bivideo.c revision 1.14 1 1.14 thorpej /* $NetBSD: bivideo.c,v 1.14 2002/09/27 02:24:29 thorpej 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.14 thorpej __KERNEL_RCSID(0, "$NetBSD: bivideo.c,v 1.14 2002/09/27 02:24:29 thorpej Exp $");
39 1.12 lukem
40 1.1 uch #define FBDEBUG
41 1.1 uch static const char _copyright[] __attribute__ ((unused)) =
42 1.1 uch "Copyright (c) 1999 Shin Takemura. All rights reserved.";
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.1 uch #include <uvm/uvm_extern.h>
52 1.1 uch
53 1.1 uch #include <machine/bus.h>
54 1.1 uch #include <machine/autoconf.h>
55 1.1 uch #include <machine/bootinfo.h>
56 1.1 uch #include <machine/config_hook.h>
57 1.1 uch
58 1.1 uch #include <dev/wscons/wsconsio.h>
59 1.1 uch #include <dev/wscons/wsdisplayvar.h>
60 1.1 uch
61 1.1 uch #include <dev/rasops/rasops.h>
62 1.1 uch
63 1.1 uch #include <dev/hpc/hpcfbvar.h>
64 1.1 uch #include <dev/hpc/hpcfbio.h>
65 1.1 uch #include <dev/hpc/bivideovar.h>
66 1.1 uch #include <dev/hpc/hpccmapvar.h>
67 1.1 uch
68 1.1 uch #define VPRINTF(arg) do { if (bootverbose) printf arg; } while(0);
69 1.1 uch
70 1.1 uch /*
71 1.1 uch * global variables
72 1.1 uch */
73 1.1 uch int bivideo_dont_attach = 0;
74 1.1 uch
75 1.1 uch /*
76 1.1 uch * function prototypes
77 1.1 uch */
78 1.2 uch int bivideomatch(struct device *, struct cfdata *, void *);
79 1.2 uch void bivideoattach(struct device *, struct device *, void *);
80 1.2 uch int bivideo_ioctl(void *, u_long, caddr_t, int, struct proc *);
81 1.2 uch paddr_t bivideo_mmap(void *, off_t, int);
82 1.1 uch
83 1.1 uch struct bivideo_softc {
84 1.1 uch struct device sc_dev;
85 1.1 uch struct hpcfb_fbconf sc_fbconf;
86 1.1 uch struct hpcfb_dspconf sc_dspconf;
87 1.1 uch void *sc_powerhook; /* power management hook */
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.6 sato void bivideo_init_backlight(struct bivideo_softc *, int);
110 1.6 sato void bivideo_init_brightness(struct bivideo_softc *, int);
111 1.6 sato void bivideo_init_contrast(struct bivideo_softc *, int);
112 1.3 sato void bivideo_set_brightness(struct bivideo_softc *, int);
113 1.3 sato void bivideo_set_contrast(struct bivideo_softc *, int);
114 1.2 uch
115 1.2 uch #if defined __mips__ || defined __sh__ || defined __arm__
116 1.2 uch #define __BTOP(x) ((paddr_t)(x) >> PGSHIFT)
117 1.2 uch #define __PTOB(x) ((paddr_t)(x) << PGSHIFT)
118 1.2 uch #else
119 1.2 uch #error "define btop, ptob."
120 1.2 uch #endif
121 1.1 uch
122 1.1 uch /*
123 1.1 uch * static variables
124 1.1 uch */
125 1.1 uch struct cfattach bivideo_ca = {
126 1.1 uch sizeof(struct bivideo_softc), bivideomatch, bivideoattach,
127 1.1 uch };
128 1.1 uch struct hpcfb_accessops bivideo_ha = {
129 1.1 uch bivideo_ioctl, bivideo_mmap
130 1.1 uch };
131 1.1 uch
132 1.1 uch static int console_flag = 0;
133 1.1 uch static int attach_flag = 0;
134 1.1 uch
135 1.1 uch /*
136 1.1 uch * function bodies
137 1.1 uch */
138 1.1 uch int
139 1.2 uch bivideomatch(struct device *parent, struct cfdata *match, void *aux)
140 1.1 uch {
141 1.1 uch struct mainbus_attach_args *ma = aux;
142 1.1 uch
143 1.1 uch if (bivideo_dont_attach ||
144 1.14 thorpej strcmp(ma->ma_name, match->cf_name))
145 1.1 uch return 0;
146 1.1 uch
147 1.1 uch return (1);
148 1.1 uch }
149 1.1 uch
150 1.1 uch void
151 1.2 uch bivideoattach(struct device *parent, struct device *self, void *aux)
152 1.1 uch {
153 1.1 uch struct bivideo_softc *sc = (struct bivideo_softc *)self;
154 1.1 uch struct hpcfb_attach_args ha;
155 1.1 uch
156 1.1 uch if (attach_flag) {
157 1.1 uch panic("%s(%d): bivideo attached twice", __FILE__, __LINE__);
158 1.1 uch }
159 1.1 uch attach_flag = 1;
160 1.1 uch
161 1.1 uch printf(": ");
162 1.1 uch if (bivideo_init(&sc->sc_fbconf) != 0) {
163 1.1 uch /* just return so that hpcfb will not be attached */
164 1.1 uch return;
165 1.1 uch }
166 1.1 uch
167 1.1 uch printf("pseudo video controller");
168 1.1 uch if (console_flag) {
169 1.1 uch printf(", console");
170 1.1 uch }
171 1.1 uch printf("\n");
172 1.1 uch printf("%s: framebuffer address: 0x%08lx\n",
173 1.1 uch sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr);
174 1.1 uch
175 1.1 uch /* Add a suspend hook to power saving */
176 1.1 uch sc->sc_powerstate = 0;
177 1.1 uch sc->sc_powerhook = powerhook_establish(bivideo_power, sc);
178 1.1 uch if (sc->sc_powerhook == NULL)
179 1.1 uch printf("%s: WARNING: unable to establish power hook\n",
180 1.1 uch sc->sc_dev.dv_xname);
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.1 uch config_found(self, &ha, hpcfbprint);
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.1 uch 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.4 sato (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.4 sato (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.1 uch int
372 1.2 uch bivideo_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
373 1.1 uch {
374 1.1 uch struct bivideo_softc *sc = (struct bivideo_softc *)v;
375 1.1 uch struct hpcfb_fbconf *fbconf;
376 1.1 uch struct hpcfb_dspconf *dspconf;
377 1.1 uch struct wsdisplay_cmap *cmap;
378 1.1 uch struct wsdisplay_param *dispparam;
379 1.1 uch
380 1.1 uch switch (cmd) {
381 1.1 uch case WSDISPLAYIO_GETCMAP:
382 1.1 uch cmap = (struct wsdisplay_cmap*)data;
383 1.1 uch
384 1.1 uch if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
385 1.1 uch sc->sc_fbconf.hf_pack_width != 8 ||
386 1.1 uch 256 <= cmap->index ||
387 1.1 uch 256 < (cmap->index + cmap->count))
388 1.1 uch return (EINVAL);
389 1.1 uch
390 1.1 uch if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) ||
391 1.1 uch !uvm_useracc(cmap->green, cmap->count, B_WRITE) ||
392 1.1 uch !uvm_useracc(cmap->blue, cmap->count, B_WRITE))
393 1.1 uch return (EFAULT);
394 1.1 uch
395 1.1 uch copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count);
396 1.1 uch copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count);
397 1.1 uch copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count);
398 1.1 uch
399 1.1 uch return (0);
400 1.1 uch
401 1.1 uch case WSDISPLAYIO_PUTCMAP:
402 1.1 uch /*
403 1.1 uch * This driver can't set color map.
404 1.1 uch */
405 1.1 uch return (EINVAL);
406 1.4 sato
407 1.4 sato case WSDISPLAYIO_SVIDEO:
408 1.4 sato if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
409 1.4 sato sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
410 1.4 sato else
411 1.4 sato sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
412 1.4 sato bivideo_update_powerstate(sc, PWRSTAT_ALL);
413 1.4 sato return 0;
414 1.4 sato
415 1.4 sato case WSDISPLAYIO_GVIDEO:
416 1.4 sato *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
417 1.4 sato WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
418 1.4 sato return 0;
419 1.1 uch
420 1.3 sato
421 1.1 uch case WSDISPLAYIO_GETPARAM:
422 1.1 uch dispparam = (struct wsdisplay_param*)data;
423 1.1 uch switch (dispparam->param) {
424 1.1 uch case WSDISPLAYIO_PARAM_BACKLIGHT:
425 1.6 sato VPRINTF(("bivideo_ioctl: GET:BACKLIGHT\n"));
426 1.6 sato bivideo_init_brightness(sc, 0);
427 1.6 sato bivideo_init_backlight(sc, 0);
428 1.6 sato VPRINTF(("bivideo_ioctl: GET:(real)BACKLIGHT %d\n",
429 1.6 sato (sc->sc_powerstate&PWRSTAT_BACKLIGHT)? 1: 0));
430 1.1 uch dispparam->min = 0;
431 1.1 uch dispparam->max = 1;
432 1.3 sato if (sc->sc_max_brightness > 0)
433 1.3 sato dispparam->curval = sc->sc_brightness > 0? 1: 0;
434 1.3 sato else
435 1.3 sato dispparam->curval =
436 1.6 sato (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1: 0;
437 1.6 sato VPRINTF(("bivideo_ioctl: GET:BACKLIGHT:%d(%s)\n",
438 1.6 sato dispparam->curval,
439 1.6 sato sc->sc_max_brightness > 0? "brightness": "light"));
440 1.3 sato return 0;
441 1.1 uch break;
442 1.1 uch case WSDISPLAYIO_PARAM_CONTRAST:
443 1.6 sato VPRINTF(("bivideo_ioctl: GET:CONTRAST\n"));
444 1.6 sato bivideo_init_contrast(sc, 0);
445 1.3 sato if (sc->sc_max_contrast > 0) {
446 1.3 sato dispparam->min = 0;
447 1.3 sato dispparam->max = sc->sc_max_contrast;
448 1.3 sato dispparam->curval = sc->sc_contrast;
449 1.6 sato VPRINTF(("bivideo_ioctl: GET:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast));
450 1.3 sato return 0;
451 1.3 sato } else {
452 1.6 sato VPRINTF(("bivideo_ioctl: GET:CONTRAST EINVAL\n"));
453 1.3 sato return (EINVAL);
454 1.3 sato }
455 1.3 sato break;
456 1.1 uch case WSDISPLAYIO_PARAM_BRIGHTNESS:
457 1.6 sato VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS\n"));
458 1.6 sato bivideo_init_brightness(sc, 0);
459 1.3 sato if (sc->sc_max_brightness > 0) {
460 1.3 sato dispparam->min = 0;
461 1.3 sato dispparam->max = sc->sc_max_brightness;
462 1.3 sato dispparam->curval = sc->sc_brightness;
463 1.6 sato VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness));
464 1.3 sato return 0;
465 1.3 sato } else {
466 1.6 sato VPRINTF(("bivideo_ioctl: GET:BRIGHTNESS EINVAL\n"));
467 1.3 sato return (EINVAL);
468 1.3 sato }
469 1.1 uch return (EINVAL);
470 1.1 uch default:
471 1.1 uch return (EINVAL);
472 1.1 uch }
473 1.1 uch return (0);
474 1.1 uch
475 1.1 uch case WSDISPLAYIO_SETPARAM:
476 1.1 uch dispparam = (struct wsdisplay_param*)data;
477 1.1 uch switch (dispparam->param) {
478 1.1 uch case WSDISPLAYIO_PARAM_BACKLIGHT:
479 1.6 sato VPRINTF(("bivideo_ioctl: SET:BACKLIGHT\n"));
480 1.1 uch if (dispparam->curval < 0 ||
481 1.1 uch 1 < dispparam->curval)
482 1.1 uch return (EINVAL);
483 1.6 sato bivideo_init_brightness(sc, 0);
484 1.6 sato VPRINTF(("bivideo_ioctl: SET:max brightness=%d\n", sc->sc_max_brightness));
485 1.3 sato if (sc->sc_max_brightness > 0) { /* dimmer */
486 1.3 sato if (dispparam->curval == 0){
487 1.3 sato sc->sc_brightness_save = sc->sc_brightness;
488 1.3 sato bivideo_set_brightness(sc, 0); /* min */
489 1.3 sato } else {
490 1.3 sato if (sc->sc_brightness_save == 0)
491 1.3 sato sc->sc_brightness_save = sc->sc_max_brightness;
492 1.3 sato bivideo_set_brightness(sc, sc->sc_brightness_save);
493 1.3 sato }
494 1.6 sato VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:brightness=%d\n", sc->sc_brightness));
495 1.3 sato } else { /* off */
496 1.3 sato if (dispparam->curval == 0)
497 1.3 sato sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
498 1.3 sato else
499 1.3 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
500 1.6 sato VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:powerstate %d\n",
501 1.3 sato (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
502 1.3 sato bivideo_update_powerstate(sc, PWRSTAT_BACKLIGHT);
503 1.6 sato VPRINTF(("bivideo_ioctl: SET:BACKLIGHT:%d\n",
504 1.3 sato (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
505 1.3 sato }
506 1.3 sato return 0;
507 1.1 uch break;
508 1.1 uch case WSDISPLAYIO_PARAM_CONTRAST:
509 1.6 sato VPRINTF(("bivideo_ioctl: SET:CONTRAST\n"));
510 1.6 sato bivideo_init_contrast(sc, 0);
511 1.3 sato if (dispparam->curval < 0 ||
512 1.3 sato sc->sc_max_contrast < dispparam->curval)
513 1.3 sato return (EINVAL);
514 1.3 sato if (sc->sc_max_contrast > 0) {
515 1.3 sato int org = sc->sc_contrast;
516 1.3 sato bivideo_set_contrast(sc, dispparam->curval);
517 1.6 sato VPRINTF(("bivideo_ioctl: SET:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast));
518 1.3 sato return 0;
519 1.3 sato } else {
520 1.6 sato VPRINTF(("bivideo_ioctl: SET:CONTRAST EINVAL\n"));
521 1.3 sato return (EINVAL);
522 1.3 sato }
523 1.3 sato break;
524 1.1 uch case WSDISPLAYIO_PARAM_BRIGHTNESS:
525 1.6 sato VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS\n"));
526 1.6 sato bivideo_init_brightness(sc, 0);
527 1.3 sato if (dispparam->curval < 0 ||
528 1.3 sato sc->sc_max_brightness < dispparam->curval)
529 1.3 sato return (EINVAL);
530 1.3 sato if (sc->sc_max_brightness > 0) {
531 1.3 sato int org = sc->sc_brightness;
532 1.3 sato bivideo_set_brightness(sc, dispparam->curval);
533 1.6 sato VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness));
534 1.3 sato return 0;
535 1.3 sato } else {
536 1.6 sato VPRINTF(("bivideo_ioctl: SET:BRIGHTNESS EINVAL\n"));
537 1.3 sato return (EINVAL);
538 1.3 sato }
539 1.3 sato break;
540 1.1 uch default:
541 1.1 uch return (EINVAL);
542 1.1 uch }
543 1.1 uch return (0);
544 1.1 uch
545 1.1 uch case HPCFBIO_GCONF:
546 1.1 uch fbconf = (struct hpcfb_fbconf *)data;
547 1.1 uch if (fbconf->hf_conf_index != 0 &&
548 1.1 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
549 1.1 uch return (EINVAL);
550 1.1 uch }
551 1.1 uch *fbconf = sc->sc_fbconf; /* structure assignment */
552 1.1 uch return (0);
553 1.1 uch case HPCFBIO_SCONF:
554 1.1 uch fbconf = (struct hpcfb_fbconf *)data;
555 1.1 uch if (fbconf->hf_conf_index != 0 &&
556 1.1 uch fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
557 1.1 uch return (EINVAL);
558 1.1 uch }
559 1.1 uch /*
560 1.1 uch * nothing to do because we have only one configration
561 1.1 uch */
562 1.1 uch return (0);
563 1.1 uch case HPCFBIO_GDSPCONF:
564 1.1 uch dspconf = (struct hpcfb_dspconf *)data;
565 1.1 uch if ((dspconf->hd_unit_index != 0 &&
566 1.1 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
567 1.1 uch (dspconf->hd_conf_index != 0 &&
568 1.1 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
569 1.1 uch return (EINVAL);
570 1.1 uch }
571 1.1 uch *dspconf = sc->sc_dspconf; /* structure assignment */
572 1.1 uch return (0);
573 1.1 uch case HPCFBIO_SDSPCONF:
574 1.1 uch dspconf = (struct hpcfb_dspconf *)data;
575 1.1 uch if ((dspconf->hd_unit_index != 0 &&
576 1.1 uch dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
577 1.1 uch (dspconf->hd_conf_index != 0 &&
578 1.1 uch dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
579 1.1 uch return (EINVAL);
580 1.1 uch }
581 1.1 uch /*
582 1.1 uch * nothing to do
583 1.1 uch * because we have only one unit and one configration
584 1.1 uch */
585 1.1 uch return (0);
586 1.1 uch case HPCFBIO_GOP:
587 1.1 uch case HPCFBIO_SOP:
588 1.1 uch /*
589 1.1 uch * curently not implemented...
590 1.1 uch */
591 1.1 uch return (EINVAL);
592 1.1 uch }
593 1.1 uch
594 1.13 atatat return (EPASSTHROUGH);
595 1.1 uch }
596 1.1 uch
597 1.1 uch paddr_t
598 1.2 uch bivideo_mmap(void *ctx, off_t offset, int prot)
599 1.1 uch {
600 1.1 uch struct bivideo_softc *sc = (struct bivideo_softc *)ctx;
601 1.1 uch
602 1.1 uch if (offset < 0 ||
603 1.1 uch (sc->sc_fbconf.hf_bytes_per_plane +
604 1.1 uch sc->sc_fbconf.hf_offset) < offset)
605 1.1 uch return -1;
606 1.1 uch
607 1.2 uch return __BTOP((u_long)bootinfo->fb_addr + offset);
608 1.3 sato }
609 1.3 sato
610 1.6 sato
611 1.3 sato void
612 1.6 sato bivideo_init_backlight(struct bivideo_softc *sc, int inattach)
613 1.3 sato {
614 1.3 sato int val = -1;
615 1.3 sato
616 1.6 sato if (sc->sc_lcd_inited&BACKLIGHT_INITED)
617 1.6 sato return;
618 1.6 sato
619 1.5 sato if (config_hook_call(CONFIG_HOOK_GET,
620 1.5 sato CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
621 1.6 sato /* we can get real light state */
622 1.6 sato VPRINTF(("bivideo_init_backlight: real backlight=%d\n", val));
623 1.5 sato if (val == 0)
624 1.5 sato sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
625 1.5 sato else
626 1.5 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
627 1.6 sato sc->sc_lcd_inited |= BACKLIGHT_INITED;
628 1.6 sato } else if (inattach) {
629 1.6 sato /*
630 1.6 sato we cannot get real light state in attach time
631 1.6 sato because light device not yet attached.
632 1.6 sato we will retry in !inattach.
633 1.6 sato temporary assume light is on.
634 1.6 sato */
635 1.5 sato sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
636 1.6 sato } else {
637 1.6 sato /* we cannot get real light state, so work by myself state */
638 1.6 sato sc->sc_lcd_inited |= BACKLIGHT_INITED;
639 1.6 sato }
640 1.3 sato }
641 1.3 sato
642 1.3 sato void
643 1.6 sato bivideo_init_brightness(struct bivideo_softc *sc, int inattach)
644 1.3 sato {
645 1.3 sato int val = -1;
646 1.3 sato
647 1.6 sato if (sc->sc_lcd_inited&BRIGHTNESS_INITED)
648 1.6 sato return;
649 1.6 sato
650 1.6 sato VPRINTF(("bivideo_init_brightness\n"));
651 1.3 sato if (config_hook_call(CONFIG_HOOK_GET,
652 1.3 sato CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
653 1.6 sato /* we can get real brightness max */
654 1.6 sato VPRINTF(("bivideo_init_brightness: real brightness max=%d\n", val));
655 1.3 sato sc->sc_max_brightness = val;
656 1.6 sato val = -1;
657 1.6 sato if (config_hook_call(CONFIG_HOOK_GET,
658 1.6 sato CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
659 1.6 sato /* we can get real brightness */
660 1.6 sato VPRINTF(("bivideo_init_brightness: real brightness=%d\n", val));
661 1.6 sato sc->sc_brightness_save = sc->sc_brightness = val;
662 1.6 sato } else {
663 1.6 sato sc->sc_brightness_save =
664 1.6 sato sc->sc_brightness = sc->sc_max_brightness;
665 1.6 sato }
666 1.6 sato sc->sc_lcd_inited |= BRIGHTNESS_INITED;
667 1.6 sato } else if (inattach) {
668 1.6 sato /*
669 1.6 sato we cannot get real brightness in attach time
670 1.6 sato because brightness device not yet attached.
671 1.6 sato we will retry in !inattach.
672 1.6 sato */
673 1.6 sato sc->sc_max_brightness = -1;
674 1.6 sato sc->sc_brightness = -1;
675 1.6 sato sc->sc_brightness_save = -1;
676 1.6 sato } else {
677 1.6 sato /* we cannot get real brightness */
678 1.6 sato sc->sc_lcd_inited |= BRIGHTNESS_INITED;
679 1.3 sato }
680 1.6 sato
681 1.3 sato return;
682 1.3 sato }
683 1.3 sato
684 1.3 sato void
685 1.6 sato bivideo_init_contrast(struct bivideo_softc *sc, int inattach)
686 1.3 sato {
687 1.3 sato int val = -1;
688 1.3 sato
689 1.6 sato if (sc->sc_lcd_inited&CONTRAST_INITED)
690 1.6 sato return;
691 1.6 sato
692 1.6 sato VPRINTF(("bivideo_init_contrast\n"));
693 1.3 sato if (config_hook_call(CONFIG_HOOK_GET,
694 1.3 sato CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
695 1.6 sato /* we can get real contrast max */
696 1.6 sato VPRINTF(("bivideo_init_contrast: real contrast max=%d\n", val));
697 1.3 sato sc->sc_max_contrast = val;
698 1.6 sato val = -1;
699 1.6 sato if (config_hook_call(CONFIG_HOOK_GET,
700 1.6 sato CONFIG_HOOK_CONTRAST, &val) != -1) {
701 1.6 sato /* we can get real contrast */
702 1.6 sato VPRINTF(("bivideo_init_contrast: real contrast=%d\n", val));
703 1.6 sato sc->sc_contrast = val;
704 1.6 sato } else {
705 1.6 sato sc->sc_contrast = sc->sc_max_contrast;
706 1.6 sato }
707 1.6 sato sc->sc_lcd_inited |= CONTRAST_INITED;
708 1.6 sato } else if (inattach) {
709 1.6 sato /*
710 1.6 sato we cannot get real contrast in attach time
711 1.6 sato because contrast device not yet attached.
712 1.6 sato we will retry in !inattach.
713 1.6 sato */
714 1.6 sato sc->sc_max_contrast = -1;
715 1.6 sato sc->sc_contrast = -1;
716 1.6 sato } else {
717 1.6 sato /* we cannot get real contrast */
718 1.6 sato sc->sc_lcd_inited |= CONTRAST_INITED;
719 1.3 sato }
720 1.6 sato
721 1.3 sato return;
722 1.3 sato }
723 1.3 sato
724 1.3 sato void
725 1.3 sato bivideo_set_brightness(struct bivideo_softc *sc, int val)
726 1.3 sato {
727 1.3 sato sc->sc_brightness = val;
728 1.3 sato
729 1.3 sato config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
730 1.3 sato if (config_hook_call(CONFIG_HOOK_GET,
731 1.3 sato CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
732 1.3 sato sc->sc_brightness = val;
733 1.3 sato }
734 1.3 sato }
735 1.3 sato
736 1.3 sato void
737 1.3 sato bivideo_set_contrast(struct bivideo_softc *sc, int val)
738 1.3 sato {
739 1.3 sato sc->sc_contrast = val;
740 1.3 sato
741 1.3 sato config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
742 1.3 sato if (config_hook_call(CONFIG_HOOK_GET,
743 1.3 sato CONFIG_HOOK_CONTRAST, &val) != -1) {
744 1.3 sato sc->sc_contrast = val;
745 1.3 sato }
746 1.1 uch }
747