vgafb.c revision 1.51
1/* $OpenBSD: vgafb.c,v 1.51 2013/08/17 09:15:47 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/device.h> 34 35#include <machine/bus.h> 36 37#include <dev/wscons/wsconsio.h> 38#include <dev/wscons/wsdisplayvar.h> 39#include <dev/rasops/rasops.h> 40 41#include <dev/ofw/openfirm.h> 42#include <macppc/macppc/ofw_machdep.h> 43#include <macppc/pci/vgafbvar.h> 44 45 46struct cfdriver vgafb_cd = { 47 NULL, "vgafb", DV_DULL, 48}; 49 50int vgafb_ioctl(void *, u_long, caddr_t, int, struct proc *); 51paddr_t vgafb_mmap(void *, off_t, int); 52int vgafb_alloc_screen(void *, const struct wsscreen_descr *, void **, 53 int *, int *, long *); 54void vgafb_free_screen(void *, void *); 55int vgafb_show_screen(void *, void *, int, void (*cb)(void *, int, int), 56 void *); 57void vgafb_burn(void *v, u_int , u_int); 58void vgafb_setcolor(struct vga_config *, u_int, uint8_t, uint8_t, uint8_t); 59void vgafb_restore_default_colors(struct vga_config *); 60 61extern struct vga_config vgafbcn; 62 63struct wsscreen_descr vgafb_stdscreen = { 64 "std", 65 0, 0, 66 0, 67 0, 0, 68 WSSCREEN_UNDERLINE | WSSCREEN_HILIT | 69 WSSCREEN_REVERSE | WSSCREEN_WSCOLORS 70}; 71 72const struct wsscreen_descr *vgafb_scrlist[] = { 73 &vgafb_stdscreen, 74}; 75 76struct wsscreen_list vgafb_screenlist = { 77 nitems(vgafb_scrlist), vgafb_scrlist 78}; 79 80struct wsdisplay_accessops vgafb_accessops = { 81 vgafb_ioctl, 82 vgafb_mmap, 83 vgafb_alloc_screen, 84 vgafb_free_screen, 85 vgafb_show_screen, 86 NULL, /* load_font */ 87 NULL, /* scrollback */ 88 NULL, /* getchar */ 89 vgafb_burn, /* burner */ 90}; 91 92int vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm); 93int vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm); 94 95#ifdef APERTURE 96extern int allowaperture; 97#endif 98 99void 100vgafb_restore_default_colors(struct vga_config *vc) 101{ 102 int i; 103 104 for (i = 0; i < 256; i++) { 105 const u_char *color; 106 107 color = &rasops_cmap[i * 3]; 108 vgafb_setcolor(vc, i, color[0], color[1], color[2]); 109 } 110} 111 112void 113vgafb_wsdisplay_attach(struct device *parent, struct vga_config *vc, 114 int console) 115{ 116 struct wsemuldisplaydev_attach_args aa; 117 118 /* Setup virtual console now that we can allocate resources. */ 119 if (console) { 120 struct rasops_info *ri = &vc->ri; 121 long defattr; 122 123 ri->ri_flg |= RI_VCONS | RI_WRONLY; 124 rasops_init(ri, 160, 160); 125 126 ri->ri_ops.alloc_attr(ri->ri_active, 0, 0, 0, &defattr); 127 wsdisplay_cnattach(&vgafb_stdscreen, ri->ri_active, 128 0, 0, defattr); 129 } 130 131 aa.console = console; 132 aa.scrdata = &vgafb_screenlist; 133 aa.accessops = &vgafb_accessops; 134 aa.accesscookie = vc; 135 aa.defaultscreens = 0; 136 137 /* no need to keep the burner function if no hw support */ 138 if (cons_backlight_available == 0) 139 vgafb_accessops.burn_screen = NULL; 140 else { 141 vc->vc_backlight_on = WSDISPLAYIO_VIDEO_OFF; 142 vgafb_burn(vc, WSDISPLAYIO_VIDEO_ON, 0); /* paranoia */ 143 } 144 145 config_found(parent, &aa, wsemuldisplaydevprint); 146} 147 148int 149vgafb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 150{ 151 struct vga_config *vc = v; 152 struct wsdisplay_fbinfo *wdf; 153 154 switch (cmd) { 155 case WSDISPLAYIO_GTYPE: 156 *(u_int *)data = WSDISPLAY_TYPE_PCIVGA; 157 return 0; 158 case WSDISPLAYIO_GINFO: 159 wdf = (void *)data; 160 wdf->height = cons_height; 161 wdf->width = cons_width; 162 wdf->depth = cons_depth; 163 wdf->cmsize = 256; 164 return 0; 165 166 case WSDISPLAYIO_LINEBYTES: 167 *(u_int *)data = cons_linebytes; 168 return 0; 169 170 case WSDISPLAYIO_GETCMAP: 171 return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data); 172 173 case WSDISPLAYIO_PUTCMAP: 174 return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data); 175 176 case WSDISPLAYIO_SMODE: 177 vc->vc_mode = *(u_int *)data; 178 /* track the state of the display, 179 * if returning to WSDISPLAYIO_MODE_EMUL 180 * restore the last palette, workaround for 181 * bad accellerated X servers that does not restore 182 * the correct palette. 183 */ 184 if (cons_depth == 8) 185 vgafb_restore_default_colors(vc); 186 break; 187 188 case WSDISPLAYIO_GETPARAM: 189 { 190 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 191 192 switch (dp->param) { 193 case WSDISPLAYIO_PARAM_BRIGHTNESS: 194 if (cons_backlight_available != 0) { 195 dp->min = MIN_BRIGHTNESS; 196 dp->max = MAX_BRIGHTNESS; 197 dp->curval = cons_brightness; 198 return 0; 199 } 200 return -1; 201 case WSDISPLAYIO_PARAM_BACKLIGHT: 202 if (cons_backlight_available != 0) { 203 dp->min = 0; 204 dp->max = 1; 205 dp->curval = vc->vc_backlight_on; 206 return 0; 207 } else 208 return -1; 209 } 210 } 211 return -1; 212 213 case WSDISPLAYIO_SETPARAM: 214 { 215 struct wsdisplay_param *dp = (struct wsdisplay_param *)data; 216 217 switch (dp->param) { 218 case WSDISPLAYIO_PARAM_BRIGHTNESS: 219 if (cons_backlight_available == 1) { 220 of_setbrightness(dp->curval); 221 return 0; 222 } else 223 return -1; 224 case WSDISPLAYIO_PARAM_BACKLIGHT: 225 if (cons_backlight_available != 0) { 226 vgafb_burn(vc, 227 dp->curval ? WSDISPLAYIO_VIDEO_ON : 228 WSDISPLAYIO_VIDEO_OFF, 0); 229 return 0; 230 } else 231 return -1; 232 } 233 } 234 return -1; 235 236 case WSDISPLAYIO_SVIDEO: 237 case WSDISPLAYIO_GVIDEO: 238 break; 239 240 case WSDISPLAYIO_GCURPOS: 241 case WSDISPLAYIO_SCURPOS: 242 case WSDISPLAYIO_GCURMAX: 243 case WSDISPLAYIO_GCURSOR: 244 case WSDISPLAYIO_SCURSOR: 245 default: 246 return -1; /* not supported yet */ 247 } 248 249 return (0); 250} 251 252paddr_t 253vgafb_mmap(void *v, off_t off, int prot) 254{ 255 struct vga_config *vc = v; 256 257 if (off & PGOFSET) 258 return (-1); 259 260 switch (vc->vc_mode) { 261 case WSDISPLAYIO_MODE_MAPPED: 262#ifdef APERTURE 263 if (allowaperture == 0) 264 return (-1); 265#endif 266 267 if (vc->mmiosize == 0) 268 return (-1); 269 270 if (off >= vc->membase && off < (vc->membase + vc->memsize)) 271 return (off); 272 273 if (off >= vc->mmiobase && off < (vc->mmiobase + vc->mmiosize)) 274 return (off); 275 break; 276 277 case WSDISPLAYIO_MODE_DUMBFB: 278 if (off >= 0x00000 && off < vc->memsize) 279 return (vc->membase + off); 280 break; 281 282 } 283 284 return (-1); 285} 286 287int 288vgafb_is_console(int node) 289{ 290 extern int fbnode; 291 292 return (fbnode == node); 293} 294 295int 296vgafb_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check) 297{ 298 struct vga_config *vc = &vgafbcn; 299 struct rasops_info *ri = &vc->ri; 300 long defattr; 301 302 vc->vc_memt = memt; 303 vc->membase = cons_addr; 304 vc->memsize = cons_linebytes * cons_height; 305 vc->vc_memh = (bus_space_handle_t)mapiodev(vc->membase, vc->memsize); 306 307 if (cons_depth == 8) 308 vgafb_restore_default_colors(vc); 309 310 ri->ri_flg = RI_FULLCLEAR | RI_CLEAR; 311 ri->ri_depth = cons_depth; 312 ri->ri_bits = (void *)vc->vc_memh; 313 ri->ri_width = cons_width; 314 ri->ri_height = cons_height; 315 ri->ri_stride = cons_linebytes; 316 ri->ri_hw = vc; 317 318 rasops_init(ri, 160, 160); 319 320 vgafb_stdscreen.nrows = ri->ri_rows; 321 vgafb_stdscreen.ncols = ri->ri_cols; 322 vgafb_stdscreen.textops = &ri->ri_ops; 323 324 ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr); 325 326 wsdisplay_cnattach(&vgafb_stdscreen, ri, 0, 0, defattr); 327 328 return (0); 329} 330 331struct { 332 u_int8_t r; 333 u_int8_t g; 334 u_int8_t b; 335} vgafb_color[256]; 336 337void 338vgafb_setcolor(struct vga_config *vc, unsigned int index, u_int8_t r, 339 u_int8_t g, u_int8_t b) 340{ 341 vc->vc_cmap_red[index] = r; 342 vc->vc_cmap_green[index] = g; 343 vc->vc_cmap_blue[index] = b; 344 345 vgafb_color[index].r = r; 346 vgafb_color[index].g = g; 347 vgafb_color[index].b = b; 348 OF_call_method_1("set-colors", cons_display_ofh, 3, 349 &vgafb_color[index], index, 1); 350} 351 352int 353vgafb_getcmap(struct vga_config *vc, struct wsdisplay_cmap *cm) 354{ 355 u_int index = cm->index; 356 u_int count = cm->count; 357 int error; 358 359 if (index >= 256 || count > 256 - index) 360 return EINVAL; 361 362 error = copyout(&vc->vc_cmap_red[index], cm->red, count); 363 if (error) 364 return error; 365 error = copyout(&vc->vc_cmap_green[index], cm->green, count); 366 if (error) 367 return error; 368 error = copyout(&vc->vc_cmap_blue[index], cm->blue, count); 369 if (error) 370 return error; 371 372 return 0; 373} 374 375int 376vgafb_putcmap(struct vga_config *vc, struct wsdisplay_cmap *cm) 377{ 378 u_int index = cm->index; 379 u_int count = cm->count; 380 u_int i; 381 int error; 382 u_int8_t *r, *g, *b; 383 384 if (index >= 256 || count > 256 - index) 385 return EINVAL; 386 387 if ((error = copyin(cm->red, &vc->vc_cmap_red[index], count)) != 0) 388 return (error); 389 if ((error = copyin(cm->green, &vc->vc_cmap_green[index], count)) != 0) 390 return (error); 391 if ((error = copyin(cm->blue, &vc->vc_cmap_blue[index], count)) != 0) 392 return (error); 393 394 r = &(vc->vc_cmap_red[index]); 395 g = &(vc->vc_cmap_green[index]); 396 b = &(vc->vc_cmap_blue[index]); 397 398 for (i = 0; i < count; i++) { 399 vgafb_color[i].r = *r; 400 vgafb_color[i].g = *g; 401 vgafb_color[i].b = *b; 402 r++, g++, b++; 403 } 404 OF_call_method_1("set-colors", cons_display_ofh, 3, 405 &vgafb_color, index, count); 406 return 0; 407} 408 409void 410vgafb_burn(void *v, u_int on, u_int flags) 411{ 412 struct vga_config *vc = v; 413 414 if (cons_backlight_available == 1 && 415 vc->vc_backlight_on != on) { 416 if (on == WSDISPLAYIO_VIDEO_ON) { 417 OF_call_method_1("backlight-on", cons_display_ofh, 0); 418 } else { 419 OF_call_method_1("backlight-off", cons_display_ofh, 0); 420 } 421 vc->vc_backlight_on = on; 422 } 423} 424 425int 426vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 427 int *curxp, int *curyp, long *attrp) 428{ 429 struct vga_config *vc = v; 430 struct rasops_info *ri = &vc->ri; 431 432 return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp); 433} 434 435void 436vgafb_free_screen(void *v, void *cookie) 437{ 438 struct vga_config *vc = v; 439 struct rasops_info *ri = &vc->ri; 440 441 return rasops_free_screen(ri, cookie); 442} 443 444int 445vgafb_show_screen(void *v, void *cookie, int waitok, 446 void (*cb)(void *, int, int), void *cbarg) 447{ 448 struct vga_config *vc = v; 449 struct rasops_info *ri = &vc->ri; 450 451 if (cookie == ri->ri_active) 452 return (0); 453 454 return rasops_show_screen(ri, cookie, waitok, cb, cbarg); 455} 456