1 1.14 macallan /* $NetBSD: pm3fb.c,v 1.14 2025/06/16 08:39:01 macallan Exp $ */ 2 1.8 andvar 3 1.1 macallan /* 4 1.1 macallan * Copyright (c) 2015 Naruaki Etomi 5 1.1 macallan * All rights reserved. 6 1.1 macallan * 7 1.1 macallan * Redistribution and use in source and binary forms, with or without 8 1.1 macallan * modification, are permitted provided that the following conditions 9 1.1 macallan * are met: 10 1.1 macallan * 1. Redistributions of source code must retain the above copyright 11 1.1 macallan * notice, this list of conditions and the following disclaimer. 12 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 macallan * notice, this list of conditions and the following disclaimer in the 14 1.1 macallan * documentation and/or other materials provided with the distribution. 15 1.1 macallan * 16 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 macallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 macallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 macallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 macallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 macallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 macallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 macallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 macallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 macallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 macallan */ 27 1.1 macallan 28 1.1 macallan /* 29 1.1 macallan * A console driver for Permedia 3 graphics controllers 30 1.1 macallan * most of the following was adapted from the xf86-video-glint driver's 31 1.1 macallan * pm3_accel.c, pm3_dac.c and pm2fb framebuffer console driver 32 1.1 macallan */ 33 1.1 macallan 34 1.8 andvar #include <sys/cdefs.h> 35 1.14 macallan __KERNEL_RCSID(0, "$NetBSD: pm3fb.c,v 1.14 2025/06/16 08:39:01 macallan Exp $"); 36 1.8 andvar 37 1.1 macallan #include <sys/param.h> 38 1.1 macallan #include <sys/systm.h> 39 1.1 macallan #include <sys/kernel.h> 40 1.1 macallan #include <sys/device.h> 41 1.1 macallan #include <sys/lwp.h> 42 1.1 macallan #include <sys/kauth.h> 43 1.1 macallan #include <sys/atomic.h> 44 1.1 macallan 45 1.1 macallan #include <dev/videomode/videomode.h> 46 1.1 macallan 47 1.1 macallan #include <dev/pci/pcivar.h> 48 1.1 macallan #include <dev/pci/pcireg.h> 49 1.1 macallan #include <dev/pci/pcidevs.h> 50 1.1 macallan #include <dev/pci/pciio.h> 51 1.1 macallan #include <dev/pci/pm3reg.h> 52 1.1 macallan 53 1.1 macallan #include <dev/wscons/wsdisplayvar.h> 54 1.1 macallan #include <dev/wscons/wsconsio.h> 55 1.1 macallan #include <dev/wsfont/wsfont.h> 56 1.1 macallan #include <dev/rasops/rasops.h> 57 1.1 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 58 1.12 macallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 59 1.1 macallan #include <dev/pci/wsdisplay_pci.h> 60 1.1 macallan 61 1.1 macallan #include <dev/i2c/i2cvar.h> 62 1.1 macallan #include <dev/i2c/i2c_bitbang.h> 63 1.1 macallan #include <dev/i2c/ddcvar.h> 64 1.1 macallan #include <dev/videomode/videomode.h> 65 1.1 macallan #include <dev/videomode/edidvar.h> 66 1.1 macallan #include <dev/videomode/edidreg.h> 67 1.1 macallan 68 1.13 macallan #include "opt_pm3fb.h" 69 1.13 macallan 70 1.1 macallan struct pm3fb_softc { 71 1.1 macallan device_t sc_dev; 72 1.1 macallan 73 1.1 macallan pci_chipset_tag_t sc_pc; 74 1.1 macallan pcitag_t sc_pcitag; 75 1.1 macallan 76 1.1 macallan bus_space_tag_t sc_memt; 77 1.1 macallan bus_space_tag_t sc_iot; 78 1.1 macallan 79 1.1 macallan bus_space_handle_t sc_regh; 80 1.1 macallan bus_addr_t sc_fb, sc_reg; 81 1.1 macallan bus_size_t sc_fbsize, sc_regsize; 82 1.1 macallan 83 1.1 macallan int sc_width, sc_height, sc_depth, sc_stride; 84 1.1 macallan int sc_locked; 85 1.1 macallan struct vcons_screen sc_console_screen; 86 1.1 macallan struct wsscreen_descr sc_defaultscreen_descr; 87 1.1 macallan const struct wsscreen_descr *sc_screens[1]; 88 1.1 macallan struct wsscreen_list sc_screenlist; 89 1.1 macallan struct vcons_data vd; 90 1.1 macallan int sc_mode; 91 1.1 macallan u_char sc_cmap_red[256]; 92 1.1 macallan u_char sc_cmap_green[256]; 93 1.1 macallan u_char sc_cmap_blue[256]; 94 1.1 macallan /* i2c stuff */ 95 1.1 macallan struct i2c_controller sc_i2c; 96 1.1 macallan uint8_t sc_edid_data[128]; 97 1.1 macallan struct edid_info sc_ei; 98 1.1 macallan const struct videomode *sc_videomode; 99 1.12 macallan glyphcache sc_gc; 100 1.1 macallan }; 101 1.1 macallan 102 1.1 macallan static int pm3fb_match(device_t, cfdata_t, void *); 103 1.1 macallan static void pm3fb_attach(device_t, device_t, void *); 104 1.1 macallan 105 1.1 macallan CFATTACH_DECL_NEW(pm3fb, sizeof(struct pm3fb_softc), 106 1.1 macallan pm3fb_match, pm3fb_attach, NULL, NULL); 107 1.1 macallan 108 1.1 macallan extern const u_char rasops_cmap[768]; 109 1.1 macallan 110 1.1 macallan static int pm3fb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 111 1.1 macallan static paddr_t pm3fb_mmap(void *, void *, off_t, int); 112 1.1 macallan static void pm3fb_init_screen(void *, struct vcons_screen *, int, long *); 113 1.1 macallan 114 1.1 macallan static int pm3fb_putcmap(struct pm3fb_softc *, struct wsdisplay_cmap *); 115 1.1 macallan static int pm3fb_getcmap(struct pm3fb_softc *, struct wsdisplay_cmap *); 116 1.1 macallan static void pm3fb_init_palette(struct pm3fb_softc *); 117 1.1 macallan static int pm3fb_putpalreg(struct pm3fb_softc *, uint8_t, uint8_t, uint8_t, uint8_t); 118 1.1 macallan 119 1.1 macallan static void pm3fb_init(struct pm3fb_softc *); 120 1.1 macallan static inline void pm3fb_wait(struct pm3fb_softc *, int); 121 1.1 macallan static void pm3fb_flush_engine(struct pm3fb_softc *); 122 1.1 macallan static void pm3fb_rectfill(struct pm3fb_softc *, int, int, int, int, uint32_t); 123 1.12 macallan static void pm3fb_rectfill_a(void *, int, int, int, int, long); 124 1.1 macallan static void pm3fb_bitblt(void *, int, int, int, int, int, int, int); 125 1.1 macallan 126 1.1 macallan static void pm3fb_cursor(void *, int, int, int); 127 1.1 macallan static void pm3fb_putchar(void *, int, int, u_int, long); 128 1.12 macallan static void pm3fb_putchar_aa(void *, int, int, u_int, long); 129 1.1 macallan static void pm3fb_copycols(void *, int, int, int, int); 130 1.1 macallan static void pm3fb_erasecols(void *, int, int, int, long); 131 1.1 macallan static void pm3fb_copyrows(void *, int, int, int); 132 1.1 macallan static void pm3fb_eraserows(void *, int, int, long); 133 1.1 macallan 134 1.1 macallan struct wsdisplay_accessops pm3fb_accessops = { 135 1.1 macallan pm3fb_ioctl, 136 1.1 macallan pm3fb_mmap, 137 1.1 macallan NULL, /* alloc_screen */ 138 1.1 macallan NULL, /* free_screen */ 139 1.1 macallan NULL, /* show_screen */ 140 1.1 macallan NULL, /* load_font */ 141 1.1 macallan NULL, /* pollc */ 142 1.1 macallan NULL /* scroll */ 143 1.1 macallan }; 144 1.1 macallan 145 1.1 macallan /* I2C glue */ 146 1.1 macallan static int pm3fb_i2c_send_start(void *, int); 147 1.1 macallan static int pm3fb_i2c_send_stop(void *, int); 148 1.1 macallan static int pm3fb_i2c_initiate_xfer(void *, i2c_addr_t, int); 149 1.1 macallan static int pm3fb_i2c_read_byte(void *, uint8_t *, int); 150 1.1 macallan static int pm3fb_i2c_write_byte(void *, uint8_t, int); 151 1.1 macallan 152 1.1 macallan /* I2C bitbang glue */ 153 1.1 macallan static void pm3fb_i2cbb_set_bits(void *, uint32_t); 154 1.1 macallan static void pm3fb_i2cbb_set_dir(void *, uint32_t); 155 1.1 macallan static uint32_t pm3fb_i2cbb_read(void *); 156 1.1 macallan 157 1.1 macallan static void pm3_setup_i2c(struct pm3fb_softc *); 158 1.1 macallan 159 1.1 macallan static const struct i2c_bitbang_ops pm3fb_i2cbb_ops = { 160 1.1 macallan pm3fb_i2cbb_set_bits, 161 1.1 macallan pm3fb_i2cbb_set_dir, 162 1.1 macallan pm3fb_i2cbb_read, 163 1.1 macallan { 164 1.1 macallan PM3_DD_SDA_IN, 165 1.1 macallan PM3_DD_SCL_IN, 166 1.1 macallan 0, 167 1.1 macallan 0 168 1.1 macallan } 169 1.1 macallan }; 170 1.1 macallan 171 1.1 macallan /* mode setting stuff */ 172 1.1 macallan static int pm3fb_set_pll(struct pm3fb_softc *, int); 173 1.1 macallan static void pm3fb_write_dac(struct pm3fb_softc *, int, uint8_t); 174 1.1 macallan static void pm3fb_set_mode(struct pm3fb_softc *, const struct videomode *); 175 1.1 macallan 176 1.1 macallan static inline void 177 1.1 macallan pm3fb_wait(struct pm3fb_softc *sc, int slots) 178 1.1 macallan { 179 1.1 macallan uint32_t reg; 180 1.1 macallan 181 1.1 macallan do { 182 1.1 macallan reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, 183 1.1 macallan PM3_INPUT_FIFO_SPACE); 184 1.1 macallan } while (reg <= slots); 185 1.1 macallan } 186 1.1 macallan 187 1.1 macallan static void 188 1.1 macallan pm3fb_flush_engine(struct pm3fb_softc *sc) 189 1.1 macallan { 190 1.1 macallan 191 1.1 macallan pm3fb_wait(sc, 2); 192 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FILTER_MODE, PM3_FM_PASS_SYNC); 193 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SYNC, 0); 194 1.1 macallan 195 1.1 macallan do { 196 1.1 macallan while (bus_space_read_4(sc->sc_memt, sc->sc_regh, PM3_OUTPUT_FIFO_WORDS) == 0); 197 1.1 macallan } while (bus_space_read_4(sc->sc_memt, sc->sc_regh, PM3_OUTPUT_FIFO) != 198 1.1 macallan PM3_SYNC_TAG); 199 1.1 macallan } 200 1.1 macallan 201 1.1 macallan static int 202 1.1 macallan pm3fb_match(device_t parent, cfdata_t match, void *aux) 203 1.1 macallan { 204 1.1 macallan struct pci_attach_args *pa = (struct pci_attach_args *)aux; 205 1.1 macallan 206 1.1 macallan if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) 207 1.1 macallan return 0; 208 1.1 macallan if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_3DLABS) 209 1.1 macallan return 0; 210 1.1 macallan 211 1.1 macallan if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3DLABS_PERMEDIA3) 212 1.1 macallan return 100; 213 1.1 macallan return (0); 214 1.1 macallan } 215 1.1 macallan 216 1.1 macallan static void 217 1.1 macallan pm3fb_attach(device_t parent, device_t self, void *aux) 218 1.1 macallan { 219 1.1 macallan struct pm3fb_softc *sc = device_private(self); 220 1.1 macallan struct pci_attach_args *pa = aux; 221 1.1 macallan struct rasops_info *ri; 222 1.1 macallan struct wsemuldisplaydev_attach_args aa; 223 1.1 macallan prop_dictionary_t dict; 224 1.1 macallan unsigned long defattr; 225 1.1 macallan bool is_console; 226 1.1 macallan uint32_t flags; 227 1.1 macallan 228 1.1 macallan sc->sc_pc = pa->pa_pc; 229 1.1 macallan sc->sc_pcitag = pa->pa_tag; 230 1.1 macallan sc->sc_memt = pa->pa_memt; 231 1.1 macallan sc->sc_iot = pa->pa_iot; 232 1.1 macallan sc->sc_dev = self; 233 1.1 macallan 234 1.1 macallan pci_aprint_devinfo(pa, NULL); 235 1.1 macallan 236 1.1 macallan /* 237 1.1 macallan * fill in parameters from properties 238 1.1 macallan * if we can't get a usable mode via DDC2 we'll use this to pick one, 239 1.1 macallan * which is why we fill them in with some conservative values that 240 1.1 macallan * hopefully work as a last resort 241 1.1 macallan */ 242 1.1 macallan dict = device_properties(self); 243 1.1 macallan if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { 244 1.1 macallan aprint_error("%s: no width property\n", device_xname(self)); 245 1.1 macallan sc->sc_width = 1280; 246 1.1 macallan } 247 1.1 macallan if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) { 248 1.1 macallan aprint_error("%s: no height property\n", device_xname(self)); 249 1.1 macallan sc->sc_height = 1024; 250 1.1 macallan } 251 1.1 macallan if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) { 252 1.1 macallan aprint_error("%s: no depth property\n", device_xname(self)); 253 1.1 macallan sc->sc_depth = 8; 254 1.1 macallan } 255 1.1 macallan 256 1.1 macallan sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3); 257 1.1 macallan 258 1.1 macallan prop_dictionary_get_bool(dict, "is_console", &is_console); 259 1.1 macallan 260 1.1 macallan pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x14, PCI_MAPREG_TYPE_MEM, 261 1.1 macallan &sc->sc_fb, &sc->sc_fbsize, &flags); 262 1.1 macallan 263 1.1 macallan if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, 264 1.1 macallan &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) { 265 1.1 macallan aprint_error("%s: failed to map registers.\n", 266 1.1 macallan device_xname(sc->sc_dev)); 267 1.1 macallan } 268 1.1 macallan 269 1.1 macallan /* 270 1.1 macallan * Permedia 3 always return 64MB fbsize 271 1.1 macallan * 16 MB should be enough -- more just wastes map entries 272 1.1 macallan */ 273 1.1 macallan if (sc->sc_fbsize != 0) 274 1.1 macallan sc->sc_fbsize = (16 << 20); 275 1.1 macallan 276 1.1 macallan /* 277 1.1 macallan * Some Power Mac G4 model could not initialize these registers, 278 1.1 macallan * Power Mac G4 (Mirrored Drive Doors), for example 279 1.1 macallan */ 280 1.1 macallan #if defined(__powerpc__) 281 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LOCALMEMCAPS, 0x02e311B8); 282 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LOCALMEMTIMINGS, 0x07424905); 283 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LOCALMEMCONTROL, 0x0c000003); 284 1.1 macallan #endif 285 1.1 macallan 286 1.1 macallan aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self), 287 1.1 macallan (int)(sc->sc_fbsize >> 20), (uint32_t)sc->sc_fb); 288 1.1 macallan 289 1.1 macallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 290 1.1 macallan "default", 291 1.1 macallan 0, 0, 292 1.1 macallan NULL, 293 1.1 macallan 8, 16, 294 1.1 macallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 295 1.1 macallan NULL 296 1.1 macallan }; 297 1.1 macallan 298 1.1 macallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 299 1.1 macallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 300 1.1 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 301 1.1 macallan sc->sc_locked = 0; 302 1.1 macallan 303 1.1 macallan pm3_setup_i2c(sc); 304 1.1 macallan 305 1.12 macallan #ifdef PM3FB_DEBUG 306 1.12 macallan sc->sc_height -= 200; 307 1.12 macallan #endif 308 1.12 macallan 309 1.1 macallan vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 310 1.1 macallan &pm3fb_accessops); 311 1.1 macallan 312 1.1 macallan sc->vd.init_screen = pm3fb_init_screen; 313 1.12 macallan sc->vd.show_screen_cookie = &sc->sc_gc; 314 1.12 macallan sc->vd.show_screen_cb = glyphcache_adapt; 315 1.1 macallan 316 1.1 macallan /* init engine here */ 317 1.1 macallan pm3fb_init(sc); 318 1.1 macallan 319 1.12 macallan sc->sc_gc.gc_bitblt = pm3fb_bitblt; 320 1.12 macallan sc->sc_gc.gc_rectfill = pm3fb_rectfill_a; 321 1.12 macallan sc->sc_gc.gc_blitcookie = sc; 322 1.12 macallan sc->sc_gc.gc_rop = 3; 323 1.12 macallan 324 1.1 macallan ri = &sc->sc_console_screen.scr_ri; 325 1.1 macallan 326 1.10 macallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 327 1.10 macallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 328 1.10 macallan 329 1.10 macallan pm3fb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 330 1.10 macallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 331 1.10 macallan pm3fb_init_palette(sc); 332 1.10 macallan 333 1.10 macallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 334 1.10 macallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 335 1.10 macallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 336 1.10 macallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 337 1.10 macallan 338 1.12 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 339 1.12 macallan uimin(2047, (sc->sc_fbsize / sc->sc_stride)) 340 1.12 macallan - sc->sc_height - 5, 341 1.12 macallan sc->sc_width, 342 1.12 macallan ri->ri_font->fontwidth, 343 1.12 macallan ri->ri_font->fontheight, 344 1.12 macallan defattr); 345 1.12 macallan 346 1.1 macallan if (is_console) { 347 1.1 macallan 348 1.1 macallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 349 1.1 macallan defattr); 350 1.1 macallan vcons_replay_msgbuf(&sc->sc_console_screen); 351 1.1 macallan } 352 1.1 macallan 353 1.1 macallan 354 1.1 macallan aa.console = is_console; 355 1.1 macallan aa.scrdata = &sc->sc_screenlist; 356 1.1 macallan aa.accessops = &pm3fb_accessops; 357 1.1 macallan aa.accesscookie = &sc->vd; 358 1.1 macallan 359 1.7 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 360 1.1 macallan } 361 1.1 macallan 362 1.1 macallan static int 363 1.1 macallan pm3fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 364 1.1 macallan struct lwp *l) 365 1.1 macallan { 366 1.1 macallan struct vcons_data *vd = v; 367 1.1 macallan struct pm3fb_softc *sc = vd->cookie; 368 1.1 macallan struct wsdisplay_fbinfo *wdf; 369 1.1 macallan struct vcons_screen *ms = vd->active; 370 1.1 macallan 371 1.1 macallan switch (cmd) { 372 1.1 macallan case WSDISPLAYIO_GTYPE: 373 1.1 macallan *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 374 1.1 macallan return 0; 375 1.1 macallan 376 1.1 macallan /* PCI config read/write passthrough. */ 377 1.1 macallan case PCI_IOC_CFGREAD: 378 1.1 macallan case PCI_IOC_CFGWRITE: 379 1.1 macallan return pci_devioctl(sc->sc_pc, sc->sc_pcitag, 380 1.1 macallan cmd, data, flag, l); 381 1.1 macallan 382 1.1 macallan case WSDISPLAYIO_GET_BUSID: 383 1.1 macallan return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 384 1.1 macallan sc->sc_pcitag, data); 385 1.1 macallan 386 1.1 macallan case WSDISPLAYIO_GINFO: 387 1.1 macallan if (ms == NULL) 388 1.1 macallan return ENODEV; 389 1.1 macallan wdf = (void *)data; 390 1.1 macallan wdf->height = ms->scr_ri.ri_height; 391 1.1 macallan wdf->width = ms->scr_ri.ri_width; 392 1.1 macallan wdf->depth = ms->scr_ri.ri_depth; 393 1.1 macallan wdf->cmsize = 256; 394 1.1 macallan return 0; 395 1.1 macallan 396 1.1 macallan case WSDISPLAYIO_GETCMAP: 397 1.1 macallan return pm3fb_getcmap(sc, 398 1.1 macallan (struct wsdisplay_cmap *)data); 399 1.1 macallan 400 1.1 macallan case WSDISPLAYIO_PUTCMAP: 401 1.1 macallan return pm3fb_putcmap(sc, 402 1.1 macallan (struct wsdisplay_cmap *)data); 403 1.1 macallan 404 1.1 macallan case WSDISPLAYIO_LINEBYTES: 405 1.1 macallan *(u_int *)data = sc->sc_stride; 406 1.1 macallan return 0; 407 1.1 macallan 408 1.1 macallan case WSDISPLAYIO_SMODE: { 409 1.1 macallan int new_mode = *(int*)data; 410 1.1 macallan if (new_mode != sc->sc_mode) { 411 1.1 macallan sc->sc_mode = new_mode; 412 1.1 macallan if(new_mode == WSDISPLAYIO_MODE_EMUL) { 413 1.1 macallan /* first set the video mode */ 414 1.1 macallan if (sc->sc_videomode != NULL) { 415 1.1 macallan pm3fb_set_mode(sc, sc->sc_videomode); 416 1.1 macallan } 417 1.1 macallan /* then initialize the drawing engine */ 418 1.1 macallan pm3fb_init(sc); 419 1.1 macallan pm3fb_init_palette(sc); 420 1.13 macallan /* clean out the glyph cache */ 421 1.13 macallan glyphcache_wipe(&sc->sc_gc); 422 1.1 macallan vcons_redraw_screen(ms); 423 1.1 macallan } else 424 1.1 macallan pm3fb_flush_engine(sc); 425 1.1 macallan } 426 1.1 macallan } 427 1.1 macallan return 0; 428 1.1 macallan case WSDISPLAYIO_GET_EDID: { 429 1.1 macallan struct wsdisplayio_edid_info *d = data; 430 1.1 macallan d->data_size = 128; 431 1.1 macallan if (d->buffer_size < 128) 432 1.1 macallan return EAGAIN; 433 1.1 macallan return copyout(sc->sc_edid_data, d->edid_data, 128); 434 1.1 macallan } 435 1.1 macallan 436 1.1 macallan case WSDISPLAYIO_GET_FBINFO: { 437 1.1 macallan struct wsdisplayio_fbinfo *fbi = data; 438 1.1 macallan return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 439 1.1 macallan } 440 1.1 macallan } 441 1.1 macallan return EPASSTHROUGH; 442 1.1 macallan } 443 1.1 macallan 444 1.1 macallan static paddr_t 445 1.1 macallan pm3fb_mmap(void *v, void *vs, off_t offset, int prot) 446 1.1 macallan { 447 1.1 macallan struct vcons_data *vd = v; 448 1.1 macallan struct pm3fb_softc *sc = vd->cookie; 449 1.1 macallan paddr_t pa; 450 1.1 macallan 451 1.1 macallan /* 'regular' framebuffer mmap()ing */ 452 1.1 macallan if (offset < sc->sc_fbsize) { 453 1.1 macallan pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot, 454 1.2 macallan BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE); 455 1.1 macallan return pa; 456 1.1 macallan } 457 1.1 macallan 458 1.1 macallan /* 459 1.1 macallan * restrict all other mappings to processes with superuser privileges 460 1.1 macallan * or the kernel itself 461 1.1 macallan */ 462 1.1 macallan if (kauth_authorize_machdep(kauth_cred_get(), 463 1.1 macallan KAUTH_MACHDEP_UNMANAGEDMEM, 464 1.1 macallan NULL, NULL, NULL, NULL) != 0) { 465 1.1 macallan aprint_normal("%s: mmap() rejected.\n", 466 1.1 macallan device_xname(sc->sc_dev)); 467 1.1 macallan return -1; 468 1.1 macallan } 469 1.1 macallan 470 1.1 macallan if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) { 471 1.1 macallan pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 472 1.2 macallan BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE); 473 1.1 macallan return pa; 474 1.1 macallan } 475 1.1 macallan 476 1.1 macallan if ((offset >= sc->sc_reg) && 477 1.1 macallan (offset < (sc->sc_reg + sc->sc_regsize))) { 478 1.1 macallan pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 479 1.1 macallan BUS_SPACE_MAP_LINEAR); 480 1.1 macallan return pa; 481 1.1 macallan } 482 1.1 macallan 483 1.1 macallan #ifdef PCI_MAGIC_IO_RANGE 484 1.1 macallan /* allow mapping of IO space */ 485 1.1 macallan if ((offset >= PCI_MAGIC_IO_RANGE) && 486 1.1 macallan (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { 487 1.1 macallan pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, 488 1.1 macallan 0, prot, BUS_SPACE_MAP_LINEAR); 489 1.1 macallan return pa; 490 1.1 macallan } 491 1.1 macallan #endif 492 1.1 macallan return -1; 493 1.1 macallan } 494 1.1 macallan 495 1.1 macallan static void 496 1.1 macallan pm3fb_init_screen(void *cookie, struct vcons_screen *scr, 497 1.1 macallan int existing, long *defattr) 498 1.1 macallan { 499 1.1 macallan struct pm3fb_softc *sc = cookie; 500 1.1 macallan struct rasops_info *ri = &scr->scr_ri; 501 1.1 macallan 502 1.1 macallan ri->ri_depth = sc->sc_depth; 503 1.1 macallan ri->ri_width = sc->sc_width; 504 1.1 macallan ri->ri_height = sc->sc_height; 505 1.1 macallan ri->ri_stride = sc->sc_stride; 506 1.14 macallan ri->ri_flg = RI_CENTER | RI_ENABLE_ALPHA | RI_FULLCLEAR; 507 1.1 macallan if (sc->sc_depth == 8) 508 1.1 macallan ri->ri_flg |= RI_8BIT_IS_RGB; 509 1.1 macallan 510 1.12 macallan scr->scr_flags |= VCONS_LOADFONT; 511 1.12 macallan 512 1.1 macallan rasops_init(ri, 0, 0); 513 1.12 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | WSSCREEN_RESIZE; 514 1.1 macallan 515 1.1 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 516 1.1 macallan sc->sc_width / ri->ri_font->fontwidth); 517 1.1 macallan 518 1.1 macallan ri->ri_hw = scr; 519 1.1 macallan ri->ri_ops.copyrows = pm3fb_copyrows; 520 1.1 macallan ri->ri_ops.copycols = pm3fb_copycols; 521 1.1 macallan ri->ri_ops.cursor = pm3fb_cursor; 522 1.1 macallan ri->ri_ops.eraserows = pm3fb_eraserows; 523 1.1 macallan ri->ri_ops.erasecols = pm3fb_erasecols; 524 1.12 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 525 1.12 macallan ri->ri_ops.putchar = pm3fb_putchar_aa; 526 1.12 macallan } else 527 1.12 macallan ri->ri_ops.putchar = pm3fb_putchar; 528 1.1 macallan } 529 1.1 macallan 530 1.1 macallan static int 531 1.1 macallan pm3fb_putcmap(struct pm3fb_softc *sc, struct wsdisplay_cmap *cm) 532 1.1 macallan { 533 1.1 macallan u_char *r, *g, *b; 534 1.1 macallan u_int index = cm->index; 535 1.1 macallan u_int count = cm->count; 536 1.1 macallan int i, error; 537 1.1 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 538 1.1 macallan 539 1.1 macallan if (cm->index >= 256 || cm->count > 256 || 540 1.1 macallan (cm->index + cm->count) > 256) 541 1.1 macallan return EINVAL; 542 1.1 macallan error = copyin(cm->red, &rbuf[index], count); 543 1.1 macallan if (error) 544 1.1 macallan return error; 545 1.1 macallan error = copyin(cm->green, &gbuf[index], count); 546 1.1 macallan if (error) 547 1.1 macallan return error; 548 1.1 macallan error = copyin(cm->blue, &bbuf[index], count); 549 1.1 macallan if (error) 550 1.1 macallan return error; 551 1.1 macallan 552 1.1 macallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 553 1.1 macallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 554 1.1 macallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 555 1.1 macallan 556 1.1 macallan r = &sc->sc_cmap_red[index]; 557 1.1 macallan g = &sc->sc_cmap_green[index]; 558 1.1 macallan b = &sc->sc_cmap_blue[index]; 559 1.1 macallan 560 1.1 macallan for (i = 0; i < count; i++) { 561 1.1 macallan pm3fb_putpalreg(sc, index, *r, *g, *b); 562 1.1 macallan index++; 563 1.1 macallan r++, g++, b++; 564 1.1 macallan } 565 1.1 macallan return 0; 566 1.1 macallan } 567 1.1 macallan 568 1.1 macallan static int 569 1.1 macallan pm3fb_getcmap(struct pm3fb_softc *sc, struct wsdisplay_cmap *cm) 570 1.1 macallan { 571 1.1 macallan u_int index = cm->index; 572 1.1 macallan u_int count = cm->count; 573 1.1 macallan int error; 574 1.1 macallan 575 1.1 macallan if (index >= 255 || count > 256 || index + count > 256) 576 1.1 macallan return EINVAL; 577 1.1 macallan 578 1.1 macallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 579 1.1 macallan if (error) 580 1.1 macallan return error; 581 1.1 macallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 582 1.1 macallan if (error) 583 1.1 macallan return error; 584 1.1 macallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 585 1.1 macallan if (error) 586 1.1 macallan return error; 587 1.1 macallan 588 1.1 macallan return 0; 589 1.1 macallan } 590 1.1 macallan 591 1.1 macallan static void 592 1.1 macallan pm3fb_init_palette(struct pm3fb_softc *sc) 593 1.1 macallan { 594 1.1 macallan struct rasops_info *ri = &sc->sc_console_screen.scr_ri; 595 1.1 macallan int i, j = 0; 596 1.1 macallan uint8_t cmap[768]; 597 1.1 macallan 598 1.1 macallan rasops_get_cmap(ri, cmap, sizeof(cmap)); 599 1.1 macallan 600 1.1 macallan for (i = 0; i < 256; i++) { 601 1.1 macallan sc->sc_cmap_red[i] = cmap[j]; 602 1.1 macallan sc->sc_cmap_green[i] = cmap[j + 1]; 603 1.1 macallan sc->sc_cmap_blue[i] = cmap[j + 2]; 604 1.1 macallan pm3fb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 605 1.1 macallan j += 3; 606 1.1 macallan } 607 1.1 macallan } 608 1.1 macallan 609 1.1 macallan static int 610 1.1 macallan pm3fb_putpalreg(struct pm3fb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, uint8_t b) 611 1.1 macallan { 612 1.1 macallan 613 1.1 macallan pm3fb_wait(sc, 4); 614 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_PAL_WRITE_IDX, idx); 615 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_PAL_DATA, r); 616 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_PAL_DATA, g); 617 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_PAL_DATA, b); 618 1.1 macallan return 0; 619 1.1 macallan } 620 1.1 macallan 621 1.1 macallan static void 622 1.1 macallan pm3fb_write_dac(struct pm3fb_softc *sc, int reg, uint8_t data) 623 1.1 macallan { 624 1.1 macallan 625 1.1 macallan pm3fb_wait(sc, 3); 626 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_INDEX_LOW, reg & 0xff); 627 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_INDEX_HIGH, (reg >> 8) & 0xff); 628 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM3_DAC_INDEX_DATA, data); 629 1.1 macallan } 630 1.1 macallan 631 1.1 macallan static void 632 1.1 macallan pm3fb_init(struct pm3fb_softc *sc) 633 1.1 macallan { 634 1.1 macallan 635 1.3 macallan pm3fb_wait(sc, 16); 636 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LB_DESTREAD_MODE, 0); 637 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LB_DESTREAD_ENABLES, 0); 638 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LB_SOURCEREAD_MODE, 0); 639 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LB_WRITE_MODE, 0); 640 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FILTER_MODE, PM3_FM_PASS_SYNC); 641 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STATISTIC_MODE, 0); 642 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DELTA_MODE, 0); 643 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RASTERIZER_MODE, 0); 644 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SCISSOR_MODE, 0); 645 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LINESTIPPLE_MODE, 0); 646 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_AREASTIPPLE_MODE, 0); 647 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_GID_MODE, 0); 648 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DEPTH_MODE, 0); 649 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STENCIL_MODE, 0); 650 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STENCIL_DATA, 0); 651 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_COLORDDA_MODE, 0); 652 1.3 macallan 653 1.3 macallan pm3fb_wait(sc, 16); 654 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTUREADDRESS_MODE, 0); 655 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTUREINDEX_MODE0, 0); 656 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTUREINDEX_MODE1, 0); 657 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTUREREAD_MODE, 0); 658 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXELLUT_MODE, 0); 659 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTUREFILTER_MODE, 0); 660 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOMPOSITE_MODE, 0); 661 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOLOR_MODE, 0); 662 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOMPOSITECOLOR_MODE1, 0); 663 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOMPOSITEALPHA_MODE1, 0); 664 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOMPOSITECOLOR_MODE0, 0); 665 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_TEXTURECOMPOSITEALPHA_MODE0, 0); 666 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FOG_MODE, 0); 667 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CHROMATEST_MODE, 0); 668 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_ALPHATEST_MODE, 0); 669 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_ANTIALIAS_MODE, 0); 670 1.3 macallan 671 1.3 macallan pm3fb_wait(sc, 16); 672 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_YUV_MODE, 0); 673 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_ALPHABLENDCOLOR_MODE, 0); 674 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_ALPHABLENDALPHA_MODE, 0); 675 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DITHER_MODE, 0); 676 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_LOGICALOP_MODE, 0); 677 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_ROUTER_MODE, 0); 678 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_WINDOW, 0); 679 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CONFIG2D, 0); 680 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SPANCOLORMASK, 0xffffffff); 681 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_XBIAS, 0); 682 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_YBIAS, 0); 683 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DELTACONTROL, 0); 684 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_BITMASKPATTERN, 0xffffffff); 685 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBDESTREAD_ENABLE, 686 1.1 macallan PM3_FBDESTREAD_SET(0xff, 0xff, 0xff)); 687 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBDESTREAD_BUFFERADDRESS0, 0); 688 1.3 macallan 689 1.3 macallan pm3fb_wait(sc, 16); 690 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBDESTREAD_BUFFEROFFSET0, 0); 691 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBDESTREAD_BUFFERWIDTH0, 692 1.1 macallan PM3_FBDESTREAD_BUFFERWIDTH_WIDTH(sc->sc_stride)); 693 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FB_DESTREAD_MODE, 694 1.1 macallan PM3_FBDRM_ENABLE | PM3_FBDRM_ENABLE0); 695 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOURCEREAD_BUFFERADDRESS, 0); 696 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOURCEREAD_BUFFEROFFSET, 0); 697 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOURCEREAD_BUFFERWIDTH, 698 1.1 macallan PM3_FBSOURCEREAD_BUFFERWIDTH_WIDTH(sc->sc_stride)); 699 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOURCEREAD_MODE, 700 1.1 macallan PM3_FBSOURCEREAD_MODE_BLOCKING | PM3_FBSOURCEREAD_MODE_ENABLE); 701 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_PIXEL_SIZE, PM3_PS_8BIT); 702 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOFTWAREWRITEMASK, 0xffffffff); 703 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBHARDWAREWRITEMASK, 0xffffffff); 704 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBWRITE_MODE, 705 1.1 macallan PM3_FBWRITEMODE_WRITEENABLE | PM3_FBWRITEMODE_OPAQUESPAN | PM3_FBWRITEMODE_ENABLE0); 706 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBWRITEBUFFERADDRESS0, 0); 707 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBWRITEBUFFEROFFSET0, 0); 708 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBWRITEBUFFERWIDTH0, 709 1.1 macallan PM3_FBWRITEBUFFERWIDTH_WIDTH(sc->sc_stride)); 710 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SIZEOF_FRAMEBUFFER, 4095); 711 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DITHER_MODE, PM3_CF_TO_DIM_CF(4)); 712 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DXDOM, 0); 713 1.3 macallan 714 1.3 macallan pm3fb_wait(sc, 6); 715 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DXSUB, 0); 716 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DY, 1 << 16); 717 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STARTXDOM, 0); 718 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STARTXSUB, 0); 719 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_STARTY, 0); 720 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_COUNT, 0); 721 1.1 macallan } 722 1.1 macallan 723 1.1 macallan static void 724 1.1 macallan pm3fb_rectfill(struct pm3fb_softc *sc, int x, int y, int wi, int he, 725 1.1 macallan uint32_t colour) 726 1.1 macallan { 727 1.1 macallan pm3fb_wait(sc, 4); 728 1.1 macallan 729 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CONFIG2D, 730 1.1 macallan PM3_CONFIG2D_USECONSTANTSOURCE | PM3_CONFIG2D_FOREGROUNDROP_ENABLE | 731 1.1 macallan (PM3_CONFIG2D_FOREGROUNDROP(0x3)) | PM3_CONFIG2D_FBWRITE_ENABLE); 732 1.1 macallan 733 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FOREGROUNDCOLOR, colour); 734 1.1 macallan 735 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RECTANGLEPOSITION, 736 1.1 macallan (((y) & 0xffff) << 16) | ((x) & 0xffff) ); 737 1.1 macallan 738 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RENDER2D, 739 1.1 macallan PM3_RENDER2D_XPOSITIVE | PM3_RENDER2D_YPOSITIVE | 740 1.1 macallan PM3_RENDER2D_OPERATION_NORMAL | PM3_RENDER2D_SPANOPERATION | 741 1.1 macallan (((he) & 0x0fff) << 16) | ((wi) & 0x0fff)); 742 1.1 macallan 743 1.3 macallan #ifdef PM3FB_DEBUG 744 1.1 macallan pm3fb_flush_engine(sc); 745 1.3 macallan #endif 746 1.1 macallan } 747 1.1 macallan 748 1.1 macallan static void 749 1.12 macallan pm3fb_rectfill_a(void *cookie, int x, int y, int wi, int he, long attr) 750 1.12 macallan { 751 1.12 macallan struct pm3fb_softc *sc = cookie; 752 1.12 macallan 753 1.12 macallan pm3fb_rectfill(sc, x, y, wi, he, 754 1.12 macallan sc->vd.active->scr_ri.ri_devcmap[(attr >> 24 & 0xf)]); 755 1.12 macallan } 756 1.12 macallan 757 1.12 macallan static void 758 1.1 macallan pm3fb_bitblt(void *cookie, int srcx, int srcy, int dstx, int dsty, 759 1.1 macallan int width, int height, int rop) 760 1.1 macallan { 761 1.1 macallan struct pm3fb_softc *sc = cookie; 762 1.1 macallan int x_align, offset_x, offset_y; 763 1.1 macallan uint32_t dir = 0; 764 1.1 macallan 765 1.2 macallan offset_x = srcx - dstx; 766 1.2 macallan offset_y = srcy - dsty; 767 1.1 macallan 768 1.1 macallan if (dsty <= srcy) { 769 1.1 macallan dir |= PM3_RENDER2D_YPOSITIVE; 770 1.1 macallan } 771 1.1 macallan 772 1.1 macallan if (dstx <= srcx) { 773 1.1 macallan dir |= PM3_RENDER2D_XPOSITIVE; 774 1.1 macallan } 775 1.1 macallan 776 1.1 macallan x_align = (srcx & 0x1f); 777 1.1 macallan 778 1.1 macallan pm3fb_wait(sc, 6); 779 1.1 macallan 780 1.1 macallan if (rop == 3){ 781 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CONFIG2D, 782 1.1 macallan PM3_CONFIG2D_USERSCISSOR_ENABLE | PM3_CONFIG2D_FOREGROUNDROP_ENABLE | PM3_CONFIG2D_BLOCKING | 783 1.1 macallan PM3_CONFIG2D_FOREGROUNDROP(rop) | PM3_CONFIG2D_FBWRITE_ENABLE); 784 1.1 macallan } else { 785 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CONFIG2D, 786 1.1 macallan PM3_CONFIG2D_USERSCISSOR_ENABLE | PM3_CONFIG2D_FOREGROUNDROP_ENABLE | PM3_CONFIG2D_BLOCKING | 787 1.1 macallan PM3_CONFIG2D_FOREGROUNDROP(rop) | PM3_CONFIG2D_FBWRITE_ENABLE | PM3_CONFIG2D_FBDESTREAD_ENABLE); 788 1.1 macallan } 789 1.1 macallan 790 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SCISSORMINXY, 791 1.1 macallan ((dsty & 0x0fff) << 16) | (dstx & 0x0fff)); 792 1.1 macallan 793 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SCISSORMAXXY, 794 1.1 macallan (((dsty + height) & 0x0fff) << 16) | ((dstx + width) & 0x0fff)); 795 1.1 macallan 796 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FBSOURCEREAD_BUFFEROFFSET, 797 1.1 macallan (((offset_y) & 0xffff) << 16) | ((offset_x) & 0xffff)); 798 1.1 macallan 799 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RECTANGLEPOSITION, 800 1.1 macallan (((dsty) & 0xffff) << 16) | ((dstx - x_align) & 0xffff)); 801 1.1 macallan 802 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RENDER2D, 803 1.1 macallan dir | 804 1.1 macallan PM3_RENDER2D_OPERATION_NORMAL | PM3_RENDER2D_SPANOPERATION | PM3_RENDER2D_FBSOURCEREADENABLE | 805 1.1 macallan (((height) & 0x0fff) << 16) | ((width + x_align) & 0x0fff)); 806 1.1 macallan 807 1.3 macallan #ifdef PM3FB_DEBUG 808 1.1 macallan pm3fb_flush_engine(sc); 809 1.3 macallan #endif 810 1.1 macallan } 811 1.1 macallan 812 1.1 macallan static void 813 1.1 macallan pm3fb_cursor(void *cookie, int on, int row, int col) 814 1.1 macallan { 815 1.1 macallan struct rasops_info *ri = cookie; 816 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 817 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 818 1.1 macallan int x, y, wi, he; 819 1.1 macallan 820 1.1 macallan wi = ri->ri_font->fontwidth; 821 1.1 macallan he = ri->ri_font->fontheight; 822 1.1 macallan 823 1.1 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 824 1.1 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 825 1.1 macallan y = ri->ri_crow * he + ri->ri_yorigin; 826 1.1 macallan if (ri->ri_flg & RI_CURSOR) { 827 1.1 macallan pm3fb_bitblt(sc, x, y, x, y, wi, he, 12); 828 1.1 macallan ri->ri_flg &= ~RI_CURSOR; 829 1.1 macallan } 830 1.1 macallan ri->ri_crow = row; 831 1.1 macallan ri->ri_ccol = col; 832 1.1 macallan if (on) { 833 1.1 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 834 1.1 macallan y = ri->ri_crow * he + ri->ri_yorigin; 835 1.1 macallan pm3fb_bitblt(sc, x, y, x, y, wi, he, 12); 836 1.1 macallan ri->ri_flg |= RI_CURSOR; 837 1.1 macallan } 838 1.1 macallan } else { 839 1.1 macallan scr->scr_ri.ri_crow = row; 840 1.1 macallan scr->scr_ri.ri_ccol = col; 841 1.1 macallan scr->scr_ri.ri_flg &= ~RI_CURSOR; 842 1.1 macallan } 843 1.1 macallan } 844 1.1 macallan 845 1.1 macallan static void 846 1.1 macallan pm3fb_putchar(void *cookie, int row, int col, u_int c, long attr) 847 1.1 macallan { 848 1.1 macallan struct rasops_info *ri = cookie; 849 1.1 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 850 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 851 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 852 1.1 macallan uint32_t mode; 853 1.1 macallan 854 1.1 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 855 1.1 macallan void *data; 856 1.1 macallan uint32_t fg, bg; 857 1.1 macallan int uc, i; 858 1.1 macallan int x, y, wi, he; 859 1.1 macallan 860 1.1 macallan wi = font->fontwidth; 861 1.1 macallan he = font->fontheight; 862 1.1 macallan 863 1.1 macallan if (!CHAR_IN_FONT(c, font)) 864 1.1 macallan return; 865 1.1 macallan 866 1.1 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 867 1.1 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 868 1.1 macallan x = ri->ri_xorigin + col * wi; 869 1.1 macallan y = ri->ri_yorigin + row * he; 870 1.1 macallan if (c == 0x20) { 871 1.1 macallan pm3fb_rectfill(sc, x, y, wi, he, bg); 872 1.1 macallan } else { 873 1.1 macallan uc = c - font->firstchar; 874 1.1 macallan data = (uint8_t *)font->data + uc * ri->ri_fontscale; 875 1.1 macallan mode = PM3_RM_MASK_MIRROR; 876 1.1 macallan 877 1.1 macallan #if BYTE_ORDER == LITTLE_ENDIAN 878 1.1 macallan switch (ri->ri_font->stride) { 879 1.1 macallan case 1: 880 1.1 macallan mode |= 4 << 7; 881 1.1 macallan break; 882 1.1 macallan case 2: 883 1.1 macallan mode |= 3 << 7; 884 1.1 macallan break; 885 1.1 macallan } 886 1.1 macallan #else 887 1.1 macallan switch (ri->ri_font->stride) { 888 1.1 macallan case 1: 889 1.1 macallan mode |= 3 << 7; 890 1.1 macallan break; 891 1.1 macallan case 2: 892 1.1 macallan mode |= 2 << 7; 893 1.1 macallan break; 894 1.1 macallan } 895 1.1 macallan #endif 896 1.12 macallan pm3fb_wait(sc, 6); 897 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 898 1.1 macallan PM3_FOREGROUNDCOLOR, fg); 899 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 900 1.1 macallan PM3_BACKGROUNDCOLOR, bg); 901 1.1 macallan 902 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RASTERIZER_MODE, mode); 903 1.1 macallan 904 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 905 1.1 macallan PM3_CONFIG2D, 906 1.1 macallan PM3_CONFIG2D_USECONSTANTSOURCE | 907 1.1 macallan PM3_CONFIG2D_FOREGROUNDROP_ENABLE | 908 1.1 macallan PM3_CONFIG2D_FOREGROUNDROP(0x03) | 909 1.1 macallan PM3_CONFIG2D_OPAQUESPAN | 910 1.1 macallan PM3_CONFIG2D_FBWRITE_ENABLE); 911 1.1 macallan 912 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 913 1.1 macallan PM3_RECTANGLEPOSITION, (((y) & 0xffff)<<16) | ((x) & 0xffff)); 914 1.1 macallan 915 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 916 1.1 macallan PM3_RENDER2D, 917 1.1 macallan PM3_RENDER2D_XPOSITIVE | 918 1.1 macallan PM3_RENDER2D_YPOSITIVE | 919 1.1 macallan PM3_RENDER2D_OPERATION_SYNCONBITMASK | 920 1.1 macallan PM3_RENDER2D_SPANOPERATION | 921 1.1 macallan ((wi) & 0x0fff) | (((he) & 0x0fff) << 16)); 922 1.1 macallan 923 1.1 macallan pm3fb_wait(sc, he); 924 1.1 macallan 925 1.1 macallan switch (ri->ri_font->stride) { 926 1.1 macallan case 1: { 927 1.1 macallan uint8_t *data8 = data; 928 1.1 macallan uint32_t reg; 929 1.1 macallan for (i = 0; i < he; i++) { 930 1.1 macallan reg = *data8; 931 1.1 macallan bus_space_write_4(sc->sc_memt, 932 1.1 macallan sc->sc_regh, 933 1.1 macallan PM3_BITMASKPATTERN, reg); 934 1.1 macallan data8++; 935 1.1 macallan } 936 1.1 macallan break; 937 1.1 macallan } 938 1.1 macallan case 2: { 939 1.1 macallan uint16_t *data16 = data; 940 1.1 macallan uint32_t reg; 941 1.1 macallan for (i = 0; i < he; i++) { 942 1.1 macallan reg = *data16; 943 1.1 macallan bus_space_write_4(sc->sc_memt, 944 1.1 macallan sc->sc_regh, 945 1.1 macallan PM3_BITMASKPATTERN, reg); 946 1.1 macallan data16++; 947 1.1 macallan } 948 1.1 macallan break; 949 1.1 macallan } 950 1.1 macallan } 951 1.1 macallan } 952 1.1 macallan } 953 1.1 macallan } 954 1.1 macallan 955 1.1 macallan static void 956 1.12 macallan pm3fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 957 1.12 macallan { 958 1.12 macallan struct rasops_info *ri = cookie; 959 1.12 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 960 1.12 macallan struct vcons_screen *scr = ri->ri_hw; 961 1.12 macallan struct pm3fb_softc *sc = scr->scr_cookie; 962 1.12 macallan uint32_t bg, fg, pixel, latch, aval; 963 1.12 macallan int i, j, x, y, wi, he, r, g, b; 964 1.12 macallan int r1, g1, b1, r0, g0, b0, fgo, bgo, shift; 965 1.12 macallan uint8_t *data8; 966 1.12 macallan int rv = GC_NOPE, cnt = 0; 967 1.12 macallan 968 1.12 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 969 1.12 macallan return; 970 1.12 macallan 971 1.12 macallan if (!CHAR_IN_FONT(c, font)) 972 1.12 macallan return; 973 1.12 macallan 974 1.12 macallan wi = font->fontwidth; 975 1.12 macallan he = font->fontheight; 976 1.12 macallan 977 1.12 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff; 978 1.12 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff; 979 1.12 macallan x = ri->ri_xorigin + col * wi; 980 1.12 macallan y = ri->ri_yorigin + row * he; 981 1.12 macallan 982 1.12 macallan /* if we draw a whitespace we're done here */ 983 1.12 macallan if (c == 0x20) { 984 1.12 macallan pm3fb_rectfill(sc, x, y, wi, he, bg); 985 1.12 macallan if (attr & 1) 986 1.12 macallan pm3fb_rectfill(sc, x, y + he - 2, wi, 1, fg); 987 1.12 macallan return; 988 1.12 macallan } 989 1.12 macallan 990 1.12 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 991 1.12 macallan if (rv == GC_OK) 992 1.12 macallan return; 993 1.12 macallan 994 1.12 macallan data8 = WSFONT_GLYPH(c, font); 995 1.12 macallan 996 1.12 macallan pm3fb_wait(sc, 3); 997 1.12 macallan 998 1.12 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CONFIG2D, 999 1.12 macallan PM3_CONFIG2D_OPAQUESPAN | 1000 1.12 macallan PM3_CONFIG2D_EXTERNALSOURCEDATA | 1001 1.12 macallan PM3_CONFIG2D_FBWRITE_ENABLE); 1002 1.12 macallan 1003 1.12 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RECTANGLEPOSITION, 1004 1.12 macallan (((y) & 0xffff) << 16) | ((x) & 0xffff) ); 1005 1.12 macallan 1006 1.12 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_RENDER2D, 1007 1.12 macallan PM3_RENDER2D_XPOSITIVE | PM3_RENDER2D_YPOSITIVE | 1008 1.12 macallan PM3_RENDER2D_OPERATION_SYNCONHOSTDATA | PM3_RENDER2D_SPANOPERATION | 1009 1.12 macallan (((he) & 0x0fff) << 16) | ((wi) & 0x0fff)); 1010 1.12 macallan 1011 1.12 macallan /* 1012 1.12 macallan * we need the RGB colours here, so get offsets into rasops_cmap 1013 1.12 macallan */ 1014 1.12 macallan fgo = ((attr >> 24) & 0xf) * 3; 1015 1.12 macallan bgo = ((attr >> 16) & 0xf) * 3; 1016 1.12 macallan 1017 1.12 macallan r0 = rasops_cmap[bgo]; 1018 1.12 macallan g0 = rasops_cmap[bgo + 1]; 1019 1.12 macallan b0 = rasops_cmap[bgo + 2]; 1020 1.12 macallan r1 = rasops_cmap[fgo]; 1021 1.12 macallan g1 = rasops_cmap[fgo + 1]; 1022 1.12 macallan b1 = rasops_cmap[fgo + 2]; 1023 1.12 macallan 1024 1.12 macallan pm3fb_wait(sc, 20); 1025 1.12 macallan 1026 1.12 macallan /* 1027 1.12 macallan * we need two loops here because lines have to be padded to full 32bit 1028 1.12 macallan */ 1029 1.12 macallan for (i = 0; i < he; i++) { 1030 1.12 macallan shift = 24; 1031 1.12 macallan latch = 0; 1032 1.12 macallan for (j = 0; j < wi; j++) { 1033 1.12 macallan aval = *data8; 1034 1.12 macallan if (aval == 0) { 1035 1.12 macallan pixel = bg; 1036 1.12 macallan } else if (aval == 255) { 1037 1.12 macallan pixel = fg; 1038 1.12 macallan } else { 1039 1.12 macallan r = aval * r1 + (255 - aval) * r0; 1040 1.12 macallan g = aval * g1 + (255 - aval) * g0; 1041 1.12 macallan b = aval * b1 + (255 - aval) * b0; 1042 1.12 macallan pixel = ((r & 0xe000) >> 8) | 1043 1.12 macallan ((g & 0xe000) >> 11) | 1044 1.12 macallan ((b & 0xc000) >> 14); 1045 1.12 macallan } 1046 1.12 macallan latch |= pixel << shift; 1047 1.12 macallan shift -= 8; 1048 1.12 macallan if (shift < 0) { 1049 1.12 macallan bus_space_write_stream_4(sc->sc_memt, sc->sc_regh, 1050 1.12 macallan PM3_SOURCE_DATA, latch); 1051 1.12 macallan cnt++; 1052 1.12 macallan if (cnt > 18) { 1053 1.12 macallan pm3fb_wait(sc, 20); 1054 1.12 macallan cnt = 0; 1055 1.12 macallan } 1056 1.12 macallan latch = 0; 1057 1.12 macallan shift = 24; 1058 1.12 macallan } 1059 1.12 macallan data8++; 1060 1.12 macallan } 1061 1.12 macallan if (shift != 24) 1062 1.12 macallan bus_space_write_stream_4(sc->sc_memt, sc->sc_regh, 1063 1.12 macallan PM3_SOURCE_DATA, latch); 1064 1.12 macallan } 1065 1.12 macallan 1066 1.12 macallan if (rv == GC_ADD) { 1067 1.12 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1068 1.12 macallan } 1069 1.12 macallan 1070 1.12 macallan if (attr & 1) 1071 1.12 macallan pm3fb_rectfill(sc, x, y + he - 2, wi, 1, fg); 1072 1.12 macallan } 1073 1.12 macallan 1074 1.12 macallan static void 1075 1.1 macallan pm3fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1076 1.1 macallan { 1077 1.1 macallan struct rasops_info *ri = cookie; 1078 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1079 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 1080 1.1 macallan int32_t xs, xd, y, width, height; 1081 1.1 macallan 1082 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1083 1.1 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1084 1.1 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1085 1.1 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1086 1.1 macallan width = ri->ri_font->fontwidth * ncols; 1087 1.1 macallan height = ri->ri_font->fontheight; 1088 1.1 macallan pm3fb_bitblt(sc, xs, y, xd, y, width, height, 3); 1089 1.1 macallan } 1090 1.1 macallan } 1091 1.1 macallan 1092 1.1 macallan static void 1093 1.1 macallan pm3fb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1094 1.1 macallan { 1095 1.1 macallan struct rasops_info *ri = cookie; 1096 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1097 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 1098 1.1 macallan int32_t x, y, width, height, fg, bg, ul; 1099 1.1 macallan 1100 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1101 1.1 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1102 1.1 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1103 1.1 macallan width = ri->ri_font->fontwidth * ncols; 1104 1.1 macallan height = ri->ri_font->fontheight; 1105 1.1 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1106 1.1 macallan 1107 1.1 macallan pm3fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1108 1.1 macallan } 1109 1.1 macallan } 1110 1.1 macallan 1111 1.1 macallan static void 1112 1.1 macallan pm3fb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1113 1.1 macallan { 1114 1.1 macallan struct rasops_info *ri = cookie; 1115 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1116 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 1117 1.1 macallan int32_t x, ys, yd, width, height; 1118 1.1 macallan 1119 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1120 1.1 macallan x = ri->ri_xorigin; 1121 1.1 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1122 1.1 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1123 1.1 macallan width = ri->ri_emuwidth; 1124 1.1 macallan height = ri->ri_font->fontheight*nrows; 1125 1.1 macallan pm3fb_bitblt(sc, x, ys, x, yd, width, height, 3); 1126 1.1 macallan } 1127 1.1 macallan } 1128 1.1 macallan 1129 1.1 macallan static void 1130 1.1 macallan pm3fb_eraserows(void *cookie, int row, int nrows, long fillattr) 1131 1.1 macallan { 1132 1.1 macallan struct rasops_info *ri = cookie; 1133 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1134 1.1 macallan struct pm3fb_softc *sc = scr->scr_cookie; 1135 1.1 macallan int32_t x, y, width, height, fg, bg, ul; 1136 1.1 macallan 1137 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1138 1.14 macallan if (row == 0 && nrows == ri->ri_rows) { 1139 1.14 macallan x = 0; 1140 1.14 macallan y = 0; 1141 1.14 macallan width = sc->sc_width; 1142 1.14 macallan height = sc->sc_height; 1143 1.14 macallan } else { 1144 1.14 macallan x = ri->ri_xorigin; 1145 1.14 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1146 1.14 macallan width = ri->ri_emuwidth; 1147 1.14 macallan height = ri->ri_font->fontheight * nrows; 1148 1.14 macallan } 1149 1.1 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1150 1.1 macallan 1151 1.1 macallan pm3fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1152 1.1 macallan } 1153 1.1 macallan } 1154 1.1 macallan 1155 1.1 macallan /* should be enough */ 1156 1.1 macallan #define MODE_IS_VALID(m) (((m)->hdisplay < 2048)) 1157 1.1 macallan 1158 1.1 macallan static void 1159 1.1 macallan pm3_setup_i2c(struct pm3fb_softc *sc) 1160 1.1 macallan { 1161 1.1 macallan int i; 1162 1.1 macallan 1163 1.1 macallan /* Fill in the i2c tag */ 1164 1.5 thorpej iic_tag_init(&sc->sc_i2c); 1165 1.1 macallan sc->sc_i2c.ic_cookie = sc; 1166 1.1 macallan sc->sc_i2c.ic_send_start = pm3fb_i2c_send_start; 1167 1.1 macallan sc->sc_i2c.ic_send_stop = pm3fb_i2c_send_stop; 1168 1.1 macallan sc->sc_i2c.ic_initiate_xfer = pm3fb_i2c_initiate_xfer; 1169 1.1 macallan sc->sc_i2c.ic_read_byte = pm3fb_i2c_read_byte; 1170 1.1 macallan sc->sc_i2c.ic_write_byte = pm3fb_i2c_write_byte; 1171 1.1 macallan sc->sc_i2c.ic_exec = NULL; 1172 1.1 macallan 1173 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DISPLAY_DATA, 0); 1174 1.1 macallan 1175 1.1 macallan /* zero out the EDID buffer */ 1176 1.1 macallan memset(sc->sc_edid_data, 0, 128); 1177 1.1 macallan 1178 1.1 macallan /* Some monitors don't respond first time */ 1179 1.1 macallan i = 0; 1180 1.1 macallan while (sc->sc_edid_data[1] == 0 && i < 10) { 1181 1.1 macallan ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128); 1182 1.1 macallan i++; 1183 1.1 macallan } 1184 1.1 macallan 1185 1.1 macallan if (edid_parse(&sc->sc_edid_data[0], &sc->sc_ei) != -1) { 1186 1.1 macallan /* 1187 1.1 macallan * Now pick a mode. 1188 1.1 macallan */ 1189 1.11 macallan #ifdef PM3FB_DEBUG 1190 1.11 macallan edid_print(&sc->sc_ei); 1191 1.11 macallan #endif 1192 1.1 macallan if ((sc->sc_ei.edid_preferred_mode != NULL)) { 1193 1.1 macallan struct videomode *m = sc->sc_ei.edid_preferred_mode; 1194 1.1 macallan if (MODE_IS_VALID(m)) { 1195 1.1 macallan sc->sc_videomode = m; 1196 1.1 macallan } else { 1197 1.1 macallan aprint_error_dev(sc->sc_dev, 1198 1.1 macallan "unable to use preferred mode\n"); 1199 1.1 macallan } 1200 1.1 macallan } 1201 1.1 macallan /* 1202 1.1 macallan * if we can't use the preferred mode go look for the 1203 1.1 macallan * best one we can support 1204 1.1 macallan */ 1205 1.1 macallan if (sc->sc_videomode == NULL) { 1206 1.1 macallan struct videomode *m = sc->sc_ei.edid_modes; 1207 1.1 macallan 1208 1.1 macallan sort_modes(sc->sc_ei.edid_modes, 1209 1.1 macallan &sc->sc_ei.edid_preferred_mode, 1210 1.1 macallan sc->sc_ei.edid_nmodes); 1211 1.1 macallan if (sc->sc_videomode == NULL) 1212 1.1 macallan for (int n = 0; n < sc->sc_ei.edid_nmodes; n++) 1213 1.1 macallan if (MODE_IS_VALID(&m[n])) { 1214 1.1 macallan sc->sc_videomode = &m[n]; 1215 1.1 macallan break; 1216 1.1 macallan } 1217 1.1 macallan } 1218 1.1 macallan } 1219 1.1 macallan if (sc->sc_videomode == NULL) { 1220 1.1 macallan /* no EDID data? */ 1221 1.1 macallan sc->sc_videomode = pick_mode_by_ref(sc->sc_width, 1222 1.1 macallan sc->sc_height, 60); 1223 1.1 macallan } 1224 1.1 macallan if (sc->sc_videomode != NULL) { 1225 1.1 macallan pm3fb_set_mode(sc, sc->sc_videomode); 1226 1.1 macallan } 1227 1.1 macallan } 1228 1.1 macallan 1229 1.1 macallan /* I2C bitbanging */ 1230 1.1 macallan static void pm3fb_i2cbb_set_bits(void *cookie, uint32_t bits) 1231 1.1 macallan { 1232 1.1 macallan struct pm3fb_softc *sc = cookie; 1233 1.1 macallan uint32_t out; 1234 1.1 macallan 1235 1.1 macallan out = bits << 2; /* bitmasks match the IN bits */ 1236 1.1 macallan 1237 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_DISPLAY_DATA, out); 1238 1.1 macallan delay(100); 1239 1.1 macallan } 1240 1.1 macallan 1241 1.1 macallan static void pm3fb_i2cbb_set_dir(void *cookie, uint32_t dir) 1242 1.1 macallan { 1243 1.1 macallan /* Nothing to do */ 1244 1.1 macallan } 1245 1.1 macallan 1246 1.1 macallan static uint32_t pm3fb_i2cbb_read(void *cookie) 1247 1.1 macallan { 1248 1.1 macallan struct pm3fb_softc *sc = cookie; 1249 1.1 macallan uint32_t bits; 1250 1.1 macallan 1251 1.1 macallan bits = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM3_DISPLAY_DATA); 1252 1.1 macallan return bits; 1253 1.1 macallan } 1254 1.1 macallan 1255 1.1 macallan /* higher level I2C stuff */ 1256 1.1 macallan static int 1257 1.1 macallan pm3fb_i2c_send_start(void *cookie, int flags) 1258 1.1 macallan { 1259 1.1 macallan 1260 1.1 macallan return (i2c_bitbang_send_start(cookie, flags, &pm3fb_i2cbb_ops)); 1261 1.1 macallan } 1262 1.1 macallan 1263 1.1 macallan static int 1264 1.1 macallan pm3fb_i2c_send_stop(void *cookie, int flags) 1265 1.1 macallan { 1266 1.1 macallan 1267 1.1 macallan return (i2c_bitbang_send_stop(cookie, flags, &pm3fb_i2cbb_ops)); 1268 1.1 macallan } 1269 1.1 macallan 1270 1.1 macallan static int 1271 1.1 macallan pm3fb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 1272 1.1 macallan { 1273 1.1 macallan 1274 1.1 macallan return (i2c_bitbang_initiate_xfer(cookie, addr, flags, 1275 1.1 macallan &pm3fb_i2cbb_ops)); 1276 1.1 macallan } 1277 1.1 macallan 1278 1.1 macallan static int 1279 1.1 macallan pm3fb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) 1280 1.1 macallan { 1281 1.1 macallan 1282 1.1 macallan return (i2c_bitbang_read_byte(cookie, valp, flags, &pm3fb_i2cbb_ops)); 1283 1.1 macallan } 1284 1.1 macallan 1285 1.1 macallan static int 1286 1.1 macallan pm3fb_i2c_write_byte(void *cookie, uint8_t val, int flags) 1287 1.1 macallan { 1288 1.1 macallan return (i2c_bitbang_write_byte(cookie, val, flags, &pm3fb_i2cbb_ops)); 1289 1.1 macallan } 1290 1.1 macallan 1291 1.1 macallan static int 1292 1.1 macallan pm3fb_set_pll(struct pm3fb_softc *sc, int freq) 1293 1.1 macallan { 1294 1.1 macallan uint8_t bf = 0, bpre = 0, bpost = 0; 1295 1.1 macallan int count; 1296 1.1 macallan unsigned long feedback, prescale, postscale, IntRef, VCO, out_freq, diff, VCOlow, VCOhigh, bdiff = 1000000; 1297 1.1 macallan 1298 1.1 macallan freq *= 10; /* convert into 100Hz units */ 1299 1.1 macallan 1300 1.1 macallan for (postscale = 0; postscale <= 5; postscale++) { 1301 1.1 macallan /* 1302 1.1 macallan * It is pointless going through the main loop if all values of 1303 1.1 macallan * prescale produce an VCO outside the acceptable range 1304 1.1 macallan */ 1305 1.1 macallan prescale = 1; 1306 1.1 macallan feedback = (prescale * (1UL << postscale) * freq) / (2 * PM3_EXT_CLOCK_FREQ); 1307 1.1 macallan VCOlow = (2 * PM3_EXT_CLOCK_FREQ * feedback) / prescale; 1308 1.1 macallan if (VCOlow > PM3_VCO_FREQ_MAX) 1309 1.1 macallan continue; 1310 1.1 macallan 1311 1.1 macallan prescale = 255; 1312 1.1 macallan feedback = (prescale * (1UL << postscale) * freq) / (2 * PM3_EXT_CLOCK_FREQ); 1313 1.1 macallan VCOhigh = (2 * PM3_EXT_CLOCK_FREQ * feedback) / prescale; 1314 1.1 macallan if (VCOhigh < PM3_VCO_FREQ_MIN) 1315 1.1 macallan continue; 1316 1.1 macallan 1317 1.1 macallan for (prescale = 1; prescale <= 255; prescale++) { 1318 1.1 macallan IntRef = PM3_EXT_CLOCK_FREQ / prescale; 1319 1.1 macallan if (IntRef < PM3_INTREF_MIN || IntRef > PM3_INTREF_MAX) { 1320 1.1 macallan if (IntRef > PM3_INTREF_MAX) { 1321 1.1 macallan /* 1322 1.1 macallan * Hopefully we will get into range as the prescale 1323 1.1 macallan * value increases 1324 1.1 macallan */ 1325 1.1 macallan continue; 1326 1.1 macallan } else { 1327 1.1 macallan /* 1328 1.1 macallan * already below minimum and it will only get worse 1329 1.1 macallan * move to the next postscale value 1330 1.1 macallan */ 1331 1.1 macallan break; 1332 1.1 macallan } 1333 1.1 macallan } 1334 1.1 macallan 1335 1.1 macallan feedback = (prescale * (1UL << postscale) * freq) / (2 * PM3_EXT_CLOCK_FREQ); 1336 1.1 macallan 1337 1.1 macallan if (feedback > 255) { 1338 1.1 macallan /* 1339 1.1 macallan * prescale, feedbackscale & postscale registers 1340 1.1 macallan * are only 8 bits wide 1341 1.1 macallan */ 1342 1.1 macallan break; 1343 1.1 macallan } else if (feedback == 255) { 1344 1.1 macallan count = 1; 1345 1.1 macallan } else { 1346 1.1 macallan count = 2; 1347 1.1 macallan } 1348 1.1 macallan 1349 1.1 macallan do { 1350 1.1 macallan VCO = (2 * PM3_EXT_CLOCK_FREQ * feedback) / prescale; 1351 1.1 macallan if (VCO >= PM3_VCO_FREQ_MIN && VCO <= PM3_VCO_FREQ_MAX) { 1352 1.1 macallan out_freq = VCO / (1UL << postscale); 1353 1.1 macallan diff = abs(out_freq - freq); 1354 1.1 macallan if (diff < bdiff) { 1355 1.1 macallan bdiff = diff; 1356 1.1 macallan bf = feedback; 1357 1.1 macallan bpre = prescale; 1358 1.1 macallan bpost = postscale; 1359 1.1 macallan if (diff == 0) 1360 1.1 macallan goto out; 1361 1.1 macallan } 1362 1.1 macallan } 1363 1.1 macallan feedback++; 1364 1.1 macallan } while (--count >= 0); 1365 1.1 macallan } 1366 1.1 macallan } 1367 1.1 macallan out: 1368 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_CLOCK0_PRE_SCALE, bpre); 1369 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_CLOCK0_FEEDBACK_SCALE, bf); 1370 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_CLOCK0_POST_SCALE, bpost); 1371 1.1 macallan return 0; 1372 1.1 macallan } 1373 1.1 macallan 1374 1.1 macallan static void 1375 1.1 macallan pm3fb_set_mode(struct pm3fb_softc *sc, const struct videomode *mode) 1376 1.1 macallan { 1377 1.1 macallan int t1, t2, t3, t4, stride; 1378 1.1 macallan uint32_t vclk, tmp1; 1379 1.1 macallan uint8_t sync = 0; 1380 1.1 macallan 1381 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_BYPASS_MASK, 0xffffffff); 1382 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_APERTURE1_CONTROL, 0x00000000); 1383 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_APERTURE2_CONTROL, 0x00000000); 1384 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FIFODISCONNECT, 0x00000007); 1385 1.1 macallan 1386 1.1 macallan t1 = mode->hsync_start - mode->hdisplay; 1387 1.1 macallan t2 = mode->vsync_start - mode->vdisplay; 1388 1.1 macallan t3 = mode->hsync_end - mode->hsync_start; 1389 1.1 macallan t4 = mode->vsync_end - mode->vsync_start; 1390 1.1 macallan stride = (mode->hdisplay + 31) & ~31; 1391 1.1 macallan 1392 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_HORIZ_TOTAL, 1393 1.11 macallan (mode->htotal >> 4) - 1); 1394 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_HORIZ_SYNC_END, 1395 1.1 macallan (t1 + t3) >> 4); 1396 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_HORIZ_SYNC_START, 1397 1.1 macallan (t1 >> 4)); 1398 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_HORIZ_BLANK_END, 1399 1.1 macallan (mode->htotal - mode->hdisplay) >> 4); 1400 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_HORIZ_GATE_END, 1401 1.1 macallan (mode->htotal - mode->hdisplay) >> 4); 1402 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SCREEN_STRIDE, 1403 1.1 macallan (stride >> 4)); 1404 1.1 macallan 1405 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1406 1.1 macallan PM3_VERT_TOTAL, mode->vtotal - 1); 1407 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1408 1.1 macallan PM3_VERT_SYNC_END, t2 + t4 - 1); 1409 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1410 1.1 macallan PM3_VERT_SYNC_START, t2 - 1); 1411 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1412 1.1 macallan PM3_VERT_BLANK_END, mode->vtotal - mode->vdisplay); 1413 1.1 macallan 1414 1.1 macallan /*8bpp*/ 1415 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1416 1.1 macallan PM3_BYAPERTURE1MODE, PM3_BYAPERTUREMODE_PIXELSIZE_8BIT); 1417 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1418 1.1 macallan PM3_BYAPERTURE2MODE, PM3_BYAPERTUREMODE_PIXELSIZE_8BIT); 1419 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_VIDEO_CONTROL, 1420 1.1 macallan (PM3_VC_ENABLE | PM3_VC_HSC_ACTIVE_HIGH | PM3_VC_VSC_ACTIVE_HIGH | PM3_VC_PIXELSIZE_8BIT)); 1421 1.1 macallan 1422 1.1 macallan vclk = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM3_V_CLOCK_CTL); 1423 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_V_CLOCK_CTL, (vclk & 0xFFFFFFFC)); 1424 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_SCREEN_BASE, 0x0); 1425 1.1 macallan 1426 1.1 macallan tmp1 = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM3_CHIP_CONFIG); 1427 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_CHIP_CONFIG, tmp1 & 0xFFFFFFFD); 1428 1.1 macallan 1429 1.1 macallan pm3fb_set_pll(sc, mode->dot_clock); 1430 1.1 macallan 1431 1.1 macallan if (mode->flags & VID_PHSYNC) 1432 1.1 macallan sync |= PM3_SC_HSYNC_ACTIVE_HIGH; 1433 1.1 macallan if (mode->flags & VID_PVSYNC) 1434 1.1 macallan sync |= PM3_SC_VSYNC_ACTIVE_HIGH; 1435 1.1 macallan 1436 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1437 1.1 macallan PM3_RD_PM3_INDEX_CONTROL, PM3_INCREMENT_DISABLE); 1438 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_SYNC_CONTROL, sync); 1439 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_DAC_CONTROL, 0x00); 1440 1.1 macallan 1441 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_PIXEL_SIZE, PM3_DACPS_8BIT); 1442 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_COLOR_FORMAT, 1443 1.12 macallan (PM3_CF_ORDER_RGB | PM3_CF_VISUAL_256_COLOR)); 1444 1.1 macallan pm3fb_write_dac(sc, PM3_RAMDAC_CMD_MISC_CONTROL, PM3_MC_DAC_SIZE_8BIT); 1445 1.1 macallan 1446 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM3_FIFOCONTROL, 0x00000905); 1447 1.1 macallan 1448 1.1 macallan sc->sc_width = mode->hdisplay; 1449 1.1 macallan sc->sc_height = mode->vdisplay; 1450 1.1 macallan sc->sc_depth = 8; 1451 1.1 macallan sc->sc_stride = stride; 1452 1.1 macallan aprint_normal_dev(sc->sc_dev, "pm3 using %d x %d in 8 bit, stride %d\n", 1453 1.4 macallan sc->sc_width, sc->sc_height, stride); 1454 1.1 macallan } 1455