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