1 1.11 andvar /* $NetBSD: tdvfb.c,v 1.11 2023/08/01 20:50:11 andvar Exp $ */ 2 1.1 rkujawa 3 1.1 rkujawa /* 4 1.1 rkujawa * Copyright (c) 2012 The NetBSD Foundation, Inc. 5 1.1 rkujawa * All rights reserved. 6 1.1 rkujawa * 7 1.1 rkujawa * This code is derived from software contributed to The NetBSD Foundation 8 1.1 rkujawa * by Radoslaw Kujawa. 9 1.1 rkujawa * 10 1.1 rkujawa * Redistribution and use in source and binary forms, with or without 11 1.1 rkujawa * modification, are permitted provided that the following conditions 12 1.1 rkujawa * are met: 13 1.1 rkujawa * 1. Redistributions of source code must retain the above copyright 14 1.1 rkujawa * notice, this list of conditions and the following disclaimer. 15 1.1 rkujawa * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 rkujawa * notice, this list of conditions and the following disclaimer in the 17 1.1 rkujawa * documentation and/or other materials provided with the distribution. 18 1.1 rkujawa * 19 1.1 rkujawa * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 rkujawa * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 rkujawa * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 rkujawa * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 rkujawa * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 rkujawa * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 rkujawa * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 rkujawa * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 rkujawa * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 1.1 rkujawa * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 rkujawa */ 30 1.1 rkujawa 31 1.1 rkujawa /* 32 1.2 rkujawa * A console driver for 3Dfx Voodoo2 (CVG) and 3Dfx Voodoo Graphics (SST-1). 33 1.1 rkujawa * 34 1.1 rkujawa * 3Dfx Glide 2.x source code, Linux driver by Ghozlane Toumi, and 35 1.1 rkujawa * "Voodoo2 Graphics Engine for 3D Game Acceleration" document were used as 36 1.1 rkujawa * reference. wscons attachment code based mostly on genfb by Michael 37 1.1 rkujawa * Lorenz. 38 1.1 rkujawa * 39 1.1 rkujawa * This driver currently only support boards with ICS GENDAC (which seems to 40 1.1 rkujawa * be most popular, however at least two different DACs were used with CVG). 41 1.4 rkujawa * 42 1.4 rkujawa * TODO (in no particular order): 43 1.4 rkujawa * - Finally fix 16-bit depth handling on big-endian machines. 44 1.4 rkujawa * - Expose card to userspace through /dev/3dfx compatible device file 45 1.4 rkujawa * (for Glide). 46 1.4 rkujawa * - Allow mmap'ing of registers through wscons access op. 47 1.4 rkujawa * - Complete wscons emul ops acceleration support. 48 1.4 rkujawa * - Add support for others DACs (need hardware). 49 1.1 rkujawa */ 50 1.1 rkujawa 51 1.1 rkujawa #include <sys/cdefs.h> 52 1.11 andvar __KERNEL_RCSID(0, "$NetBSD: tdvfb.c,v 1.11 2023/08/01 20:50:11 andvar Exp $"); 53 1.1 rkujawa 54 1.1 rkujawa #include <sys/param.h> 55 1.1 rkujawa #include <sys/systm.h> 56 1.1 rkujawa #include <sys/kernel.h> 57 1.1 rkujawa #include <sys/device.h> 58 1.1 rkujawa #include <sys/endian.h> 59 1.1 rkujawa 60 1.1 rkujawa #include <dev/pci/pcivar.h> 61 1.1 rkujawa #include <dev/pci/pcireg.h> 62 1.1 rkujawa #include <dev/pci/pcidevs.h> 63 1.1 rkujawa #include <dev/pci/pciio.h> 64 1.1 rkujawa 65 1.1 rkujawa #include <dev/pci/tdvfbreg.h> 66 1.1 rkujawa #include <dev/pci/tdvfbvar.h> 67 1.1 rkujawa 68 1.1 rkujawa #include <dev/videomode/videomode.h> 69 1.4 rkujawa #include <dev/pci/wsdisplay_pci.h> 70 1.1 rkujawa 71 1.1 rkujawa #include "opt_wsemul.h" 72 1.1 rkujawa #include "opt_tdvfb.h" 73 1.1 rkujawa 74 1.1 rkujawa #define MAXLOOP 4096 75 1.5 rkujawa /* #define TDVFB_DEBUG 1 */ 76 1.1 rkujawa 77 1.1 rkujawa static int tdvfb_match(device_t, cfdata_t, void *); 78 1.1 rkujawa static void tdvfb_attach(device_t, device_t, void *); 79 1.1 rkujawa 80 1.1 rkujawa static uint32_t tdvfb_cvg_read(struct tdvfb_softc *sc, uint32_t reg); 81 1.1 rkujawa static void tdvfb_cvg_write(struct tdvfb_softc *sc, uint32_t reg, 82 1.1 rkujawa uint32_t val); 83 1.1 rkujawa static void tdvfb_cvg_set(struct tdvfb_softc *sc, uint32_t reg, 84 1.1 rkujawa uint32_t bits); 85 1.1 rkujawa static void tdvfb_cvg_unset(struct tdvfb_softc *sc, uint32_t reg, 86 1.1 rkujawa uint32_t bits); 87 1.1 rkujawa static uint8_t tdvfb_cvg_dac_read(struct tdvfb_softc *sc, uint32_t reg); 88 1.3 rkujawa static void tdvfb_cvg_dac_write(struct tdvfb_softc *sc, uint32_t reg, 89 1.1 rkujawa uint32_t val); 90 1.1 rkujawa static void tdvfb_wait(struct tdvfb_softc *sc); 91 1.1 rkujawa 92 1.1 rkujawa static bool tdvfb_init(struct tdvfb_softc *sc); 93 1.1 rkujawa static void tdvfb_fbiinit_defaults(struct tdvfb_softc *sc); 94 1.1 rkujawa static size_t tdvfb_mem_size(struct tdvfb_softc *sc); 95 1.1 rkujawa 96 1.1 rkujawa static bool tdvfb_videomode_set(struct tdvfb_softc *sc); 97 1.1 rkujawa static void tdvfb_videomode_dac(struct tdvfb_softc *sc); 98 1.1 rkujawa 99 1.1 rkujawa static bool tdvfb_gendac_detect(struct tdvfb_softc *sc); 100 1.1 rkujawa static struct tdvfb_dac_timing tdvfb_gendac_calc_pll(int freq); 101 1.1 rkujawa static void tdvfb_gendac_set_cvg_timing(struct tdvfb_softc *sc, 102 1.1 rkujawa struct tdvfb_dac_timing *timing); 103 1.1 rkujawa static void tdvfb_gendac_set_vid_timing(struct tdvfb_softc *sc, 104 1.1 rkujawa struct tdvfb_dac_timing *timing); 105 1.1 rkujawa 106 1.4 rkujawa static paddr_t tdvfb_mmap(void *v, void *vs, off_t offset, int prot); 107 1.4 rkujawa static int tdvfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 108 1.4 rkujawa struct lwp *l); 109 1.1 rkujawa static void tdvfb_init_screen(void *cookie, struct vcons_screen *scr, 110 1.1 rkujawa int existing, long *defattr); 111 1.1 rkujawa static void tdvfb_init_palette(struct tdvfb_softc *sc); 112 1.3 rkujawa /* blitter support */ 113 1.3 rkujawa static void tdvfb_rectfill(struct tdvfb_softc *sc, int x, int y, int wi, 114 1.3 rkujawa int he, uint32_t color); 115 1.3 rkujawa static void tdvfb_bitblt(struct tdvfb_softc *sc, int xs, int ys, int xd, 116 1.3 rkujawa int yd, int wi, int he); 117 1.3 rkujawa /* accelerated raster ops */ 118 1.3 rkujawa static void tdvfb_eraserows(void *cookie, int row, int nrows, 119 1.3 rkujawa long fillattr); 120 1.3 rkujawa static void tdvfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows); 121 1.1 rkujawa 122 1.1 rkujawa CFATTACH_DECL_NEW(tdvfb, sizeof(struct tdvfb_softc), 123 1.1 rkujawa tdvfb_match, tdvfb_attach, NULL, NULL); 124 1.1 rkujawa 125 1.4 rkujawa struct wsdisplay_accessops tdvfb_accessops = { 126 1.4 rkujawa tdvfb_ioctl, 127 1.4 rkujawa tdvfb_mmap, 128 1.4 rkujawa NULL, /* alloc_screen */ 129 1.4 rkujawa NULL, /* free_screen */ 130 1.4 rkujawa NULL, /* show_screen */ 131 1.4 rkujawa NULL, /* load_font */ 132 1.4 rkujawa NULL, /* pollc */ 133 1.4 rkujawa NULL /* scroll */ 134 1.4 rkujawa }; 135 1.4 rkujawa 136 1.1 rkujawa static int 137 1.1 rkujawa tdvfb_match(device_t parent, cfdata_t match, void *aux) 138 1.1 rkujawa { 139 1.1 rkujawa const struct pci_attach_args *pa = (const struct pci_attach_args *)aux; 140 1.1 rkujawa 141 1.1 rkujawa if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_3DFX) && 142 1.1 rkujawa (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DFX_VOODOO2)) 143 1.1 rkujawa return 100; 144 1.2 rkujawa if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_3DFX) && 145 1.2 rkujawa (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DFX_VOODOO)) 146 1.2 rkujawa return 100; 147 1.1 rkujawa 148 1.1 rkujawa return 0; 149 1.1 rkujawa } 150 1.1 rkujawa 151 1.1 rkujawa static void 152 1.1 rkujawa tdvfb_attach(device_t parent, device_t self, void *aux) 153 1.1 rkujawa { 154 1.1 rkujawa struct tdvfb_softc *sc = device_private(self); 155 1.1 rkujawa struct wsemuldisplaydev_attach_args ws_aa; 156 1.1 rkujawa struct rasops_info *ri; 157 1.1 rkujawa const struct pci_attach_args *pa = aux; 158 1.1 rkujawa pcireg_t screg; 159 1.1 rkujawa bool console; 160 1.1 rkujawa long defattr; 161 1.1 rkujawa 162 1.1 rkujawa #ifdef TDVFB_CONSOLE 163 1.1 rkujawa console = true; 164 1.1 rkujawa #else 165 1.1 rkujawa console = false; 166 1.1 rkujawa #endif 167 1.1 rkujawa 168 1.1 rkujawa sc->sc_pc = pa->pa_pc; 169 1.1 rkujawa sc->sc_pcitag = pa->pa_tag; 170 1.1 rkujawa sc->sc_dev = self; 171 1.1 rkujawa 172 1.2 rkujawa if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DFX_VOODOO2) 173 1.2 rkujawa sc->sc_voodootype = TDV_VOODOO_2; 174 1.2 rkujawa else 175 1.2 rkujawa sc->sc_voodootype = TDV_VOODOO_1; 176 1.2 rkujawa 177 1.1 rkujawa screg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, 178 1.1 rkujawa PCI_COMMAND_STATUS_REG); 179 1.1 rkujawa screg |= PCI_COMMAND_MEM_ENABLE; 180 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, 181 1.1 rkujawa screg); 182 1.1 rkujawa 183 1.1 rkujawa pci_aprint_devinfo(pa, NULL); 184 1.1 rkujawa 185 1.1 rkujawa /* map the BAR */ 186 1.5 rkujawa if (pci_mapreg_map(pa, TDV_MM_BAR, PCI_MAPREG_TYPE_MEM, 187 1.5 rkujawa BUS_SPACE_MAP_LINEAR, &sc->sc_cvgt, &sc->sc_cvgh, 188 1.5 rkujawa &sc->sc_cvg_pa, 0) != 0 ) { 189 1.1 rkujawa aprint_error_dev(sc->sc_dev, "unable to map CVG BAR"); 190 1.1 rkujawa return; 191 1.1 rkujawa } 192 1.1 rkujawa 193 1.1 rkujawa /* Map the framebuffer. */ 194 1.1 rkujawa if (bus_space_subregion(sc->sc_cvgt, sc->sc_cvgh, TDV_OFF_FB, 195 1.1 rkujawa TDV_FB_SIZE, &sc->sc_fbh)) { 196 1.1 rkujawa aprint_error_dev(sc->sc_dev, "unable to map the framebuffer"); 197 1.1 rkujawa } 198 1.1 rkujawa 199 1.2 rkujawa aprint_normal_dev(sc->sc_dev, "registers at 0x%08x, fb at 0x%08x\n", 200 1.4 rkujawa (uint32_t) sc->sc_cvg_pa, (uint32_t) sc->sc_cvg_pa + TDV_OFF_FB); 201 1.1 rkujawa 202 1.1 rkujawa /* Do the low level setup. */ 203 1.1 rkujawa if (!tdvfb_init(sc)) { 204 1.1 rkujawa aprint_error_dev(sc->sc_dev, "could not initialize CVG\n"); 205 1.1 rkujawa return; 206 1.1 rkujawa } 207 1.1 rkujawa 208 1.1 rkujawa /* 209 1.1 rkujawa * The card is alive now, let's check how much framebuffer memory 210 1.1 rkujawa * do we have. 211 1.1 rkujawa */ 212 1.1 rkujawa sc->sc_memsize = tdvfb_mem_size(sc); 213 1.1 rkujawa 214 1.8 matt aprint_normal_dev(sc->sc_dev, "%zu MB framebuffer memory present\n", 215 1.4 rkujawa sc->sc_memsize / 1024 / 1024); 216 1.4 rkujawa 217 1.2 rkujawa /* Select video mode, 800x600 32bpp 60Hz by default... */ 218 1.1 rkujawa sc->sc_width = 800; 219 1.1 rkujawa sc->sc_height = 600; 220 1.4 rkujawa #if BYTE_ORDER == BIG_ENDIAN 221 1.3 rkujawa sc->sc_bpp = 32; /* XXX: 16 would allow blitter use. */ 222 1.4 rkujawa #else 223 1.4 rkujawa sc->sc_bpp = 16; 224 1.4 rkujawa #endif 225 1.1 rkujawa sc->sc_linebytes = 1024 * (sc->sc_bpp / 8); 226 1.1 rkujawa sc->sc_videomode = pick_mode_by_ref(sc->sc_width, sc->sc_height, 60); 227 1.1 rkujawa 228 1.4 rkujawa aprint_normal_dev(sc->sc_dev, "setting %dx%d %d bpp resolution\n", 229 1.4 rkujawa sc->sc_width, sc->sc_height, sc->sc_bpp); 230 1.4 rkujawa 231 1.1 rkujawa tdvfb_videomode_set(sc); 232 1.1 rkujawa 233 1.1 rkujawa sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 234 1.1 rkujawa "default", 235 1.1 rkujawa 0, 0, 236 1.1 rkujawa NULL, 237 1.1 rkujawa 8, 16, 238 1.1 rkujawa WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 239 1.1 rkujawa NULL 240 1.1 rkujawa }; 241 1.1 rkujawa sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 242 1.1 rkujawa sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 243 1.1 rkujawa sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 244 1.1 rkujawa 245 1.1 rkujawa vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 246 1.4 rkujawa &tdvfb_accessops); 247 1.1 rkujawa sc->vd.init_screen = tdvfb_init_screen; 248 1.1 rkujawa 249 1.1 rkujawa ri = &sc->sc_console_screen.scr_ri; 250 1.1 rkujawa 251 1.1 rkujawa tdvfb_init_palette(sc); 252 1.1 rkujawa 253 1.1 rkujawa if (console) { 254 1.1 rkujawa vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 255 1.1 rkujawa &defattr); 256 1.1 rkujawa 257 1.1 rkujawa sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC | 258 1.1 rkujawa VCONS_DONT_READ; 259 1.1 rkujawa vcons_redraw_screen(&sc->sc_console_screen); 260 1.1 rkujawa 261 1.1 rkujawa sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 262 1.1 rkujawa sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 263 1.1 rkujawa sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 264 1.1 rkujawa sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 265 1.1 rkujawa 266 1.1 rkujawa wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 267 1.1 rkujawa defattr); 268 1.1 rkujawa vcons_replay_msgbuf(&sc->sc_console_screen); 269 1.6 macallan } else { 270 1.6 macallan if (sc->sc_console_screen.scr_ri.ri_rows == 0) { 271 1.6 macallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 272 1.6 macallan &defattr); 273 1.6 macallan } else 274 1.6 macallan (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 275 1.1 rkujawa } 276 1.1 rkujawa 277 1.1 rkujawa ws_aa.console = console; 278 1.1 rkujawa ws_aa.scrdata = &sc->sc_screenlist; 279 1.4 rkujawa ws_aa.accessops = &tdvfb_accessops; 280 1.1 rkujawa ws_aa.accesscookie = &sc->vd; 281 1.1 rkujawa 282 1.10 thorpej config_found(sc->sc_dev, &ws_aa, wsemuldisplaydevprint, CFARGS_NONE); 283 1.1 rkujawa } 284 1.1 rkujawa 285 1.1 rkujawa static void 286 1.1 rkujawa tdvfb_init_palette(struct tdvfb_softc *sc) 287 1.1 rkujawa { 288 1.1 rkujawa int i, j; 289 1.1 rkujawa 290 1.1 rkujawa j = 0; 291 1.1 rkujawa for (i = 0; i < 256; i++) { 292 1.1 rkujawa sc->sc_cmap_red[i] = rasops_cmap[j]; 293 1.1 rkujawa sc->sc_cmap_green[i] = rasops_cmap[j + 1]; 294 1.1 rkujawa sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; 295 1.1 rkujawa j += 3; 296 1.1 rkujawa } 297 1.1 rkujawa } 298 1.1 rkujawa 299 1.1 rkujawa static void 300 1.1 rkujawa tdvfb_init_screen(void *cookie, struct vcons_screen *scr, int existing, 301 1.1 rkujawa long *defattr) 302 1.1 rkujawa { 303 1.1 rkujawa struct tdvfb_softc *sc = cookie; 304 1.1 rkujawa struct rasops_info *ri = &scr->scr_ri; 305 1.1 rkujawa 306 1.1 rkujawa wsfont_init(); 307 1.1 rkujawa 308 1.1 rkujawa ri->ri_depth = sc->sc_bpp; 309 1.1 rkujawa ri->ri_width = sc->sc_width; 310 1.1 rkujawa ri->ri_height = sc->sc_height; 311 1.1 rkujawa ri->ri_stride = sc->sc_linebytes; 312 1.1 rkujawa ri->ri_flg = RI_CENTER; 313 1.3 rkujawa 314 1.3 rkujawa #if BYTE_ORDER == BIG_ENDIAN 315 1.3 rkujawa #if 0 /* XXX: not yet :( */ 316 1.3 rkujawa if (sc->sc_bpp == 16) 317 1.3 rkujawa ri->ri_flg |= RI_BITSWAP; 318 1.3 rkujawa #endif 319 1.3 rkujawa #endif 320 1.3 rkujawa 321 1.5 rkujawa ri->ri_bits = (char *) bus_space_vaddr(sc->sc_cvgt, sc->sc_fbh); 322 1.5 rkujawa #ifdef TDVFB_DEBUG 323 1.5 rkujawa aprint_normal_dev(sc->sc_dev, "fb handle: %lx, ri_bits: %p\n", sc->sc_fbh, ri->ri_bits); 324 1.5 rkujawa #endif /* TDVFB_DEBUG */ 325 1.1 rkujawa 326 1.1 rkujawa scr->scr_flags |= VCONS_DONT_READ; 327 1.1 rkujawa 328 1.1 rkujawa rasops_init(ri, 0, 0); 329 1.1 rkujawa ri->ri_caps = WSSCREEN_WSCOLORS; 330 1.1 rkujawa rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 331 1.1 rkujawa sc->sc_width / ri->ri_font->fontwidth); 332 1.1 rkujawa 333 1.1 rkujawa ri->ri_hw = scr; 334 1.3 rkujawa 335 1.3 rkujawa /* If we are a Voodoo2 and running in 16 bits try to use blitter. */ 336 1.3 rkujawa if ((sc->sc_voodootype == TDV_VOODOO_2) && (sc->sc_bpp == 16)) { 337 1.3 rkujawa aprint_normal_dev(sc->sc_dev, "using CVG blitter\n"); 338 1.3 rkujawa ri->ri_ops.eraserows = tdvfb_eraserows; 339 1.3 rkujawa ri->ri_ops.copyrows = tdvfb_copyrows; 340 1.3 rkujawa } 341 1.1 rkujawa } 342 1.1 rkujawa 343 1.1 rkujawa static bool 344 1.1 rkujawa tdvfb_videomode_set(struct tdvfb_softc *sc) 345 1.1 rkujawa { 346 1.1 rkujawa uint32_t fbiinit1, fbiinit5, fbiinit6, lfbmode; 347 1.1 rkujawa uint16_t vbackporch, vsyncon, vsyncoff; 348 1.1 rkujawa uint16_t hbackporch, hsyncon, hsyncoff; 349 1.1 rkujawa uint16_t yheight, xwidth; 350 1.1 rkujawa 351 1.7 mrg fbiinit5 = fbiinit6 = 0; /* XXX gcc */ 352 1.7 mrg 353 1.1 rkujawa yheight = sc->sc_videomode->vdisplay; 354 1.1 rkujawa xwidth = sc->sc_videomode->hdisplay; 355 1.1 rkujawa 356 1.1 rkujawa vbackporch = sc->sc_videomode->vtotal - sc->sc_videomode->vsync_end; 357 1.1 rkujawa hbackporch = sc->sc_videomode->htotal - sc->sc_videomode->hsync_end; 358 1.1 rkujawa 359 1.1 rkujawa vsyncon = sc->sc_videomode->vsync_end - sc->sc_videomode->vsync_start; 360 1.1 rkujawa hsyncon = sc->sc_videomode->hsync_end - sc->sc_videomode->hsync_start; 361 1.1 rkujawa 362 1.1 rkujawa vsyncoff = sc->sc_videomode->vtotal - vsyncon; 363 1.1 rkujawa hsyncoff = sc->sc_videomode->htotal - hsyncon; 364 1.1 rkujawa #ifdef TDVFB_DEBUG 365 1.1 rkujawa aprint_normal_dev(sc->sc_dev, 366 1.1 rkujawa "xy %d %d hbp %d vbp %d, hson %d, hsoff %d, vson %d, vsoff %d\n", 367 1.1 rkujawa xwidth, yheight, hbackporch, vbackporch, hsyncon, hsyncoff, 368 1.1 rkujawa vsyncon, vsyncoff); 369 1.1 rkujawa #endif /* TDVFB_DEBUG */ 370 1.1 rkujawa 371 1.1 rkujawa sc->vid_timing = tdvfb_gendac_calc_pll(sc->sc_videomode->dot_clock); 372 1.1 rkujawa 373 1.2 rkujawa if(sc->sc_voodootype == TDV_VOODOO_2) 374 1.2 rkujawa sc->sc_x_tiles = (sc->sc_videomode->hdisplay + 63 ) / 64 * 2; 375 1.2 rkujawa else 376 1.2 rkujawa sc->sc_x_tiles = (sc->sc_videomode->hdisplay + 63 ) / 64; 377 1.1 rkujawa 378 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_NOPCMD, 0); 379 1.1 rkujawa tdvfb_wait(sc); 380 1.1 rkujawa 381 1.1 rkujawa /* enable writing to fbiinit regs, reset, disable DRAM refresh */ 382 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 383 1.1 rkujawa TDV_INITENABLE_EN_INIT); 384 1.1 rkujawa tdvfb_cvg_set(sc, TDV_OFF_FBIINIT1, TDV_FBIINIT1_VIDEO_RST); 385 1.1 rkujawa tdvfb_cvg_set(sc, TDV_OFF_FBIINIT0, TDV_FBIINIT0_FBI_RST | 386 1.1 rkujawa TDV_FBIINIT0_FIFO_RST); 387 1.1 rkujawa tdvfb_cvg_unset(sc, TDV_OFF_FBIINIT2, TDV_FBIINIT2_DRAM_REFR); 388 1.1 rkujawa tdvfb_wait(sc); 389 1.1 rkujawa 390 1.2 rkujawa /* program video timings into CVG/SST-1*/ 391 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_VDIMENSIONS, yheight << 16 | (xwidth - 1)); 392 1.2 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BACKPORCH, vbackporch << 16 | 393 1.2 rkujawa (hbackporch - 2)); 394 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_HSYNC, hsyncoff << 16 | (hsyncon - 1)); 395 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_VSYNC, vsyncoff << 16 | vsyncon); 396 1.1 rkujawa 397 1.1 rkujawa tdvfb_videomode_dac(sc); 398 1.1 rkujawa 399 1.1 rkujawa fbiinit1 = ((tdvfb_cvg_read(sc, TDV_OFF_FBIINIT1) & 400 1.1 rkujawa TDV_FBIINIT1_VIDMASK) | 401 1.1 rkujawa TDV_FBIINIT1_DR_DATA | 402 1.1 rkujawa TDV_FBIINIT1_DR_BLANKING | 403 1.1 rkujawa TDV_FBIINIT1_DR_HVSYNC | 404 1.1 rkujawa TDV_FBIINIT1_DR_DCLK | 405 1.1 rkujawa TDV_FBIINIT1_IN_VCLK_2X ); 406 1.1 rkujawa 407 1.2 rkujawa if (sc->sc_voodootype == TDV_VOODOO_2) { 408 1.2 rkujawa fbiinit1 |= ((sc->sc_x_tiles & 0x20) >> 5) 409 1.2 rkujawa << TDV_FBIINIT1_TILES_X_MSB | ((sc->sc_x_tiles & 0x1e) >> 1) 410 1.2 rkujawa << TDV_FBIINIT1_TILES_X; 411 1.2 rkujawa fbiinit6 = (sc->sc_x_tiles & 0x1) << TDV_FBIINIT6_TILES_X_LSB; 412 1.2 rkujawa } else 413 1.2 rkujawa fbiinit1 |= sc->sc_x_tiles << TDV_FBIINIT1_TILES_X; 414 1.1 rkujawa 415 1.1 rkujawa fbiinit1 |= TDV_FBIINIT1_VCLK_2X << TDV_FBIINIT1_VCLK_SRC; 416 1.1 rkujawa 417 1.2 rkujawa if (sc->sc_voodootype == TDV_VOODOO_2) { 418 1.2 rkujawa fbiinit5 = tdvfb_cvg_read(sc, TDV_OFF_FBIINIT5) 419 1.2 rkujawa & TDV_FBIINIT5_VIDMASK; 420 1.2 rkujawa if (sc->sc_videomode->flags & VID_PHSYNC) 421 1.2 rkujawa fbiinit5 |= TDV_FBIINIT5_PHSYNC; 422 1.2 rkujawa if (sc->sc_videomode->flags & VID_PVSYNC) 423 1.2 rkujawa fbiinit5 |= TDV_FBIINIT5_PVSYNC; 424 1.2 rkujawa } 425 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT1, fbiinit1); 426 1.2 rkujawa if (sc->sc_voodootype == TDV_VOODOO_2) { 427 1.2 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT6, fbiinit6); 428 1.2 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT5, fbiinit5); 429 1.2 rkujawa } 430 1.1 rkujawa tdvfb_wait(sc); 431 1.1 rkujawa 432 1.1 rkujawa /* unreset, enable DRAM refresh */ 433 1.1 rkujawa tdvfb_cvg_unset(sc, TDV_OFF_FBIINIT1, TDV_FBIINIT1_VIDEO_RST); 434 1.1 rkujawa tdvfb_cvg_unset(sc, TDV_OFF_FBIINIT0, TDV_FBIINIT0_FBI_RST | 435 1.1 rkujawa TDV_FBIINIT0_FIFO_RST); 436 1.1 rkujawa tdvfb_cvg_set(sc, TDV_OFF_FBIINIT2, TDV_FBIINIT2_DRAM_REFR); 437 1.11 andvar /* disable access to FBIINIT regs */ 438 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 439 1.1 rkujawa TDV_INITENABLE_EN_FIFO); 440 1.1 rkujawa tdvfb_wait(sc); 441 1.1 rkujawa 442 1.3 rkujawa if (sc->sc_bpp == 16) 443 1.3 rkujawa lfbmode = TDV_LFBMODE_565; 444 1.3 rkujawa else if (sc->sc_bpp == 32) 445 1.3 rkujawa lfbmode = TDV_LFBMODE_8888; 446 1.3 rkujawa else 447 1.3 rkujawa return false; 448 1.1 rkujawa 449 1.1 rkujawa #if BYTE_ORDER == BIG_ENDIAN 450 1.1 rkujawa lfbmode |= TDV_LFBMODE_BSW_WR | TDV_LFBMODE_BSW_RD; 451 1.1 rkujawa #endif 452 1.1 rkujawa 453 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_LFBMODE, lfbmode); 454 1.1 rkujawa 455 1.1 rkujawa return true; 456 1.1 rkujawa } 457 1.1 rkujawa 458 1.1 rkujawa /* 459 1.1 rkujawa * Update DAC parameters for selected video mode. 460 1.1 rkujawa */ 461 1.1 rkujawa static void 462 1.1 rkujawa tdvfb_videomode_dac(struct tdvfb_softc *sc) 463 1.1 rkujawa { 464 1.1 rkujawa uint32_t fbiinit2, fbiinit3; 465 1.1 rkujawa 466 1.1 rkujawa /* remember current FBIINIT settings */ 467 1.1 rkujawa fbiinit2 = tdvfb_cvg_read(sc, TDV_OFF_FBIINIT2); 468 1.1 rkujawa fbiinit3 = tdvfb_cvg_read(sc, TDV_OFF_FBIINIT3); 469 1.1 rkujawa 470 1.1 rkujawa /* remap DAC */ 471 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 472 1.1 rkujawa TDV_INITENABLE_EN_INIT | TDV_INITENABLE_REMAPDAC); 473 1.1 rkujawa 474 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_CMD, TDV_GENDAC_CMD_16BITS); 475 1.1 rkujawa 476 1.1 rkujawa tdvfb_gendac_set_vid_timing(sc, &(sc->vid_timing)); 477 1.1 rkujawa 478 1.1 rkujawa /* disable remapping */ 479 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 480 1.1 rkujawa TDV_INITENABLE_EN_INIT); 481 1.1 rkujawa /* restore */ 482 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT2, fbiinit2); 483 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT2, fbiinit3); 484 1.1 rkujawa } 485 1.1 rkujawa 486 1.1 rkujawa /* 487 1.1 rkujawa * Check how much memory do we have. Actually, Voodoo1/2 has separate 488 1.1 rkujawa * framebuffer and texture memory. This function only checks for framebuffer 489 1.1 rkujawa * memory. Texture memory ramains unused. 490 1.1 rkujawa */ 491 1.1 rkujawa static size_t 492 1.1 rkujawa tdvfb_mem_size(struct tdvfb_softc *sc) 493 1.1 rkujawa { 494 1.1 rkujawa size_t mem_size; 495 1.1 rkujawa uint32_t vram_test4, vram_test2; 496 1.1 rkujawa 497 1.1 rkujawa bus_space_write_4(sc->sc_cvgt, sc->sc_fbh, 0, 0x11aabbaa); 498 1.1 rkujawa bus_space_write_4(sc->sc_cvgt, sc->sc_fbh, 0x100000, 0x22aabbaa); 499 1.1 rkujawa bus_space_write_4(sc->sc_cvgt, sc->sc_fbh, 0x200000, 0x44aabbaa); 500 1.1 rkujawa 501 1.1 rkujawa vram_test4 = bus_space_read_4(sc->sc_cvgt, sc->sc_fbh, 0x400000); 502 1.1 rkujawa vram_test2 = bus_space_read_4(sc->sc_cvgt, sc->sc_fbh, 0x200000); 503 1.1 rkujawa 504 1.1 rkujawa if (vram_test4 == 0x44aabbaa) 505 1.1 rkujawa mem_size = 4*1024*1024; 506 1.1 rkujawa else if (vram_test2 == 0x22aabbaa) { 507 1.1 rkujawa mem_size = 2*1024*1024; 508 1.1 rkujawa } else 509 1.1 rkujawa mem_size = 1*1024*1024; 510 1.1 rkujawa 511 1.1 rkujawa return mem_size; 512 1.1 rkujawa } 513 1.1 rkujawa 514 1.1 rkujawa /* do the low level init of Voodoo board */ 515 1.1 rkujawa static bool 516 1.1 rkujawa tdvfb_init(struct tdvfb_softc *sc) 517 1.1 rkujawa { 518 1.1 rkujawa /* undocumented - found in glide code */ 519 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_VCLK_DISABLE_REG, 0); 520 1.1 rkujawa /* allow write to hardware initialization registers */ 521 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 522 1.1 rkujawa TDV_INITENABLE_EN_INIT); 523 1.1 rkujawa 524 1.1 rkujawa /* reset the board */ 525 1.1 rkujawa tdvfb_cvg_set(sc, TDV_OFF_FBIINIT1, TDV_FBIINIT1_VIDEO_RST); 526 1.1 rkujawa tdvfb_wait(sc); 527 1.1 rkujawa tdvfb_cvg_set(sc, TDV_OFF_FBIINIT0, TDV_FBIINIT0_FBI_RST | 528 1.1 rkujawa TDV_FBIINIT0_FIFO_RST); 529 1.1 rkujawa tdvfb_wait(sc); 530 1.1 rkujawa 531 1.1 rkujawa /* disable video RAM refresh */ 532 1.1 rkujawa tdvfb_cvg_unset(sc, TDV_OFF_FBIINIT2, TDV_FBIINIT2_DRAM_REFR); 533 1.1 rkujawa tdvfb_wait(sc); 534 1.1 rkujawa 535 1.1 rkujawa /* on voodoo1 I had to read FBIINIT2 before remapping, 536 1.1 rkujawa * otherwise weird things were happening, on v2 it works just fine */ 537 1.1 rkujawa /* tdvfb_cvg_read(sc, TDV_OFF_FBIINIT2); */ 538 1.1 rkujawa 539 1.1 rkujawa /* remap DAC */ 540 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 541 1.1 rkujawa TDV_INITENABLE_EN_INIT | TDV_INITENABLE_REMAPDAC); 542 1.1 rkujawa 543 1.1 rkujawa /* detect supported DAC, TODO: we really should support other DACs */ 544 1.1 rkujawa if(!tdvfb_gendac_detect(sc)) { 545 1.1 rkujawa aprint_error_dev(sc->sc_dev, "could not detect ICS GENDAC\n"); 546 1.1 rkujawa return false; 547 1.1 rkujawa } 548 1.1 rkujawa 549 1.2 rkujawa /* calculate PLL used to drive the chips (graphics clock) */ 550 1.2 rkujawa if(sc->sc_voodootype == TDV_VOODOO_2) 551 1.2 rkujawa sc->cvg_timing = tdvfb_gendac_calc_pll(TDV_CVG_CLK); 552 1.2 rkujawa else 553 1.2 rkujawa sc->cvg_timing = tdvfb_gendac_calc_pll(TDV_SST_CLK); 554 1.1 rkujawa 555 1.1 rkujawa /* set PLL for gfx clock */ 556 1.1 rkujawa tdvfb_gendac_set_cvg_timing(sc, &(sc->cvg_timing)); 557 1.1 rkujawa 558 1.1 rkujawa /* don't remap the DAC anymore */ 559 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 560 1.1 rkujawa TDV_INITENABLE_EN_INIT | TDV_INITENABLE_EN_FIFO); 561 1.1 rkujawa 562 1.1 rkujawa /* set FBIINIT registers to some default values that make sense */ 563 1.1 rkujawa tdvfb_fbiinit_defaults(sc); 564 1.1 rkujawa 565 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_INITENABLE_REG, 566 1.1 rkujawa TDV_INITENABLE_EN_FIFO); 567 1.1 rkujawa pci_conf_write(sc->sc_pc, sc->sc_pcitag, TDV_VCLK_ENABLE_REG, 0); 568 1.1 rkujawa 569 1.1 rkujawa return true; 570 1.1 rkujawa } 571 1.1 rkujawa 572 1.1 rkujawa static void 573 1.1 rkujawa tdvfb_fbiinit_defaults(struct tdvfb_softc *sc) 574 1.1 rkujawa { 575 1.1 rkujawa uint32_t fbiinit0, fbiinit1, fbiinit2, fbiinit3, fbiinit4, fbiinit6; 576 1.1 rkujawa 577 1.1 rkujawa fbiinit0 = TDV_FBIINIT0_VGA_PASS; /* disable VGA passthrough */ 578 1.1 rkujawa fbiinit1 = /*TDV_FBIINIT1_PCIWAIT |*/ /* one wait state for PCI write */ 579 1.1 rkujawa TDV_FBIINIT1_LFB_EN | /* enable lfb reads */ 580 1.1 rkujawa TDV_FBIINIT1_VIDEO_RST | /* video timing reset */ 581 1.1 rkujawa 10 << TDV_FBIINIT1_TILES_X | /* tiles x/horizontal */ 582 1.1 rkujawa TDV_FBIINIT1_VCLK_2X << TDV_FBIINIT1_VCLK_SRC ; 583 1.1 rkujawa 584 1.1 rkujawa fbiinit2 = TDV_FBIINIT2_SWB_ALG |/* swap buffer use DAC sync */ 585 1.1 rkujawa TDV_FBIINIT2_FAST_RAS | /* fast RAS read */ 586 1.1 rkujawa TDV_FBIINIT2_DRAM_OE | /* enable DRAM OE */ 587 1.1 rkujawa TDV_FBIINIT2_DRAM_REFR | /* enable DRAM refresh */ 588 1.1 rkujawa TDV_FBIINIT2_FIFO_RDA | /* FIFO read ahead */ 589 1.1 rkujawa TDV_FBIINIT2_DRAM_REF16 << TDV_FBIINIT2_DRAM_REFLD; /* 16 ms */ 590 1.1 rkujawa 591 1.1 rkujawa fbiinit3 = TDV_FBIINIT3_TREX_DIS; /* disable texture mapping */ 592 1.1 rkujawa 593 1.1 rkujawa fbiinit4 = /*TDV_FBIINIT4_PCIWAIT|*/ /* one wait state for PCI write */ 594 1.1 rkujawa TDV_FBIINIT4_LFB_RDA; /* lfb read ahead */ 595 1.1 rkujawa 596 1.1 rkujawa fbiinit6 = 0; 597 1.1 rkujawa #ifdef TDVFB_DEBUG 598 1.1 rkujawa aprint_normal("fbiinit: 0 %x, 1 %x, 2 %x, 3 %x, 4 %x, 6 %x\n", 599 1.1 rkujawa fbiinit0, fbiinit1, fbiinit2, fbiinit3, fbiinit4, fbiinit6); 600 1.1 rkujawa #endif /* TDVFB_DEBUG */ 601 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT0, fbiinit0); 602 1.1 rkujawa tdvfb_wait(sc); 603 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT1, fbiinit1); 604 1.1 rkujawa tdvfb_wait(sc); 605 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT2, fbiinit2); 606 1.1 rkujawa tdvfb_wait(sc); 607 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT3, fbiinit3); 608 1.1 rkujawa tdvfb_wait(sc); 609 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT4, fbiinit4); 610 1.1 rkujawa tdvfb_wait(sc); 611 1.2 rkujawa if (sc->sc_voodootype == TDV_VOODOO_2) { 612 1.2 rkujawa tdvfb_cvg_write(sc, TDV_OFF_FBIINIT6, fbiinit6); 613 1.2 rkujawa tdvfb_wait(sc); 614 1.2 rkujawa } 615 1.1 rkujawa } 616 1.1 rkujawa 617 1.1 rkujawa static void 618 1.1 rkujawa tdvfb_gendac_set_vid_timing(struct tdvfb_softc *sc, 619 1.1 rkujawa struct tdvfb_dac_timing *timing) 620 1.1 rkujawa { 621 1.1 rkujawa uint8_t pllreg; 622 1.1 rkujawa 623 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, TDV_GENDAC_PLL_CTRL); 624 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 625 1.1 rkujawa 626 1.1 rkujawa /* write the timing for gfx clock into "slot" 0 */ 627 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLWR, TDV_GENDAC_PLL_0); 628 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, timing->m); 629 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, timing->n); 630 1.1 rkujawa /* select "slot" 0 for output */ 631 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLWR, TDV_GENDAC_PLL_CTRL); 632 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, 633 1.1 rkujawa (pllreg & TDV_GENDAC_VIDPLLMASK) | TDV_GENDAC_PLL_VIDCLK | 634 1.1 rkujawa TDV_GENDAC_PLL_VIDCLK0); 635 1.1 rkujawa tdvfb_wait(sc); 636 1.1 rkujawa tdvfb_wait(sc); 637 1.1 rkujawa #ifdef TDVFB_DEBUG 638 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, TDV_GENDAC_PLL_0); 639 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 640 1.1 rkujawa aprint_normal("vid read again: %d\n", pllreg); 641 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 642 1.1 rkujawa aprint_normal("vid read again: %d\n", pllreg); 643 1.1 rkujawa #endif /* TDVFB_DEBUG */ 644 1.1 rkujawa } 645 1.1 rkujawa 646 1.1 rkujawa static void 647 1.1 rkujawa tdvfb_gendac_set_cvg_timing(struct tdvfb_softc *sc, 648 1.1 rkujawa struct tdvfb_dac_timing *timing) 649 1.1 rkujawa { 650 1.1 rkujawa uint8_t pllreg; 651 1.1 rkujawa 652 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, TDV_GENDAC_PLL_CTRL); 653 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 654 1.1 rkujawa 655 1.1 rkujawa /* write the timing for gfx clock into "slot" A */ 656 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLWR, TDV_GENDAC_PLL_A); 657 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, timing->m); 658 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, timing->n); 659 1.1 rkujawa /* select "slot" A for output */ 660 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLWR, TDV_GENDAC_PLL_CTRL); 661 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLDATA, 662 1.1 rkujawa (pllreg & TDV_GENDAC_CVGPLLMASK) | TDV_GENDAC_PLL_CVGCLKA); 663 1.1 rkujawa #ifdef TDVFB_DEBUG 664 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, TDV_GENDAC_PLL_A); 665 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 666 1.1 rkujawa aprint_normal("read again: %d\n", pllreg); 667 1.1 rkujawa pllreg = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 668 1.1 rkujawa aprint_normal("read again: %d\n", pllreg); 669 1.1 rkujawa #endif /* TDVFB_DEBUG */ 670 1.1 rkujawa tdvfb_wait(sc); 671 1.1 rkujawa } 672 1.1 rkujawa 673 1.1 rkujawa static struct tdvfb_dac_timing 674 1.1 rkujawa tdvfb_gendac_calc_pll(int freq) 675 1.1 rkujawa { 676 1.1 rkujawa int n1, n2; 677 1.1 rkujawa int m, mdbl; 678 1.1 rkujawa int best_m, best_n1, best_error; 679 1.1 rkujawa int fout; 680 1.1 rkujawa struct tdvfb_dac_timing timing; 681 1.1 rkujawa 682 1.1 rkujawa best_m = -1; best_n1 = -1; 683 1.1 rkujawa 684 1.1 rkujawa /* select highest possible n2, check n2 * fCLK < TDV_GENDAC_MAXVCO */ 685 1.1 rkujawa for (n2 = TDV_GENDAC_MAX_N2; n2 >= TDV_GENDAC_MIN_N2; n2--) { 686 1.1 rkujawa if ((freq * (1 << n2)) < TDV_GENDAC_MAXVCO) 687 1.1 rkujawa break; 688 1.1 rkujawa } 689 1.1 rkujawa 690 1.1 rkujawa best_error = freq; 691 1.1 rkujawa 692 1.1 rkujawa /* 693 1.1 rkujawa * m+2 2^n2 * fOUT 694 1.1 rkujawa * ---- = ----------- 695 1.1 rkujawa * n1+2 fREF 696 1.1 rkujawa */ 697 1.1 rkujawa for (n1 = TDV_GENDAC_MIN_N1; n1 <= TDV_GENDAC_MAX_N1; n1++) { 698 1.1 rkujawa /* loop mostly inspired by Linux driver */ 699 1.1 rkujawa mdbl = (2 * freq * (1 << n2)*(n1 + 2)) / TDV_GENDAC_REFFREQ - 4; 700 1.1 rkujawa if (mdbl % 2) 701 1.1 rkujawa m = mdbl/2+1; 702 1.1 rkujawa else 703 1.1 rkujawa m = mdbl/2; 704 1.1 rkujawa 705 1.1 rkujawa if(m > TDV_GENDAC_MAX_M) 706 1.1 rkujawa break; 707 1.1 rkujawa 708 1.1 rkujawa fout = (TDV_GENDAC_REFFREQ * (m + 2)) / ((1 << n2) * (n1 + 2)); 709 1.1 rkujawa if ((abs(fout - freq) < best_error) && (m > 0)) { 710 1.1 rkujawa best_n1 = n1; 711 1.1 rkujawa best_m = m; 712 1.1 rkujawa best_error = abs(fout - freq); 713 1.1 rkujawa if (200*best_error < freq) break; 714 1.1 rkujawa } 715 1.1 rkujawa 716 1.1 rkujawa } 717 1.1 rkujawa 718 1.1 rkujawa fout = (TDV_GENDAC_REFFREQ * (best_m + 2)) / ((1 << n2) * (best_n1 + 2)); 719 1.1 rkujawa timing.m = best_m; 720 1.1 rkujawa timing.n = (n2 << 5) | best_n1; 721 1.1 rkujawa timing.fout = fout; 722 1.1 rkujawa 723 1.1 rkujawa #ifdef TDVFB_DEBUG 724 1.1 rkujawa aprint_normal("tdvfb_gendac_calc_pll ret: m %d, n %d, fout %d kHz\n", 725 1.1 rkujawa timing.m, timing.n, timing.fout); 726 1.1 rkujawa #endif /* TDVFB_DEBUG */ 727 1.1 rkujawa 728 1.1 rkujawa return timing; 729 1.1 rkujawa } 730 1.1 rkujawa 731 1.1 rkujawa static bool 732 1.1 rkujawa tdvfb_gendac_detect(struct tdvfb_softc *sc) 733 1.1 rkujawa { 734 1.1 rkujawa uint8_t m_f1, m_f7, m_fb; 735 1.1 rkujawa uint8_t n_f1, n_f7, n_fb; 736 1.1 rkujawa 737 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, 0x1); 738 1.1 rkujawa m_f1 = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 739 1.1 rkujawa n_f1 = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 740 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, 0x7); 741 1.1 rkujawa m_f7 = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 742 1.1 rkujawa n_f7 = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 743 1.1 rkujawa tdvfb_cvg_dac_write(sc, TDV_GENDAC_PLLRD, 0xB); 744 1.1 rkujawa m_fb = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 745 1.1 rkujawa n_fb = tdvfb_cvg_dac_read(sc, TDV_GENDAC_PLLDATA); 746 1.1 rkujawa 747 1.1 rkujawa if( (m_f1 == TDV_GENDAC_DFLT_F1_M) && 748 1.1 rkujawa (n_f1 == TDV_GENDAC_DFLT_F1_N) && 749 1.1 rkujawa (m_f7 == TDV_GENDAC_DFLT_F7_M) && 750 1.1 rkujawa (n_f7 == TDV_GENDAC_DFLT_F7_N) && 751 1.7 mrg (m_fb == TDV_GENDAC_DFLT_FB_M) && 752 1.1 rkujawa (n_fb == TDV_GENDAC_DFLT_FB_N) ) { 753 1.1 rkujawa aprint_normal_dev(sc->sc_dev, "ICS 5342 GENDAC\n"); 754 1.1 rkujawa return true; 755 1.1 rkujawa } 756 1.1 rkujawa 757 1.1 rkujawa return false; 758 1.1 rkujawa } 759 1.1 rkujawa 760 1.1 rkujawa static void 761 1.1 rkujawa tdvfb_wait(struct tdvfb_softc *sc) 762 1.1 rkujawa { 763 1.1 rkujawa uint32_t x, cnt; 764 1.1 rkujawa cnt = 0; 765 1.1 rkujawa for (x = 0; x < MAXLOOP; x++) { 766 1.1 rkujawa if (tdvfb_cvg_read(sc, TDV_OFF_STATUS) & TDV_STATUS_FBI_BUSY) 767 1.1 rkujawa cnt = 0; 768 1.1 rkujawa else 769 1.1 rkujawa cnt++; 770 1.1 rkujawa 771 1.1 rkujawa if (cnt >= 5) /* Voodoo2 specs suggest at least 3 */ 772 1.1 rkujawa break; 773 1.1 rkujawa } 774 1.1 rkujawa 775 1.1 rkujawa if (x == MAXLOOP) 776 1.1 rkujawa /* 777 1.1 rkujawa * The console probably isn't working now anyway, so maybe 778 1.1 rkujawa * let's panic... At least it will drop into ddb if some other 779 1.1 rkujawa * device a console. 780 1.1 rkujawa */ 781 1.1 rkujawa panic("tdvfb is stuck!\n"); 782 1.1 rkujawa } 783 1.1 rkujawa 784 1.1 rkujawa static uint32_t 785 1.1 rkujawa tdvfb_cvg_read(struct tdvfb_softc *sc, uint32_t reg) 786 1.1 rkujawa { 787 1.1 rkujawa uint32_t rv; 788 1.1 rkujawa rv = bus_space_read_4(sc->sc_cvgt, sc->sc_cvgh, reg); 789 1.5 rkujawa #ifdef TDVFB_DEBUG_REGS 790 1.1 rkujawa aprint_normal("cvg_read val %x from reg %x\n", rv, reg); 791 1.5 rkujawa #endif /* TDVFB_DEBUG_REGS */ 792 1.1 rkujawa return rv; 793 1.1 rkujawa } 794 1.1 rkujawa 795 1.1 rkujawa static void 796 1.1 rkujawa tdvfb_cvg_write(struct tdvfb_softc *sc, uint32_t reg, uint32_t val) 797 1.1 rkujawa { 798 1.5 rkujawa #ifdef TDVFB_DEBUG_REGS 799 1.1 rkujawa aprint_normal("cvg_write val %x to reg %x\n", val, reg); 800 1.5 rkujawa #endif /* TDVFB_DEBUG_REGS */ 801 1.1 rkujawa bus_space_write_4(sc->sc_cvgt, sc->sc_cvgh, reg, val); 802 1.1 rkujawa } 803 1.1 rkujawa 804 1.1 rkujawa static void 805 1.1 rkujawa tdvfb_cvg_set(struct tdvfb_softc *sc, uint32_t reg, uint32_t bits) 806 1.1 rkujawa { 807 1.1 rkujawa uint32_t v; 808 1.1 rkujawa v = tdvfb_cvg_read(sc, reg) | bits; 809 1.1 rkujawa tdvfb_cvg_write(sc, reg, v); 810 1.1 rkujawa } 811 1.1 rkujawa 812 1.1 rkujawa static void 813 1.1 rkujawa tdvfb_cvg_unset(struct tdvfb_softc *sc, uint32_t reg, uint32_t bits) 814 1.1 rkujawa { 815 1.1 rkujawa uint32_t v; 816 1.1 rkujawa v = tdvfb_cvg_read(sc, reg) & ~bits; 817 1.1 rkujawa tdvfb_cvg_write(sc, reg, v); 818 1.1 rkujawa } 819 1.1 rkujawa 820 1.1 rkujawa static uint8_t 821 1.1 rkujawa tdvfb_cvg_dac_read(struct tdvfb_softc *sc, uint32_t reg) 822 1.1 rkujawa { 823 1.1 rkujawa uint32_t rv; 824 1.1 rkujawa 825 1.1 rkujawa tdvfb_cvg_dac_write(sc, reg, TDV_DAC_DATA_READ); 826 1.1 rkujawa 827 1.1 rkujawa rv = tdvfb_cvg_read(sc, TDV_OFF_DAC_READ); 828 1.5 rkujawa #ifdef TDVFB_DEBUG_REGS 829 1.1 rkujawa aprint_normal("cvg_dac_read val %x from reg %x\n", rv, reg); 830 1.5 rkujawa #endif /* TDVFB_DEBUG_REGS */ 831 1.1 rkujawa return rv & 0xFF; 832 1.1 rkujawa } 833 1.1 rkujawa 834 1.3 rkujawa static void 835 1.1 rkujawa tdvfb_cvg_dac_write(struct tdvfb_softc *sc, uint32_t reg, uint32_t val) 836 1.1 rkujawa { 837 1.1 rkujawa uint32_t wreg; 838 1.1 rkujawa 839 1.1 rkujawa wreg = ((reg & TDV_GENDAC_ADDRMASK) << 8) | val; 840 1.1 rkujawa 841 1.5 rkujawa #ifdef TDVFB_DEBUG_REGS 842 1.1 rkujawa aprint_normal("cvg_dac_write val %x to reg %x (%x)\n", val, reg, 843 1.1 rkujawa wreg); 844 1.5 rkujawa #endif /* TDVFB_DEBUG_REGS */ 845 1.1 rkujawa 846 1.1 rkujawa tdvfb_cvg_write(sc, TDV_OFF_DAC_DATA, wreg); 847 1.1 rkujawa tdvfb_wait(sc); 848 1.1 rkujawa } 849 1.1 rkujawa 850 1.3 rkujawa static void 851 1.3 rkujawa tdvfb_rectfill(struct tdvfb_softc *sc, int x, int y, int wi, int he, 852 1.3 rkujawa uint32_t color) 853 1.3 rkujawa { 854 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTSRC, 0); 855 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTDST, 0); 856 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTROP, TDV_BLTROP_COPY); 857 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTXYSTRIDE, 858 1.3 rkujawa sc->sc_linebytes | (sc->sc_linebytes << 16)); 859 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTDSTXY, x | (y << 16)); 860 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTSIZE, wi | (he << 16)); 861 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTCMD, TDV_BLTCMD_RECTFILL | 862 1.3 rkujawa TDV_BLTCMD_LAUNCH | TDV_BLTCMD_FMT_565 << 3 | TDV_BLTCMD_DSTTILED | 863 1.3 rkujawa TDV_BLTCMD_CLIPRECT ); 864 1.3 rkujawa tdvfb_wait(sc); 865 1.3 rkujawa } 866 1.3 rkujawa 867 1.3 rkujawa static void 868 1.3 rkujawa tdvfb_bitblt(struct tdvfb_softc *sc, int xs, int ys, int xd, int yd, int wi, 869 1.3 rkujawa int he) 870 1.3 rkujawa { 871 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTSRC, 0); 872 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTDST, 0); 873 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTROP, TDV_BLTROP_COPY); 874 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTXYSTRIDE, 875 1.3 rkujawa sc->sc_linebytes | (sc->sc_linebytes << 16)); 876 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTSRCXY, xs | (ys << 16)); 877 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTDSTXY, xd | (yd << 16)); 878 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTSIZE, wi | (he << 16)); 879 1.3 rkujawa tdvfb_cvg_write(sc, TDV_OFF_BLTCMD, TDV_BLTCMD_SCR2SCR | 880 1.3 rkujawa TDV_BLTCMD_LAUNCH | TDV_BLTCMD_FMT_565 << 3); 881 1.3 rkujawa 882 1.3 rkujawa tdvfb_wait(sc); 883 1.3 rkujawa } 884 1.3 rkujawa 885 1.3 rkujawa static void 886 1.3 rkujawa tdvfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 887 1.3 rkujawa { 888 1.3 rkujawa struct tdvfb_softc *sc; 889 1.3 rkujawa struct rasops_info *ri; 890 1.3 rkujawa struct vcons_screen *scr; 891 1.3 rkujawa int x, ys, yd, wi, he; 892 1.3 rkujawa 893 1.3 rkujawa ri = cookie; 894 1.3 rkujawa scr = ri->ri_hw; 895 1.3 rkujawa sc = scr->scr_cookie; 896 1.3 rkujawa 897 1.3 rkujawa if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 898 1.3 rkujawa x = ri->ri_xorigin; 899 1.3 rkujawa ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 900 1.3 rkujawa yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 901 1.3 rkujawa wi = ri->ri_emuwidth; 902 1.3 rkujawa he = ri->ri_font->fontheight * nrows; 903 1.3 rkujawa tdvfb_bitblt(sc, x, ys, x, yd, wi, he); 904 1.3 rkujawa } 905 1.3 rkujawa } 906 1.3 rkujawa 907 1.3 rkujawa static void 908 1.3 rkujawa tdvfb_eraserows(void *cookie, int row, int nrows, long fillattr) 909 1.3 rkujawa { 910 1.3 rkujawa 911 1.3 rkujawa struct tdvfb_softc *sc; 912 1.3 rkujawa struct rasops_info *ri; 913 1.3 rkujawa struct vcons_screen *scr; 914 1.3 rkujawa int x, y, wi, he, fg, bg, ul; 915 1.3 rkujawa 916 1.3 rkujawa ri = cookie; 917 1.3 rkujawa scr = ri->ri_hw; 918 1.3 rkujawa sc = scr->scr_cookie; 919 1.3 rkujawa 920 1.3 rkujawa if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 921 1.3 rkujawa rasops_unpack_attr(fillattr, &fg, &bg, &ul); 922 1.3 rkujawa if ((row == 0) && (nrows == ri->ri_rows)) 923 1.3 rkujawa tdvfb_rectfill(sc, 0, 0, ri->ri_width, 924 1.3 rkujawa ri->ri_height, ri->ri_devcmap[bg]); 925 1.3 rkujawa else { 926 1.3 rkujawa x = ri->ri_xorigin; 927 1.3 rkujawa y = ri->ri_yorigin + ri->ri_font->fontheight * row; 928 1.3 rkujawa wi = ri->ri_emuwidth; 929 1.3 rkujawa he = ri->ri_font->fontheight * nrows; 930 1.3 rkujawa tdvfb_rectfill(sc, x, y, wi, he, ri->ri_devcmap[bg]); 931 1.3 rkujawa } 932 1.3 rkujawa } 933 1.3 rkujawa } 934 1.3 rkujawa 935 1.4 rkujawa static int 936 1.4 rkujawa tdvfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 937 1.4 rkujawa { 938 1.4 rkujawa struct vcons_data *vd; 939 1.4 rkujawa struct tdvfb_softc *sc; 940 1.4 rkujawa struct wsdisplay_fbinfo *wsfbi; 941 1.4 rkujawa struct vcons_screen *ms; 942 1.4 rkujawa 943 1.4 rkujawa vd = v; 944 1.4 rkujawa sc = vd->cookie; 945 1.4 rkujawa ms = vd->active; 946 1.4 rkujawa 947 1.4 rkujawa switch (cmd) { 948 1.4 rkujawa case WSDISPLAYIO_GTYPE: 949 1.4 rkujawa *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 950 1.4 rkujawa return 0; 951 1.4 rkujawa 952 1.4 rkujawa case PCI_IOC_CFGREAD: 953 1.4 rkujawa case PCI_IOC_CFGWRITE: 954 1.4 rkujawa return pci_devioctl(sc->sc_pc, sc->sc_pcitag, 955 1.4 rkujawa cmd, data, flag, l); 956 1.4 rkujawa 957 1.4 rkujawa case WSDISPLAYIO_GET_BUSID: 958 1.4 rkujawa return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 959 1.4 rkujawa sc->sc_pcitag, data); 960 1.4 rkujawa 961 1.4 rkujawa case WSDISPLAYIO_GINFO: 962 1.4 rkujawa if (ms == NULL) 963 1.4 rkujawa return ENODEV; 964 1.4 rkujawa 965 1.4 rkujawa wsfbi = (void*) data; 966 1.4 rkujawa wsfbi->height = ms->scr_ri.ri_height; 967 1.4 rkujawa wsfbi->width = ms->scr_ri.ri_width; 968 1.4 rkujawa wsfbi->depth = ms->scr_ri.ri_depth; 969 1.4 rkujawa wsfbi->cmsize = 256; 970 1.4 rkujawa return 0; 971 1.4 rkujawa 972 1.4 rkujawa case WSDISPLAYIO_LINEBYTES: 973 1.4 rkujawa *(u_int*)data = sc->sc_linebytes; 974 1.4 rkujawa return 0; 975 1.4 rkujawa 976 1.4 rkujawa case WSDISPLAYIO_SMODE: 977 1.4 rkujawa { 978 1.4 rkujawa int new_mode = *(int*)data; 979 1.4 rkujawa if (new_mode != sc->sc_mode) { 980 1.4 rkujawa sc->sc_mode = new_mode; 981 1.4 rkujawa if(new_mode == WSDISPLAYIO_MODE_EMUL) 982 1.4 rkujawa vcons_redraw_screen(ms); 983 1.4 rkujawa } 984 1.4 rkujawa return 0; 985 1.4 rkujawa } 986 1.5 rkujawa case WSDISPLAYIO_GET_FBINFO: 987 1.5 rkujawa { 988 1.5 rkujawa struct wsdisplayio_fbinfo *fbi = data; 989 1.5 rkujawa struct rasops_info *ri; 990 1.5 rkujawa int ret; 991 1.5 rkujawa 992 1.5 rkujawa ri = &sc->vd.active->scr_ri; 993 1.5 rkujawa ret = wsdisplayio_get_fbinfo(ri, fbi); 994 1.5 rkujawa return ret; 995 1.5 rkujawa } 996 1.4 rkujawa } 997 1.4 rkujawa return EPASSTHROUGH; 998 1.4 rkujawa } 999 1.4 rkujawa 1000 1.4 rkujawa static paddr_t 1001 1.4 rkujawa tdvfb_mmap(void *v, void *vs, off_t offset, int prot) 1002 1.4 rkujawa { 1003 1.4 rkujawa struct vcons_data *vd; 1004 1.4 rkujawa struct tdvfb_softc *sc; 1005 1.4 rkujawa paddr_t pa; 1006 1.4 rkujawa 1007 1.4 rkujawa vd = v; 1008 1.4 rkujawa sc = vd->cookie; 1009 1.4 rkujawa 1010 1.4 rkujawa if (offset < sc->sc_memsize) { 1011 1.4 rkujawa pa = bus_space_mmap(sc->sc_cvgt, sc->sc_fbh + offset, 0, prot, 1012 1.4 rkujawa BUS_SPACE_MAP_LINEAR); 1013 1.4 rkujawa return pa; 1014 1.4 rkujawa } 1015 1.4 rkujawa 1016 1.4 rkujawa return -1; 1017 1.4 rkujawa } 1018 1.4 rkujawa 1019