mq200.c revision 1.10 1 /* $NetBSD: mq200.c,v 1.10 2001/02/27 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 & PWRSTAT_SUSPEND));
201
202 if (updates & PWRSTAT_BACKLIGHT)
203 config_hook_call(CONFIG_HOOK_POWERCONTROL,
204 CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
205 (void*)(!(sc->sc_powerstate & PWRSTAT_SUSPEND) &&
206 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)));
207 }
208
209 static void
210 mq200_power(why, arg)
211 int why;
212 void *arg;
213 {
214 #if 0
215 struct mq200_softc *sc = arg;
216
217 switch (why) {
218 case PWR_SUSPEND:
219 sc->sc_powerstate |= PWRSTAT_SUSPEND;
220 mq200_update_powerstate(sc, PWRSTAT_ALL);
221 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
222 break;
223 case PWR_STANDBY:
224 sc->sc_powerstate |= PWRSTAT_SUSPEND;
225 mq200_update_powerstate(sc, PWRSTAT_ALL);
226 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
227 break;
228 case PWR_RESUME:
229 sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
230 mq200_update_powerstate(sc, PWRSTAT_ALL);
231 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
232 break;
233 }
234
235 printf("MQ200_PMCSR=%08x\n", sc->sc_mq200pwstate);
236 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
237 MQ200_PMCSR, sc->sc_mq200pwstate);
238 #endif
239 }
240
241 static int
242 mq200_hardpower(ctx, type, id, msg)
243 void *ctx;
244 int type;
245 long id;
246 void *msg;
247 {
248 struct mq200_softc *sc = ctx;
249 int why = (int)msg;
250
251 switch (why) {
252 case PWR_SUSPEND:
253 sc->sc_powerstate |= PWRSTAT_SUSPEND;
254 mq200_update_powerstate(sc, PWRSTAT_ALL);
255 sc->sc_mq200pwstate = MQ200_POWERSTATE_D2;
256 break;
257 case PWR_STANDBY:
258 sc->sc_powerstate |= PWRSTAT_SUSPEND;
259 mq200_update_powerstate(sc, PWRSTAT_ALL);
260 sc->sc_mq200pwstate = MQ200_POWERSTATE_D3;
261 break;
262 case PWR_RESUME:
263 sc->sc_powerstate &= ~PWRSTAT_SUSPEND;
264 mq200_update_powerstate(sc, PWRSTAT_ALL);
265 sc->sc_mq200pwstate = MQ200_POWERSTATE_D0;
266 break;
267 }
268
269 bus_space_write_4(sc->sc_iot, sc->sc_ioh,
270 MQ200_PMCSR, sc->sc_mq200pwstate);
271
272 /*
273 * you should wait until the
274 * power state transit sequence will end.
275 */
276 {
277 unsigned long tmp;
278 do {
279 tmp = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
280 MQ200_PMCSR);
281 } while ((tmp & 0x3) != (sc->sc_mq200pwstate & 0x3));
282 delay(100000); /* XXX */
283 }
284
285 return (0);
286 }
287
288
289 static int
290 mq200_fbinit(fb)
291 struct hpcfb_fbconf *fb;
292 {
293
294 /*
295 * get fb settings from bootinfo
296 */
297 if (bootinfo == NULL ||
298 bootinfo->fb_addr == 0 ||
299 bootinfo->fb_line_bytes == 0 ||
300 bootinfo->fb_width == 0 ||
301 bootinfo->fb_height == 0) {
302 printf("no frame buffer infomation.\n");
303 return (-1);
304 }
305
306 /* zero fill */
307 bzero(fb, sizeof(*fb));
308
309 fb->hf_conf_index = 0; /* configuration index */
310 fb->hf_nconfs = 1; /* how many configurations */
311 strcpy(fb->hf_name, "built-in video");
312 /* frame buffer name */
313 strcpy(fb->hf_conf_name, "default");
314 /* configuration name */
315 fb->hf_height = bootinfo->fb_height;
316 fb->hf_width = bootinfo->fb_width;
317 fb->hf_baseaddr = mips_ptob(mips_btop(bootinfo->fb_addr));
318 fb->hf_offset = (u_long)bootinfo->fb_addr - fb->hf_baseaddr;
319 /* frame buffer start offset */
320 fb->hf_bytes_per_line = bootinfo->fb_line_bytes;
321 fb->hf_nplanes = 1;
322 fb->hf_bytes_per_plane = bootinfo->fb_height *
323 bootinfo->fb_line_bytes;
324
325 fb->hf_access_flags |= HPCFB_ACCESS_BYTE;
326 fb->hf_access_flags |= HPCFB_ACCESS_WORD;
327 fb->hf_access_flags |= HPCFB_ACCESS_DWORD;
328
329 switch (bootinfo->fb_type) {
330 /*
331 * gray scale
332 */
333 case BIFB_D2_M2L_3:
334 case BIFB_D2_M2L_3x2:
335 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
336 /* fall through */
337 case BIFB_D2_M2L_0:
338 case BIFB_D2_M2L_0x2:
339 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
340 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
341 fb->hf_pack_width = 8;
342 fb->hf_pixels_per_pack = 4;
343 fb->hf_pixel_width = 2;
344 fb->hf_class_data_length = sizeof(struct hf_gray_tag);
345 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
346 break;
347
348 case BIFB_D4_M2L_F:
349 case BIFB_D4_M2L_Fx2:
350 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
351 /* fall through */
352 case BIFB_D4_M2L_0:
353 case BIFB_D4_M2L_0x2:
354 fb->hf_class = HPCFB_CLASS_GRAYSCALE;
355 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
356 fb->hf_pack_width = 8;
357 fb->hf_pixels_per_pack = 2;
358 fb->hf_pixel_width = 4;
359 fb->hf_class_data_length = sizeof(struct hf_gray_tag);
360 fb->hf_u.hf_gray.hf_flags = 0; /* reserved for future use */
361 break;
362
363 /*
364 * indexed color
365 */
366 case BIFB_D8_FF:
367 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
368 /* fall through */
369 case BIFB_D8_00:
370 fb->hf_class = HPCFB_CLASS_INDEXCOLOR;
371 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
372 fb->hf_pack_width = 8;
373 fb->hf_pixels_per_pack = 1;
374 fb->hf_pixel_width = 8;
375 fb->hf_class_data_length = sizeof(struct hf_indexed_tag);
376 fb->hf_u.hf_indexed.hf_flags = 0; /* reserved for future use */
377 break;
378
379 /*
380 * RGB color
381 */
382 case BIFB_D16_FFFF:
383 fb->hf_access_flags |= HPCFB_ACCESS_REVERSE;
384 /* fall through */
385 case BIFB_D16_0000:
386 fb->hf_class = HPCFB_CLASS_RGBCOLOR;
387 fb->hf_access_flags |= HPCFB_ACCESS_STATIC;
388 #if BYTE_ORDER == LITTLE_ENDIAN
389 fb->hf_swap_flags = HPCFB_SWAP_BYTE;
390 #endif
391 fb->hf_pack_width = 16;
392 fb->hf_pixels_per_pack = 1;
393 fb->hf_pixel_width = 16;
394
395 fb->hf_class_data_length = sizeof(struct hf_rgb_tag);
396 fb->hf_u.hf_rgb.hf_flags = 0; /* reserved for future use */
397
398 fb->hf_u.hf_rgb.hf_red_width = 5;
399 fb->hf_u.hf_rgb.hf_red_shift = 11;
400 fb->hf_u.hf_rgb.hf_green_width = 6;
401 fb->hf_u.hf_rgb.hf_green_shift = 5;
402 fb->hf_u.hf_rgb.hf_blue_width = 5;
403 fb->hf_u.hf_rgb.hf_blue_shift = 0;
404 fb->hf_u.hf_rgb.hf_alpha_width = 0;
405 fb->hf_u.hf_rgb.hf_alpha_shift = 0;
406 break;
407
408 default:
409 printf("unknown type (=%d).\n", bootinfo->fb_type);
410 return (-1);
411 break;
412 }
413
414 return (0); /* no error */
415 }
416
417 int
418 mq200_ioctl(v, cmd, data, flag, p)
419 void *v;
420 u_long cmd;
421 caddr_t data;
422 int flag;
423 struct proc *p;
424 {
425 struct mq200_softc *sc = (struct mq200_softc *)v;
426 struct hpcfb_fbconf *fbconf;
427 struct hpcfb_dspconf *dspconf;
428 struct wsdisplay_cmap *cmap;
429 struct wsdisplay_param *dispparam;
430
431 switch (cmd) {
432 case WSDISPLAYIO_GETCMAP:
433 cmap = (struct wsdisplay_cmap*)data;
434
435 if (sc->sc_fbconf.hf_class != HPCFB_CLASS_INDEXCOLOR ||
436 sc->sc_fbconf.hf_pack_width != 8 ||
437 256 <= cmap->index ||
438 256 < (cmap->index + cmap->count))
439 return (EINVAL);
440
441 #if 0
442 if (!uvm_useracc(cmap->red, cmap->count, B_WRITE) ||
443 !uvm_useracc(cmap->green, cmap->count, B_WRITE) ||
444 !uvm_useracc(cmap->blue, cmap->count, B_WRITE))
445 return (EFAULT);
446
447 copyout(&bivideo_cmap_r[cmap->index], cmap->red, cmap->count);
448 copyout(&bivideo_cmap_g[cmap->index], cmap->green,cmap->count);
449 copyout(&bivideo_cmap_b[cmap->index], cmap->blue, cmap->count);
450 #endif
451
452 return (0);
453
454 case WSDISPLAYIO_PUTCMAP:
455 /*
456 * This driver can't set color map.
457 */
458 return (EINVAL);
459
460 case WSDISPLAYIO_GETPARAM:
461 dispparam = (struct wsdisplay_param*)data;
462 switch (dispparam->param) {
463 case WSDISPLAYIO_PARAM_BACKLIGHT:
464 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT call\n"));
465 if (sc->sc_max_brightness == -1)
466 mq200_init_brightness(sc);
467 mq200_get_backlight(sc);
468 dispparam->min = 0;
469 dispparam->max = 1;
470 if (sc->sc_max_brightness > 0)
471 dispparam->curval = sc->sc_brightness > 0? 1: 0;
472 else
473 dispparam->curval =
474 (sc->sc_powerstate&PWRSTAT_BACKLIGHT) ? 1 : 0;
475 VPRINTF(("mq200_ioctl: GETPARAM:BACKLIGHT:%d\n",
476 dispparam->curval));
477 return 0;
478 break;
479 case WSDISPLAYIO_PARAM_CONTRAST:
480 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST call\n"));
481 if (sc->sc_max_contrast == -1)
482 mq200_init_contrast(sc);
483 if (sc->sc_max_contrast > 0) {
484 dispparam->min = 0;
485 dispparam->max = sc->sc_max_contrast;
486 dispparam->curval = sc->sc_contrast;
487 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST max=%d, current=%d\n", sc->sc_max_contrast, sc->sc_contrast));
488 return 0;
489 } else {
490 VPRINTF(("mq200_ioctl: GETPARAM:CONTRAST ret\n"));
491 return (EINVAL);
492 }
493 break;
494 case WSDISPLAYIO_PARAM_BRIGHTNESS:
495 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS call\n"));
496 if (sc->sc_max_brightness == -1)
497 mq200_init_brightness(sc);
498 if (sc->sc_max_brightness > 0) {
499 dispparam->min = 0;
500 dispparam->max = sc->sc_max_brightness;
501 dispparam->curval = sc->sc_brightness;
502 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS max=%d, current=%d\n", sc->sc_max_brightness, sc->sc_brightness));
503 return 0;
504 } else {
505 VPRINTF(("mq200_ioctl: GETPARAM:BRIGHTNESS ret\n"));
506 return (EINVAL);
507 }
508 return (EINVAL);
509 default:
510 return (EINVAL);
511 }
512 return (0);
513
514 case WSDISPLAYIO_SETPARAM:
515 dispparam = (struct wsdisplay_param*)data;
516 switch (dispparam->param) {
517 case WSDISPLAYIO_PARAM_BACKLIGHT:
518 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT call\n"));
519 if (dispparam->curval < 0 ||
520 1 < dispparam->curval)
521 return (EINVAL);
522 if (sc->sc_max_brightness == -1)
523 mq200_init_brightness(sc);
524 VPRINTF(("mq200_ioctl: SETPARAM:max brightness=%d\n", sc->sc_max_brightness));
525 if (sc->sc_max_brightness > 0) { /* dimmer */
526 if (dispparam->curval == 0){
527 sc->sc_brightness_save = sc->sc_brightness;
528 mq200_set_brightness(sc, 0); /* min */
529 } else {
530 if (sc->sc_brightness_save == 0)
531 sc->sc_brightness_save = sc->sc_max_brightness;
532 mq200_set_brightness(sc, sc->sc_brightness_save);
533 }
534 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: brightness=%d\n", sc->sc_brightness));
535 } else { /* off */
536 if (dispparam->curval == 0)
537 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
538 else
539 sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
540 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT: powerstate %d\n",
541 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
542 mq200_update_powerstate(sc, PWRSTAT_BACKLIGHT);
543 VPRINTF(("mq200_ioctl: SETPARAM:BACKLIGHT:%d\n",
544 (sc->sc_powerstate & PWRSTAT_BACKLIGHT)?1:0));
545 }
546 return 0;
547 break;
548 case WSDISPLAYIO_PARAM_CONTRAST:
549 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST call\n"));
550 if (sc->sc_max_contrast == -1)
551 mq200_init_contrast(sc);
552 if (dispparam->curval < 0 ||
553 sc->sc_max_contrast < dispparam->curval)
554 return (EINVAL);
555 if (sc->sc_max_contrast > 0) {
556 int org = sc->sc_contrast;
557 mq200_set_contrast(sc, dispparam->curval);
558 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST org=%d, current=%d\n", org, sc->sc_contrast));
559 return 0;
560 } else {
561 VPRINTF(("mq200_ioctl: SETPARAM:CONTRAST ret\n"));
562 return (EINVAL);
563 }
564 break;
565 case WSDISPLAYIO_PARAM_BRIGHTNESS:
566 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS call\n"));
567 if (sc->sc_max_brightness == -1)
568 mq200_init_brightness(sc);
569 if (dispparam->curval < 0 ||
570 sc->sc_max_brightness < dispparam->curval)
571 return (EINVAL);
572 if (sc->sc_max_brightness > 0) {
573 int org = sc->sc_brightness;
574 mq200_set_brightness(sc, dispparam->curval);
575 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS org=%d, current=%d\n", org, sc->sc_brightness));
576 return 0;
577 } else {
578 VPRINTF(("mq200_ioctl: SETPARAM:BRIGHTNESS ret\n"));
579 return (EINVAL);
580 }
581 break;
582 default:
583 return (EINVAL);
584 }
585 return (0);
586
587 case HPCFBIO_GCONF:
588 fbconf = (struct hpcfb_fbconf *)data;
589 if (fbconf->hf_conf_index != 0 &&
590 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
591 return (EINVAL);
592 }
593 *fbconf = sc->sc_fbconf; /* structure assignment */
594 return (0);
595 case HPCFBIO_SCONF:
596 fbconf = (struct hpcfb_fbconf *)data;
597 if (fbconf->hf_conf_index != 0 &&
598 fbconf->hf_conf_index != HPCFB_CURRENT_CONFIG) {
599 return (EINVAL);
600 }
601 /*
602 * nothing to do because we have only one configration
603 */
604 return (0);
605 case HPCFBIO_GDSPCONF:
606 dspconf = (struct hpcfb_dspconf *)data;
607 if ((dspconf->hd_unit_index != 0 &&
608 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
609 (dspconf->hd_conf_index != 0 &&
610 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
611 return (EINVAL);
612 }
613 *dspconf = sc->sc_dspconf; /* structure assignment */
614 return (0);
615 case HPCFBIO_SDSPCONF:
616 dspconf = (struct hpcfb_dspconf *)data;
617 if ((dspconf->hd_unit_index != 0 &&
618 dspconf->hd_unit_index != HPCFB_CURRENT_UNIT) ||
619 (dspconf->hd_conf_index != 0 &&
620 dspconf->hd_conf_index != HPCFB_CURRENT_CONFIG)) {
621 return (EINVAL);
622 }
623 /*
624 * nothing to do
625 * because we have only one unit and one configration
626 */
627 return (0);
628 case HPCFBIO_GOP:
629 case HPCFBIO_SOP:
630 /*
631 * curently not implemented...
632 */
633 return (EINVAL);
634 }
635
636 return (ENOTTY);
637 }
638
639 paddr_t
640 mq200_mmap(ctx, offset, prot)
641 void *ctx;
642 off_t offset;
643 int prot;
644 {
645 struct mq200_softc *sc = (struct mq200_softc *)ctx;
646
647 if (offset < 0 || MQ200_MAPSIZE <= offset)
648 return -1;
649
650 return mips_btop(sc->sc_baseaddr + offset);
651 }
652
653
654 void
655 mq200_get_backlight(sc)
656 struct mq200_softc *sc;
657 {
658 int val = -1;
659
660 if (sc->sc_max_brightness < 0) {
661 if (config_hook_call(CONFIG_HOOK_GET,
662 CONFIG_HOOK_POWER_LCDLIGHT, &val) != -1) {
663 if (val == 0)
664 sc->sc_powerstate &= ~PWRSTAT_BACKLIGHT;
665 else
666 sc->sc_powerstate |= PWRSTAT_BACKLIGHT;
667 }
668 }
669 }
670
671 void
672 mq200_init_brightness(sc)
673 struct mq200_softc *sc;
674 {
675 int val = -1;
676
677 VPRINTF(("mq200_init_brightness\n"));
678 if (config_hook_call(CONFIG_HOOK_GET,
679 CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
680 sc->sc_brightness_save = sc->sc_brightness = val;
681 }
682 val = -1;
683 if (config_hook_call(CONFIG_HOOK_GET,
684 CONFIG_HOOK_BRIGHTNESS_MAX, &val) != -1) {
685 sc->sc_max_brightness = val;
686 }
687 return;
688 }
689
690
691 void
692 mq200_init_contrast(sc)
693 struct mq200_softc *sc;
694 {
695 int val = -1;
696
697 VPRINTF(("mq200_init_contrast\n"));
698 if (config_hook_call(CONFIG_HOOK_GET,
699 CONFIG_HOOK_CONTRAST, &val) != -1) {
700 sc->sc_contrast = val;
701 }
702 val = -1;
703 if (config_hook_call(CONFIG_HOOK_GET,
704 CONFIG_HOOK_CONTRAST_MAX, &val) != -1) {
705 sc->sc_max_contrast = val;
706 }
707 return;
708 }
709
710 void
711 mq200_set_brightness(sc, val)
712 struct mq200_softc *sc;
713 int val;
714 {
715 sc->sc_brightness = val;
716
717 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
718 if (config_hook_call(CONFIG_HOOK_GET,
719 CONFIG_HOOK_BRIGHTNESS, &val) != -1) {
720 sc->sc_brightness = val;
721 }
722 }
723
724 void
725 mq200_set_contrast(sc, val)
726 struct mq200_softc *sc;
727 int val;
728 {
729 sc->sc_contrast = val;
730
731 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
732 if (config_hook_call(CONFIG_HOOK_GET,
733 CONFIG_HOOK_CONTRAST, &val) != -1) {
734 sc->sc_contrast = val;
735 }
736 }
737