xref: /openbsd/sys/arch/macppc/pci/vgafb.c (revision 898184e3)
1 /*	$OpenBSD: vgafb.c,v 1.41 2012/08/30 21:54:13 mpi Exp $	*/
2 /*	$NetBSD: vga.c,v 1.3 1996/12/02 22:24:54 cgd Exp $	*/
3 
4 /*
5  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
6  * All rights reserved.
7  *
8  * Author: Chris G. Demetriou
9  *
10  * Permission to use, copy, modify and distribute this software and
11  * its documentation is hereby granted, provided that both the copyright
12  * notice and this permission notice appear in all copies of the
13  * software, derivative works or modified versions, and any portions
14  * thereof, and that both notices appear in supporting documentation.
15  *
16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19  *
20  * Carnegie Mellon requests users of this software to return to
21  *
22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23  *  School of Computer Science
24  *  Carnegie Mellon University
25  *  Pittsburgh PA 15213-3890
26  *
27  * any improvements or extensions that they make and grant Carnegie the
28  * rights to redistribute these changes.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/device.h>
35 #include <sys/buf.h>
36 
37 #include <uvm/uvm_extern.h>
38 
39 #include <machine/bus.h>
40 
41 #include <dev/cons.h>
42 #include <dev/ofw/openfirm.h>
43 #include <macppc/macppc/ofw_machdep.h>
44 
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/rasops/rasops.h>
48 #include <dev/wsfont/wsfont.h>
49 
50 #include <macppc/pci/vgafbvar.h>
51 
52 struct cfdriver vgafb_cd = {
53 	NULL, "vgafb", DV_DULL,
54 };
55 
56 void vgafb_setcolor(struct vga_config *vc, unsigned int index,
57 		    u_int8_t r, u_int8_t g, u_int8_t b);
58 void vgafb_restore_default_colors(struct vga_config *vc);
59 
60 struct vgafb_devconfig {
61 	struct rasops_info dc_rinfo;    /* raster display data */
62 	int dc_blanked;			/* currently had video disabled */
63 };
64 
65 extern struct vga_config vgafb_pci_console_vc;
66 struct vgafb_devconfig vgafb_console_dc;
67 
68 struct wsscreen_descr vgafb_stdscreen = {
69 	"std",
70 	0, 0,   /* will be filled in -- XXX shouldn't, it's global */
71 	0,
72 	0, 0,
73 	WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
74 	WSSCREEN_REVERSE | WSSCREEN_WSCOLORS
75 };
76 const struct wsscreen_descr *vgafb_scrlist[] = {
77 	&vgafb_stdscreen,
78 	/* XXX other formats, graphics screen? */
79 };
80 
81 struct wsscreen_list vgafb_screenlist = {
82 	sizeof(vgafb_scrlist) / sizeof(struct wsscreen_descr *), vgafb_scrlist
83 };
84 
85 struct wsdisplay_accessops vgafb_accessops = {
86 	vgafb_ioctl,
87 	vgafb_mmap,
88 	vgafb_alloc_screen,
89 	vgafb_free_screen,
90 	vgafb_show_screen,
91 	NULL,		/* load_font */
92 	NULL,		/* scrollback */
93 	NULL,		/* getchar */
94 	vgafb_burn,	/* burner */
95 };
96 
97 int	vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm);
98 int	vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm);
99 
100 #define FONT_WIDTH 8
101 #define FONT_HEIGHT 16
102 
103 #ifdef APERTURE
104 extern int allowaperture;
105 #endif
106 
107 
108 void
109 vgafb_init(bus_space_tag_t iot, bus_space_tag_t memt, struct vga_config *vc,
110     u_int32_t  membase, size_t memsize, u_int32_t mmiobase, size_t mmiosize)
111 {
112         vc->vc_iot = iot;
113         vc->vc_memt = memt;
114 	vc->vc_paddr = membase;
115 
116 	if (mmiosize != 0)
117 	       if (bus_space_map(vc->vc_memt, mmiobase, mmiosize, 0,
118 		   &vc->vc_mmioh))
119 			panic("vgafb_init: couldn't map mmio");
120 
121 	/* memsize should only be visible region for console */
122 	memsize = cons_height * cons_linebytes;
123         if (bus_space_map(vc->vc_memt, membase, memsize,
124 	    /* XXX */ppc_proc_is_64b ? 0 : 1, &vc->vc_memh))
125 		panic("vgafb_init: can't map mem space");
126 
127 	vc->vc_crow = vc->vc_ccol = 0; /* Has to be some onscreen value */
128 	vc->vc_so = 0;
129 
130 	/* clear screen, frob cursor, etc.? */
131 	/*
132 	*/
133 
134 	vc->vc_at = 0x00 | 0xf;			/* black bg|white fg */
135 	vc->vc_so_at = 0x00 | 0xf | 0x80;	/* black bg|white fg|blink */
136 
137 	if (cons_depth == 8) {
138 		vgafb_restore_default_colors(vc);
139 	}
140 }
141 
142 void
143 vgafb_restore_default_colors(struct vga_config *vc)
144 {
145 	int i;
146 
147 	for (i = 0; i < 256; i++) {
148 		const u_char *color;
149 
150 		color = &rasops_cmap[i * 3];
151 		vgafb_setcolor(vc, i, color[0], color[1], color[2]);
152 	}
153 }
154 
155 void
156 vgafb_wsdisplay_attach(struct device *parent, struct vga_config *vc,
157     int console)
158 {
159 	struct wsemuldisplaydev_attach_args aa;
160 
161         aa.console = console;
162 	aa.scrdata = &vgafb_screenlist;
163 	aa.accessops = &vgafb_accessops;
164 	aa.accesscookie = vc;
165 	aa.defaultscreens = 0;
166 
167 	/* no need to keep the burner function if no hw support */
168 	if (cons_backlight_available == 0)
169 		vgafb_accessops.burn_screen = NULL;
170 	else {
171 		vc->vc_backlight_on = WSDISPLAYIO_VIDEO_OFF;
172 		vgafb_burn(vc, WSDISPLAYIO_VIDEO_ON, 0);	/* paranoia */
173 	}
174 
175         config_found(parent, &aa, wsemuldisplaydevprint);
176 }
177 
178 int
179 vgafb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
180 {
181 	struct vga_config *vc = v;
182 	struct wsdisplay_fbinfo *wdf;
183 
184 	switch (cmd) {
185 	case WSDISPLAYIO_GTYPE:
186 		*(u_int *)data = WSDISPLAY_TYPE_PCIVGA;
187 		return 0;
188 	case WSDISPLAYIO_GINFO:
189 		wdf = (void *)data;
190 		wdf->height = cons_height;
191 		wdf->width  = cons_width;
192 		wdf->depth  = cons_depth;
193 		wdf->cmsize = 256;
194 		return 0;
195 
196 	case WSDISPLAYIO_LINEBYTES:
197 		*(u_int *)data = cons_linebytes;
198 		return 0;
199 
200 	case WSDISPLAYIO_GETCMAP:
201 		return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data);
202 
203 	case WSDISPLAYIO_PUTCMAP:
204 		return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data);
205 
206 	case WSDISPLAYIO_SMODE:
207 		vc->vc_mode = *(u_int *)data;
208 		/* track the state of the display,
209 		 * if returning to WSDISPLAYIO_MODE_EMUL
210 		 * restore the last palette, workaround for
211 		 * bad accellerated X servers that does not restore
212 		 * the correct palette.
213 		 */
214 		if (cons_depth == 8)
215 			vgafb_restore_default_colors(vc);
216 		break;
217 
218 	case WSDISPLAYIO_GETPARAM:
219 	{
220 		struct wsdisplay_param *dp = (struct wsdisplay_param *)data;
221 
222 		switch (dp->param) {
223 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
224 			if (cons_backlight_available != 0) {
225 				dp->min = MIN_BRIGHTNESS;
226 				dp->max = MAX_BRIGHTNESS;
227 				dp->curval = cons_brightness;
228 				return 0;
229 			}
230 			return -1;
231 		case WSDISPLAYIO_PARAM_BACKLIGHT:
232 			if (cons_backlight_available != 0) {
233 				dp->min = 0;
234 				dp->max = 1;
235 				dp->curval = vc->vc_backlight_on;
236 				return 0;
237 			} else
238 				return -1;
239 		}
240 	}
241 		return -1;
242 
243 	case WSDISPLAYIO_SETPARAM:
244 	{
245 		struct wsdisplay_param *dp = (struct wsdisplay_param *)data;
246 
247 		switch (dp->param) {
248 		case WSDISPLAYIO_PARAM_BRIGHTNESS:
249 			if (cons_backlight_available == 1) {
250 				of_setbrightness(dp->curval);
251 				return 0;
252 			} else
253 				return -1;
254 		case WSDISPLAYIO_PARAM_BACKLIGHT:
255 			if (cons_backlight_available != 0) {
256 				vgafb_burn(vc,
257 				    dp->curval ? WSDISPLAYIO_VIDEO_ON :
258 				      WSDISPLAYIO_VIDEO_OFF, 0);
259 				return 0;
260 			} else
261 				return -1;
262 		}
263 	}
264 		return -1;
265 
266 	case WSDISPLAYIO_SVIDEO:
267 	case WSDISPLAYIO_GVIDEO:
268 		break;
269 
270 	case WSDISPLAYIO_GCURPOS:
271 	case WSDISPLAYIO_SCURPOS:
272 	case WSDISPLAYIO_GCURMAX:
273 	case WSDISPLAYIO_GCURSOR:
274 	case WSDISPLAYIO_SCURSOR:
275 	default:
276 		return -1; /* not supported yet */
277 	}
278 
279         return (0);
280 }
281 
282 paddr_t
283 vgafb_mmap(void *v, off_t off, int prot)
284 {
285 	struct vga_config *vc = v;
286 
287 	if (off & PGOFSET)
288 		return (-1);
289 
290 	switch (vc->vc_mode) {
291 	case WSDISPLAYIO_MODE_MAPPED:
292 #ifdef APERTURE
293 		if (allowaperture == 0)
294 			return (-1);
295 #endif
296 
297 		if (vc->mmiosize == 0)
298 			return (-1);
299 
300 		if (off >= vc->membase && off < (vc->membase + vc->memsize))
301 			return (off);
302 
303 		 if (off >= vc->mmiobase && off < (vc->mmiobase+vc->mmiosize))
304 			return (off);
305 		break;
306 
307 	case WSDISPLAYIO_MODE_DUMBFB:
308 		if (off >= 0x00000 && off < vc->memsize)
309 			return (vc->vc_paddr + off);
310 		break;
311 
312 	}
313 
314 	return (-1);
315 }
316 
317 int
318 vgafb_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
319 {
320 	struct vga_config *vc = &vgafb_pci_console_vc;
321 	struct vgafb_devconfig *dc = &vgafb_console_dc;
322         struct rasops_info *ri = &dc->dc_rinfo;
323         long defattr;
324         int i;
325 
326 	vgafb_init(iot, memt, vc, cons_addr, cons_linebytes * cons_height,0, 0);
327 
328 	ri->ri_flg = RI_CENTER;
329 	ri->ri_depth = cons_depth;
330 	ri->ri_bits = (void *)vc->vc_memh;
331 	ri->ri_width = cons_width;
332 	ri->ri_height = cons_height;
333 	ri->ri_stride = cons_linebytes;
334 	ri->ri_hw = dc;
335 
336 	/* Clear the screen */
337 	for (i = 0; i < cons_linebytes * cons_height; i++)
338 		bus_space_write_1(memt,	vc->vc_memh, i, 0);
339 
340 	rasops_init(ri, 160, 160);	/* XXX */
341 
342 	vgafb_stdscreen.nrows = ri->ri_rows;
343 	vgafb_stdscreen.ncols = ri->ri_cols;
344 	vgafb_stdscreen.textops = &ri->ri_ops;
345 
346 	ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
347 
348 	wsdisplay_cnattach(&vgafb_stdscreen, ri, 0, 0, defattr);
349 	vc->nscreens++;
350 
351 	return (0);
352 }
353 
354 struct {
355 	u_int8_t r;
356 	u_int8_t g;
357 	u_int8_t b;
358 } vgafb_color[256];
359 
360 void
361 vgafb_setcolor(struct vga_config *vc, unsigned int index, u_int8_t r,
362     u_int8_t g, u_int8_t b)
363 {
364 	vc->vc_cmap_red[index] = r;
365 	vc->vc_cmap_green[index] = g;
366 	vc->vc_cmap_blue[index] = b;
367 
368 	vgafb_color[index].r = r;
369 	vgafb_color[index].g = g;
370 	vgafb_color[index].b = b;
371 	OF_call_method_1("set-colors", cons_display_ofh, 3,
372 	    &vgafb_color[index], index, 1);
373 }
374 
375 int
376 vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm)
377 {
378 	u_int index = cm->index;
379 	u_int count = cm->count;
380 	int error;
381 
382 	if (index >= 256 || count > 256 - index)
383 		return EINVAL;
384 
385 	error = copyout(&vc->vc_cmap_red[index],   cm->red,   count);
386 	if (error)
387 		return error;
388 	error = copyout(&vc->vc_cmap_green[index], cm->green, count);
389 	if (error)
390 		return error;
391 	error = copyout(&vc->vc_cmap_blue[index],  cm->blue,  count);
392 	if (error)
393 		return error;
394 
395 	return 0;
396 }
397 
398 int
399 vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm)
400 {
401 	u_int index = cm->index;
402 	u_int count = cm->count;
403 	u_int i;
404 	int error;
405 	u_int8_t *r, *g, *b;
406 
407 	if (index >= 256 || count > 256 - index)
408 		return EINVAL;
409 
410 	if ((error = copyin(cm->red, &vc->vc_cmap_red[index], count)) != 0)
411 		return (error);
412 	if ((error = copyin(cm->green, &vc->vc_cmap_green[index], count)) != 0)
413 		return (error);
414 	if ((error = copyin(cm->blue, &vc->vc_cmap_blue[index], count)) != 0)
415 		return (error);
416 
417 	r = &(vc->vc_cmap_red[index]);
418 	g = &(vc->vc_cmap_green[index]);
419 	b = &(vc->vc_cmap_blue[index]);
420 
421 	for (i = 0; i < count; i++) {
422 		vgafb_color[i].r = *r;
423 		vgafb_color[i].g = *g;
424 		vgafb_color[i].b = *b;
425 		r++, g++, b++;
426 	}
427 	OF_call_method_1("set-colors", cons_display_ofh, 3,
428 	    &vgafb_color, index, count);
429 	return 0;
430 }
431 
432 void
433 vgafb_burn(void *v, u_int on, u_int flags)
434 {
435 	struct vga_config *vc = v;
436 
437 	if (cons_backlight_available == 1 &&
438 	    vc->vc_backlight_on != on) {
439 		if (on == WSDISPLAYIO_VIDEO_ON) {
440 			OF_call_method_1("backlight-on", cons_display_ofh, 0);
441 		} else {
442 			OF_call_method_1("backlight-off", cons_display_ofh, 0);
443 		}
444 		vc->vc_backlight_on = on;
445 	}
446 }
447 
448 int
449 vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
450     int *curxp, int *curyp, long *attrp)
451 {
452 	struct vga_config *vc = v;
453 	long defattr;
454 
455 	if (vc->nscreens > 0)
456 		return (ENOMEM);
457 
458 	*cookiep = &vc->dc_rinfo; /* one and only for now */
459 	*curxp = 0;
460 	*curyp = 0;
461 	vc->dc_rinfo.ri_ops.alloc_attr(&vc->dc_rinfo, 0, 0, 0, &defattr);
462 	*attrp = defattr;
463 
464 	vc->nscreens++;
465 
466 	return (0);
467 }
468 
469 void
470 vgafb_free_screen(void *v, void *cookie)
471 {
472 	struct vga_config *vc = v;
473 
474 	if (vc == &vgafb_pci_console_vc)
475 		panic("vgafb_free_screen: console");
476 
477 	vc->nscreens--;
478 }
479 
480 int
481 vgafb_show_screen(void *v, void *cookie, int waitok,
482     void (*cb)(void *, int, int), void *cbarg)
483 {
484 	return (0);
485 }
486