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