1 /* $NetBSD: unichromefb.c,v 1.4 2006/08/13 20:27:33 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jared D. McNeill. 18 * 4. Neither the name of The NetBSD Foundation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright 1998-2006 VIA Technologies, Inc. All Rights Reserved. 37 * Copyright 2001-2006 S3 Graphics, Inc. All Rights Reserved. 38 * 39 * Permission is hereby granted, free of charge, to any person obtaining a 40 * copy of this software and associated documentation files (the "Software"), 41 * to deal in the Software without restriction, including without limitation 42 * the rights to use, copy, modify, merge, publish, distribute, sub license, 43 * and/or sell copies of the Software, and to permit persons to whom the 44 * Software is furnished to do so, subject to the following conditions: 45 * 46 * The above copyright notice and this permission notice (including the 47 * next paragraph) shall be included in all copies or substantial portions 48 * of the Software. 49 * 50 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 53 * THE AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 54 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 55 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 56 * DEALINGS IN THE SOFTWARE. 57 */ 58 59 #include <sys/cdefs.h> 60 __KERNEL_RCSID(0, "$NetBSD: unichromefb.c,v 1.4 2006/08/13 20:27:33 jmcneill Exp $"); 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/device.h> 65 #include <sys/malloc.h> 66 67 #include <machine/bus.h> 68 69 #include <dev/pci/pcivar.h> 70 #include <dev/pci/pcireg.h> 71 #include <dev/pci/pcidevs.h> 72 73 #include <dev/wscons/wsdisplayvar.h> 74 #include <dev/wscons/wsconsio.h> 75 #include <dev/wsfont/wsfont.h> 76 #include <dev/rasops/rasops.h> 77 #include <dev/wscons/wsdisplay_vconsvar.h> 78 79 #include <dev/pci/unichromereg.h> 80 #include <dev/pci/unichromemode.h> 81 #include <dev/pci/unichromehw.h> 82 #include <dev/pci/unichromeconfig.h> 83 #include <dev/pci/unichromeaccel.h> 84 85 #include "vga.h" 86 87 #if NVGA > 0 88 #include <dev/ic/mc6845reg.h> 89 #include <dev/ic/pcdisplayvar.h> 90 #include <dev/ic/vgareg.h> 91 #include <dev/ic/vgavar.h> 92 #endif 93 94 /* XXX */ 95 #define UNICHROMEFB_DEPTH 16 96 #define UNICHROMEFB_MODE VIA_RES_1280X1024 97 #define UNICHROMEFB_WIDTH 1280 98 #define UNICHROMEFB_HEIGHT 1024 99 100 struct unichromefb_softc { 101 struct device sc_dev; 102 struct vcons_data sc_vd; 103 void * sc_fbbase; 104 unsigned int sc_fbaddr; 105 unsigned int sc_fbsize; 106 107 bus_space_tag_t sc_iot; 108 bus_space_handle_t sc_ioh; 109 110 bus_space_tag_t sc_memt; 111 bus_space_handle_t sc_memh; 112 113 int sc_width; 114 int sc_height; 115 int sc_depth; 116 int sc_stride; 117 118 int sc_wsmode; 119 120 int sc_accel; 121 }; 122 123 static int unichromefb_match(struct device *, struct cfdata *, void *); 124 static void unichromefb_attach(struct device *, struct device *, void *); 125 126 struct wsscreen_descr unichromefb_stdscreen = { 127 "fb", 128 0, 0, 129 NULL, 130 8, 16, 131 }; 132 133 static int unichromefb_ioctl(void *, void *, u_long, caddr_t, int, 134 struct lwp *); 135 static paddr_t unichromefb_mmap(void *, void *, off_t, int); 136 137 static void unichromefb_init_screen(void *, struct vcons_screen *, 138 int, long *); 139 140 /* hardware access */ 141 static uint8_t uni_rd(struct unichromefb_softc *, int, uint8_t); 142 static void uni_wr(struct unichromefb_softc *, int, uint8_t, uint8_t); 143 static void uni_wr_mask(struct unichromefb_softc *, int, uint8_t, 144 uint8_t, uint8_t); 145 static void uni_wr_x(struct unichromefb_softc *, struct io_reg *, int); 146 static void uni_wr_dac(struct unichromefb_softc *, uint8_t, uint8_t, 147 uint8_t, uint8_t); 148 149 /* helpers */ 150 static struct VideoModeTable * uni_getmode(int); 151 static void uni_setmode(struct unichromefb_softc *, int, int); 152 static void uni_crt_lock(struct unichromefb_softc *); 153 static void uni_crt_unlock(struct unichromefb_softc *); 154 static void uni_crt_enable(struct unichromefb_softc *); 155 static void uni_crt_disable(struct unichromefb_softc *); 156 static void uni_screen_enable(struct unichromefb_softc *); 157 static void uni_screen_disable(struct unichromefb_softc *); 158 static void uni_set_start(struct unichromefb_softc *); 159 static void uni_set_crtc(struct unichromefb_softc *, 160 struct crt_mode_table *, int, int, int); 161 static void uni_load_crtc(struct unichromefb_softc *, struct display_timing, 162 int); 163 static void uni_load_reg(struct unichromefb_softc *, int, int, 164 struct io_register *, int); 165 static void uni_fix_crtc(struct unichromefb_softc *); 166 static void uni_load_offset(struct unichromefb_softc *, int, int, int); 167 static void uni_load_fetchcnt(struct unichromefb_softc *, int, int, int); 168 static void uni_load_fifo(struct unichromefb_softc *, int, int, int); 169 static void uni_set_depth(struct unichromefb_softc *, int, int); 170 static uint32_t uni_get_clkval(struct unichromefb_softc *, int); 171 static void uni_set_vclk(struct unichromefb_softc *, uint32_t, int); 172 static void uni_init_dac(struct unichromefb_softc *, int); 173 static void uni_init_accel(struct unichromefb_softc *); 174 static void uni_set_accel_depth(struct unichromefb_softc *); 175 176 /* graphics ops */ 177 static void uni_wait_idle(struct unichromefb_softc *); 178 static void uni_fillrect(struct unichromefb_softc *, 179 int, int, int, int, int); 180 static void uni_rectinvert(struct unichromefb_softc *, 181 int, int, int, int); 182 static void uni_bitblit(struct unichromefb_softc *, int, int, int, int, 183 int, int); 184 static void uni_setup_mono(struct unichromefb_softc *, int, int, int, 185 int, uint32_t, uint32_t); 186 #if notyet 187 static void uni_cursor_show(struct unichromefb_softc *); 188 static void uni_cursor_hide(struct unichromefb_softc *); 189 #endif 190 191 /* rasops glue */ 192 static void uni_copycols(void *, int, int, int, int); 193 static void uni_copyrows(void *, int, int, int); 194 static void uni_erasecols(void *, int, int, int, long); 195 static void uni_eraserows(void *, int, int, long); 196 static void uni_cursor(void *, int, int, int); 197 static void uni_putchar(void *, int, int, u_int, long); 198 199 struct wsdisplay_accessops unichromefb_accessops = { 200 unichromefb_ioctl, 201 unichromefb_mmap, 202 NULL, 203 NULL, 204 NULL, 205 NULL, 206 }; 207 208 static struct vcons_screen unichromefb_console_screen; 209 210 const struct wsscreen_descr *_unichromefb_scrlist[] = { 211 &unichromefb_stdscreen, 212 }; 213 214 struct wsscreen_list unichromefb_screenlist = { 215 sizeof(_unichromefb_scrlist) / sizeof(struct wsscreen_descr *), 216 _unichromefb_scrlist 217 }; 218 219 CFATTACH_DECL(unichromefb, sizeof(struct unichromefb_softc), 220 unichromefb_match, unichromefb_attach, NULL, NULL); 221 222 static int 223 unichromefb_match(struct device *parent, struct cfdata *match, void *opaque) 224 { 225 struct pci_attach_args *pa; 226 227 pa = (struct pci_attach_args *)opaque; 228 229 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || 230 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) 231 return 0; 232 233 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_VIATECH) 234 return 0; 235 236 switch (PCI_PRODUCT(pa->pa_id)) { 237 case PCI_PRODUCT_VIATECH_VT3314_IG: 238 return 10; /* beat vga(4) */ 239 } 240 241 return 0; 242 } 243 244 static void 245 unichromefb_attach(struct device *parent, struct device *self, void *opaque) 246 { 247 struct unichromefb_softc *sc; 248 struct pci_attach_args *pa; 249 struct rasops_info *ri; 250 struct wsemuldisplaydev_attach_args aa; 251 bus_space_handle_t ap_memh; 252 uint8_t val; 253 bus_addr_t mmiobase; 254 bus_size_t mmiosize; 255 long defattr; 256 257 sc = (struct unichromefb_softc *)self; 258 pa = (struct pci_attach_args *)opaque; 259 260 sc->sc_width = UNICHROMEFB_WIDTH; 261 sc->sc_height = UNICHROMEFB_HEIGHT; 262 sc->sc_depth = UNICHROMEFB_DEPTH; 263 sc->sc_stride = sc->sc_width * (sc->sc_depth / 8); 264 265 sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL; 266 267 sc->sc_iot = pa->pa_iot; 268 269 #if NVGA > 0 270 /* XXX vga_cnattach claims the I/O registers that we need; 271 * we need to nuke it here so we can take over. 272 */ 273 vga_cndetach(); 274 #endif 275 276 if (bus_space_map(sc->sc_iot, VIA_REGBASE, 0x20, 0, &sc->sc_ioh)) { 277 aprint_error(": failed to map I/O registers\n"); 278 return; 279 } 280 281 sc->sc_memt = pa->pa_memt; 282 val = uni_rd(sc, VIASR, SR30); 283 sc->sc_fbaddr = val << 24; 284 val = uni_rd(sc, VIASR, SR39); 285 sc->sc_fbsize = val * (4*1024*1024); 286 if (sc->sc_fbsize < 16*1024*1024 || sc->sc_fbsize > 64*1024*1024) 287 sc->sc_fbsize = 16*1024*1024; 288 if (bus_space_map(sc->sc_memt, sc->sc_fbaddr, sc->sc_fbsize, 289 BUS_SPACE_MAP_LINEAR, &ap_memh)) { 290 aprint_error(": failed to map aperture at 0x%08x/0x%x\n", 291 sc->sc_fbaddr, sc->sc_fbsize); 292 return; 293 } 294 sc->sc_fbbase = (caddr_t)bus_space_vaddr(sc->sc_memt, ap_memh); 295 296 if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_MEM, 0, 297 &sc->sc_memt, &sc->sc_memh, &mmiobase, &mmiosize)) { 298 sc->sc_accel = 0; 299 aprint_error(": failed to map MMIO registers\n"); 300 } else { 301 sc->sc_accel = 1; 302 } 303 304 aprint_naive("\n"); 305 aprint_normal(": VIA UniChrome frame buffer\n"); 306 307 if (sc->sc_accel) 308 aprint_normal("%s: MMIO @0x%08x/0x%x\n", 309 sc->sc_dev.dv_xname, (uint32_t)mmiobase, 310 (uint32_t)mmiosize); 311 312 ri = &unichromefb_console_screen.scr_ri; 313 memset(ri, 0, sizeof(struct rasops_info)); 314 315 vcons_init(&sc->sc_vd, sc, &unichromefb_stdscreen, 316 &unichromefb_accessops); 317 sc->sc_vd.init_screen = unichromefb_init_screen; 318 319 uni_setmode(sc, UNICHROMEFB_MODE, sc->sc_depth); 320 321 uni_init_dac(sc, IGA1); 322 if (sc->sc_accel) { 323 uni_init_accel(sc); 324 uni_fillrect(sc, 0, 0, sc->sc_width, sc->sc_height, 0); 325 } 326 327 aprint_normal("%s: FB @0x%08x (%dx%dx%d)\n", sc->sc_dev.dv_xname, 328 sc->sc_fbaddr, sc->sc_width, sc->sc_height, sc->sc_depth); 329 330 unichromefb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 331 vcons_init_screen(&sc->sc_vd, &unichromefb_console_screen, 1, &defattr); 332 333 unichromefb_stdscreen.ncols = ri->ri_cols; 334 unichromefb_stdscreen.nrows = ri->ri_rows; 335 unichromefb_stdscreen.textops = &ri->ri_ops; 336 unichromefb_stdscreen.capabilities = ri->ri_caps; 337 unichromefb_stdscreen.modecookie = NULL; 338 339 wsdisplay_cnattach(&unichromefb_stdscreen, ri, 0, 0, defattr); 340 341 aa.console = 1; /* XXX */ 342 aa.scrdata = &unichromefb_screenlist; 343 aa.accessops = &unichromefb_accessops; 344 aa.accesscookie = &sc->sc_vd; 345 346 config_found(self, &aa, wsemuldisplaydevprint); 347 348 return; 349 } 350 351 static int 352 unichromefb_ioctl(void *v, void *vs, u_long cmd, caddr_t data, int flag, 353 struct lwp *l) 354 { 355 struct vcons_data *vd; 356 struct unichromefb_softc *sc; 357 struct wsdisplay_fbinfo *fb; 358 359 vd = (struct vcons_data *)v; 360 sc = (struct unichromefb_softc *)vd->cookie; 361 362 switch (cmd) { 363 case WSDISPLAYIO_GTYPE: 364 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 365 return 0; 366 case WSDISPLAYIO_GINFO: 367 if (vd->active != NULL) { 368 fb = (struct wsdisplay_fbinfo *)data; 369 fb->width = sc->sc_width; 370 fb->height = sc->sc_height; 371 fb->depth = sc->sc_depth; 372 fb->cmsize = 256; 373 return 0; 374 } else 375 return ENODEV; 376 case WSDISPLAYIO_GVIDEO: 377 return ENODEV; 378 case WSDISPLAYIO_SVIDEO: 379 return ENODEV; 380 case WSDISPLAYIO_GETCMAP: 381 return EINVAL; 382 case WSDISPLAYIO_PUTCMAP: 383 return EINVAL; 384 case WSDISPLAYIO_LINEBYTES: 385 *(u_int *)data = sc->sc_stride; 386 return 0; 387 case WSDISPLAYIO_SMODE: 388 { 389 int new_mode = *(int *)data; 390 if (new_mode != sc->sc_wsmode) { 391 sc->sc_wsmode = new_mode; 392 if (new_mode == WSDISPLAYIO_MODE_EMUL) 393 vcons_redraw_screen(vd->active); 394 } 395 } 396 return 0; 397 case WSDISPLAYIO_SSPLASH: 398 return ENODEV; 399 case WSDISPLAYIO_SPROGRESS: 400 return ENODEV; 401 } 402 403 return EPASSTHROUGH; 404 } 405 406 static paddr_t 407 unichromefb_mmap(void *v, void *vs, off_t offset, int prot) 408 { 409 return -1; 410 } 411 412 static void 413 unichromefb_init_screen(void *c, struct vcons_screen *scr, int existing, 414 long *defattr) 415 { 416 struct unichromefb_softc *sc; 417 struct rasops_info *ri; 418 419 sc = (struct unichromefb_softc *)c; 420 ri = &scr->scr_ri; 421 ri->ri_flg = RI_CENTER; 422 ri->ri_depth = sc->sc_depth; 423 ri->ri_width = sc->sc_width; 424 ri->ri_height = sc->sc_height; 425 ri->ri_stride = sc->sc_stride; 426 ri->ri_bits = sc->sc_fbbase; 427 if (existing) 428 ri->ri_flg |= RI_CLEAR; 429 430 switch (ri->ri_depth) { 431 case 32: 432 ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8; 433 ri->ri_rpos = 16; 434 ri->ri_gpos = 8; 435 ri->ri_bpos = 0; 436 break; 437 case 16: 438 ri->ri_rnum = 5; 439 ri->ri_gnum = 6; 440 ri->ri_bnum = 5; 441 ri->ri_rpos = 11; 442 ri->ri_gpos = 5; 443 ri->ri_bpos = 0; 444 break; 445 } 446 447 rasops_init(ri, sc->sc_height / 16, sc->sc_width / 8); 448 ri->ri_caps = WSSCREEN_WSCOLORS; 449 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 450 sc->sc_width / ri->ri_font->fontwidth); 451 452 ri->ri_hw = scr; 453 if (sc->sc_accel) { 454 ri->ri_ops.copyrows = uni_copyrows; 455 ri->ri_ops.copycols = uni_copycols; 456 ri->ri_ops.eraserows = uni_eraserows; 457 ri->ri_ops.erasecols = uni_erasecols; 458 ri->ri_ops.cursor = uni_cursor; 459 ri->ri_ops.putchar = uni_putchar; 460 } 461 462 return; 463 } 464 465 /* 466 * hardware access 467 */ 468 static uint8_t 469 uni_rd(struct unichromefb_softc *sc, int off, uint8_t idx) 470 { 471 bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx); 472 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, off + 1); 473 } 474 475 static void 476 uni_wr(struct unichromefb_softc *sc, int off, uint8_t idx, uint8_t val) 477 { 478 bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx); 479 bus_space_write_1(sc->sc_iot, sc->sc_ioh, off + 1, val); 480 } 481 482 static void 483 uni_wr_mask(struct unichromefb_softc *sc, int off, uint8_t idx, 484 uint8_t val, uint8_t mask) 485 { 486 uint8_t tmp; 487 488 bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, idx); 489 tmp = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off + 1); 490 bus_space_write_1(sc->sc_iot, sc->sc_ioh, off + 1, 491 ((val & mask) | (tmp & ~mask))); 492 } 493 494 static void 495 uni_wr_dac(struct unichromefb_softc *sc, uint8_t idx, 496 uint8_t r, uint8_t g, uint8_t b) 497 { 498 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_INDEX_WRITE, idx); 499 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, r); 500 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, g); 501 bus_space_write_1(sc->sc_iot, sc->sc_ioh, LUT_DATA, b); 502 } 503 504 static void 505 uni_wr_x(struct unichromefb_softc *sc, struct io_reg *tbl, int num) 506 { 507 int i; 508 uint8_t tmp; 509 510 for (i = 0; i < num; i++) { 511 bus_space_write_1(sc->sc_iot, sc->sc_ioh, tbl[i].port, 512 tbl[i].index); 513 tmp = bus_space_read_1(sc->sc_iot, sc->sc_iot, 514 tbl[i].port + 1); 515 tmp = (tmp & (~tbl[i].mask)) | tbl[i].value; 516 bus_space_write_1(sc->sc_iot, sc->sc_ioh, tbl[i].index + 1, 517 tmp); 518 } 519 } 520 521 /* 522 * helpers 523 */ 524 static struct VideoModeTable * 525 uni_getmode(int mode) 526 { 527 int i; 528 529 for (i = 0; i < NUM_TOTAL_MODETABLE; i++) 530 if (CLE266Modes[i].ModeIndex == mode) 531 return &CLE266Modes[i]; 532 533 return NULL; 534 } 535 536 static void 537 uni_setmode(struct unichromefb_softc *sc, int idx, int bpp) 538 { 539 struct VideoModeTable *vtbl; 540 struct crt_mode_table *crt; 541 int i; 542 543 /* XXX */ 544 vtbl = uni_getmode(idx); 545 if (vtbl == NULL) 546 panic("%s: unsupported mode: %d\n", sc->sc_dev.dv_xname, idx); 547 548 crt = vtbl->crtc; 549 550 uni_screen_disable(sc); 551 552 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus); 553 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, 0); 554 555 /* XXX assume CN900 for now */ 556 uni_wr_x(sc, CN900_ModeXregs, NUM_TOTAL_CN900_ModeXregs); 557 558 uni_crt_disable(sc); 559 560 /* Fill VPIT params */ 561 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, VPIT.Misc); 562 563 /* Write sequencer */ 564 for (i = 1; i <= StdSR; i++) { 565 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIASR, i); 566 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIASR + 1, 567 VPIT.SR[i - 1]); 568 } 569 570 uni_set_start(sc); 571 572 uni_set_crtc(sc, crt, idx, bpp / 8, IGA1); 573 574 for (i = 0; i < StdGR; i++) { 575 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAGR, i); 576 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAGR + 1, 577 VPIT.GR[i]); 578 } 579 580 for (i = 0; i < StdAR; i++) { 581 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus); 582 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, i); 583 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, 584 VPIT.AR[i]); 585 } 586 587 (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIAStatus); 588 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAAR, 0x20); 589 590 uni_set_crtc(sc, crt, idx, bpp / 8, IGA1); 591 /* set crt output path */ 592 uni_wr_mask(sc, VIASR, SR16, 0x00, BIT6); 593 594 uni_crt_enable(sc); 595 uni_screen_enable(sc); 596 597 return; 598 } 599 600 static void 601 uni_crt_lock(struct unichromefb_softc *sc) 602 { 603 uni_wr_mask(sc, VIACR, CR11, BIT7, BIT7); 604 } 605 606 static void 607 uni_crt_unlock(struct unichromefb_softc *sc) 608 { 609 uni_wr_mask(sc, VIACR, CR11, 0, BIT7); 610 uni_wr_mask(sc, VIACR, CR47, 0, BIT0); 611 } 612 613 static void 614 uni_crt_enable(struct unichromefb_softc *sc) 615 { 616 uni_wr_mask(sc, VIACR, CR36, 0, BIT5+BIT4); 617 } 618 619 static void 620 uni_crt_disable(struct unichromefb_softc *sc) 621 { 622 uni_wr_mask(sc, VIACR, CR36, BIT5+BIT4, BIT5+BIT4); 623 } 624 625 static void 626 uni_screen_enable(struct unichromefb_softc *sc) 627 { 628 uni_wr_mask(sc, VIASR, SR01, 0, BIT5); 629 } 630 631 static void 632 uni_screen_disable(struct unichromefb_softc *sc) 633 { 634 uni_wr_mask(sc, VIASR, SR01, 0x20, BIT5); 635 } 636 637 static void 638 uni_set_start(struct unichromefb_softc *sc) 639 { 640 uni_crt_unlock(sc); 641 642 uni_wr(sc, VIACR, CR0C, 0x00); 643 uni_wr(sc, VIACR, CR0D, 0x00); 644 uni_wr(sc, VIACR, CR34, 0x00); 645 uni_wr_mask(sc, VIACR, CR48, 0x00, BIT0 + BIT1); 646 647 uni_wr(sc, VIACR, CR62, 0x00); 648 uni_wr(sc, VIACR, CR63, 0x00); 649 uni_wr(sc, VIACR, CR64, 0x00); 650 uni_wr(sc, VIACR, CRA3, 0x00); 651 652 uni_crt_lock(sc); 653 } 654 655 static void 656 uni_set_crtc(struct unichromefb_softc *sc, struct crt_mode_table *ctbl, 657 int mode, int bpp_byte, int iga) 658 { 659 struct VideoModeTable *vtbl; 660 struct display_timing crtreg; 661 int i; 662 int index; 663 int haddr, vaddr; 664 uint8_t val; 665 uint32_t pll_d_n; 666 667 index = 0; 668 669 vtbl = uni_getmode(mode); 670 for (i = 0; i < vtbl->mode_array; i++) { 671 index = i; 672 if (ctbl[i].refresh_rate == 60) 673 break; 674 } 675 676 crtreg = ctbl[index].crtc; 677 678 haddr = crtreg.hor_addr; 679 vaddr = crtreg.ver_addr; 680 681 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIARMisc); 682 if (ctbl[index].h_sync_polarity == NEGATIVE) { 683 if (ctbl[index].v_sync_polarity == NEGATIVE) 684 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, 685 (val & (~(BIT6+BIT7))) | (BIT6+BIT7)); 686 else 687 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, 688 (val & (~(BIT6+BIT7))) | (BIT6)); 689 } else { 690 if (ctbl[index].v_sync_polarity == NEGATIVE) 691 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, 692 (val & (~(BIT6+BIT7))) | (BIT7)); 693 else 694 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, 695 (val & (~(BIT6+BIT7)))); 696 } 697 698 if (iga == IGA1) { 699 uni_crt_unlock(sc); 700 uni_wr(sc, VIACR, CR09, 0x00); 701 uni_wr_mask(sc, VIACR, CR11, 0x00, BIT4+BIT5+BIT6); 702 uni_wr_mask(sc, VIACR, CR17, 0x00, BIT7); 703 } 704 705 uni_load_crtc(sc, crtreg, iga); 706 uni_fix_crtc(sc); 707 uni_crt_lock(sc); 708 uni_wr_mask(sc, VIACR, CR17, 0x80, BIT7); 709 710 uni_load_offset(sc, haddr, bpp_byte, iga); 711 uni_load_fetchcnt(sc, haddr, bpp_byte, iga); 712 uni_load_fifo(sc, iga, haddr, vaddr); 713 714 uni_set_depth(sc, bpp_byte, iga); 715 pll_d_n = uni_get_clkval(sc, ctbl[index].clk); 716 uni_set_vclk(sc, pll_d_n, iga); 717 } 718 719 static void 720 uni_load_crtc(struct unichromefb_softc *sc, 721 struct display_timing device_timing, int iga) 722 { 723 int regnum, val; 724 struct io_register *reg; 725 int i; 726 727 regnum = val = 0; 728 reg = NULL; 729 730 uni_crt_unlock(sc); 731 732 for (i = 0; i < 12; i++) { 733 switch (iga) { 734 case IGA1: 735 switch (i) { 736 case H_TOTAL_INDEX: 737 val = IGA1_HOR_TOTAL_FORMULA( 738 device_timing.hor_total); 739 regnum = iga1_crtc_reg.hor_total.reg_num; 740 reg = iga1_crtc_reg.hor_total.reg; 741 break; 742 case H_ADDR_INDEX: 743 val = IGA1_HOR_ADDR_FORMULA( 744 device_timing.hor_addr); 745 regnum = iga1_crtc_reg.hor_addr.reg_num; 746 reg = iga1_crtc_reg.hor_addr.reg; 747 break; 748 case H_BLANK_START_INDEX: 749 val = IGA1_HOR_BLANK_START_FORMULA( 750 device_timing.hor_blank_start); 751 regnum = iga1_crtc_reg.hor_blank_start.reg_num; 752 reg = iga1_crtc_reg.hor_blank_start.reg; 753 break; 754 case H_BLANK_END_INDEX: 755 val = IGA1_HOR_BLANK_END_FORMULA( 756 device_timing.hor_blank_start, 757 device_timing.hor_blank_end); 758 regnum = iga1_crtc_reg.hor_blank_end.reg_num; 759 reg = iga1_crtc_reg.hor_blank_end.reg; 760 break; 761 case H_SYNC_START_INDEX: 762 val = IGA1_HOR_SYNC_START_FORMULA( 763 device_timing.hor_sync_start); 764 regnum = iga1_crtc_reg.hor_sync_start.reg_num; 765 reg = iga1_crtc_reg.hor_sync_start.reg; 766 break; 767 case H_SYNC_END_INDEX: 768 val = IGA1_HOR_SYNC_END_FORMULA( 769 device_timing.hor_sync_start, 770 device_timing.hor_sync_end); 771 regnum = iga1_crtc_reg.hor_sync_end.reg_num; 772 reg = iga1_crtc_reg.hor_sync_end.reg; 773 break; 774 case V_TOTAL_INDEX: 775 val = IGA1_VER_TOTAL_FORMULA( 776 device_timing.ver_total); 777 regnum = iga1_crtc_reg.ver_total.reg_num; 778 reg = iga1_crtc_reg.ver_total.reg; 779 break; 780 case V_ADDR_INDEX: 781 val = IGA1_VER_ADDR_FORMULA( 782 device_timing.ver_addr); 783 regnum = iga1_crtc_reg.ver_addr.reg_num; 784 reg = iga1_crtc_reg.ver_addr.reg; 785 break; 786 case V_BLANK_START_INDEX: 787 val = IGA1_VER_BLANK_START_FORMULA( 788 device_timing.ver_blank_start); 789 regnum = iga1_crtc_reg.ver_blank_start.reg_num; 790 reg = iga1_crtc_reg.ver_blank_start.reg; 791 break; 792 case V_BLANK_END_INDEX: 793 val = IGA1_VER_BLANK_END_FORMULA( 794 device_timing.ver_blank_start, 795 device_timing.ver_blank_end); 796 regnum = iga1_crtc_reg.ver_blank_end.reg_num; 797 reg = iga1_crtc_reg.ver_blank_end.reg; 798 break; 799 case V_SYNC_START_INDEX: 800 val = IGA1_VER_SYNC_START_FORMULA( 801 device_timing.ver_sync_start); 802 regnum = iga1_crtc_reg.ver_sync_start.reg_num; 803 reg = iga1_crtc_reg.ver_sync_start.reg; 804 break; 805 case V_SYNC_END_INDEX: 806 val = IGA1_VER_SYNC_END_FORMULA( 807 device_timing.ver_sync_start, 808 device_timing.ver_sync_end); 809 regnum = iga1_crtc_reg.ver_sync_end.reg_num; 810 reg = iga1_crtc_reg.ver_sync_end.reg; 811 break; 812 default: 813 printf("%s: unknown index %d while setting up CRTC\n", 814 sc->sc_dev.dv_xname, i); 815 break; 816 } 817 break; 818 case IGA2: 819 printf("%s: %s: IGA2 not supported\n", 820 sc->sc_dev.dv_xname, __func__); 821 break; 822 } 823 824 uni_load_reg(sc, val, regnum, reg, VIACR); 825 } 826 827 uni_crt_lock(sc); 828 } 829 830 static void 831 uni_load_reg(struct unichromefb_softc *sc, int timing, int regnum, 832 struct io_register *reg, int type) 833 { 834 int regmask, bitnum, data; 835 int i, j; 836 int shift_next_reg; 837 int startidx, endidx, cridx; 838 uint16_t getbit; 839 840 bitnum = 0; 841 842 for (i = 0; i < regnum; i++) { 843 regmask = data = 0; 844 startidx = reg[i].start_bit; 845 endidx = reg[i].end_bit; 846 cridx = reg[i].io_addr; 847 848 shift_next_reg = bitnum; 849 850 for (j = startidx; j <= endidx; j++) { 851 regmask = regmask | (BIT0 << j); 852 getbit = (timing & (BIT0 << bitnum)); 853 data = data | ((getbit >> shift_next_reg) << startidx); 854 ++bitnum; 855 } 856 857 if (type == VIACR) 858 uni_wr_mask(sc, VIACR, cridx, data, regmask); 859 else 860 uni_wr_mask(sc, VIASR, cridx, data, regmask); 861 } 862 863 return; 864 } 865 866 static void 867 uni_fix_crtc(struct unichromefb_softc *sc) 868 { 869 uni_wr_mask(sc, VIACR, CR03, 0x80, BIT7); 870 uni_wr(sc, VIACR, CR18, 0xff); 871 uni_wr_mask(sc, VIACR, CR07, 0x10, BIT4); 872 uni_wr_mask(sc, VIACR, CR09, 0x40, BIT6); 873 uni_wr_mask(sc, VIACR, CR35, 0x10, BIT4); 874 uni_wr_mask(sc, VIACR, CR33, 0x06, BIT0+BIT1+BIT2); 875 uni_wr(sc, VIACR, CR17, 0xe3); 876 uni_wr(sc, VIACR, CR08, 0x00); 877 uni_wr(sc, VIACR, CR14, 0x00); 878 879 return; 880 } 881 882 static void 883 uni_load_offset(struct unichromefb_softc *sc, int haddr, int bpp, int iga) 884 { 885 886 switch (iga) { 887 case IGA1: 888 uni_load_reg(sc, 889 IGA1_OFFSET_FORMULA(haddr, bpp), 890 offset_reg.iga1_offset_reg.reg_num, 891 offset_reg.iga1_offset_reg.reg, 892 VIACR); 893 break; 894 default: 895 printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname, 896 __func__); 897 break; 898 } 899 900 return; 901 } 902 903 static void 904 uni_load_fetchcnt(struct unichromefb_softc *sc, int haddr, int bpp, int iga) 905 { 906 907 switch (iga) { 908 case IGA1: 909 uni_load_reg(sc, 910 IGA1_FETCH_COUNT_FORMULA(haddr, bpp), 911 fetch_count_reg.iga1_fetch_count_reg.reg_num, 912 fetch_count_reg.iga1_fetch_count_reg.reg, 913 VIASR); 914 break; 915 default: 916 printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname, 917 __func__); 918 break; 919 } 920 921 return; 922 } 923 924 static void 925 uni_load_fifo(struct unichromefb_softc *sc, int iga, int horact, int veract) 926 { 927 int val, regnum; 928 struct io_register *reg; 929 int iga1_fifo_max_depth, iga1_fifo_threshold; 930 int iga1_fifo_high_threshold, iga1_display_queue_expire_num; 931 932 reg = NULL; 933 iga1_fifo_max_depth = iga1_fifo_threshold = 0; 934 iga1_fifo_high_threshold = iga1_display_queue_expire_num = 0; 935 936 switch (iga) { 937 case IGA1: 938 /* XXX if (type == CN900) { */ 939 iga1_fifo_max_depth = CN900_IGA1_FIFO_MAX_DEPTH; 940 iga1_fifo_threshold = CN900_IGA1_FIFO_THRESHOLD; 941 iga1_fifo_high_threshold = CN900_IGA1_FIFO_HIGH_THRESHOLD; 942 if (horact > 1280 && veract > 1024) 943 iga1_display_queue_expire_num = 16; 944 else 945 iga1_display_queue_expire_num = 946 CN900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM; 947 /* XXX } */ 948 949 /* set display FIFO depth select */ 950 val = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth); 951 regnum = 952 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num; 953 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg; 954 uni_load_reg(sc, val, regnum, reg, VIASR); 955 956 /* set display FIFO threshold select */ 957 val = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold); 958 regnum = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg_num; 959 reg = fifo_threshold_select_reg.iga1_fifo_threshold_select_reg.reg; 960 uni_load_reg(sc, val, regnum, reg, VIASR); 961 962 /* set display FIFO high threshold select */ 963 val = IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold); 964 regnum = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg_num; 965 reg = fifo_high_threshold_select_reg.iga1_fifo_high_threshold_select_reg.reg; 966 uni_load_reg(sc, val, regnum, reg, VIASR); 967 968 /* set display queue expire num */ 969 val = IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(iga1_display_queue_expire_num); 970 regnum = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg_num; 971 reg = display_queue_expire_num_reg.iga1_display_queue_expire_num_reg.reg; 972 uni_load_reg(sc, val, regnum, reg, VIASR); 973 974 break; 975 default: 976 printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname, 977 __func__); 978 break; 979 } 980 981 return; 982 } 983 984 static void 985 uni_set_depth(struct unichromefb_softc *sc, int bpp, int iga) 986 { 987 switch (iga) { 988 case IGA1: 989 switch (bpp) { 990 case MODE_32BPP: 991 uni_wr_mask(sc, VIASR, SR15, 0xae, 0xfe); 992 break; 993 case MODE_16BPP: 994 uni_wr_mask(sc, VIASR, SR15, 0xb6, 0xfe); 995 break; 996 case MODE_8BPP: 997 uni_wr_mask(sc, VIASR, SR15, 0x22, 0xfe); 998 break; 999 default: 1000 printf("%s: %s: mode (%d) unsupported\n", 1001 sc->sc_dev.dv_xname, __func__, bpp); 1002 } 1003 break; 1004 default: 1005 printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname, 1006 __func__); 1007 break; 1008 } 1009 } 1010 1011 static uint32_t 1012 uni_get_clkval(struct unichromefb_softc *sc, int clk) 1013 { 1014 int i; 1015 1016 for (i = 0; i < NUM_TOTAL_PLL_TABLE; i++) { 1017 if (clk == pll_value[i].clk) { 1018 /* XXX only CN900 supported for now */ 1019 return pll_value[i].k800_pll; 1020 } 1021 } 1022 1023 aprint_error("%s: can't find matching PLL value\n", 1024 sc->sc_dev.dv_xname); 1025 1026 return 0; 1027 } 1028 1029 static void 1030 uni_set_vclk(struct unichromefb_softc *sc, uint32_t clk, int iga) 1031 { 1032 uint8_t val; 1033 1034 /* hardware reset on */ 1035 uni_wr_mask(sc, VIACR, CR17, 0x00, BIT7); 1036 1037 switch (iga) { 1038 case IGA1: 1039 /* XXX only CN900 is supported */ 1040 uni_wr(sc, VIASR, SR44, clk / 0x10000); 1041 uni_wr(sc, VIASR, SR45, (clk & 0xffff) / 0x100); 1042 uni_wr(sc, VIASR, SR46, clk % 0x100); 1043 break; 1044 default: 1045 printf("%s: %s: only IGA1 is supported\n", sc->sc_dev.dv_xname, 1046 __func__); 1047 break; 1048 } 1049 1050 /* hardware reset off */ 1051 uni_wr_mask(sc, VIACR, CR17, 0x80, BIT7); 1052 1053 /* reset pll */ 1054 switch (iga) { 1055 case IGA1: 1056 uni_wr_mask(sc, VIASR, SR40, 0x02, BIT1); 1057 uni_wr_mask(sc, VIASR, SR40, 0x00, BIT1); 1058 break; 1059 } 1060 1061 /* good to go */ 1062 val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, VIARMisc); 1063 val |= (BIT2+BIT3); 1064 bus_space_write_1(sc->sc_iot, sc->sc_ioh, VIAWMisc, val); 1065 1066 return; 1067 } 1068 1069 static void 1070 uni_init_dac(struct unichromefb_softc *sc, int iga) 1071 { 1072 int i; 1073 1074 /* XXX only IGA1 for now */ 1075 uni_wr_mask(sc, VIASR, SR1A, 0x00, BIT0); 1076 uni_wr_mask(sc, VIASR, SR18, 0x00, BIT7+BIT6); 1077 for (i = 0; i < 256; i++) 1078 uni_wr_dac(sc, i, 1079 palLUT_table[i].red, palLUT_table[i].green, palLUT_table[i].blue); 1080 1081 uni_wr_mask(sc, VIASR, SR18, 0xc0, BIT7+BIT6); 1082 1083 return; 1084 } 1085 1086 static void 1087 uni_init_accel(struct unichromefb_softc *sc) 1088 { 1089 1090 /* init 2D engine regs to reset 2D engine */ 1091 MMIO_OUT32(VIA_REG_GEMODE, 0); 1092 MMIO_OUT32(VIA_REG_SRCPOS, 0); 1093 MMIO_OUT32(VIA_REG_DSTPOS, 0); 1094 MMIO_OUT32(VIA_REG_DIMENSION, 0); 1095 MMIO_OUT32(VIA_REG_PATADDR, 0); 1096 MMIO_OUT32(VIA_REG_FGCOLOR, 0); 1097 MMIO_OUT32(VIA_REG_BGCOLOR, 0); 1098 MMIO_OUT32(VIA_REG_CLIPTL, 0); 1099 MMIO_OUT32(VIA_REG_CLIPBR, 0); 1100 MMIO_OUT32(VIA_REG_OFFSET, 0); 1101 MMIO_OUT32(VIA_REG_KEYCONTROL, 0); 1102 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1103 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1104 MMIO_OUT32(VIA_REG_PITCH, 0); 1105 MMIO_OUT32(VIA_REG_MONOPAT1, 0); 1106 1107 /* init AGP and VQ registers */ 1108 MMIO_OUT32(VIA_REG_TRANSET, 0x00100000); 1109 MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000000); 1110 MMIO_OUT32(VIA_REG_TRANSPACE, 0x00333004); 1111 MMIO_OUT32(VIA_REG_TRANSPACE, 0x60000000); 1112 MMIO_OUT32(VIA_REG_TRANSPACE, 0x61000000); 1113 MMIO_OUT32(VIA_REG_TRANSPACE, 0x62000000); 1114 MMIO_OUT32(VIA_REG_TRANSPACE, 0x63000000); 1115 MMIO_OUT32(VIA_REG_TRANSPACE, 0x64000000); 1116 MMIO_OUT32(VIA_REG_TRANSPACE, 0x7d000000); 1117 1118 MMIO_OUT32(VIA_REG_TRANSET, 0xfe020000); 1119 MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000000); 1120 1121 /* disable VQ */ 1122 MMIO_OUT32(VIA_REG_TRANSET, 0x00fe0000); 1123 MMIO_OUT32(VIA_REG_TRANSPACE, 0x00000004); 1124 MMIO_OUT32(VIA_REG_TRANSPACE, 0x40008c0f); 1125 MMIO_OUT32(VIA_REG_TRANSPACE, 0x44000000); 1126 MMIO_OUT32(VIA_REG_TRANSPACE, 0x45080c04); 1127 MMIO_OUT32(VIA_REG_TRANSPACE, 0x46800408); 1128 1129 uni_set_accel_depth(sc); 1130 1131 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1132 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1133 1134 MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE | 1135 (((sc->sc_width * sc->sc_depth >> 3) >> 3) | 1136 (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16))); 1137 1138 return; 1139 } 1140 1141 static void 1142 uni_set_accel_depth(struct unichromefb_softc *sc) 1143 { 1144 uint32_t gemode; 1145 1146 gemode = MMIO_IN32(0x04) & 0xfffffcff; 1147 1148 switch (sc->sc_depth) { 1149 case 32: 1150 gemode |= VIA_GEM_32bpp; 1151 break; 1152 case 16: 1153 gemode |= VIA_GEM_16bpp; 1154 break; 1155 default: 1156 gemode |= VIA_GEM_8bpp; 1157 break; 1158 } 1159 1160 /* set colour depth and pitch */ 1161 MMIO_OUT32(VIA_REG_GEMODE, gemode); 1162 1163 return; 1164 } 1165 1166 static void 1167 uni_wait_idle(struct unichromefb_softc *sc) 1168 { 1169 int loop = 0; 1170 1171 while (!(MMIO_IN32(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && 1172 (loop++ < MAXLOOP)) 1173 ; 1174 1175 while ((MMIO_IN32(VIA_REG_STATUS) & 1176 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && 1177 (loop++ < MAXLOOP)) 1178 ; 1179 1180 if (loop >= MAXLOOP) 1181 aprint_error("%s: engine stall\n", sc->sc_dev.dv_xname); 1182 1183 return; 1184 } 1185 1186 static void 1187 uni_fillrect(struct unichromefb_softc *sc, int x, int y, int width, 1188 int height, int colour) 1189 { 1190 1191 uni_wait_idle(sc); 1192 1193 MMIO_OUT32(VIA_REG_SRCPOS, 0); 1194 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1195 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1196 MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE | 1197 (((sc->sc_width * sc->sc_depth >> 3) >> 3) | 1198 (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16))); 1199 MMIO_OUT32(VIA_REG_DSTPOS, ((y << 16) | x)); 1200 MMIO_OUT32(VIA_REG_DIMENSION, 1201 (((height - 1) << 16) | (width - 1))); 1202 MMIO_OUT32(VIA_REG_FGCOLOR, colour); 1203 MMIO_OUT32(VIA_REG_GECMD, (0x01 | 0x2000 | 0xf0 << 24)); 1204 1205 return; 1206 } 1207 1208 static void 1209 uni_rectinvert(struct unichromefb_softc *sc, int x, int y, int width, 1210 int height) 1211 { 1212 1213 uni_wait_idle(sc); 1214 1215 MMIO_OUT32(VIA_REG_SRCPOS, 0); 1216 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1217 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1218 MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE | 1219 (((sc->sc_width * sc->sc_depth >> 3) >> 3) | 1220 (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16))); 1221 MMIO_OUT32(VIA_REG_DSTPOS, ((y << 16) | x)); 1222 MMIO_OUT32(VIA_REG_DIMENSION, 1223 (((height - 1) << 16) | (width - 1))); 1224 MMIO_OUT32(VIA_REG_GECMD, (0x01 | 0x2000 | 0x55 << 24)); 1225 1226 return; 1227 } 1228 1229 static void 1230 uni_bitblit(struct unichromefb_softc *sc, int xs, int ys, int xd, int yd, int width, int height) 1231 { 1232 uint32_t dir; 1233 1234 dir = 0; 1235 1236 if (ys < yd) { 1237 yd += height - 1; 1238 ys += height - 1; 1239 dir |= 0x4000; 1240 } 1241 1242 if (xs < xd) { 1243 xd += width - 1; 1244 xs += width - 1; 1245 dir |= 0x8000; 1246 } 1247 1248 uni_wait_idle(sc); 1249 1250 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1251 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1252 MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE | 1253 (((sc->sc_width * sc->sc_depth >> 3) >> 3) | 1254 (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16))); 1255 MMIO_OUT32(VIA_REG_SRCPOS, ys << 16 | xs); 1256 MMIO_OUT32(VIA_REG_DSTPOS, yd << 16 | xd); 1257 MMIO_OUT32(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1)); 1258 MMIO_OUT32(VIA_REG_GECMD, (0x01 | dir | (0xcc << 24))); 1259 1260 return; 1261 } 1262 1263 static void 1264 uni_setup_mono(struct unichromefb_softc *sc, int xd, int yd, int width, int height, 1265 uint32_t fg, uint32_t bg) 1266 { 1267 1268 uni_wait_idle(sc); 1269 1270 MMIO_OUT32(VIA_REG_SRCBASE, 0); 1271 MMIO_OUT32(VIA_REG_DSTBASE, 0); 1272 MMIO_OUT32(VIA_REG_PITCH, VIA_PITCH_ENABLE | 1273 (((sc->sc_width * sc->sc_depth >> 3) >> 3) | 1274 (((sc->sc_width * sc->sc_depth >> 3) >> 3) << 16))); 1275 MMIO_OUT32(VIA_REG_SRCPOS, 0); 1276 MMIO_OUT32(VIA_REG_DSTPOS, (yd << 16) | xd); 1277 MMIO_OUT32(VIA_REG_DIMENSION, ((height - 1) << 16) | (width - 1)); 1278 MMIO_OUT32(VIA_REG_FGCOLOR, fg); 1279 MMIO_OUT32(VIA_REG_BGCOLOR, bg); 1280 MMIO_OUT32(VIA_REG_GECMD, 0xcc020142); 1281 1282 return; 1283 } 1284 1285 #if notyet 1286 static void 1287 uni_cursor_show(struct unichromefb_softc *sc) 1288 { 1289 uint32_t val; 1290 1291 val = MMIO_IN32(VIA_REG_CURSOR_MODE); 1292 val |= 1; 1293 MMIO_OUT32(VIA_REG_CURSOR_MODE, val); 1294 1295 return; 1296 } 1297 1298 static void 1299 uni_cursor_hide(struct unichromefb_softc *sc) 1300 { 1301 uint32_t val; 1302 1303 val = MMIO_IN32(VIA_REG_CURSOR_MODE); 1304 val &= 0xfffffffe; 1305 MMIO_OUT32(VIA_REG_CURSOR_MODE, val); 1306 1307 return; 1308 } 1309 #endif 1310 1311 /* 1312 * rasops glue 1313 */ 1314 static void 1315 uni_copycols(void *opaque, int row, int srccol, int dstcol, int ncols) 1316 { 1317 struct rasops_info *ri; 1318 struct vcons_screen *scr; 1319 struct unichromefb_softc *sc; 1320 int xs, xd, y, width, height; 1321 1322 ri = (struct rasops_info *)opaque; 1323 scr = (struct vcons_screen *)ri->ri_hw; 1324 sc = (struct unichromefb_softc *)scr->scr_cookie; 1325 1326 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1327 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1328 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1329 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1330 width = ri->ri_font->fontwidth * ncols; 1331 height = ri->ri_font->fontheight; 1332 uni_bitblit(sc, xs, y, xd, y, width, height); 1333 } 1334 1335 return; 1336 } 1337 1338 static void 1339 uni_copyrows(void *opaque, int srcrow, int dstrow, int nrows) 1340 { 1341 struct rasops_info *ri; 1342 struct vcons_screen *scr; 1343 struct unichromefb_softc *sc; 1344 int x, ys, yd, width, height; 1345 1346 ri = (struct rasops_info *)opaque; 1347 scr = (struct vcons_screen *)ri->ri_hw; 1348 sc = (struct unichromefb_softc *)scr->scr_cookie; 1349 1350 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1351 x = ri->ri_xorigin; 1352 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1353 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1354 width = ri->ri_emuwidth; 1355 height = ri->ri_font->fontheight * nrows; 1356 uni_bitblit(sc, x, ys, x, yd, width, height); 1357 } 1358 1359 return; 1360 } 1361 1362 static void 1363 uni_erasecols(void *opaque, int row, int startcol, int ncols, long fillattr) 1364 { 1365 struct rasops_info *ri; 1366 struct vcons_screen *scr; 1367 struct unichromefb_softc *sc; 1368 int x, y, width, height, fg, bg, ul; 1369 1370 ri = (struct rasops_info *)opaque; 1371 scr = (struct vcons_screen *)ri->ri_hw; 1372 sc = (struct unichromefb_softc *)scr->scr_cookie; 1373 1374 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1375 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1376 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1377 width = ri->ri_font->fontwidth * ncols; 1378 height = ri->ri_font->fontheight; 1379 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1380 uni_fillrect(sc, x, y, width, height, ri->ri_devcmap[bg]); 1381 } 1382 1383 return; 1384 } 1385 1386 static void 1387 uni_eraserows(void *opaque, int row, int nrows, long fillattr) 1388 { 1389 struct rasops_info *ri; 1390 struct vcons_screen *scr; 1391 struct unichromefb_softc *sc; 1392 int x, y, width, height, fg, bg, ul; 1393 1394 ri = (struct rasops_info *)opaque; 1395 scr = (struct vcons_screen *)ri->ri_hw; 1396 sc = (struct unichromefb_softc *)scr->scr_cookie; 1397 1398 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1399 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1400 if ((row == 0) && (nrows == ri->ri_rows)) { 1401 /* clear the whole screen */ 1402 uni_fillrect(sc, 0, 0, ri->ri_width, 1403 ri->ri_height, ri->ri_devcmap[bg]); 1404 } else { 1405 x = ri->ri_xorigin; 1406 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1407 width = ri->ri_emuwidth; 1408 height = ri->ri_font->fontheight * nrows; 1409 uni_fillrect(sc, x, y, width, height, 1410 ri->ri_devcmap[bg]); 1411 } 1412 } 1413 1414 return; 1415 } 1416 1417 static void 1418 uni_cursor(void *opaque, int on, int row, int col) 1419 { 1420 struct rasops_info *ri; 1421 struct vcons_screen *scr; 1422 struct unichromefb_softc *sc; 1423 int x, y, wi, he; 1424 1425 ri = (struct rasops_info *)opaque; 1426 scr = (struct vcons_screen *)ri->ri_hw; 1427 sc = (struct unichromefb_softc *)scr->scr_cookie; 1428 1429 uni_wait_idle(sc); 1430 1431 wi = ri->ri_font->fontwidth; 1432 he = ri->ri_font->fontheight; 1433 1434 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1435 x = ri->ri_ccol * wi + ri->ri_xorigin; 1436 y = ri->ri_crow * he + ri->ri_yorigin; 1437 if (ri->ri_flg & RI_CURSOR) { 1438 uni_rectinvert(sc, x, y, wi, he); 1439 ri->ri_flg &= ~RI_CURSOR; 1440 } 1441 ri->ri_crow = row; 1442 ri->ri_ccol = col; 1443 if (on) { 1444 x = ri->ri_ccol * wi + ri->ri_xorigin; 1445 y = ri->ri_crow * he + ri->ri_yorigin; 1446 uni_rectinvert(sc, x, y, wi, he); 1447 ri->ri_flg |= RI_CURSOR; 1448 } 1449 } else { 1450 ri->ri_flg &= ~RI_CURSOR; 1451 ri->ri_crow = row; 1452 ri->ri_ccol = col; 1453 } 1454 1455 return; 1456 } 1457 1458 static void 1459 uni_putchar(void *opaque, int row, int col, u_int c, long attr) 1460 { 1461 struct rasops_info *ri; 1462 struct vcons_screen *scr; 1463 struct unichromefb_softc *sc; 1464 1465 ri = (struct rasops_info *)opaque; 1466 scr = (struct vcons_screen *)ri->ri_hw; 1467 sc = (struct unichromefb_softc *)scr->scr_cookie; 1468 1469 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL) { 1470 uint32_t *data; 1471 int fg, bg, ul, uc, i; 1472 int x, y, wi, he; 1473 1474 wi = ri->ri_font->fontwidth; 1475 he = ri->ri_font->fontheight; 1476 1477 if (!CHAR_IN_FONT(c, ri->ri_font)) 1478 return; 1479 1480 rasops_unpack_attr(attr, &fg, &bg, &ul); 1481 x = ri->ri_xorigin + col * wi; 1482 y = ri->ri_yorigin + row * he; 1483 if (c == 0x20) 1484 uni_fillrect(sc, x, y, wi, he, ri->ri_devcmap[bg]); 1485 else { 1486 uc = c - ri->ri_font->firstchar; 1487 data = (uint32_t *)((uint8_t *)ri->ri_font->data + 1488 uc * ri->ri_fontscale); 1489 uni_setup_mono(sc, x, y, wi, he, 1490 ri->ri_devcmap[fg], ri->ri_devcmap[bg]); 1491 for (i = 0; i < (wi * he) / 4; i++) { 1492 MMIO_OUT32(VIA_MMIO_BLTBASE, *data); 1493 data++; 1494 } 1495 } 1496 } 1497 1498 return; 1499 } 1500