1 /* $NetBSD: machfb.c,v 1.91 2013/12/18 11:53:17 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Bang Jun-Young 5 * Copyright (c) 2005, 2006, 2007 Michael Lorenz 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * Some code is derived from ATI Rage Pro and Derivatives Programmer's Guide. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, 37 "$NetBSD: machfb.c,v 1.91 2013/12/18 11:53:17 macallan Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/device.h> 43 #include <sys/malloc.h> 44 #include <sys/callout.h> 45 #include <sys/lwp.h> 46 #include <sys/kauth.h> 47 48 #include <dev/videomode/videomode.h> 49 #include <dev/videomode/edidvar.h> 50 51 #include <dev/pci/pcivar.h> 52 #include <dev/pci/pcireg.h> 53 #include <dev/pci/pcidevs.h> 54 #include <dev/pci/pciio.h> 55 #include <dev/pci/machfbreg.h> 56 57 #include <dev/wscons/wsdisplayvar.h> 58 59 #include <dev/wscons/wsconsio.h> 60 #include <dev/wsfont/wsfont.h> 61 #include <dev/rasops/rasops.h> 62 #include <dev/pci/wsdisplay_pci.h> 63 64 #include <dev/wscons/wsdisplay_vconsvar.h> 65 #include <dev/wscons/wsdisplay_glyphcachevar.h> 66 67 #include "opt_wsemul.h" 68 #include "opt_machfb.h" 69 70 #define MACH64_REG_SIZE 0x800 71 #define MACH64_REG_OFF 0x7ff800 72 73 #define NBARS 3 /* number of Mach64 PCI BARs */ 74 75 struct vga_bar { 76 bus_addr_t vb_base; 77 bus_size_t vb_size; 78 pcireg_t vb_type; 79 int vb_flags; 80 }; 81 82 struct mach64_softc { 83 device_t sc_dev; 84 pci_chipset_tag_t sc_pc; 85 pcitag_t sc_pcitag; 86 87 struct vga_bar sc_bars[NBARS]; 88 struct vga_bar sc_rom; 89 90 #define sc_aperbase sc_bars[0].vb_base 91 #define sc_apersize sc_bars[0].vb_size 92 93 #define sc_iobase sc_bars[1].vb_base 94 #define sc_iosize sc_bars[1].vb_size 95 96 #define sc_regbase sc_bars[2].vb_base 97 #define sc_regsize sc_bars[2].vb_size 98 99 bus_space_tag_t sc_regt; 100 bus_space_tag_t sc_memt; 101 bus_space_tag_t sc_iot; 102 bus_space_handle_t sc_regh; 103 bus_space_handle_t sc_memh; 104 #if 0 105 void *sc_aperture; /* mapped aperture vaddr */ 106 void *sc_registers; /* mapped registers vaddr */ 107 #endif 108 uint32_t sc_nbus, sc_ndev, sc_nfunc; 109 size_t memsize; 110 int memtype; 111 112 int sc_mode; 113 int sc_bg; 114 int sc_locked; 115 116 int has_dsp; 117 int bits_per_pixel; 118 int max_x; 119 int max_y; 120 int virt_x; 121 int virt_y; 122 int color_depth; 123 124 int mem_freq; 125 int ramdac_freq; 126 int ref_freq; 127 128 int ref_div; 129 int log2_vclk_post_div; 130 int vclk_post_div; 131 int vclk_fb_div; 132 int mclk_post_div; 133 int mclk_fb_div; 134 int sc_clock; /* which clock to use */ 135 136 struct videomode *sc_my_mode; 137 int sc_edid_size; 138 uint8_t sc_edid_data[1024]; 139 140 u_char sc_cmap_red[256]; 141 u_char sc_cmap_green[256]; 142 u_char sc_cmap_blue[256]; 143 int sc_dacw, sc_blanked, sc_console; 144 struct vcons_data vd; 145 struct wsdisplay_accessops sc_accessops; 146 glyphcache sc_gc; 147 }; 148 149 struct mach64_crtcregs { 150 uint32_t h_total_disp; 151 uint32_t h_sync_strt_wid; 152 uint32_t v_total_disp; 153 uint32_t v_sync_strt_wid; 154 uint32_t gen_cntl; 155 uint32_t clock_cntl; 156 uint32_t color_depth; 157 uint32_t dot_clock; 158 }; 159 160 static struct { 161 uint16_t chip_id; 162 uint32_t ramdac_freq; 163 } const mach64_info[] = { 164 { PCI_PRODUCT_ATI_MACH64_GX, 135000 }, 165 { PCI_PRODUCT_ATI_MACH64_CX, 135000 }, 166 { PCI_PRODUCT_ATI_MACH64_CT, 135000 }, 167 { PCI_PRODUCT_ATI_RAGE_PRO_AGP, 230000 }, 168 { PCI_PRODUCT_ATI_RAGE_PRO_AGP1X, 230000 }, 169 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_B, 230000 }, 170 { PCI_PRODUCT_ATI_RAGE_XL_AGP, 230000 }, 171 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_P, 230000 }, 172 { PCI_PRODUCT_ATI_RAGE_PRO_PCI_L, 230000 }, 173 { PCI_PRODUCT_ATI_RAGE_XL_PCI, 230000 }, 174 { PCI_PRODUCT_ATI_RAGE_XL_PCI66, 230000 }, 175 { PCI_PRODUCT_ATI_RAGE_II, 135000 }, 176 { PCI_PRODUCT_ATI_RAGE_IIP, 200000 }, 177 { PCI_PRODUCT_ATI_RAGE_IIC_PCI, 230000 }, 178 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_B, 230000 }, 179 { PCI_PRODUCT_ATI_RAGE_IIC_AGP_P, 230000 }, 180 #if 0 181 { PCI_PRODUCT_ATI_RAGE_MOB_M3_PCI, 230000 }, 182 { PCI_PRODUCT_ATI_RAGE_MOB_M3_AGP, 230000 }, 183 { PCI_PRODUCT_ATI_RAGE_MOBILITY, 230000 }, 184 #endif 185 { PCI_PRODUCT_ATI_RAGE_L_MOB_M1_PCI, 230000 }, 186 { PCI_PRODUCT_ATI_RAGE_LT_PRO_AGP, 230000 }, 187 { PCI_PRODUCT_ATI_RAGE_LT_PRO, 230000 }, 188 { PCI_PRODUCT_ATI_RAGE_LT, 230000 }, 189 { PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI, 230000 }, 190 { PCI_PRODUCT_ATI_MACH64_VT, 170000 }, 191 { PCI_PRODUCT_ATI_MACH64_VTB, 200000 }, 192 { PCI_PRODUCT_ATI_MACH64_VT4, 230000 } 193 }; 194 195 static int mach64_chip_id, mach64_chip_rev; 196 static struct videomode default_mode = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; 197 198 static const char *mach64_gx_memtype_names[] = { 199 "DRAM", "VRAM", "VRAM", "DRAM", 200 "DRAM", "VRAM", "VRAM", "(unknown type)" 201 }; 202 203 static const char *mach64_memtype_names[] = { 204 "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM", 205 "(unknown type)" 206 }; 207 208 static struct videomode mach64_modes[] = { 209 /* 640x400 @ 70 Hz, 31.5 kHz */ 210 { 25175, 640, 664, 760, 800, 400, 409, 411, 450, 0, NULL, }, 211 /* 640x480 @ 72 Hz, 36.5 kHz */ 212 { 25175, 640, 664, 760, 800, 480, 491, 493, 525, 0, NULL, }, 213 /* 800x600 @ 72 Hz, 48.0 kHz */ 214 { 50000, 800, 856, 976, 1040, 600, 637, 643, 666, 215 VID_PHSYNC | VID_PVSYNC, NULL, }, 216 /* 1024x768 @ 70 Hz, 56.5 kHz */ 217 { 75000, 1024, 1048, 1184, 1328, 768, 771, 777, 806, 218 VID_NHSYNC | VID_NVSYNC, NULL, }, 219 /* 1152x864 @ 70 Hz, 62.4 kHz */ 220 { 92000, 1152, 1208, 1368, 1474, 864, 865, 875, 895, 0, NULL, }, 221 /* 1280x1024 @ 70 Hz, 74.59 kHz */ 222 { 126500, 1280, 1312, 1472, 1696, 1024, 1032, 1040, 1068, 223 VID_NHSYNC | VID_NVSYNC, NULL, } 224 }; 225 226 extern const u_char rasops_cmap[768]; 227 228 static int mach64_match(device_t, cfdata_t, void *); 229 static void mach64_attach(device_t, device_t, void *); 230 231 CFATTACH_DECL_NEW(machfb, sizeof(struct mach64_softc), mach64_match, mach64_attach, 232 NULL, NULL); 233 234 static void mach64_init(struct mach64_softc *); 235 static int mach64_get_memsize(struct mach64_softc *); 236 static int mach64_get_max_ramdac(struct mach64_softc *); 237 238 #if defined(__sparc__) || defined(__powerpc__) 239 static void mach64_get_mode(struct mach64_softc *, struct videomode *); 240 #endif 241 242 static int mach64_calc_crtcregs(struct mach64_softc *, 243 struct mach64_crtcregs *, 244 struct videomode *); 245 static void mach64_set_crtcregs(struct mach64_softc *, 246 struct mach64_crtcregs *); 247 248 static int mach64_modeswitch(struct mach64_softc *, struct videomode *); 249 static void mach64_set_dsp(struct mach64_softc *); 250 static void mach64_set_pll(struct mach64_softc *, int); 251 static void mach64_reset_engine(struct mach64_softc *); 252 static void mach64_init_engine(struct mach64_softc *); 253 #if 0 254 static void mach64_adjust_frame(struct mach64_softc *, int, int); 255 #endif 256 static void mach64_init_lut(struct mach64_softc *); 257 258 static void mach64_init_screen(void *, struct vcons_screen *, int, long *); 259 static int mach64_set_screentype(struct mach64_softc *, 260 const struct wsscreen_descr *); 261 static int mach64_is_console(struct mach64_softc *); 262 263 static void mach64_cursor(void *, int, int, int); 264 #if 0 265 static int mach64_mapchar(void *, int, u_int *); 266 #endif 267 static void mach64_putchar_mono(void *, int, int, u_int, long); 268 static void mach64_putchar_aa8(void *, int, int, u_int, long); 269 static void mach64_copycols(void *, int, int, int, int); 270 static void mach64_erasecols(void *, int, int, int, long); 271 static void mach64_copyrows(void *, int, int, int); 272 static void mach64_eraserows(void *, int, int, long); 273 static void mach64_clearscreen(struct mach64_softc *); 274 275 static int mach64_putcmap(struct mach64_softc *, struct wsdisplay_cmap *); 276 static int mach64_getcmap(struct mach64_softc *, struct wsdisplay_cmap *); 277 static int mach64_putpalreg(struct mach64_softc *, uint8_t, uint8_t, 278 uint8_t, uint8_t); 279 static void mach64_bitblt(void *, int, int, int, int, int, int, int); 280 static void mach64_rectfill(struct mach64_softc *, int, int, int, int, int); 281 static void mach64_setup_mono(struct mach64_softc *, int, int, int, int, 282 uint32_t, uint32_t); 283 static void mach64_feed_bytes(struct mach64_softc *, int, uint8_t *); 284 #if 0 285 static void mach64_showpal(struct mach64_softc *); 286 #endif 287 288 static void machfb_blank(struct mach64_softc *, int); 289 static int machfb_drm_print(void *, const char *); 290 291 static struct wsscreen_descr mach64_defaultscreen = { 292 "default", 293 80, 30, 294 NULL, 295 8, 16, 296 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 297 &default_mode 298 }, mach64_80x25_screen = { 299 "80x25", 80, 25, 300 NULL, 301 8, 16, 302 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 303 &mach64_modes[0] 304 }, mach64_80x30_screen = { 305 "80x30", 80, 30, 306 NULL, 307 8, 16, 308 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 309 &mach64_modes[1] 310 }, mach64_80x40_screen = { 311 "80x40", 80, 40, 312 NULL, 313 8, 10, 314 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 315 &mach64_modes[0] 316 }, mach64_80x50_screen = { 317 "80x50", 80, 50, 318 NULL, 319 8, 8, 320 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 321 &mach64_modes[0] 322 }, mach64_100x37_screen = { 323 "100x37", 100, 37, 324 NULL, 325 8, 16, 326 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 327 &mach64_modes[2] 328 }, mach64_128x48_screen = { 329 "128x48", 128, 48, 330 NULL, 331 8, 16, 332 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 333 &mach64_modes[3] 334 }, mach64_144x54_screen = { 335 "144x54", 144, 54, 336 NULL, 337 8, 16, 338 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 339 &mach64_modes[4] 340 }, mach64_160x64_screen = { 341 "160x54", 160, 64, 342 NULL, 343 8, 16, 344 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 345 &mach64_modes[5] 346 }; 347 348 static const struct wsscreen_descr *_mach64_scrlist[] = { 349 &mach64_defaultscreen, 350 &mach64_80x25_screen, 351 &mach64_80x30_screen, 352 &mach64_80x40_screen, 353 &mach64_80x50_screen, 354 &mach64_100x37_screen, 355 &mach64_128x48_screen, 356 &mach64_144x54_screen, 357 &mach64_160x64_screen 358 }; 359 360 static struct wsscreen_list mach64_screenlist = { 361 __arraycount(_mach64_scrlist), 362 _mach64_scrlist 363 }; 364 365 static int mach64_ioctl(void *, void *, u_long, void *, int, 366 struct lwp *); 367 static paddr_t mach64_mmap(void *, void *, off_t, int); 368 369 #if 0 370 static int mach64_load_font(void *, void *, struct wsdisplay_font *); 371 #endif 372 373 374 static struct vcons_screen mach64_console_screen; 375 376 /* 377 * Inline functions for getting access to register aperture. 378 */ 379 380 static inline uint32_t 381 regr(struct mach64_softc *sc, uint32_t index) 382 { 383 return bus_space_read_4(sc->sc_regt, sc->sc_regh, index + 0x400); 384 } 385 386 static inline uint8_t 387 regrb(struct mach64_softc *sc, uint32_t index) 388 { 389 return bus_space_read_1(sc->sc_regt, sc->sc_regh, index + 0x400); 390 } 391 392 static inline void 393 regw(struct mach64_softc *sc, uint32_t index, uint32_t data) 394 { 395 bus_space_write_4(sc->sc_regt, sc->sc_regh, index + 0x400, data); 396 bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4, 397 BUS_SPACE_BARRIER_WRITE); 398 } 399 400 static inline void 401 regws(struct mach64_softc *sc, uint32_t index, uint32_t data) 402 { 403 bus_space_write_stream_4(sc->sc_regt, sc->sc_regh, index + 0x400, data); 404 bus_space_barrier(sc->sc_regt, sc->sc_regh, index + 0x400, 4, 405 BUS_SPACE_BARRIER_WRITE); 406 } 407 408 static inline void 409 regwb(struct mach64_softc *sc, uint32_t index, uint8_t data) 410 { 411 bus_space_write_1(sc->sc_regt, sc->sc_regh, index + 0x400, data); 412 bus_space_barrier(sc->sc_regt, sc->sc_regh, index + 0x400, 1, 413 BUS_SPACE_BARRIER_WRITE); 414 } 415 416 static inline void 417 regwb_pll(struct mach64_softc *sc, uint32_t index, uint8_t data) 418 { 419 uint32_t reg; 420 421 reg = regr(sc, CLOCK_CNTL); 422 reg |= PLL_WR_EN; 423 regw(sc, CLOCK_CNTL, reg); 424 reg &= ~(PLL_ADDR | PLL_DATA); 425 reg |= (index & 0x3f) << PLL_ADDR_SHIFT; 426 reg |= data << PLL_DATA_SHIFT; 427 reg |= CLOCK_STROBE; 428 regw(sc, CLOCK_CNTL, reg); 429 reg &= ~PLL_WR_EN; 430 regw(sc, CLOCK_CNTL, reg); 431 } 432 433 static inline uint8_t 434 regrb_pll(struct mach64_softc *sc, uint32_t index) 435 { 436 437 regwb(sc, CLOCK_CNTL + 1, index << 2); 438 return regrb(sc, CLOCK_CNTL + 2); 439 } 440 441 static inline void 442 wait_for_fifo(struct mach64_softc *sc, uint8_t v) 443 { 444 while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v)) 445 continue; 446 } 447 448 static inline void 449 wait_for_idle(struct mach64_softc *sc) 450 { 451 wait_for_fifo(sc, 16); 452 while ((regr(sc, GUI_STAT) & 1) != 0) 453 continue; 454 } 455 456 static int 457 mach64_match(device_t parent, cfdata_t match, void *aux) 458 { 459 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 460 int i; 461 462 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY || 463 PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA) 464 return 0; 465 466 for (i = 0; i < __arraycount(mach64_info); i++) 467 if (PCI_PRODUCT(pa->pa_id) == mach64_info[i].chip_id) { 468 mach64_chip_id = PCI_PRODUCT(pa->pa_id); 469 mach64_chip_rev = PCI_REVISION(pa->pa_class); 470 return 100; 471 } 472 473 return 0; 474 } 475 476 static void 477 mach64_attach(device_t parent, device_t self, void *aux) 478 { 479 struct mach64_softc *sc = device_private(self); 480 struct pci_attach_args *pa = aux; 481 struct rasops_info *ri; 482 prop_data_t edid_data; 483 #if defined(__sparc__) || defined(__powerpc__) 484 const struct videomode *mode = NULL; 485 #endif 486 int bar, id, expected_id; 487 int is_gx; 488 const char **memtype_names; 489 struct wsemuldisplaydev_attach_args aa; 490 long defattr; 491 int setmode, width, height; 492 pcireg_t screg; 493 uint32_t reg; 494 const pcireg_t enables = PCI_COMMAND_MEM_ENABLE; 495 int use_mmio = FALSE; 496 497 sc->sc_dev = self; 498 sc->sc_pc = pa->pa_pc; 499 sc->sc_pcitag = pa->pa_tag; 500 sc->sc_dacw = -1; 501 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 502 sc->sc_nbus = pa->pa_bus; 503 sc->sc_ndev = pa->pa_device; 504 sc->sc_nfunc = pa->pa_function; 505 sc->sc_locked = 0; 506 sc->sc_iot = pa->pa_iot; 507 sc->sc_accessops.ioctl = mach64_ioctl; 508 sc->sc_accessops.mmap = mach64_mmap; 509 510 pci_aprint_devinfo(pa, "Graphics processor"); 511 #ifdef MACHFB_DEBUG 512 printf(prop_dictionary_externalize(device_properties(self))); 513 #endif 514 515 /* enable memory access */ 516 screg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); 517 if ((screg & enables) != enables) { 518 screg |= enables; 519 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 520 PCI_COMMAND_STATUS_REG, screg); 521 } 522 for (bar = 0; bar < NBARS; bar++) { 523 reg = PCI_MAPREG_START + (bar * 4); 524 sc->sc_bars[bar].vb_type = pci_mapreg_type(sc->sc_pc, 525 sc->sc_pcitag, reg); 526 (void)pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, reg, 527 sc->sc_bars[bar].vb_type, &sc->sc_bars[bar].vb_base, 528 &sc->sc_bars[bar].vb_size, &sc->sc_bars[bar].vb_flags); 529 } 530 aprint_debug_dev(sc->sc_dev, "aperture size %08x\n", 531 (uint32_t)sc->sc_apersize); 532 533 sc->sc_rom.vb_type = PCI_MAPREG_TYPE_ROM; 534 pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, PCI_MAPREG_ROM, 535 sc->sc_rom.vb_type, &sc->sc_rom.vb_base, 536 &sc->sc_rom.vb_size, &sc->sc_rom.vb_flags); 537 sc->sc_memt = pa->pa_memt; 538 539 /* use MMIO register aperture if available */ 540 if ((sc->sc_regbase != 0) && (sc->sc_regbase != 0xffffffff)) { 541 if (pci_mapreg_map(pa, MACH64_BAR_MMIO, PCI_MAPREG_TYPE_MEM, 0, 542 &sc->sc_regt, &sc->sc_regh, &sc->sc_regbase, 543 &sc->sc_regsize) == 0) { 544 545 /* 546 * the MMIO aperture maps both 1KB register blocks, but 547 * all register offsets are relative to the 2nd one so 548 * for now fix this up in MACH64_REG_OFF and the access 549 * functions 550 */ 551 aprint_normal_dev(sc->sc_dev, "using MMIO aperture\n"); 552 use_mmio = TRUE; 553 } 554 } 555 if (!use_mmio) { 556 if (bus_space_map(sc->sc_memt, sc->sc_aperbase, sc->sc_apersize, 557 BUS_SPACE_MAP_LINEAR, &sc->sc_memh)) { 558 panic("%s: failed to map aperture", 559 device_xname(sc->sc_dev)); 560 } 561 562 sc->sc_regt = sc->sc_memt; 563 bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF, 564 MACH64_REG_SIZE, &sc->sc_regh); 565 } 566 567 mach64_init(sc); 568 569 aprint_normal_dev(sc->sc_dev, 570 "%d MB aperture at 0x%08x, %d KB registers at 0x%08x\n", 571 (u_int)(sc->sc_apersize / (1024 * 1024)), 572 (u_int)sc->sc_aperbase, (u_int)(sc->sc_regsize / 1024), 573 (u_int)sc->sc_regbase); 574 575 printf("%s: %d KB ROM at 0x%08x\n", device_xname(sc->sc_dev), 576 (int)sc->sc_rom.vb_size >> 10, (uint32_t)sc->sc_rom.vb_base); 577 578 prop_dictionary_get_uint32(device_properties(self), "width", &width); 579 prop_dictionary_get_uint32(device_properties(self), "height", &height); 580 581 if ((edid_data = prop_dictionary_get(device_properties(self), "EDID")) 582 != NULL) { 583 struct edid_info ei; 584 585 sc->sc_edid_size = min(1024, prop_data_size(edid_data)); 586 memset(sc->sc_edid_data, 0, sizeof(sc->sc_edid_data)); 587 memcpy(sc->sc_edid_data, prop_data_data_nocopy(edid_data), 588 sc->sc_edid_size); 589 590 edid_parse(sc->sc_edid_data, &ei); 591 592 #ifdef MACHFB_DEBUG 593 edid_print(&ei); 594 #endif 595 } 596 597 is_gx = 0; 598 switch(mach64_chip_id) { 599 case PCI_PRODUCT_ATI_MACH64_GX: 600 case PCI_PRODUCT_ATI_MACH64_CX: 601 is_gx = 1; 602 case PCI_PRODUCT_ATI_MACH64_CT: 603 sc->has_dsp = 0; 604 break; 605 case PCI_PRODUCT_ATI_MACH64_VT: 606 case PCI_PRODUCT_ATI_RAGE_II: 607 if((mach64_chip_rev & 0x07) == 0) { 608 sc->has_dsp = 0; 609 break; 610 } 611 /* Otherwise fall through. */ 612 default: 613 sc->has_dsp = 1; 614 } 615 616 memtype_names = is_gx ? mach64_gx_memtype_names : mach64_memtype_names; 617 618 sc->memsize = mach64_get_memsize(sc); 619 620 if(is_gx) 621 sc->memtype = (regr(sc, CONFIG_STAT0) >> 3) & 0x07; 622 else 623 sc->memtype = regr(sc, CONFIG_STAT0) & 0x07; 624 625 /* 626 * XXX is there any way to calculate reference frequency from 627 * known values? 628 */ 629 if ((mach64_chip_id == PCI_PRODUCT_ATI_RAGE_XL_PCI) || 630 ((mach64_chip_id >= PCI_PRODUCT_ATI_RAGE_LT_PRO_PCI) && 631 (mach64_chip_id <= PCI_PRODUCT_ATI_RAGE_LT_PRO))) { 632 aprint_normal_dev(sc->sc_dev, "ref_freq=29.498MHz\n"); 633 sc->ref_freq = 29498; 634 } else 635 sc->ref_freq = 14318; 636 637 reg = regr(sc, CLOCK_CNTL); 638 aprint_debug("CLOCK_CNTL: %08x\n", reg); 639 sc->sc_clock = reg & 3; 640 aprint_debug("using clock %d\n", sc->sc_clock); 641 642 sc->ref_div = regrb_pll(sc, PLL_REF_DIV); 643 aprint_debug("ref_div: %d\n", sc->ref_div); 644 sc->mclk_fb_div = regrb_pll(sc, MCLK_FB_DIV); 645 aprint_debug("mclk_fb_div: %d\n", sc->mclk_fb_div); 646 sc->mem_freq = (2 * sc->ref_freq * sc->mclk_fb_div) / 647 (sc->ref_div * 2); 648 sc->mclk_post_div = (sc->mclk_fb_div * 2 * sc->ref_freq) / 649 (sc->mem_freq * sc->ref_div); 650 sc->ramdac_freq = mach64_get_max_ramdac(sc); 651 aprint_normal_dev(sc->sc_dev, 652 "%ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz\n", 653 (u_long)sc->memsize, 654 memtype_names[sc->memtype], 655 sc->mem_freq / 1000, sc->mem_freq % 1000, 656 sc->ramdac_freq / 1000); 657 658 id = regr(sc, CONFIG_CHIP_ID) & 0xffff; 659 switch(mach64_chip_id) { 660 case PCI_PRODUCT_ATI_MACH64_GX: 661 expected_id = 0x00d7; 662 break; 663 case PCI_PRODUCT_ATI_MACH64_CX: 664 expected_id = 0x0057; 665 break; 666 default: 667 /* Most chip IDs match their PCI product ID. */ 668 expected_id = mach64_chip_id; 669 } 670 671 if (id != expected_id) { 672 aprint_error_dev(sc->sc_dev, 673 "chip ID mismatch, 0x%x != 0x%x\n", id, expected_id); 674 return; 675 } 676 677 sc->sc_console = mach64_is_console(sc); 678 aprint_debug("gen_cntl: %08x\n", regr(sc, CRTC_GEN_CNTL)); 679 #if defined(__sparc__) || defined(__powerpc__) 680 if (sc->sc_console) { 681 if (mode != NULL) { 682 memcpy(&default_mode, mode, sizeof(struct videomode)); 683 setmode = 1; 684 } else { 685 mach64_get_mode(sc, &default_mode); 686 setmode = 0; 687 } 688 sc->sc_my_mode = &default_mode; 689 } else { 690 /* fill in default_mode if it's empty */ 691 mach64_get_mode(sc, &default_mode); 692 if (default_mode.dot_clock == 0) { 693 memcpy(&default_mode, &mach64_modes[4], 694 sizeof(default_mode)); 695 } 696 sc->sc_my_mode = &default_mode; 697 setmode = 1; 698 } 699 #else 700 if (default_mode.dot_clock == 0) { 701 memcpy(&default_mode, &mach64_modes[0], 702 sizeof(default_mode)); 703 } 704 sc->sc_my_mode = &mach64_modes[0]; 705 setmode = 1; 706 #endif 707 708 sc->bits_per_pixel = 8; 709 sc->virt_x = sc->sc_my_mode->hdisplay; 710 sc->virt_y = sc->sc_my_mode->vdisplay; 711 sc->max_x = sc->virt_x - 1; 712 sc->max_y = (sc->memsize * 1024) / 713 (sc->virt_x * (sc->bits_per_pixel / 8)) - 1; 714 715 sc->color_depth = CRTC_PIX_WIDTH_8BPP; 716 717 mach64_init_engine(sc); 718 719 if (setmode) 720 mach64_modeswitch(sc, sc->sc_my_mode); 721 722 aprint_normal_dev(sc->sc_dev, 723 "initial resolution %dx%d at %d bpp\n", 724 sc->sc_my_mode->hdisplay, sc->sc_my_mode->vdisplay, 725 sc->bits_per_pixel); 726 727 wsfont_init(); 728 729 vcons_init(&sc->vd, sc, &mach64_defaultscreen, &sc->sc_accessops); 730 sc->vd.init_screen = mach64_init_screen; 731 732 sc->sc_gc.gc_bitblt = mach64_bitblt; 733 sc->sc_gc.gc_blitcookie = sc; 734 sc->sc_gc.gc_rop = MIX_SRC; 735 736 ri = &mach64_console_screen.scr_ri; 737 if (sc->sc_console) { 738 739 vcons_init_screen(&sc->vd, &mach64_console_screen, 1, 740 &defattr); 741 mach64_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 742 743 mach64_defaultscreen.textops = &ri->ri_ops; 744 mach64_defaultscreen.capabilities = ri->ri_caps; 745 mach64_defaultscreen.nrows = ri->ri_rows; 746 mach64_defaultscreen.ncols = ri->ri_cols; 747 glyphcache_init(&sc->sc_gc, sc->sc_my_mode->vdisplay + 5, 748 ((sc->memsize * 1024) / sc->sc_my_mode->hdisplay) - 749 sc->sc_my_mode->vdisplay - 5, 750 sc->sc_my_mode->hdisplay, 751 ri->ri_font->fontwidth, 752 ri->ri_font->fontheight, 753 defattr); 754 wsdisplay_cnattach(&mach64_defaultscreen, ri, 0, 0, defattr); 755 } else { 756 /* 757 * since we're not the console we can postpone the rest 758 * until someone actually allocates a screen for us 759 */ 760 mach64_modeswitch(sc, sc->sc_my_mode); 761 if (mach64_console_screen.scr_ri.ri_rows == 0) { 762 /* do some minimal setup to avoid weirdnesses later */ 763 vcons_init_screen(&sc->vd, &mach64_console_screen, 1, 764 &defattr); 765 } else 766 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 767 768 glyphcache_init(&sc->sc_gc, sc->sc_my_mode->vdisplay + 5, 769 ((sc->memsize * 1024) / sc->sc_my_mode->hdisplay) - 770 sc->sc_my_mode->vdisplay - 5, 771 sc->sc_my_mode->hdisplay, 772 ri->ri_font->fontwidth, 773 ri->ri_font->fontheight, 774 defattr); 775 } 776 777 sc->sc_bg = mach64_console_screen.scr_ri.ri_devcmap[WS_DEFAULT_BG]; 778 mach64_clearscreen(sc); 779 mach64_init_lut(sc); 780 781 if (sc->sc_console) 782 vcons_replay_msgbuf(&mach64_console_screen); 783 784 machfb_blank(sc, 0); /* unblank the screen */ 785 786 aa.console = sc->sc_console; 787 aa.scrdata = &mach64_screenlist; 788 aa.accessops = &sc->sc_accessops; 789 aa.accesscookie = &sc->vd; 790 791 config_found(self, &aa, wsemuldisplaydevprint); 792 #if 0 793 /* XXX 794 * turns out some firmware doesn't turn these back on when needed 795 * so we need to turn them off only when mapping vram in 796 * WSDISPLAYIO_MODE_DUMB would overlap ( unlikely but far from 797 * impossible ) 798 */ 799 if (use_mmio) { 800 /* 801 * Now that we took over, turn off the aperture registers if we 802 * don't use them. Can't do this earlier since on some hardware 803 * we use firmware calls as early console output which may in 804 * turn try to access these registers. 805 */ 806 reg = regr(sc, BUS_CNTL); 807 aprint_debug_dev(sc->sc_dev, "BUS_CNTL: %08x\n", reg); 808 reg |= BUS_APER_REG_DIS; 809 regw(sc, BUS_CNTL, reg); 810 } 811 #endif 812 config_found_ia(self, "drm", aux, machfb_drm_print); 813 } 814 815 static int 816 machfb_drm_print(void *aux, const char *pnp) 817 { 818 if (pnp) 819 aprint_normal("direct rendering for %s", pnp); 820 return (UNSUPP); 821 } 822 823 static void 824 mach64_init_screen(void *cookie, struct vcons_screen *scr, int existing, 825 long *defattr) 826 { 827 struct mach64_softc *sc = cookie; 828 struct rasops_info *ri = &scr->scr_ri; 829 830 /* XXX for now */ 831 #define setmode 0 832 833 ri->ri_depth = sc->bits_per_pixel; 834 ri->ri_width = sc->sc_my_mode->hdisplay; 835 ri->ri_height = sc->sc_my_mode->vdisplay; 836 ri->ri_stride = ri->ri_width; 837 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 838 if (ri->ri_depth == 8) 839 ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA; 840 841 #ifdef VCONS_DRAW_INTR 842 scr->scr_flags |= VCONS_DONT_READ; 843 #endif 844 845 if (existing) { 846 if (setmode && mach64_set_screentype(sc, scr->scr_type)) { 847 panic("%s: failed to switch video mode", 848 device_xname(sc->sc_dev)); 849 } 850 } 851 852 rasops_init(ri, 0, 0); 853 ri->ri_caps = WSSCREEN_WSCOLORS; 854 rasops_reconfig(ri, sc->sc_my_mode->vdisplay / ri->ri_font->fontheight, 855 sc->sc_my_mode->hdisplay / ri->ri_font->fontwidth); 856 857 /* enable acceleration */ 858 ri->ri_hw = scr; 859 ri->ri_ops.copyrows = mach64_copyrows; 860 ri->ri_ops.copycols = mach64_copycols; 861 ri->ri_ops.eraserows = mach64_eraserows; 862 ri->ri_ops.erasecols = mach64_erasecols; 863 ri->ri_ops.cursor = mach64_cursor; 864 if (FONT_IS_ALPHA(ri->ri_font)) { 865 ri->ri_ops.putchar = mach64_putchar_aa8; 866 } else 867 ri->ri_ops.putchar = mach64_putchar_mono; 868 } 869 870 static void 871 mach64_init(struct mach64_softc *sc) 872 { 873 sc->sc_blanked = 0; 874 } 875 876 static int 877 mach64_get_memsize(struct mach64_softc *sc) 878 { 879 int tmp, memsize; 880 int mem_tab[] = { 881 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384 882 }; 883 tmp = regr(sc, MEM_CNTL); 884 #ifdef DIAGNOSTIC 885 aprint_debug_dev(sc->sc_dev, "memctl %08x\n", tmp); 886 #endif 887 if (sc->has_dsp) { 888 tmp &= 0x0000000f; 889 if (tmp < 8) 890 memsize = (tmp + 1) * 512; 891 else if (tmp < 12) 892 memsize = (tmp - 3) * 1024; 893 else 894 memsize = (tmp - 7) * 2048; 895 } else { 896 memsize = mem_tab[tmp & 0x07]; 897 } 898 899 return memsize; 900 } 901 902 static int 903 mach64_get_max_ramdac(struct mach64_softc *sc) 904 { 905 int i; 906 907 if ((mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT || 908 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II) && 909 (mach64_chip_rev & 0x07)) 910 return 170000; 911 912 for (i = 0; i < __arraycount(mach64_info); i++) 913 if (mach64_chip_id == mach64_info[i].chip_id) 914 return mach64_info[i].ramdac_freq; 915 916 if (sc->bits_per_pixel == 8) 917 return 135000; 918 else 919 return 80000; 920 } 921 922 #if defined(__sparc__) || defined(__powerpc__) 923 static void 924 mach64_get_mode(struct mach64_softc *sc, struct videomode *mode) 925 { 926 struct mach64_crtcregs crtc; 927 928 crtc.h_total_disp = regr(sc, CRTC_H_TOTAL_DISP); 929 crtc.h_sync_strt_wid = regr(sc, CRTC_H_SYNC_STRT_WID); 930 crtc.v_total_disp = regr(sc, CRTC_V_TOTAL_DISP); 931 crtc.v_sync_strt_wid = regr(sc, CRTC_V_SYNC_STRT_WID); 932 933 mode->htotal = ((crtc.h_total_disp & 0xffff) + 1) << 3; 934 mode->hdisplay = ((crtc.h_total_disp >> 16) + 1) << 3; 935 mode->hsync_start = ((crtc.h_sync_strt_wid & 0xffff) + 1) << 3; 936 mode->hsync_end = ((crtc.h_sync_strt_wid >> 16) << 3) + 937 mode->hsync_start; 938 mode->vtotal = (crtc.v_total_disp & 0xffff) + 1; 939 mode->vdisplay = (crtc.v_total_disp >> 16) + 1; 940 mode->vsync_start = (crtc.v_sync_strt_wid & 0xffff) + 1; 941 mode->vsync_end = (crtc.v_sync_strt_wid >> 16) + mode->vsync_start; 942 943 #ifdef MACHFB_DEBUG 944 printf("mach64_get_mode: %d %d %d %d %d %d %d %d\n", 945 mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, 946 mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal); 947 #endif 948 } 949 #endif 950 951 static int 952 mach64_calc_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc, 953 struct videomode *mode) 954 { 955 956 if (mode->dot_clock > sc->ramdac_freq) 957 /* Clock too high. */ 958 return 1; 959 960 crtc->h_total_disp = (((mode->hdisplay >> 3) - 1) << 16) | 961 ((mode->htotal >> 3) - 1); 962 crtc->h_sync_strt_wid = 963 (((mode->hsync_end - mode->hsync_start) >> 3) << 16) | 964 ((mode->hsync_start >> 3) - 1); 965 966 crtc->v_total_disp = ((mode->vdisplay - 1) << 16) | 967 (mode->vtotal - 1); 968 crtc->v_sync_strt_wid = 969 ((mode->vsync_end - mode->vsync_start) << 16) | 970 (mode->vsync_start - 1); 971 972 if (mode->flags & VID_NVSYNC) 973 crtc->v_sync_strt_wid |= CRTC_VSYNC_NEG; 974 975 switch (sc->bits_per_pixel) { 976 case 8: 977 crtc->color_depth = CRTC_PIX_WIDTH_8BPP; 978 break; 979 case 16: 980 crtc->color_depth = CRTC_PIX_WIDTH_16BPP; 981 break; 982 case 32: 983 crtc->color_depth = CRTC_PIX_WIDTH_32BPP; 984 break; 985 } 986 987 crtc->gen_cntl = 0; 988 if (mode->flags & VID_INTERLACE) 989 crtc->gen_cntl |= CRTC_INTERLACE_EN; 990 991 if (mode->flags & VID_CSYNC) 992 crtc->gen_cntl |= CRTC_CSYNC_EN; 993 994 crtc->dot_clock = mode->dot_clock; 995 996 return 0; 997 } 998 999 static void 1000 mach64_set_crtcregs(struct mach64_softc *sc, struct mach64_crtcregs *crtc) 1001 { 1002 1003 mach64_set_pll(sc, crtc->dot_clock); 1004 1005 if (sc->has_dsp) 1006 mach64_set_dsp(sc); 1007 1008 regw(sc, CRTC_H_TOTAL_DISP, crtc->h_total_disp); 1009 regw(sc, CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid); 1010 regw(sc, CRTC_V_TOTAL_DISP, crtc->v_total_disp); 1011 regw(sc, CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid); 1012 1013 regw(sc, CRTC_VLINE_CRNT_VLINE, 0); 1014 1015 regw(sc, CRTC_OFF_PITCH, (sc->virt_x >> 3) << 22); 1016 1017 regw(sc, CRTC_GEN_CNTL, crtc->gen_cntl | crtc->color_depth | 1018 /* XXX this unconditionally enables composite sync on SPARC */ 1019 #ifdef __sparc__ 1020 CRTC_CSYNC_EN | 1021 #endif 1022 CRTC_EXT_DISP_EN | CRTC_EXT_EN); 1023 } 1024 1025 static int 1026 mach64_modeswitch(struct mach64_softc *sc, struct videomode *mode) 1027 { 1028 struct mach64_crtcregs crtc; 1029 1030 memset(&crtc, 0, sizeof crtc); /* XXX gcc */ 1031 1032 if (mach64_calc_crtcregs(sc, &crtc, mode)) 1033 return 1; 1034 aprint_debug("crtc dot clock: %d\n", crtc.dot_clock); 1035 if (crtc.dot_clock == 0) { 1036 aprint_error("%s: preposterous dot clock (%d)\n", 1037 device_xname(sc->sc_dev), crtc.dot_clock); 1038 return 1; 1039 } 1040 mach64_set_crtcregs(sc, &crtc); 1041 return 0; 1042 } 1043 1044 static void 1045 mach64_reset_engine(struct mach64_softc *sc) 1046 { 1047 1048 /* Reset engine.*/ 1049 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE); 1050 1051 /* Enable engine. */ 1052 regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE); 1053 1054 /* Ensure engine is not locked up by clearing any FIFO or 1055 host errors. */ 1056 regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK | 1057 BUS_FIFO_ERR_ACK); 1058 } 1059 1060 static void 1061 mach64_init_engine(struct mach64_softc *sc) 1062 { 1063 uint32_t pitch_value; 1064 1065 pitch_value = sc->virt_x; 1066 1067 if (sc->bits_per_pixel == 24) 1068 pitch_value *= 3; 1069 1070 mach64_reset_engine(sc); 1071 1072 wait_for_fifo(sc, 14); 1073 1074 regw(sc, CONTEXT_MASK, 0xffffffff); 1075 1076 regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22); 1077 1078 /* make sure the visible area starts where we're going to draw */ 1079 regw(sc, CRTC_OFF_PITCH, (sc->virt_x >> 3) << 22); 1080 1081 regw(sc, DST_Y_X, 0); 1082 regw(sc, DST_HEIGHT, 0); 1083 regw(sc, DST_BRES_ERR, 0); 1084 regw(sc, DST_BRES_INC, 0); 1085 regw(sc, DST_BRES_DEC, 0); 1086 1087 regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT | 1088 DST_Y_TOP_TO_BOTTOM); 1089 1090 regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22); 1091 1092 regw(sc, SRC_Y_X, 0); 1093 regw(sc, SRC_HEIGHT1_WIDTH1, 1); 1094 regw(sc, SRC_Y_X_START, 0); 1095 regw(sc, SRC_HEIGHT2_WIDTH2, 1); 1096 1097 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1098 1099 wait_for_fifo(sc, 13); 1100 regw(sc, HOST_CNTL, 0); 1101 1102 regw(sc, PAT_REG0, 0); 1103 regw(sc, PAT_REG1, 0); 1104 regw(sc, PAT_CNTL, 0); 1105 1106 regw(sc, SC_LEFT, 0); 1107 regw(sc, SC_TOP, 0); 1108 regw(sc, SC_BOTTOM, 0x3fff); 1109 regw(sc, SC_RIGHT, pitch_value - 1); 1110 1111 regw(sc, DP_BKGD_CLR, WS_DEFAULT_BG); 1112 regw(sc, DP_FRGD_CLR, WS_DEFAULT_FG); 1113 regw(sc, DP_WRITE_MASK, 0xffffffff); 1114 regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST); 1115 1116 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 1117 1118 wait_for_fifo(sc, 3); 1119 regw(sc, CLR_CMP_CLR, 0); 1120 regw(sc, CLR_CMP_MASK, 0xffffffff); 1121 regw(sc, CLR_CMP_CNTL, 0); 1122 1123 wait_for_fifo(sc, 3); 1124 switch (sc->bits_per_pixel) { 1125 case 8: 1126 regw(sc, DP_PIX_WIDTH, HOST_1BPP | SRC_8BPP | DST_8BPP); 1127 regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP); 1128 /* We want 8 bit per channel */ 1129 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1130 break; 1131 case 32: 1132 regw(sc, DP_PIX_WIDTH, HOST_1BPP | SRC_32BPP | DST_32BPP); 1133 regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP); 1134 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN); 1135 break; 1136 } 1137 regw(sc, DP_WRITE_MASK, 0xff); 1138 1139 wait_for_fifo(sc, 5); 1140 regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20); 1141 regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 1142 1143 wait_for_idle(sc); 1144 } 1145 1146 #if 0 1147 static void 1148 mach64_adjust_frame(struct mach64_softc *sc, int x, int y) 1149 { 1150 int offset; 1151 1152 offset = ((x + y * sc->virt_x) * (sc->bits_per_pixel >> 3)) >> 3; 1153 1154 regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) | 1155 offset); 1156 } 1157 #endif 1158 1159 static void 1160 mach64_set_dsp(struct mach64_softc *sc) 1161 { 1162 uint32_t fifo_depth, page_size, dsp_precision, dsp_loop_latency; 1163 uint32_t dsp_off, dsp_on, dsp_xclks_per_qw; 1164 uint32_t xclks_per_qw, y; 1165 uint32_t fifo_off, fifo_on; 1166 1167 aprint_normal_dev(sc->sc_dev, "initializing the DSP\n"); 1168 1169 if (mach64_chip_id == PCI_PRODUCT_ATI_MACH64_VT || 1170 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_II || 1171 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIP || 1172 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_PCI || 1173 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_B || 1174 mach64_chip_id == PCI_PRODUCT_ATI_RAGE_IIC_AGP_P) { 1175 dsp_loop_latency = 0; 1176 fifo_depth = 24; 1177 } else { 1178 dsp_loop_latency = 2; 1179 fifo_depth = 32; 1180 } 1181 1182 dsp_precision = 0; 1183 xclks_per_qw = (sc->mclk_fb_div * sc->vclk_post_div * 64 << 11) / 1184 (sc->vclk_fb_div * sc->mclk_post_div * sc->bits_per_pixel); 1185 y = (xclks_per_qw * fifo_depth) >> 11; 1186 while (y) { 1187 y >>= 1; 1188 dsp_precision++; 1189 } 1190 dsp_precision -= 5; 1191 fifo_off = ((xclks_per_qw * (fifo_depth - 1)) >> 5) + (3 << 6); 1192 1193 switch (sc->memtype) { 1194 case DRAM: 1195 case EDO_DRAM: 1196 case PSEUDO_EDO: 1197 if (sc->memsize > 1024) { 1198 page_size = 9; 1199 dsp_loop_latency += 6; 1200 } else { 1201 page_size = 10; 1202 if (sc->memtype == DRAM) 1203 dsp_loop_latency += 8; 1204 else 1205 dsp_loop_latency += 7; 1206 } 1207 break; 1208 case SDRAM: 1209 case SGRAM: 1210 if (sc->memsize > 1024) { 1211 page_size = 8; 1212 dsp_loop_latency += 8; 1213 } else { 1214 page_size = 10; 1215 dsp_loop_latency += 9; 1216 } 1217 break; 1218 default: 1219 page_size = 10; 1220 dsp_loop_latency += 9; 1221 break; 1222 } 1223 1224 if (xclks_per_qw >= (page_size << 11)) 1225 fifo_on = ((2 * page_size + 1) << 6) + (xclks_per_qw >> 5); 1226 else 1227 fifo_on = (3 * page_size + 2) << 6; 1228 1229 dsp_xclks_per_qw = xclks_per_qw >> dsp_precision; 1230 dsp_on = fifo_on >> dsp_precision; 1231 dsp_off = fifo_off >> dsp_precision; 1232 1233 #ifdef MACHFB_DEBUG 1234 printf("dsp_xclks_per_qw = %d, dsp_on = %d, dsp_off = %d,\n" 1235 "dsp_precision = %d, dsp_loop_latency = %d,\n" 1236 "mclk_fb_div = %d, vclk_fb_div = %d,\n" 1237 "mclk_post_div = %d, vclk_post_div = %d\n", 1238 dsp_xclks_per_qw, dsp_on, dsp_off, dsp_precision, dsp_loop_latency, 1239 sc->mclk_fb_div, sc->vclk_fb_div, 1240 sc->mclk_post_div, sc->vclk_post_div); 1241 #endif 1242 1243 regw(sc, DSP_ON_OFF, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF)); 1244 regw(sc, DSP_CONFIG, ((dsp_precision << 20) & DSP_PRECISION) | 1245 ((dsp_loop_latency << 16) & DSP_LOOP_LATENCY) | 1246 (dsp_xclks_per_qw & DSP_XCLKS_PER_QW)); 1247 } 1248 1249 static void 1250 mach64_set_pll(struct mach64_softc *sc, int clock) 1251 { 1252 uint32_t q, clockreg; 1253 int clockshift = sc->sc_clock << 1; 1254 uint8_t reg, vclk_ctl; 1255 1256 q = (clock * sc->ref_div * 100) / (2 * sc->ref_freq); 1257 #ifdef MACHFB_DEBUG 1258 printf("q = %d\n", q); 1259 #endif 1260 if (q > 25500) { 1261 aprint_error_dev(sc->sc_dev, "Warning: q > 25500\n"); 1262 q = 25500; 1263 sc->vclk_post_div = 1; 1264 sc->log2_vclk_post_div = 0; 1265 } else if (q > 12750) { 1266 sc->vclk_post_div = 1; 1267 sc->log2_vclk_post_div = 0; 1268 } else if (q > 6350) { 1269 sc->vclk_post_div = 2; 1270 sc->log2_vclk_post_div = 1; 1271 } else if (q > 3150) { 1272 sc->vclk_post_div = 4; 1273 sc->log2_vclk_post_div = 2; 1274 } else if (q >= 1600) { 1275 sc->vclk_post_div = 8; 1276 sc->log2_vclk_post_div = 3; 1277 } else { 1278 aprint_error_dev(sc->sc_dev, "Warning: q < 1600\n"); 1279 sc->vclk_post_div = 8; 1280 sc->log2_vclk_post_div = 3; 1281 } 1282 sc->vclk_fb_div = q * sc->vclk_post_div / 100; 1283 aprint_debug("post_div: %d log2_post_div: %d mclk_div: %d\n", 1284 sc->vclk_post_div, sc->log2_vclk_post_div, sc->mclk_fb_div); 1285 1286 vclk_ctl = regrb_pll(sc, PLL_VCLK_CNTL); 1287 aprint_debug("vclk_ctl: %02x\n", vclk_ctl); 1288 vclk_ctl |= PLL_VCLK_RESET; 1289 regwb_pll(sc, PLL_VCLK_CNTL, vclk_ctl); 1290 1291 regwb_pll(sc, MCLK_FB_DIV, sc->mclk_fb_div); 1292 reg = regrb_pll(sc, VCLK_POST_DIV); 1293 reg &= ~(3 << clockshift); 1294 reg |= (sc->log2_vclk_post_div << clockshift); 1295 regwb_pll(sc, VCLK_POST_DIV, reg); 1296 regwb_pll(sc, VCLK0_FB_DIV + sc->sc_clock, sc->vclk_fb_div); 1297 1298 vclk_ctl &= ~PLL_VCLK_RESET; 1299 regwb_pll(sc, PLL_VCLK_CNTL, vclk_ctl); 1300 1301 clockreg = regr(sc, CLOCK_CNTL); 1302 clockreg &= ~CLOCK_SEL; 1303 clockreg |= sc->sc_clock | CLOCK_STROBE; 1304 regw(sc, CLOCK_CNTL, clockreg); 1305 } 1306 1307 static void 1308 mach64_init_lut(struct mach64_softc *sc) 1309 { 1310 uint8_t cmap[768]; 1311 int i, idx; 1312 1313 rasops_get_cmap(&mach64_console_screen.scr_ri, cmap, sizeof(cmap)); 1314 idx = 0; 1315 for (i = 0; i < 256; i++) { 1316 mach64_putpalreg(sc, i, cmap[idx], cmap[idx + 1], 1317 cmap[idx + 2]); 1318 idx += 3; 1319 } 1320 } 1321 1322 static int 1323 mach64_putpalreg(struct mach64_softc *sc, uint8_t index, uint8_t r, uint8_t g, 1324 uint8_t b) 1325 { 1326 sc->sc_cmap_red[index] = r; 1327 sc->sc_cmap_green[index] = g; 1328 sc->sc_cmap_blue[index] = b; 1329 /* 1330 * writing the dac index takes a while, in theory we can poll some 1331 * register to see when it's ready - but we better avoid writing it 1332 * unnecessarily 1333 */ 1334 if (index != sc->sc_dacw) { 1335 regwb(sc, DAC_MASK, 0xff); 1336 regwb(sc, DAC_WINDEX, index); 1337 } 1338 sc->sc_dacw = index + 1; 1339 regwb(sc, DAC_DATA, r); 1340 regwb(sc, DAC_DATA, g); 1341 regwb(sc, DAC_DATA, b); 1342 return 0; 1343 } 1344 1345 static int 1346 mach64_putcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm) 1347 { 1348 uint index = cm->index; 1349 uint count = cm->count; 1350 int i, error; 1351 uint8_t rbuf[256], gbuf[256], bbuf[256]; 1352 uint8_t *r, *g, *b; 1353 1354 if (cm->index >= 256 || cm->count > 256 || 1355 (cm->index + cm->count) > 256) 1356 return EINVAL; 1357 error = copyin(cm->red, &rbuf[index], count); 1358 if (error) 1359 return error; 1360 error = copyin(cm->green, &gbuf[index], count); 1361 if (error) 1362 return error; 1363 error = copyin(cm->blue, &bbuf[index], count); 1364 if (error) 1365 return error; 1366 1367 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 1368 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 1369 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 1370 1371 r = &sc->sc_cmap_red[index]; 1372 g = &sc->sc_cmap_green[index]; 1373 b = &sc->sc_cmap_blue[index]; 1374 1375 for (i = 0; i < count; i++) { 1376 mach64_putpalreg(sc, index, *r, *g, *b); 1377 index++; 1378 r++, g++, b++; 1379 } 1380 return 0; 1381 } 1382 1383 static int 1384 mach64_getcmap(struct mach64_softc *sc, struct wsdisplay_cmap *cm) 1385 { 1386 u_int index = cm->index; 1387 u_int count = cm->count; 1388 int error; 1389 1390 if (index >= 255 || count > 256 || index + count > 256) 1391 return EINVAL; 1392 1393 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 1394 if (error) 1395 return error; 1396 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 1397 if (error) 1398 return error; 1399 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 1400 if (error) 1401 return error; 1402 1403 return 0; 1404 } 1405 1406 static int 1407 mach64_set_screentype(struct mach64_softc *sc, const struct wsscreen_descr *des) 1408 { 1409 struct mach64_crtcregs regs; 1410 1411 if (mach64_calc_crtcregs(sc, ®s, 1412 (struct videomode *)des->modecookie)) 1413 return 1; 1414 1415 mach64_set_crtcregs(sc, ®s); 1416 return 0; 1417 } 1418 1419 static int 1420 mach64_is_console(struct mach64_softc *sc) 1421 { 1422 bool console = 0; 1423 1424 prop_dictionary_get_bool(device_properties(sc->sc_dev), 1425 "is_console", &console); 1426 return console; 1427 } 1428 1429 /* 1430 * wsdisplay_emulops 1431 */ 1432 1433 static void 1434 mach64_cursor(void *cookie, int on, int row, int col) 1435 { 1436 struct rasops_info *ri = cookie; 1437 struct vcons_screen *scr = ri->ri_hw; 1438 struct mach64_softc *sc = scr->scr_cookie; 1439 int x, y, wi, he; 1440 1441 wi = ri->ri_font->fontwidth; 1442 he = ri->ri_font->fontheight; 1443 1444 if ((!sc->sc_locked) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1445 x = ri->ri_ccol * wi + ri->ri_xorigin; 1446 y = ri->ri_crow * he + ri->ri_yorigin; 1447 if (ri->ri_flg & RI_CURSOR) { 1448 mach64_bitblt(sc, x, y, x, y, wi, he, MIX_NOT_SRC); 1449 ri->ri_flg &= ~RI_CURSOR; 1450 } 1451 ri->ri_crow = row; 1452 ri->ri_ccol = col; 1453 if (on) { 1454 x = ri->ri_ccol * wi + ri->ri_xorigin; 1455 y = ri->ri_crow * he + ri->ri_yorigin; 1456 mach64_bitblt(sc, x, y, x, y, wi, he, MIX_NOT_SRC); 1457 ri->ri_flg |= RI_CURSOR; 1458 } 1459 } else { 1460 scr->scr_ri.ri_crow = row; 1461 scr->scr_ri.ri_ccol = col; 1462 scr->scr_ri.ri_flg &= ~RI_CURSOR; 1463 } 1464 } 1465 1466 #if 0 1467 static int 1468 mach64_mapchar(void *cookie, int uni, u_int *index) 1469 { 1470 return 0; 1471 } 1472 #endif 1473 1474 static void 1475 mach64_putchar_mono(void *cookie, int row, int col, u_int c, long attr) 1476 { 1477 struct rasops_info *ri = cookie; 1478 struct wsdisplay_font *font = PICK_FONT(ri, c); 1479 struct vcons_screen *scr = ri->ri_hw; 1480 struct mach64_softc *sc = scr->scr_cookie; 1481 1482 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1483 int fg, bg, uc; 1484 uint8_t *data; 1485 int x, y, wi, he; 1486 wi = font->fontwidth; 1487 he = font->fontheight; 1488 1489 if (!CHAR_IN_FONT(c, font)) 1490 return; 1491 bg = ri->ri_devcmap[(attr >> 16) & 0x0f]; 1492 fg = ri->ri_devcmap[(attr >> 24) & 0x0f]; 1493 x = ri->ri_xorigin + col * wi; 1494 y = ri->ri_yorigin + row * he; 1495 if (c == 0x20) { 1496 mach64_rectfill(sc, x, y, wi, he, bg); 1497 } else { 1498 uc = c - font->firstchar; 1499 data = (uint8_t *)font->data + uc * 1500 ri->ri_fontscale; 1501 1502 mach64_setup_mono(sc, x, y, wi, he, fg, bg); 1503 mach64_feed_bytes(sc, ri->ri_fontscale, data); 1504 } 1505 } 1506 } 1507 1508 static void 1509 mach64_putchar_aa8(void *cookie, int row, int col, u_int c, long attr) 1510 { 1511 struct rasops_info *ri = cookie; 1512 struct wsdisplay_font *font = PICK_FONT(ri, c); 1513 struct vcons_screen *scr = ri->ri_hw; 1514 struct mach64_softc *sc = scr->scr_cookie; 1515 uint32_t bg, latch = 0, bg8, fg8, pixel; 1516 int i, x, y, wi, he, r, g, b, aval; 1517 int r1, g1, b1, r0, g0, b0, fgo, bgo; 1518 uint8_t *data8; 1519 int rv = 0, cnt = 0; 1520 1521 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1522 return; 1523 1524 if (!CHAR_IN_FONT(c, font)) 1525 return; 1526 1527 wi = font->fontwidth; 1528 he = font->fontheight; 1529 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0x0f]; 1530 x = ri->ri_xorigin + col * wi; 1531 y = ri->ri_yorigin + row * he; 1532 1533 if (c == 0x20) { 1534 mach64_rectfill(sc, x, y, wi, he, bg); 1535 return; 1536 } 1537 1538 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1539 if (rv == GC_OK) 1540 return; 1541 1542 data8 = WSFONT_GLYPH(c, font); 1543 1544 wait_for_fifo(sc, 11); 1545 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); 1546 regw(sc, DP_SRC, MONO_SRC_ONE | BKGD_SRC_HOST | FRGD_SRC_HOST); 1547 regw(sc, DP_MIX, ((MIX_SRC & 0xffff) << 16) | MIX_SRC); 1548 regw(sc, CLR_CMP_CNTL ,0); /* no transparency */ 1549 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1550 regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT); 1551 regw(sc, HOST_CNTL, HOST_BYTE_ALIGN); 1552 regw(sc, SRC_Y_X, 0); 1553 regw(sc, SRC_WIDTH1, wi); 1554 regw(sc, DST_Y_X, (x << 16) | y); 1555 regw(sc, DST_HEIGHT_WIDTH, (wi << 16) | he); 1556 1557 /* 1558 * we need the RGB colours here, so get offsets into rasops_cmap 1559 */ 1560 fgo = ((attr >> 24) & 0xf) * 3; 1561 bgo = ((attr >> 16) & 0xf) * 3; 1562 1563 r0 = rasops_cmap[bgo]; 1564 r1 = rasops_cmap[fgo]; 1565 g0 = rasops_cmap[bgo + 1]; 1566 g1 = rasops_cmap[fgo + 1]; 1567 b0 = rasops_cmap[bgo + 2]; 1568 b1 = rasops_cmap[fgo + 2]; 1569 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1570 bg8 = R3G3B2(r0, g0, b0); 1571 fg8 = R3G3B2(r1, g1, b1); 1572 1573 wait_for_fifo(sc, 10); 1574 1575 for (i = 0; i < ri->ri_fontscale; i++) { 1576 aval = *data8; 1577 if (aval == 0) { 1578 pixel = bg8; 1579 } else if (aval == 255) { 1580 pixel = fg8; 1581 } else { 1582 r = aval * r1 + (255 - aval) * r0; 1583 g = aval * g1 + (255 - aval) * g0; 1584 b = aval * b1 + (255 - aval) * b0; 1585 pixel = ((r & 0xe000) >> 8) | 1586 ((g & 0xe000) >> 11) | 1587 ((b & 0xc000) >> 14); 1588 } 1589 latch = (latch << 8) | pixel; 1590 /* write in 32bit chunks */ 1591 if ((i & 3) == 3) { 1592 regws(sc, HOST_DATA0, latch); 1593 /* 1594 * not strictly necessary, old data should be shifted 1595 * out 1596 */ 1597 latch = 0; 1598 cnt++; 1599 if (cnt > 8) { 1600 wait_for_fifo(sc, 10); 1601 cnt = 0; 1602 } 1603 } 1604 data8++; 1605 } 1606 /* if we have pixels left in latch write them out */ 1607 if ((i & 3) != 0) { 1608 latch = latch << ((4 - (i & 3)) << 3); 1609 regws(sc, HOST_DATA0, latch); 1610 } 1611 1612 if (rv == GC_ADD) { 1613 glyphcache_add(&sc->sc_gc, c, x, y); 1614 } 1615 } 1616 1617 static void 1618 mach64_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1619 { 1620 struct rasops_info *ri = cookie; 1621 struct vcons_screen *scr = ri->ri_hw; 1622 struct mach64_softc *sc = scr->scr_cookie; 1623 int32_t xs, xd, y, width, height; 1624 1625 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1626 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1627 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1628 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1629 width = ri->ri_font->fontwidth * ncols; 1630 height = ri->ri_font->fontheight; 1631 mach64_bitblt(sc, xs, y, xd, y, width, height, MIX_SRC); 1632 } 1633 } 1634 1635 static void 1636 mach64_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1637 { 1638 struct rasops_info *ri = cookie; 1639 struct vcons_screen *scr = ri->ri_hw; 1640 struct mach64_softc *sc = scr->scr_cookie; 1641 int32_t x, y, width, height, fg, bg, ul; 1642 1643 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1644 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1645 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1646 width = ri->ri_font->fontwidth * ncols; 1647 height = ri->ri_font->fontheight; 1648 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1649 1650 mach64_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1651 } 1652 } 1653 1654 static void 1655 mach64_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1656 { 1657 struct rasops_info *ri = cookie; 1658 struct vcons_screen *scr = ri->ri_hw; 1659 struct mach64_softc *sc = scr->scr_cookie; 1660 int32_t x, ys, yd, width, height; 1661 1662 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1663 x = ri->ri_xorigin; 1664 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1665 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1666 width = ri->ri_emuwidth; 1667 height = ri->ri_font->fontheight*nrows; 1668 mach64_bitblt(sc, x, ys, x, yd, width, height, MIX_SRC); 1669 } 1670 } 1671 1672 static void 1673 mach64_eraserows(void *cookie, int row, int nrows, long fillattr) 1674 { 1675 struct rasops_info *ri = cookie; 1676 struct vcons_screen *scr = ri->ri_hw; 1677 struct mach64_softc *sc = scr->scr_cookie; 1678 int32_t x, y, width, height, fg, bg, ul; 1679 1680 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1681 if ((row == 0) && (nrows == ri->ri_rows)) { 1682 /* clear full screen */ 1683 x = 0; 1684 y = 0; 1685 width = sc->virt_x; 1686 height = sc->virt_y; 1687 } else { 1688 x = ri->ri_xorigin; 1689 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1690 width = ri->ri_emuwidth; 1691 height = ri->ri_font->fontheight * nrows; 1692 } 1693 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1694 1695 mach64_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1696 } 1697 } 1698 1699 static void 1700 mach64_bitblt(void *cookie, int xs, int ys, int xd, int yd, int width, int height, int rop) 1701 { 1702 struct mach64_softc *sc = cookie; 1703 uint32_t dest_ctl = 0; 1704 1705 wait_for_fifo(sc, 10); 1706 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); 1707 regw(sc, DP_SRC, FRGD_SRC_BLIT); 1708 regw(sc, DP_MIX, (rop & 0xffff) << 16); 1709 regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 1710 if (yd < ys) { 1711 dest_ctl = DST_Y_TOP_TO_BOTTOM; 1712 } else { 1713 ys += height - 1; 1714 yd += height - 1; 1715 dest_ctl = DST_Y_BOTTOM_TO_TOP; 1716 } 1717 if (xd < xs) { 1718 dest_ctl |= DST_X_LEFT_TO_RIGHT; 1719 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1720 } else { 1721 dest_ctl |= DST_X_RIGHT_TO_LEFT; 1722 xs += width - 1; 1723 xd += width - 1; 1724 regw(sc, SRC_CNTL, SRC_LINE_X_RIGHT_TO_LEFT); 1725 } 1726 regw(sc, DST_CNTL, dest_ctl); 1727 1728 regw(sc, SRC_Y_X, (xs << 16) | ys); 1729 regw(sc, SRC_WIDTH1, width); 1730 regw(sc, DST_Y_X, (xd << 16) | yd); 1731 regw(sc, DST_HEIGHT_WIDTH, (width << 16) | height); 1732 } 1733 1734 static void 1735 mach64_setup_mono(struct mach64_softc *sc, int xd, int yd, int width, 1736 int height, uint32_t fg, uint32_t bg) 1737 { 1738 wait_for_idle(sc); 1739 regw(sc, DP_WRITE_MASK, 0xff); /* XXX only good for 8 bit */ 1740 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_1BPP | HOST_1BPP); 1741 regw(sc, DP_SRC, MONO_SRC_HOST | BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR); 1742 regw(sc, DP_MIX, ((MIX_SRC & 0xffff) << 16) | MIX_SRC); 1743 regw(sc, CLR_CMP_CNTL ,0); /* no transparency */ 1744 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1745 regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT); 1746 regw(sc, HOST_CNTL, HOST_BYTE_ALIGN); 1747 regw(sc, DP_BKGD_CLR, bg); 1748 regw(sc, DP_FRGD_CLR, fg); 1749 regw(sc, SRC_Y_X, 0); 1750 regw(sc, SRC_WIDTH1, width); 1751 regw(sc, DST_Y_X, (xd << 16) | yd); 1752 regw(sc, DST_HEIGHT_WIDTH, (width << 16) | height); 1753 /* now feed the data into the chip */ 1754 } 1755 1756 static void 1757 mach64_feed_bytes(struct mach64_softc *sc, int count, uint8_t *data) 1758 { 1759 int i; 1760 uint32_t latch = 0, bork; 1761 int shift = 0; 1762 int reg = 0; 1763 1764 for (i = 0; i < count; i++) { 1765 bork = data[i]; 1766 latch |= (bork << shift); 1767 if (shift == 24) { 1768 regw(sc, HOST_DATA0 + reg, latch); 1769 latch = 0; 1770 shift = 0; 1771 reg = (reg + 4) & 0x3c; 1772 } else 1773 shift += 8; 1774 } 1775 if (shift != 0) /* 24 */ 1776 regw(sc, HOST_DATA0 + reg, latch); 1777 } 1778 1779 1780 static void 1781 mach64_rectfill(struct mach64_softc *sc, int x, int y, int width, int height, 1782 int colour) 1783 { 1784 wait_for_fifo(sc, 11); 1785 regw(sc, DP_FRGD_CLR, colour); 1786 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP); 1787 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR); 1788 regw(sc, DP_MIX, MIX_SRC << 16); 1789 regw(sc, CLR_CMP_CNTL, 0); /* no transparency */ 1790 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT); 1791 regw(sc, DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 1792 1793 regw(sc, SRC_Y_X, (x << 16) | y); 1794 regw(sc, SRC_WIDTH1, width); 1795 regw(sc, DST_Y_X, (x << 16) | y); 1796 regw(sc, DST_HEIGHT_WIDTH, (width << 16) | height); 1797 } 1798 1799 static void 1800 mach64_clearscreen(struct mach64_softc *sc) 1801 { 1802 mach64_rectfill(sc, 0, 0, sc->virt_x, sc->virt_y, sc->sc_bg); 1803 } 1804 1805 1806 #if 0 1807 static void 1808 mach64_showpal(struct mach64_softc *sc) 1809 { 1810 int i, x = 0; 1811 1812 for (i = 0; i < 16; i++) { 1813 mach64_rectfill(sc, x, 0, 64, 64, i); 1814 x += 64; 1815 } 1816 } 1817 #endif 1818 1819 /* 1820 * wsdisplay_accessops 1821 */ 1822 1823 static int 1824 mach64_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1825 struct lwp *l) 1826 { 1827 struct vcons_data *vd = v; 1828 struct mach64_softc *sc = vd->cookie; 1829 struct wsdisplay_fbinfo *wdf; 1830 struct vcons_screen *ms = vd->active; 1831 1832 switch (cmd) { 1833 case WSDISPLAYIO_GTYPE: 1834 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 1835 return 0; 1836 1837 case WSDISPLAYIO_LINEBYTES: 1838 *(u_int *)data = sc->virt_x * sc->bits_per_pixel / 8; 1839 return 0; 1840 1841 case WSDISPLAYIO_GINFO: 1842 wdf = (void *)data; 1843 wdf->height = sc->virt_y; 1844 wdf->width = sc->virt_x; 1845 wdf->depth = sc->bits_per_pixel; 1846 wdf->cmsize = 256; 1847 return 0; 1848 1849 case WSDISPLAYIO_GETCMAP: 1850 return mach64_getcmap(sc, 1851 (struct wsdisplay_cmap *)data); 1852 1853 case WSDISPLAYIO_PUTCMAP: 1854 return mach64_putcmap(sc, 1855 (struct wsdisplay_cmap *)data); 1856 1857 /* PCI config read/write passthrough. */ 1858 case PCI_IOC_CFGREAD: 1859 case PCI_IOC_CFGWRITE: 1860 return pci_devioctl(sc->sc_pc, sc->sc_pcitag, 1861 cmd, data, flag, l); 1862 1863 case WSDISPLAYIO_GET_BUSID: 1864 return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 1865 sc->sc_pcitag, data); 1866 1867 case WSDISPLAYIO_SMODE: { 1868 int new_mode = *(int*)data; 1869 if (new_mode != sc->sc_mode) { 1870 sc->sc_mode = new_mode; 1871 if ((new_mode == WSDISPLAYIO_MODE_EMUL) 1872 && (ms != NULL)) 1873 { 1874 /* restore initial video mode */ 1875 mach64_init(sc); 1876 mach64_init_engine(sc); 1877 mach64_init_lut(sc); 1878 mach64_modeswitch(sc, sc->sc_my_mode); 1879 mach64_clearscreen(sc); 1880 glyphcache_wipe(&sc->sc_gc); 1881 vcons_redraw_screen(ms); 1882 } 1883 } 1884 } 1885 return 0; 1886 case WSDISPLAYIO_GET_EDID: { 1887 struct wsdisplayio_edid_info *d = data; 1888 return wsdisplayio_get_edid(sc->sc_dev, d); 1889 } 1890 1891 case WSDISPLAYIO_GET_FBINFO: { 1892 struct wsdisplayio_fbinfo *fbi = data; 1893 return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 1894 } 1895 } 1896 return EPASSTHROUGH; 1897 } 1898 1899 static paddr_t 1900 mach64_mmap(void *v, void *vs, off_t offset, int prot) 1901 { 1902 struct vcons_data *vd = v; 1903 struct mach64_softc *sc = vd->cookie; 1904 paddr_t pa; 1905 1906 if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) { 1907 /* 1908 *'regular' framebuffer mmap()ing 1909 */ 1910 if (offset < (sc->memsize * 1024)) { 1911 pa = bus_space_mmap(sc->sc_memt, sc->sc_aperbase, 1912 offset, prot, BUS_SPACE_MAP_LINEAR); 1913 return pa; 1914 } 1915 } else if (sc->sc_mode == WSDISPLAYIO_MODE_MAPPED) { 1916 /* 1917 * restrict all other mappings to processes with superuser 1918 * privileges 1919 */ 1920 if (kauth_authorize_machdep(kauth_cred_get(), 1921 KAUTH_MACHDEP_UNMANAGEDMEM, 1922 NULL, NULL, NULL, NULL) != 0) { 1923 return -1; 1924 } 1925 if ((offset >= sc->sc_aperbase) && 1926 (offset < (sc->sc_aperbase + sc->sc_apersize))) { 1927 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 1928 BUS_SPACE_MAP_LINEAR); 1929 return pa; 1930 } 1931 1932 if ((offset >= sc->sc_regbase) && 1933 (offset < (sc->sc_regbase + sc->sc_regsize))) { 1934 pa = bus_space_mmap(sc->sc_regt, offset, 0, prot, 1935 BUS_SPACE_MAP_LINEAR); 1936 return pa; 1937 } 1938 1939 if ((offset >= sc->sc_rom.vb_base) && 1940 (offset < (sc->sc_rom.vb_base + sc->sc_rom.vb_size))) { 1941 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 1942 BUS_SPACE_MAP_LINEAR); 1943 return pa; 1944 } 1945 1946 #ifdef PCI_MAGIC_IO_RANGE 1947 if ((offset >= PCI_MAGIC_IO_RANGE) && 1948 (offset <= PCI_MAGIC_IO_RANGE + 0x10000)) { 1949 return bus_space_mmap(sc->sc_iot, 1950 offset - PCI_MAGIC_IO_RANGE, 0, prot, 0); 1951 } 1952 #endif 1953 } 1954 return -1; 1955 } 1956 1957 #if 0 1958 static int 1959 mach64_load_font(void *v, void *cookie, struct wsdisplay_font *data) 1960 { 1961 1962 return 0; 1963 } 1964 #endif 1965 1966 void 1967 machfb_blank(struct mach64_softc *sc, int blank) 1968 { 1969 uint32_t reg; 1970 1971 #define MACH64_BLANK (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS) 1972 1973 switch (blank) 1974 { 1975 case 0: 1976 reg = regr(sc, CRTC_GEN_CNTL); 1977 regw(sc, CRTC_GEN_CNTL, reg & ~(MACH64_BLANK)); 1978 sc->sc_blanked = 0; 1979 break; 1980 case 1: 1981 reg = regr(sc, CRTC_GEN_CNTL); 1982 regw(sc, CRTC_GEN_CNTL, reg | (MACH64_BLANK)); 1983 sc->sc_blanked = 1; 1984 break; 1985 default: 1986 break; 1987 } 1988 } 1989