1 1.50 thorpej /* $NetBSD: crmfb.c,v 1.50 2023/12/20 15:29:07 thorpej Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 jmcneill * Copyright (c) 2007 Jared D. McNeill <jmcneill (at) invisible.ca> 5 1.12 macallan * 2008 Michael Lorenz <macallan (at) netbsd.org> 6 1.1 jmcneill * All rights reserved. 7 1.1 jmcneill * 8 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 9 1.1 jmcneill * modification, are permitted provided that the following conditions 10 1.1 jmcneill * are met: 11 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 12 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 13 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 15 1.1 jmcneill * documentation and/or other materials provided with the distribution. 16 1.1 jmcneill * 17 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 28 1.1 jmcneill */ 29 1.1 jmcneill 30 1.1 jmcneill /* 31 1.1 jmcneill * SGI-CRM (O2) Framebuffer driver 32 1.1 jmcneill */ 33 1.1 jmcneill 34 1.1 jmcneill #include <sys/cdefs.h> 35 1.50 thorpej __KERNEL_RCSID(0, "$NetBSD: crmfb.c,v 1.50 2023/12/20 15:29:07 thorpej Exp $"); 36 1.1 jmcneill 37 1.1 jmcneill #include <sys/param.h> 38 1.1 jmcneill #include <sys/systm.h> 39 1.1 jmcneill #include <sys/device.h> 40 1.1 jmcneill 41 1.1 jmcneill #include <machine/autoconf.h> 42 1.35 dyoung #include <sys/bus.h> 43 1.1 jmcneill #include <machine/machtype.h> 44 1.1 jmcneill #include <machine/vmparam.h> 45 1.1 jmcneill 46 1.2 jmcneill #include <dev/arcbios/arcbios.h> 47 1.2 jmcneill #include <dev/arcbios/arcbiosvar.h> 48 1.2 jmcneill 49 1.1 jmcneill #include <dev/wscons/wsdisplayvar.h> 50 1.1 jmcneill #include <dev/wscons/wsconsio.h> 51 1.1 jmcneill #include <dev/wsfont/wsfont.h> 52 1.1 jmcneill #include <dev/rasops/rasops.h> 53 1.1 jmcneill #include <dev/wscons/wsdisplay_vconsvar.h> 54 1.1 jmcneill 55 1.30 macallan #include <dev/i2c/i2cvar.h> 56 1.30 macallan #include <dev/i2c/i2c_bitbang.h> 57 1.30 macallan #include <dev/i2c/ddcvar.h> 58 1.30 macallan #include <dev/videomode/videomode.h> 59 1.45 jmcneill #include <dev/videomode/vesagtf.h> 60 1.30 macallan #include <dev/videomode/edidvar.h> 61 1.30 macallan 62 1.7 macallan #include <arch/sgimips/dev/crmfbreg.h> 63 1.7 macallan 64 1.32 macallan #include "opt_crmfb.h" 65 1.32 macallan 66 1.32 macallan #ifdef CRMFB_DEBUG 67 1.32 macallan #define DPRINTF printf 68 1.32 macallan #else 69 1.32 macallan #define DPRINTF while (0) printf 70 1.32 macallan #endif 71 1.3 jmcneill 72 1.1 jmcneill struct wsscreen_descr crmfb_defaultscreen = { 73 1.1 jmcneill "default", 74 1.1 jmcneill 0, 0, 75 1.1 jmcneill NULL, 76 1.1 jmcneill 8, 16, 77 1.44 macallan WSSCREEN_WSCOLORS | WSSCREEN_RESIZE, 78 1.1 jmcneill NULL, 79 1.1 jmcneill }; 80 1.1 jmcneill 81 1.1 jmcneill const struct wsscreen_descr *_crmfb_scrlist[] = { 82 1.1 jmcneill &crmfb_defaultscreen, 83 1.1 jmcneill }; 84 1.1 jmcneill 85 1.1 jmcneill struct wsscreen_list crmfb_screenlist = { 86 1.1 jmcneill sizeof(_crmfb_scrlist) / sizeof(struct wsscreen_descr *), 87 1.1 jmcneill _crmfb_scrlist 88 1.1 jmcneill }; 89 1.1 jmcneill 90 1.1 jmcneill static struct vcons_screen crmfb_console_screen; 91 1.1 jmcneill 92 1.1 jmcneill static int crmfb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 93 1.1 jmcneill static paddr_t crmfb_mmap(void *, void *, off_t, int); 94 1.1 jmcneill static void crmfb_init_screen(void *, struct vcons_screen *, int, long *); 95 1.1 jmcneill 96 1.1 jmcneill struct wsdisplay_accessops crmfb_accessops = { 97 1.1 jmcneill crmfb_ioctl, 98 1.1 jmcneill crmfb_mmap, 99 1.1 jmcneill NULL, /* alloc_screen */ 100 1.1 jmcneill NULL, /* free_screen */ 101 1.1 jmcneill NULL, /* show_screen */ 102 1.1 jmcneill NULL, /* load_font */ 103 1.1 jmcneill NULL, /* pollc */ 104 1.1 jmcneill NULL, /* scroll */ 105 1.1 jmcneill }; 106 1.1 jmcneill 107 1.1 jmcneill /* Memory to allocate to SGI-CRM -- remember, this is stolen from 108 1.1 jmcneill * host memory! 109 1.1 jmcneill */ 110 1.1 jmcneill #define CRMFB_TILESIZE (512*128) 111 1.1 jmcneill 112 1.29 macallan static int crmfb_match(device_t, struct cfdata *, void *); 113 1.29 macallan static void crmfb_attach(device_t, device_t, void *); 114 1.1 jmcneill int crmfb_probe(void); 115 1.1 jmcneill 116 1.1 jmcneill #define KERNADDR(p) ((void *)((p).addr)) 117 1.1 jmcneill #define DMAADDR(p) ((p).map->dm_segs[0].ds_addr) 118 1.1 jmcneill 119 1.10 sekiya #define CRMFB_REG_MASK(msb, lsb) \ 120 1.10 sekiya ( (((uint32_t) 1 << ((msb)-(lsb)+1)) - 1) << (lsb) ) 121 1.10 sekiya 122 1.10 sekiya 123 1.1 jmcneill struct crmfb_dma { 124 1.1 jmcneill bus_dmamap_t map; 125 1.1 jmcneill void *addr; 126 1.1 jmcneill bus_dma_segment_t segs[1]; 127 1.1 jmcneill int nsegs; 128 1.1 jmcneill size_t size; 129 1.1 jmcneill }; 130 1.1 jmcneill 131 1.1 jmcneill struct crmfb_softc { 132 1.29 macallan device_t sc_dev; 133 1.1 jmcneill struct vcons_data sc_vd; 134 1.30 macallan struct i2c_controller sc_i2c; 135 1.30 macallan int sc_dir; 136 1.1 jmcneill 137 1.1 jmcneill bus_space_tag_t sc_iot; 138 1.1 jmcneill bus_space_handle_t sc_ioh; 139 1.11 macallan bus_space_handle_t sc_reh; 140 1.7 macallan 141 1.1 jmcneill bus_dma_tag_t sc_dmat; 142 1.1 jmcneill 143 1.1 jmcneill struct crmfb_dma sc_dma; 144 1.1 jmcneill struct crmfb_dma sc_dmai; 145 1.1 jmcneill 146 1.1 jmcneill int sc_width; 147 1.1 jmcneill int sc_height; 148 1.1 jmcneill int sc_depth; 149 1.34 macallan int sc_console_depth; 150 1.11 macallan int sc_tiles_x, sc_tiles_y; 151 1.1 jmcneill uint32_t sc_fbsize; 152 1.18 macallan int sc_mte_direction; 153 1.34 macallan int sc_mte_x_shift; 154 1.34 macallan uint32_t sc_mte_mode; 155 1.38 macallan uint32_t sc_de_mode; 156 1.39 macallan uint32_t sc_src_mode; 157 1.39 macallan uint32_t sc_dst_mode; 158 1.39 macallan int sc_needs_sync; 159 1.39 macallan uint8_t *sc_lptr; 160 1.21 macallan paddr_t sc_linear; 161 1.38 macallan uint32_t sc_vtflags; 162 1.38 macallan int sc_wsmode, sc_video_on; 163 1.38 macallan uint8_t sc_edid_data[128]; 164 1.38 macallan struct edid_info sc_edid_info; 165 1.6 macallan 166 1.6 macallan /* cursor stuff */ 167 1.6 macallan int sc_cur_x; 168 1.6 macallan int sc_cur_y; 169 1.6 macallan int sc_hot_x; 170 1.6 macallan int sc_hot_y; 171 1.6 macallan 172 1.1 jmcneill u_char sc_cmap_red[256]; 173 1.1 jmcneill u_char sc_cmap_green[256]; 174 1.1 jmcneill u_char sc_cmap_blue[256]; 175 1.1 jmcneill }; 176 1.1 jmcneill 177 1.1 jmcneill static int crmfb_putcmap(struct crmfb_softc *, struct wsdisplay_cmap *); 178 1.1 jmcneill static int crmfb_getcmap(struct crmfb_softc *, struct wsdisplay_cmap *); 179 1.1 jmcneill static void crmfb_set_palette(struct crmfb_softc *, 180 1.1 jmcneill int, uint8_t, uint8_t, uint8_t); 181 1.6 macallan static int crmfb_set_curpos(struct crmfb_softc *, int, int); 182 1.6 macallan static int crmfb_gcursor(struct crmfb_softc *, struct wsdisplay_cursor *); 183 1.6 macallan static int crmfb_scursor(struct crmfb_softc *, struct wsdisplay_cursor *); 184 1.7 macallan static inline void crmfb_write_reg(struct crmfb_softc *, int, uint32_t); 185 1.11 macallan static inline uint32_t crmfb_read_reg(struct crmfb_softc *, int); 186 1.11 macallan static int crmfb_wait_dma_idle(struct crmfb_softc *); 187 1.7 macallan 188 1.7 macallan /* setup video hw in given colour depth */ 189 1.7 macallan static int crmfb_setup_video(struct crmfb_softc *, int); 190 1.7 macallan static void crmfb_setup_palette(struct crmfb_softc *); 191 1.1 jmcneill 192 1.11 macallan static void crmfb_fill_rect(struct crmfb_softc *, int, int, int, int, uint32_t); 193 1.11 macallan static void crmfb_bitblt(struct crmfb_softc *, int, int, int, int, int, int, 194 1.11 macallan uint32_t); 195 1.15 macallan static void crmfb_scroll(struct crmfb_softc *, int, int, int, int, int, int); 196 1.11 macallan 197 1.11 macallan static void crmfb_copycols(void *, int, int, int, int); 198 1.11 macallan static void crmfb_erasecols(void *, int, int, int, long); 199 1.11 macallan static void crmfb_copyrows(void *, int, int, int); 200 1.11 macallan static void crmfb_eraserows(void *, int, int, long); 201 1.11 macallan static void crmfb_cursor(void *, int, int, int); 202 1.11 macallan static void crmfb_putchar(void *, int, int, u_int, long); 203 1.39 macallan static void crmfb_putchar_aa(void *, int, int, u_int, long); 204 1.11 macallan 205 1.30 macallan /* I2C glue */ 206 1.30 macallan static int crmfb_i2c_send_start(void *, int); 207 1.30 macallan static int crmfb_i2c_send_stop(void *, int); 208 1.30 macallan static int crmfb_i2c_initiate_xfer(void *, i2c_addr_t, int); 209 1.30 macallan static int crmfb_i2c_read_byte(void *, uint8_t *, int); 210 1.30 macallan static int crmfb_i2c_write_byte(void *, uint8_t, int); 211 1.30 macallan 212 1.30 macallan /* I2C bitbang glue */ 213 1.30 macallan static void crmfb_i2cbb_set_bits(void *, uint32_t); 214 1.30 macallan static void crmfb_i2cbb_set_dir(void *, uint32_t); 215 1.30 macallan static uint32_t crmfb_i2cbb_read(void *); 216 1.30 macallan 217 1.30 macallan static const struct i2c_bitbang_ops crmfb_i2cbb_ops = { 218 1.30 macallan crmfb_i2cbb_set_bits, 219 1.30 macallan crmfb_i2cbb_set_dir, 220 1.30 macallan crmfb_i2cbb_read, 221 1.30 macallan { 222 1.30 macallan CRMFB_I2C_SDA, 223 1.30 macallan CRMFB_I2C_SCL, 224 1.30 macallan 0, 225 1.30 macallan 1 226 1.30 macallan } 227 1.30 macallan }; 228 1.30 macallan static void crmfb_setup_ddc(struct crmfb_softc *); 229 1.30 macallan 230 1.32 macallan /* mode setting stuff */ 231 1.32 macallan static uint32_t calc_pll(int); /* frequency in kHz */ 232 1.32 macallan static int crmfb_set_mode(struct crmfb_softc *, const struct videomode *); 233 1.45 jmcneill static int crmfb_parse_mode(const char *, struct videomode *); 234 1.32 macallan 235 1.29 macallan CFATTACH_DECL_NEW(crmfb, sizeof(struct crmfb_softc), 236 1.1 jmcneill crmfb_match, crmfb_attach, NULL, NULL); 237 1.1 jmcneill 238 1.1 jmcneill static int 239 1.29 macallan crmfb_match(device_t parent, struct cfdata *cf, void *opaque) 240 1.1 jmcneill { 241 1.1 jmcneill return crmfb_probe(); 242 1.1 jmcneill } 243 1.1 jmcneill 244 1.1 jmcneill static void 245 1.29 macallan crmfb_attach(device_t parent, device_t self, void *opaque) 246 1.1 jmcneill { 247 1.1 jmcneill struct mainbus_attach_args *ma; 248 1.1 jmcneill struct crmfb_softc *sc; 249 1.1 jmcneill struct rasops_info *ri; 250 1.1 jmcneill struct wsemuldisplaydev_attach_args aa; 251 1.1 jmcneill uint32_t d, h; 252 1.1 jmcneill uint16_t *p; 253 1.1 jmcneill unsigned long v; 254 1.1 jmcneill long defattr; 255 1.2 jmcneill const char *consdev; 256 1.45 jmcneill const char *modestr; 257 1.45 jmcneill struct videomode mode, *pmode; 258 1.11 macallan int rv, i; 259 1.1 jmcneill 260 1.29 macallan sc = device_private(self); 261 1.29 macallan sc->sc_dev = self; 262 1.29 macallan 263 1.1 jmcneill ma = (struct mainbus_attach_args *)opaque; 264 1.1 jmcneill 265 1.40 macallan sc->sc_iot = normal_memt; 266 1.1 jmcneill sc->sc_dmat = &sgimips_default_bus_dma_tag; 267 1.1 jmcneill sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL; 268 1.1 jmcneill 269 1.1 jmcneill aprint_normal(": SGI CRIME Graphics Display Engine\n"); 270 1.1 jmcneill rv = bus_space_map(sc->sc_iot, ma->ma_addr, 0 /* XXX */, 271 1.1 jmcneill BUS_SPACE_MAP_LINEAR, &sc->sc_ioh); 272 1.1 jmcneill if (rv) 273 1.1 jmcneill panic("crmfb_attach: can't map I/O space"); 274 1.11 macallan rv = bus_space_map(sc->sc_iot, 0x15000000, 0x6000, 0, &sc->sc_reh); 275 1.11 macallan if (rv) 276 1.11 macallan panic("crmfb_attach: can't map rendering engine"); 277 1.1 jmcneill 278 1.1 jmcneill /* determine mode configured by firmware */ 279 1.9 jmcneill d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_VT_HCMAP); 280 1.9 jmcneill sc->sc_width = (d >> CRMFB_VT_HCMAP_ON_SHIFT) & 0xfff; 281 1.1 jmcneill d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_VT_VCMAP); 282 1.9 jmcneill sc->sc_height = (d >> CRMFB_VT_VCMAP_ON_SHIFT) & 0xfff; 283 1.1 jmcneill d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_FRM_TILESIZE); 284 1.1 jmcneill h = (d >> CRMFB_FRM_TILESIZE_DEPTH_SHIFT) & 0x3; 285 1.1 jmcneill if (h == 0) 286 1.1 jmcneill sc->sc_depth = 8; 287 1.1 jmcneill else if (h == 1) 288 1.1 jmcneill sc->sc_depth = 16; 289 1.1 jmcneill else 290 1.1 jmcneill sc->sc_depth = 32; 291 1.1 jmcneill 292 1.4 martin if (sc->sc_width == 0 || sc->sc_height == 0) { 293 1.38 macallan /* 294 1.38 macallan * XXX 295 1.38 macallan * actually, these days we probably could 296 1.38 macallan */ 297 1.29 macallan aprint_error_dev(sc->sc_dev, 298 1.29 macallan "device unusable if not setup by firmware\n"); 299 1.4 martin bus_space_unmap(sc->sc_iot, sc->sc_ioh, 0 /* XXX */); 300 1.4 martin return; 301 1.4 martin } 302 1.4 martin 303 1.29 macallan aprint_normal_dev(sc->sc_dev, "initial resolution %dx%d\n", 304 1.29 macallan sc->sc_width, sc->sc_height); 305 1.1 jmcneill 306 1.34 macallan sc->sc_console_depth = 8; 307 1.34 macallan 308 1.32 macallan crmfb_setup_ddc(sc); 309 1.45 jmcneill pmode = sc->sc_edid_info.edid_preferred_mode; 310 1.45 jmcneill 311 1.45 jmcneill modestr = arcbios_GetEnvironmentVariable("crmfb_mode"); 312 1.45 jmcneill if (crmfb_parse_mode(modestr, &mode) == 0) 313 1.45 jmcneill pmode = &mode; 314 1.45 jmcneill 315 1.45 jmcneill if (pmode != NULL && crmfb_set_mode(sc, pmode)) 316 1.45 jmcneill aprint_normal_dev(sc->sc_dev, "using %dx%d\n", 317 1.45 jmcneill sc->sc_width, sc->sc_height); 318 1.45 jmcneill 319 1.7 macallan /* 320 1.7 macallan * first determine how many tiles we need 321 1.7 macallan * in 32bit each tile is 128x128 pixels 322 1.7 macallan */ 323 1.11 macallan sc->sc_tiles_x = (sc->sc_width + 127) >> 7; 324 1.11 macallan sc->sc_tiles_y = (sc->sc_height + 127) >> 7; 325 1.11 macallan sc->sc_fbsize = 0x10000 * sc->sc_tiles_x * sc->sc_tiles_y; 326 1.1 jmcneill 327 1.7 macallan sc->sc_dmai.size = 256 * sizeof(uint16_t); 328 1.1 jmcneill rv = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmai.size, 65536, 0, 329 1.1 jmcneill sc->sc_dmai.segs, 330 1.1 jmcneill sizeof(sc->sc_dmai.segs) / sizeof(sc->sc_dmai.segs[0]), 331 1.1 jmcneill &sc->sc_dmai.nsegs, BUS_DMA_NOWAIT); 332 1.1 jmcneill if (rv) 333 1.1 jmcneill panic("crmfb_attach: can't allocate DMA memory"); 334 1.1 jmcneill rv = bus_dmamem_map(sc->sc_dmat, sc->sc_dmai.segs, sc->sc_dmai.nsegs, 335 1.1 jmcneill sc->sc_dmai.size, &sc->sc_dmai.addr, 336 1.1 jmcneill BUS_DMA_NOWAIT); 337 1.1 jmcneill if (rv) 338 1.1 jmcneill panic("crmfb_attach: can't map DMA memory"); 339 1.1 jmcneill rv = bus_dmamap_create(sc->sc_dmat, sc->sc_dmai.size, 1, 340 1.1 jmcneill sc->sc_dmai.size, 0, BUS_DMA_NOWAIT, &sc->sc_dmai.map); 341 1.1 jmcneill if (rv) 342 1.1 jmcneill panic("crmfb_attach: can't create DMA map"); 343 1.1 jmcneill rv = bus_dmamap_load(sc->sc_dmat, sc->sc_dmai.map, sc->sc_dmai.addr, 344 1.1 jmcneill sc->sc_dmai.size, NULL, BUS_DMA_NOWAIT); 345 1.1 jmcneill if (rv) 346 1.1 jmcneill panic("crmfb_attach: can't load DMA map"); 347 1.1 jmcneill 348 1.39 macallan /* allocate an extra 128Kb for a linear buffer */ 349 1.39 macallan sc->sc_dma.size = 0x10000 * (16 * sc->sc_tiles_x + 2); 350 1.1 jmcneill rv = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dma.size, 65536, 0, 351 1.1 jmcneill sc->sc_dma.segs, 352 1.1 jmcneill sizeof(sc->sc_dma.segs) / sizeof(sc->sc_dma.segs[0]), 353 1.1 jmcneill &sc->sc_dma.nsegs, BUS_DMA_NOWAIT); 354 1.1 jmcneill if (rv) 355 1.1 jmcneill panic("crmfb_attach: can't allocate DMA memory"); 356 1.1 jmcneill rv = bus_dmamem_map(sc->sc_dmat, sc->sc_dma.segs, sc->sc_dma.nsegs, 357 1.1 jmcneill sc->sc_dma.size, &sc->sc_dma.addr, 358 1.1 jmcneill BUS_DMA_NOWAIT | BUS_DMA_COHERENT); 359 1.1 jmcneill if (rv) 360 1.1 jmcneill panic("crmfb_attach: can't map DMA memory"); 361 1.1 jmcneill rv = bus_dmamap_create(sc->sc_dmat, sc->sc_dma.size, 1, 362 1.1 jmcneill sc->sc_dma.size, 0, BUS_DMA_NOWAIT, &sc->sc_dma.map); 363 1.1 jmcneill if (rv) 364 1.1 jmcneill panic("crmfb_attach: can't create DMA map"); 365 1.44 macallan 366 1.1 jmcneill rv = bus_dmamap_load(sc->sc_dmat, sc->sc_dma.map, sc->sc_dma.addr, 367 1.1 jmcneill sc->sc_dma.size, NULL, BUS_DMA_NOWAIT); 368 1.1 jmcneill if (rv) 369 1.1 jmcneill panic("crmfb_attach: can't load DMA map"); 370 1.1 jmcneill 371 1.1 jmcneill p = KERNADDR(sc->sc_dmai); 372 1.1 jmcneill v = (unsigned long)DMAADDR(sc->sc_dma); 373 1.11 macallan for (i = 0; i < (sc->sc_tiles_x * sc->sc_tiles_y); i++) { 374 1.1 jmcneill p[i] = ((uint32_t)v >> 16) + i; 375 1.1 jmcneill } 376 1.44 macallan 377 1.26 tsutsui bus_dmamap_sync(sc->sc_dmat, sc->sc_dmai.map, 0, sc->sc_dmai.size, 378 1.26 tsutsui BUS_DMASYNC_PREWRITE); 379 1.44 macallan 380 1.21 macallan sc->sc_linear = (paddr_t)DMAADDR(sc->sc_dma) + 0x100000 * sc->sc_tiles_x; 381 1.39 macallan sc->sc_lptr = (char *)KERNADDR(sc->sc_dma) + (0x100000 * sc->sc_tiles_x); 382 1.1 jmcneill 383 1.29 macallan aprint_normal_dev(sc->sc_dev, "allocated %d byte fb @ %p (%p)\n", 384 1.1 jmcneill sc->sc_fbsize, KERNADDR(sc->sc_dmai), KERNADDR(sc->sc_dma)); 385 1.1 jmcneill 386 1.34 macallan crmfb_setup_video(sc, sc->sc_console_depth); 387 1.1 jmcneill ri = &crmfb_console_screen.scr_ri; 388 1.1 jmcneill memset(ri, 0, sizeof(struct rasops_info)); 389 1.38 macallan sc->sc_video_on = 1; 390 1.1 jmcneill 391 1.1 jmcneill vcons_init(&sc->sc_vd, sc, &crmfb_defaultscreen, &crmfb_accessops); 392 1.1 jmcneill sc->sc_vd.init_screen = crmfb_init_screen; 393 1.1 jmcneill crmfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 394 1.1 jmcneill vcons_init_screen(&sc->sc_vd, &crmfb_console_screen, 1, &defattr); 395 1.1 jmcneill 396 1.1 jmcneill crmfb_defaultscreen.ncols = ri->ri_cols; 397 1.1 jmcneill crmfb_defaultscreen.nrows = ri->ri_rows; 398 1.1 jmcneill crmfb_defaultscreen.textops = &ri->ri_ops; 399 1.1 jmcneill crmfb_defaultscreen.capabilities = ri->ri_caps; 400 1.1 jmcneill crmfb_defaultscreen.modecookie = NULL; 401 1.1 jmcneill 402 1.7 macallan crmfb_setup_palette(sc); 403 1.14 macallan crmfb_fill_rect(sc, 0, 0, sc->sc_width, sc->sc_height, 404 1.17 macallan ri->ri_devcmap[(defattr >> 16) & 0xff]); 405 1.1 jmcneill 406 1.27 matt consdev = arcbios_GetEnvironmentVariable("ConsoleOut"); 407 1.2 jmcneill if (consdev != NULL && strcmp(consdev, "video()") == 0) { 408 1.2 jmcneill wsdisplay_cnattach(&crmfb_defaultscreen, ri, 0, 0, defattr); 409 1.28 macallan vcons_replay_msgbuf(&crmfb_console_screen); 410 1.2 jmcneill aa.console = 1; 411 1.2 jmcneill } else 412 1.2 jmcneill aa.console = 0; 413 1.1 jmcneill aa.scrdata = &crmfb_screenlist; 414 1.1 jmcneill aa.accessops = &crmfb_accessops; 415 1.1 jmcneill aa.accesscookie = &sc->sc_vd; 416 1.1 jmcneill 417 1.49 thorpej config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE); 418 1.1 jmcneill 419 1.6 macallan sc->sc_cur_x = 0; 420 1.6 macallan sc->sc_cur_y = 0; 421 1.6 macallan sc->sc_hot_x = 0; 422 1.6 macallan sc->sc_hot_y = 0; 423 1.6 macallan 424 1.1 jmcneill return; 425 1.1 jmcneill } 426 1.1 jmcneill 427 1.1 jmcneill int 428 1.1 jmcneill crmfb_probe(void) 429 1.1 jmcneill { 430 1.1 jmcneill 431 1.1 jmcneill if (mach_type != MACH_SGI_IP32) 432 1.1 jmcneill return 0; 433 1.1 jmcneill 434 1.1 jmcneill return 1; 435 1.1 jmcneill } 436 1.1 jmcneill 437 1.1 jmcneill static int 438 1.1 jmcneill crmfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 439 1.1 jmcneill { 440 1.1 jmcneill struct vcons_data *vd; 441 1.1 jmcneill struct crmfb_softc *sc; 442 1.1 jmcneill struct wsdisplay_fbinfo *wdf; 443 1.1 jmcneill int nmode; 444 1.1 jmcneill 445 1.1 jmcneill vd = (struct vcons_data *)v; 446 1.1 jmcneill sc = (struct crmfb_softc *)vd->cookie; 447 1.1 jmcneill 448 1.1 jmcneill switch (cmd) { 449 1.1 jmcneill case WSDISPLAYIO_GTYPE: 450 1.1 jmcneill /* not really, but who cares? */ 451 1.38 macallan /* xf86-video-crime does */ 452 1.7 macallan *(u_int *)data = WSDISPLAY_TYPE_CRIME; 453 1.1 jmcneill return 0; 454 1.1 jmcneill case WSDISPLAYIO_GINFO: 455 1.1 jmcneill if (vd->active != NULL) { 456 1.1 jmcneill wdf = (void *)data; 457 1.1 jmcneill wdf->height = sc->sc_height; 458 1.1 jmcneill wdf->width = sc->sc_width; 459 1.7 macallan wdf->depth = 32; 460 1.1 jmcneill wdf->cmsize = 256; 461 1.1 jmcneill return 0; 462 1.1 jmcneill } else 463 1.1 jmcneill return ENODEV; 464 1.1 jmcneill case WSDISPLAYIO_GETCMAP: 465 1.1 jmcneill if (sc->sc_depth == 8) 466 1.1 jmcneill return crmfb_getcmap(sc, (struct wsdisplay_cmap *)data); 467 1.1 jmcneill else 468 1.1 jmcneill return EINVAL; 469 1.1 jmcneill case WSDISPLAYIO_PUTCMAP: 470 1.1 jmcneill if (sc->sc_depth == 8) 471 1.1 jmcneill return crmfb_putcmap(sc, (struct wsdisplay_cmap *)data); 472 1.1 jmcneill else 473 1.1 jmcneill return EINVAL; 474 1.1 jmcneill case WSDISPLAYIO_LINEBYTES: 475 1.1 jmcneill *(u_int *)data = sc->sc_width * sc->sc_depth / 8; 476 1.1 jmcneill return 0; 477 1.1 jmcneill case WSDISPLAYIO_SMODE: 478 1.1 jmcneill nmode = *(int *)data; 479 1.1 jmcneill if (nmode != sc->sc_wsmode) { 480 1.1 jmcneill sc->sc_wsmode = nmode; 481 1.7 macallan if (nmode == WSDISPLAYIO_MODE_EMUL) { 482 1.34 macallan crmfb_setup_video(sc, sc->sc_console_depth); 483 1.7 macallan crmfb_setup_palette(sc); 484 1.1 jmcneill vcons_redraw_screen(vd->active); 485 1.7 macallan } else { 486 1.7 macallan crmfb_setup_video(sc, 32); 487 1.7 macallan } 488 1.1 jmcneill } 489 1.1 jmcneill return 0; 490 1.5 jmcneill case WSDISPLAYIO_SVIDEO: 491 1.38 macallan { 492 1.38 macallan int d = *(int *)data; 493 1.38 macallan if (d == sc->sc_video_on) 494 1.38 macallan return 0; 495 1.38 macallan sc->sc_video_on = d; 496 1.38 macallan if (d == WSDISPLAYIO_VIDEO_ON) { 497 1.38 macallan crmfb_write_reg(sc, 498 1.38 macallan CRMFB_VT_FLAGS, sc->sc_vtflags); 499 1.38 macallan } else { 500 1.38 macallan /* turn all SYNCs off */ 501 1.38 macallan crmfb_write_reg(sc, CRMFB_VT_FLAGS, 502 1.38 macallan sc->sc_vtflags | CRMFB_VT_FLAGS_VDRV_LOW | 503 1.38 macallan CRMFB_VT_FLAGS_HDRV_LOW | 504 1.38 macallan CRMFB_VT_FLAGS_SYNC_LOW); 505 1.38 macallan } 506 1.38 macallan } 507 1.38 macallan return 0; 508 1.38 macallan 509 1.5 jmcneill case WSDISPLAYIO_GVIDEO: 510 1.38 macallan *(int *)data = sc->sc_video_on; 511 1.38 macallan return 0; 512 1.6 macallan 513 1.6 macallan case WSDISPLAYIO_GCURPOS: 514 1.6 macallan { 515 1.6 macallan struct wsdisplay_curpos *pos; 516 1.6 macallan 517 1.6 macallan pos = (struct wsdisplay_curpos *)data; 518 1.6 macallan pos->x = sc->sc_cur_x; 519 1.6 macallan pos->y = sc->sc_cur_y; 520 1.6 macallan } 521 1.6 macallan return 0; 522 1.6 macallan case WSDISPLAYIO_SCURPOS: 523 1.6 macallan { 524 1.6 macallan struct wsdisplay_curpos *pos; 525 1.6 macallan 526 1.6 macallan pos = (struct wsdisplay_curpos *)data; 527 1.6 macallan crmfb_set_curpos(sc, pos->x, pos->y); 528 1.6 macallan } 529 1.6 macallan return 0; 530 1.6 macallan case WSDISPLAYIO_GCURMAX: 531 1.6 macallan { 532 1.6 macallan struct wsdisplay_curpos *pos; 533 1.6 macallan 534 1.6 macallan pos = (struct wsdisplay_curpos *)data; 535 1.6 macallan pos->x = 32; 536 1.6 macallan pos->y = 32; 537 1.6 macallan } 538 1.6 macallan return 0; 539 1.6 macallan case WSDISPLAYIO_GCURSOR: 540 1.6 macallan { 541 1.6 macallan struct wsdisplay_cursor *cu; 542 1.6 macallan 543 1.6 macallan cu = (struct wsdisplay_cursor *)data; 544 1.6 macallan return crmfb_gcursor(sc, cu); 545 1.6 macallan } 546 1.6 macallan case WSDISPLAYIO_SCURSOR: 547 1.6 macallan { 548 1.6 macallan struct wsdisplay_cursor *cu; 549 1.6 macallan 550 1.6 macallan cu = (struct wsdisplay_cursor *)data; 551 1.6 macallan return crmfb_scursor(sc, cu); 552 1.6 macallan } 553 1.38 macallan case WSDISPLAYIO_GET_EDID: { 554 1.38 macallan struct wsdisplayio_edid_info *d = data; 555 1.38 macallan 556 1.38 macallan d->data_size = 128; 557 1.38 macallan if (d->buffer_size < 128) 558 1.38 macallan return EAGAIN; 559 1.38 macallan if (sc->sc_edid_data[1] == 0) 560 1.38 macallan return ENODATA; 561 1.38 macallan return copyout(sc->sc_edid_data, d->edid_data, 128); 562 1.38 macallan } 563 1.1 jmcneill } 564 1.1 jmcneill return EPASSTHROUGH; 565 1.1 jmcneill } 566 1.1 jmcneill 567 1.1 jmcneill static paddr_t 568 1.1 jmcneill crmfb_mmap(void *v, void *vs, off_t offset, int prot) 569 1.1 jmcneill { 570 1.1 jmcneill struct vcons_data *vd; 571 1.1 jmcneill struct crmfb_softc *sc; 572 1.1 jmcneill paddr_t pa; 573 1.1 jmcneill 574 1.1 jmcneill vd = (struct vcons_data *)v; 575 1.1 jmcneill sc = (struct crmfb_softc *)vd->cookie; 576 1.1 jmcneill 577 1.14 macallan /* we probably shouldn't let anyone mmap the framebuffer */ 578 1.7 macallan #if 1 579 1.22 macallan if (offset >= 0 && offset < (0x100000 * sc->sc_tiles_x)) { 580 1.1 jmcneill pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dma.segs, 581 1.1 jmcneill sc->sc_dma.nsegs, offset, prot, 582 1.40 macallan BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_PREFETCHABLE); 583 1.1 jmcneill return pa; 584 1.1 jmcneill } 585 1.7 macallan #endif 586 1.14 macallan /* 587 1.14 macallan * here would the TLBs be but we don't want to show them to userland 588 1.14 macallan * so we return the page containing the status register 589 1.14 macallan */ 590 1.14 macallan if ((offset >= 0x15000000) && (offset < 0x15002000)) 591 1.14 macallan return bus_space_mmap(sc->sc_iot, 0x15004000, 0, prot, 0); 592 1.14 macallan /* now the actual engine registers */ 593 1.14 macallan if ((offset >= 0x15002000) && (offset < 0x15005000)) 594 1.14 macallan return bus_space_mmap(sc->sc_iot, offset, 0, prot, 0); 595 1.39 macallan /* and now the linear area */ 596 1.39 macallan if ((offset >= 0x15010000) && (offset < 0x15030000)) 597 1.14 macallan return bus_dmamem_mmap(sc->sc_dmat, sc->sc_dma.segs, 598 1.21 macallan sc->sc_dma.nsegs, 599 1.40 macallan offset + (0x100000 * sc->sc_tiles_x) - 0x15010000, prot, 600 1.40 macallan BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_PREFETCHABLE); 601 1.1 jmcneill return -1; 602 1.1 jmcneill } 603 1.1 jmcneill 604 1.1 jmcneill static void 605 1.1 jmcneill crmfb_init_screen(void *c, struct vcons_screen *scr, int existing, 606 1.1 jmcneill long *defattr) 607 1.1 jmcneill { 608 1.1 jmcneill struct crmfb_softc *sc; 609 1.1 jmcneill struct rasops_info *ri; 610 1.1 jmcneill 611 1.1 jmcneill sc = (struct crmfb_softc *)c; 612 1.1 jmcneill ri = &scr->scr_ri; 613 1.1 jmcneill 614 1.44 macallan scr->scr_flags |= VCONS_LOADFONT; 615 1.44 macallan 616 1.44 macallan ri->ri_flg = RI_CENTER | RI_FULLCLEAR | 617 1.44 macallan RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 618 1.34 macallan ri->ri_depth = sc->sc_console_depth; 619 1.1 jmcneill ri->ri_width = sc->sc_width; 620 1.1 jmcneill ri->ri_height = sc->sc_height; 621 1.1 jmcneill ri->ri_stride = ri->ri_width * (ri->ri_depth / 8); 622 1.38 macallan 623 1.1 jmcneill switch (ri->ri_depth) { 624 1.38 macallan case 8: 625 1.38 macallan ri->ri_flg |= RI_8BIT_IS_RGB; 626 1.38 macallan break; 627 1.1 jmcneill case 16: 628 1.1 jmcneill ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 5; 629 1.34 macallan ri->ri_rpos = 11; 630 1.34 macallan ri->ri_gpos = 6; 631 1.34 macallan ri->ri_bpos = 1; 632 1.1 jmcneill break; 633 1.1 jmcneill case 32: 634 1.1 jmcneill ri->ri_rnum = ri->ri_gnum = ri->ri_bnum = 8; 635 1.1 jmcneill ri->ri_rpos = 8; 636 1.1 jmcneill ri->ri_gpos = 16; 637 1.1 jmcneill ri->ri_bpos = 24; 638 1.1 jmcneill break; 639 1.1 jmcneill } 640 1.38 macallan 641 1.41 macallan ri->ri_bits = NULL; 642 1.1 jmcneill 643 1.36 macallan rasops_init(ri, 0, 0); 644 1.44 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_RESIZE; 645 1.1 jmcneill rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, 646 1.1 jmcneill ri->ri_width / ri->ri_font->fontwidth); 647 1.1 jmcneill ri->ri_hw = scr; 648 1.1 jmcneill 649 1.11 macallan ri->ri_ops.cursor = crmfb_cursor; 650 1.11 macallan ri->ri_ops.copyrows = crmfb_copyrows; 651 1.11 macallan ri->ri_ops.eraserows = crmfb_eraserows; 652 1.11 macallan ri->ri_ops.copycols = crmfb_copycols; 653 1.11 macallan ri->ri_ops.erasecols = crmfb_erasecols; 654 1.39 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 655 1.39 macallan ri->ri_ops.putchar = crmfb_putchar_aa; 656 1.39 macallan } else { 657 1.39 macallan ri->ri_ops.putchar = crmfb_putchar; 658 1.39 macallan } 659 1.1 jmcneill return; 660 1.1 jmcneill } 661 1.1 jmcneill 662 1.1 jmcneill static int 663 1.1 jmcneill crmfb_putcmap(struct crmfb_softc *sc, struct wsdisplay_cmap *cm) 664 1.1 jmcneill { 665 1.1 jmcneill u_int idx, cnt; 666 1.1 jmcneill u_char r[256], g[256], b[256]; 667 1.1 jmcneill u_char *rp, *gp, *bp; 668 1.1 jmcneill int rv, i; 669 1.1 jmcneill 670 1.1 jmcneill idx = cm->index; 671 1.1 jmcneill cnt = cm->count; 672 1.1 jmcneill 673 1.1 jmcneill if (idx >= 255 || cnt > 256 || idx + cnt > 256) 674 1.1 jmcneill return EINVAL; 675 1.1 jmcneill 676 1.1 jmcneill rv = copyin(cm->red, &r[idx], cnt); 677 1.1 jmcneill if (rv) 678 1.1 jmcneill return rv; 679 1.1 jmcneill rv = copyin(cm->green, &g[idx], cnt); 680 1.1 jmcneill if (rv) 681 1.1 jmcneill return rv; 682 1.1 jmcneill rv = copyin(cm->blue, &b[idx], cnt); 683 1.1 jmcneill if (rv) 684 1.1 jmcneill return rv; 685 1.1 jmcneill 686 1.1 jmcneill memcpy(&sc->sc_cmap_red[idx], &r[idx], cnt); 687 1.1 jmcneill memcpy(&sc->sc_cmap_green[idx], &g[idx], cnt); 688 1.1 jmcneill memcpy(&sc->sc_cmap_blue[idx], &b[idx], cnt); 689 1.1 jmcneill 690 1.1 jmcneill rp = &sc->sc_cmap_red[idx]; 691 1.1 jmcneill gp = &sc->sc_cmap_green[idx]; 692 1.1 jmcneill bp = &sc->sc_cmap_blue[idx]; 693 1.1 jmcneill 694 1.1 jmcneill for (i = 0; i < cnt; i++) { 695 1.1 jmcneill crmfb_set_palette(sc, idx, *rp, *gp, *bp); 696 1.1 jmcneill idx++; 697 1.1 jmcneill rp++, gp++, bp++; 698 1.1 jmcneill } 699 1.1 jmcneill 700 1.1 jmcneill return 0; 701 1.1 jmcneill } 702 1.1 jmcneill 703 1.1 jmcneill static int 704 1.1 jmcneill crmfb_getcmap(struct crmfb_softc *sc, struct wsdisplay_cmap *cm) 705 1.1 jmcneill { 706 1.1 jmcneill u_int idx, cnt; 707 1.1 jmcneill int rv; 708 1.1 jmcneill 709 1.1 jmcneill idx = cm->index; 710 1.1 jmcneill cnt = cm->count; 711 1.1 jmcneill 712 1.1 jmcneill if (idx >= 255 || cnt > 256 || idx + cnt > 256) 713 1.1 jmcneill return EINVAL; 714 1.1 jmcneill 715 1.1 jmcneill rv = copyout(&sc->sc_cmap_red[idx], cm->red, cnt); 716 1.1 jmcneill if (rv) 717 1.1 jmcneill return rv; 718 1.1 jmcneill rv = copyout(&sc->sc_cmap_green[idx], cm->green, cnt); 719 1.1 jmcneill if (rv) 720 1.1 jmcneill return rv; 721 1.1 jmcneill rv = copyout(&sc->sc_cmap_blue[idx], cm->blue, cnt); 722 1.1 jmcneill if (rv) 723 1.1 jmcneill return rv; 724 1.1 jmcneill 725 1.1 jmcneill return 0; 726 1.1 jmcneill } 727 1.1 jmcneill 728 1.1 jmcneill static void 729 1.1 jmcneill crmfb_set_palette(struct crmfb_softc *sc, int reg, uint8_t r, uint8_t g, 730 1.1 jmcneill uint8_t b) 731 1.1 jmcneill { 732 1.1 jmcneill uint32_t val; 733 1.1 jmcneill 734 1.1 jmcneill if (reg > 255 || sc->sc_depth != 8) 735 1.1 jmcneill return; 736 1.1 jmcneill 737 1.1 jmcneill while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_CMAP_FIFO) >= 63) 738 1.1 jmcneill DELAY(10); 739 1.1 jmcneill 740 1.23 jmcneill val = (r << 8) | (g << 16) | (b << 24); 741 1.7 macallan crmfb_write_reg(sc, CRMFB_CMAP + (reg * 4), val); 742 1.1 jmcneill 743 1.1 jmcneill return; 744 1.1 jmcneill } 745 1.6 macallan 746 1.6 macallan static int 747 1.6 macallan crmfb_set_curpos(struct crmfb_softc *sc, int x, int y) 748 1.6 macallan { 749 1.6 macallan uint32_t val; 750 1.6 macallan 751 1.6 macallan sc->sc_cur_x = x; 752 1.6 macallan sc->sc_cur_y = y; 753 1.6 macallan 754 1.6 macallan val = ((x - sc->sc_hot_x) & 0xffff) | ((y - sc->sc_hot_y) << 16); 755 1.7 macallan crmfb_write_reg(sc, CRMFB_CURSOR_POS, val); 756 1.6 macallan 757 1.6 macallan return 0; 758 1.6 macallan } 759 1.6 macallan 760 1.6 macallan static int 761 1.6 macallan crmfb_gcursor(struct crmfb_softc *sc, struct wsdisplay_cursor *cur) 762 1.6 macallan { 763 1.6 macallan /* do nothing for now */ 764 1.6 macallan return 0; 765 1.6 macallan } 766 1.6 macallan 767 1.6 macallan static int 768 1.6 macallan crmfb_scursor(struct crmfb_softc *sc, struct wsdisplay_cursor *cur) 769 1.6 macallan { 770 1.6 macallan if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 771 1.6 macallan 772 1.7 macallan crmfb_write_reg(sc, CRMFB_CURSOR_CONTROL, cur->enable ? 1 : 0); 773 1.6 macallan } 774 1.6 macallan if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 775 1.6 macallan 776 1.6 macallan sc->sc_hot_x = cur->hot.x; 777 1.6 macallan sc->sc_hot_y = cur->hot.y; 778 1.6 macallan } 779 1.6 macallan if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 780 1.6 macallan 781 1.6 macallan crmfb_set_curpos(sc, cur->pos.x, cur->pos.y); 782 1.6 macallan } 783 1.6 macallan if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 784 1.6 macallan int i; 785 1.6 macallan uint32_t val; 786 1.6 macallan 787 1.6 macallan for (i = 0; i < cur->cmap.count; i++) { 788 1.6 macallan val = (cur->cmap.red[i] << 24) | 789 1.6 macallan (cur->cmap.green[i] << 16) | 790 1.6 macallan (cur->cmap.blue[i] << 8); 791 1.7 macallan crmfb_write_reg(sc, CRMFB_CURSOR_CMAP0 + 792 1.7 macallan ((i + cur->cmap.index) << 2), val); 793 1.6 macallan } 794 1.6 macallan } 795 1.6 macallan if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 796 1.6 macallan 797 1.6 macallan int i, j, cnt = 0; 798 1.6 macallan uint32_t latch = 0, omask; 799 1.6 macallan uint8_t imask; 800 1.6 macallan for (i = 0; i < 64; i++) { 801 1.6 macallan omask = 0x80000000; 802 1.6 macallan imask = 0x01; 803 1.6 macallan cur->image[cnt] &= cur->mask[cnt]; 804 1.6 macallan for (j = 0; j < 8; j++) { 805 1.6 macallan if (cur->image[cnt] & imask) 806 1.6 macallan latch |= omask; 807 1.6 macallan omask >>= 1; 808 1.6 macallan if (cur->mask[cnt] & imask) 809 1.6 macallan latch |= omask; 810 1.6 macallan omask >>= 1; 811 1.6 macallan imask <<= 1; 812 1.6 macallan } 813 1.6 macallan cnt++; 814 1.6 macallan imask = 0x01; 815 1.6 macallan cur->image[cnt] &= cur->mask[cnt]; 816 1.6 macallan for (j = 0; j < 8; j++) { 817 1.6 macallan if (cur->image[cnt] & imask) 818 1.6 macallan latch |= omask; 819 1.6 macallan omask >>= 1; 820 1.6 macallan if (cur->mask[cnt] & imask) 821 1.6 macallan latch |= omask; 822 1.6 macallan omask >>= 1; 823 1.6 macallan imask <<= 1; 824 1.6 macallan } 825 1.6 macallan cnt++; 826 1.7 macallan crmfb_write_reg(sc, CRMFB_CURSOR_BITMAP + (i << 2), 827 1.7 macallan latch); 828 1.6 macallan latch = 0; 829 1.6 macallan } 830 1.6 macallan } 831 1.6 macallan return 0; 832 1.6 macallan } 833 1.7 macallan 834 1.7 macallan static inline void 835 1.7 macallan crmfb_write_reg(struct crmfb_softc *sc, int offset, uint32_t val) 836 1.7 macallan { 837 1.7 macallan 838 1.7 macallan bus_space_write_4(sc->sc_iot, sc->sc_ioh, offset, val); 839 1.7 macallan wbflush(); 840 1.7 macallan } 841 1.7 macallan 842 1.11 macallan static inline uint32_t 843 1.11 macallan crmfb_read_reg(struct crmfb_softc *sc, int offset) 844 1.11 macallan { 845 1.11 macallan 846 1.11 macallan return bus_space_read_4(sc->sc_iot, sc->sc_ioh, offset); 847 1.11 macallan } 848 1.11 macallan 849 1.39 macallan static inline void 850 1.39 macallan crmfb_wait_idle(struct crmfb_softc *sc) 851 1.39 macallan { 852 1.39 macallan int i = 0; 853 1.39 macallan 854 1.39 macallan do { 855 1.39 macallan i++; 856 1.39 macallan } while (((bus_space_read_4(sc->sc_iot, sc->sc_reh, CRIME_DE_STATUS) & 857 1.39 macallan CRIME_DE_IDLE) == 0) && (i < 100000000)); 858 1.39 macallan if (i >= 100000000) 859 1.39 macallan aprint_error("crmfb_wait_idle() timed out\n"); 860 1.39 macallan sc->sc_needs_sync = 0; 861 1.39 macallan } 862 1.39 macallan 863 1.39 macallan /* writes to CRIME_DE_MODE_* only take effect when the engine is idle */ 864 1.39 macallan 865 1.39 macallan static inline void 866 1.39 macallan crmfb_src_mode(struct crmfb_softc *sc, uint32_t mode) 867 1.39 macallan { 868 1.39 macallan if (mode == sc->sc_src_mode) 869 1.39 macallan return; 870 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_MODE_SRC, mode); 871 1.39 macallan sc->sc_needs_sync = 1; 872 1.39 macallan sc->sc_src_mode = mode; 873 1.39 macallan } 874 1.39 macallan 875 1.39 macallan static inline void 876 1.39 macallan crmfb_dst_mode(struct crmfb_softc *sc, uint32_t mode) 877 1.39 macallan { 878 1.39 macallan if (mode == sc->sc_dst_mode) 879 1.39 macallan return; 880 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_MODE_DST, mode); 881 1.39 macallan sc->sc_needs_sync = 1; 882 1.39 macallan sc->sc_dst_mode = mode; 883 1.39 macallan } 884 1.39 macallan 885 1.39 macallan static inline void 886 1.39 macallan crmfb_make_room(struct crmfb_softc *sc, int num) 887 1.39 macallan { 888 1.39 macallan int i = 0, slots; 889 1.39 macallan uint32_t status; 890 1.39 macallan 891 1.39 macallan if (sc->sc_needs_sync != 0) { 892 1.39 macallan crmfb_wait_idle(sc); 893 1.39 macallan return; 894 1.39 macallan } 895 1.39 macallan 896 1.39 macallan do { 897 1.39 macallan i++; 898 1.39 macallan status = bus_space_read_4(sc->sc_iot, sc->sc_reh, 899 1.39 macallan CRIME_DE_STATUS); 900 1.39 macallan slots = 60 - CRIME_PIPE_LEVEL(status); 901 1.39 macallan } while (slots <= num); 902 1.39 macallan } 903 1.39 macallan 904 1.11 macallan static int 905 1.11 macallan crmfb_wait_dma_idle(struct crmfb_softc *sc) 906 1.11 macallan { 907 1.11 macallan int bail = 100000, idle; 908 1.11 macallan 909 1.11 macallan do { 910 1.11 macallan idle = ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, 911 1.11 macallan CRMFB_OVR_CONTROL) & 1) == 0) && 912 1.11 macallan ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, 913 1.11 macallan CRMFB_FRM_CONTROL) & 1) == 0) && 914 1.11 macallan ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, 915 1.11 macallan CRMFB_DID_CONTROL) & 1) == 0); 916 1.11 macallan if (!idle) 917 1.11 macallan delay(10); 918 1.11 macallan bail--; 919 1.11 macallan } while ((!idle) && (bail > 0)); 920 1.11 macallan return idle; 921 1.11 macallan } 922 1.11 macallan 923 1.7 macallan static int 924 1.7 macallan crmfb_setup_video(struct crmfb_softc *sc, int depth) 925 1.7 macallan { 926 1.11 macallan uint64_t reg; 927 1.38 macallan uint32_t d, h, page; 928 1.32 macallan int i, bail, tile_width, tlbptr, lptr, j, tx, shift, overhang; 929 1.10 sekiya const char *wantsync; 930 1.11 macallan uint16_t v; 931 1.11 macallan 932 1.7 macallan /* disable DMA */ 933 1.7 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_OVR_CONTROL); 934 1.7 macallan d &= ~(1 << CRMFB_OVR_CONTROL_DMAEN_SHIFT); 935 1.7 macallan crmfb_write_reg(sc, CRMFB_OVR_CONTROL, d); 936 1.7 macallan DELAY(50000); 937 1.7 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_FRM_CONTROL); 938 1.7 macallan d &= ~(1 << CRMFB_FRM_CONTROL_DMAEN_SHIFT); 939 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_CONTROL, d); 940 1.7 macallan DELAY(50000); 941 1.32 macallan crmfb_write_reg(sc, CRMFB_DID_CONTROL, d); 942 1.7 macallan DELAY(50000); 943 1.7 macallan 944 1.11 macallan if (!crmfb_wait_dma_idle(sc)) 945 1.11 macallan aprint_error("crmfb: crmfb_wait_dma_idle timed out\n"); 946 1.11 macallan 947 1.7 macallan /* ensure that CRM starts drawing at the top left of the screen 948 1.7 macallan * when we re-enable DMA later 949 1.7 macallan */ 950 1.7 macallan d = (1 << CRMFB_VT_XY_FREEZE_SHIFT); 951 1.7 macallan crmfb_write_reg(sc, CRMFB_VT_XY, d); 952 1.7 macallan delay(1000); 953 1.7 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_DOTCLOCK); 954 1.7 macallan d &= ~(1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT); 955 1.7 macallan crmfb_write_reg(sc, CRMFB_DOTCLOCK, d); 956 1.11 macallan 957 1.11 macallan /* wait for dotclock to turn off */ 958 1.11 macallan bail = 10000; 959 1.11 macallan while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_DOTCLOCK) & 960 1.11 macallan (1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT)) && (bail > 0)) { 961 1.11 macallan delay(10); 962 1.11 macallan bail--; 963 1.11 macallan } 964 1.7 macallan 965 1.7 macallan /* reset FIFO */ 966 1.7 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_FRM_TILESIZE); 967 1.7 macallan d |= (1 << CRMFB_FRM_TILESIZE_FIFOR_SHIFT); 968 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_TILESIZE, d); 969 1.7 macallan d &= ~(1 << CRMFB_FRM_TILESIZE_FIFOR_SHIFT); 970 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_TILESIZE, d); 971 1.7 macallan 972 1.7 macallan /* setup colour mode */ 973 1.7 macallan switch (depth) { 974 1.7 macallan case 8: 975 1.38 macallan h = CRMFB_MODE_TYP_RG3B2; 976 1.11 macallan tile_width = 512; 977 1.7 macallan break; 978 1.7 macallan case 16: 979 1.7 macallan h = CRMFB_MODE_TYP_ARGB5; 980 1.11 macallan tile_width = 256; 981 1.7 macallan break; 982 1.7 macallan case 32: 983 1.7 macallan h = CRMFB_MODE_TYP_RGB8; 984 1.11 macallan tile_width = 128; 985 1.7 macallan break; 986 1.7 macallan default: 987 1.7 macallan panic("Unsupported depth"); 988 1.7 macallan } 989 1.7 macallan d = h << CRMFB_MODE_TYP_SHIFT; 990 1.7 macallan d |= CRMFB_MODE_BUF_BOTH << CRMFB_MODE_BUF_SHIFT; 991 1.7 macallan for (i = 0; i < (32 * 4); i += 4) 992 1.7 macallan bus_space_write_4(sc->sc_iot, sc->sc_ioh, CRMFB_MODE + i, d); 993 1.7 macallan wbflush(); 994 1.7 macallan 995 1.7 macallan /* setup tile pointer, but don't turn on DMA yet! */ 996 1.7 macallan h = DMAADDR(sc->sc_dmai); 997 1.7 macallan d = (h >> 9) << CRMFB_FRM_CONTROL_TILEPTR_SHIFT; 998 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_CONTROL, d); 999 1.7 macallan 1000 1.7 macallan /* init framebuffer width and pixel size */ 1001 1.11 macallan /*d = (1 << CRMFB_FRM_TILESIZE_WIDTH_SHIFT);*/ 1002 1.11 macallan 1003 1.11 macallan d = ((int)(sc->sc_width / tile_width)) << 1004 1.11 macallan CRMFB_FRM_TILESIZE_WIDTH_SHIFT; 1005 1.32 macallan overhang = sc->sc_width % tile_width; 1006 1.32 macallan if (overhang != 0) { 1007 1.32 macallan uint32_t val; 1008 1.32 macallan DPRINTF("tile width: %d\n", tile_width); 1009 1.32 macallan DPRINTF("overhang: %d\n", overhang); 1010 1.32 macallan val = (overhang * (depth >> 3)) >> 5; 1011 1.32 macallan DPRINTF("reg: %08x\n", val); 1012 1.32 macallan d |= (val & 0x1f); 1013 1.32 macallan DPRINTF("d: %08x\n", d); 1014 1.32 macallan } 1015 1.11 macallan 1016 1.7 macallan switch (depth) { 1017 1.7 macallan case 8: 1018 1.7 macallan h = CRMFB_FRM_TILESIZE_DEPTH_8; 1019 1.7 macallan break; 1020 1.7 macallan case 16: 1021 1.7 macallan h = CRMFB_FRM_TILESIZE_DEPTH_16; 1022 1.7 macallan break; 1023 1.7 macallan case 32: 1024 1.7 macallan h = CRMFB_FRM_TILESIZE_DEPTH_32; 1025 1.7 macallan break; 1026 1.7 macallan default: 1027 1.7 macallan panic("Unsupported depth"); 1028 1.7 macallan } 1029 1.7 macallan d |= (h << CRMFB_FRM_TILESIZE_DEPTH_SHIFT); 1030 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_TILESIZE, d); 1031 1.7 macallan 1032 1.11 macallan /*h = sc->sc_width * sc->sc_height / (512 / (depth >> 3));*/ 1033 1.11 macallan h = sc->sc_height; 1034 1.7 macallan d = h << CRMFB_FRM_PIXSIZE_HEIGHT_SHIFT; 1035 1.7 macallan crmfb_write_reg(sc, CRMFB_FRM_PIXSIZE, d); 1036 1.7 macallan 1037 1.7 macallan /* turn off firmware overlay and hardware cursor */ 1038 1.7 macallan crmfb_write_reg(sc, CRMFB_OVR_WIDTH_TILE, 0); 1039 1.7 macallan crmfb_write_reg(sc, CRMFB_CURSOR_CONTROL, 0); 1040 1.7 macallan 1041 1.32 macallan /* turn on DMA for the framebuffer */ 1042 1.32 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_FRM_CONTROL); 1043 1.32 macallan d |= (1 << CRMFB_FRM_CONTROL_DMAEN_SHIFT); 1044 1.32 macallan crmfb_write_reg(sc, CRMFB_FRM_CONTROL, d); 1045 1.32 macallan 1046 1.7 macallan /* enable drawing again */ 1047 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_XY, 0); 1048 1.7 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_DOTCLOCK); 1049 1.7 macallan d |= (1 << CRMFB_DOTCLOCK_CLKRUN_SHIFT); 1050 1.7 macallan crmfb_write_reg(sc, CRMFB_DOTCLOCK, d); 1051 1.7 macallan 1052 1.10 sekiya /* turn off sync-on-green */ 1053 1.10 sekiya 1054 1.27 matt wantsync = arcbios_GetEnvironmentVariable("SyncOnGreen"); 1055 1.10 sekiya if ( (wantsync != NULL) && (wantsync[0] == 'n') ) { 1056 1.38 macallan sc->sc_vtflags |= CRMFB_VT_FLAGS_SYNC_LOW; 1057 1.10 sekiya crmfb_write_reg(sc, CRMFB_VT_FLAGS, d); 1058 1.10 sekiya } 1059 1.10 sekiya 1060 1.7 macallan sc->sc_depth = depth; 1061 1.11 macallan 1062 1.11 macallan /* finally set up the drawing engine's TLB A */ 1063 1.11 macallan v = (DMAADDR(sc->sc_dma) >> 16) & 0xffff; 1064 1.11 macallan tlbptr = 0; 1065 1.15 macallan tx = ((sc->sc_width + (tile_width - 1)) & ~(tile_width - 1)) / 1066 1.15 macallan tile_width; 1067 1.14 macallan 1068 1.32 macallan DPRINTF("tx: %d\n", tx); 1069 1.21 macallan 1070 1.21 macallan for (i = 0; i < 16; i++) { 1071 1.11 macallan reg = 0; 1072 1.11 macallan shift = 64; 1073 1.21 macallan lptr = 0; 1074 1.11 macallan for (j = 0; j < tx; j++) { 1075 1.11 macallan shift -= 16; 1076 1.11 macallan reg |= (((uint64_t)(v | 0x8000)) << shift); 1077 1.11 macallan if (shift == 0) { 1078 1.11 macallan shift = 64; 1079 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 1080 1.21 macallan CRIME_RE_TLB_A + tlbptr + lptr, 1081 1.15 macallan reg); 1082 1.33 plunky DPRINTF("%04x: %016"PRIx64"\n", tlbptr + lptr, reg); 1083 1.21 macallan reg = 0; 1084 1.21 macallan lptr += 8; 1085 1.11 macallan } 1086 1.11 macallan v++; 1087 1.11 macallan } 1088 1.11 macallan if (shift != 64) { 1089 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 1090 1.21 macallan CRIME_RE_TLB_A + tlbptr + lptr, reg); 1091 1.33 plunky DPRINTF("%04x: %016"PRIx64"\n", tlbptr + lptr, reg); 1092 1.11 macallan } 1093 1.11 macallan tlbptr += 32; 1094 1.11 macallan } 1095 1.11 macallan 1096 1.39 macallan /* now put the last 128kB into the 1st linear TLB */ 1097 1.21 macallan page = (sc->sc_linear >> 12) | 0x80000000; 1098 1.21 macallan tlbptr = 0; 1099 1.39 macallan for (i = 0; i < 16; i++) { 1100 1.21 macallan reg = ((uint64_t)page << 32) | (page + 1); 1101 1.21 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 1102 1.21 macallan CRIME_RE_LINEAR_A + tlbptr, reg); 1103 1.21 macallan page += 2; 1104 1.21 macallan tlbptr += 8; 1105 1.21 macallan } 1106 1.11 macallan wbflush(); 1107 1.11 macallan 1108 1.11 macallan /* do some very basic engine setup */ 1109 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_CLIPMODE, 0); 1110 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_WINOFFSET_SRC, 0); 1111 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_WINOFFSET_DST, 0); 1112 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PLANEMASK, 1113 1.15 macallan 0xffffffff); 1114 1.11 macallan 1115 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 0x20, 0); 1116 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 0x28, 0); 1117 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 0x30, 0); 1118 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 0x38, 0); 1119 1.11 macallan bus_space_write_8(sc->sc_iot, sc->sc_reh, 0x40, 0); 1120 1.11 macallan 1121 1.11 macallan switch (depth) { 1122 1.42 christos case 8: 1123 1.42 christos sc->sc_de_mode = DE_MODE_TLB_A | DE_MODE_BUFDEPTH_8 | 1124 1.42 christos DE_MODE_TYPE_CI | DE_MODE_PIXDEPTH_8; 1125 1.42 christos sc->sc_mte_mode = MTE_MODE_DST_ECC | 1126 1.42 christos (MTE_TLB_A << MTE_DST_TLB_SHIFT) | 1127 1.42 christos (MTE_TLB_A << MTE_SRC_TLB_SHIFT) | 1128 1.42 christos (MTE_DEPTH_8 << MTE_DEPTH_SHIFT); 1129 1.42 christos sc->sc_mte_x_shift = 0; 1130 1.42 christos break; 1131 1.42 christos case 16: 1132 1.42 christos sc->sc_de_mode = DE_MODE_TLB_A | DE_MODE_BUFDEPTH_16 | 1133 1.42 christos DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_16; 1134 1.42 christos sc->sc_mte_mode = MTE_MODE_DST_ECC | 1135 1.42 christos (MTE_TLB_A << MTE_DST_TLB_SHIFT) | 1136 1.42 christos (MTE_TLB_A << MTE_SRC_TLB_SHIFT) | 1137 1.42 christos (MTE_DEPTH_16 << MTE_DEPTH_SHIFT); 1138 1.42 christos sc->sc_mte_x_shift = 1; 1139 1.42 christos break; 1140 1.42 christos case 32: 1141 1.42 christos sc->sc_de_mode = DE_MODE_TLB_A | DE_MODE_BUFDEPTH_32 | 1142 1.42 christos DE_MODE_TYPE_RGBA | DE_MODE_PIXDEPTH_32; 1143 1.42 christos sc->sc_mte_mode = MTE_MODE_DST_ECC | 1144 1.42 christos (MTE_TLB_A << MTE_DST_TLB_SHIFT) | 1145 1.42 christos (MTE_TLB_A << MTE_SRC_TLB_SHIFT) | 1146 1.42 christos (MTE_DEPTH_32 << MTE_DEPTH_SHIFT); 1147 1.42 christos sc->sc_mte_x_shift = 2; 1148 1.42 christos break; 1149 1.42 christos default: 1150 1.47 msaitoh panic("%s: unsupported colour depth %d\n", __func__, 1151 1.42 christos depth); 1152 1.11 macallan } 1153 1.39 macallan sc->sc_needs_sync = 0; 1154 1.39 macallan sc->sc_src_mode = 0xffffffff; 1155 1.39 macallan sc->sc_dst_mode = 0xffffffff; 1156 1.39 macallan 1157 1.39 macallan crmfb_src_mode(sc, sc->sc_de_mode); 1158 1.39 macallan crmfb_dst_mode(sc, sc->sc_de_mode); 1159 1.39 macallan 1160 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_STEP_X, 1); 1161 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_STEP_Y, 1); 1162 1.15 macallan 1163 1.15 macallan /* initialize memory transfer engine */ 1164 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_MODE, 1165 1.34 macallan sc->sc_mte_mode | MTE_MODE_COPY); 1166 1.18 macallan sc->sc_mte_direction = 1; 1167 1.16 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_DST_Y_STEP, 1); 1168 1.16 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_SRC_Y_STEP, 1); 1169 1.15 macallan 1170 1.7 macallan return 0; 1171 1.7 macallan } 1172 1.7 macallan 1173 1.19 macallan static void 1174 1.18 macallan crmfb_set_mte_direction(struct crmfb_softc *sc, int dir) 1175 1.18 macallan { 1176 1.18 macallan if (dir == sc->sc_mte_direction) 1177 1.18 macallan return; 1178 1.18 macallan 1179 1.39 macallan crmfb_make_room(sc, 2); 1180 1.18 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_DST_Y_STEP, dir); 1181 1.18 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_SRC_Y_STEP, dir); 1182 1.20 macallan sc->sc_mte_direction = dir; 1183 1.18 macallan } 1184 1.18 macallan 1185 1.7 macallan static void 1186 1.7 macallan crmfb_setup_palette(struct crmfb_softc *sc) 1187 1.7 macallan { 1188 1.39 macallan int i, j, x; 1189 1.39 macallan uint32_t col; 1190 1.39 macallan struct rasops_info *ri = &crmfb_console_screen.scr_ri; 1191 1.7 macallan 1192 1.7 macallan for (i = 0; i < 256; i++) { 1193 1.7 macallan crmfb_set_palette(sc, i, rasops_cmap[(i * 3) + 2], 1194 1.7 macallan rasops_cmap[(i * 3) + 1], rasops_cmap[(i * 3) + 0]); 1195 1.7 macallan sc->sc_cmap_red[i] = rasops_cmap[(i * 3) + 2]; 1196 1.7 macallan sc->sc_cmap_green[i] = rasops_cmap[(i * 3) + 1]; 1197 1.7 macallan sc->sc_cmap_blue[i] = rasops_cmap[(i * 3) + 0]; 1198 1.7 macallan } 1199 1.11 macallan 1200 1.39 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 1201 1.39 macallan sc->sc_de_mode = 1202 1.39 macallan (sc->sc_de_mode & ~DE_MODE_TYPE_MASK) | DE_MODE_TYPE_RGB; 1203 1.39 macallan } 1204 1.11 macallan 1205 1.39 macallan /* draw 16 character cells in 32bit RGBA for alpha blending */ 1206 1.39 macallan crmfb_make_room(sc, 3); 1207 1.39 macallan crmfb_dst_mode(sc, 1208 1.39 macallan DE_MODE_TLB_A | 1209 1.39 macallan DE_MODE_BUFDEPTH_32 | 1210 1.39 macallan DE_MODE_TYPE_RGBA | 1211 1.39 macallan DE_MODE_PIXDEPTH_32); 1212 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_DRAWMODE, 1213 1.39 macallan DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK); 1214 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PRIMITIVE, 1215 1.39 macallan DE_PRIM_RECTANGLE | DE_PRIM_TB); 1216 1.39 macallan j = 0; 1217 1.39 macallan x = 0; 1218 1.39 macallan for (i = 0; i < 16; i++) { 1219 1.39 macallan crmfb_make_room(sc, 2); 1220 1.39 macallan col = (rasops_cmap[j] << 24) | 1221 1.39 macallan (rasops_cmap[j + 1] << 16) | 1222 1.39 macallan (rasops_cmap[j + 2] << 8); 1223 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_FG, col); 1224 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_X_VERTEX_0, 1225 1.39 macallan (x << 16) | ((sc->sc_height - 500) & 0xffff)); 1226 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1227 1.39 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1228 1.39 macallan ((x + ri->ri_font->fontwidth - 1) << 16) | 1229 1.39 macallan ((sc->sc_height + ri->ri_font->fontheight - 1) & 0xffff)); 1230 1.39 macallan j += 3; 1231 1.39 macallan x += ri->ri_font->fontwidth; 1232 1.39 macallan } 1233 1.39 macallan crmfb_dst_mode(sc, sc->sc_de_mode); 1234 1.11 macallan } 1235 1.11 macallan 1236 1.11 macallan static void 1237 1.11 macallan crmfb_fill_rect(struct crmfb_softc *sc, int x, int y, int width, int height, 1238 1.11 macallan uint32_t colour) 1239 1.11 macallan { 1240 1.34 macallan int rxa, rxe; 1241 1.34 macallan 1242 1.34 macallan rxa = x << sc->sc_mte_x_shift; 1243 1.34 macallan rxe = ((x + width) << sc->sc_mte_x_shift) - 1; 1244 1.18 macallan crmfb_set_mte_direction(sc, 1); 1245 1.39 macallan crmfb_make_room(sc, 4); 1246 1.17 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_MODE, 1247 1.34 macallan sc->sc_mte_mode | 0); 1248 1.17 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_BG, colour); 1249 1.17 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_DST0, 1250 1.34 macallan (rxa << 16) | (y & 0xffff)); 1251 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1252 1.17 macallan CRIME_MTE_DST1 | CRIME_DE_START, 1253 1.34 macallan (rxe << 16) | ((y + height - 1) & 0xffff)); 1254 1.11 macallan } 1255 1.11 macallan 1256 1.11 macallan static void 1257 1.11 macallan crmfb_bitblt(struct crmfb_softc *sc, int xs, int ys, int xd, int yd, 1258 1.11 macallan int wi, int he, uint32_t rop) 1259 1.11 macallan { 1260 1.11 macallan uint32_t prim = DE_PRIM_RECTANGLE; 1261 1.11 macallan int rxa, rya, rxe, rye, rxs, rys; 1262 1.39 macallan crmfb_make_room(sc, 2); 1263 1.39 macallan crmfb_src_mode(sc, sc->sc_de_mode); 1264 1.39 macallan crmfb_make_room(sc, 6); 1265 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_DRAWMODE, 1266 1.11 macallan DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | DE_DRAWMODE_ROP | 1267 1.11 macallan DE_DRAWMODE_XFER_EN); 1268 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_ROP, rop); 1269 1.11 macallan if (xs < xd) { 1270 1.11 macallan prim |= DE_PRIM_RL; 1271 1.11 macallan rxe = xd; 1272 1.11 macallan rxa = xd + wi - 1; 1273 1.11 macallan rxs = xs + wi - 1; 1274 1.11 macallan } else { 1275 1.11 macallan prim |= DE_PRIM_LR; 1276 1.11 macallan rxe = xd + wi - 1; 1277 1.11 macallan rxa = xd; 1278 1.11 macallan rxs = xs; 1279 1.11 macallan } 1280 1.11 macallan if (ys < yd) { 1281 1.11 macallan prim |= DE_PRIM_BT; 1282 1.11 macallan rye = yd; 1283 1.11 macallan rya = yd + he - 1; 1284 1.11 macallan rys = ys + he - 1; 1285 1.11 macallan } else { 1286 1.11 macallan prim |= DE_PRIM_TB; 1287 1.11 macallan rye = yd + he - 1; 1288 1.11 macallan rya = yd; 1289 1.11 macallan rys = ys; 1290 1.11 macallan } 1291 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PRIMITIVE, prim); 1292 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_ADDR_SRC, 1293 1.11 macallan (rxs << 16) | (rys & 0xffff)); 1294 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_X_VERTEX_0, 1295 1.11 macallan (rxa << 16) | (rya & 0xffff)); 1296 1.11 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1297 1.11 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1298 1.11 macallan (rxe << 16) | (rye & 0xffff)); 1299 1.11 macallan } 1300 1.11 macallan 1301 1.15 macallan static void 1302 1.15 macallan crmfb_scroll(struct crmfb_softc *sc, int xs, int ys, int xd, int yd, 1303 1.15 macallan int wi, int he) 1304 1.15 macallan { 1305 1.15 macallan int rxa, rya, rxe, rye, rxd, ryd, rxde, ryde; 1306 1.15 macallan 1307 1.34 macallan rxa = xs << sc->sc_mte_x_shift; 1308 1.34 macallan rxd = xd << sc->sc_mte_x_shift; 1309 1.34 macallan rxe = ((xs + wi) << sc->sc_mte_x_shift) - 1; 1310 1.34 macallan rxde = ((xd + wi) << sc->sc_mte_x_shift) - 1; 1311 1.16 macallan 1312 1.39 macallan crmfb_make_room(sc, 1); 1313 1.16 macallan 1314 1.17 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_MODE, 1315 1.34 macallan sc->sc_mte_mode | MTE_MODE_COPY); 1316 1.17 macallan 1317 1.15 macallan if (ys < yd) { 1318 1.15 macallan /* bottom to top */ 1319 1.15 macallan rye = ys; 1320 1.15 macallan rya = ys + he - 1; 1321 1.15 macallan ryd = yd + he - 1; 1322 1.15 macallan ryde = yd; 1323 1.18 macallan crmfb_set_mte_direction(sc, -1); 1324 1.15 macallan } else { 1325 1.15 macallan /* top to bottom */ 1326 1.15 macallan rye = ys + he - 1; 1327 1.15 macallan rya = ys; 1328 1.15 macallan ryd = yd; 1329 1.15 macallan ryde = yd + he - 1; 1330 1.18 macallan crmfb_set_mte_direction(sc, 1); 1331 1.15 macallan } 1332 1.39 macallan crmfb_make_room(sc, 4); 1333 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_SRC0, 1334 1.15 macallan (rxa << 16) | rya); 1335 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_SRC1, 1336 1.15 macallan (rxe << 16) | rye); 1337 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1338 1.15 macallan CRIME_MTE_DST0, 1339 1.15 macallan (rxd << 16) | ryd); 1340 1.15 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_MTE_DST1 | 1341 1.15 macallan CRIME_DE_START, 1342 1.15 macallan (rxde << 16) | ryde); 1343 1.15 macallan } 1344 1.15 macallan 1345 1.11 macallan static void 1346 1.11 macallan crmfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1347 1.11 macallan { 1348 1.11 macallan struct rasops_info *ri = cookie; 1349 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1350 1.11 macallan int32_t xs, xd, y, width, height; 1351 1.11 macallan 1352 1.11 macallan xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1353 1.11 macallan xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1354 1.11 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1355 1.11 macallan width = ri->ri_font->fontwidth * ncols; 1356 1.11 macallan height = ri->ri_font->fontheight; 1357 1.11 macallan crmfb_bitblt(scr->scr_cookie, xs, y, xd, y, width, height, 3); 1358 1.11 macallan } 1359 1.11 macallan 1360 1.11 macallan static void 1361 1.11 macallan crmfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1362 1.11 macallan { 1363 1.11 macallan struct rasops_info *ri = cookie; 1364 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1365 1.11 macallan int32_t x, y, width, height, bg; 1366 1.11 macallan 1367 1.11 macallan x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1368 1.11 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1369 1.11 macallan width = ri->ri_font->fontwidth * ncols; 1370 1.11 macallan height = ri->ri_font->fontheight; 1371 1.11 macallan bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; 1372 1.11 macallan crmfb_fill_rect(scr->scr_cookie, x, y, width, height, bg); 1373 1.11 macallan } 1374 1.11 macallan 1375 1.11 macallan static void 1376 1.11 macallan crmfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1377 1.11 macallan { 1378 1.11 macallan struct rasops_info *ri = cookie; 1379 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1380 1.11 macallan int32_t x, ys, yd, width, height; 1381 1.11 macallan 1382 1.11 macallan x = ri->ri_xorigin; 1383 1.11 macallan ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1384 1.11 macallan yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1385 1.11 macallan width = ri->ri_emuwidth; 1386 1.11 macallan height = ri->ri_font->fontheight * nrows; 1387 1.15 macallan 1388 1.16 macallan crmfb_scroll(scr->scr_cookie, x, ys, x, yd, width, height); 1389 1.11 macallan } 1390 1.11 macallan 1391 1.11 macallan static void 1392 1.11 macallan crmfb_eraserows(void *cookie, int row, int nrows, long fillattr) 1393 1.11 macallan { 1394 1.11 macallan struct rasops_info *ri = cookie; 1395 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1396 1.11 macallan int32_t x, y, width, height, bg; 1397 1.11 macallan 1398 1.11 macallan if ((row == 0) && (nrows == ri->ri_rows)) { 1399 1.11 macallan x = y = 0; 1400 1.11 macallan width = ri->ri_width; 1401 1.11 macallan height = ri->ri_height; 1402 1.11 macallan } else { 1403 1.11 macallan x = ri->ri_xorigin; 1404 1.11 macallan y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1405 1.11 macallan width = ri->ri_emuwidth; 1406 1.11 macallan height = ri->ri_font->fontheight * nrows; 1407 1.11 macallan } 1408 1.11 macallan bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff]; 1409 1.11 macallan crmfb_fill_rect(scr->scr_cookie, x, y, width, height, bg); 1410 1.11 macallan } 1411 1.11 macallan 1412 1.11 macallan static void 1413 1.11 macallan crmfb_cursor(void *cookie, int on, int row, int col) 1414 1.11 macallan { 1415 1.11 macallan struct rasops_info *ri = cookie; 1416 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1417 1.11 macallan struct crmfb_softc *sc = scr->scr_cookie; 1418 1.11 macallan int x, y, wi,he; 1419 1.11 macallan 1420 1.11 macallan wi = ri->ri_font->fontwidth; 1421 1.11 macallan he = ri->ri_font->fontheight; 1422 1.11 macallan 1423 1.11 macallan if (ri->ri_flg & RI_CURSOR) { 1424 1.11 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1425 1.11 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1426 1.11 macallan crmfb_bitblt(sc, x, y, x, y, wi, he, 12); 1427 1.11 macallan ri->ri_flg &= ~RI_CURSOR; 1428 1.11 macallan } 1429 1.11 macallan 1430 1.11 macallan ri->ri_crow = row; 1431 1.11 macallan ri->ri_ccol = col; 1432 1.11 macallan 1433 1.11 macallan if (on) 1434 1.11 macallan { 1435 1.11 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 1436 1.11 macallan y = ri->ri_crow * he + ri->ri_yorigin; 1437 1.11 macallan crmfb_bitblt(sc, x, y, x, y, wi, he, 12); 1438 1.11 macallan ri->ri_flg |= RI_CURSOR; 1439 1.11 macallan } 1440 1.11 macallan } 1441 1.11 macallan 1442 1.11 macallan static void 1443 1.11 macallan crmfb_putchar(void *cookie, int row, int col, u_int c, long attr) 1444 1.11 macallan { 1445 1.11 macallan struct rasops_info *ri = cookie; 1446 1.11 macallan struct vcons_screen *scr = ri->ri_hw; 1447 1.11 macallan struct crmfb_softc *sc = scr->scr_cookie; 1448 1.28 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1449 1.28 macallan uint32_t bg, fg; 1450 1.28 macallan int x, y, wi, he, i, uc; 1451 1.28 macallan uint8_t *fd8; 1452 1.28 macallan uint16_t *fd16; 1453 1.28 macallan void *fd; 1454 1.11 macallan 1455 1.28 macallan wi = font->fontwidth; 1456 1.28 macallan he = font->fontheight; 1457 1.11 macallan 1458 1.11 macallan x = ri->ri_xorigin + col * wi; 1459 1.11 macallan y = ri->ri_yorigin + row * he; 1460 1.11 macallan 1461 1.17 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xff]; 1462 1.28 macallan fg = ri->ri_devcmap[(attr >> 24) & 0xff]; 1463 1.28 macallan uc = c - font->firstchar; 1464 1.28 macallan fd = (uint8_t *)font->data + uc * ri->ri_fontscale; 1465 1.11 macallan if (c == 0x20) { 1466 1.11 macallan crmfb_fill_rect(sc, x, y, wi, he, bg); 1467 1.11 macallan } else { 1468 1.39 macallan crmfb_make_room(sc, 6); 1469 1.28 macallan /* setup */ 1470 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_DRAWMODE, 1471 1.28 macallan DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | 1472 1.28 macallan DE_DRAWMODE_ROP | 1473 1.28 macallan DE_DRAWMODE_OPAQUE_STIP | DE_DRAWMODE_POLY_STIP); 1474 1.34 macallan wbflush(); 1475 1.34 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_ROP, 3); 1476 1.34 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_FG, fg); 1477 1.34 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_BG, bg); 1478 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PRIMITIVE, 1479 1.28 macallan DE_PRIM_RECTANGLE | DE_PRIM_LR | DE_PRIM_TB); 1480 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_STIPPLE_MODE, 1481 1.28 macallan 0x001f0000); 1482 1.28 macallan /* now let's feed the engine */ 1483 1.39 macallan crmfb_make_room(sc, 30); 1484 1.28 macallan if (font->stride == 1) { 1485 1.28 macallan /* shovel in 8 bit quantities */ 1486 1.28 macallan fd8 = fd; 1487 1.28 macallan for (i = 0; i < he; i++) { 1488 1.39 macallan if (i & 8) 1489 1.39 macallan crmfb_make_room(sc, 30); 1490 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1491 1.28 macallan CRIME_DE_STIPPLE_PAT, *fd8 << 24); 1492 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1493 1.28 macallan CRIME_DE_X_VERTEX_0, (x << 16) | y); 1494 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1495 1.28 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1496 1.28 macallan ((x + wi) << 16) | y); 1497 1.28 macallan y++; 1498 1.28 macallan fd8++; 1499 1.28 macallan } 1500 1.28 macallan } else if (font->stride == 2) { 1501 1.28 macallan /* shovel in 16 bit quantities */ 1502 1.28 macallan fd16 = fd; 1503 1.28 macallan for (i = 0; i < he; i++) { 1504 1.39 macallan if (i & 8) 1505 1.39 macallan crmfb_make_room(sc, 30); 1506 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1507 1.28 macallan CRIME_DE_STIPPLE_PAT, *fd16 << 16); 1508 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1509 1.28 macallan CRIME_DE_X_VERTEX_0, (x << 16) | y); 1510 1.28 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1511 1.28 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1512 1.28 macallan ((x + wi) << 16) | y); 1513 1.28 macallan y++; 1514 1.28 macallan fd16++; 1515 1.28 macallan } 1516 1.28 macallan } 1517 1.11 macallan } 1518 1.11 macallan } 1519 1.30 macallan 1520 1.30 macallan static void 1521 1.39 macallan crmfb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1522 1.39 macallan { 1523 1.39 macallan struct rasops_info *ri = cookie; 1524 1.39 macallan struct vcons_screen *scr = ri->ri_hw; 1525 1.39 macallan struct crmfb_softc *sc = scr->scr_cookie; 1526 1.39 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1527 1.39 macallan uint32_t bg, fg; 1528 1.39 macallan int x, y, wi, he, uc, xx; 1529 1.39 macallan void *fd; 1530 1.39 macallan 1531 1.39 macallan wi = font->fontwidth; 1532 1.39 macallan he = font->fontheight; 1533 1.39 macallan 1534 1.39 macallan x = ri->ri_xorigin + col * wi; 1535 1.39 macallan y = ri->ri_yorigin + row * he; 1536 1.39 macallan 1537 1.39 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xff]; 1538 1.39 macallan fg = (attr >> 24); 1539 1.39 macallan uc = c - font->firstchar; 1540 1.39 macallan fd = (uint8_t *)font->data + uc * ri->ri_fontscale; 1541 1.39 macallan 1542 1.39 macallan /* fill the cell with the background colour */ 1543 1.39 macallan crmfb_fill_rect(sc, x, y, wi, he, bg); 1544 1.39 macallan 1545 1.39 macallan /* if all we draw is a space we're done */ 1546 1.39 macallan if (c == 0x20) 1547 1.39 macallan return; 1548 1.39 macallan 1549 1.39 macallan /* copy the glyph into the linear buffer */ 1550 1.39 macallan memcpy(sc->sc_lptr, fd, ri->ri_fontscale); 1551 1.39 macallan wbflush(); 1552 1.39 macallan 1553 1.39 macallan /* now blit it on top of the requested fg colour cell */ 1554 1.39 macallan xx = fg * wi; 1555 1.39 macallan crmfb_make_room(sc, 2); 1556 1.39 macallan crmfb_src_mode(sc, 1557 1.39 macallan DE_MODE_LIN_A | 1558 1.39 macallan DE_MODE_BUFDEPTH_8 | 1559 1.39 macallan DE_MODE_TYPE_CI | 1560 1.39 macallan DE_MODE_PIXDEPTH_8); 1561 1.39 macallan crmfb_dst_mode(sc, 1562 1.39 macallan DE_MODE_TLB_A | 1563 1.39 macallan DE_MODE_BUFDEPTH_32 | 1564 1.39 macallan DE_MODE_TYPE_CI | 1565 1.39 macallan DE_MODE_PIXDEPTH_8); 1566 1.39 macallan 1567 1.39 macallan crmfb_make_room(sc, 6); 1568 1.39 macallan /* only write into the alpha channel */ 1569 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_DRAWMODE, 1570 1.39 macallan DE_DRAWMODE_PLANEMASK | 0x08 | 1571 1.39 macallan DE_DRAWMODE_XFER_EN); 1572 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PRIMITIVE, 1573 1.39 macallan DE_PRIM_RECTANGLE | DE_PRIM_TB); 1574 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_STRD_SRC, 1); 1575 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_ADDR_SRC, 0); 1576 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_X_VERTEX_0, 1577 1.39 macallan (xx << 16) | (sc->sc_height & 0xffff)); 1578 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1579 1.39 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1580 1.39 macallan ((xx + wi - 1) << 16) | ((sc->sc_height + he - 1) & 0xffff)); 1581 1.39 macallan 1582 1.39 macallan /* now draw the actual character */ 1583 1.39 macallan crmfb_make_room(sc, 2); 1584 1.39 macallan crmfb_src_mode(sc, 1585 1.39 macallan DE_MODE_TLB_A | 1586 1.39 macallan DE_MODE_BUFDEPTH_32 | 1587 1.39 macallan DE_MODE_TYPE_RGBA | 1588 1.39 macallan DE_MODE_PIXDEPTH_32); 1589 1.39 macallan crmfb_dst_mode(sc, sc->sc_de_mode); 1590 1.39 macallan 1591 1.39 macallan crmfb_make_room(sc, 6); 1592 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_DRAWMODE, 1593 1.39 macallan DE_DRAWMODE_PLANEMASK | DE_DRAWMODE_BYTEMASK | 1594 1.39 macallan DE_DRAWMODE_ALPHA_BLEND | 1595 1.39 macallan DE_DRAWMODE_XFER_EN); 1596 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_ALPHA_FUNC, 1597 1.39 macallan DE_ALPHA_ADD | 1598 1.39 macallan (DE_ALPHA_OP_SRC_ALPHA << DE_ALPHA_OP_SRC_SHIFT) | 1599 1.39 macallan (DE_ALPHA_OP_1_MINUS_SRC_ALPHA << DE_ALPHA_OP_DST_SHIFT)); 1600 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_PRIMITIVE, 1601 1.39 macallan DE_PRIM_RECTANGLE | DE_PRIM_TB); 1602 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_XFER_ADDR_SRC, 1603 1.39 macallan (xx << 16) | (sc->sc_height & 0xffff)); 1604 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, CRIME_DE_X_VERTEX_0, 1605 1.39 macallan (x << 16) | (y & 0xffff)); 1606 1.39 macallan bus_space_write_4(sc->sc_iot, sc->sc_reh, 1607 1.39 macallan CRIME_DE_X_VERTEX_1 | CRIME_DE_START, 1608 1.39 macallan ((x + wi - 1) << 16) | ((y + he - 1) & 0xffff)); 1609 1.39 macallan } 1610 1.39 macallan 1611 1.39 macallan static void 1612 1.30 macallan crmfb_setup_ddc(struct crmfb_softc *sc) 1613 1.30 macallan { 1614 1.30 macallan int i; 1615 1.30 macallan 1616 1.38 macallan memset(sc->sc_edid_data, 0, 128); 1617 1.46 thorpej iic_tag_init(&sc->sc_i2c); 1618 1.30 macallan sc->sc_i2c.ic_cookie = sc; 1619 1.30 macallan sc->sc_i2c.ic_send_start = crmfb_i2c_send_start; 1620 1.30 macallan sc->sc_i2c.ic_send_stop = crmfb_i2c_send_stop; 1621 1.30 macallan sc->sc_i2c.ic_initiate_xfer = crmfb_i2c_initiate_xfer; 1622 1.30 macallan sc->sc_i2c.ic_read_byte = crmfb_i2c_read_byte; 1623 1.30 macallan sc->sc_i2c.ic_write_byte = crmfb_i2c_write_byte; 1624 1.30 macallan i = 0; 1625 1.38 macallan while (sc->sc_edid_data[1] == 0 && i++ < 10) 1626 1.38 macallan ddc_read_edid(&sc->sc_i2c, sc->sc_edid_data, 128); 1627 1.30 macallan if (i > 1) 1628 1.30 macallan aprint_debug_dev(sc->sc_dev, 1629 1.30 macallan "had to try %d times to get EDID data\n", i); 1630 1.30 macallan if (i < 11) { 1631 1.38 macallan edid_parse(sc->sc_edid_data, &sc->sc_edid_info); 1632 1.32 macallan edid_print(&sc->sc_edid_info); 1633 1.30 macallan } 1634 1.30 macallan } 1635 1.30 macallan 1636 1.30 macallan /* I2C bitbanging */ 1637 1.30 macallan static void 1638 1.30 macallan crmfb_i2cbb_set_bits(void *cookie, uint32_t bits) 1639 1.30 macallan { 1640 1.30 macallan struct crmfb_softc *sc = cookie; 1641 1.30 macallan 1642 1.30 macallan bus_space_write_4(sc->sc_iot, sc->sc_ioh, CRMFB_I2C_VGA, bits ^ 3); 1643 1.30 macallan } 1644 1.30 macallan 1645 1.30 macallan static void 1646 1.30 macallan crmfb_i2cbb_set_dir(void *cookie, uint32_t dir) 1647 1.30 macallan { 1648 1.30 macallan 1649 1.30 macallan /* Nothing to do */ 1650 1.30 macallan } 1651 1.30 macallan 1652 1.30 macallan static uint32_t 1653 1.30 macallan crmfb_i2cbb_read(void *cookie) 1654 1.30 macallan { 1655 1.30 macallan struct crmfb_softc *sc = cookie; 1656 1.30 macallan 1657 1.30 macallan return bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_I2C_VGA) ^ 3; 1658 1.30 macallan } 1659 1.30 macallan 1660 1.30 macallan static int 1661 1.30 macallan crmfb_i2c_send_start(void *cookie, int flags) 1662 1.30 macallan { 1663 1.30 macallan 1664 1.30 macallan return i2c_bitbang_send_start(cookie, flags, &crmfb_i2cbb_ops); 1665 1.30 macallan } 1666 1.30 macallan 1667 1.30 macallan static int 1668 1.30 macallan crmfb_i2c_send_stop(void *cookie, int flags) 1669 1.30 macallan { 1670 1.30 macallan 1671 1.30 macallan return i2c_bitbang_send_stop(cookie, flags, &crmfb_i2cbb_ops); 1672 1.30 macallan } 1673 1.30 macallan 1674 1.30 macallan static int 1675 1.30 macallan crmfb_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 1676 1.30 macallan { 1677 1.30 macallan 1678 1.30 macallan return i2c_bitbang_initiate_xfer(cookie, addr, flags, 1679 1.30 macallan &crmfb_i2cbb_ops); 1680 1.30 macallan } 1681 1.30 macallan 1682 1.30 macallan static int 1683 1.30 macallan crmfb_i2c_read_byte(void *cookie, uint8_t *valp, int flags) 1684 1.30 macallan { 1685 1.30 macallan 1686 1.30 macallan return i2c_bitbang_read_byte(cookie, valp, flags, &crmfb_i2cbb_ops); 1687 1.30 macallan } 1688 1.30 macallan 1689 1.30 macallan static int 1690 1.30 macallan crmfb_i2c_write_byte(void *cookie, uint8_t val, int flags) 1691 1.30 macallan { 1692 1.30 macallan 1693 1.30 macallan return i2c_bitbang_write_byte(cookie, val, flags, &crmfb_i2cbb_ops); 1694 1.30 macallan } 1695 1.32 macallan 1696 1.32 macallan /* mode setting stuff */ 1697 1.32 macallan static uint32_t 1698 1.32 macallan calc_pll(int f_out) 1699 1.32 macallan { 1700 1.32 macallan uint32_t ret; 1701 1.32 macallan int f_in = 20000; /* 20MHz in */ 1702 1.32 macallan int M, N, P; 1703 1.32 macallan int error, div, best = 9999999; 1704 1.32 macallan int ff1, ff2; 1705 1.32 macallan int MM = 0, NN = 0, PP = 0, ff = 0; 1706 1.32 macallan 1707 1.32 macallan /* f_out = M * f_in / (N * (1 << P) */ 1708 1.32 macallan 1709 1.32 macallan for (P = 0; P < 4; P++) { 1710 1.32 macallan for (N = 64; N > 0; N--) { 1711 1.32 macallan div = N * (1 << P); 1712 1.32 macallan M = f_out * div / f_in; 1713 1.32 macallan if ((M < 257) && (M > 100)) { 1714 1.32 macallan ff1 = M * f_in / div; 1715 1.32 macallan ff2 = (M + 1) * f_in / div; 1716 1.32 macallan error = abs(ff1 - f_out); 1717 1.32 macallan if (error < best) { 1718 1.32 macallan MM = M; 1719 1.32 macallan NN = N; 1720 1.32 macallan PP = P; 1721 1.32 macallan ff = ff1; 1722 1.32 macallan best = error; 1723 1.32 macallan } 1724 1.32 macallan error = abs(ff2 - f_out); 1725 1.32 macallan if ((error < best) && ( M < 256)){ 1726 1.32 macallan MM = M + 1; 1727 1.32 macallan NN = N; 1728 1.32 macallan PP = P; 1729 1.32 macallan ff = ff2; 1730 1.32 macallan best = error; 1731 1.32 macallan } 1732 1.32 macallan } 1733 1.32 macallan } 1734 1.32 macallan } 1735 1.32 macallan DPRINTF("%d: M %d N %d P %d -> %d\n", f_out, MM, NN, PP, ff); 1736 1.32 macallan /* now shove the parameters into the register's format */ 1737 1.32 macallan ret = (MM - 1) | ((NN - 1) << 8) | (P << 14); 1738 1.32 macallan return ret; 1739 1.32 macallan } 1740 1.32 macallan 1741 1.32 macallan static int 1742 1.32 macallan crmfb_set_mode(struct crmfb_softc *sc, const struct videomode *mode) 1743 1.32 macallan { 1744 1.32 macallan uint32_t d, dc; 1745 1.32 macallan int tmp, diff; 1746 1.32 macallan 1747 1.34 macallan switch (mode->hdisplay % 32) { 1748 1.34 macallan case 0: 1749 1.34 macallan sc->sc_console_depth = 8; 1750 1.34 macallan break; 1751 1.34 macallan case 16: 1752 1.34 macallan sc->sc_console_depth = 16; 1753 1.34 macallan break; 1754 1.34 macallan case 8: 1755 1.34 macallan case 24: 1756 1.34 macallan sc->sc_console_depth = 32; 1757 1.34 macallan break; 1758 1.34 macallan default: 1759 1.34 macallan aprint_error_dev(sc->sc_dev, 1760 1.34 macallan "hdisplay (%d) is not a multiple of 32\n", 1761 1.34 macallan mode->hdisplay); 1762 1.34 macallan return FALSE; 1763 1.32 macallan } 1764 1.34 macallan if (mode->dot_clock > 150000) { 1765 1.34 macallan aprint_error_dev(sc->sc_dev, 1766 1.34 macallan "requested dot clock is too high ( %d MHz )\n", 1767 1.34 macallan mode->dot_clock / 1000); 1768 1.32 macallan return FALSE; 1769 1.32 macallan } 1770 1.32 macallan 1771 1.32 macallan /* disable DMA */ 1772 1.32 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_OVR_CONTROL); 1773 1.32 macallan d &= ~(1 << CRMFB_OVR_CONTROL_DMAEN_SHIFT); 1774 1.32 macallan crmfb_write_reg(sc, CRMFB_OVR_CONTROL, d); 1775 1.32 macallan DELAY(50000); 1776 1.32 macallan d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CRMFB_FRM_CONTROL); 1777 1.32 macallan d &= ~(1 << CRMFB_FRM_CONTROL_DMAEN_SHIFT); 1778 1.32 macallan crmfb_write_reg(sc, CRMFB_FRM_CONTROL, d); 1779 1.32 macallan DELAY(50000); 1780 1.32 macallan crmfb_write_reg(sc, CRMFB_DID_CONTROL, d); 1781 1.32 macallan DELAY(50000); 1782 1.32 macallan 1783 1.32 macallan if (!crmfb_wait_dma_idle(sc)) 1784 1.32 macallan aprint_error("crmfb: crmfb_wait_dma_idle timed out\n"); 1785 1.32 macallan 1786 1.32 macallan /* ok, now we're good to go */ 1787 1.32 macallan dc = calc_pll(mode->dot_clock); 1788 1.32 macallan 1789 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_XY, 1 << CRMFB_VT_XY_FREEZE_SHIFT); 1790 1.32 macallan delay(1000); 1791 1.32 macallan 1792 1.32 macallan /* set the dot clock pll but don't start it yet */ 1793 1.32 macallan crmfb_write_reg(sc, CRMFB_DOTCLOCK, dc); 1794 1.32 macallan delay(10000); 1795 1.32 macallan 1796 1.32 macallan /* pixel counter */ 1797 1.32 macallan d = mode->htotal | (mode->vtotal << 12); 1798 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_XYMAX, d); 1799 1.32 macallan 1800 1.32 macallan /* video timings */ 1801 1.32 macallan d = mode->vsync_end | (mode->vsync_start << 12); 1802 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_VSYNC, d); 1803 1.32 macallan 1804 1.32 macallan d = mode->hsync_end | (mode->hsync_start << 12); 1805 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_HSYNC, d); 1806 1.32 macallan 1807 1.32 macallan d = mode->vtotal | (mode->vdisplay << 12); 1808 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_VBLANK, d); 1809 1.32 macallan 1810 1.32 macallan d = (mode->htotal - 5) | ((mode->hdisplay - 5) << 12); 1811 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_HBLANK, d); 1812 1.32 macallan 1813 1.32 macallan d = mode->vtotal | (mode->vdisplay << 12); 1814 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_VCMAP, d); 1815 1.32 macallan d = mode->htotal | (mode->hdisplay << 12); 1816 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_HCMAP, d); 1817 1.32 macallan 1818 1.32 macallan d = 0; 1819 1.32 macallan if (mode->flags & VID_NHSYNC) d |= CRMFB_VT_FLAGS_HDRV_INVERT; 1820 1.32 macallan if (mode->flags & VID_NVSYNC) d |= CRMFB_VT_FLAGS_VDRV_INVERT; 1821 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_FLAGS, d); 1822 1.38 macallan sc->sc_vtflags = d; 1823 1.32 macallan 1824 1.32 macallan diff = -abs(mode->vtotal - mode->vdisplay - 1); 1825 1.32 macallan d = ((uint32_t)diff << 12) & 0x00fff000; 1826 1.32 macallan d |= (mode->htotal - 20); 1827 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_DID_STARTXY, d); 1828 1.32 macallan 1829 1.32 macallan d = ((uint32_t)(diff + 1) << 12) & 0x00fff000; 1830 1.32 macallan d |= (mode->htotal - 54); 1831 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_CRS_STARTXY, d); 1832 1.32 macallan 1833 1.32 macallan d = ((uint32_t)diff << 12) & 0x00fff000; 1834 1.32 macallan d |= (mode->htotal - 4); 1835 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_VC_STARTXY, d); 1836 1.32 macallan 1837 1.32 macallan tmp = mode->htotal - 19; 1838 1.32 macallan d = tmp << 12; 1839 1.32 macallan d |= ((tmp + mode->hdisplay - 2) % mode->htotal); 1840 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_HPIX_EN, d); 1841 1.32 macallan 1842 1.32 macallan d = mode->vdisplay | (mode->vtotal << 12); 1843 1.32 macallan crmfb_write_reg(sc, CRMFB_VT_VPIX_EN, d); 1844 1.32 macallan 1845 1.32 macallan sc->sc_width = mode->hdisplay; 1846 1.32 macallan sc->sc_height = mode->vdisplay; 1847 1.32 macallan 1848 1.32 macallan return TRUE; 1849 1.32 macallan } 1850 1.45 jmcneill 1851 1.45 jmcneill /* 1852 1.45 jmcneill * Parse a mode string in the form WIDTHxHEIGHT[@REFRESH] and return 1853 1.45 jmcneill * monitor timings generated using the VESA GTF formula. 1854 1.45 jmcneill */ 1855 1.45 jmcneill static int 1856 1.45 jmcneill crmfb_parse_mode(const char *modestr, struct videomode *mode) 1857 1.45 jmcneill { 1858 1.45 jmcneill char *x, *at; 1859 1.45 jmcneill int width, height, refresh; 1860 1.45 jmcneill 1861 1.45 jmcneill if (modestr == NULL) 1862 1.45 jmcneill return EINVAL; 1863 1.45 jmcneill 1864 1.45 jmcneill x = strchr(modestr, 'x'); 1865 1.45 jmcneill at = strchr(modestr, '@'); 1866 1.45 jmcneill 1867 1.45 jmcneill if (x == NULL || (at != NULL && at < x)) 1868 1.45 jmcneill return EINVAL; 1869 1.45 jmcneill 1870 1.45 jmcneill width = strtoul(modestr, NULL, 10); 1871 1.45 jmcneill height = strtoul(x + 1, NULL, 10); 1872 1.45 jmcneill refresh = at ? strtoul(at + 1, NULL, 10) : 60; 1873 1.45 jmcneill 1874 1.45 jmcneill if (width == 0 || height == 0 || refresh == 0) 1875 1.45 jmcneill return EINVAL; 1876 1.45 jmcneill 1877 1.45 jmcneill vesagtf_mode(width, height, refresh, mode); 1878 1.45 jmcneill 1879 1.45 jmcneill return 0; 1880 1.45 jmcneill } 1881