1 /* $NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * The President and Fellows of Harvard College. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * 13 * All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Harvard University. 16 * This product includes software developed by the University of 17 * California, Lawrence Berkeley Laboratory. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 3. All advertising materials mentioning features or use of this software 28 * must display the following acknowledgement: 29 * This product includes software developed by the University of 30 * California, Berkeley and its contributors. 31 * This product includes software developed by Harvard University and 32 * its contributors. 33 * 4. Neither the name of the University nor the names of its contributors 34 * may be used to endorse or promote products derived from this software 35 * without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * 49 * Based on: 50 * NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp 51 * NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp 52 */ 53 54 /* 55 * Driver for Campus-II on-board mbus-based video (cgfourteen). 56 * Provides minimum emulation of a Sun cgthree 8-bit framebuffer to 57 * allow X to run. 58 * 59 * Does not handle interrupts, even though they can occur. 60 * 61 * XXX should defer colormap updates to vertical retrace interrupts 62 */ 63 64 /* 65 * The following is for debugging only; it opens up a security hole 66 * enabled by allowing any user to map the control registers for the 67 * cg14 into their space. 68 */ 69 #undef CG14_MAP_REGS 70 71 /* 72 * The following enables 24-bit operation: when opened, the framebuffer 73 * will switch to 24-bit mode (actually 32-bit mode), and provide a 74 * simple cg8 emulation. 75 * 76 * XXX Note that the code enabled by this define is currently untested/broken. 77 */ 78 #undef CG14_CG8 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $"); 82 83 #include <sys/param.h> 84 #include <sys/systm.h> 85 #include <sys/buf.h> 86 #include <sys/device.h> 87 #include <sys/ioctl.h> 88 #include <sys/malloc.h> 89 #include <sys/mman.h> 90 #include <sys/tty.h> 91 #include <sys/conf.h> 92 93 #include <uvm/uvm_extern.h> 94 95 #include <machine/bus.h> 96 #include <machine/autoconf.h> 97 98 #include <dev/sbus/sbusvar.h> 99 100 #include <dev/sun/fbio.h> 101 #include <dev/sun/fbvar.h> 102 103 #include <sparc/dev/cgfourteenreg.h> 104 #include <sparc/dev/cgfourteenvar.h> 105 106 /* autoconfiguration driver */ 107 static int cgfourteenmatch(struct device *, struct cfdata *, void *); 108 static void cgfourteenattach(struct device *, struct device *, void *); 109 static void cgfourteenunblank(struct device *); 110 111 CFATTACH_DECL(cgfourteen, sizeof(struct cgfourteen_softc), 112 cgfourteenmatch, cgfourteenattach, NULL, NULL); 113 114 extern struct cfdriver cgfourteen_cd; 115 116 dev_type_open(cgfourteenopen); 117 dev_type_close(cgfourteenclose); 118 dev_type_ioctl(cgfourteenioctl); 119 dev_type_mmap(cgfourteenmmap); 120 121 const struct cdevsw cgfourteen_cdevsw = { 122 cgfourteenopen, cgfourteenclose, noread, nowrite, cgfourteenioctl, 123 nostop, notty, nopoll, cgfourteenmmap, nokqfilter, 124 }; 125 126 /* frame buffer generic driver */ 127 static struct fbdriver cgfourteenfbdriver = { 128 cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, 129 nopoll, cgfourteenmmap, nokqfilter 130 }; 131 132 static void cg14_set_video(struct cgfourteen_softc *, int); 133 static int cg14_get_video(struct cgfourteen_softc *); 134 static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int); 135 static int cg14_put_cmap(struct fbcmap *, union cg14cmap *, int); 136 static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int); 137 static void cg14_init(struct cgfourteen_softc *); 138 static void cg14_reset(struct cgfourteen_softc *); 139 static void cg14_loadomap(struct cgfourteen_softc *); /* cursor overlay */ 140 static void cg14_setcursor(struct cgfourteen_softc *); /* set position */ 141 static void cg14_loadcursor(struct cgfourteen_softc *); /* set shape */ 142 143 /* 144 * We map the display memory with an offset of 256K when emulating the cg3 or 145 * cg8; the cg3 uses this offset for compatibility with the cg4, and both the 146 * cg4 and cg8 have a mono overlay plane and an overlay enable plane in the 147 * first 256K. Mapping at an offset of 0x04000000 causes only the color 148 * frame buffer to be mapped, without the overlay planes. 149 */ 150 #define START (128*1024 + 128*1024) 151 #define NOOVERLAY (0x04000000) 152 153 /* 154 * Match a cgfourteen. 155 */ 156 static int 157 cgfourteenmatch(struct device *parent, struct cfdata *cf, void *aux) 158 { 159 union obio_attach_args *uoba = aux; 160 struct sbus_attach_args *sa = &uoba->uoba_sbus; 161 162 /* 163 * The cgfourteen is a local-bus video adaptor, accessed directly 164 * via the processor, and not through device space or an external 165 * bus. Thus we look _only_ at the obio bus. 166 * Additionally, these things exist only on the Sun4m. 167 */ 168 169 if (uoba->uoba_isobio4 != 0 || !CPU_ISSUN4M) 170 return (0); 171 172 /* Check driver name */ 173 return (strcmp(cf->cf_name, sa->sa_name) == 0); 174 } 175 176 /* 177 * Attach a display. We need to notice if it is the console, too. 178 */ 179 static void 180 cgfourteenattach(struct device *parent, struct device *self, void *aux) 181 { 182 union obio_attach_args *uoba = aux; 183 struct sbus_attach_args *sa = &uoba->uoba_sbus; 184 struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self; 185 struct fbdevice *fb = &sc->sc_fb; 186 bus_space_handle_t bh; 187 int node, ramsize; 188 volatile uint32_t *lut; 189 int i, isconsole; 190 191 node = sa->sa_node; 192 193 /* Remember cookies for cgfourteenmmap() */ 194 sc->sc_bustag = sa->sa_bustag; 195 196 fb->fb_driver = &cgfourteenfbdriver; 197 fb->fb_device = &sc->sc_dev; 198 /* Mask out invalid flags from the user. */ 199 fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK; 200 201 /* 202 * We're emulating a cg3/8, so represent ourselves as one 203 */ 204 #ifdef CG14_CG8 205 fb->fb_type.fb_type = FBTYPE_MEMCOLOR; 206 fb->fb_type.fb_depth = 32; 207 #else 208 fb->fb_type.fb_type = FBTYPE_SUN3COLOR; 209 fb->fb_type.fb_depth = 8; 210 #endif 211 fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node); 212 #ifdef CG14_CG8 213 /* 214 * fb_setsize_obp set fb->fb_linebytes based on the current 215 * depth reported by obp, but that defaults to 8 bits (as 216 * reported by getpropint(). Update the value to reflect 217 * the depth that will be used after open. 218 * The display memory size returned by the cg8 driver includes 219 * the space used by the overlay planes, but the size returned 220 * by the cg3 driver does not; emulate the other drivers. 221 */ 222 fb->fb_linebytes = (fb->fb_type.fb_width * fb->fb_type.fb_depth) / 8; 223 ramsize = roundup(START + (fb->fb_type.fb_height * fb->fb_linebytes), 224 PAGE_SIZE); 225 #else 226 ramsize = roundup(fb->fb_type.fb_height * fb->fb_linebytes, PAGE_SIZE); 227 #endif 228 fb->fb_type.fb_cmsize = CG14_CLUT_SIZE; 229 fb->fb_type.fb_size = ramsize; 230 231 if (sa->sa_nreg < 2) { 232 printf("%s: only %d register sets\n", 233 self->dv_xname, sa->sa_nreg); 234 return; 235 } 236 bcopy(sa->sa_reg, sc->sc_physadr, 237 sa->sa_nreg * sizeof(struct openprom_addr)); 238 239 /* 240 * Now map in the 8 useful pages of registers 241 */ 242 if (sa->sa_size < 0x10000) { 243 #ifdef DIAGNOSTIC 244 printf("warning: can't find all cgfourteen registers...\n"); 245 #endif 246 sa->sa_size = 0x10000; 247 } 248 if (sbus_bus_map(sa->sa_bustag, 249 sa->sa_slot, sa->sa_offset, sa->sa_size, 250 BUS_SPACE_MAP_LINEAR, &bh) != 0) { 251 printf("%s: cannot map control registers\n", self->dv_xname); 252 return; 253 } 254 255 sc->sc_ctl = (struct cg14ctl *) (bh); 256 sc->sc_hwc = (struct cg14curs *) (bh + CG14_OFFSET_CURS); 257 sc->sc_dac = (struct cg14dac *) (bh + CG14_OFFSET_DAC); 258 sc->sc_xlut = (struct cg14xlut *) (bh + CG14_OFFSET_XLUT); 259 sc->sc_clut1 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT1); 260 sc->sc_clut2 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT2); 261 sc->sc_clut3 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT3); 262 sc->sc_clutincr = (u_int *) (bh + CG14_OFFSET_CLUTINCR); 263 264 /* 265 * Let the user know that we're here 266 */ 267 #ifdef CG14_CG8 268 printf(": cgeight emulated at %dx%dx24bpp", 269 fb->fb_type.fb_width, fb->fb_type.fb_height); 270 #else 271 printf(": cgthree emulated at %dx%dx8bpp", 272 fb->fb_type.fb_width, fb->fb_type.fb_height); 273 #endif 274 /* 275 * Enable the video, but don't change the pixel depth. 276 */ 277 cg14_set_video(sc, 1); 278 279 /* 280 * Grab the initial colormap 281 */ 282 lut = sc->sc_clut1->clut_lut; 283 for (i = 0; i < CG14_CLUT_SIZE; i++) 284 sc->sc_cmap.cm_chip[i] = lut[i]; 285 286 /* See if we're the console */ 287 isconsole = fb_is_console(node); 288 289 if (isconsole) { 290 printf(" (console)\n"); 291 #ifdef notdef 292 /* 293 * We don't use the raster console since the cg14 is 294 * fast enough already. 295 */ 296 #ifdef RASTERCONSOLE 297 fbrcons_init(fb); 298 #endif 299 #endif /* notdef */ 300 } else 301 printf("\n"); 302 303 /* Attach to /dev/fb */ 304 fb_attach(&sc->sc_fb, isconsole); 305 } 306 307 /* 308 * Keep track of the number of opens made. In the 24-bit driver, we need to 309 * switch to 24-bit mode on the first open, and switch back to 8-bit on 310 * the last close. This kind of nonsense is needed to give screenblank 311 * a fighting chance of working. 312 */ 313 static int cg14_opens = 0; 314 315 int 316 cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) 317 { 318 struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; 319 int unit = minor(dev); 320 int s, oldopens; 321 322 if (unit >= cgfourteen_cd.cd_ndevs || 323 cgfourteen_cd.cd_devs[unit] == NULL) 324 return (ENXIO); 325 326 s = splhigh(); 327 oldopens = cg14_opens++; 328 splx(s); 329 330 /* Setup the cg14 as we want it, and save the original PROM state */ 331 if (oldopens == 0) /* first open only, to make screenblank work */ 332 cg14_init(sc); 333 334 return (0); 335 } 336 337 int 338 cgfourteenclose(dev_t dev, int flags, int mode, struct lwp *l) 339 { 340 struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; 341 int s, opens; 342 343 s = splhigh(); 344 opens = --cg14_opens; 345 if (cg14_opens < 0) 346 opens = cg14_opens = 0; 347 splx(s); 348 349 /* 350 * Restore video state to make the PROM happy, on last close. 351 */ 352 if (opens == 0) 353 cg14_reset(sc); 354 355 return (0); 356 } 357 358 int 359 cgfourteenioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l) 360 { 361 struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; 362 struct fbgattr *fba; 363 union cg14cursor_cmap tcm; 364 int v, error; 365 u_int count; 366 u_int eplane[32], cplane[32]; 367 368 switch (cmd) { 369 370 case FBIOGTYPE: 371 *(struct fbtype *)data = sc->sc_fb.fb_type; 372 break; 373 374 case FBIOGATTR: 375 fba = (struct fbgattr *)data; 376 fba->real_type = FBTYPE_MDICOLOR; 377 fba->owner = 0; /* XXX ??? */ 378 fba->fbtype = sc->sc_fb.fb_type; 379 fba->sattr.flags = 0; 380 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 381 fba->sattr.dev_specific[0] = -1; 382 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 383 fba->emu_types[1] = -1; 384 break; 385 386 case FBIOGETCMAP: 387 return (cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, 388 CG14_CLUT_SIZE)); 389 390 case FBIOPUTCMAP: 391 /* copy to software map */ 392 #define p ((struct fbcmap *)data) 393 #ifdef CG14_CG8 394 p->index &= 0xffffff; 395 #endif 396 error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE); 397 if (error) 398 return (error); 399 /* now blast them into the chip */ 400 /* XXX should use retrace interrupt */ 401 cg14_load_hwcmap(sc, p->index, p->count); 402 #undef p 403 break; 404 405 case FBIOGVIDEO: 406 *(int *)data = cg14_get_video(sc); 407 break; 408 409 case FBIOSVIDEO: 410 cg14_set_video(sc, *(int *)data); 411 break; 412 413 /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 414 #define p ((struct fbcursor *)data) 415 #define cc (&sc->sc_cursor) 416 case FBIOGCURSOR: 417 /* do not quite want everything here... */ 418 p->set = FB_CUR_SETALL; /* close enough, anyway */ 419 p->enable = cc->cc_enable; 420 p->pos = cc->cc_pos; 421 p->hot = cc->cc_hot; 422 p->size = cc->cc_size; 423 424 /* begin ugh ... can we lose some of this crap?? */ 425 if (p->image != NULL) { 426 count = cc->cc_size.y * 32 / NBBY; 427 error = copyout(cc->cc_cplane, p->image, count); 428 if (error) 429 return (error); 430 error = copyout(cc->cc_eplane, p->mask, count); 431 if (error) 432 return (error); 433 } 434 if (p->cmap.red != NULL) { 435 error = cg14_get_cmap(&p->cmap, 436 (union cg14cmap *)&cc->cc_color, 2); 437 if (error) 438 return (error); 439 } else { 440 p->cmap.index = 0; 441 p->cmap.count = 2; 442 } 443 /* end ugh */ 444 break; 445 446 case FBIOSCURSOR: 447 /* 448 * For setcmap and setshape, verify parameters, so that 449 * we do not get halfway through an update and then crap 450 * out with the software state screwed up. 451 */ 452 v = p->set; 453 if (v & FB_CUR_SETCMAP) { 454 /* 455 * This use of a temporary copy of the cursor 456 * colormap is not terribly efficient, but these 457 * copies are small (8 bytes)... 458 */ 459 tcm = cc->cc_color; 460 error = cg14_put_cmap(&p->cmap, (union cg14cmap *)&tcm, 461 2); 462 if (error) 463 return (error); 464 } 465 if (v & FB_CUR_SETSHAPE) { 466 if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 467 return (EINVAL); 468 count = p->size.y * 32 / NBBY; 469 error = copyin(p->mask, eplane, count); 470 if (error) 471 return error; 472 error = copyin(p->image, cplane, count); 473 if (error) 474 return error; 475 } 476 477 /* parameters are OK; do it */ 478 if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 479 if (v & FB_CUR_SETCUR) 480 cc->cc_enable = p->enable; 481 if (v & FB_CUR_SETPOS) 482 cc->cc_pos = p->pos; 483 if (v & FB_CUR_SETHOT) 484 cc->cc_hot = p->hot; 485 cg14_setcursor(sc); 486 } 487 if (v & FB_CUR_SETCMAP) { 488 cc->cc_color = tcm; 489 cg14_loadomap(sc); /* XXX defer to vertical retrace */ 490 } 491 if (v & FB_CUR_SETSHAPE) { 492 cc->cc_size = p->size; 493 count = p->size.y * 32 / NBBY; 494 memset(cc->cc_eplane, 0, sizeof cc->cc_eplane); 495 memcpy(cc->cc_eplane, eplane, count); 496 memset(cc->cc_cplane, 0, sizeof cc->cc_cplane); 497 memcpy(cc->cc_cplane, cplane, count); 498 cg14_loadcursor(sc); 499 } 500 break; 501 502 #undef cc 503 #undef p 504 case FBIOGCURPOS: 505 *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 506 break; 507 508 case FBIOSCURPOS: 509 sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 510 cg14_setcursor(sc); 511 break; 512 513 case FBIOGCURMAX: 514 /* max cursor size is 32x32 */ 515 ((struct fbcurpos *)data)->x = 32; 516 ((struct fbcurpos *)data)->y = 32; 517 break; 518 519 default: 520 return (ENOTTY); 521 } 522 return (0); 523 } 524 525 /* 526 * Undo the effect of an FBIOSVIDEO that turns the video off. 527 */ 528 static void 529 cgfourteenunblank(struct device *dev) 530 { 531 532 cg14_set_video((struct cgfourteen_softc *)dev, 1); 533 } 534 535 /* 536 * Return the address that would map the given device at the given 537 * offset, allowing for the given protection, or return -1 for error. 538 * 539 * The cg14 frame buffer can be mapped in either 8-bit or 32-bit mode 540 * starting at the address stored in the PROM. In 8-bit mode, the X 541 * channel is not present, and can be ignored. In 32-bit mode, mapping 542 * at 0K delivers a 32-bpp buffer where the upper 8 bits select the X 543 * channel information. We hardwire the Xlut to all zeroes to insure 544 * that, regardless of this value, direct 24-bit color access will be 545 * used. 546 * 547 * Alternatively, mapping the frame buffer at an offset of 16M seems to 548 * tell the chip to ignore the X channel. XXX where does it get the X value 549 * to use? 550 */ 551 paddr_t 552 cgfourteenmmap(dev_t dev, off_t off, int prot) 553 { 554 struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; 555 556 if (off & PGOFSET) 557 panic("cgfourteenmmap"); 558 559 if (off < 0) 560 return (-1); 561 562 #if defined(DEBUG) && defined(CG14_MAP_REGS) /* XXX: security hole */ 563 /* 564 * Map the control registers into user space. Should only be 565 * used for debugging! 566 */ 567 if ((u_int)off >= 0x10000000 && (u_int)off < 0x10000000 + 16*4096) { 568 off -= 0x10000000; 569 if (bus_space_mmap(sc->sc_bustag, 570 BUS_ADDR(sc->sc_physadr[CG14_CTL_IDX].sbr_slot, 571 sc->sc_physadr[CG14_CTL_IDX].sbr_offset), 572 off, prot, BUS_SPACE_MAP_LINEAR)); 573 } 574 #endif 575 576 if ((u_int)off >= NOOVERLAY) 577 off -= NOOVERLAY; 578 else if ((u_int)off >= START) 579 off -= START; 580 else 581 off = 0; 582 583 /* 584 * fb_size includes the overlay space only for the CG8. 585 */ 586 #ifdef CG14_CG8 587 if (off >= sc->sc_fb.fb_type.fb_size - START) 588 #else 589 if (off >= sc->sc_fb.fb_type.fb_size) 590 #endif 591 { 592 #ifdef DEBUG 593 printf("\nmmap request out of bounds: request 0x%x, " 594 "bound 0x%x\n", (unsigned) off, 595 (unsigned)sc->sc_fb.fb_type.fb_size); 596 #endif 597 return (-1); 598 } 599 600 return (bus_space_mmap(sc->sc_bustag, 601 BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].oa_space, 602 sc->sc_physadr[CG14_PXL_IDX].oa_base), 603 off, prot, BUS_SPACE_MAP_LINEAR)); 604 } 605 606 /* 607 * Miscellaneous helper functions 608 */ 609 610 /* Initialize the framebuffer, storing away useful state for later reset */ 611 static void 612 cg14_init(struct cgfourteen_softc *sc) 613 { 614 volatile uint32_t *clut; 615 volatile uint8_t *xlut; 616 int i; 617 618 /* 619 * We stash away the following to restore on close: 620 * 621 * color look-up table 1 (sc->sc_saveclut) 622 * x look-up table (sc->sc_savexlut) 623 * control register (sc->sc_savectl) 624 * cursor control register (sc->sc_savehwc) 625 */ 626 sc->sc_savectl = sc->sc_ctl->ctl_mctl; 627 sc->sc_savehwc = sc->sc_hwc->curs_ctl; 628 629 clut = sc->sc_clut1->clut_lut; 630 xlut = sc->sc_xlut->xlut_lut; 631 for (i = 0; i < CG14_CLUT_SIZE; i++) { 632 sc->sc_saveclut.cm_chip[i] = clut[i]; 633 sc->sc_savexlut[i] = xlut[i]; 634 } 635 636 #ifdef CG14_CG8 637 /* 638 * Enable the video, and put in 24 bit mode. 639 */ 640 sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_32 | 641 CG14_MCTL_POWERCTL; 642 643 /* 644 * Zero the xlut to enable direct-color mode 645 */ 646 memset(sc->sc_xlut, 0, CG14_CLUT_SIZE); 647 #else 648 /* 649 * Enable the video and put it in 8 bit mode 650 */ 651 sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_8 | 652 CG14_MCTL_POWERCTL; 653 #endif 654 } 655 656 /* Restore the state saved on cg14_init */ 657 static void 658 cg14_reset(struct cgfourteen_softc *sc) 659 { 660 volatile uint32_t *clut; 661 volatile uint8_t *xlut; 662 int i; 663 664 /* 665 * We restore the following, saved in cg14_init: 666 * 667 * color look-up table 1 (sc->sc_saveclut) 668 * x look-up table (sc->sc_savexlut) 669 * control register (sc->sc_savectl) 670 * cursor control register (sc->sc_savehwc) 671 * 672 * Note that we don't touch the video enable bits in the 673 * control register; otherwise, screenblank wouldn't work. 674 */ 675 sc->sc_ctl->ctl_mctl = (sc->sc_ctl->ctl_mctl & (CG14_MCTL_ENABLEVID | 676 CG14_MCTL_POWERCTL)) | 677 (sc->sc_savectl & ~(CG14_MCTL_ENABLEVID | 678 CG14_MCTL_POWERCTL)); 679 sc->sc_hwc->curs_ctl = sc->sc_savehwc; 680 681 clut = sc->sc_clut1->clut_lut; 682 xlut = sc->sc_xlut->xlut_lut; 683 for (i = 0; i < CG14_CLUT_SIZE; i++) { 684 clut[i] = sc->sc_saveclut.cm_chip[i]; 685 xlut[i] = sc->sc_savexlut[i]; 686 } 687 } 688 689 /* Enable/disable video display; power down monitor if DPMS-capable */ 690 static void 691 cg14_set_video(struct cgfourteen_softc *sc, int enable) 692 { 693 694 /* 695 * We can only use DPMS to power down the display if the chip revision 696 * is greater than 0. 697 */ 698 if (enable) { 699 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 700 sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID | 701 CG14_MCTL_POWERCTL); 702 else 703 sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID; 704 } else { 705 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 706 sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID | 707 CG14_MCTL_POWERCTL); 708 else 709 sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID; 710 } 711 } 712 713 /* Get status of video display */ 714 static int 715 cg14_get_video(struct cgfourteen_softc *sc) 716 { 717 718 return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); 719 } 720 721 /* Read the software shadow colormap */ 722 static int 723 cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 724 { 725 u_int i, start, count; 726 u_char *cp; 727 int error; 728 729 start = p->index; 730 count = p->count; 731 if (start >= cmsize || count > cmsize - start) 732 return (EINVAL); 733 734 for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { 735 error = copyout(&cp[3], &p->red[i], 1); 736 if (error) 737 return error; 738 error = copyout(&cp[2], &p->green[i], 1); 739 if (error) 740 return error; 741 error = copyout(&cp[1], &p->blue[i], 1); 742 if (error) 743 return error; 744 } 745 return (0); 746 } 747 748 /* Write the software shadow colormap */ 749 static int 750 cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 751 { 752 u_int i, start, count; 753 u_char *cp; 754 u_char cmap[256][4]; 755 int error; 756 757 start = p->index; 758 count = p->count; 759 if (start >= cmsize || count > cmsize - start) 760 return (EINVAL); 761 762 memcpy(&cmap, &cm->cm_map, sizeof cmap); 763 for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) { 764 error = copyin(&p->red[i], &cp[3], 1); 765 if (error) 766 return error; 767 error = copyin(&p->green[i], &cp[2], 1); 768 if (error) 769 return error; 770 error = copyin(&p->blue[i], &cp[1], 1); 771 if (error) 772 return error; 773 cp[0] = 0; /* no alpha channel */ 774 } 775 memcpy(&cm->cm_map, &cmap, sizeof cmap); 776 return (0); 777 } 778 779 static void 780 cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors) 781 { 782 783 /* XXX switch to auto-increment, and on retrace intr */ 784 785 /* Setup pointers to source and dest */ 786 uint32_t *colp = &sc->sc_cmap.cm_chip[start]; 787 volatile uint32_t *lutp = &sc->sc_clut1->clut_lut[start]; 788 789 /* Copy by words */ 790 while (--ncolors >= 0) 791 *lutp++ = *colp++; 792 } 793 794 /* 795 * Load the cursor (overlay `foreground' and `background') colors. 796 */ 797 static void 798 cg14_setcursor(struct cgfourteen_softc *sc) 799 { 800 801 /* we need to subtract the hot-spot value here */ 802 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 803 804 sc->sc_hwc->curs_ctl = (sc->sc_cursor.cc_enable ? CG14_CURS_ENABLE : 0); 805 sc->sc_hwc->curs_x = COORD(x); 806 sc->sc_hwc->curs_y = COORD(y); 807 808 #undef COORD 809 } 810 811 static void 812 cg14_loadcursor(struct cgfourteen_softc *sc) 813 { 814 volatile struct cg14curs *hwc; 815 u_int edgemask, m; 816 int i; 817 818 /* 819 * Keep the top size.x bits. Here we *throw out* the top 820 * size.x bits from an all-one-bits word, introducing zeros in 821 * the top size.x bits, then invert all the bits to get what 822 * we really wanted as our mask. But this fails if size.x is 823 * 32---a sparc uses only the low 5 bits of the shift count--- 824 * so we have to special case that. 825 */ 826 edgemask = ~0; 827 if (sc->sc_cursor.cc_size.x < 32) 828 edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 829 hwc = sc->sc_hwc; 830 for (i = 0; i < 32; i++) { 831 m = sc->sc_cursor.cc_eplane[i] & edgemask; 832 hwc->curs_plane0[i] = m; 833 hwc->curs_plane1[i] = m & sc->sc_cursor.cc_cplane[i]; 834 } 835 } 836 837 static void 838 cg14_loadomap(struct cgfourteen_softc *sc) 839 { 840 841 /* set background color */ 842 sc->sc_hwc->curs_color1 = sc->sc_cursor.cc_color.cm_chip[0]; 843 /* set foreground color */ 844 sc->sc_hwc->curs_color2 = sc->sc_cursor.cc_color.cm_chip[1]; 845 } 846