mq200.c revision 1.11 1 /* $NetBSD: mq200.c,v 1.11 2001/03/09 08:54:18 sato Exp $ */
2
3 /*-
4 * Copyright (c) 2000 Takemura Shin
5 * 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. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/device.h>
35 #include <sys/systm.h>
36 #include <sys/reboot.h>
37
38 #include <uvm/uvm_extern.h>
39
40 #include <dev/wscons/wsconsio.h>
41
42 #include <machine/bootinfo.h>
43 #include <machine/bus.h>
44 #include <machine/autoconf.h>
45 #include <machine/config_hook.h>
46 #include <machine/platid.h>
47 #include <machine/platid_mask.h>
48
49 #include <hpcmips/dev/mq200reg.h>
50 #include <hpcmips/dev/mq200var.h>
51 #include "bivideo.h"
52 #if NBIVIDEO > 0
53 #include <dev/hpc/bivideovar.h>
54 #endif
55
56 #define MQ200DEBUG
57 #ifdef MQ200DEBUG
58 #ifndef MQ200DEBUG_CONF
59 #define MQ200DEBUG_CONF 0
60 #endif
61 int mq200_debug = MQ200DEBUG_CONF;
62 #define DPRINTF(arg) do { if (mq200_debug) printf arg; } while(0);
63 #define DPRINTFN(n, arg) do { if (mq200_debug > (n)) printf arg; } while (0);
64 #define VPRINTF(arg) do { if (bootverbose || mq200_debug) printf arg; } while(0);
65 #define VPRINTFN(n, arg) do { if (bootverbose || mq200_debug > (n)) printf arg; } while (0);
66 #else
67 #define DPRINTF(arg) do { } while (0);
68 #define DPRINTFN(n, arg) do { } while (0);
69 #define VPRINTF(arg) do { if (bootverbose) printf arg; } while(0);
70 #define VPRINTFN(n, arg) do { if (bootverbose) printf arg; } while (0);
71 #endif
72
73 /*
74 * function prototypes
75 */
76 static void mq200_power __P((int, void *));
77 static int mq200_hardpower __P((void *, int, long, void *));
78 static int mq200_fbinit __P((struct hpcfb_fbconf *));
79 static int mq200_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
80 static paddr_t mq200_mmap __P((void *, off_t offset, int));
81 static void mq200_update_powerstate __P((struct mq200_softc *, int));
82 void mq200_get_backlight __P((struct mq200_softc *));
83 void mq200_init_brightness __P((struct mq200_softc *));
84 void mq200_init_contrast __P((struct mq200_softc *));
85 void mq200_set_brightness __P((struct mq200_softc *, int));
86 void mq200_set_contrast __P((struct mq200_softc *, int));
87
88 /*
89 * static variables
90 */
91 struct hpcfb_accessops mq200_ha = {
92 mq200_ioctl, mq200_mmap
93 };
94
95 int
96 mq200_probe(iot, ioh)
97 bus_space_tag_t iot;
98 bus_space_handle_t ioh;
99 {
100 unsigned long regval;
101
102 #if NBIVIDEO > 0
103 if (bivideo_dont_attach) /* some video driver already attached */
104 return (0);
105 #endif /* NBIVIDEO > 0 */
106
107 regval = bus_space_read_4(iot, ioh, MQ200_PC00R);
108 VPRINTF(("mq200 probe: vendor id=%04lx product id=%04lx\n",
109 regval & 0xffff, (regval >> 16) & 0xffff));
110 if (regval != ((MQ200_PRODUCT_ID << 16) | MQ200_VENDOR_ID))
111 return (0);
112
113 return (1);
114 }
115
116 void
117 mq200_attach(sc)
118 struct mq200_softc *sc;
119 {
120 unsigned long regval;
121 struct hpcfb_attach_args ha;
122 int console = (bootinfo->bi_cnuse & BI_CNUSE_SERIAL) ? 0 : 1;
123
124 printf(": ");
125 if (mq200_fbinit(&sc->sc_fbconf) != 0) {
126 /* just return so that hpcfb will not be attached */
127 return;
128 }
129
130 sc->sc_fbconf.hf_baseaddr = (u_long)bootinfo->fb_addr;
131 sc->sc_fbconf.hf_offset = (u_long)sc->sc_fbconf.hf_baseaddr -
132 MIPS_PHYS_TO_KSEG1(mips_ptob(mips_btop(sc->sc_baseaddr)));
133 DPRINTF(("hf_baseaddr=%lx\n", sc->sc_fbconf.hf_baseaddr));
134 DPRINTF(("hf_offset=%lx\n", sc->sc_fbconf.hf_offset));
135
136 regval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MQ200_PC08R);
137 printf("MQ200 Rev.%02lx video controller", regval & 0xff);
138 if (console) {
139 printf(", console");
140 }
141 printf("\n");
142 printf("%s: framebuffer address: 0x%08lx\n",
143 sc->sc_dev.dv_xname, (u_long)bootinfo->fb_addr);
144
145 /* Add a power hook to power saving */
146 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
147 sc->sc_powerhook = powerhook_establish(mq200_power, sc);
148 if (sc->sc_powerhook == NULL)
149 printf("%s: WARNING: unable to establish power hook\n",
150 sc->sc_dev.dv_xname);
151
152 /* Add a hard power hook to power saving */
153 sc->sc_hardpowerhook = config_hook(CONFIG_HOOK_PMEVENT,
154 CONFIG_HOOK_PMEVENT_HARDPOWER,
155 CONFIG_HOOK_SHARE,
156 mq200_hardpower, sc);
157 if (sc->sc_hardpowerhook == NULL)
158 printf("%s: WARNING: unable to establish hard power hook\n",
159 sc->sc_dev.dv_xname);
160
161 /* initialize backlight brightness and lcd contrast */
162 sc->sc_brightness = sc->sc_contrast =
163 sc->sc_max_brightness = sc->sc_max_contrast = -1;
164 mq200_init_brightness(sc);
165 mq200_init_contrast(sc);
166 mq200_get_backlight(sc);
167
168 if (console && hpcfb_cnattach(&sc->sc_fbconf) != 0) {
169 panic("mq200_attach: can't init fb console");
170 }
171
172 ha.ha_console = console;
173 ha.ha_accessops = &mq200_ha;
174 ha.ha_accessctx = sc;
175 ha.ha_curfbconf = 0;
176 ha.ha_nfbconf = 1;
177 ha.ha_fbconflist = &sc->sc_fbconf;
178 ha.ha_curdspconf = 0;
179 ha.ha_ndspconf = 1;
180 ha.ha_dspconflist = &sc->sc_dspconf;
181
182 config_found(&sc->sc_dev, &ha, hpcfbprint);
183
184 #if NBIVIDEO > 0
185 /*
186 * bivideo is no longer need
187 */
188 bivideo_dont_attach = 1;
189 #endif /* NBIVIDEO > 0 */
190 }
191
192 static void
193 mq200_update_powerstate(sc, updates)
194 struct mq200_softc *sc;
195 int updates;
196 {
197 if (updates & PWRSTAT_LCD)
198 config_hook_call(CONFIG_HOOK_POWERCONTROL,
199 CONFIG_HOOK_POWERCONTROL_LCD,
200 (void*)!(sc->sc_powerstate &
201 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)));
202
203 if (updates & PWRSTAT_BACKLIGHT)
204 config_hook_call(CONFIG_HOOK_POWERCONTROL,
205 CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
206 (void*)(!(sc->sc_powerstate &
207 (PWRSTAT_VIDEOOFF|PWRSTAT_SUSPEND)) &&
208 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
209 }
210
211 static void
212 mq200_power(why, arg)
213 int why;
214 void *arg;
215 {
216 #if 0
217 struct mq200_softc *sc = arg;
218
219 switch (why) {
220 case PWR_SUSPEND:
221 sc->sc_powerstate |= PWRSTAT_SUSPEND;
222 mq200_update_powerstate(sc, PWRSTAT_ALL);
223 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
224 break;
225 case PWR_STANDBY:
226 sc->sc_powerstate |= PWRSTAT_SUSPEND;
227 mq200_update_powerstate(sc, PWRSTAT_ALL);
228 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
229 break;
230 case PWR_RESUME:
231 sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
232 mq200_update_powerstate(sc, PWRSTAT_ALL);
233 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
234 break;
235 }
236
237 printf("MQ200_PMCSR=%08x\n", sc->sc_mq200pwstate);
238 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
239 MQ200_PMCSR, sc->sc_mq200pwstate);
240 #endif
241 }
242
243 static int
244 mq200_hardpower(ctx, type, id, msg)
245 void *ctx;
246 int type;
247 long id;
248 void *msg;
249 {
250 struct mq200_softc *sc = ctx;
251 int why = (int)msg;
252
253 switch (why) {
254 case PWR_SUSPEND:
255 sc->sc_powerstate |= PWRSTAT_SUSPEND;
256 mq200_update_powerstate(sc, PWRSTAT_ALL);
257 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
258 break;
259 case PWR_STANDBY:
260 sc->sc_powerstate |= PWRSTAT_SUSPEND;
261 mq200_update_powerstate(sc, PWRSTAT_ALL);
262 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
263 break;
264 case PWR_RESUME:
265 sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
266 mq200_update_powerstate(sc, PWRSTAT_ALL);
267 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
268 break;
269 }
270
271 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
272 MQ200_PMCSR, sc->sc_mq200pwstate);
273
274 /*
275 * you should wait until the
276 * power state transit sequence will end.
277 */
278 {
279 unsigned long tmp;
280 do {
281 tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
282 MQ200_PMCSR);
283 } while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3));
284 delay(100000); /* XXX */
285 }
286
287 return (0);
288 }
289
290
291 static int
292 mq200_fbinit(fb)
293 struct hpcfb_fbconf *fb;
294 {
295
296 /*
297 * get fb settings from bootinfo
298 */
299 if (bootinfo == NULL ||
300 bootinfo->fb_addr == 0 ||
301 bootinfo->fb_line_bytes == 0 ||
302 bootinfo->fb_width == 0 ||
303 bootinfo->fb_height == 0) {
304 printf("no frame buffer infomation.\n");
305 return (-1);
306 }
307
308 /* zero fill */
309 bzero(fb, sizeof(*fb));
310
311 fb->hf_conf_index = 0; /* configuration index */
312 fb->hf_nconfs = 1; /* how many configurations */
313 strcpy(fb->hf_name, "built-in video");
314 /* frame buffer name */
315 strcpy(fb->hf_conf_name, "default");
316 /* configuration name */
317 fb->hf_height = bootinfo->fb_height;
318 fb->hf_width = bootinfo->fb_width;
319 fb->hf_baseaddr = mips_ptob(mips_btop(bootinfo->fb_addr));
320 fb->hf_offset = (u_long)bootinfo->fb_addr - fb->hf_baseaddr;
321 /* frame buffer start offset */
322 fb->hf_bytes_per_line = bootinfo->fb_line_bytes;
323 fb->hf_nplanes = 1;
324 fb->hf_bytes_per_plane = bootinfo->fb_height *
325 bootinfo->fb_line_bytes;
326
327 fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
328 fb->hf_access_flags |= HPCFB_ACCESS_WORD;
329 fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
330
331 switch (bootinfo->fb_type) {
332 /*
333 * gray scale
334 */
335 case BIFB_D2_M2L_3:
336 case BIFB_D2_M2L_3x2:
337 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
338 /* fall through */
339 case BIFB_D2_M2L_0:
340 case BIFB_D2_M2L_0x2:
341 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
342 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
343 fb->hf_pack_width = 8;
344 fb->hf_pixels_per_pack = 4;
345 fb->hf_pixel_width = 2;
346 fb->hf_class_data_length = sizeof(struct hf_gray_tag);
347 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
348 break;
349
350 case BIFB_D4_M2L_F:
351 case BIFB_D4_M2L_Fx2:
352 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
353 /* fall through */
354 case BIFB_D4_M2L_0:
355 case BIFB_D4_M2L_0x2:
356 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
357 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
358 fb->hf_pack_width = 8;
359 fb->hf_pixels_per_pack = 2;
360 fb->hf_pixel_width = 4;
361 fb->hf_class_data_length = sizeof(struct hf_gray_tag);
362 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
363 break;
364
365 /*
366 * indexed color
367 */
368 case BIFB_D8_FF:
369 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
370 /* fall through */
371 case BIFB_D8_00:
372 fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
373 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
374 fb->hf_pack_width = 8;
375 fb->hf_pixels_per_pack = 1;
376 fb->hf_pixel_width = 8;
377 fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
378 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
379 break;
380
381 /*
382 * RGB color
383 */
384 case BIFB_D16_FFFF:
385 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
386 /* fall through */
387 case BIFB_D16_0000:
388 fb->hf_class = HPCFB_CLASS_RGBCOLOR;
389 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
390 #if BYTE_ORDER == LITTLE_ENDIAN
391 fb->hf_swap_flags = HPCFB_SWAP_BYTE;
392 #endif
393 fb->hf_pack_width = 16;
394 fb->hf_pixels_per_pack = 1;
395 fb->hf_pixel_width = 16;
396
397 fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
398 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */
399
400 fb->hf_u.hf_rgb.hf_red_width = 5;
401 fb->hf_u.hf_rgb.hf_red_shift = 11;
402 fb->hf_u.hf_rgb.hf_green_width = 6;
403 fb->hf_u.hf_rgb.hf_green_shift = 5;
404 fb->hf_u.hf_rgb.hf_blue_width = 5;
405 fb->hf_u.hf_rgb.hf_blue_shift = 0;
406 fb->hf_u.hf_rgb.hf_alpha_width = 0;
407 fb->hf_u.hf_rgb.hf_alpha_shift = 0;
408 break;
409
410 default:
411 printf("unknown type (=%d).\n", bootinfo->fb_type);
412 return (-1);
413 break;
414 }
415
416 return (0); /* no error */
417 }
418
419 int
420 mq200_ioctl(v, cmd, data, flag, p)
421 void *v;
422 u_long cmd;
423 caddr_t data;
424 int flag;
425 struct proc *p;
426 {
427 struct mq200_softc *sc = (struct mq200_softc *)v;
428 struct hpcfb_fbconf *fbconf;
429 struct hpcfb_dspconf *dspconf;
430 struct wsdisplay_cmap *cmap;
431 struct wsdisplay_param *dispparam;
432
433 switch (cmd) {
434 case WSDISPLAYIO_GETCMAP:
435 cmap = (struct wsdisplay_cmap*)data;
436
437 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
438 sc->sc_fbconf.hf_pack_width != 8 ||
439 256 <= cmap->index ||
440 256 < (cmap->index + cmap->count))
441 return (EINVAL);
442
443 #if 0
444 if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) ||
445 !uvm_useracc(cmap->green, cmap->count, B_WRITE) ||
446 !uvm_useracc(cmap->blue, cmap->count, B_WRITE))
447 return (EFAULT);
448
449 copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count);
450 copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count);
451 copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count);
452 #endif
453
454 return (0);
455
456 case WSDISPLAYIO_PUTCMAP:
457 /*
458 * This driver can't set color map.
459 */
460 return (EINVAL);
461
462 case WSDISPLAYIO_SVIDEO:
463 if (*(int *)data == WSDISPLAYIO_VIDEO_OFF)
464 sc->sc_powerstate |= PWRSTAT_VIDEOOFF;
465 else
466 sc->sc_powerstate &= ~PWRSTAT_VIDEOOFF;
467 mq200_update_powerstate(sc, PWRSTAT_ALL);
468 return 0;
469
470 case WSDISPLAYIO_GVIDEO:
471 *(int *)data = (sc->sc_powerstate&PWRSTAT_VIDEOOFF) ?
472 WSDISPLAYIO_VIDEO_OFF:WSDISPLAYIO_VIDEO_ON;
473 return 0;
474
475 case WSDISPLAYIO_GETPARAM:
476 dispparam = (struct wsdisplay_param*)data;
477 switch (dispparam->param) {
478 case WSDISPLAYIO_PARAM_BACKLIGHT:
479 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT call\n"));
480 if (sc->sc_max_brightness == -1)
481 mq200_init_brightness(sc);
482 mq200_get_backlight(sc);
483 dispparam->min = 0;
484 dispparam->max = 1;
485 if (sc->sc_max_brightness > 0)
486 dispparam->curval = sc->sc_brightness > 0? 1: 0;
487 else
488 dispparam->curval =
489 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1 : 0;
490 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT:%d\n",
491 dispparam->curval));
492 return 0;
493 break;
494 case WSDISPLAYIO_PARAM_CONTRAST:
495 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST call\n"));
496 if (sc->sc_max_contrast == -1)
497 mq200_init_contrast(sc);
498 if (sc->sc_max_contrast > 0) {
499 dispparam->min = 0;
500 dispparam->max = sc->sc_max_contrast;
501 dispparam->curval = sc->sc_contrast;
502 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast));
503 return 0;
504 } else {
505 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST ret\n"));
506 return (EINVAL);
507 }
508 break;
509 case WSDISPLAYIO_PARAM_BRIGHTNESS:
510 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS call\n"));
511 if (sc->sc_max_brightness == -1)
512 mq200_init_brightness(sc);
513 if (sc->sc_max_brightness > 0) {
514 dispparam->min = 0;
515 dispparam->max = sc->sc_max_brightness;
516 dispparam->curval = sc->sc_brightness;
517 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness));
518 return 0;
519 } else {
520 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS ret\n"));
521 return (EINVAL);
522 }
523 return (EINVAL);
524 default:
525 return (EINVAL);
526 }
527 return (0);
528
529 case WSDISPLAYIO_SETPARAM:
530 dispparam = (struct wsdisplay_param*)data;
531 switch (dispparam->param) {
532 case WSDISPLAYIO_PARAM_BACKLIGHT:
533 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT call\n"));
534 if (dispparam->curval < 0 ||
535 1 < dispparam->curval)
536 return (EINVAL);
537 if (sc->sc_max_brightness == -1)
538 mq200_init_brightness(sc);
539 VPRINTF(("mq200_ioctl: SETPARAM:max brightness=%d\n", sc->sc_max_brightness));
540 if (sc->sc_max_brightness > 0) { /* dimmer */
541 if (dispparam->curval == 0){
542 sc->sc_brightness_save = sc->sc_brightness;
543 mq200_set_brightness(sc, 0); /* min */
544 } else {
545 if (sc->sc_brightness_save == 0)
546 sc->sc_brightness_save = sc->sc_max_brightness;
547 mq200_set_brightness(sc, sc->sc_brightness_save);
548 }
549 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: brightness=%d\n", sc->sc_brightness));
550 } else { /* off */
551 if (dispparam->curval == 0)
552 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
553 else
554 sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
555 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: powerstate %d\n",
556 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
557 mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT);
558 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT:%d\n",
559 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
560 }
561 return 0;
562 break;
563 case WSDISPLAYIO_PARAM_CONTRAST:
564 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST call\n"));
565 if (sc->sc_max_contrast == -1)
566 mq200_init_contrast(sc);
567 if (dispparam->curval < 0 ||
568 sc->sc_max_contrast < dispparam->curval)
569 return (EINVAL);
570 if (sc->sc_max_contrast > 0) {
571 int org = sc->sc_contrast;
572 mq200_set_contrast(sc, dispparam->curval);
573 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast));
574 return 0;
575 } else {
576 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST ret\n"));
577 return (EINVAL);
578 }
579 break;
580 case WSDISPLAYIO_PARAM_BRIGHTNESS:
581 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS call\n"));
582 if (sc->sc_max_brightness == -1)
583 mq200_init_brightness(sc);
584 if (dispparam->curval < 0 ||
585 sc->sc_max_brightness < dispparam->curval)
586 return (EINVAL);
587 if (sc->sc_max_brightness > 0) {
588 int org = sc->sc_brightness;
589 mq200_set_brightness(sc, dispparam->curval);
590 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness));
591 return 0;
592 } else {
593 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS ret\n"));
594 return (EINVAL);
595 }
596 break;
597 default:
598 return (EINVAL);
599 }
600 return (0);
601
602 case HPCFBIO_GCONF:
603 fbconf = (struct hpcfb_fbconf *)data;
604 if (fbconf->hf_conf_index != 0 &&
605 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
606 return (EINVAL);
607 }
608 *fbconf = sc->sc_fbconf; /* structure assignment */
609 return (0);
610 case HPCFBIO_SCONF:
611 fbconf = (struct hpcfb_fbconf *)data;
612 if (fbconf->hf_conf_index != 0 &&
613 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
614 return (EINVAL);
615 }
616 /*
617 * nothing to do because we have only one configration
618 */
619 return (0);
620 case HPCFBIO_GDSPCONF:
621 dspconf = (struct hpcfb_dspconf *)data;
622 if ((dspconf->hd_unit_index != 0 &&
623 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
624 (dspconf->hd_conf_index != 0 &&
625 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
626 return (EINVAL);
627 }
628 *dspconf = sc->sc_dspconf; /* structure assignment */
629 return (0);
630 case HPCFBIO_SDSPCONF:
631 dspconf = (struct hpcfb_dspconf *)data;
632 if ((dspconf->hd_unit_index != 0 &&
633 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
634 (dspconf->hd_conf_index != 0 &&
635 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
636 return (EINVAL);
637 }
638 /*
639 * nothing to do
640 * because we have only one unit and one configration
641 */
642 return (0);
643 case HPCFBIO_GOP:
644 case HPCFBIO_SOP:
645 /*
646 * curently not implemented...
647 */
648 return (EINVAL);
649 }
650
651 return (ENOTTY);
652 }
653
654 paddr_t
655 mq200_mmap(ctx, offset, prot)
656 void *ctx;
657 off_t offset;
658 int prot;
659 {
660 struct mq200_softc *sc = (struct mq200_softc *)ctx;
661
662 if (offset < 0 || MQ200_MAPSIZE <= offset)
663 return -1;
664
665 return mips_btop(sc->sc_baseaddr + offset);
666 }
667
668
669 void
670 mq200_get_backlight(sc)
671 struct mq200_softc *sc;
672 {
673 int val = -1;
674
675 if (sc->sc_max_brightness < 0) {
676 if (config_hook_call(CONFIG_HOOK_GET,
677 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
678 if (val == 0)
679 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
680 else
681 sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
682 }
683 }
684 }
685
686 void
687 mq200_init_brightness(sc)
688 struct mq200_softc *sc;
689 {
690 int val = -1;
691
692 VPRINTF(("mq200_init_brightness\n"));
693 if (config_hook_call(CONFIG_HOOK_GET,
694 CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
695 sc->sc_brightness_save = sc->sc_brightness = val;
696 }
697 val = -1;
698 if (config_hook_call(CONFIG_HOOK_GET,
699 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
700 sc->sc_max_brightness = val;
701 }
702 return;
703 }
704
705
706 void
707 mq200_init_contrast(sc)
708 struct mq200_softc *sc;
709 {
710 int val = -1;
711
712 VPRINTF(("mq200_init_contrast\n"));
713 if (config_hook_call(CONFIG_HOOK_GET,
714 CONFIG_HOOK_CONTRAST, &val) != -1) {
715 sc->sc_contrast = val;
716 }
717 val = -1;
718 if (config_hook_call(CONFIG_HOOK_GET,
719 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
720 sc->sc_max_contrast = val;
721 }
722 return;
723 }
724
725 void
726 mq200_set_brightness(sc, val)
727 struct mq200_softc *sc;
728 int val;
729 {
730 sc->sc_brightness = val;
731
732 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
733 if (config_hook_call(CONFIG_HOOK_GET,
734 CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
735 sc->sc_brightness = val;
736 }
737 }
738
739 void
740 mq200_set_contrast(sc, val)
741 struct mq200_softc *sc;
742 int val;
743 {
744 sc->sc_contrast = val;
745
746 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
747 if (config_hook_call(CONFIG_HOOK_GET,
748 CONFIG_HOOK_CONTRAST, &val) != -1) {
749 sc->sc_contrast = val;
750 }
751 }
752