1 1.37 macallan /* $NetBSD: pm2fb.c,v 1.37 2025/06/04 08:06:46 macallan Exp $ */ 2 1.1 macallan 3 1.1 macallan /* 4 1.19 macallan * Copyright (c) 2009, 2012 Michael Lorenz 5 1.27 macallan * 2014 Naruaki Etomi 6 1.1 macallan * All rights reserved. 7 1.1 macallan * 8 1.1 macallan * Redistribution and use in source and binary forms, with or without 9 1.1 macallan * modification, are permitted provided that the following conditions 10 1.1 macallan * are met: 11 1.1 macallan * 1. Redistributions of source code must retain the above copyright 12 1.1 macallan * notice, this list of conditions and the following disclaimer. 13 1.1 macallan * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 macallan * notice, this list of conditions and the following disclaimer in the 15 1.1 macallan * documentation and/or other materials provided with the distribution. 16 1.1 macallan * 17 1.1 macallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 macallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.1 macallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 macallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 macallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.1 macallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.1 macallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.1 macallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.1 macallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 1.1 macallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 macallan */ 28 1.1 macallan 29 1.1 macallan /* 30 1.1 macallan * A console driver for Permedia 2 graphics controllers 31 1.1 macallan */ 32 1.1 macallan 33 1.1 macallan #include <sys/cdefs.h> 34 1.37 macallan __KERNEL_RCSID(0, "$NetBSD: pm2fb.c,v 1.37 2025/06/04 08:06:46 macallan Exp $"); 35 1.1 macallan 36 1.1 macallan #include <sys/param.h> 37 1.1 macallan #include <sys/systm.h> 38 1.1 macallan #include <sys/kernel.h> 39 1.1 macallan #include <sys/device.h> 40 1.1 macallan #include <sys/lwp.h> 41 1.1 macallan #include <sys/kauth.h> 42 1.15 macallan #include <sys/atomic.h> 43 1.1 macallan 44 1.1 macallan #include <dev/videomode/videomode.h> 45 1.1 macallan 46 1.1 macallan #include <dev/pci/pcivar.h> 47 1.1 macallan #include <dev/pci/pcireg.h> 48 1.1 macallan #include <dev/pci/pcidevs.h> 49 1.1 macallan #include <dev/pci/pciio.h> 50 1.1 macallan #include <dev/pci/pm2reg.h> 51 1.1 macallan 52 1.1 macallan #include <dev/wscons/wsdisplayvar.h> 53 1.1 macallan #include <dev/wscons/wsconsio.h> 54 1.1 macallan #include <dev/wsfont/wsfont.h> 55 1.1 macallan #include <dev/rasops/rasops.h> 56 1.1 macallan #include <dev/wscons/wsdisplay_vconsvar.h> 57 1.17 macallan #include <dev/wscons/wsdisplay_glyphcachevar.h> 58 1.7 cegger #include <dev/pci/wsdisplay_pci.h> 59 1.1 macallan 60 1.1 macallan #include <dev/i2c/i2cvar.h> 61 1.8 macallan #include <dev/i2c/i2c_bitbang.h> 62 1.8 macallan #include <dev/i2c/ddcvar.h> 63 1.8 macallan #include <dev/videomode/videomode.h> 64 1.8 macallan #include <dev/videomode/edidvar.h> 65 1.8 macallan #include <dev/videomode/edidreg.h> 66 1.8 macallan 67 1.9 macallan #include "opt_pm2fb.h" 68 1.9 macallan 69 1.8 macallan #ifdef PM2FB_DEBUG 70 1.8 macallan #define DPRINTF aprint_error 71 1.8 macallan #else 72 1.8 macallan #define DPRINTF while (0) printf 73 1.8 macallan #endif 74 1.1 macallan 75 1.27 macallan #if BYTE_ORDER == LITTLE_ENDIAN 76 1.27 macallan /* 77 1.27 macallan * XXX 78 1.27 macallan * A temporary workaround for unaligned blits on little endian hardware. 79 1.27 macallan * This makes pm2fb_bitblt() work well on little endian hardware to get 80 1.27 macallan * scrolling right, but not much more. Unaligned blits ( as in, where the lower 81 1.27 macallan * 2 bits of the source and destination X coordinates don't match ) are still 82 1.27 macallan * wrong so the glyph cache is also disabled. 83 1.27 macallan */ 84 1.27 macallan #define BITBLT_LE_WORKAROUND 85 1.27 macallan #endif 86 1.27 macallan 87 1.1 macallan struct pm2fb_softc { 88 1.1 macallan device_t sc_dev; 89 1.1 macallan 90 1.1 macallan pci_chipset_tag_t sc_pc; 91 1.1 macallan pcitag_t sc_pcitag; 92 1.1 macallan 93 1.1 macallan bus_space_tag_t sc_memt; 94 1.1 macallan bus_space_tag_t sc_iot; 95 1.1 macallan 96 1.1 macallan bus_space_handle_t sc_regh; 97 1.1 macallan bus_addr_t sc_fb, sc_reg; 98 1.1 macallan bus_size_t sc_fbsize, sc_regsize; 99 1.1 macallan 100 1.1 macallan int sc_width, sc_height, sc_depth, sc_stride; 101 1.1 macallan int sc_locked; 102 1.1 macallan struct vcons_screen sc_console_screen; 103 1.1 macallan struct wsscreen_descr sc_defaultscreen_descr; 104 1.1 macallan const struct wsscreen_descr *sc_screens[1]; 105 1.1 macallan struct wsscreen_list sc_screenlist; 106 1.1 macallan struct vcons_data vd; 107 1.1 macallan int sc_mode; 108 1.1 macallan u_char sc_cmap_red[256]; 109 1.1 macallan u_char sc_cmap_green[256]; 110 1.1 macallan u_char sc_cmap_blue[256]; 111 1.1 macallan /* engine stuff */ 112 1.3 macallan uint32_t sc_pprod; 113 1.15 macallan int sc_is_pm2; 114 1.8 macallan /* i2c stuff */ 115 1.8 macallan struct i2c_controller sc_i2c; 116 1.8 macallan uint8_t sc_edid_data[128]; 117 1.15 macallan struct edid_info sc_ei; 118 1.18 macallan const struct videomode *sc_videomode; 119 1.17 macallan glyphcache sc_gc; 120 1.1 macallan }; 121 1.1 macallan 122 1.1 macallan static int pm2fb_match(device_t, cfdata_t, void *); 123 1.1 macallan static void pm2fb_attach(device_t, device_t, void *); 124 1.1 macallan 125 1.1 macallan CFATTACH_DECL_NEW(pm2fb, sizeof(struct pm2fb_softc), 126 1.1 macallan pm2fb_match, pm2fb_attach, NULL, NULL); 127 1.1 macallan 128 1.1 macallan extern const u_char rasops_cmap[768]; 129 1.1 macallan 130 1.1 macallan static int pm2fb_ioctl(void *, void *, u_long, void *, int, 131 1.1 macallan struct lwp *); 132 1.1 macallan static paddr_t pm2fb_mmap(void *, void *, off_t, int); 133 1.1 macallan static void pm2fb_init_screen(void *, struct vcons_screen *, int, long *); 134 1.1 macallan 135 1.1 macallan static int pm2fb_putcmap(struct pm2fb_softc *, struct wsdisplay_cmap *); 136 1.1 macallan static int pm2fb_getcmap(struct pm2fb_softc *, struct wsdisplay_cmap *); 137 1.26 macallan static void pm2fb_init_palette(struct pm2fb_softc *); 138 1.1 macallan static int pm2fb_putpalreg(struct pm2fb_softc *, uint8_t, uint8_t, 139 1.1 macallan uint8_t, uint8_t); 140 1.1 macallan 141 1.1 macallan static void pm2fb_init(struct pm2fb_softc *); 142 1.21 macallan static inline void pm2fb_wait(struct pm2fb_softc *, int); 143 1.1 macallan static void pm2fb_flush_engine(struct pm2fb_softc *); 144 1.1 macallan static void pm2fb_rectfill(struct pm2fb_softc *, int, int, int, int, 145 1.1 macallan uint32_t); 146 1.20 macallan static void pm2fb_rectfill_a(void *, int, int, int, int, long); 147 1.17 macallan static void pm2fb_bitblt(void *, int, int, int, int, int, int, int); 148 1.1 macallan 149 1.1 macallan static void pm2fb_cursor(void *, int, int, int); 150 1.1 macallan static void pm2fb_putchar(void *, int, int, u_int, long); 151 1.17 macallan static void pm2fb_putchar_aa(void *, int, int, u_int, long); 152 1.1 macallan static void pm2fb_copycols(void *, int, int, int, int); 153 1.1 macallan static void pm2fb_erasecols(void *, int, int, int, long); 154 1.1 macallan static void pm2fb_copyrows(void *, int, int, int); 155 1.1 macallan static void pm2fb_eraserows(void *, int, int, long); 156 1.1 macallan 157 1.1 macallan struct wsdisplay_accessops pm2fb_accessops = { 158 1.1 macallan pm2fb_ioctl, 159 1.1 macallan pm2fb_mmap, 160 1.1 macallan NULL, /* alloc_screen */ 161 1.1 macallan NULL, /* free_screen */ 162 1.1 macallan NULL, /* show_screen */ 163 1.1 macallan NULL, /* load_font */ 164 1.1 macallan NULL, /* pollc */ 165 1.1 macallan NULL /* scroll */ 166 1.1 macallan }; 167 1.1 macallan 168 1.8 macallan /* I2C glue */ 169 1.8 macallan static int pm2fb_i2c_send_start(void *, int); 170 1.8 macallan static int pm2fb_i2c_send_stop(void *, int); 171 1.8 macallan static int pm2fb_i2c_initiate_xfer(void *, i2c_addr_t, int); 172 1.8 macallan static int pm2fb_i2c_read_byte(void *, uint8_t *, int); 173 1.8 macallan static int pm2fb_i2c_write_byte(void *, uint8_t, int); 174 1.8 macallan 175 1.8 macallan /* I2C bitbang glue */ 176 1.8 macallan static void pm2fb_i2cbb_set_bits(void *, uint32_t); 177 1.8 macallan static void pm2fb_i2cbb_set_dir(void *, uint32_t); 178 1.8 macallan static uint32_t pm2fb_i2cbb_read(void *); 179 1.8 macallan 180 1.8 macallan static void pm2_setup_i2c(struct pm2fb_softc *); 181 1.8 macallan 182 1.8 macallan static const struct i2c_bitbang_ops pm2fb_i2cbb_ops = { 183 1.8 macallan pm2fb_i2cbb_set_bits, 184 1.8 macallan pm2fb_i2cbb_set_dir, 185 1.8 macallan pm2fb_i2cbb_read, 186 1.8 macallan { 187 1.8 macallan PM2_DD_SDA_IN, 188 1.8 macallan PM2_DD_SCL_IN, 189 1.8 macallan 0, 190 1.8 macallan 0 191 1.8 macallan } 192 1.8 macallan }; 193 1.8 macallan 194 1.15 macallan /* mode setting stuff */ 195 1.15 macallan static int pm2fb_set_pll(struct pm2fb_softc *, int); 196 1.27 macallan static int pm2vfb_set_pll(struct pm2fb_softc *, int); 197 1.15 macallan static uint8_t pm2fb_read_dac(struct pm2fb_softc *, int); 198 1.15 macallan static void pm2fb_write_dac(struct pm2fb_softc *, int, uint8_t); 199 1.18 macallan static void pm2fb_set_mode(struct pm2fb_softc *, const struct videomode *); 200 1.18 macallan 201 1.27 macallan const struct { 202 1.27 macallan int vendor; 203 1.27 macallan int product; 204 1.27 macallan int flags; 205 1.27 macallan } pm2fb_pci_devices[] = { 206 1.27 macallan { 207 1.27 macallan PCI_VENDOR_3DLABS, 208 1.27 macallan PCI_PRODUCT_3DLABS_PERMEDIA2V, 209 1.27 macallan 0 210 1.27 macallan }, 211 1.27 macallan { 212 1.27 macallan PCI_VENDOR_TI, 213 1.27 macallan PCI_PRODUCT_TI_TVP4020, 214 1.27 macallan 1 215 1.27 macallan }, 216 1.27 macallan { 217 1.27 macallan 0, 218 1.27 macallan 0, 219 1.27 macallan 0 220 1.27 macallan } 221 1.27 macallan }; 222 1.27 macallan 223 1.18 macallan /* this table is from xf86-video-glint */ 224 1.18 macallan #define PARTPROD(a,b,c) (((a)<<6) | ((b)<<3) | (c)) 225 1.18 macallan int partprodPermedia[] = { 226 1.18 macallan -1, 227 1.18 macallan PARTPROD(0,0,1), PARTPROD(0,1,1), PARTPROD(1,1,1), PARTPROD(1,1,2), 228 1.18 macallan PARTPROD(1,2,2), PARTPROD(2,2,2), PARTPROD(1,2,3), PARTPROD(2,2,3), 229 1.18 macallan PARTPROD(1,3,3), PARTPROD(2,3,3), PARTPROD(1,2,4), PARTPROD(3,3,3), 230 1.18 macallan PARTPROD(1,3,4), PARTPROD(2,3,4), -1, PARTPROD(3,3,4), 231 1.18 macallan PARTPROD(1,4,4), PARTPROD(2,4,4), -1, PARTPROD(3,4,4), 232 1.18 macallan -1, PARTPROD(2,3,5), -1, PARTPROD(4,4,4), 233 1.18 macallan PARTPROD(1,4,5), PARTPROD(2,4,5), PARTPROD(3,4,5), -1, 234 1.18 macallan -1, -1, -1, PARTPROD(4,4,5), 235 1.18 macallan PARTPROD(1,5,5), PARTPROD(2,5,5), -1, PARTPROD(3,5,5), 236 1.18 macallan -1, -1, -1, PARTPROD(4,5,5), 237 1.18 macallan -1, -1, -1, PARTPROD(3,4,6), 238 1.18 macallan -1, -1, -1, PARTPROD(5,5,5), 239 1.18 macallan PARTPROD(1,5,6), PARTPROD(2,5,6), -1, PARTPROD(3,5,6), 240 1.18 macallan -1, -1, -1, PARTPROD(4,5,6), 241 1.18 macallan -1, -1, -1, -1, 242 1.18 macallan -1, -1, -1, PARTPROD(5,5,6), 243 1.18 macallan -1, -1, -1, -1, 244 1.18 macallan -1, -1, -1, -1, 245 1.18 macallan -1, -1, -1, -1, 246 1.18 macallan -1, -1, -1, -1, 247 1.18 macallan -1, -1, -1, -1, 248 1.18 macallan -1, -1, -1, -1, 249 1.18 macallan -1, -1, -1, -1, 250 1.18 macallan -1, -1, -1, -1, 251 1.18 macallan -1, -1, -1, -1, 252 1.18 macallan -1, -1, -1, -1, 253 1.18 macallan -1, -1, -1, -1, 254 1.18 macallan -1, -1, -1, -1, 255 1.18 macallan -1, -1, -1, -1, 256 1.18 macallan -1, -1, -1, -1, 257 1.18 macallan -1, -1, -1, -1, 258 1.18 macallan -1, -1, -1, -1, 259 1.18 macallan 0}; 260 1.15 macallan 261 1.1 macallan static inline void 262 1.1 macallan pm2fb_wait(struct pm2fb_softc *sc, int slots) 263 1.1 macallan { 264 1.1 macallan uint32_t reg; 265 1.1 macallan 266 1.1 macallan do { 267 1.1 macallan reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, 268 1.1 macallan PM2_INPUT_FIFO_SPACE); 269 1.1 macallan } while (reg <= slots); 270 1.1 macallan } 271 1.1 macallan 272 1.1 macallan static void 273 1.1 macallan pm2fb_flush_engine(struct pm2fb_softc *sc) 274 1.1 macallan { 275 1.1 macallan 276 1.1 macallan pm2fb_wait(sc, 2); 277 1.1 macallan 278 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_FILTER_MODE, 279 1.1 macallan PM2FLT_PASS_SYNC); 280 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SYNC, 0); 281 1.1 macallan do { 282 1.1 macallan while (bus_space_read_4(sc->sc_memt, sc->sc_regh, 283 1.1 macallan PM2_OUTPUT_FIFO_WORDS) == 0); 284 1.1 macallan } while (bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_OUTPUT_FIFO) != 285 1.27 macallan PM2_SYNC_TAG); 286 1.1 macallan } 287 1.1 macallan 288 1.1 macallan static int 289 1.1 macallan pm2fb_match(device_t parent, cfdata_t match, void *aux) 290 1.1 macallan { 291 1.1 macallan struct pci_attach_args *pa = (struct pci_attach_args *)aux; 292 1.27 macallan int i; 293 1.1 macallan 294 1.1 macallan if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) 295 1.1 macallan return 0; 296 1.1 macallan 297 1.27 macallan for (i = 0; pm2fb_pci_devices[i].vendor; i++) { 298 1.27 macallan if ((PCI_VENDOR(pa->pa_id) == pm2fb_pci_devices[i].vendor && 299 1.27 macallan PCI_PRODUCT(pa->pa_id) == pm2fb_pci_devices[i].product)) 300 1.27 macallan return 100; 301 1.27 macallan } 302 1.27 macallan 303 1.1 macallan return (0); 304 1.1 macallan } 305 1.1 macallan 306 1.1 macallan static void 307 1.1 macallan pm2fb_attach(device_t parent, device_t self, void *aux) 308 1.1 macallan { 309 1.1 macallan struct pm2fb_softc *sc = device_private(self); 310 1.1 macallan struct pci_attach_args *pa = aux; 311 1.1 macallan struct rasops_info *ri; 312 1.1 macallan struct wsemuldisplaydev_attach_args aa; 313 1.1 macallan prop_dictionary_t dict; 314 1.1 macallan unsigned long defattr; 315 1.28 macallan bool is_console = FALSE; 316 1.16 macallan uint32_t flags; 317 1.27 macallan int i; 318 1.1 macallan 319 1.1 macallan sc->sc_pc = pa->pa_pc; 320 1.1 macallan sc->sc_pcitag = pa->pa_tag; 321 1.1 macallan sc->sc_memt = pa->pa_memt; 322 1.1 macallan sc->sc_iot = pa->pa_iot; 323 1.1 macallan sc->sc_dev = self; 324 1.27 macallan 325 1.27 macallan for (i = 0; pm2fb_pci_devices[i].vendor; i++) { 326 1.27 macallan if (PCI_PRODUCT(pa->pa_id) == pm2fb_pci_devices[i].product) { 327 1.27 macallan sc->sc_is_pm2 = pm2fb_pci_devices[i].flags ; 328 1.27 macallan break; 329 1.27 macallan } 330 1.27 macallan } 331 1.27 macallan 332 1.12 drochner pci_aprint_devinfo(pa, NULL); 333 1.1 macallan 334 1.18 macallan /* 335 1.18 macallan * fill in parameters from properties 336 1.18 macallan * if we can't get a usable mode via DDC2 we'll use this to pick one, 337 1.18 macallan * which is why we fill them in with some conservative values that 338 1.18 macallan * hopefully work as a last resort 339 1.18 macallan */ 340 1.1 macallan dict = device_properties(self); 341 1.1 macallan if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { 342 1.1 macallan aprint_error("%s: no width property\n", device_xname(self)); 343 1.18 macallan sc->sc_width = 1024; 344 1.1 macallan } 345 1.1 macallan if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) { 346 1.1 macallan aprint_error("%s: no height property\n", device_xname(self)); 347 1.18 macallan sc->sc_height = 768; 348 1.1 macallan } 349 1.1 macallan if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) { 350 1.1 macallan aprint_error("%s: no depth property\n", device_xname(self)); 351 1.18 macallan sc->sc_depth = 8; 352 1.1 macallan } 353 1.18 macallan 354 1.1 macallan /* 355 1.1 macallan * don't look at the linebytes property - The Raptor firmware lies 356 1.1 macallan * about it. Get it from width * depth >> 3 instead. 357 1.1 macallan */ 358 1.15 macallan 359 1.1 macallan sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3); 360 1.1 macallan 361 1.1 macallan prop_dictionary_get_bool(dict, "is_console", &is_console); 362 1.1 macallan 363 1.3 macallan pci_mapreg_info(pa->pa_pc, pa->pa_tag, 0x14, PCI_MAPREG_TYPE_MEM, 364 1.3 macallan &sc->sc_fb, &sc->sc_fbsize, &flags); 365 1.1 macallan 366 1.1 macallan if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, 0, 367 1.1 macallan &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) { 368 1.1 macallan aprint_error("%s: failed to map registers.\n", 369 1.1 macallan device_xname(sc->sc_dev)); 370 1.1 macallan } 371 1.1 macallan 372 1.1 macallan /* 373 1.1 macallan * XXX yeah, casting the fb address to uint32_t is formally wrong 374 1.1 macallan * but as far as I know there are no PM2 with 64bit BARs 375 1.1 macallan */ 376 1.1 macallan aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self), 377 1.1 macallan (int)(sc->sc_fbsize >> 20), (uint32_t)sc->sc_fb); 378 1.1 macallan 379 1.1 macallan sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 380 1.1 macallan "default", 381 1.1 macallan 0, 0, 382 1.1 macallan NULL, 383 1.1 macallan 8, 16, 384 1.1 macallan WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 385 1.1 macallan NULL 386 1.1 macallan }; 387 1.1 macallan sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 388 1.1 macallan sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 389 1.1 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 390 1.1 macallan sc->sc_locked = 0; 391 1.1 macallan 392 1.8 macallan pm2_setup_i2c(sc); 393 1.8 macallan 394 1.1 macallan vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 395 1.1 macallan &pm2fb_accessops); 396 1.1 macallan sc->vd.init_screen = pm2fb_init_screen; 397 1.37 macallan sc->vd.show_screen_cookie = &sc->sc_gc; 398 1.37 macallan sc->vd.show_screen_cb = glyphcache_adapt; 399 1.26 macallan 400 1.1 macallan /* init engine here */ 401 1.1 macallan pm2fb_init(sc); 402 1.1 macallan 403 1.1 macallan ri = &sc->sc_console_screen.scr_ri; 404 1.1 macallan 405 1.17 macallan sc->sc_gc.gc_bitblt = pm2fb_bitblt; 406 1.20 macallan sc->sc_gc.gc_rectfill = pm2fb_rectfill_a; 407 1.17 macallan sc->sc_gc.gc_blitcookie = sc; 408 1.17 macallan sc->sc_gc.gc_rop = 3; 409 1.17 macallan 410 1.17 macallan #ifdef PM2FB_DEBUG 411 1.17 macallan /* 412 1.17 macallan * leave some room at the bottom of the screen for various blitter 413 1.17 macallan * tests and in order to make the glyph cache visible 414 1.17 macallan */ 415 1.17 macallan sc->sc_height -= 200; 416 1.17 macallan #endif 417 1.17 macallan 418 1.1 macallan if (is_console) { 419 1.1 macallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 420 1.1 macallan &defattr); 421 1.1 macallan sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 422 1.1 macallan 423 1.1 macallan pm2fb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 424 1.1 macallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 425 1.1 macallan sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 426 1.1 macallan sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 427 1.1 macallan sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 428 1.1 macallan sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 429 1.20 macallan 430 1.17 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 431 1.30 riastrad uimin(2047, (sc->sc_fbsize / sc->sc_stride)) 432 1.20 macallan - sc->sc_height - 5, 433 1.18 macallan sc->sc_width, 434 1.18 macallan ri->ri_font->fontwidth, 435 1.18 macallan ri->ri_font->fontheight, 436 1.18 macallan defattr); 437 1.1 macallan wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 438 1.1 macallan defattr); 439 1.1 macallan vcons_replay_msgbuf(&sc->sc_console_screen); 440 1.1 macallan } else { 441 1.14 macallan if (sc->sc_console_screen.scr_ri.ri_rows == 0) { 442 1.14 macallan /* do some minimal setup to avoid weirdnesses later */ 443 1.21 macallan vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, 444 1.21 macallan &defattr); 445 1.23 macallan } else 446 1.23 macallan (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 447 1.21 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 448 1.30 riastrad uimin(2047, (sc->sc_fbsize / sc->sc_stride)) 449 1.20 macallan - sc->sc_height - 5, 450 1.18 macallan sc->sc_width, 451 1.18 macallan ri->ri_font->fontwidth, 452 1.18 macallan ri->ri_font->fontheight, 453 1.18 macallan defattr); 454 1.1 macallan } 455 1.1 macallan 456 1.26 macallan pm2fb_init_palette(sc); 457 1.26 macallan 458 1.1 macallan aa.console = is_console; 459 1.1 macallan aa.scrdata = &sc->sc_screenlist; 460 1.1 macallan aa.accessops = &pm2fb_accessops; 461 1.1 macallan aa.accesscookie = &sc->vd; 462 1.1 macallan 463 1.33 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 464 1.17 macallan 465 1.17 macallan #ifdef PM2FB_DEBUG 466 1.17 macallan /* 467 1.17 macallan * draw a pattern to check if pm2fb_bitblt() gets the alignment stuff 468 1.17 macallan * right 469 1.17 macallan */ 470 1.17 macallan pm2fb_rectfill(sc, 0, sc->sc_height, sc->sc_width, 200, 0xffffffff); 471 1.17 macallan pm2fb_rectfill(sc, 0, sc->sc_height, 300, 10, 0); 472 1.17 macallan pm2fb_rectfill(sc, 10, sc->sc_height, 200, 10, 0xe0e0e0e0); 473 1.17 macallan for (i = 1; i < 20; i++) { 474 1.17 macallan pm2fb_bitblt(sc, 0, sc->sc_height, 475 1.17 macallan i, sc->sc_height + 10 * i, 476 1.17 macallan 300, 10, 3); 477 1.17 macallan pm2fb_bitblt(sc, i, sc->sc_height, 478 1.17 macallan 400, sc->sc_height + 10 * i, 479 1.17 macallan 300, 10, 3); 480 1.17 macallan } 481 1.17 macallan #endif 482 1.1 macallan } 483 1.1 macallan 484 1.1 macallan static int 485 1.1 macallan pm2fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 486 1.1 macallan struct lwp *l) 487 1.1 macallan { 488 1.1 macallan struct vcons_data *vd = v; 489 1.1 macallan struct pm2fb_softc *sc = vd->cookie; 490 1.1 macallan struct wsdisplay_fbinfo *wdf; 491 1.1 macallan struct vcons_screen *ms = vd->active; 492 1.1 macallan 493 1.1 macallan switch (cmd) { 494 1.6 cegger case WSDISPLAYIO_GTYPE: 495 1.6 cegger *(u_int *)data = WSDISPLAY_TYPE_PCIMISC; 496 1.6 cegger return 0; 497 1.6 cegger 498 1.6 cegger /* PCI config read/write passthrough. */ 499 1.6 cegger case PCI_IOC_CFGREAD: 500 1.6 cegger case PCI_IOC_CFGWRITE: 501 1.6 cegger return pci_devioctl(sc->sc_pc, sc->sc_pcitag, 502 1.6 cegger cmd, data, flag, l); 503 1.6 cegger 504 1.7 cegger case WSDISPLAYIO_GET_BUSID: 505 1.7 cegger return wsdisplayio_busid_pci(sc->sc_dev, sc->sc_pc, 506 1.7 cegger sc->sc_pcitag, data); 507 1.7 cegger 508 1.6 cegger case WSDISPLAYIO_GINFO: 509 1.6 cegger if (ms == NULL) 510 1.6 cegger return ENODEV; 511 1.6 cegger wdf = (void *)data; 512 1.6 cegger wdf->height = ms->scr_ri.ri_height; 513 1.6 cegger wdf->width = ms->scr_ri.ri_width; 514 1.6 cegger wdf->depth = ms->scr_ri.ri_depth; 515 1.6 cegger wdf->cmsize = 256; 516 1.6 cegger return 0; 517 1.6 cegger 518 1.6 cegger case WSDISPLAYIO_GETCMAP: 519 1.6 cegger return pm2fb_getcmap(sc, 520 1.6 cegger (struct wsdisplay_cmap *)data); 521 1.6 cegger 522 1.6 cegger case WSDISPLAYIO_PUTCMAP: 523 1.6 cegger return pm2fb_putcmap(sc, 524 1.6 cegger (struct wsdisplay_cmap *)data); 525 1.6 cegger 526 1.6 cegger case WSDISPLAYIO_LINEBYTES: 527 1.6 cegger *(u_int *)data = sc->sc_stride; 528 1.6 cegger return 0; 529 1.1 macallan 530 1.6 cegger case WSDISPLAYIO_SMODE: { 531 1.6 cegger int new_mode = *(int*)data; 532 1.6 cegger if (new_mode != sc->sc_mode) { 533 1.6 cegger sc->sc_mode = new_mode; 534 1.6 cegger if(new_mode == WSDISPLAYIO_MODE_EMUL) { 535 1.23 macallan /* first set the video mode */ 536 1.23 macallan if (sc->sc_videomode != NULL) { 537 1.23 macallan pm2fb_set_mode(sc, sc->sc_videomode); 538 1.23 macallan } 539 1.23 macallan /* then initialize the drawing engine */ 540 1.17 macallan pm2fb_init(sc); 541 1.26 macallan pm2fb_init_palette(sc); 542 1.23 macallan /* clean out the glyph cache */ 543 1.17 macallan glyphcache_wipe(&sc->sc_gc); 544 1.23 macallan /* and redraw everything */ 545 1.6 cegger vcons_redraw_screen(ms); 546 1.6 cegger } else 547 1.6 cegger pm2fb_flush_engine(sc); 548 1.6 cegger } 549 1.6 cegger } 550 1.6 cegger return 0; 551 1.8 macallan case WSDISPLAYIO_GET_EDID: { 552 1.8 macallan struct wsdisplayio_edid_info *d = data; 553 1.8 macallan d->data_size = 128; 554 1.8 macallan if (d->buffer_size < 128) 555 1.8 macallan return EAGAIN; 556 1.8 macallan return copyout(sc->sc_edid_data, d->edid_data, 128); 557 1.8 macallan } 558 1.25 macallan 559 1.25 macallan case WSDISPLAYIO_GET_FBINFO: { 560 1.25 macallan struct wsdisplayio_fbinfo *fbi = data; 561 1.25 macallan return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 562 1.25 macallan } 563 1.1 macallan } 564 1.1 macallan return EPASSTHROUGH; 565 1.1 macallan } 566 1.1 macallan 567 1.1 macallan static paddr_t 568 1.1 macallan pm2fb_mmap(void *v, void *vs, off_t offset, int prot) 569 1.1 macallan { 570 1.1 macallan struct vcons_data *vd = v; 571 1.1 macallan struct pm2fb_softc *sc = vd->cookie; 572 1.1 macallan paddr_t pa; 573 1.1 macallan 574 1.1 macallan /* 'regular' framebuffer mmap()ing */ 575 1.1 macallan if (offset < sc->sc_fbsize) { 576 1.1 macallan pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot, 577 1.1 macallan BUS_SPACE_MAP_LINEAR); 578 1.1 macallan return pa; 579 1.1 macallan } 580 1.1 macallan 581 1.1 macallan /* 582 1.1 macallan * restrict all other mappings to processes with superuser privileges 583 1.1 macallan * or the kernel itself 584 1.1 macallan */ 585 1.16 macallan if (kauth_authorize_machdep(kauth_cred_get(), 586 1.16 macallan KAUTH_MACHDEP_UNMANAGEDMEM, 587 1.13 elad NULL, NULL, NULL, NULL) != 0) { 588 1.1 macallan aprint_normal("%s: mmap() rejected.\n", 589 1.1 macallan device_xname(sc->sc_dev)); 590 1.1 macallan return -1; 591 1.1 macallan } 592 1.1 macallan 593 1.1 macallan if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) { 594 1.1 macallan pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 595 1.1 macallan BUS_SPACE_MAP_LINEAR); 596 1.1 macallan return pa; 597 1.1 macallan } 598 1.1 macallan 599 1.1 macallan if ((offset >= sc->sc_reg) && 600 1.1 macallan (offset < (sc->sc_reg + sc->sc_regsize))) { 601 1.1 macallan pa = bus_space_mmap(sc->sc_memt, offset, 0, prot, 602 1.1 macallan BUS_SPACE_MAP_LINEAR); 603 1.1 macallan return pa; 604 1.1 macallan } 605 1.29 macallan /* XXX 2nd fb BAR? */ 606 1.1 macallan 607 1.1 macallan #ifdef PCI_MAGIC_IO_RANGE 608 1.1 macallan /* allow mapping of IO space */ 609 1.1 macallan if ((offset >= PCI_MAGIC_IO_RANGE) && 610 1.1 macallan (offset < PCI_MAGIC_IO_RANGE + 0x10000)) { 611 1.1 macallan pa = bus_space_mmap(sc->sc_iot, offset - PCI_MAGIC_IO_RANGE, 612 1.1 macallan 0, prot, BUS_SPACE_MAP_LINEAR); 613 1.1 macallan return pa; 614 1.1 macallan } 615 1.1 macallan #endif 616 1.1 macallan 617 1.1 macallan return -1; 618 1.1 macallan } 619 1.1 macallan 620 1.1 macallan static void 621 1.1 macallan pm2fb_init_screen(void *cookie, struct vcons_screen *scr, 622 1.1 macallan int existing, long *defattr) 623 1.1 macallan { 624 1.1 macallan struct pm2fb_softc *sc = cookie; 625 1.1 macallan struct rasops_info *ri = &scr->scr_ri; 626 1.1 macallan 627 1.1 macallan ri->ri_depth = sc->sc_depth; 628 1.1 macallan ri->ri_width = sc->sc_width; 629 1.1 macallan ri->ri_height = sc->sc_height; 630 1.1 macallan ri->ri_stride = sc->sc_stride; 631 1.3 macallan ri->ri_flg = RI_CENTER; 632 1.16 macallan if (sc->sc_depth == 8) 633 1.17 macallan ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA; 634 1.1 macallan 635 1.37 macallan scr->scr_flags |= VCONS_LOADFONT; 636 1.37 macallan 637 1.11 macallan rasops_init(ri, 0, 0); 638 1.37 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_UNDERLINE | WSSCREEN_RESIZE; 639 1.1 macallan 640 1.1 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 641 1.1 macallan sc->sc_width / ri->ri_font->fontwidth); 642 1.1 macallan 643 1.1 macallan ri->ri_hw = scr; 644 1.1 macallan ri->ri_ops.copyrows = pm2fb_copyrows; 645 1.1 macallan ri->ri_ops.copycols = pm2fb_copycols; 646 1.1 macallan ri->ri_ops.cursor = pm2fb_cursor; 647 1.1 macallan ri->ri_ops.eraserows = pm2fb_eraserows; 648 1.1 macallan ri->ri_ops.erasecols = pm2fb_erasecols; 649 1.17 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 650 1.17 macallan ri->ri_ops.putchar = pm2fb_putchar_aa; 651 1.17 macallan } else 652 1.17 macallan ri->ri_ops.putchar = pm2fb_putchar; 653 1.1 macallan } 654 1.1 macallan 655 1.1 macallan static int 656 1.1 macallan pm2fb_putcmap(struct pm2fb_softc *sc, struct wsdisplay_cmap *cm) 657 1.1 macallan { 658 1.1 macallan u_char *r, *g, *b; 659 1.1 macallan u_int index = cm->index; 660 1.1 macallan u_int count = cm->count; 661 1.1 macallan int i, error; 662 1.1 macallan u_char rbuf[256], gbuf[256], bbuf[256]; 663 1.1 macallan 664 1.1 macallan #ifdef PM2FB_DEBUG 665 1.1 macallan aprint_debug("putcmap: %d %d\n",index, count); 666 1.1 macallan #endif 667 1.1 macallan if (cm->index >= 256 || cm->count > 256 || 668 1.1 macallan (cm->index + cm->count) > 256) 669 1.1 macallan return EINVAL; 670 1.1 macallan error = copyin(cm->red, &rbuf[index], count); 671 1.1 macallan if (error) 672 1.1 macallan return error; 673 1.1 macallan error = copyin(cm->green, &gbuf[index], count); 674 1.1 macallan if (error) 675 1.1 macallan return error; 676 1.1 macallan error = copyin(cm->blue, &bbuf[index], count); 677 1.1 macallan if (error) 678 1.1 macallan return error; 679 1.1 macallan 680 1.1 macallan memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 681 1.1 macallan memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 682 1.1 macallan memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 683 1.1 macallan 684 1.1 macallan r = &sc->sc_cmap_red[index]; 685 1.1 macallan g = &sc->sc_cmap_green[index]; 686 1.1 macallan b = &sc->sc_cmap_blue[index]; 687 1.1 macallan 688 1.1 macallan for (i = 0; i < count; i++) { 689 1.1 macallan pm2fb_putpalreg(sc, index, *r, *g, *b); 690 1.1 macallan index++; 691 1.1 macallan r++, g++, b++; 692 1.1 macallan } 693 1.1 macallan return 0; 694 1.1 macallan } 695 1.1 macallan 696 1.1 macallan static int 697 1.1 macallan pm2fb_getcmap(struct pm2fb_softc *sc, struct wsdisplay_cmap *cm) 698 1.1 macallan { 699 1.1 macallan u_int index = cm->index; 700 1.1 macallan u_int count = cm->count; 701 1.1 macallan int error; 702 1.1 macallan 703 1.1 macallan if (index >= 255 || count > 256 || index + count > 256) 704 1.1 macallan return EINVAL; 705 1.1 macallan 706 1.1 macallan error = copyout(&sc->sc_cmap_red[index], cm->red, count); 707 1.1 macallan if (error) 708 1.1 macallan return error; 709 1.1 macallan error = copyout(&sc->sc_cmap_green[index], cm->green, count); 710 1.1 macallan if (error) 711 1.1 macallan return error; 712 1.1 macallan error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 713 1.1 macallan if (error) 714 1.1 macallan return error; 715 1.1 macallan 716 1.1 macallan return 0; 717 1.1 macallan } 718 1.1 macallan 719 1.1 macallan static void 720 1.26 macallan pm2fb_init_palette(struct pm2fb_softc *sc) 721 1.1 macallan { 722 1.26 macallan struct rasops_info *ri = &sc->sc_console_screen.scr_ri; 723 1.26 macallan int i, j = 0; 724 1.26 macallan uint8_t cmap[768]; 725 1.1 macallan 726 1.26 macallan rasops_get_cmap(ri, cmap, sizeof(cmap)); 727 1.26 macallan for (i = 0; i < 256; i++) { 728 1.26 macallan sc->sc_cmap_red[i] = cmap[j]; 729 1.26 macallan sc->sc_cmap_green[i] = cmap[j + 1]; 730 1.26 macallan sc->sc_cmap_blue[i] = cmap[j + 2]; 731 1.26 macallan pm2fb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]); 732 1.26 macallan j += 3; 733 1.1 macallan } 734 1.1 macallan } 735 1.1 macallan 736 1.1 macallan static int 737 1.1 macallan pm2fb_putpalreg(struct pm2fb_softc *sc, uint8_t idx, uint8_t r, uint8_t g, 738 1.1 macallan uint8_t b) 739 1.1 macallan { 740 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM2_DAC_PAL_WRITE_IDX, idx); 741 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM2_DAC_DATA, r); 742 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM2_DAC_DATA, g); 743 1.1 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, PM2_DAC_DATA, b); 744 1.1 macallan return 0; 745 1.1 macallan } 746 1.1 macallan 747 1.15 macallan static uint8_t 748 1.15 macallan pm2fb_read_dac(struct pm2fb_softc *sc, int reg) 749 1.15 macallan { 750 1.15 macallan if (sc->sc_is_pm2) { 751 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 752 1.15 macallan PM2_DAC_PAL_WRITE_IDX, reg); 753 1.15 macallan return bus_space_read_1(sc->sc_memt, sc->sc_regh, 754 1.15 macallan PM2_DAC_INDEX_DATA); 755 1.15 macallan } else { 756 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 757 1.15 macallan PM2V_DAC_INDEX_LOW, reg & 0xff); 758 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 759 1.15 macallan PM2V_DAC_INDEX_HIGH, (reg >> 8) & 0xff); 760 1.15 macallan return bus_space_read_1(sc->sc_memt, sc->sc_regh, 761 1.15 macallan PM2V_DAC_INDEX_DATA); 762 1.15 macallan } 763 1.15 macallan } 764 1.15 macallan 765 1.15 macallan static void 766 1.15 macallan pm2fb_write_dac(struct pm2fb_softc *sc, int reg, uint8_t data) 767 1.15 macallan { 768 1.18 macallan pm2fb_wait(sc, 3); 769 1.15 macallan if (sc->sc_is_pm2) { 770 1.27 macallan pm2fb_wait(sc, 2); 771 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 772 1.15 macallan PM2_DAC_PAL_WRITE_IDX, reg); 773 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 774 1.15 macallan PM2_DAC_INDEX_DATA, data); 775 1.15 macallan } else { 776 1.27 macallan pm2fb_wait(sc, 3); 777 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 778 1.15 macallan PM2V_DAC_INDEX_LOW, reg & 0xff); 779 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 780 1.15 macallan PM2V_DAC_INDEX_HIGH, (reg >> 8) & 0xff); 781 1.15 macallan bus_space_write_1(sc->sc_memt, sc->sc_regh, 782 1.15 macallan PM2V_DAC_INDEX_DATA, data); 783 1.15 macallan } 784 1.15 macallan } 785 1.15 macallan 786 1.1 macallan static void 787 1.1 macallan pm2fb_init(struct pm2fb_softc *sc) 788 1.1 macallan { 789 1.1 macallan pm2fb_flush_engine(sc); 790 1.1 macallan 791 1.26 macallan pm2fb_wait(sc, 9); 792 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_SCREEN_BASE, 0); 793 1.26 macallan /* set aperture endianness */ 794 1.26 macallan #if BYTE_ORDER == BIG_ENDIAN 795 1.26 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_APERTURE1_CONTROL, 796 1.26 macallan PM2_AP_BYTESWAP | PM2_AP_HALFWORDSWAP); 797 1.26 macallan #else 798 1.26 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_APERTURE1_CONTROL, 0); 799 1.26 macallan #endif 800 1.1 macallan #if 0 801 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_BYPASS_MASK, 802 1.1 macallan 0xffffffff); 803 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_FB_WRITE_MASK, 804 1.1 macallan 0xffffffff); 805 1.3 macallan #endif 806 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HW_WRITEMASK, 807 1.3 macallan 0xffffffff); 808 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_SW_WRITEMASK, 809 1.3 macallan 0xffffffff); 810 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_WRITE_MODE, 811 1.3 macallan PM2WM_WRITE_EN); 812 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCREENSIZE, 813 1.3 macallan (sc->sc_height << 16) | sc->sc_width); 814 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCISSOR_MODE, 815 1.3 macallan PM2SC_SCREEN_EN); 816 1.3 macallan pm2fb_wait(sc, 8); 817 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DITHER_MODE, 0); 818 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ALPHA_MODE, 0); 819 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DDA_MODE, 0); 820 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEX_COLOUR_MODE, 0); 821 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEX_ADDRESS_MODE, 0); 822 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEX_READ_MODE, 0); 823 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEX_LUT_MODE, 0); 824 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_YUV_MODE, 0); 825 1.3 macallan pm2fb_wait(sc, 8); 826 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DEPTH_MODE, 0); 827 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DEPTH, 0); 828 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STENCIL_MODE, 0); 829 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STIPPLE_MODE, 0); 830 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ROP_MODE, 0); 831 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_WINDOW_ORIGIN, 0); 832 1.18 macallan #if 0 833 1.3 macallan sc->sc_pprod = bus_space_read_4(sc->sc_memt, sc->sc_regh, 834 1.3 macallan PM2_FB_READMODE) & 835 1.3 macallan (PM2FB_PP0_MASK | PM2FB_PP1_MASK | PM2FB_PP2_MASK); 836 1.18 macallan #endif 837 1.18 macallan sc->sc_pprod = partprodPermedia[sc->sc_stride >> 5]; 838 1.18 macallan 839 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_FB_READMODE, 840 1.3 macallan sc->sc_pprod); 841 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_TEXMAP_FORMAT, 842 1.3 macallan sc->sc_pprod); 843 1.15 macallan pm2fb_wait(sc, 9); 844 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DY, 1 << 16); 845 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DXDOM, 0); 846 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STARTXDOM, 0); 847 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STARTXSUB, 0); 848 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_STARTY, 0); 849 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_COUNT, 0); 850 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCISSOR_MINYX, 0); 851 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCISSOR_MAXYX, 852 1.3 macallan 0x0fff0fff); 853 1.17 macallan /* 854 1.17 macallan * another scissor we need to disable in order to blit into off-screen 855 1.17 macallan * memory 856 1.17 macallan */ 857 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SCREENSIZE, 858 1.17 macallan 0x0fff0fff); 859 1.17 macallan 860 1.15 macallan switch(sc->sc_depth) { 861 1.15 macallan case 8: 862 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 863 1.15 macallan PM2_RE_PIXEL_SIZE, PM2PS_8BIT); 864 1.15 macallan break; 865 1.15 macallan case 16: 866 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 867 1.15 macallan PM2_RE_PIXEL_SIZE, PM2PS_16BIT); 868 1.15 macallan break; 869 1.15 macallan case 32: 870 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 871 1.15 macallan PM2_RE_PIXEL_SIZE, PM2PS_32BIT); 872 1.15 macallan break; 873 1.15 macallan } 874 1.1 macallan pm2fb_flush_engine(sc); 875 1.17 macallan DPRINTF("pixel size: %08x\n", 876 1.17 macallan bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_RE_PIXEL_SIZE)); 877 1.1 macallan } 878 1.1 macallan 879 1.1 macallan static void 880 1.1 macallan pm2fb_rectfill(struct pm2fb_softc *sc, int x, int y, int wi, int he, 881 1.1 macallan uint32_t colour) 882 1.1 macallan { 883 1.1 macallan 884 1.29 macallan pm2fb_wait(sc, 9); 885 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DDA_MODE, 0); 886 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_MODE, 0); 887 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ALPHA_MODE, 0); 888 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DITHER_MODE, 0); 889 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_CONFIG, 890 1.1 macallan PM2RECFG_WRITE_EN); 891 1.2 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_BLOCK_COLOUR, 892 1.1 macallan colour); 893 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_START, 894 1.1 macallan (y << 16) | x); 895 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_SIZE, 896 1.1 macallan (he << 16) | wi); 897 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RENDER, 898 1.2 macallan PM2RE_RECTANGLE | PM2RE_INC_X | PM2RE_INC_Y | PM2RE_FASTFILL); 899 1.1 macallan } 900 1.1 macallan 901 1.1 macallan static void 902 1.20 macallan pm2fb_rectfill_a(void *cookie, int x, int y, int wi, int he, long attr) 903 1.20 macallan { 904 1.20 macallan struct pm2fb_softc *sc = cookie; 905 1.20 macallan 906 1.20 macallan pm2fb_rectfill(sc, x, y, wi, he, 907 1.20 macallan sc->vd.active->scr_ri.ri_devcmap[(attr >> 24 & 0xf)]); 908 1.20 macallan } 909 1.20 macallan 910 1.20 macallan static void 911 1.17 macallan pm2fb_bitblt(void *cookie, int xs, int ys, int xd, int yd, 912 1.1 macallan int wi, int he, int rop) 913 1.1 macallan { 914 1.17 macallan struct pm2fb_softc *sc = cookie; 915 1.1 macallan uint32_t dir = 0; 916 1.24 martin int rxd, rwi, rxdelta; 917 1.1 macallan 918 1.1 macallan if (yd <= ys) { 919 1.1 macallan dir |= PM2RE_INC_Y; 920 1.1 macallan } 921 1.1 macallan if (xd <= xs) { 922 1.1 macallan dir |= PM2RE_INC_X; 923 1.1 macallan } 924 1.29 macallan pm2fb_wait(sc, 10); 925 1.2 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DDA_MODE, 0); 926 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_MODE, 0); 927 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ALPHA_MODE, 0); 928 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DITHER_MODE, 0); 929 1.15 macallan if (sc->sc_depth == 8) { 930 1.16 macallan int adjust; 931 1.15 macallan /* 932 1.15 macallan * use packed mode for some extra speed 933 1.15 macallan * this copies 32bit quantities even in 8 bit mode, so we need 934 1.15 macallan * to adjust for cases where the lower two bits in source and 935 1.15 macallan * destination X don't align, and/or where the width isn't a 936 1.15 macallan * multiple of 4 937 1.15 macallan */ 938 1.15 macallan if (rop == 3) { 939 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 940 1.15 macallan PM2_RE_CONFIG, 941 1.15 macallan PM2RECFG_READ_SRC | PM2RECFG_WRITE_EN | 942 1.15 macallan PM2RECFG_ROP_EN | PM2RECFG_PACKED | (rop << 6)); 943 1.15 macallan } else { 944 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 945 1.15 macallan PM2_RE_CONFIG, 946 1.15 macallan PM2RECFG_READ_SRC | PM2RECFG_READ_DST | 947 1.15 macallan PM2RECFG_WRITE_EN | PM2RECFG_PACKED | 948 1.15 macallan PM2RECFG_ROP_EN | (rop << 6)); 949 1.15 macallan } 950 1.15 macallan rxd = xd >> 2; 951 1.17 macallan rwi = (wi + 7) >> 2; 952 1.17 macallan rxdelta = (xs & 0xffc) - (xd & 0xffc); 953 1.15 macallan /* adjust for non-aligned x */ 954 1.27 macallan #ifdef BITBLT_LE_WORKAROUND 955 1.27 macallan /* I have no idea why this seems to work */ 956 1.27 macallan adjust = 1; 957 1.27 macallan #else 958 1.17 macallan adjust = ((xd & 3) - (xs & 3)); 959 1.27 macallan #endif 960 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 961 1.15 macallan PM2_RE_PACKEDDATA_LIMIT, 962 1.16 macallan (xd << 16) | (xd + wi) | (adjust << 29)); 963 1.17 macallan 964 1.3 macallan } else { 965 1.15 macallan /* we're in 16 or 32bit mode */ 966 1.15 macallan if (rop == 3) { 967 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 968 1.15 macallan PM2_RE_CONFIG, 969 1.15 macallan PM2RECFG_READ_SRC | PM2RECFG_WRITE_EN | 970 1.15 macallan PM2RECFG_ROP_EN | PM2RECFG_PACKED | (rop << 6)); 971 1.15 macallan } else { 972 1.15 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 973 1.15 macallan PM2_RE_CONFIG, 974 1.15 macallan PM2RECFG_READ_SRC | PM2RECFG_READ_DST | 975 1.15 macallan PM2RECFG_WRITE_EN | PM2RECFG_PACKED | 976 1.15 macallan PM2RECFG_ROP_EN | (rop << 6)); 977 1.15 macallan } 978 1.15 macallan rxd = xd; 979 1.15 macallan rwi = wi; 980 1.17 macallan rxdelta = xs - xd; 981 1.15 macallan } 982 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_START, 983 1.15 macallan (yd << 16) | rxd); 984 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RECT_SIZE, 985 1.15 macallan (he << 16) | rwi); 986 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_SOURCE_DELTA, 987 1.17 macallan (((ys - yd) & 0xfff) << 16) | (rxdelta & 0xfff)); 988 1.1 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_RENDER, 989 1.1 macallan PM2RE_RECTANGLE | dir); 990 1.1 macallan } 991 1.1 macallan 992 1.1 macallan static void 993 1.1 macallan pm2fb_cursor(void *cookie, int on, int row, int col) 994 1.1 macallan { 995 1.1 macallan struct rasops_info *ri = cookie; 996 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 997 1.1 macallan struct pm2fb_softc *sc = scr->scr_cookie; 998 1.1 macallan int x, y, wi, he; 999 1.1 macallan 1000 1.1 macallan wi = ri->ri_font->fontwidth; 1001 1.1 macallan he = ri->ri_font->fontheight; 1002 1.1 macallan 1003 1.1 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1004 1.1 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1005 1.1 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1006 1.1 macallan if (ri->ri_flg & RI_CURSOR) { 1007 1.1 macallan pm2fb_bitblt(sc, x, y, x, y, wi, he, 12); 1008 1.1 macallan ri->ri_flg &= ~RI_CURSOR; 1009 1.1 macallan } 1010 1.1 macallan ri->ri_crow = row; 1011 1.1 macallan ri->ri_ccol = col; 1012 1.1 macallan if (on) { 1013 1.1 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1014 1.1 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1015 1.1 macallan pm2fb_bitblt(sc, x, y, x, y, wi, he, 12); 1016 1.1 macallan ri->ri_flg |= RI_CURSOR; 1017 1.1 macallan } 1018 1.1 macallan } else { 1019 1.1 macallan scr->scr_ri.ri_crow = row; 1020 1.1 macallan scr->scr_ri.ri_ccol = col; 1021 1.1 macallan scr->scr_ri.ri_flg &= ~RI_CURSOR; 1022 1.1 macallan } 1023 1.1 macallan 1024 1.1 macallan } 1025 1.1 macallan 1026 1.1 macallan static void 1027 1.1 macallan pm2fb_putchar(void *cookie, int row, int col, u_int c, long attr) 1028 1.1 macallan { 1029 1.3 macallan struct rasops_info *ri = cookie; 1030 1.4 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1031 1.3 macallan struct vcons_screen *scr = ri->ri_hw; 1032 1.3 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1033 1.3 macallan uint32_t mode; 1034 1.3 macallan 1035 1.3 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1036 1.3 macallan void *data; 1037 1.3 macallan uint32_t fg, bg; 1038 1.3 macallan int uc, i; 1039 1.3 macallan int x, y, wi, he; 1040 1.3 macallan 1041 1.4 macallan wi = font->fontwidth; 1042 1.4 macallan he = font->fontheight; 1043 1.3 macallan 1044 1.4 macallan if (!CHAR_IN_FONT(c, font)) 1045 1.3 macallan return; 1046 1.3 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1047 1.3 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1048 1.3 macallan x = ri->ri_xorigin + col * wi; 1049 1.3 macallan y = ri->ri_yorigin + row * he; 1050 1.3 macallan if (c == 0x20) { 1051 1.3 macallan pm2fb_rectfill(sc, x, y, wi, he, bg); 1052 1.3 macallan } else { 1053 1.4 macallan uc = c - font->firstchar; 1054 1.4 macallan data = (uint8_t *)font->data + uc * ri->ri_fontscale; 1055 1.3 macallan 1056 1.3 macallan mode = PM2RM_MASK_MIRROR; 1057 1.27 macallan #if BYTE_ORDER == LITTLE_ENDIAN 1058 1.27 macallan switch (ri->ri_font->stride) { 1059 1.27 macallan case 1: 1060 1.27 macallan mode |= 4 << 7; 1061 1.27 macallan break; 1062 1.27 macallan case 2: 1063 1.27 macallan mode |= 3 << 7; 1064 1.27 macallan break; 1065 1.27 macallan } 1066 1.27 macallan #else 1067 1.3 macallan switch (ri->ri_font->stride) { 1068 1.3 macallan case 1: 1069 1.3 macallan mode |= 3 << 7; 1070 1.3 macallan break; 1071 1.3 macallan case 2: 1072 1.3 macallan mode |= 2 << 7; 1073 1.3 macallan break; 1074 1.3 macallan } 1075 1.27 macallan #endif 1076 1.3 macallan pm2fb_wait(sc, 8); 1077 1.3 macallan 1078 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1079 1.3 macallan PM2_RE_MODE, mode); 1080 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1081 1.3 macallan PM2_RE_CONFIG, PM2RECFG_WRITE_EN); 1082 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1083 1.3 macallan PM2_RE_BLOCK_COLOUR, bg); 1084 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1085 1.3 macallan PM2_RE_RECT_START, (y << 16) | x); 1086 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1087 1.3 macallan PM2_RE_RECT_SIZE, (he << 16) | wi); 1088 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1089 1.3 macallan PM2_RE_RENDER, 1090 1.3 macallan PM2RE_RECTANGLE | 1091 1.3 macallan PM2RE_INC_X | PM2RE_INC_Y | PM2RE_FASTFILL); 1092 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1093 1.3 macallan PM2_RE_BLOCK_COLOUR, fg); 1094 1.3 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1095 1.3 macallan PM2_RE_RENDER, 1096 1.3 macallan PM2RE_RECTANGLE | PM2RE_SYNC_ON_MASK | 1097 1.3 macallan PM2RE_INC_X | PM2RE_INC_Y | PM2RE_FASTFILL); 1098 1.3 macallan 1099 1.3 macallan pm2fb_wait(sc, he); 1100 1.3 macallan switch (ri->ri_font->stride) { 1101 1.3 macallan case 1: { 1102 1.3 macallan uint8_t *data8 = data; 1103 1.3 macallan uint32_t reg; 1104 1.3 macallan for (i = 0; i < he; i++) { 1105 1.3 macallan reg = *data8; 1106 1.3 macallan bus_space_write_4(sc->sc_memt, 1107 1.3 macallan sc->sc_regh, 1108 1.3 macallan PM2_RE_BITMASK, reg); 1109 1.3 macallan data8++; 1110 1.3 macallan } 1111 1.3 macallan break; 1112 1.3 macallan } 1113 1.3 macallan case 2: { 1114 1.3 macallan uint16_t *data16 = data; 1115 1.3 macallan uint32_t reg; 1116 1.3 macallan for (i = 0; i < he; i++) { 1117 1.3 macallan reg = *data16; 1118 1.3 macallan bus_space_write_4(sc->sc_memt, 1119 1.3 macallan sc->sc_regh, 1120 1.3 macallan PM2_RE_BITMASK, reg); 1121 1.3 macallan data16++; 1122 1.3 macallan } 1123 1.3 macallan break; 1124 1.3 macallan } 1125 1.3 macallan } 1126 1.3 macallan } 1127 1.20 macallan if (attr & 1) 1128 1.20 macallan pm2fb_rectfill(sc, x, y + he - 2, wi, 1, fg); 1129 1.3 macallan } 1130 1.1 macallan } 1131 1.1 macallan 1132 1.1 macallan static void 1133 1.17 macallan pm2fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1134 1.17 macallan { 1135 1.17 macallan struct rasops_info *ri = cookie; 1136 1.17 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1137 1.17 macallan struct vcons_screen *scr = ri->ri_hw; 1138 1.17 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1139 1.29 macallan uint32_t bg, fg, pixel, /*bg32,*/ fg32, aval; 1140 1.29 macallan int i, x, y, wi, he; 1141 1.29 macallan int r1, g1, b1, /*r0, g0, b0,*/ fgo/*, bgo*/; 1142 1.17 macallan uint8_t *data8; 1143 1.17 macallan int rv = GC_NOPE, cnt = 0; 1144 1.17 macallan 1145 1.17 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1146 1.17 macallan return; 1147 1.17 macallan 1148 1.17 macallan if (!CHAR_IN_FONT(c, font)) 1149 1.17 macallan return; 1150 1.17 macallan 1151 1.17 macallan wi = font->fontwidth; 1152 1.17 macallan he = font->fontheight; 1153 1.17 macallan 1154 1.17 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1155 1.20 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1156 1.17 macallan x = ri->ri_xorigin + col * wi; 1157 1.17 macallan y = ri->ri_yorigin + row * he; 1158 1.29 macallan 1159 1.29 macallan /* always blit the cell with the background colour */ 1160 1.29 macallan pm2fb_rectfill(sc, x, y, wi, he, bg); 1161 1.29 macallan 1162 1.29 macallan /* if we draw a whitespace we're done here */ 1163 1.17 macallan if (c == 0x20) { 1164 1.20 macallan if (attr & 1) 1165 1.20 macallan pm2fb_rectfill(sc, x, y + he - 2, wi, 1, fg); 1166 1.17 macallan return; 1167 1.17 macallan } 1168 1.17 macallan 1169 1.27 macallan #ifdef BITBLT_LE_WORKAROUND 1170 1.27 macallan rv = GC_NOPE; 1171 1.27 macallan #else 1172 1.17 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1173 1.17 macallan if (rv == GC_OK) 1174 1.17 macallan return; 1175 1.27 macallan #endif 1176 1.17 macallan 1177 1.17 macallan data8 = WSFONT_GLYPH(c, font); 1178 1.17 macallan 1179 1.29 macallan pm2fb_wait(sc, 7); 1180 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_MODE, 0); 1181 1.17 macallan /* 1182 1.29 macallan * XXX 1183 1.36 macallan * we *should* be able to get away without reading the framebuffer 1184 1.29 macallan * since our background colour is always constant, but for some reason 1185 1.29 macallan * that produces random, mostly black background 1186 1.17 macallan */ 1187 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_CONFIG, 1188 1.29 macallan PM2RECFG_WRITE_EN | PM2RECFG_READ_DST); 1189 1.29 macallan 1190 1.29 macallan /* enable alpha blending and R3G3B2 output */ 1191 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_ALPHA_MODE, 1192 1.29 macallan PM2AL_ENABLE | 1193 1.29 macallan PM2AL_OP_SRC_IS_SRC_ALPHA | 1194 1.29 macallan PM2AL_OP_DST_IS_ONE_MINUS_SRC_ALPHA | 1195 1.29 macallan PM2AL_332F | PM2AL_RGB); 1196 1.29 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_RE_DITHER_MODE, 1197 1.29 macallan PM2DM_ENABLE | 1198 1.29 macallan PM2DM_332F | PM2DM_RGB); 1199 1.29 macallan 1200 1.29 macallan /* 1201 1.29 macallan * we need the RGB colours here, so get offsets into rasops_cmap 1202 1.29 macallan */ 1203 1.29 macallan fgo = ((attr >> 24) & 0xf) * 3; 1204 1.29 macallan 1205 1.29 macallan r1 = rasops_cmap[fgo]; 1206 1.29 macallan g1 = rasops_cmap[fgo + 1]; 1207 1.29 macallan b1 = rasops_cmap[fgo + 2]; 1208 1.29 macallan 1209 1.29 macallan fg32 = ( r1 << 16) | (g1 << 8) | b1; 1210 1.29 macallan 1211 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1212 1.17 macallan PM2_RE_RECT_START, (y << 16) | x); 1213 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1214 1.17 macallan PM2_RE_RECT_SIZE, (he << 16) | wi); 1215 1.29 macallan 1216 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1217 1.17 macallan PM2_RE_RENDER, 1218 1.17 macallan PM2RE_RECTANGLE | PM2RE_SYNC_ON_HOST | 1219 1.17 macallan PM2RE_INC_X | PM2RE_INC_Y); 1220 1.29 macallan 1221 1.36 macallan pm2fb_wait(sc, 50); 1222 1.29 macallan 1223 1.17 macallan /* 1224 1.34 andvar * and now we just hammer the foreground colour and alpha values into 1225 1.29 macallan * the upload port 1226 1.17 macallan */ 1227 1.17 macallan for (i = 0; i < ri->ri_fontscale; i++) { 1228 1.17 macallan aval = *data8; 1229 1.29 macallan pixel = fg32 | (aval << 24); 1230 1.36 macallan cnt++; 1231 1.17 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, 1232 1.17 macallan PM2_RE_COLOUR, pixel); 1233 1.17 macallan 1234 1.36 macallan if (cnt > 48) { 1235 1.36 macallan pm2fb_wait(sc, 50); 1236 1.17 macallan cnt = 0; 1237 1.17 macallan } 1238 1.17 macallan data8++; 1239 1.17 macallan } 1240 1.17 macallan 1241 1.17 macallan if (rv == GC_ADD) { 1242 1.17 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1243 1.36 macallan } 1244 1.36 macallan 1245 1.36 macallan if (attr & 1) 1246 1.20 macallan pm2fb_rectfill(sc, x, y + he - 2, wi, 1, fg); 1247 1.17 macallan } 1248 1.17 macallan 1249 1.17 macallan static void 1250 1.1 macallan pm2fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1251 1.1 macallan { 1252 1.1 macallan struct rasops_info *ri = cookie; 1253 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1254 1.1 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1255 1.1 macallan int32_t xs, xd, y, width, height; 1256 1.1 macallan 1257 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1258 1.1 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1259 1.1 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1260 1.1 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1261 1.1 macallan width = ri->ri_font->fontwidth * ncols; 1262 1.1 macallan height = ri->ri_font->fontheight; 1263 1.1 macallan pm2fb_bitblt(sc, xs, y, xd, y, width, height, 3); 1264 1.1 macallan } 1265 1.1 macallan } 1266 1.1 macallan 1267 1.1 macallan static void 1268 1.1 macallan pm2fb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1269 1.1 macallan { 1270 1.1 macallan struct rasops_info *ri = cookie; 1271 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1272 1.1 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1273 1.1 macallan int32_t x, y, width, height, fg, bg, ul; 1274 1.1 macallan 1275 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1276 1.1 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1277 1.1 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1278 1.1 macallan width = ri->ri_font->fontwidth * ncols; 1279 1.1 macallan height = ri->ri_font->fontheight; 1280 1.1 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1281 1.1 macallan 1282 1.1 macallan pm2fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1283 1.1 macallan } 1284 1.1 macallan } 1285 1.1 macallan 1286 1.1 macallan static void 1287 1.1 macallan pm2fb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1288 1.1 macallan { 1289 1.1 macallan struct rasops_info *ri = cookie; 1290 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1291 1.1 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1292 1.1 macallan int32_t x, ys, yd, width, height; 1293 1.1 macallan 1294 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1295 1.1 macallan x = ri->ri_xorigin; 1296 1.1 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1297 1.1 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1298 1.1 macallan width = ri->ri_emuwidth; 1299 1.1 macallan height = ri->ri_font->fontheight*nrows; 1300 1.1 macallan pm2fb_bitblt(sc, x, ys, x, yd, width, height, 3); 1301 1.1 macallan } 1302 1.1 macallan } 1303 1.1 macallan 1304 1.1 macallan static void 1305 1.1 macallan pm2fb_eraserows(void *cookie, int row, int nrows, long fillattr) 1306 1.1 macallan { 1307 1.1 macallan struct rasops_info *ri = cookie; 1308 1.1 macallan struct vcons_screen *scr = ri->ri_hw; 1309 1.1 macallan struct pm2fb_softc *sc = scr->scr_cookie; 1310 1.1 macallan int32_t x, y, width, height, fg, bg, ul; 1311 1.1 macallan 1312 1.1 macallan if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1313 1.1 macallan x = ri->ri_xorigin; 1314 1.1 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1315 1.1 macallan width = ri->ri_emuwidth; 1316 1.1 macallan height = ri->ri_font->fontheight * nrows; 1317 1.1 macallan rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1318 1.1 macallan 1319 1.1 macallan pm2fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1320 1.1 macallan } 1321 1.1 macallan } 1322 1.1 macallan 1323 1.18 macallan /* 1324 1.19 macallan * Permedia2 can't blit outside of 2048x2048, so reject anything higher 1325 1.19 macallan * max. dot clock is probably too high 1326 1.18 macallan */ 1327 1.18 macallan 1328 1.18 macallan #define MODE_IS_VALID(m) (((m)->hdisplay < 2048) && \ 1329 1.19 macallan ((m)->dot_clock < 230000)) 1330 1.18 macallan 1331 1.8 macallan static void 1332 1.8 macallan pm2_setup_i2c(struct pm2fb_softc *sc) 1333 1.8 macallan { 1334 1.36 macallan int i, ok; 1335 1.8 macallan #ifdef PM2FB_DEBUG 1336 1.15 macallan int j; 1337 1.8 macallan #endif 1338 1.8 macallan 1339 1.8 macallan /* Fill in the i2c tag */ 1340 1.31 thorpej iic_tag_init(&sc->sc_i2c); 1341 1.8 macallan sc->sc_i2c.ic_cookie = sc; 1342 1.8 macallan sc->sc_i2c.ic_send_start = pm2fb_i2c_send_start; 1343 1.8 macallan sc->sc_i2c.ic_send_stop = pm2fb_i2c_send_stop; 1344 1.8 macallan sc->sc_i2c.ic_initiate_xfer = pm2fb_i2c_initiate_xfer; 1345 1.8 macallan sc->sc_i2c.ic_read_byte = pm2fb_i2c_read_byte; 1346 1.8 macallan sc->sc_i2c.ic_write_byte = pm2fb_i2c_write_byte; 1347 1.8 macallan 1348 1.8 macallan DPRINTF("data: %08x\n", bus_space_read_4(sc->sc_memt, sc->sc_regh, 1349 1.8 macallan PM2_DISPLAY_DATA)); 1350 1.8 macallan 1351 1.8 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_DISPLAY_DATA, 0); 1352 1.8 macallan 1353 1.8 macallan /* zero out the EDID buffer */ 1354 1.8 macallan memset(sc->sc_edid_data, 0, 128); 1355 1.8 macallan 1356 1.8 macallan /* Some monitors don't respond first time */ 1357 1.8 macallan i = 0; 1358 1.36 macallan ok = 0; 1359 1.36 macallan while (!ok && i < 10) { 1360 1.8 macallan ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128); 1361 1.36 macallan ok = (edid_parse(&sc->sc_edid_data[0], &sc->sc_ei) != -1); 1362 1.15 macallan i++; 1363 1.15 macallan } 1364 1.8 macallan #ifdef PM2FB_DEBUG 1365 1.15 macallan printf("i = %d\n", i); 1366 1.15 macallan for (i = 0; i < 128; i += 16) { 1367 1.15 macallan printf("%02x:", i); 1368 1.15 macallan for (j = 0; j < 16; j++) 1369 1.15 macallan printf(" %02x", sc->sc_edid_data[i + j]); 1370 1.15 macallan printf("\n"); 1371 1.15 macallan } 1372 1.15 macallan #endif 1373 1.18 macallan 1374 1.36 macallan if (ok) { 1375 1.15 macallan #ifdef PM2FB_DEBUG 1376 1.15 macallan edid_print(&sc->sc_ei); 1377 1.15 macallan #endif 1378 1.15 macallan 1379 1.15 macallan /* 1380 1.15 macallan * Now pick a mode. 1381 1.15 macallan */ 1382 1.15 macallan if ((sc->sc_ei.edid_preferred_mode != NULL)) { 1383 1.15 macallan struct videomode *m = sc->sc_ei.edid_preferred_mode; 1384 1.15 macallan if (MODE_IS_VALID(m)) { 1385 1.15 macallan sc->sc_videomode = m; 1386 1.15 macallan } else { 1387 1.15 macallan aprint_error_dev(sc->sc_dev, 1388 1.15 macallan "unable to use preferred mode\n"); 1389 1.15 macallan } 1390 1.15 macallan } 1391 1.15 macallan /* 1392 1.15 macallan * if we can't use the preferred mode go look for the 1393 1.15 macallan * best one we can support 1394 1.15 macallan */ 1395 1.15 macallan if (sc->sc_videomode == NULL) { 1396 1.15 macallan struct videomode *m = sc->sc_ei.edid_modes; 1397 1.15 macallan 1398 1.15 macallan sort_modes(sc->sc_ei.edid_modes, 1399 1.22 christos &sc->sc_ei.edid_preferred_mode, 1400 1.22 christos sc->sc_ei.edid_nmodes); 1401 1.22 christos if (sc->sc_videomode == NULL) 1402 1.22 christos for (int n = 0; n < sc->sc_ei.edid_nmodes; n++) 1403 1.22 christos if (MODE_IS_VALID(&m[n])) { 1404 1.22 christos sc->sc_videomode = &m[n]; 1405 1.22 christos break; 1406 1.22 christos } 1407 1.15 macallan } 1408 1.15 macallan } 1409 1.18 macallan if (sc->sc_videomode == NULL) { 1410 1.18 macallan /* no EDID data? */ 1411 1.18 macallan sc->sc_videomode = pick_mode_by_ref(sc->sc_width, 1412 1.18 macallan sc->sc_height, 60); 1413 1.18 macallan } 1414 1.15 macallan if (sc->sc_videomode != NULL) { 1415 1.18 macallan pm2fb_set_mode(sc, sc->sc_videomode); 1416 1.8 macallan } 1417 1.8 macallan } 1418 1.8 macallan 1419 1.8 macallan /* I2C bitbanging */ 1420 1.8 macallan static void pm2fb_i2cbb_set_bits(void *cookie, uint32_t bits) 1421 1.8 macallan { 1422 1.8 macallan struct pm2fb_softc *sc = cookie; 1423 1.8 macallan uint32_t out; 1424 1.8 macallan 1425 1.8 macallan out = bits << 2; /* bitmasks match the IN bits */ 1426 1.8 macallan 1427 1.8 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_DISPLAY_DATA, out); 1428 1.15 macallan delay(100); 1429 1.8 macallan } 1430 1.8 macallan 1431 1.8 macallan static void pm2fb_i2cbb_set_dir(void *cookie, uint32_t dir) 1432 1.8 macallan { 1433 1.8 macallan /* Nothing to do */ 1434 1.8 macallan } 1435 1.8 macallan 1436 1.8 macallan static uint32_t pm2fb_i2cbb_read(void *cookie) 1437 1.8 macallan { 1438 1.8 macallan struct pm2fb_softc *sc = cookie; 1439 1.8 macallan uint32_t bits; 1440 1.8 macallan 1441 1.8 macallan bits = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_DISPLAY_DATA); 1442 1.8 macallan return bits; 1443 1.8 macallan } 1444 1.8 macallan 1445 1.8 macallan /* higher level I2C stuff */ 1446 1.8 macallan static int 1447 1.8 macallan pm2fb_i2c_send_start(void *cookie, int flags) 1448 1.8 macallan { 1449 1.8 macallan return (i2c_bitbang_send_start(cookie, flags, &pm2fb_i2cbb_ops)); 1450 1.8 macallan } 1451 1.8 macallan 1452 1.8 macallan static int 1453 1.8 macallan pm2fb_i2c_send_stop(void *cookie, int flags) 1454 1.8 macallan { 1455 1.8 macallan 1456 1.8 macallan return (i2c_bitbang_send_stop(cookie, flags, &pm2fb_i2cbb_ops)); 1457 1.8 macallan } 1458 1.8 macallan 1459 1.8 macallan static int 1460 1.8 macallan pm2fb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 1461 1.8 macallan { 1462 1.8 macallan 1463 1.8 macallan return (i2c_bitbang_initiate_xfer(cookie, addr, flags, 1464 1.8 macallan &pm2fb_i2cbb_ops)); 1465 1.8 macallan } 1466 1.8 macallan 1467 1.8 macallan static int 1468 1.8 macallan pm2fb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) 1469 1.8 macallan { 1470 1.8 macallan return (i2c_bitbang_read_byte(cookie, valp, flags, &pm2fb_i2cbb_ops)); 1471 1.8 macallan } 1472 1.8 macallan 1473 1.8 macallan static int 1474 1.8 macallan pm2fb_i2c_write_byte(void *cookie, uint8_t val, int flags) 1475 1.8 macallan { 1476 1.8 macallan return (i2c_bitbang_write_byte(cookie, val, flags, &pm2fb_i2cbb_ops)); 1477 1.8 macallan } 1478 1.15 macallan 1479 1.15 macallan static int 1480 1.27 macallan pm2vfb_set_pll(struct pm2fb_softc *sc, int freq) 1481 1.15 macallan { 1482 1.24 martin int m, n, p, diff, out_freq, bm = 1, bn = 3, bp = 0, 1483 1.24 martin bdiff = 1000000 /* , bfreq */; 1484 1.15 macallan int fi; 1485 1.18 macallan uint8_t temp; 1486 1.15 macallan 1487 1.18 macallan for (m = 1; m < 128; m++) { 1488 1.18 macallan for (n = 2 * m + 1; n < 256; n++) { 1489 1.27 macallan fi = PM2_EXT_CLOCK_FREQ * n / m; 1490 1.18 macallan for (p = 0; p < 2; p++) { 1491 1.18 macallan out_freq = fi >> (p + 1); 1492 1.15 macallan diff = abs(out_freq - freq); 1493 1.15 macallan if (diff < bdiff) { 1494 1.15 macallan bdiff = diff; 1495 1.24 martin /* bfreq = out_freq; */ 1496 1.15 macallan bm = m; 1497 1.15 macallan bn = n; 1498 1.15 macallan bp = p; 1499 1.15 macallan } 1500 1.15 macallan } 1501 1.15 macallan } 1502 1.15 macallan } 1503 1.20 macallan #if 0 1504 1.20 macallan /* 1505 1.20 macallan * XXX 1506 1.20 macallan * output between switching modes and attaching a wsdisplay will 1507 1.20 macallan * go through firmware calls on sparc64 and potentially mess up 1508 1.20 macallan * our drawing engine state 1509 1.20 macallan */ 1510 1.18 macallan DPRINTF("best: %d kHz ( %d off ), %d %d %d\n", bfreq, bdiff, bm, bn, bp); 1511 1.20 macallan #endif 1512 1.18 macallan temp = pm2fb_read_dac(sc, PM2V_DAC_CLOCK_CONTROL) & 0xfc; 1513 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_CONTROL, 0); 1514 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_CLOCK_A_M, bm); 1515 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_CLOCK_A_N, bn); 1516 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_CLOCK_A_P, bp); 1517 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_CLOCK_CONTROL, temp | 3); 1518 1.15 macallan return 0; 1519 1.15 macallan } 1520 1.18 macallan 1521 1.27 macallan static int 1522 1.27 macallan pm2fb_set_pll(struct pm2fb_softc *sc, int freq) 1523 1.27 macallan { 1524 1.27 macallan uint8_t reg, bm = 0, bn = 0, bp = 0; 1525 1.27 macallan unsigned int m, n, p, fi, diff, out_freq, bdiff = 1000000; 1526 1.27 macallan 1527 1.27 macallan for (n = 2; n < 15; n++) { 1528 1.27 macallan for (m = 2 ; m < 256; m++) { 1529 1.27 macallan fi = PM2_EXT_CLOCK_FREQ * m / n; 1530 1.27 macallan if (fi >= PM2_PLL_FREQ_MIN && fi <= PM2_PLL_FREQ_MAX) { 1531 1.27 macallan for (p = 0; p < 5; p++) { 1532 1.27 macallan out_freq = fi >> p; 1533 1.27 macallan diff = abs(out_freq - freq); 1534 1.27 macallan if (diff < bdiff) { 1535 1.27 macallan bm = m; 1536 1.27 macallan bn = n; 1537 1.27 macallan bp = p; 1538 1.27 macallan bdiff = diff; 1539 1.27 macallan } 1540 1.27 macallan } 1541 1.27 macallan } 1542 1.27 macallan } 1543 1.27 macallan } 1544 1.27 macallan 1545 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_PIXELCLKA_M, bm); 1546 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_PIXELCLKA_N, bn); 1547 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_PIXELCLKA_P, (bp | 0x08)); 1548 1.27 macallan 1549 1.27 macallan do { 1550 1.27 macallan reg = bus_space_read_1(sc->sc_memt, sc->sc_regh, 1551 1.27 macallan PM2_DAC_INDEX_DATA); 1552 1.27 macallan } while (reg == PCLK_LOCKED); 1553 1.27 macallan 1554 1.27 macallan return 0; 1555 1.27 macallan } 1556 1.27 macallan 1557 1.27 macallan /* 1558 1.27 macallan * most of the following was adapted from the xf86-video-glint driver's 1559 1.27 macallan * pm2_dac.c (8bpp only) 1560 1.27 macallan */ 1561 1.27 macallan static void 1562 1.27 macallan pm2fb_set_dac(struct pm2fb_softc *sc, const struct videomode *mode) 1563 1.27 macallan { 1564 1.27 macallan int t1, t2, t3, t4, stride; 1565 1.27 macallan uint32_t vclk, tmp; 1566 1.27 macallan uint8_t sync = 0; 1567 1.27 macallan 1568 1.27 macallan t1 = mode->hsync_start - mode->hdisplay; 1569 1.27 macallan t2 = mode->vsync_start - mode->vdisplay; 1570 1.27 macallan t3 = mode->hsync_end - mode->hsync_start; 1571 1.27 macallan t4 = mode->vsync_end - mode->vsync_start; 1572 1.27 macallan 1573 1.27 macallan /* first round up to the next multiple of 32 */ 1574 1.27 macallan stride = (mode->hdisplay + 31) & ~31; 1575 1.27 macallan /* then find the next bigger one that we have partial products for */ 1576 1.27 macallan while ((partprodPermedia[stride >> 5] == -1) && (stride < 2048)) { 1577 1.27 macallan stride += 32; 1578 1.27 macallan } 1579 1.27 macallan 1580 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HTOTAL, 1581 1.27 macallan ((mode->htotal) >> 2) - 1); 1582 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HSYNC_END, 1583 1.27 macallan (t1 + t3) >> 2); 1584 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HSYNC_START, 1585 1.27 macallan (t1 >> 2)); 1586 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HBLANK_END, 1587 1.27 macallan (mode->htotal - mode->hdisplay) >> 2); 1588 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HGATE_END, 1589 1.27 macallan (mode->htotal - mode->hdisplay) >> 2); 1590 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_SCREEN_STRIDE, 1591 1.27 macallan stride >> 3); 1592 1.27 macallan 1593 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VTOTAL, 1594 1.27 macallan mode->vtotal - 2); 1595 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VSYNC_END, 1596 1.27 macallan t2 + t4 - 1); 1597 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VSYNC_START, 1598 1.27 macallan t2 - 1); 1599 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VBLANK_END, 1600 1.27 macallan mode->vtotal - mode->vdisplay); 1601 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VIDEO_CONTROL, 1602 1.27 macallan PM2_VC_VIDEO_ENABLE | 1603 1.27 macallan PM2_VC_HSYNC_ACT_HIGH | PM2_VC_VSYNC_ACT_HIGH); 1604 1.27 macallan 1605 1.27 macallan vclk = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_VCLKCTL); 1606 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VCLKCTL, 1607 1.27 macallan vclk & 0xfffffffc); 1608 1.27 macallan 1609 1.27 macallan tmp = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_CHIP_CONFIG); 1610 1.27 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_CHIP_CONFIG, 1611 1.27 macallan tmp & 0xffffffdd); 1612 1.27 macallan 1613 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_MODE_CONTROL, MOC_BUFFERFRONT); 1614 1.27 macallan pm2fb_set_pll(sc, mode->dot_clock); 1615 1.27 macallan 1616 1.27 macallan sync = MC_PALETTE_8BIT; 1617 1.27 macallan 1618 1.27 macallan if (!(mode->flags & VID_PHSYNC)) 1619 1.27 macallan sync |= MC_HSYNC_INV; 1620 1.27 macallan if (!(mode->flags & VID_PVSYNC)) 1621 1.27 macallan sync |= MC_VSYNC_INV; 1622 1.27 macallan 1623 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_MISC_CONTROL, sync); 1624 1.27 macallan pm2fb_write_dac(sc, PM2_DAC_COLOR_MODE, 1625 1.27 macallan CM_PALETTE | CM_GUI_ENABLE | CM_RGB); 1626 1.27 macallan 1627 1.27 macallan sc->sc_width = mode->hdisplay; 1628 1.27 macallan sc->sc_height = mode->vdisplay; 1629 1.27 macallan sc->sc_depth = 8; 1630 1.27 macallan sc->sc_stride = stride; 1631 1.27 macallan aprint_normal_dev(sc->sc_dev, "pm2 using %d x %d in 8 bit, stride %d\n", 1632 1.27 macallan sc->sc_width, sc->sc_height, stride); 1633 1.27 macallan } 1634 1.27 macallan 1635 1.18 macallan /* 1636 1.18 macallan * most of the following was adapted from the xf86-video-glint driver's 1637 1.18 macallan * pm2v_dac.c 1638 1.18 macallan */ 1639 1.18 macallan static void 1640 1.27 macallan pm2vfb_set_dac(struct pm2fb_softc *sc, const struct videomode *mode) 1641 1.18 macallan { 1642 1.19 macallan int t1, t2, t3, t4, stride; 1643 1.18 macallan uint32_t vclk; 1644 1.18 macallan uint8_t sync = 0; 1645 1.18 macallan 1646 1.18 macallan t1 = mode->hsync_start - mode->hdisplay; 1647 1.18 macallan t2 = mode->vsync_start - mode->vdisplay; 1648 1.18 macallan t3 = mode->hsync_end - mode->hsync_start; 1649 1.18 macallan t4 = mode->vsync_end - mode->vsync_start; 1650 1.18 macallan 1651 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HTOTAL, 1652 1.18 macallan ((mode->htotal) >> 3) - 1); 1653 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HSYNC_END, 1654 1.18 macallan (t1 + t3) >> 3); 1655 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HSYNC_START, 1656 1.18 macallan (t1 >> 3) - 1); 1657 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HBLANK_END, 1658 1.18 macallan (mode->htotal - mode->hdisplay) >> 3); 1659 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_HGATE_END, 1660 1.18 macallan (mode->htotal - mode->hdisplay) >> 3); 1661 1.19 macallan 1662 1.19 macallan /* first round up to the next multiple of 32 */ 1663 1.19 macallan stride = (mode->hdisplay + 31) & ~31; 1664 1.19 macallan /* then find the next bigger one that we have partial products for */ 1665 1.19 macallan while ((partprodPermedia[stride >> 5] == -1) && (stride < 2048)) { 1666 1.19 macallan stride += 32; 1667 1.19 macallan } 1668 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_SCREEN_STRIDE, 1669 1.19 macallan stride >> 3); 1670 1.18 macallan 1671 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VTOTAL, 1672 1.18 macallan mode->vtotal - 1); 1673 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VSYNC_END, 1674 1.18 macallan t2 + t4); 1675 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VSYNC_START, 1676 1.18 macallan t2); 1677 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VBLANK_END, 1678 1.18 macallan mode->vtotal - mode->vdisplay); 1679 1.18 macallan 1680 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VIDEO_CONTROL, 1681 1.18 macallan PM2_VC_VIDEO_ENABLE | PM2_VC_RAMDAC_64BIT | 1682 1.18 macallan PM2_VC_HSYNC_ACT_HIGH | PM2_VC_VSYNC_ACT_HIGH); 1683 1.18 macallan 1684 1.18 macallan vclk = bus_space_read_4(sc->sc_memt, sc->sc_regh, PM2_VCLKCTL); 1685 1.18 macallan bus_space_write_4(sc->sc_memt, sc->sc_regh, PM2_VCLKCTL, 1686 1.18 macallan vclk & 0xfffffffc); 1687 1.18 macallan 1688 1.27 macallan pm2vfb_set_pll(sc, mode->dot_clock / 2); 1689 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_MISC_CONTROL, PM2V_DAC_8BIT); 1690 1.18 macallan 1691 1.18 macallan if (mode->flags & VID_PHSYNC) 1692 1.18 macallan sync |= PM2V_DAC_HSYNC_INV; 1693 1.18 macallan if (mode->flags & VID_PVSYNC) 1694 1.18 macallan sync |= PM2V_DAC_VSYNC_INV; 1695 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_SYNC_CONTROL, sync); 1696 1.18 macallan 1697 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_COLOR_FORMAT, PM2V_DAC_PALETTE); 1698 1.18 macallan pm2fb_write_dac(sc, PM2V_DAC_PIXEL_SIZE, PM2V_PS_8BIT); 1699 1.18 macallan sc->sc_width = mode->hdisplay; 1700 1.18 macallan sc->sc_height = mode->vdisplay; 1701 1.18 macallan sc->sc_depth = 8; 1702 1.19 macallan sc->sc_stride = stride; 1703 1.27 macallan aprint_normal_dev(sc->sc_dev, "pm2v using %d x %d in 8 bit, stride %d\n", 1704 1.19 macallan sc->sc_width, sc->sc_height, stride); 1705 1.18 macallan } 1706 1.27 macallan 1707 1.27 macallan static void 1708 1.27 macallan pm2fb_set_mode(struct pm2fb_softc *sc, const struct videomode *mode) 1709 1.27 macallan { 1710 1.27 macallan if (sc->sc_is_pm2) { 1711 1.27 macallan pm2fb_set_dac(sc, mode); 1712 1.27 macallan } else { 1713 1.27 macallan pm2vfb_set_dac(sc, mode); 1714 1.27 macallan } 1715 1.27 macallan } 1716