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