xref: /openbsd/sys/arch/macppc/macppc/ofw_machdep.c (revision 3b9d585e)
1 /*	$OpenBSD: ofw_machdep.c,v 1.65 2024/04/13 23:44:11 jsg Exp $	*/
2 /*	$NetBSD: ofw_machdep.c,v 1.1 1996/09/30 16:34:50 ws Exp $	*/
3 
4 /*
5  * Copyright (C) 1996 Wolfgang Solfrank.
6  * Copyright (C) 1996 TooLs GmbH.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by TooLs GmbH.
20  * 4. The name of TooLs GmbH may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "akbd.h"
36 #include "ukbd.h"
37 #include "wsdisplay.h"
38 #include "zstty.h"
39 
40 #include <sys/param.h>
41 #include <sys/conf.h>
42 #include <sys/device.h>
43 #include <sys/systm.h>
44 
45 #include <uvm/uvm_extern.h>
46 
47 #include <powerpc/powerpc.h>
48 #include <machine/autoconf.h>
49 
50 #include <dev/ofw/openfirm.h>
51 #include <dev/ofw/ofw_pci.h>
52 
53 #include <macppc/macppc/ofw_machdep.h>
54 
55 #if NAKBD > 0
56 #include <dev/adb/akbdvar.h>
57 #endif
58 
59 #if NUKBD > 0
60 #include <dev/usb/ukbdvar.h>
61 #endif
62 
63 #if NWSDISPLAY > 0
64 #include <dev/wscons/wsconsio.h>
65 #include <dev/wscons/wsdisplayvar.h>
66 #include <dev/rasops/rasops.h>
67 #endif
68 
69 struct mem_region64 {
70 	uint64_t start;
71 	uint32_t size;
72 } __packed;
73 
74 #define	OFMEM_REGIONS	32
75 static struct mem_region   OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
76 static struct mem_region64 OFmem64[OFMEM_REGIONS + 1];
77 
78 /*
79  * Section 5.1.7. Memory Management Unit properties.
80  */
81 struct ofw_map {
82 	uint32_t	om_virt;
83 	uint32_t	om_size;
84 	uint32_t	om_phys;
85 	uint32_t	om_mode;
86 } __packed;
87 
88 struct ofw_map64 {
89 	uint32_t	om_virt;
90 	uint32_t	om_size;
91 	uint64_t	om_phys;
92 	uint32_t	om_mode;
93 } __packed;
94 
95 static struct ofw_map	ofw_maps[OFMEM_REGIONS];
96 static struct ofw_map64	ofw_maps64[OFMEM_REGIONS];
97 
98 #if NWSDISPLAY > 0
99 struct ofwfb {
100 	struct rasops_info	ofw_ri;
101 	struct wsscreen_descr	ofw_wsd;
102 };
103 
104 /* Early boot framebuffer */
105 static struct ofwfb ofwfb;
106 #endif
107 
108 int	save_ofw_mapping(void);
109 void	ofw_consinit(int);
110 void	ofw_read_mem_regions(int, int, int);
111 
112 int	ofw_set_param(struct wsdisplay_param *);
113 int	ofw_get_param(struct wsdisplay_param *);
114 
115 /*
116  * This is called during initppc, before the system is really initialized.
117  * It shall provide the total and the available regions of RAM.
118  * Both lists must have a zero-size entry as terminator.
119  * The available regions need not take the kernel into account, but needs
120  * to provide space for two additional entry beyond the terminating one.
121  */
122 void
ppc_mem_regions(struct mem_region ** memp,struct mem_region ** availp)123 ppc_mem_regions(struct mem_region **memp, struct mem_region **availp)
124 {
125 	*memp = OFmem;
126 
127 	/* HACK */
128 	if (OFmem[0].size == 0) {
129 		*memp = OFavail;
130 	}
131 
132 	*availp = OFavail;
133 }
134 
135 void
ofw_read_mem_regions(int phandle,int address_cells,int size_cells)136 ofw_read_mem_regions(int phandle, int address_cells, int size_cells)
137 {
138 	int nreg, navail;
139 	int i, j;
140 
141 	switch (address_cells) {
142 	default:
143 	case 1:
144 		nreg = OF_getprop(phandle, "reg", OFmem,
145 		    sizeof(OFmem[0]) * OFMEM_REGIONS) / sizeof(OFmem[0]);
146 		break;
147 	case 2:
148 		nreg = OF_getprop(phandle, "reg", OFmem64,
149 		    sizeof(OFmem64[0]) * OFMEM_REGIONS) / sizeof(OFmem64[0]);
150 		break;
151 	}
152 
153 	navail = OF_getprop(phandle, "available", OFavail,
154 	    sizeof(OFavail[0]) * OFMEM_REGIONS) / sizeof(OFavail[0]);
155 	if (nreg <= 0 || navail <= 0)
156 		panic("no memory?");
157 
158 	/* Eliminate empty or unreachable regions. */
159 	switch (address_cells) {
160 	default:
161 	case 1:
162 		for (i = 0, j = 0; i < nreg; i++) {
163 			if (OFmem[i].size == 0)
164 				continue;
165 			if (i != j) {
166 				OFmem[j].start = OFmem[i].start;
167 				OFmem[j].size = OFmem[i].size;
168 				OFmem[i].start = 0;
169 				OFmem[i].size = 0;
170 			}
171 			j++;
172 		}
173 		break;
174 	case 2:
175 		for (i = 0, j = 0; i < nreg; i++) {
176 			if (OFmem64[i].size == 0)
177 				continue;
178 			if (OFmem64[i].start >= 1ULL << 32)
179 				continue;
180 			OFmem[j].start = OFmem64[i].start;
181 			if (OFmem64[i].start + OFmem64[i].size >= 1ULL << 32)
182 				OFmem[j].size = (1ULL << 32) - OFmem64[i].start;
183 			else
184 				OFmem[j].size = OFmem64[i].size;
185 			j++;
186 		}
187 		break;
188 	}
189 }
190 
191 typedef void (fwcall_f)(int, int);
192 extern fwcall_f *fwcall;
193 fwcall_f fwentry;
194 
195 int OF_stdout;
196 int OF_stdin;
197 
198 /*
199  * Called early in the boot process, we are still running on the stack
200  * provided by the bootloader using the firmware's page table.
201  */
202 int
save_ofw_mapping(void)203 save_ofw_mapping(void)
204 {
205 	int chosen, memory, root, mmui, mmu = -1;
206 	int acells, scells;
207 	int i, len;
208 
209 	if ((chosen = OF_finddevice("/chosen")) == -1)
210 		return (0);
211 
212 	ofw_consinit(chosen);
213 
214 	/* Get memory node. */
215 	memory = OF_finddevice("/memory");
216 	if (memory == -1)
217 		panic("no memory?");
218 
219 	/* Are physical addresses encoded in 32 or 64 bits? */
220 	root = OF_parent(memory);
221 	if (OF_getprop(root, "#address-cells", &acells, 4) <= 0)
222 		acells = 1;
223 	if (OF_getprop(root, "#size-cells", &scells, 4) <= 0)
224 		scells = 1;
225 
226 	if (scells != 1)
227 		panic("unexpected memory layout %d:%d", acells, scells);
228 
229 	ofw_read_mem_regions(memory, acells, scells);
230 
231 	/* Get firmware mappings. */
232 	if (OF_getprop(chosen, "mmu", &mmui, sizeof(int)) != -1)
233 		mmu = OF_instance_to_package(mmui);
234 	if (mmu != -1) {
235 		len = OF_getproplen(mmu, "translations");
236 		if (len <= 0)
237 			return (0);
238 	}
239 
240 	switch (acells) {
241 	case 2:
242 		OF_getprop(mmu, "translations", ofw_maps64, sizeof(ofw_maps64));
243 
244 		for (i = 0; i < nitems(ofw_maps64); i++) {
245 			if (ofw_maps64[i].om_phys >= 1ULL << 32)
246 				continue;
247 
248 			ofw_maps[i].om_virt = ofw_maps64[i].om_virt;
249 			ofw_maps[i].om_size = ofw_maps64[i].om_size;
250 			ofw_maps[i].om_phys = (uint32_t)ofw_maps64[i].om_phys;
251 			ofw_maps[i].om_mode = ofw_maps64[i].om_mode;
252 		}
253 		break;
254 	case 1:
255 	default:
256 		OF_getprop(mmu, "translations", ofw_maps, sizeof(ofw_maps));
257 		break;
258 	}
259 
260 	/*
261 	 * Next time we'll call the firmware make sure we save and
262 	 * restore our MMU settings.
263 	 */
264 	fwcall = &fwentry;
265 
266 	return (0);
267 }
268 
269 static int display_ofh;
270 int cons_backlight;
271 int cons_brightness;
272 int cons_backlight_available;
273 int fbnode;
274 
275 void of_display_console(void);
276 
277 void
ofwconprobe(void)278 ofwconprobe(void)
279 {
280 	char type[32];
281 	int stdout_node;
282 
283 	stdout_node = OF_instance_to_package(OF_stdout);
284 
285 	/* handle different types of console */
286 
287 	bzero(type, sizeof(type));
288 	if (OF_getprop(stdout_node,  "device_type", type, sizeof(type)) == -1) {
289 		return; /* XXX */
290 	}
291 	if (strcmp(type, "display") == 0) {
292 		of_display_console();
293 		return;
294 	}
295 	if (strcmp(type, "serial") == 0) {
296 #if NZSTTY > 0
297 		/* zscnprobe/zscninit do all the required initialization */
298 		return;
299 #endif
300 	}
301 
302 	OF_stdout = OF_open("screen");
303 	OF_stdin = OF_open("keyboard");
304 
305 	/* cross fingers that this works. */
306 	of_display_console();
307 
308 	return;
309 }
310 
311 #define DEVTREE_UNKNOWN 0
312 #define DEVTREE_USB	1
313 #define DEVTREE_ADB	2
314 int ofw_devtree = DEVTREE_UNKNOWN;
315 
316 #define OFW_HAVE_USBKBD 1
317 #define OFW_HAVE_ADBKBD 2
318 int ofw_have_kbd = 0;
319 
320 void ofw_recurse_keyboard(int pnode);
321 void ofw_find_keyboard(void);
322 
323 void
ofw_recurse_keyboard(int pnode)324 ofw_recurse_keyboard(int pnode)
325 {
326 	char name[32];
327 	int old_devtree;
328 	int len;
329 	int node;
330 
331 	for (node = OF_child(pnode); node != 0; node = OF_peer(node)) {
332 
333 		len = OF_getprop(node, "name", name, 20);
334 		if (len == 0)
335 			continue;
336 		name[len] = 0;
337 		if (strcmp(name, "keyboard") == 0) {
338 			/* found a keyboard node, where is it? */
339 			if (ofw_devtree == DEVTREE_USB) {
340 				ofw_have_kbd |= OFW_HAVE_USBKBD;
341 			} else if (ofw_devtree == DEVTREE_ADB) {
342 				ofw_have_kbd |= OFW_HAVE_ADBKBD;
343 			} else {
344 				/* hid or some other keyboard? ignore */
345 			}
346 			continue;
347 		}
348 
349 		old_devtree = ofw_devtree;
350 
351 		if (strcmp(name, "adb") == 0) {
352 			ofw_devtree = DEVTREE_ADB;
353 		}
354 		if (strcmp(name, "usb") == 0) {
355 			ofw_devtree = DEVTREE_USB;
356 		}
357 
358 		ofw_recurse_keyboard(node);
359 
360 		ofw_devtree = old_devtree; /* nest? */
361 	}
362 }
363 
364 void
ofw_find_keyboard(void)365 ofw_find_keyboard(void)
366 {
367 	int stdin_node;
368 	char iname[32];
369 	int len, attach = 0;
370 
371 	stdin_node = OF_instance_to_package(OF_stdin);
372 	len = OF_getprop(stdin_node, "name", iname, 20);
373 	iname[len] = 0;
374 	printf(" console in [%s]", iname);
375 
376 	/* GRR, apple removed the interface once used for keyboard
377 	 * detection walk the OFW tree to find keyboards and what type.
378 	 */
379 
380 	ofw_recurse_keyboard(OF_peer(0));
381 
382 	len = OF_getprop(OF_peer(0), "model", iname, sizeof(iname));
383 	iname[len] = 0;
384 
385 	if (ofw_have_kbd == (OFW_HAVE_USBKBD | OFW_HAVE_ADBKBD)) {
386 		/*
387 		 * If a PowerBook reports having ABD and USB keyboards,
388 		 * use the builtin ADB one for console, the USB one is
389 		 * certainly a HID device.
390 		 */
391 		if (strncmp(iname, "PowerBook", 9) == 0)
392 			ofw_have_kbd = OFW_HAVE_ADBKBD;
393 		else
394 			ofw_have_kbd = OFW_HAVE_USBKBD;
395 		printf("USB and ADB found");
396 	}
397 	if (ofw_have_kbd == OFW_HAVE_USBKBD) {
398 #if NUKBD > 0
399 		printf(", using USB\n");
400 		ukbd_cnattach();
401 		attach = 1;
402 #endif
403 	} else if (ofw_have_kbd == OFW_HAVE_ADBKBD) {
404 #if NAKBD >0
405 		printf(", using ADB\n");
406 		akbd_cnattach();
407 		attach = 1;
408 #endif
409 	}
410 	if (attach == 0) {
411 #if NUKBD > 0
412 		printf(", no keyboard attached, trying usb anyway\n");
413 		ukbd_cnattach();
414 #else
415 		printf(", no keyboard found!\n");
416 #endif
417 	}
418 }
419 
420 void
of_display_console(void)421 of_display_console(void)
422 {
423 	struct ofw_pci_register addr[8];
424 	int cons_height, cons_width, cons_linebytes, cons_depth;
425 	uint32_t cons_addr;
426 	char name[32];
427 	int len, err;
428 	int stdout_node;
429 
430 	stdout_node = OF_instance_to_package(OF_stdout);
431 	len = OF_getprop(stdout_node, "name", name, 20);
432 	name[len] = 0;
433 	printf("console out [%s]", name);
434 	display_ofh = OF_stdout;
435 	err = OF_getprop(stdout_node, "width", &cons_width, 4);
436 	if ( err != 4) {
437 		cons_width = 0;
438 	}
439 	err = OF_getprop(stdout_node, "linebytes", &cons_linebytes, 4);
440 	if ( err != 4) {
441 		cons_linebytes = cons_width;
442 	}
443 	err = OF_getprop(stdout_node, "height", &cons_height, 4);
444 	if ( err != 4) {
445 		cons_height = 0;
446 	}
447 	err = OF_getprop(stdout_node, "depth", &cons_depth, 4);
448 	if ( err != 4) {
449 		cons_depth = 0;
450 	}
451 	err = OF_getprop(stdout_node, "address", &cons_addr, 4);
452 	if ( err != 4) {
453 		OF_interpret("frame-buffer-adr", 1, &cons_addr);
454 	}
455 
456 	ofw_find_keyboard();
457 
458 	fbnode = stdout_node;
459 	len = OF_getprop(stdout_node, "assigned-addresses", addr, sizeof(addr));
460 	if (len == -1) {
461 		fbnode = OF_parent(stdout_node);
462 		len = OF_getprop(fbnode, "name", name, 20);
463 		name[len] = 0;
464 
465 		printf("using parent %s:", name);
466 		len = OF_getprop(fbnode, "assigned-addresses",
467 			addr, sizeof(addr));
468 		if (len < sizeof(addr[0])) {
469 			panic(": no address");
470 		}
471 	}
472 
473 	if (OF_getnodebyname(0, "backlight") != 0) {
474 		cons_backlight_available = 1;
475 		cons_backlight = WSDISPLAYIO_VIDEO_ON;
476 		of_setbrightness(DEFAULT_BRIGHTNESS);
477 
478 		/* wsconsctl hooks */
479 		ws_get_param = ofw_get_param;
480 		ws_set_param = ofw_set_param;
481 	}
482 
483 #if 1
484 	printf(": memaddr %x, size %x ", addr[0].phys_lo, addr[0].size_lo);
485 	printf(": consaddr %x ", cons_addr);
486 	printf(": ioaddr %x, size %x", addr[1].phys_lo, addr[1].size_lo);
487 	printf(": width %d linebytes %d height %d depth %d\n",
488 		cons_width, cons_linebytes, cons_height, cons_depth);
489 #endif
490 
491 #if NWSDISPLAY > 0
492 {
493 	struct ofwfb *fb = &ofwfb;
494 	struct rasops_info *ri = &fb->ofw_ri;
495 	uint32_t defattr;
496 
497 	ri->ri_width = cons_width;
498 	ri->ri_height = cons_height;
499 	ri->ri_depth = cons_depth;
500 	ri->ri_stride = cons_linebytes;
501 	ri->ri_flg = RI_CENTER | RI_FULLCLEAR | RI_CLEAR;
502 	ri->ri_bits = (void *)mapiodev(cons_addr, cons_linebytes * cons_height);
503 	ri->ri_hw = fb;
504 
505 	if (cons_depth == 8)
506 		of_setcolors(rasops_cmap, 0, 256);
507 
508 	rasops_init(ri, 160, 160);
509 
510 	strlcpy(fb->ofw_wsd.name, "std", sizeof(fb->ofw_wsd.name));
511 	fb->ofw_wsd.capabilities = ri->ri_caps;
512 	fb->ofw_wsd.ncols = ri->ri_cols;
513 	fb->ofw_wsd.nrows = ri->ri_rows;
514 	fb->ofw_wsd.textops = &ri->ri_ops;
515 #if 0
516 	fb->ofw_wsd.fontwidth = ri->ri_font->fontwidth;
517 	fb->ofw_wsd.fontheight = ri->ri_font->fontheight;
518 #endif
519 
520 	ri->ri_ops.pack_attr(ri, 0, 0, 0, &defattr);
521 	wsdisplay_cnattach(&fb->ofw_wsd, ri, 0, 0, defattr);
522 }
523 #endif
524 }
525 
526 void
ofwconsswitch(struct rasops_info * ri)527 ofwconsswitch(struct rasops_info *ri)
528 {
529 #if NWSDISPLAY > 0
530 	ri->ri_width = ofwfb.ofw_ri.ri_width;
531 	ri->ri_height = ofwfb.ofw_ri.ri_height;
532 	ri->ri_depth = ofwfb.ofw_ri.ri_depth;
533 	ri->ri_stride = ofwfb.ofw_ri.ri_stride;
534 
535 	ri->ri_bits = ofwfb.ofw_ri.ri_bits /* XXX */;
536 #endif
537 }
538 
539 void
of_setbacklight(int on)540 of_setbacklight(int on)
541 {
542 	if (cons_backlight_available == 0)
543 		return;
544 
545 	cons_backlight = on;
546 
547 	if (on)
548 		OF_call_method_1("backlight-on", display_ofh, 0);
549 	else
550 		OF_call_method_1("backlight-off", display_ofh, 0);
551 }
552 
553 void
of_setbrightness(int brightness)554 of_setbrightness(int brightness)
555 {
556 	if (cons_backlight_available == 0)
557 		return;
558 
559 	if (brightness < MIN_BRIGHTNESS)
560 		brightness = MIN_BRIGHTNESS;
561 	else if (brightness > MAX_BRIGHTNESS)
562 		brightness = MAX_BRIGHTNESS;
563 
564 	cons_brightness = brightness;
565 
566 	/*
567 	 * The OF method is called "set-contrast" but affects brightness.
568 	 * Don't ask.
569 	 */
570 	OF_call_method_1("set-contrast", display_ofh, 1, cons_brightness);
571 
572 	/* XXX this routine should also save the brightness settings in the nvram */
573 }
574 
575 uint8_t of_cmap[256 * 3];
576 
577 void
of_setcolors(const uint8_t * cmap,unsigned int index,unsigned int count)578 of_setcolors(const uint8_t *cmap, unsigned int index, unsigned int count)
579 {
580 	bcopy(cmap, of_cmap, sizeof(of_cmap));
581 	OF_call_method_1("set-colors", display_ofh, 3, &of_cmap, index, count);
582 }
583 
584 #include <dev/cons.h>
585 
586 cons_decl(ofw);
587 
588 /*
589  * Console support functions
590  */
591 void
ofwcnprobe(struct consdev * cd)592 ofwcnprobe(struct consdev *cd)
593 {
594 }
595 
596 void
ofwcninit(struct consdev * cd)597 ofwcninit(struct consdev *cd)
598 {
599 }
600 void
ofwcnputc(dev_t dev,int c)601 ofwcnputc(dev_t dev, int c)
602 {
603 	char ch = c;
604 
605 	OF_write(OF_stdout, &ch, 1);
606 }
607 int
ofwcngetc(dev_t dev)608 ofwcngetc(dev_t dev)
609 {
610         unsigned char ch = '\0';
611         int l;
612 
613         while ((l = OF_read(OF_stdin, &ch, 1)) != 1)
614                 if (l != -2 && l != 0)
615                         return -1;
616         return ch;
617 }
618 
619 void
ofwcnpollc(dev_t dev,int on)620 ofwcnpollc(dev_t dev, int on)
621 {
622 }
623 
624 struct consdev consdev_ofw = {
625         ofwcnprobe,
626         ofwcninit,
627         ofwcngetc,
628         ofwcnputc,
629         ofwcnpollc,
630         NULL,
631 };
632 
633 void
ofw_consinit(int chosen)634 ofw_consinit(int chosen)
635 {
636 	struct consdev *cp = &consdev_ofw;
637 
638 	OF_getprop(chosen, "stdin", &OF_stdin, sizeof(OF_stdin));
639 	OF_getprop(chosen, "stdout", &OF_stdout, sizeof(OF_stdout));
640 
641 	/* If the screen is to be console, but not active, open it */
642 	if (OF_stdout == 0)
643 		OF_stdout = OF_open("screen");
644 
645 	cn_tab = cp;
646 }
647 
648 int
ofw_set_param(struct wsdisplay_param * dp)649 ofw_set_param(struct wsdisplay_param *dp)
650 {
651 	switch (dp->param) {
652 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
653 		if (cons_backlight_available != 0) {
654 			of_setbrightness(dp->curval);
655 			return 0;
656 		}
657 		break;
658 	case WSDISPLAYIO_PARAM_BACKLIGHT:
659 		if (cons_backlight_available != 0) {
660 			of_setbacklight(dp->curval ? WSDISPLAYIO_VIDEO_ON
661 			    : WSDISPLAYIO_VIDEO_OFF);
662 			return 0;
663 		}
664 		break;
665 	default:
666 		break;
667 	}
668 
669 	return -1;
670 }
671 
672 int
ofw_get_param(struct wsdisplay_param * dp)673 ofw_get_param(struct wsdisplay_param *dp)
674 {
675 	switch (dp->param) {
676 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
677 		if (cons_backlight_available != 0) {
678 			dp->min = MIN_BRIGHTNESS;
679 			dp->max = MAX_BRIGHTNESS;
680 			dp->curval = cons_brightness;
681 			return 0;
682 		}
683 		break;
684 	case WSDISPLAYIO_PARAM_BACKLIGHT:
685 		if (cons_backlight_available != 0) {
686 			dp->min = 0;
687 			dp->max = 1;
688 			dp->curval = cons_backlight;
689 			return 0;
690 		}
691 		break;
692 	default:
693 		break;
694 	}
695 
696 	return -1;
697 }
698