1 1.8 thorpej /* $NetBSD: omap3_dss.c,v 1.8 2025/09/06 22:53:48 thorpej Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /* 4 1.1 jmcneill * Copyright (c) 2010 Michael Lorenz 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 jmcneill * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 jmcneill * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 jmcneill * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 jmcneill * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 jmcneill * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 jmcneill */ 27 1.1 jmcneill 28 1.1 jmcneill /* 29 1.1 jmcneill * A console driver for OMAP 3530's built-in video controller 30 1.1 jmcneill * tested on beagleboard only so far 31 1.1 jmcneill */ 32 1.1 jmcneill 33 1.1 jmcneill #include "opt_wsdisplay_compat.h" 34 1.1 jmcneill 35 1.1 jmcneill #include <sys/cdefs.h> 36 1.8 thorpej __KERNEL_RCSID(0, "$NetBSD: omap3_dss.c,v 1.8 2025/09/06 22:53:48 thorpej Exp $"); 37 1.1 jmcneill 38 1.1 jmcneill #include <sys/param.h> 39 1.1 jmcneill #include <sys/systm.h> 40 1.1 jmcneill #include <sys/kernel.h> 41 1.1 jmcneill #include <sys/device.h> 42 1.1 jmcneill #include <sys/lwp.h> 43 1.1 jmcneill #include <sys/kauth.h> 44 1.1 jmcneill #include <sys/bus.h> 45 1.1 jmcneill 46 1.1 jmcneill #include <uvm/uvm_extern.h> 47 1.1 jmcneill 48 1.1 jmcneill #include <dev/videomode/videomode.h> 49 1.1 jmcneill #include <dev/videomode/edidvar.h> 50 1.1 jmcneill 51 1.1 jmcneill #include <dev/fdt/fdtvar.h> 52 1.8 thorpej #include <dev/fdt/fdt_console.h> 53 1.1 jmcneill 54 1.1 jmcneill #include <arm/ti/omap3_dssreg.h> 55 1.1 jmcneill 56 1.1 jmcneill #include <dev/wscons/wsdisplayvar.h> 57 1.1 jmcneill #include <dev/wscons/wsconsio.h> 58 1.1 jmcneill #include <dev/wsfont/wsfont.h> 59 1.1 jmcneill #include <dev/rasops/rasops.h> 60 1.1 jmcneill #include <dev/wscons/wsdisplay_vconsvar.h> 61 1.1 jmcneill 62 1.1 jmcneill struct omapfb_softc { 63 1.1 jmcneill device_t sc_dev; 64 1.1 jmcneill 65 1.1 jmcneill bus_space_tag_t sc_iot; 66 1.1 jmcneill bus_dma_tag_t sc_dmat; 67 1.1 jmcneill bus_space_handle_t sc_regh; 68 1.1 jmcneill bus_dmamap_t sc_dmamap; 69 1.1 jmcneill bus_dma_segment_t sc_dmamem[1]; 70 1.1 jmcneill size_t sc_vramsize; 71 1.1 jmcneill 72 1.1 jmcneill int sc_width, sc_height, sc_depth, sc_stride; 73 1.1 jmcneill int sc_locked; 74 1.1 jmcneill void *sc_fbaddr, *sc_vramaddr; 75 1.1 jmcneill 76 1.1 jmcneill int sc_cursor_offset; 77 1.1 jmcneill uint32_t *sc_cursor_img; 78 1.1 jmcneill int sc_cursor_x, sc_cursor_y; 79 1.1 jmcneill int sc_hot_x, sc_hot_y; 80 1.1 jmcneill uint8_t sc_cursor_bitmap[8 * 64]; 81 1.1 jmcneill uint8_t sc_cursor_mask[8 * 64]; 82 1.1 jmcneill uint32_t sc_cursor_cmap[4]; 83 1.1 jmcneill 84 1.1 jmcneill bus_addr_t sc_fbhwaddr; 85 1.1 jmcneill uint32_t *sc_clut; 86 1.1 jmcneill uint32_t sc_dispc_config; 87 1.1 jmcneill int sc_video_is_on; 88 1.1 jmcneill struct vcons_screen sc_console_screen; 89 1.1 jmcneill struct wsscreen_descr sc_defaultscreen_descr; 90 1.1 jmcneill const struct wsscreen_descr *sc_screens[1]; 91 1.1 jmcneill struct wsscreen_list sc_screenlist; 92 1.1 jmcneill struct vcons_data vd; 93 1.1 jmcneill int sc_mode; 94 1.1 jmcneill uint8_t sc_cmap_red[256], sc_cmap_green[256], sc_cmap_blue[256]; 95 1.1 jmcneill void (*sc_putchar)(void *, int, int, u_int, long); 96 1.1 jmcneill 97 1.1 jmcneill uint8_t sc_edid_data[1024]; 98 1.1 jmcneill size_t sc_edid_size; 99 1.1 jmcneill }; 100 1.1 jmcneill 101 1.1 jmcneill static int omapfb_match(device_t, cfdata_t, void *); 102 1.1 jmcneill static void omapfb_attach(device_t, device_t, void *); 103 1.1 jmcneill 104 1.1 jmcneill CFATTACH_DECL_NEW(omap3_dss, sizeof(struct omapfb_softc), 105 1.1 jmcneill omapfb_match, omapfb_attach, NULL, NULL); 106 1.1 jmcneill 107 1.1 jmcneill static int omapfb_ioctl(void *, void *, u_long, void *, int, 108 1.1 jmcneill struct lwp *); 109 1.1 jmcneill static paddr_t omapfb_mmap(void *, void *, off_t, int); 110 1.1 jmcneill static void omapfb_init_screen(void *, struct vcons_screen *, int, long *); 111 1.1 jmcneill 112 1.1 jmcneill static int omapfb_putcmap(struct omapfb_softc *, struct wsdisplay_cmap *); 113 1.1 jmcneill static int omapfb_getcmap(struct omapfb_softc *, struct wsdisplay_cmap *); 114 1.1 jmcneill static void omapfb_restore_palette(struct omapfb_softc *); 115 1.1 jmcneill static void omapfb_putpalreg(struct omapfb_softc *, int, uint8_t, 116 1.1 jmcneill uint8_t, uint8_t); 117 1.1 jmcneill 118 1.1 jmcneill static int omapfb_set_depth(struct omapfb_softc *, int); 119 1.1 jmcneill static void omapfb_set_video(struct omapfb_softc *, int); 120 1.1 jmcneill 121 1.1 jmcneill static void omapfb_move_cursor(struct omapfb_softc *, int, int); 122 1.1 jmcneill static int omapfb_do_cursor(struct omapfb_softc *, 123 1.1 jmcneill struct wsdisplay_cursor *); 124 1.1 jmcneill 125 1.1 jmcneill #if NOMAPDMA > 0 126 1.1 jmcneill static void omapfb_init(struct omapfb_softc *); 127 1.1 jmcneill static void omapfb_wait_idle(struct omapfb_softc *); 128 1.1 jmcneill static void omapfb_rectfill(struct omapfb_softc *, int, int, int, int, 129 1.1 jmcneill uint32_t); 130 1.1 jmcneill static void omapfb_bitblt(struct omapfb_softc *, int, int, int, int, int, 131 1.1 jmcneill int, int); 132 1.1 jmcneill 133 1.1 jmcneill static void omapfb_cursor(void *, int, int, int); 134 1.1 jmcneill static void omapfb_putchar(void *, int, int, u_int, long); 135 1.1 jmcneill static void omapfb_copycols(void *, int, int, int, int); 136 1.1 jmcneill static void omapfb_erasecols(void *, int, int, int, long); 137 1.1 jmcneill static void omapfb_copyrows(void *, int, int, int); 138 1.1 jmcneill static void omapfb_eraserows(void *, int, int, long); 139 1.1 jmcneill #endif /* NOMAPDMA > 0 */ 140 1.1 jmcneill 141 1.1 jmcneill struct wsdisplay_accessops omapfb_accessops = { 142 1.1 jmcneill omapfb_ioctl, 143 1.1 jmcneill omapfb_mmap, 144 1.1 jmcneill NULL, /* alloc_screen */ 145 1.1 jmcneill NULL, /* free_screen */ 146 1.1 jmcneill NULL, /* show_screen */ 147 1.1 jmcneill NULL, /* load_font */ 148 1.1 jmcneill NULL, /* pollc */ 149 1.1 jmcneill NULL /* scroll */ 150 1.1 jmcneill }; 151 1.1 jmcneill 152 1.1 jmcneill uint32_t venc_mode_ntsc[] = { 153 1.1 jmcneill 0x00000000, 0x00000001, 0x00008040, 0x00000359, 154 1.1 jmcneill 0x0000020c, 0x00000000, 0x043f2631, 0x00000000, 155 1.1 jmcneill 0x00000102, 0x0000016c, 0x0000012f, 0x00000043, 156 1.1 jmcneill 0x00000038, 0x00000007, 0x00000001, 0x00000038, 157 1.1 jmcneill 0x21f07c1f, 0x00000000, 0x01310011, 0x0000f003, 158 1.1 jmcneill 0x00000000, 0x069300f4, 0x0016020c, 0x00060107, 159 1.1 jmcneill 0x008e0350, 0x000f0359, 0x01a00000, 0x020701a0, 160 1.1 jmcneill 0x01ac0024, 0x020d01ac, 0x00000006, 0x03480078, 161 1.1 jmcneill 0x02060024, 0x0001008a, 0x01ac0106, 0x01060006, 162 1.1 jmcneill 0x00140001, 0x00010001, 0x00f90000, 0x0000000d, 163 1.1 jmcneill 0x00000000}; 164 1.1 jmcneill 165 1.1 jmcneill extern const u_char rasops_cmap[768]; 166 1.1 jmcneill 167 1.3 thorpej static const struct device_compatible_entry compat_data[] = { 168 1.3 thorpej { .compat = "ti,omap3-dss" }, 169 1.3 thorpej DEVICE_COMPAT_EOL 170 1.1 jmcneill }; 171 1.1 jmcneill 172 1.1 jmcneill static int omapfb_console_phandle = -1; 173 1.1 jmcneill 174 1.1 jmcneill static int 175 1.1 jmcneill omapfb_match(device_t parent, cfdata_t match, void *aux) 176 1.1 jmcneill { 177 1.1 jmcneill struct fdt_attach_args * const faa = aux; 178 1.1 jmcneill 179 1.3 thorpej return of_compatible_match(faa->faa_phandle, compat_data); 180 1.1 jmcneill } 181 1.1 jmcneill 182 1.1 jmcneill static void 183 1.1 jmcneill omapfb_attach(device_t parent, device_t self, void *aux) 184 1.1 jmcneill { 185 1.1 jmcneill struct omapfb_softc *sc = device_private(self); 186 1.1 jmcneill struct fdt_attach_args *faa = aux; 187 1.1 jmcneill const int phandle = faa->faa_phandle; 188 1.1 jmcneill struct rasops_info *ri; 189 1.1 jmcneill struct wsemuldisplaydev_attach_args aa; 190 1.1 jmcneill prop_dictionary_t dict; 191 1.1 jmcneill prop_data_t edid_data; 192 1.1 jmcneill unsigned long defattr; 193 1.1 jmcneill #ifdef WSDISPLAY_MULTICONS 194 1.1 jmcneill bool is_console = true; 195 1.1 jmcneill #else 196 1.1 jmcneill bool is_console = phandle == omapfb_console_phandle; 197 1.1 jmcneill #endif 198 1.1 jmcneill uint32_t sz, reg; 199 1.1 jmcneill int segs, i, j; 200 1.1 jmcneill bus_addr_t addr; 201 1.1 jmcneill bus_size_t size; 202 1.1 jmcneill 203 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 204 1.1 jmcneill aprint_error(": couldn't get registers\n"); 205 1.1 jmcneill return; 206 1.1 jmcneill } 207 1.1 jmcneill 208 1.1 jmcneill sc->sc_dev = self; 209 1.1 jmcneill sc->sc_iot = faa->faa_bst; 210 1.1 jmcneill sc->sc_dmat = faa->faa_dmat; 211 1.1 jmcneill 212 1.1 jmcneill if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_regh) != 0) { 213 1.1 jmcneill aprint_error(": couldn't map registers\n"); 214 1.1 jmcneill return; 215 1.1 jmcneill } 216 1.1 jmcneill 217 1.1 jmcneill aprint_naive("\n"); 218 1.1 jmcneill aprint_normal(": OMAP onboard video\n"); 219 1.1 jmcneill 220 1.1 jmcneill sc->sc_video_is_on = 1; 221 1.1 jmcneill 222 1.1 jmcneill /* 223 1.1 jmcneill * XXX 224 1.1 jmcneill * different u-boot versions initialize the graphics controller in 225 1.1 jmcneill * different ways, so we look for the display resolution in a few 226 1.1 jmcneill * different places... 227 1.1 jmcneill */ 228 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE); 229 1.1 jmcneill if (sz == 0) { 230 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh, 231 1.1 jmcneill OMAPFB_DISPC_SIZE_LCD); 232 1.1 jmcneill } 233 1.1 jmcneill if (sz == 0) { 234 1.1 jmcneill sz = bus_space_read_4(sc->sc_iot, sc->sc_regh, 235 1.1 jmcneill OMAPFB_DISPC_SIZE_DIG); 236 1.1 jmcneill } 237 1.1 jmcneill 238 1.1 jmcneill /* ... and make sure it ends up where we need it */ 239 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE, sz); 240 1.1 jmcneill 241 1.1 jmcneill sc->sc_width = (sz & 0xfff) + 1; 242 1.1 jmcneill sc->sc_height = ((sz & 0x0fff0000 ) >> 16) + 1; 243 1.1 jmcneill sc->sc_depth = 16; 244 1.1 jmcneill sc->sc_stride = sc->sc_width << 1; 245 1.1 jmcneill 246 1.1 jmcneill if (sc->sc_width == 1 || sc->sc_height == 1) { 247 1.1 jmcneill aprint_error_dev(self, "bogus display size, not attaching\n"); 248 1.1 jmcneill return; 249 1.1 jmcneill } 250 1.1 jmcneill 251 1.1 jmcneill printf("%s: firmware set up %d x %d\n", device_xname(self), 252 1.1 jmcneill sc->sc_width, sc->sc_height); 253 1.1 jmcneill #if 0 254 1.1 jmcneill printf("DSS revision: %08x\n", 255 1.1 jmcneill bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_REVISION)); 256 1.1 jmcneill #endif 257 1.1 jmcneill dict = device_properties(self); 258 1.1 jmcneill edid_data = prop_dictionary_get(dict, "EDID"); 259 1.1 jmcneill 260 1.1 jmcneill if (edid_data != NULL) { 261 1.1 jmcneill struct edid_info ei; 262 1.1 jmcneill 263 1.1 jmcneill sc->sc_edid_size = uimin(prop_data_size(edid_data), 1024); 264 1.1 jmcneill memset(sc->sc_edid_data, 0, sizeof(sc->sc_edid_data)); 265 1.2 skrll memcpy(sc->sc_edid_data, prop_data_value(edid_data), sc->sc_edid_size); 266 1.1 jmcneill 267 1.1 jmcneill edid_parse(sc->sc_edid_data, &ei); 268 1.1 jmcneill edid_print(&ei); 269 1.1 jmcneill } 270 1.1 jmcneill 271 1.1 jmcneill /* setup video DMA */ 272 1.1 jmcneill sc->sc_vramsize = (12 << 20) + PAGE_SIZE; /* 12MB + CLUT */ 273 1.1 jmcneill 274 1.1 jmcneill if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0, 275 1.1 jmcneill sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) { 276 1.1 jmcneill panic("boo!\n"); 277 1.1 jmcneill aprint_error_dev(sc->sc_dev, 278 1.1 jmcneill "failed to allocate video memory\n"); 279 1.1 jmcneill return; 280 1.1 jmcneill } 281 1.1 jmcneill 282 1.1 jmcneill if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize, 283 1.1 jmcneill &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) { 284 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to map video RAM\n"); 285 1.1 jmcneill return; 286 1.1 jmcneill } 287 1.1 jmcneill sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + PAGE_SIZE; 288 1.1 jmcneill sc->sc_clut = sc->sc_vramaddr; 289 1.1 jmcneill 290 1.1 jmcneill if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize, 291 1.1 jmcneill 0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) { 292 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to create DMA map\n"); 293 1.1 jmcneill return; 294 1.1 jmcneill } 295 1.1 jmcneill 296 1.1 jmcneill if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr, 297 1.1 jmcneill sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) { 298 1.1 jmcneill aprint_error_dev(sc->sc_dev, "failed to load DMA map\n"); 299 1.1 jmcneill return; 300 1.1 jmcneill } 301 1.1 jmcneill 302 1.1 jmcneill if (sc->sc_depth == 8) { 303 1.1 jmcneill j = 0; 304 1.1 jmcneill for (i = 0; i < 256; i++) { 305 1.1 jmcneill sc->sc_cmap_red[i] = rasops_cmap[j]; 306 1.1 jmcneill sc->sc_cmap_green[i] = rasops_cmap[j + 1]; 307 1.1 jmcneill sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; 308 1.1 jmcneill j += 3; 309 1.1 jmcneill } 310 1.1 jmcneill } else { 311 1.1 jmcneill for (i = 0; i < 256; i++) { 312 1.1 jmcneill sc->sc_cmap_red[i] = i; 313 1.1 jmcneill sc->sc_cmap_green[i] = i; 314 1.1 jmcneill sc->sc_cmap_blue[i] = i; 315 1.1 jmcneill } 316 1.1 jmcneill } 317 1.1 jmcneill omapfb_restore_palette(sc); 318 1.1 jmcneill 319 1.1 jmcneill /* now that we have video memory, stick it to the video controller */ 320 1.1 jmcneill 321 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG); 322 1.1 jmcneill reg &= ~(OMAP_DISPC_SYSC_STANDBY_MASK | OMAP_DISPC_SYSC_IDLE_MASK); 323 1.1 jmcneill reg |= OMAP_DISPC_SYSC_SMART_STANDBY | OMAP_DISPC_SYSC_SMART_IDLE | 324 1.1 jmcneill OMAP_DISPC_SYSC_WAKEUP_ENABLE | OMAP_SYSCONF_AUTOIDLE; 325 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG, reg); 326 1.1 jmcneill 327 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_SYSCONFIG, 328 1.1 jmcneill OMAP_SYSCONF_AUTOIDLE); 329 1.1 jmcneill 330 1.1 jmcneill reg = OMAP_DISPC_CFG_TV_ALPHA_EN | OMAP_DISPC_CFG_LCD_ALPHA_EN; 331 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG, reg); 332 1.1 jmcneill sc->sc_dispc_config = reg; 333 1.1 jmcneill 334 1.1 jmcneill /* we use overlay 1 for the console and X */ 335 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GLOBAL_ALPHA, 336 1.1 jmcneill 0x00ff00ff); 337 1.1 jmcneill sc->sc_fbhwaddr = sc->sc_dmamem->ds_addr + PAGE_SIZE; 338 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_BASE_0, 339 1.1 jmcneill sc->sc_fbhwaddr); 340 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 341 1.1 jmcneill OMAPFB_DISPC_VID1_POSITION, 0); 342 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_SIZE, 343 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1)); 344 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 345 1.1 jmcneill OMAPFB_DISPC_VID1_PICTURE_SIZE, 346 1.1 jmcneill ((sc->sc_height - 1) << 16) | (sc->sc_width - 1)); 347 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 348 1.1 jmcneill OMAPFB_DISPC_VID1_ROW_INC, 1); 349 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 350 1.1 jmcneill OMAPFB_DISPC_VID1_PIXEL_INC, 1); 351 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 352 1.1 jmcneill OMAPFB_DISPC_VID1_PRELOAD, 0x60); 353 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ATTRIBUTES, 354 1.1 jmcneill OMAP_VID_ATTR_ENABLE | 355 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 | 356 1.1 jmcneill OMAP_VID_ATTR_RGB16 | 357 1.1 jmcneill OMAP_VID_ATTR_REPLICATION); 358 1.1 jmcneill 359 1.1 jmcneill /* turn off overlay 2 */ 360 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 361 1.1 jmcneill OMAPFB_DISPC_VID2_ATTRIBUTES, 0); 362 1.1 jmcneill 363 1.1 jmcneill /* initialize the gfx layer for use as hardware cursor */ 364 1.1 jmcneill sc->sc_cursor_cmap[0] = 0; 365 1.1 jmcneill sc->sc_cursor_offset = (12 << 20) - (64 * 64 * 4); 366 1.1 jmcneill sc->sc_cursor_img = 367 1.1 jmcneill (uint32_t *)((uint8_t *)sc->sc_fbaddr + sc->sc_cursor_offset); 368 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0, 369 1.1 jmcneill sc->sc_fbhwaddr + sc->sc_cursor_offset); 370 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_TABLE_BASE, 371 1.1 jmcneill sc->sc_dmamem->ds_addr); 372 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE, 373 1.1 jmcneill 0x003f003f); 374 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION, 375 1.1 jmcneill 0x00100010); 376 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 377 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD, 0x60); 378 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ATTRIBUTES, 379 1.1 jmcneill /*OMAP_DISPC_ATTR_ENABLE |*/ 380 1.1 jmcneill OMAP_DISPC_ATTR_BURST_16x32 | 381 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 | 382 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION); 383 1.1 jmcneill 384 1.1 jmcneill #if 0 385 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 386 1.1 jmcneill OMAPFB_DSS_CONTROL)); 387 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_CONTROL, 388 1.1 jmcneill /*OMAP_DSSCTRL_DISPC_CLK_SWITCH |*/ 389 1.1 jmcneill OMAP_DSSCTRL_CLOCK_MODE | 390 1.1 jmcneill OMAP_DSSCTRL_VENC_CLOCK_4X | 391 1.1 jmcneill OMAP_DSSCTRL_DAC_DEMEN); 392 1.1 jmcneill #endif 393 1.1 jmcneill 394 1.1 jmcneill #if 0 395 1.1 jmcneill /* VENC to NTSC mode */ 396 1.1 jmcneill int adr = OMAPFB_VENC_F_CONTROL; 397 1.1 jmcneill for (i = 0; i < __arraycount(venc_mode_ntsc); i++) { 398 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, adr, 399 1.1 jmcneill venc_mode_ntsc[i]); 400 1.1 jmcneill adr += 4; 401 1.1 jmcneill } 402 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_F_CONTROL, 403 1.1 jmcneill venc_mode_ntsc[0]); 404 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_SYNC_CTRL, 405 1.1 jmcneill venc_mode_ntsc[2]); 406 1.1 jmcneill 407 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_DEFAULT_COLOR_1, 408 1.1 jmcneill 0x00ff0000); 409 1.1 jmcneill #endif 410 1.1 jmcneill 411 1.1 jmcneill /* now we make sure the video output is actually running */ 412 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 413 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 414 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 415 1.1 jmcneill 416 1.1 jmcneill #ifdef OMAPFB_DEBUG 417 1.1 jmcneill printf("attr: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 418 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES)); 419 1.1 jmcneill printf("preload: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 420 1.1 jmcneill OMAPFB_DISPC_GFX_PRELOAD)); 421 1.1 jmcneill printf("config: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 422 1.1 jmcneill OMAPFB_DISPC_CONFIG)); 423 1.1 jmcneill printf("control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 424 1.1 jmcneill OMAPFB_DISPC_CONTROL)); 425 1.1 jmcneill printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 426 1.1 jmcneill OMAPFB_DSS_CONTROL)); 427 1.1 jmcneill printf("threshold: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 428 1.1 jmcneill OMAPFB_DISPC_GFX_FIFO_THRESH)); 429 1.1 jmcneill printf("GFX size: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 430 1.1 jmcneill OMAPFB_DISPC_GFX_SIZE)); 431 1.1 jmcneill printf("row inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 432 1.1 jmcneill OMAPFB_DISPC_GFX_ROW_INC)); 433 1.1 jmcneill printf("pixel inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh, 434 1.1 jmcneill OMAPFB_DISPC_GFX_PIXEL_INC)); 435 1.1 jmcneill #endif 436 1.1 jmcneill 437 1.1 jmcneill sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 438 1.1 jmcneill "default", 439 1.1 jmcneill 0, 0, 440 1.1 jmcneill NULL, 441 1.1 jmcneill 8, 16, 442 1.1 jmcneill WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 443 1.1 jmcneill NULL 444 1.1 jmcneill }; 445 1.1 jmcneill sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 446 1.1 jmcneill sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 447 1.1 jmcneill sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 448 1.1 jmcneill sc->sc_locked = 0; 449 1.1 jmcneill 450 1.1 jmcneill vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr, 451 1.1 jmcneill &omapfb_accessops); 452 1.1 jmcneill sc->vd.init_screen = omapfb_init_screen; 453 1.1 jmcneill 454 1.1 jmcneill /* init engine here */ 455 1.1 jmcneill #if NOMAPDMA > 0 456 1.1 jmcneill omapfb_init(sc); 457 1.1 jmcneill #endif 458 1.1 jmcneill 459 1.1 jmcneill ri = &sc->sc_console_screen.scr_ri; 460 1.1 jmcneill vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr); 461 1.1 jmcneill sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 462 1.1 jmcneill #if NOMAPDMA > 0 463 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 464 1.1 jmcneill ri->ri_devcmap[(defattr >> 16) & 0xff]); 465 1.1 jmcneill #endif 466 1.1 jmcneill sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 467 1.1 jmcneill sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 468 1.1 jmcneill sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 469 1.1 jmcneill sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 470 1.1 jmcneill 471 1.1 jmcneill if (is_console) 472 1.1 jmcneill wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 473 1.1 jmcneill defattr); 474 1.1 jmcneill 475 1.1 jmcneill vcons_replay_msgbuf(&sc->sc_console_screen); 476 1.1 jmcneill 477 1.1 jmcneill aa.console = is_console; 478 1.1 jmcneill aa.scrdata = &sc->sc_screenlist; 479 1.1 jmcneill aa.accessops = &omapfb_accessops; 480 1.1 jmcneill aa.accesscookie = &sc->vd; 481 1.1 jmcneill 482 1.5 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 483 1.1 jmcneill #ifdef OMAPFB_DEBUG 484 1.1 jmcneill #if NOMAPDMA > 0 485 1.1 jmcneill omapfb_rectfill(sc, 100, 100, 100, 100, 0xe000); 486 1.1 jmcneill omapfb_rectfill(sc, 100, 200, 100, 100, 0x01f8); 487 1.1 jmcneill omapfb_rectfill(sc, 200, 100, 100, 100, 0x01f8); 488 1.1 jmcneill omapfb_rectfill(sc, 200, 200, 100, 100, 0xe000); 489 1.1 jmcneill omapfb_bitblt(sc, 100, 100, 400, 100, 200, 200, 0); 490 1.1 jmcneill /* let's see if we can draw something */ 491 1.1 jmcneill printf("OMAPDMAC_CDAC: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CDAC)); 492 1.1 jmcneill printf("OMAPDMAC_CSR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CSR)); 493 1.1 jmcneill printf("OMAPDMAC_CCR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CCR)); 494 1.1 jmcneill #endif 495 1.1 jmcneill #endif 496 1.1 jmcneill } 497 1.1 jmcneill 498 1.1 jmcneill static int 499 1.1 jmcneill omapfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 500 1.1 jmcneill struct lwp *l) 501 1.1 jmcneill { 502 1.1 jmcneill struct vcons_data *vd = v; 503 1.1 jmcneill struct omapfb_softc *sc = vd->cookie; 504 1.1 jmcneill struct wsdisplay_fbinfo *wdf; 505 1.1 jmcneill struct vcons_screen *ms = vd->active; 506 1.1 jmcneill 507 1.1 jmcneill switch (cmd) { 508 1.1 jmcneill 509 1.1 jmcneill case WSDISPLAYIO_GTYPE: 510 1.1 jmcneill *(u_int *)data = WSDISPLAY_TYPE_OMAP3; 511 1.1 jmcneill return 0; 512 1.1 jmcneill 513 1.1 jmcneill case WSDISPLAYIO_GET_BUSID: 514 1.1 jmcneill { 515 1.1 jmcneill struct wsdisplayio_bus_id *busid; 516 1.1 jmcneill 517 1.1 jmcneill busid = data; 518 1.1 jmcneill busid->bus_type = WSDISPLAYIO_BUS_SOC; 519 1.1 jmcneill return 0; 520 1.1 jmcneill } 521 1.1 jmcneill 522 1.1 jmcneill case WSDISPLAYIO_GINFO: 523 1.1 jmcneill if (ms == NULL) 524 1.1 jmcneill return ENODEV; 525 1.1 jmcneill wdf = (void *)data; 526 1.1 jmcneill wdf->height = ms->scr_ri.ri_height; 527 1.1 jmcneill wdf->width = ms->scr_ri.ri_width; 528 1.1 jmcneill wdf->depth = 32; 529 1.1 jmcneill wdf->cmsize = 256; 530 1.1 jmcneill return 0; 531 1.1 jmcneill 532 1.1 jmcneill case WSDISPLAYIO_GETCMAP: 533 1.1 jmcneill return omapfb_getcmap(sc, 534 1.1 jmcneill (struct wsdisplay_cmap *)data); 535 1.1 jmcneill 536 1.1 jmcneill case WSDISPLAYIO_PUTCMAP: 537 1.1 jmcneill return omapfb_putcmap(sc, 538 1.1 jmcneill (struct wsdisplay_cmap *)data); 539 1.1 jmcneill 540 1.1 jmcneill case WSDISPLAYIO_LINEBYTES: 541 1.1 jmcneill *(u_int *)data = sc->sc_width * 4; 542 1.1 jmcneill return 0; 543 1.1 jmcneill 544 1.1 jmcneill case WSDISPLAYIO_SMODE: 545 1.1 jmcneill { 546 1.1 jmcneill int new_mode = *(int*)data; 547 1.1 jmcneill 548 1.1 jmcneill if (new_mode != sc->sc_mode) { 549 1.1 jmcneill sc->sc_mode = new_mode; 550 1.1 jmcneill if (new_mode == WSDISPLAYIO_MODE_EMUL) { 551 1.1 jmcneill omapfb_set_depth(sc, 16); 552 1.1 jmcneill vcons_redraw_screen(ms); 553 1.1 jmcneill } else { 554 1.1 jmcneill omapfb_set_depth(sc, 32); 555 1.1 jmcneill } 556 1.1 jmcneill } 557 1.1 jmcneill } 558 1.1 jmcneill return 0; 559 1.1 jmcneill 560 1.1 jmcneill case WSDISPLAYIO_GET_FBINFO: 561 1.1 jmcneill { 562 1.1 jmcneill struct wsdisplayio_fbinfo *fbi = data; 563 1.1 jmcneill 564 1.1 jmcneill fbi->fbi_width = sc->sc_width; 565 1.1 jmcneill fbi->fbi_height = sc->sc_height; 566 1.1 jmcneill fbi->fbi_stride = sc->sc_width << 2; 567 1.1 jmcneill fbi->fbi_bitsperpixel = 32; 568 1.1 jmcneill fbi->fbi_pixeltype = WSFB_RGB; 569 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16; 570 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 571 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 572 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 573 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0; 574 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 575 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 576 1.1 jmcneill fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 577 1.1 jmcneill fbi->fbi_flags = 0; 578 1.1 jmcneill fbi->fbi_fbsize = sc->sc_vramsize; 579 1.1 jmcneill fbi->fbi_fboffset = 0; 580 1.1 jmcneill fbi->fbi_flags = WSFB_VRAM_IS_RAM; 581 1.1 jmcneill 582 1.1 jmcneill } 583 1.1 jmcneill return 0; 584 1.1 jmcneill 585 1.1 jmcneill case WSDISPLAYIO_GVIDEO: 586 1.1 jmcneill { 587 1.1 jmcneill int *on = data; 588 1.1 jmcneill *on = sc->sc_video_is_on; 589 1.1 jmcneill } 590 1.1 jmcneill return 0; 591 1.1 jmcneill 592 1.1 jmcneill case WSDISPLAYIO_SVIDEO: 593 1.1 jmcneill { 594 1.1 jmcneill int *on = data; 595 1.1 jmcneill omapfb_set_video(sc, *on); 596 1.1 jmcneill } 597 1.1 jmcneill return 0; 598 1.1 jmcneill 599 1.1 jmcneill case WSDISPLAYIO_GCURPOS: 600 1.1 jmcneill { 601 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data; 602 1.1 jmcneill 603 1.1 jmcneill cp->x = sc->sc_cursor_x; 604 1.1 jmcneill cp->y = sc->sc_cursor_y; 605 1.1 jmcneill } 606 1.1 jmcneill return 0; 607 1.1 jmcneill case WSDISPLAYIO_SCURPOS: 608 1.1 jmcneill { 609 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data; 610 1.1 jmcneill 611 1.1 jmcneill omapfb_move_cursor(sc, cp->x, cp->y); 612 1.1 jmcneill } 613 1.1 jmcneill return 0; 614 1.1 jmcneill case WSDISPLAYIO_GCURMAX: 615 1.1 jmcneill { 616 1.1 jmcneill struct wsdisplay_curpos *cp = (void *)data; 617 1.1 jmcneill 618 1.1 jmcneill cp->x = 64; 619 1.1 jmcneill cp->y = 64; 620 1.1 jmcneill } 621 1.1 jmcneill return 0; 622 1.1 jmcneill case WSDISPLAYIO_SCURSOR: 623 1.1 jmcneill { 624 1.1 jmcneill struct wsdisplay_cursor *cursor = (void *)data; 625 1.1 jmcneill 626 1.1 jmcneill return omapfb_do_cursor(sc, cursor); 627 1.1 jmcneill } 628 1.1 jmcneill } 629 1.1 jmcneill return EPASSTHROUGH; 630 1.1 jmcneill } 631 1.1 jmcneill 632 1.1 jmcneill static paddr_t 633 1.1 jmcneill omapfb_mmap(void *v, void *vs, off_t offset, int prot) 634 1.1 jmcneill { 635 1.1 jmcneill paddr_t pa = -1; 636 1.1 jmcneill struct vcons_data *vd = v; 637 1.1 jmcneill struct omapfb_softc *sc = vd->cookie; 638 1.1 jmcneill 639 1.1 jmcneill /* 'regular' framebuffer mmap()ing */ 640 1.1 jmcneill if (offset < sc->sc_vramsize) { 641 1.1 jmcneill pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1, 642 1.1 jmcneill offset + PAGE_SIZE, prot, BUS_DMA_PREFETCHABLE); 643 1.1 jmcneill return pa; 644 1.1 jmcneill } 645 1.1 jmcneill return pa; 646 1.1 jmcneill } 647 1.1 jmcneill 648 1.1 jmcneill static void 649 1.1 jmcneill omapfb_init_screen(void *cookie, struct vcons_screen *scr, 650 1.1 jmcneill int existing, long *defattr) 651 1.1 jmcneill { 652 1.1 jmcneill struct omapfb_softc *sc = cookie; 653 1.1 jmcneill struct rasops_info *ri = &scr->scr_ri; 654 1.1 jmcneill 655 1.1 jmcneill ri->ri_depth = sc->sc_depth; 656 1.1 jmcneill ri->ri_width = sc->sc_width; 657 1.1 jmcneill ri->ri_height = sc->sc_height; 658 1.1 jmcneill ri->ri_stride = sc->sc_stride; 659 1.1 jmcneill ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 660 1.1 jmcneill 661 1.1 jmcneill ri->ri_bits = (char *)sc->sc_fbaddr; 662 1.1 jmcneill 663 1.1 jmcneill #if NOMAPDMA < 1 664 1.1 jmcneill scr->scr_flags |= VCONS_DONT_READ; 665 1.1 jmcneill #endif 666 1.1 jmcneill 667 1.1 jmcneill if (existing) { 668 1.1 jmcneill ri->ri_flg |= RI_CLEAR; 669 1.1 jmcneill } 670 1.1 jmcneill 671 1.1 jmcneill rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8); 672 1.1 jmcneill ri->ri_caps = WSSCREEN_WSCOLORS; 673 1.1 jmcneill 674 1.1 jmcneill rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 675 1.1 jmcneill sc->sc_width / ri->ri_font->fontwidth); 676 1.1 jmcneill 677 1.1 jmcneill ri->ri_hw = scr; 678 1.1 jmcneill 679 1.1 jmcneill #if NOMAPDMA > 0 680 1.1 jmcneill ri->ri_ops.copyrows = omapfb_copyrows; 681 1.1 jmcneill ri->ri_ops.copycols = omapfb_copycols; 682 1.1 jmcneill ri->ri_ops.eraserows = omapfb_eraserows; 683 1.1 jmcneill ri->ri_ops.erasecols = omapfb_erasecols; 684 1.1 jmcneill ri->ri_ops.cursor = omapfb_cursor; 685 1.1 jmcneill sc->sc_putchar = ri->ri_ops.putchar; 686 1.1 jmcneill ri->ri_ops.putchar = omapfb_putchar; 687 1.1 jmcneill #endif 688 1.1 jmcneill } 689 1.1 jmcneill 690 1.1 jmcneill static int 691 1.1 jmcneill omapfb_putcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm) 692 1.1 jmcneill { 693 1.1 jmcneill u_char *r, *g, *b; 694 1.1 jmcneill u_int index = cm->index; 695 1.1 jmcneill u_int count = cm->count; 696 1.1 jmcneill int i, error; 697 1.1 jmcneill u_char rbuf[256], gbuf[256], bbuf[256]; 698 1.1 jmcneill 699 1.1 jmcneill if (cm->index >= 256 || cm->count > 256 || 700 1.1 jmcneill (cm->index + cm->count) > 256) 701 1.1 jmcneill return EINVAL; 702 1.1 jmcneill error = copyin(cm->red, &rbuf[index], count); 703 1.1 jmcneill if (error) 704 1.1 jmcneill return error; 705 1.1 jmcneill error = copyin(cm->green, &gbuf[index], count); 706 1.1 jmcneill if (error) 707 1.1 jmcneill return error; 708 1.1 jmcneill error = copyin(cm->blue, &bbuf[index], count); 709 1.1 jmcneill if (error) 710 1.1 jmcneill return error; 711 1.1 jmcneill 712 1.1 jmcneill memcpy(&sc->sc_cmap_red[index], &rbuf[index], count); 713 1.1 jmcneill memcpy(&sc->sc_cmap_green[index], &gbuf[index], count); 714 1.1 jmcneill memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count); 715 1.1 jmcneill 716 1.1 jmcneill r = &sc->sc_cmap_red[index]; 717 1.1 jmcneill g = &sc->sc_cmap_green[index]; 718 1.1 jmcneill b = &sc->sc_cmap_blue[index]; 719 1.1 jmcneill 720 1.1 jmcneill for (i = 0; i < count; i++) { 721 1.1 jmcneill omapfb_putpalreg(sc, index, *r, *g, *b); 722 1.1 jmcneill index++; 723 1.1 jmcneill r++, g++, b++; 724 1.1 jmcneill } 725 1.1 jmcneill return 0; 726 1.1 jmcneill } 727 1.1 jmcneill 728 1.1 jmcneill static int 729 1.1 jmcneill omapfb_getcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm) 730 1.1 jmcneill { 731 1.1 jmcneill u_int index = cm->index; 732 1.1 jmcneill u_int count = cm->count; 733 1.1 jmcneill int error; 734 1.1 jmcneill 735 1.1 jmcneill if (index >= 255 || count > 256 || index + count > 256) 736 1.1 jmcneill return EINVAL; 737 1.1 jmcneill 738 1.1 jmcneill error = copyout(&sc->sc_cmap_red[index], cm->red, count); 739 1.1 jmcneill if (error) 740 1.1 jmcneill return error; 741 1.1 jmcneill error = copyout(&sc->sc_cmap_green[index], cm->green, count); 742 1.1 jmcneill if (error) 743 1.1 jmcneill return error; 744 1.1 jmcneill error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 745 1.1 jmcneill if (error) 746 1.1 jmcneill return error; 747 1.1 jmcneill 748 1.1 jmcneill return 0; 749 1.1 jmcneill } 750 1.1 jmcneill 751 1.1 jmcneill static void 752 1.1 jmcneill omapfb_restore_palette(struct omapfb_softc *sc) 753 1.1 jmcneill { 754 1.1 jmcneill int i; 755 1.1 jmcneill 756 1.1 jmcneill for (i = 0; i < 256; i++) { 757 1.1 jmcneill omapfb_putpalreg(sc, i, sc->sc_cmap_red[i], 758 1.1 jmcneill sc->sc_cmap_green[i], sc->sc_cmap_blue[i]); 759 1.1 jmcneill } 760 1.1 jmcneill } 761 1.1 jmcneill 762 1.1 jmcneill static void 763 1.1 jmcneill omapfb_putpalreg(struct omapfb_softc *sc, int idx, uint8_t r, uint8_t g, 764 1.1 jmcneill uint8_t b) 765 1.1 jmcneill { 766 1.1 jmcneill uint32_t reg; 767 1.1 jmcneill 768 1.1 jmcneill if ((idx < 0) || (idx > 255)) 769 1.1 jmcneill return; 770 1.1 jmcneill /* whack the DAC */ 771 1.1 jmcneill reg = (r << 16) | (g << 8) | b; 772 1.1 jmcneill sc->sc_clut[idx] = reg; 773 1.1 jmcneill } 774 1.1 jmcneill 775 1.1 jmcneill static int 776 1.1 jmcneill omapfb_set_depth(struct omapfb_softc *sc, int d) 777 1.1 jmcneill { 778 1.1 jmcneill uint32_t reg; 779 1.1 jmcneill 780 1.1 jmcneill reg = OMAP_VID_ATTR_ENABLE | 781 1.1 jmcneill OMAP_VID_ATTR_BURST_16x32 | 782 1.1 jmcneill OMAP_VID_ATTR_REPLICATION; 783 1.1 jmcneill switch (d) { 784 1.1 jmcneill case 16: 785 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB16; 786 1.1 jmcneill break; 787 1.1 jmcneill case 32: 788 1.1 jmcneill reg |= OMAP_VID_ATTR_RGB24; 789 1.1 jmcneill break; 790 1.1 jmcneill default: 791 1.1 jmcneill aprint_error_dev(sc->sc_dev, 792 1.1 jmcneill "unsupported depth (%d)\n", d); 793 1.1 jmcneill return EINVAL; 794 1.1 jmcneill } 795 1.1 jmcneill 796 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 797 1.1 jmcneill OMAPFB_DISPC_VID1_ATTRIBUTES, reg); 798 1.1 jmcneill 799 1.1 jmcneill /* 800 1.1 jmcneill * now tell the video controller that we're done mucking around and 801 1.1 jmcneill * actually update its settings 802 1.1 jmcneill */ 803 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 804 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 805 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 806 1.1 jmcneill 807 1.1 jmcneill sc->sc_depth = d; 808 1.1 jmcneill sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3); 809 1.1 jmcneill 810 1.1 jmcneill /* clear the screen here */ 811 1.1 jmcneill #if NOMAPDMA > 0 812 1.1 jmcneill omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 0); 813 1.1 jmcneill #else 814 1.1 jmcneill memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_height); 815 1.1 jmcneill #endif 816 1.1 jmcneill return 0; 817 1.1 jmcneill } 818 1.1 jmcneill 819 1.1 jmcneill static void 820 1.1 jmcneill omapfb_set_video(struct omapfb_softc *sc, int on) 821 1.1 jmcneill { 822 1.1 jmcneill uint32_t reg; 823 1.1 jmcneill 824 1.1 jmcneill if (on == sc->sc_video_is_on) 825 1.1 jmcneill return; 826 1.1 jmcneill if (on) { 827 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 828 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config); 829 1.1 jmcneill on = 1; 830 1.1 jmcneill } else { 831 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 832 1.1 jmcneill OMAPFB_DISPC_CONFIG, sc->sc_dispc_config | 833 1.1 jmcneill OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED | 834 1.1 jmcneill OMAP_DISPC_CFG_PIXELCLK_GATED | 835 1.1 jmcneill OMAP_DISPC_CFG_PIXELDATA_GATED); 836 1.1 jmcneill } 837 1.1 jmcneill 838 1.1 jmcneill /* 839 1.1 jmcneill * now tell the video controller that we're done mucking around and 840 1.1 jmcneill * actually update its settings 841 1.1 jmcneill */ 842 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 843 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 844 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 845 1.1 jmcneill 846 1.1 jmcneill aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__, 847 1.1 jmcneill bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG)); 848 1.1 jmcneill sc->sc_video_is_on = on; 849 1.1 jmcneill } 850 1.1 jmcneill 851 1.1 jmcneill #if NOMAPDMA > 0 852 1.1 jmcneill static void 853 1.1 jmcneill omapfb_init(struct omapfb_softc *sc) 854 1.1 jmcneill { 855 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CLNK_CTRL, 0); 856 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CICRI, 0); 857 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI, 858 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 | 859 1.1 jmcneill CSDPI_WRITE_POSTED | CSDPI_DATA_TYPE_16); 860 1.1 jmcneill } 861 1.1 jmcneill 862 1.1 jmcneill static void 863 1.1 jmcneill omapfb_wait_idle(struct omapfb_softc *sc) 864 1.1 jmcneill { 865 1.1 jmcneill while ((omapdma_read_ch_reg(0, OMAPDMAC_CCR) & CCR_WR_ACTIVE) != 0); 866 1.1 jmcneill } 867 1.1 jmcneill 868 1.1 jmcneill static void 869 1.1 jmcneill omapfb_rectfill(struct omapfb_softc *sc, int x, int y, int wi, int he, 870 1.1 jmcneill uint32_t colour) 871 1.1 jmcneill { 872 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */ 873 1.1 jmcneill int width_in_bytes = wi * bpp; 874 1.1 jmcneill uint32_t daddr; 875 1.1 jmcneill 876 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * y + x * bpp; 877 1.1 jmcneill omapfb_wait_idle(sc); 878 1.1 jmcneill 879 1.1 jmcneill /* 880 1.1 jmcneill * stupid hardware 881 1.1 jmcneill * in 32bit mode the DMA controller always writes 0 into the upper 882 1.1 jmcneill * byte, so we can use this mode only if we actually want that 883 1.1 jmcneill */ 884 1.1 jmcneill if (((colour & 0xff00) == 0) && 885 1.1 jmcneill (((daddr | width_in_bytes) & 3) == 0)) { 886 1.1 jmcneill /* 887 1.1 jmcneill * everything is properly aligned so we can copy stuff in 888 1.1 jmcneill * 32bit chunks instead of pixel by pixel 889 1.1 jmcneill */ 890 1.1 jmcneill wi = wi >> 1; 891 1.1 jmcneill 892 1.1 jmcneill /* just in case */ 893 1.1 jmcneill colour |= colour << 16; 894 1.1 jmcneill 895 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI, 896 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 | 897 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST | 898 1.1 jmcneill CSDPI_DATA_TYPE_32); 899 1.1 jmcneill } else { 900 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI, 901 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 | 902 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST | 903 1.1 jmcneill CSDPI_DATA_TYPE_16); 904 1.1 jmcneill } 905 1.1 jmcneill 906 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi); 907 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he); 908 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr); 909 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR, 910 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX | 911 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR); 912 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, 1); 913 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI, 914 1.1 jmcneill (sc->sc_stride - width_in_bytes) + 1); 915 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_COLOR, colour); 916 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR, 917 1.1 jmcneill CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX | 918 1.1 jmcneill CCR_SRC_AMODE_CONST_ADDR | CCR_ENABLE); 919 1.1 jmcneill } 920 1.1 jmcneill 921 1.1 jmcneill static void 922 1.1 jmcneill omapfb_bitblt(struct omapfb_softc *sc, int xs, int ys, int xd, int yd, 923 1.1 jmcneill int wi, int he, int rop) 924 1.1 jmcneill { 925 1.1 jmcneill int bpp = sc->sc_depth >> 3; /* bytes per pixel */ 926 1.1 jmcneill int width_in_bytes = wi * bpp; 927 1.1 jmcneill 928 1.1 jmcneill int hstep, vstep; 929 1.1 jmcneill uint32_t saddr, daddr; 930 1.1 jmcneill 931 1.1 jmcneill saddr = sc->sc_fbhwaddr + sc->sc_stride * ys + xs * bpp; 932 1.1 jmcneill daddr = sc->sc_fbhwaddr + sc->sc_stride * yd + xd * bpp; 933 1.1 jmcneill 934 1.1 jmcneill if (ys < yd) { 935 1.1 jmcneill /* need to go vertically backwards */ 936 1.1 jmcneill vstep = 1 - (sc->sc_stride + width_in_bytes); 937 1.1 jmcneill saddr += sc->sc_stride * (he - 1); 938 1.1 jmcneill daddr += sc->sc_stride * (he - 1); 939 1.1 jmcneill } else 940 1.1 jmcneill vstep = (sc->sc_stride - width_in_bytes) + 1; 941 1.1 jmcneill if ((xs < xd) && (ys == yd)) { 942 1.1 jmcneill /* 943 1.1 jmcneill * need to go horizontally backwards, only needed if source 944 1.1 jmcneill * and destination pixels are on the same line 945 1.1 jmcneill */ 946 1.1 jmcneill hstep = 1 - (sc->sc_depth >> 2); 947 1.1 jmcneill vstep = sc->sc_stride + bpp * (wi - 1) + 1; 948 1.1 jmcneill saddr += bpp * (wi - 1); 949 1.1 jmcneill daddr += bpp * (wi - 1); 950 1.1 jmcneill } else 951 1.1 jmcneill hstep = 1; 952 1.1 jmcneill 953 1.1 jmcneill omapfb_wait_idle(sc); 954 1.1 jmcneill if (((saddr | daddr | width_in_bytes) & 3) == 0) { 955 1.1 jmcneill /* 956 1.1 jmcneill * everything is properly aligned so we can copy stuff in 957 1.1 jmcneill * 32bit chunks instead of pixel by pixel 958 1.1 jmcneill */ 959 1.1 jmcneill wi = wi >> 1; 960 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI, 961 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 | 962 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST | 963 1.1 jmcneill CSDPI_DATA_TYPE_32); 964 1.1 jmcneill } else { 965 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSDPI, 966 1.1 jmcneill CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 | 967 1.1 jmcneill CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST | 968 1.1 jmcneill CSDPI_DATA_TYPE_16); 969 1.1 jmcneill } 970 1.1 jmcneill 971 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi); 972 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CFN, he); 973 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSSA, saddr); 974 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr); 975 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR, 976 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX | 977 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX); 978 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSEI, hstep); 979 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CSFI, vstep); 980 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDEI, hstep); 981 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CDFI, vstep); 982 1.1 jmcneill omapdma_write_ch_reg(0, OMAPDMAC_CCR, 983 1.1 jmcneill CCR_DST_AMODE_DOUBLE_INDEX | 984 1.1 jmcneill CCR_SRC_AMODE_DOUBLE_INDEX | CCR_ENABLE); 985 1.1 jmcneill } 986 1.1 jmcneill 987 1.1 jmcneill static void 988 1.1 jmcneill omapfb_cursor(void *cookie, int on, int row, int col) 989 1.1 jmcneill { 990 1.1 jmcneill struct rasops_info *ri = cookie; 991 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 992 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 993 1.1 jmcneill int pos; 994 1.1 jmcneill 995 1.1 jmcneill pos = col + row * ri->ri_cols; 996 1.6 riastrad pos += vcons_offset_to_zero(scr); 997 1.1 jmcneill if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 998 1.1 jmcneill if (ri->ri_flg & RI_CURSOR) { 999 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos], 1000 1.1 jmcneill scr->scr_attrs[pos]); 1001 1.1 jmcneill ri->ri_flg &= ~RI_CURSOR; 1002 1.1 jmcneill } 1003 1.1 jmcneill ri->ri_crow = row; 1004 1.1 jmcneill ri->ri_ccol = col; 1005 1.1 jmcneill if (on) { 1006 1.1 jmcneill omapfb_putchar(cookie, row, col, scr->scr_chars[pos], 1007 1.1 jmcneill scr->scr_attrs[pos] ^ 0x0f0f0000); 1008 1.1 jmcneill ri->ri_flg |= RI_CURSOR; 1009 1.1 jmcneill } 1010 1.1 jmcneill } else { 1011 1.1 jmcneill scr->scr_ri.ri_crow = row; 1012 1.1 jmcneill scr->scr_ri.ri_ccol = col; 1013 1.1 jmcneill scr->scr_ri.ri_flg &= ~RI_CURSOR; 1014 1.1 jmcneill } 1015 1.1 jmcneill } 1016 1.1 jmcneill 1017 1.1 jmcneill static void 1018 1.1 jmcneill omapfb_putchar(void *cookie, int row, int col, u_int c, long attr) 1019 1.1 jmcneill { 1020 1.1 jmcneill struct rasops_info *ri = cookie; 1021 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 1022 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 1023 1.1 jmcneill 1024 1.1 jmcneill if (c == 0x20) { 1025 1.1 jmcneill uint32_t fg, bg, ul; 1026 1.1 jmcneill rasops_unpack_attr(attr, &fg, &bg, &ul); 1027 1.1 jmcneill omapfb_rectfill(sc, 1028 1.1 jmcneill ri->ri_xorigin + ri->ri_font->fontwidth * col, 1029 1.1 jmcneill ri->ri_yorigin + ri->ri_font->fontheight * row, 1030 1.1 jmcneill ri->ri_font->fontwidth, 1031 1.1 jmcneill ri->ri_font->fontheight, 1032 1.1 jmcneill ri->ri_devcmap[bg]); 1033 1.1 jmcneill return; 1034 1.1 jmcneill } 1035 1.1 jmcneill omapfb_wait_idle(sc); 1036 1.1 jmcneill sc->sc_putchar(cookie, row, col, c, attr); 1037 1.1 jmcneill } 1038 1.1 jmcneill 1039 1.1 jmcneill static void 1040 1.1 jmcneill omapfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1041 1.1 jmcneill { 1042 1.1 jmcneill struct rasops_info *ri = cookie; 1043 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 1044 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 1045 1.1 jmcneill int32_t xs, xd, y, width, height; 1046 1.1 jmcneill 1047 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1048 1.1 jmcneill xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1049 1.1 jmcneill xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1050 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1051 1.1 jmcneill width = ri->ri_font->fontwidth * ncols; 1052 1.1 jmcneill height = ri->ri_font->fontheight; 1053 1.1 jmcneill omapfb_bitblt(sc, xs, y, xd, y, width, height, 12); 1054 1.1 jmcneill } 1055 1.1 jmcneill } 1056 1.1 jmcneill 1057 1.1 jmcneill static void 1058 1.1 jmcneill omapfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1059 1.1 jmcneill { 1060 1.1 jmcneill struct rasops_info *ri = cookie; 1061 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 1062 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 1063 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul; 1064 1.1 jmcneill 1065 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1066 1.1 jmcneill x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1067 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1068 1.1 jmcneill width = ri->ri_font->fontwidth * ncols; 1069 1.1 jmcneill height = ri->ri_font->fontheight; 1070 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1071 1.1 jmcneill 1072 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1073 1.1 jmcneill } 1074 1.1 jmcneill } 1075 1.1 jmcneill 1076 1.1 jmcneill static void 1077 1.1 jmcneill omapfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1078 1.1 jmcneill { 1079 1.1 jmcneill struct rasops_info *ri = cookie; 1080 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 1081 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 1082 1.1 jmcneill int32_t x, ys, yd, width, height; 1083 1.1 jmcneill 1084 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1085 1.1 jmcneill x = ri->ri_xorigin; 1086 1.1 jmcneill ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1087 1.1 jmcneill yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1088 1.1 jmcneill width = ri->ri_emuwidth; 1089 1.1 jmcneill height = ri->ri_font->fontheight * nrows; 1090 1.1 jmcneill omapfb_bitblt(sc, x, ys, x, yd, width, height, 12); 1091 1.1 jmcneill } 1092 1.1 jmcneill } 1093 1.1 jmcneill 1094 1.1 jmcneill static void 1095 1.1 jmcneill omapfb_eraserows(void *cookie, int row, int nrows, long fillattr) 1096 1.1 jmcneill { 1097 1.1 jmcneill struct rasops_info *ri = cookie; 1098 1.1 jmcneill struct vcons_screen *scr = ri->ri_hw; 1099 1.1 jmcneill struct omapfb_softc *sc = scr->scr_cookie; 1100 1.1 jmcneill int32_t x, y, width, height, fg, bg, ul; 1101 1.1 jmcneill 1102 1.1 jmcneill if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1103 1.1 jmcneill x = ri->ri_xorigin; 1104 1.1 jmcneill y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1105 1.1 jmcneill width = ri->ri_emuwidth; 1106 1.1 jmcneill height = ri->ri_font->fontheight * nrows; 1107 1.1 jmcneill rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1108 1.1 jmcneill 1109 1.1 jmcneill omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1110 1.1 jmcneill } 1111 1.1 jmcneill } 1112 1.1 jmcneill #endif /* NOMAPDMA > 0 */ 1113 1.1 jmcneill 1114 1.1 jmcneill static void 1115 1.1 jmcneill omapfb_move_cursor(struct omapfb_softc *sc, int x, int y) 1116 1.1 jmcneill { 1117 1.1 jmcneill uint32_t pos, reg, addr; 1118 1.1 jmcneill int xx, yy, wi = 64, he = 64; 1119 1.1 jmcneill 1120 1.1 jmcneill /* 1121 1.1 jmcneill * we need to special case anything and everything where the cursor 1122 1.1 jmcneill * may be partially off screen 1123 1.1 jmcneill */ 1124 1.1 jmcneill 1125 1.1 jmcneill addr = sc->sc_fbhwaddr + sc->sc_cursor_offset; 1126 1.1 jmcneill xx = x - sc->sc_hot_x; 1127 1.1 jmcneill yy = y - sc->sc_hot_y; 1128 1.1 jmcneill 1129 1.1 jmcneill /* 1130 1.1 jmcneill * if we're off to the top or left we need to shif the start address 1131 1.1 jmcneill * and shrink the gfx layer size 1132 1.1 jmcneill */ 1133 1.1 jmcneill if (xx < 0) { 1134 1.1 jmcneill wi += xx; 1135 1.1 jmcneill addr -= xx * 4; 1136 1.1 jmcneill xx = 0; 1137 1.1 jmcneill } 1138 1.1 jmcneill if (yy < 0) { 1139 1.1 jmcneill he += yy; 1140 1.1 jmcneill addr -= yy * 64 * 4; 1141 1.1 jmcneill yy = 0; 1142 1.1 jmcneill } 1143 1.1 jmcneill if (xx > (sc->sc_width - 64)) { 1144 1.1 jmcneill wi -= (xx + 64 - sc->sc_width); 1145 1.1 jmcneill } 1146 1.1 jmcneill if (yy > (sc->sc_height - 64)) { 1147 1.1 jmcneill he -= (yy + 64 - sc->sc_height); 1148 1.1 jmcneill } 1149 1.1 jmcneill pos = (yy << 16) | xx; 1150 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0, 1151 1.1 jmcneill addr); 1152 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION, 1153 1.1 jmcneill pos); 1154 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE, 1155 1.1 jmcneill ((he - 1) << 16) | (wi - 1)); 1156 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ROW_INC, 1157 1.1 jmcneill (64 - wi) * 4 + 1); 1158 1.1 jmcneill /* 1159 1.1 jmcneill * now tell the video controller that we're done mucking around and 1160 1.1 jmcneill * actually update its settings 1161 1.1 jmcneill */ 1162 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL); 1163 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 1164 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 1165 1.1 jmcneill } 1166 1.1 jmcneill 1167 1.1 jmcneill static int 1168 1.1 jmcneill omapfb_do_cursor(struct omapfb_softc * sc, 1169 1.1 jmcneill struct wsdisplay_cursor *cur) 1170 1.1 jmcneill { 1171 1.1 jmcneill int whack = 0; 1172 1.1 jmcneill int shape = 0; 1173 1.1 jmcneill 1174 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1175 1.1 jmcneill uint32_t attr = OMAP_DISPC_ATTR_BURST_16x32 | 1176 1.1 jmcneill OMAP_DISPC_ATTR_ARGB32 | 1177 1.1 jmcneill OMAP_DISPC_ATTR_REPLICATION; 1178 1.1 jmcneill 1179 1.1 jmcneill if (cur->enable) attr |= OMAP_DISPC_ATTR_ENABLE; 1180 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, 1181 1.1 jmcneill OMAPFB_DISPC_GFX_ATTRIBUTES, attr); 1182 1.1 jmcneill whack = 1; 1183 1.1 jmcneill } 1184 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1185 1.1 jmcneill 1186 1.1 jmcneill sc->sc_hot_x = cur->hot.x; 1187 1.1 jmcneill sc->sc_hot_y = cur->hot.y; 1188 1.1 jmcneill cur->which |= WSDISPLAY_CURSOR_DOPOS; 1189 1.1 jmcneill } 1190 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1191 1.1 jmcneill 1192 1.1 jmcneill omapfb_move_cursor(sc, cur->pos.x, cur->pos.y); 1193 1.1 jmcneill } 1194 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1195 1.1 jmcneill int i; 1196 1.1 jmcneill uint32_t val; 1197 1.1 jmcneill 1198 1.1 jmcneill for (i = 0; i < uimin(cur->cmap.count, 3); i++) { 1199 1.1 jmcneill val = (cur->cmap.red[i] << 16 ) | 1200 1.1 jmcneill (cur->cmap.green[i] << 8) | 1201 1.1 jmcneill (cur->cmap.blue[i] ) | 1202 1.1 jmcneill 0xff000000; 1203 1.1 jmcneill sc->sc_cursor_cmap[i + cur->cmap.index + 2] = val; 1204 1.1 jmcneill } 1205 1.1 jmcneill shape = 1; 1206 1.1 jmcneill } 1207 1.1 jmcneill if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1208 1.1 jmcneill 1209 1.1 jmcneill copyin(cur->mask, sc->sc_cursor_mask, 64 * 8); 1210 1.1 jmcneill copyin(cur->image, sc->sc_cursor_bitmap, 64 * 8); 1211 1.1 jmcneill shape = 1; 1212 1.1 jmcneill } 1213 1.1 jmcneill if (shape) { 1214 1.1 jmcneill int i, j, idx; 1215 1.1 jmcneill uint8_t mask; 1216 1.1 jmcneill 1217 1.1 jmcneill for (i = 0; i < 64 * 8; i++) { 1218 1.1 jmcneill mask = 0x01; 1219 1.1 jmcneill for (j = 0; j < 8; j++) { 1220 1.1 jmcneill idx = ((sc->sc_cursor_mask[i] & mask) ? 2 : 0) | 1221 1.1 jmcneill ((sc->sc_cursor_bitmap[i] & mask) ? 1 : 0); 1222 1.1 jmcneill sc->sc_cursor_img[i * 8 + j] = 1223 1.1 jmcneill sc->sc_cursor_cmap[idx]; 1224 1.1 jmcneill mask = mask << 1; 1225 1.1 jmcneill } 1226 1.1 jmcneill } 1227 1.1 jmcneill } 1228 1.1 jmcneill if (whack) { 1229 1.1 jmcneill uint32_t reg; 1230 1.1 jmcneill 1231 1.1 jmcneill reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, 1232 1.1 jmcneill OMAPFB_DISPC_CONTROL); 1233 1.1 jmcneill bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL, 1234 1.1 jmcneill reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL); 1235 1.1 jmcneill } 1236 1.1 jmcneill return 0; 1237 1.1 jmcneill 1238 1.1 jmcneill } 1239 1.1 jmcneill 1240 1.1 jmcneill static int 1241 1.1 jmcneill omapfb_console_match(int phandle) 1242 1.1 jmcneill { 1243 1.3 thorpej return of_compatible_match(phandle, compat_data); 1244 1.1 jmcneill } 1245 1.1 jmcneill 1246 1.1 jmcneill static void 1247 1.1 jmcneill omapfb_console_consinit(struct fdt_attach_args *faa, u_int uart_freq) 1248 1.1 jmcneill { 1249 1.1 jmcneill omapfb_console_phandle = faa->faa_phandle; 1250 1.1 jmcneill } 1251 1.1 jmcneill 1252 1.1 jmcneill static const struct fdt_console omapfb_fdt_console = { 1253 1.1 jmcneill .match = omapfb_console_match, 1254 1.1 jmcneill .consinit = omapfb_console_consinit, 1255 1.1 jmcneill }; 1256 1.1 jmcneill 1257 1.1 jmcneill FDT_CONSOLE(omapfb, &omapfb_fdt_console); 1258