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