Home | History | Annotate | Line # | Download | only in ti
omap3_dss.c revision 1.1
      1  1.1  jmcneill /*	$NetBSD: omap3_dss.c,v 1.1 2019/10/31 17:08:54 jmcneill 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.1  jmcneill __KERNEL_RCSID(0, "$NetBSD: omap3_dss.c,v 1.1 2019/10/31 17:08:54 jmcneill 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/malloc.h>
     43  1.1  jmcneill #include <sys/lwp.h>
     44  1.1  jmcneill #include <sys/kauth.h>
     45  1.1  jmcneill #include <sys/bus.h>
     46  1.1  jmcneill 
     47  1.1  jmcneill #include <uvm/uvm_extern.h>
     48  1.1  jmcneill 
     49  1.1  jmcneill #include <dev/videomode/videomode.h>
     50  1.1  jmcneill #include <dev/videomode/edidvar.h>
     51  1.1  jmcneill 
     52  1.1  jmcneill #include <dev/fdt/fdtvar.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.1  jmcneill static const char * const compatible[] = {
    168  1.1  jmcneill 	"ti,omap3-dss",
    169  1.1  jmcneill 	NULL
    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.1  jmcneill 	return of_match_compatible(faa->faa_phandle, compatible);
    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.1  jmcneill 		memcpy(sc->sc_edid_data, prop_data_data_nocopy(edid_data),
    266  1.1  jmcneill 		    sc->sc_edid_size);
    267  1.1  jmcneill 
    268  1.1  jmcneill 		edid_parse(sc->sc_edid_data, &ei);
    269  1.1  jmcneill 		edid_print(&ei);
    270  1.1  jmcneill 	}
    271  1.1  jmcneill 
    272  1.1  jmcneill 	/* setup video DMA */
    273  1.1  jmcneill 	sc->sc_vramsize = (12 << 20) + PAGE_SIZE; /* 12MB + CLUT */
    274  1.1  jmcneill 
    275  1.1  jmcneill 	if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_vramsize, 0, 0,
    276  1.1  jmcneill 	    sc->sc_dmamem, 1, &segs, BUS_DMA_NOWAIT) != 0) {
    277  1.1  jmcneill 		panic("boo!\n");
    278  1.1  jmcneill 		aprint_error_dev(sc->sc_dev,
    279  1.1  jmcneill 		    "failed to allocate video memory\n");
    280  1.1  jmcneill 		return;
    281  1.1  jmcneill 	}
    282  1.1  jmcneill 
    283  1.1  jmcneill 	if (bus_dmamem_map(sc->sc_dmat, sc->sc_dmamem, 1, sc->sc_vramsize,
    284  1.1  jmcneill 	    &sc->sc_vramaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
    285  1.1  jmcneill 		aprint_error_dev(sc->sc_dev, "failed to map video RAM\n");
    286  1.1  jmcneill 		return;
    287  1.1  jmcneill 	}
    288  1.1  jmcneill 	sc->sc_fbaddr = (uint8_t *)sc->sc_vramaddr + PAGE_SIZE;
    289  1.1  jmcneill 	sc->sc_clut = sc->sc_vramaddr;
    290  1.1  jmcneill 
    291  1.1  jmcneill 	if (bus_dmamap_create(sc->sc_dmat, sc->sc_vramsize, 1, sc->sc_vramsize,
    292  1.1  jmcneill 	    0, BUS_DMA_NOWAIT, &sc->sc_dmamap) != 0) {
    293  1.1  jmcneill 		aprint_error_dev(sc->sc_dev, "failed to create DMA map\n");
    294  1.1  jmcneill 		return;
    295  1.1  jmcneill 	}
    296  1.1  jmcneill 
    297  1.1  jmcneill 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_vramaddr,
    298  1.1  jmcneill 	    sc->sc_vramsize, NULL, BUS_DMA_NOWAIT) != 0) {
    299  1.1  jmcneill 		aprint_error_dev(sc->sc_dev, "failed to load DMA map\n");
    300  1.1  jmcneill 		return;
    301  1.1  jmcneill 	}
    302  1.1  jmcneill 
    303  1.1  jmcneill 	if (sc->sc_depth == 8) {
    304  1.1  jmcneill 		j = 0;
    305  1.1  jmcneill 		for (i = 0; i < 256; i++) {
    306  1.1  jmcneill 			sc->sc_cmap_red[i] = rasops_cmap[j];
    307  1.1  jmcneill 			sc->sc_cmap_green[i] = rasops_cmap[j + 1];
    308  1.1  jmcneill 			sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
    309  1.1  jmcneill 			j += 3;
    310  1.1  jmcneill 		}
    311  1.1  jmcneill 	} else {
    312  1.1  jmcneill 		for (i = 0; i < 256; i++) {
    313  1.1  jmcneill 			sc->sc_cmap_red[i] = i;
    314  1.1  jmcneill 			sc->sc_cmap_green[i] = i;
    315  1.1  jmcneill 			sc->sc_cmap_blue[i] = i;
    316  1.1  jmcneill 		}
    317  1.1  jmcneill 	}
    318  1.1  jmcneill 	omapfb_restore_palette(sc);
    319  1.1  jmcneill 
    320  1.1  jmcneill 	/* now that we have video memory, stick it to the video controller */
    321  1.1  jmcneill 
    322  1.1  jmcneill 	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG);
    323  1.1  jmcneill 	reg &= ~(OMAP_DISPC_SYSC_STANDBY_MASK | OMAP_DISPC_SYSC_IDLE_MASK);
    324  1.1  jmcneill 	reg |= OMAP_DISPC_SYSC_SMART_STANDBY | OMAP_DISPC_SYSC_SMART_IDLE |
    325  1.1  jmcneill 	       OMAP_DISPC_SYSC_WAKEUP_ENABLE | OMAP_SYSCONF_AUTOIDLE;
    326  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_SYSCONFIG, reg);
    327  1.1  jmcneill 
    328  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_SYSCONFIG,
    329  1.1  jmcneill 	    OMAP_SYSCONF_AUTOIDLE);
    330  1.1  jmcneill 
    331  1.1  jmcneill 	reg = OMAP_DISPC_CFG_TV_ALPHA_EN | OMAP_DISPC_CFG_LCD_ALPHA_EN;
    332  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG, reg);
    333  1.1  jmcneill 	sc->sc_dispc_config = reg;
    334  1.1  jmcneill 
    335  1.1  jmcneill 	/* we use overlay 1 for the console and X */
    336  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GLOBAL_ALPHA,
    337  1.1  jmcneill 	    0x00ff00ff);
    338  1.1  jmcneill 	sc->sc_fbhwaddr = sc->sc_dmamem->ds_addr + PAGE_SIZE;
    339  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_BASE_0,
    340  1.1  jmcneill 	    sc->sc_fbhwaddr);
    341  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    342  1.1  jmcneill 	    OMAPFB_DISPC_VID1_POSITION, 0);
    343  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_SIZE,
    344  1.1  jmcneill 	    ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
    345  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    346  1.1  jmcneill 	    OMAPFB_DISPC_VID1_PICTURE_SIZE,
    347  1.1  jmcneill 	    ((sc->sc_height - 1) << 16) | (sc->sc_width - 1));
    348  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    349  1.1  jmcneill 	    OMAPFB_DISPC_VID1_ROW_INC, 1);
    350  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    351  1.1  jmcneill 	    OMAPFB_DISPC_VID1_PIXEL_INC, 1);
    352  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    353  1.1  jmcneill 	    OMAPFB_DISPC_VID1_PRELOAD, 0x60);
    354  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_VID1_ATTRIBUTES,
    355  1.1  jmcneill 	    OMAP_VID_ATTR_ENABLE |
    356  1.1  jmcneill 	    OMAP_VID_ATTR_BURST_16x32 |
    357  1.1  jmcneill 	    OMAP_VID_ATTR_RGB16 |
    358  1.1  jmcneill 	    OMAP_VID_ATTR_REPLICATION);
    359  1.1  jmcneill 
    360  1.1  jmcneill 	/* turn off overlay 2 */
    361  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    362  1.1  jmcneill 	    OMAPFB_DISPC_VID2_ATTRIBUTES, 0);
    363  1.1  jmcneill 
    364  1.1  jmcneill 	/* initialize the gfx layer for use as hardware cursor */
    365  1.1  jmcneill 	sc->sc_cursor_cmap[0] = 0;
    366  1.1  jmcneill 	sc->sc_cursor_offset = (12 << 20) - (64 * 64 * 4);
    367  1.1  jmcneill 	sc->sc_cursor_img =
    368  1.1  jmcneill 	   (uint32_t *)((uint8_t *)sc->sc_fbaddr + sc->sc_cursor_offset);
    369  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
    370  1.1  jmcneill 	    sc->sc_fbhwaddr + sc->sc_cursor_offset);
    371  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_TABLE_BASE,
    372  1.1  jmcneill 	    sc->sc_dmamem->ds_addr);
    373  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
    374  1.1  jmcneill 	    0x003f003f);
    375  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
    376  1.1  jmcneill 	    0x00100010);
    377  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    378  1.1  jmcneill 	    OMAPFB_DISPC_GFX_PRELOAD, 0x60);
    379  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ATTRIBUTES,
    380  1.1  jmcneill 	    /*OMAP_DISPC_ATTR_ENABLE |*/
    381  1.1  jmcneill 	    OMAP_DISPC_ATTR_BURST_16x32 |
    382  1.1  jmcneill 	    OMAP_DISPC_ATTR_ARGB32 |
    383  1.1  jmcneill 	    OMAP_DISPC_ATTR_REPLICATION);
    384  1.1  jmcneill 
    385  1.1  jmcneill #if 0
    386  1.1  jmcneill 	printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    387  1.1  jmcneill 	    OMAPFB_DSS_CONTROL));
    388  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DSS_CONTROL,
    389  1.1  jmcneill 	    /*OMAP_DSSCTRL_DISPC_CLK_SWITCH |*/
    390  1.1  jmcneill 	    OMAP_DSSCTRL_CLOCK_MODE |
    391  1.1  jmcneill 	    OMAP_DSSCTRL_VENC_CLOCK_4X |
    392  1.1  jmcneill 	    OMAP_DSSCTRL_DAC_DEMEN);
    393  1.1  jmcneill #endif
    394  1.1  jmcneill 
    395  1.1  jmcneill #if 0
    396  1.1  jmcneill 	/* VENC to NTSC mode */
    397  1.1  jmcneill 	int adr = OMAPFB_VENC_F_CONTROL;
    398  1.1  jmcneill 	for (i = 0; i < __arraycount(venc_mode_ntsc); i++) {
    399  1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_regh, adr,
    400  1.1  jmcneill 		    venc_mode_ntsc[i]);
    401  1.1  jmcneill 		adr += 4;
    402  1.1  jmcneill 	}
    403  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_F_CONTROL,
    404  1.1  jmcneill 		    venc_mode_ntsc[0]);
    405  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_VENC_SYNC_CTRL,
    406  1.1  jmcneill 		    venc_mode_ntsc[2]);
    407  1.1  jmcneill 
    408  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_DEFAULT_COLOR_1,
    409  1.1  jmcneill 	    0x00ff0000);
    410  1.1  jmcneill #endif
    411  1.1  jmcneill 
    412  1.1  jmcneill 	/* now we make sure the video output is actually running */
    413  1.1  jmcneill 	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
    414  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
    415  1.1  jmcneill 	    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
    416  1.1  jmcneill 
    417  1.1  jmcneill #ifdef OMAPFB_DEBUG
    418  1.1  jmcneill 	printf("attr: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    419  1.1  jmcneill 	    OMAPFB_DISPC_GFX_ATTRIBUTES));
    420  1.1  jmcneill 	printf("preload: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    421  1.1  jmcneill 	    OMAPFB_DISPC_GFX_PRELOAD));
    422  1.1  jmcneill 	printf("config: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    423  1.1  jmcneill 	    OMAPFB_DISPC_CONFIG));
    424  1.1  jmcneill 	printf("control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    425  1.1  jmcneill 	    OMAPFB_DISPC_CONTROL));
    426  1.1  jmcneill 	printf("dss_control: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    427  1.1  jmcneill 	    OMAPFB_DSS_CONTROL));
    428  1.1  jmcneill 	printf("threshold: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    429  1.1  jmcneill 	    OMAPFB_DISPC_GFX_FIFO_THRESH));
    430  1.1  jmcneill 	printf("GFX size: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    431  1.1  jmcneill 	    OMAPFB_DISPC_GFX_SIZE));
    432  1.1  jmcneill 	printf("row inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    433  1.1  jmcneill 	    OMAPFB_DISPC_GFX_ROW_INC));
    434  1.1  jmcneill 	printf("pixel inc: %08x\n", bus_space_read_4(sc->sc_iot, sc->sc_regh,
    435  1.1  jmcneill 	    OMAPFB_DISPC_GFX_PIXEL_INC));
    436  1.1  jmcneill #endif
    437  1.1  jmcneill 
    438  1.1  jmcneill 	sc->sc_defaultscreen_descr = (struct wsscreen_descr){
    439  1.1  jmcneill 		"default",
    440  1.1  jmcneill 		0, 0,
    441  1.1  jmcneill 		NULL,
    442  1.1  jmcneill 		8, 16,
    443  1.1  jmcneill 		WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
    444  1.1  jmcneill 		NULL
    445  1.1  jmcneill 	};
    446  1.1  jmcneill 	sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
    447  1.1  jmcneill 	sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
    448  1.1  jmcneill 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
    449  1.1  jmcneill 	sc->sc_locked = 0;
    450  1.1  jmcneill 
    451  1.1  jmcneill 	vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
    452  1.1  jmcneill 	    &omapfb_accessops);
    453  1.1  jmcneill 	sc->vd.init_screen = omapfb_init_screen;
    454  1.1  jmcneill 
    455  1.1  jmcneill 	/* init engine here */
    456  1.1  jmcneill #if NOMAPDMA > 0
    457  1.1  jmcneill 	omapfb_init(sc);
    458  1.1  jmcneill #endif
    459  1.1  jmcneill 
    460  1.1  jmcneill 	ri = &sc->sc_console_screen.scr_ri;
    461  1.1  jmcneill 	vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1, &defattr);
    462  1.1  jmcneill 	sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
    463  1.1  jmcneill #if NOMAPDMA > 0
    464  1.1  jmcneill 	omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
    465  1.1  jmcneill 	    ri->ri_devcmap[(defattr >> 16) & 0xff]);
    466  1.1  jmcneill #endif
    467  1.1  jmcneill 	sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
    468  1.1  jmcneill 	sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
    469  1.1  jmcneill 	sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
    470  1.1  jmcneill 	sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
    471  1.1  jmcneill 
    472  1.1  jmcneill 	if (is_console)
    473  1.1  jmcneill 		wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
    474  1.1  jmcneill 		    defattr);
    475  1.1  jmcneill 
    476  1.1  jmcneill 	vcons_replay_msgbuf(&sc->sc_console_screen);
    477  1.1  jmcneill 
    478  1.1  jmcneill 	aa.console = is_console;
    479  1.1  jmcneill 	aa.scrdata = &sc->sc_screenlist;
    480  1.1  jmcneill 	aa.accessops = &omapfb_accessops;
    481  1.1  jmcneill 	aa.accesscookie = &sc->vd;
    482  1.1  jmcneill 
    483  1.1  jmcneill 	config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
    484  1.1  jmcneill #ifdef OMAPFB_DEBUG
    485  1.1  jmcneill #if NOMAPDMA > 0
    486  1.1  jmcneill 	omapfb_rectfill(sc, 100, 100, 100, 100, 0xe000);
    487  1.1  jmcneill 	omapfb_rectfill(sc, 100, 200, 100, 100, 0x01f8);
    488  1.1  jmcneill 	omapfb_rectfill(sc, 200, 100, 100, 100, 0x01f8);
    489  1.1  jmcneill 	omapfb_rectfill(sc, 200, 200, 100, 100, 0xe000);
    490  1.1  jmcneill 	omapfb_bitblt(sc, 100, 100, 400, 100, 200, 200, 0);
    491  1.1  jmcneill 	/* let's see if we can draw something */
    492  1.1  jmcneill 	printf("OMAPDMAC_CDAC: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CDAC));
    493  1.1  jmcneill 	printf("OMAPDMAC_CSR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CSR));
    494  1.1  jmcneill 	printf("OMAPDMAC_CCR: %08x\n", omapdma_read_ch_reg(0, OMAPDMAC_CCR));
    495  1.1  jmcneill #endif
    496  1.1  jmcneill #endif
    497  1.1  jmcneill }
    498  1.1  jmcneill 
    499  1.1  jmcneill static int
    500  1.1  jmcneill omapfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
    501  1.1  jmcneill 	struct lwp *l)
    502  1.1  jmcneill {
    503  1.1  jmcneill 	struct vcons_data *vd = v;
    504  1.1  jmcneill 	struct omapfb_softc *sc = vd->cookie;
    505  1.1  jmcneill 	struct wsdisplay_fbinfo *wdf;
    506  1.1  jmcneill 	struct vcons_screen *ms = vd->active;
    507  1.1  jmcneill 
    508  1.1  jmcneill 	switch (cmd) {
    509  1.1  jmcneill 
    510  1.1  jmcneill 		case WSDISPLAYIO_GTYPE:
    511  1.1  jmcneill 			*(u_int *)data = WSDISPLAY_TYPE_OMAP3;
    512  1.1  jmcneill 			return 0;
    513  1.1  jmcneill 
    514  1.1  jmcneill 		case WSDISPLAYIO_GET_BUSID:
    515  1.1  jmcneill 			{
    516  1.1  jmcneill 				struct wsdisplayio_bus_id *busid;
    517  1.1  jmcneill 
    518  1.1  jmcneill 				busid = data;
    519  1.1  jmcneill 				busid->bus_type = WSDISPLAYIO_BUS_SOC;
    520  1.1  jmcneill 				return 0;
    521  1.1  jmcneill 			}
    522  1.1  jmcneill 
    523  1.1  jmcneill 		case WSDISPLAYIO_GINFO:
    524  1.1  jmcneill 			if (ms == NULL)
    525  1.1  jmcneill 				return ENODEV;
    526  1.1  jmcneill 			wdf = (void *)data;
    527  1.1  jmcneill 			wdf->height = ms->scr_ri.ri_height;
    528  1.1  jmcneill 			wdf->width = ms->scr_ri.ri_width;
    529  1.1  jmcneill 			wdf->depth = 32;
    530  1.1  jmcneill 			wdf->cmsize = 256;
    531  1.1  jmcneill 			return 0;
    532  1.1  jmcneill 
    533  1.1  jmcneill 		case WSDISPLAYIO_GETCMAP:
    534  1.1  jmcneill 			return omapfb_getcmap(sc,
    535  1.1  jmcneill 			    (struct wsdisplay_cmap *)data);
    536  1.1  jmcneill 
    537  1.1  jmcneill 		case WSDISPLAYIO_PUTCMAP:
    538  1.1  jmcneill 			return omapfb_putcmap(sc,
    539  1.1  jmcneill 			    (struct wsdisplay_cmap *)data);
    540  1.1  jmcneill 
    541  1.1  jmcneill 		case WSDISPLAYIO_LINEBYTES:
    542  1.1  jmcneill 			*(u_int *)data = sc->sc_width * 4;
    543  1.1  jmcneill 			return 0;
    544  1.1  jmcneill 
    545  1.1  jmcneill 		case WSDISPLAYIO_SMODE:
    546  1.1  jmcneill 			{
    547  1.1  jmcneill 				int new_mode = *(int*)data;
    548  1.1  jmcneill 
    549  1.1  jmcneill 				if (new_mode != sc->sc_mode) {
    550  1.1  jmcneill 					sc->sc_mode = new_mode;
    551  1.1  jmcneill 					if (new_mode == WSDISPLAYIO_MODE_EMUL) {
    552  1.1  jmcneill 						omapfb_set_depth(sc, 16);
    553  1.1  jmcneill 						vcons_redraw_screen(ms);
    554  1.1  jmcneill 					} else {
    555  1.1  jmcneill 						omapfb_set_depth(sc, 32);
    556  1.1  jmcneill 					}
    557  1.1  jmcneill 				}
    558  1.1  jmcneill 			}
    559  1.1  jmcneill 			return 0;
    560  1.1  jmcneill 
    561  1.1  jmcneill 		case WSDISPLAYIO_GET_FBINFO:
    562  1.1  jmcneill 			{
    563  1.1  jmcneill 				struct wsdisplayio_fbinfo *fbi = data;
    564  1.1  jmcneill 
    565  1.1  jmcneill 				fbi->fbi_width = sc->sc_width;
    566  1.1  jmcneill 				fbi->fbi_height = sc->sc_height;
    567  1.1  jmcneill 				fbi->fbi_stride = sc->sc_width << 2;
    568  1.1  jmcneill 				fbi->fbi_bitsperpixel = 32;
    569  1.1  jmcneill 				fbi->fbi_pixeltype = WSFB_RGB;
    570  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.red_offset = 16;
    571  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.red_size = 8;
    572  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8;
    573  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.green_size = 8;
    574  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
    575  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8;
    576  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
    577  1.1  jmcneill 				fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
    578  1.1  jmcneill 				fbi->fbi_flags = 0;
    579  1.1  jmcneill 				fbi->fbi_fbsize = sc->sc_vramsize;
    580  1.1  jmcneill 				fbi->fbi_fboffset = 0;
    581  1.1  jmcneill 				fbi->fbi_flags = WSFB_VRAM_IS_RAM;
    582  1.1  jmcneill 
    583  1.1  jmcneill 			}
    584  1.1  jmcneill 			return 0;
    585  1.1  jmcneill 
    586  1.1  jmcneill 		case WSDISPLAYIO_GVIDEO:
    587  1.1  jmcneill 			{
    588  1.1  jmcneill 				int *on = data;
    589  1.1  jmcneill 				*on = sc->sc_video_is_on;
    590  1.1  jmcneill 			}
    591  1.1  jmcneill 			return 0;
    592  1.1  jmcneill 
    593  1.1  jmcneill 		case WSDISPLAYIO_SVIDEO:
    594  1.1  jmcneill 			{
    595  1.1  jmcneill 				int *on = data;
    596  1.1  jmcneill 				omapfb_set_video(sc, *on);
    597  1.1  jmcneill 			}
    598  1.1  jmcneill 			return 0;
    599  1.1  jmcneill 
    600  1.1  jmcneill 		case WSDISPLAYIO_GCURPOS:
    601  1.1  jmcneill 			{
    602  1.1  jmcneill 				struct wsdisplay_curpos *cp = (void *)data;
    603  1.1  jmcneill 
    604  1.1  jmcneill 				cp->x = sc->sc_cursor_x;
    605  1.1  jmcneill 				cp->y = sc->sc_cursor_y;
    606  1.1  jmcneill 			}
    607  1.1  jmcneill 			return 0;
    608  1.1  jmcneill 		case WSDISPLAYIO_SCURPOS:
    609  1.1  jmcneill 			{
    610  1.1  jmcneill 				struct wsdisplay_curpos *cp = (void *)data;
    611  1.1  jmcneill 
    612  1.1  jmcneill 				omapfb_move_cursor(sc, cp->x, cp->y);
    613  1.1  jmcneill 			}
    614  1.1  jmcneill 			return 0;
    615  1.1  jmcneill 		case WSDISPLAYIO_GCURMAX:
    616  1.1  jmcneill 			{
    617  1.1  jmcneill 				struct wsdisplay_curpos *cp = (void *)data;
    618  1.1  jmcneill 
    619  1.1  jmcneill 				cp->x = 64;
    620  1.1  jmcneill 				cp->y = 64;
    621  1.1  jmcneill 			}
    622  1.1  jmcneill 			return 0;
    623  1.1  jmcneill 		case WSDISPLAYIO_SCURSOR:
    624  1.1  jmcneill 			{
    625  1.1  jmcneill 				struct wsdisplay_cursor *cursor = (void *)data;
    626  1.1  jmcneill 
    627  1.1  jmcneill 				return omapfb_do_cursor(sc, cursor);
    628  1.1  jmcneill 			}
    629  1.1  jmcneill 	}
    630  1.1  jmcneill 	return EPASSTHROUGH;
    631  1.1  jmcneill }
    632  1.1  jmcneill 
    633  1.1  jmcneill static paddr_t
    634  1.1  jmcneill omapfb_mmap(void *v, void *vs, off_t offset, int prot)
    635  1.1  jmcneill {
    636  1.1  jmcneill 	paddr_t pa = -1;
    637  1.1  jmcneill 	struct vcons_data *vd = v;
    638  1.1  jmcneill 	struct omapfb_softc *sc = vd->cookie;
    639  1.1  jmcneill 
    640  1.1  jmcneill 	/* 'regular' framebuffer mmap()ing */
    641  1.1  jmcneill 	if (offset < sc->sc_vramsize) {
    642  1.1  jmcneill 		pa = bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmamem, 1,
    643  1.1  jmcneill 		    offset + PAGE_SIZE, prot, BUS_DMA_PREFETCHABLE);
    644  1.1  jmcneill 		return pa;
    645  1.1  jmcneill 	}
    646  1.1  jmcneill 	return pa;
    647  1.1  jmcneill }
    648  1.1  jmcneill 
    649  1.1  jmcneill static void
    650  1.1  jmcneill omapfb_init_screen(void *cookie, struct vcons_screen *scr,
    651  1.1  jmcneill     int existing, long *defattr)
    652  1.1  jmcneill {
    653  1.1  jmcneill 	struct omapfb_softc *sc = cookie;
    654  1.1  jmcneill 	struct rasops_info *ri = &scr->scr_ri;
    655  1.1  jmcneill 
    656  1.1  jmcneill 	ri->ri_depth = sc->sc_depth;
    657  1.1  jmcneill 	ri->ri_width = sc->sc_width;
    658  1.1  jmcneill 	ri->ri_height = sc->sc_height;
    659  1.1  jmcneill 	ri->ri_stride = sc->sc_stride;
    660  1.1  jmcneill 	ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
    661  1.1  jmcneill 
    662  1.1  jmcneill 	ri->ri_bits = (char *)sc->sc_fbaddr;
    663  1.1  jmcneill 
    664  1.1  jmcneill #if NOMAPDMA < 1
    665  1.1  jmcneill 	scr->scr_flags |= VCONS_DONT_READ;
    666  1.1  jmcneill #endif
    667  1.1  jmcneill 
    668  1.1  jmcneill 	if (existing) {
    669  1.1  jmcneill 		ri->ri_flg |= RI_CLEAR;
    670  1.1  jmcneill 	}
    671  1.1  jmcneill 
    672  1.1  jmcneill 	rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
    673  1.1  jmcneill 	ri->ri_caps = WSSCREEN_WSCOLORS;
    674  1.1  jmcneill 
    675  1.1  jmcneill 	rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
    676  1.1  jmcneill 		    sc->sc_width / ri->ri_font->fontwidth);
    677  1.1  jmcneill 
    678  1.1  jmcneill 	ri->ri_hw = scr;
    679  1.1  jmcneill 
    680  1.1  jmcneill #if NOMAPDMA > 0
    681  1.1  jmcneill 	ri->ri_ops.copyrows = omapfb_copyrows;
    682  1.1  jmcneill 	ri->ri_ops.copycols = omapfb_copycols;
    683  1.1  jmcneill 	ri->ri_ops.eraserows = omapfb_eraserows;
    684  1.1  jmcneill 	ri->ri_ops.erasecols = omapfb_erasecols;
    685  1.1  jmcneill 	ri->ri_ops.cursor = omapfb_cursor;
    686  1.1  jmcneill 	sc->sc_putchar = ri->ri_ops.putchar;
    687  1.1  jmcneill 	ri->ri_ops.putchar = omapfb_putchar;
    688  1.1  jmcneill #endif
    689  1.1  jmcneill }
    690  1.1  jmcneill 
    691  1.1  jmcneill static int
    692  1.1  jmcneill omapfb_putcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
    693  1.1  jmcneill {
    694  1.1  jmcneill 	u_char *r, *g, *b;
    695  1.1  jmcneill 	u_int index = cm->index;
    696  1.1  jmcneill 	u_int count = cm->count;
    697  1.1  jmcneill 	int i, error;
    698  1.1  jmcneill 	u_char rbuf[256], gbuf[256], bbuf[256];
    699  1.1  jmcneill 
    700  1.1  jmcneill 	if (cm->index >= 256 || cm->count > 256 ||
    701  1.1  jmcneill 	    (cm->index + cm->count) > 256)
    702  1.1  jmcneill 		return EINVAL;
    703  1.1  jmcneill 	error = copyin(cm->red, &rbuf[index], count);
    704  1.1  jmcneill 	if (error)
    705  1.1  jmcneill 		return error;
    706  1.1  jmcneill 	error = copyin(cm->green, &gbuf[index], count);
    707  1.1  jmcneill 	if (error)
    708  1.1  jmcneill 		return error;
    709  1.1  jmcneill 	error = copyin(cm->blue, &bbuf[index], count);
    710  1.1  jmcneill 	if (error)
    711  1.1  jmcneill 		return error;
    712  1.1  jmcneill 
    713  1.1  jmcneill 	memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
    714  1.1  jmcneill 	memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
    715  1.1  jmcneill 	memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
    716  1.1  jmcneill 
    717  1.1  jmcneill 	r = &sc->sc_cmap_red[index];
    718  1.1  jmcneill 	g = &sc->sc_cmap_green[index];
    719  1.1  jmcneill 	b = &sc->sc_cmap_blue[index];
    720  1.1  jmcneill 
    721  1.1  jmcneill 	for (i = 0; i < count; i++) {
    722  1.1  jmcneill 		omapfb_putpalreg(sc, index, *r, *g, *b);
    723  1.1  jmcneill 		index++;
    724  1.1  jmcneill 		r++, g++, b++;
    725  1.1  jmcneill 	}
    726  1.1  jmcneill 	return 0;
    727  1.1  jmcneill }
    728  1.1  jmcneill 
    729  1.1  jmcneill static int
    730  1.1  jmcneill omapfb_getcmap(struct omapfb_softc *sc, struct wsdisplay_cmap *cm)
    731  1.1  jmcneill {
    732  1.1  jmcneill 	u_int index = cm->index;
    733  1.1  jmcneill 	u_int count = cm->count;
    734  1.1  jmcneill 	int error;
    735  1.1  jmcneill 
    736  1.1  jmcneill 	if (index >= 255 || count > 256 || index + count > 256)
    737  1.1  jmcneill 		return EINVAL;
    738  1.1  jmcneill 
    739  1.1  jmcneill 	error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
    740  1.1  jmcneill 	if (error)
    741  1.1  jmcneill 		return error;
    742  1.1  jmcneill 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
    743  1.1  jmcneill 	if (error)
    744  1.1  jmcneill 		return error;
    745  1.1  jmcneill 	error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
    746  1.1  jmcneill 	if (error)
    747  1.1  jmcneill 		return error;
    748  1.1  jmcneill 
    749  1.1  jmcneill 	return 0;
    750  1.1  jmcneill }
    751  1.1  jmcneill 
    752  1.1  jmcneill static void
    753  1.1  jmcneill omapfb_restore_palette(struct omapfb_softc *sc)
    754  1.1  jmcneill {
    755  1.1  jmcneill 	int i;
    756  1.1  jmcneill 
    757  1.1  jmcneill 	for (i = 0; i < 256; i++) {
    758  1.1  jmcneill 		omapfb_putpalreg(sc, i, sc->sc_cmap_red[i],
    759  1.1  jmcneill 		    sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
    760  1.1  jmcneill 	}
    761  1.1  jmcneill }
    762  1.1  jmcneill 
    763  1.1  jmcneill static void
    764  1.1  jmcneill omapfb_putpalreg(struct omapfb_softc *sc, int idx, uint8_t r, uint8_t g,
    765  1.1  jmcneill     uint8_t b)
    766  1.1  jmcneill {
    767  1.1  jmcneill 	uint32_t reg;
    768  1.1  jmcneill 
    769  1.1  jmcneill 	if ((idx < 0) || (idx > 255))
    770  1.1  jmcneill 		return;
    771  1.1  jmcneill 	/* whack the DAC */
    772  1.1  jmcneill 	reg = (r << 16) | (g << 8) | b;
    773  1.1  jmcneill 	sc->sc_clut[idx] = reg;
    774  1.1  jmcneill }
    775  1.1  jmcneill 
    776  1.1  jmcneill static int
    777  1.1  jmcneill omapfb_set_depth(struct omapfb_softc *sc, int d)
    778  1.1  jmcneill {
    779  1.1  jmcneill 	uint32_t reg;
    780  1.1  jmcneill 
    781  1.1  jmcneill 	reg = OMAP_VID_ATTR_ENABLE |
    782  1.1  jmcneill 	      OMAP_VID_ATTR_BURST_16x32 |
    783  1.1  jmcneill 	      OMAP_VID_ATTR_REPLICATION;
    784  1.1  jmcneill 	switch (d) {
    785  1.1  jmcneill 		case 16:
    786  1.1  jmcneill 			reg |= OMAP_VID_ATTR_RGB16;
    787  1.1  jmcneill 			break;
    788  1.1  jmcneill 		case 32:
    789  1.1  jmcneill 			reg |= OMAP_VID_ATTR_RGB24;
    790  1.1  jmcneill 			break;
    791  1.1  jmcneill 		default:
    792  1.1  jmcneill 			aprint_error_dev(sc->sc_dev,
    793  1.1  jmcneill 			    "unsupported depth (%d)\n", d);
    794  1.1  jmcneill 			return EINVAL;
    795  1.1  jmcneill 	}
    796  1.1  jmcneill 
    797  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh,
    798  1.1  jmcneill 	    OMAPFB_DISPC_VID1_ATTRIBUTES, reg);
    799  1.1  jmcneill 
    800  1.1  jmcneill 	/*
    801  1.1  jmcneill 	 * now tell the video controller that we're done mucking around and
    802  1.1  jmcneill 	 * actually update its settings
    803  1.1  jmcneill 	 */
    804  1.1  jmcneill 	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
    805  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
    806  1.1  jmcneill 	    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
    807  1.1  jmcneill 
    808  1.1  jmcneill 	sc->sc_depth = d;
    809  1.1  jmcneill 	sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
    810  1.1  jmcneill 
    811  1.1  jmcneill 	/* clear the screen here */
    812  1.1  jmcneill #if NOMAPDMA > 0
    813  1.1  jmcneill 	omapfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, 0);
    814  1.1  jmcneill #else
    815  1.1  jmcneill 	memset(sc->sc_fbaddr, 0, sc->sc_stride * sc->sc_height);
    816  1.1  jmcneill #endif
    817  1.1  jmcneill 	return 0;
    818  1.1  jmcneill }
    819  1.1  jmcneill 
    820  1.1  jmcneill static void
    821  1.1  jmcneill omapfb_set_video(struct omapfb_softc *sc, int on)
    822  1.1  jmcneill {
    823  1.1  jmcneill 	uint32_t reg;
    824  1.1  jmcneill 
    825  1.1  jmcneill 	if (on == sc->sc_video_is_on)
    826  1.1  jmcneill 		return;
    827  1.1  jmcneill 	if (on) {
    828  1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_regh,
    829  1.1  jmcneill 		    OMAPFB_DISPC_CONFIG, sc->sc_dispc_config);
    830  1.1  jmcneill 		on = 1;
    831  1.1  jmcneill 	} else {
    832  1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_regh,
    833  1.1  jmcneill 		    OMAPFB_DISPC_CONFIG, sc->sc_dispc_config |
    834  1.1  jmcneill 		    OMAP_DISPC_CFG_VSYNC_GATED | OMAP_DISPC_CFG_HSYNC_GATED |
    835  1.1  jmcneill 		    OMAP_DISPC_CFG_PIXELCLK_GATED |
    836  1.1  jmcneill 		    OMAP_DISPC_CFG_PIXELDATA_GATED);
    837  1.1  jmcneill 	}
    838  1.1  jmcneill 
    839  1.1  jmcneill 	/*
    840  1.1  jmcneill 	 * now tell the video controller that we're done mucking around and
    841  1.1  jmcneill 	 * actually update its settings
    842  1.1  jmcneill 	 */
    843  1.1  jmcneill 	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
    844  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
    845  1.1  jmcneill 	    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
    846  1.1  jmcneill 
    847  1.1  jmcneill 	aprint_debug_dev(sc->sc_dev, "%s %08x\n", __func__,
    848  1.1  jmcneill 	    bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONFIG));
    849  1.1  jmcneill 	sc->sc_video_is_on = on;
    850  1.1  jmcneill }
    851  1.1  jmcneill 
    852  1.1  jmcneill #if NOMAPDMA > 0
    853  1.1  jmcneill static void
    854  1.1  jmcneill omapfb_init(struct omapfb_softc *sc)
    855  1.1  jmcneill {
    856  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CLNK_CTRL, 0);
    857  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CICRI, 0);
    858  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
    859  1.1  jmcneill 	    CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
    860  1.1  jmcneill 	    CSDPI_WRITE_POSTED | CSDPI_DATA_TYPE_16);
    861  1.1  jmcneill }
    862  1.1  jmcneill 
    863  1.1  jmcneill static void
    864  1.1  jmcneill omapfb_wait_idle(struct omapfb_softc *sc)
    865  1.1  jmcneill {
    866  1.1  jmcneill 	while ((omapdma_read_ch_reg(0, OMAPDMAC_CCR) & CCR_WR_ACTIVE) != 0);
    867  1.1  jmcneill }
    868  1.1  jmcneill 
    869  1.1  jmcneill static void
    870  1.1  jmcneill omapfb_rectfill(struct omapfb_softc *sc, int x, int y, int wi, int he,
    871  1.1  jmcneill      uint32_t colour)
    872  1.1  jmcneill {
    873  1.1  jmcneill 	int bpp = sc->sc_depth >> 3;	/* bytes per pixel */
    874  1.1  jmcneill 	int width_in_bytes = wi * bpp;
    875  1.1  jmcneill 	uint32_t daddr;
    876  1.1  jmcneill 
    877  1.1  jmcneill 	daddr = sc->sc_fbhwaddr + sc->sc_stride * y + x * bpp;
    878  1.1  jmcneill 	omapfb_wait_idle(sc);
    879  1.1  jmcneill 
    880  1.1  jmcneill 	/*
    881  1.1  jmcneill 	 * stupid hardware
    882  1.1  jmcneill 	 * in 32bit mode the DMA controller always writes 0 into the upper
    883  1.1  jmcneill 	 * byte, so we can use this mode only if we actually want that
    884  1.1  jmcneill 	 */
    885  1.1  jmcneill 	if (((colour & 0xff00) == 0) &&
    886  1.1  jmcneill 	   (((daddr | width_in_bytes) & 3) == 0)) {
    887  1.1  jmcneill 		/*
    888  1.1  jmcneill 		 * everything is properly aligned so we can copy stuff in
    889  1.1  jmcneill 		 * 32bit chunks instead of pixel by pixel
    890  1.1  jmcneill 		 */
    891  1.1  jmcneill 		wi = wi >> 1;
    892  1.1  jmcneill 
    893  1.1  jmcneill 		/* just in case */
    894  1.1  jmcneill 		colour |= colour << 16;
    895  1.1  jmcneill 
    896  1.1  jmcneill 		omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
    897  1.1  jmcneill 		    CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
    898  1.1  jmcneill 		    CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
    899  1.1  jmcneill 		    CSDPI_DATA_TYPE_32);
    900  1.1  jmcneill 	} else {
    901  1.1  jmcneill 		omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
    902  1.1  jmcneill 		    CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
    903  1.1  jmcneill 		    CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
    904  1.1  jmcneill 		    CSDPI_DATA_TYPE_16);
    905  1.1  jmcneill 	}
    906  1.1  jmcneill 
    907  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
    908  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
    909  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
    910  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CCR,
    911  1.1  jmcneill 	    CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
    912  1.1  jmcneill 	    CCR_SRC_AMODE_CONST_ADDR);
    913  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDEI, 1);
    914  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDFI,
    915  1.1  jmcneill 	    (sc->sc_stride - width_in_bytes) + 1);
    916  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_COLOR, colour);
    917  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CCR,
    918  1.1  jmcneill 	    CCR_CONST_FILL_ENABLE | CCR_DST_AMODE_DOUBLE_INDEX |
    919  1.1  jmcneill 	    CCR_SRC_AMODE_CONST_ADDR | CCR_ENABLE);
    920  1.1  jmcneill }
    921  1.1  jmcneill 
    922  1.1  jmcneill static void
    923  1.1  jmcneill omapfb_bitblt(struct omapfb_softc *sc, int xs, int ys, int xd, int yd,
    924  1.1  jmcneill     int wi, int he, int rop)
    925  1.1  jmcneill {
    926  1.1  jmcneill 	int bpp = sc->sc_depth >> 3;	/* bytes per pixel */
    927  1.1  jmcneill 	int width_in_bytes = wi * bpp;
    928  1.1  jmcneill 
    929  1.1  jmcneill 	int hstep, vstep;
    930  1.1  jmcneill 	uint32_t saddr, daddr;
    931  1.1  jmcneill 
    932  1.1  jmcneill 	saddr = sc->sc_fbhwaddr + sc->sc_stride * ys + xs * bpp;
    933  1.1  jmcneill 	daddr = sc->sc_fbhwaddr + sc->sc_stride * yd + xd * bpp;
    934  1.1  jmcneill 
    935  1.1  jmcneill 	if (ys < yd) {
    936  1.1  jmcneill 		/* need to go vertically backwards */
    937  1.1  jmcneill 		vstep = 1 - (sc->sc_stride + width_in_bytes);
    938  1.1  jmcneill 		saddr += sc->sc_stride * (he - 1);
    939  1.1  jmcneill 		daddr += sc->sc_stride * (he - 1);
    940  1.1  jmcneill 	} else
    941  1.1  jmcneill 		vstep = (sc->sc_stride - width_in_bytes) + 1;
    942  1.1  jmcneill 	if ((xs < xd) && (ys == yd)) {
    943  1.1  jmcneill 		/*
    944  1.1  jmcneill 		 * need to go horizontally backwards, only needed if source
    945  1.1  jmcneill 		 * and destination pixels are on the same line
    946  1.1  jmcneill 		 */
    947  1.1  jmcneill 		hstep = 1 - (sc->sc_depth >> 2);
    948  1.1  jmcneill 		vstep = sc->sc_stride + bpp * (wi - 1) + 1;
    949  1.1  jmcneill 		saddr += bpp * (wi - 1);
    950  1.1  jmcneill 		daddr += bpp * (wi - 1);
    951  1.1  jmcneill 	} else
    952  1.1  jmcneill 		hstep = 1;
    953  1.1  jmcneill 
    954  1.1  jmcneill 	omapfb_wait_idle(sc);
    955  1.1  jmcneill 	if (((saddr | daddr | width_in_bytes) & 3) == 0) {
    956  1.1  jmcneill 		/*
    957  1.1  jmcneill 		 * everything is properly aligned so we can copy stuff in
    958  1.1  jmcneill 		 * 32bit chunks instead of pixel by pixel
    959  1.1  jmcneill 		 */
    960  1.1  jmcneill 		wi = wi >> 1;
    961  1.1  jmcneill 		omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
    962  1.1  jmcneill 		    CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
    963  1.1  jmcneill 		    CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
    964  1.1  jmcneill 		    CSDPI_DATA_TYPE_32);
    965  1.1  jmcneill 	} else {
    966  1.1  jmcneill 		omapdma_write_ch_reg(0, OMAPDMAC_CSDPI,
    967  1.1  jmcneill 		    CSDPI_SRC_BURST_64 | CSDPI_DST_BURST_64 |
    968  1.1  jmcneill 		    CSDPI_DST_PACKED | CSDPI_WRITE_POSTED_EXCEPT_LAST |
    969  1.1  jmcneill 		    CSDPI_DATA_TYPE_16);
    970  1.1  jmcneill 	}
    971  1.1  jmcneill 
    972  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CEN, wi);
    973  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CFN, he);
    974  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CSSA, saddr);
    975  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDSA, daddr);
    976  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CCR,
    977  1.1  jmcneill 	    CCR_DST_AMODE_DOUBLE_INDEX |
    978  1.1  jmcneill 	    CCR_SRC_AMODE_DOUBLE_INDEX);
    979  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CSEI, hstep);
    980  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CSFI, vstep);
    981  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDEI, hstep);
    982  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CDFI, vstep);
    983  1.1  jmcneill 	omapdma_write_ch_reg(0, OMAPDMAC_CCR,
    984  1.1  jmcneill 	    CCR_DST_AMODE_DOUBLE_INDEX |
    985  1.1  jmcneill 	    CCR_SRC_AMODE_DOUBLE_INDEX | CCR_ENABLE);
    986  1.1  jmcneill }
    987  1.1  jmcneill 
    988  1.1  jmcneill static void
    989  1.1  jmcneill omapfb_cursor(void *cookie, int on, int row, int col)
    990  1.1  jmcneill {
    991  1.1  jmcneill 	struct rasops_info *ri = cookie;
    992  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
    993  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
    994  1.1  jmcneill 	int pos;
    995  1.1  jmcneill 
    996  1.1  jmcneill 	pos = col + row * ri->ri_cols;
    997  1.1  jmcneill #ifdef WSDISPLAY_SCROLLSUPPORT
    998  1.1  jmcneill 	pos += scr->scr_offset_to_zero;
    999  1.1  jmcneill #endif
   1000  1.1  jmcneill 	if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
   1001  1.1  jmcneill 		if (ri->ri_flg & RI_CURSOR) {
   1002  1.1  jmcneill 			omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
   1003  1.1  jmcneill 			    scr->scr_attrs[pos]);
   1004  1.1  jmcneill 			ri->ri_flg &= ~RI_CURSOR;
   1005  1.1  jmcneill 		}
   1006  1.1  jmcneill 		ri->ri_crow = row;
   1007  1.1  jmcneill 		ri->ri_ccol = col;
   1008  1.1  jmcneill 		if (on) {
   1009  1.1  jmcneill 			omapfb_putchar(cookie, row, col, scr->scr_chars[pos],
   1010  1.1  jmcneill 			    scr->scr_attrs[pos] ^ 0x0f0f0000);
   1011  1.1  jmcneill 			ri->ri_flg |= RI_CURSOR;
   1012  1.1  jmcneill 		}
   1013  1.1  jmcneill 	} else {
   1014  1.1  jmcneill 		scr->scr_ri.ri_crow = row;
   1015  1.1  jmcneill 		scr->scr_ri.ri_ccol = col;
   1016  1.1  jmcneill 		scr->scr_ri.ri_flg &= ~RI_CURSOR;
   1017  1.1  jmcneill 	}
   1018  1.1  jmcneill }
   1019  1.1  jmcneill 
   1020  1.1  jmcneill static void
   1021  1.1  jmcneill omapfb_putchar(void *cookie, int row, int col, u_int c, long attr)
   1022  1.1  jmcneill {
   1023  1.1  jmcneill 	struct rasops_info *ri = cookie;
   1024  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
   1025  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
   1026  1.1  jmcneill 
   1027  1.1  jmcneill 	if (c == 0x20) {
   1028  1.1  jmcneill 		uint32_t fg, bg, ul;
   1029  1.1  jmcneill 		rasops_unpack_attr(attr, &fg, &bg, &ul);
   1030  1.1  jmcneill 		omapfb_rectfill(sc,
   1031  1.1  jmcneill 		    ri->ri_xorigin + ri->ri_font->fontwidth * col,
   1032  1.1  jmcneill 		    ri->ri_yorigin + ri->ri_font->fontheight * row,
   1033  1.1  jmcneill 		    ri->ri_font->fontwidth,
   1034  1.1  jmcneill 		    ri->ri_font->fontheight,
   1035  1.1  jmcneill 		    ri->ri_devcmap[bg]);
   1036  1.1  jmcneill 		return;
   1037  1.1  jmcneill 	}
   1038  1.1  jmcneill 	omapfb_wait_idle(sc);
   1039  1.1  jmcneill 	sc->sc_putchar(cookie, row, col, c, attr);
   1040  1.1  jmcneill }
   1041  1.1  jmcneill 
   1042  1.1  jmcneill static void
   1043  1.1  jmcneill omapfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
   1044  1.1  jmcneill {
   1045  1.1  jmcneill 	struct rasops_info *ri = cookie;
   1046  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
   1047  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
   1048  1.1  jmcneill 	int32_t xs, xd, y, width, height;
   1049  1.1  jmcneill 
   1050  1.1  jmcneill 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
   1051  1.1  jmcneill 		xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
   1052  1.1  jmcneill 		xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
   1053  1.1  jmcneill 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
   1054  1.1  jmcneill 		width = ri->ri_font->fontwidth * ncols;
   1055  1.1  jmcneill 		height = ri->ri_font->fontheight;
   1056  1.1  jmcneill 		omapfb_bitblt(sc, xs, y, xd, y, width, height, 12);
   1057  1.1  jmcneill 	}
   1058  1.1  jmcneill }
   1059  1.1  jmcneill 
   1060  1.1  jmcneill static void
   1061  1.1  jmcneill omapfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
   1062  1.1  jmcneill {
   1063  1.1  jmcneill 	struct rasops_info *ri = cookie;
   1064  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
   1065  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
   1066  1.1  jmcneill 	int32_t x, y, width, height, fg, bg, ul;
   1067  1.1  jmcneill 
   1068  1.1  jmcneill 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
   1069  1.1  jmcneill 		x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
   1070  1.1  jmcneill 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
   1071  1.1  jmcneill 		width = ri->ri_font->fontwidth * ncols;
   1072  1.1  jmcneill 		height = ri->ri_font->fontheight;
   1073  1.1  jmcneill 		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
   1074  1.1  jmcneill 
   1075  1.1  jmcneill 		omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
   1076  1.1  jmcneill 	}
   1077  1.1  jmcneill }
   1078  1.1  jmcneill 
   1079  1.1  jmcneill static void
   1080  1.1  jmcneill omapfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
   1081  1.1  jmcneill {
   1082  1.1  jmcneill 	struct rasops_info *ri = cookie;
   1083  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
   1084  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
   1085  1.1  jmcneill 	int32_t x, ys, yd, width, height;
   1086  1.1  jmcneill 
   1087  1.1  jmcneill 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
   1088  1.1  jmcneill 		x = ri->ri_xorigin;
   1089  1.1  jmcneill 		ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
   1090  1.1  jmcneill 		yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
   1091  1.1  jmcneill 		width = ri->ri_emuwidth;
   1092  1.1  jmcneill 		height = ri->ri_font->fontheight * nrows;
   1093  1.1  jmcneill 		omapfb_bitblt(sc, x, ys, x, yd, width, height, 12);
   1094  1.1  jmcneill 	}
   1095  1.1  jmcneill }
   1096  1.1  jmcneill 
   1097  1.1  jmcneill static void
   1098  1.1  jmcneill omapfb_eraserows(void *cookie, int row, int nrows, long fillattr)
   1099  1.1  jmcneill {
   1100  1.1  jmcneill 	struct rasops_info *ri = cookie;
   1101  1.1  jmcneill 	struct vcons_screen *scr = ri->ri_hw;
   1102  1.1  jmcneill 	struct omapfb_softc *sc = scr->scr_cookie;
   1103  1.1  jmcneill 	int32_t x, y, width, height, fg, bg, ul;
   1104  1.1  jmcneill 
   1105  1.1  jmcneill 	if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
   1106  1.1  jmcneill 		x = ri->ri_xorigin;
   1107  1.1  jmcneill 		y = ri->ri_yorigin + ri->ri_font->fontheight * row;
   1108  1.1  jmcneill 		width = ri->ri_emuwidth;
   1109  1.1  jmcneill 		height = ri->ri_font->fontheight * nrows;
   1110  1.1  jmcneill 		rasops_unpack_attr(fillattr, &fg, &bg, &ul);
   1111  1.1  jmcneill 
   1112  1.1  jmcneill 		omapfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
   1113  1.1  jmcneill 	}
   1114  1.1  jmcneill }
   1115  1.1  jmcneill #endif /* NOMAPDMA > 0 */
   1116  1.1  jmcneill 
   1117  1.1  jmcneill static void
   1118  1.1  jmcneill omapfb_move_cursor(struct omapfb_softc *sc, int x, int y)
   1119  1.1  jmcneill {
   1120  1.1  jmcneill 	uint32_t pos, reg, addr;
   1121  1.1  jmcneill 	int xx, yy, wi = 64, he = 64;
   1122  1.1  jmcneill 
   1123  1.1  jmcneill 	/*
   1124  1.1  jmcneill 	 * we need to special case anything and everything where the cursor
   1125  1.1  jmcneill 	 * may be partially off screen
   1126  1.1  jmcneill 	 */
   1127  1.1  jmcneill 
   1128  1.1  jmcneill 	addr = sc->sc_fbhwaddr + sc->sc_cursor_offset;
   1129  1.1  jmcneill 	xx = x - sc->sc_hot_x;
   1130  1.1  jmcneill 	yy = y - sc->sc_hot_y;
   1131  1.1  jmcneill 
   1132  1.1  jmcneill 	/*
   1133  1.1  jmcneill 	 * if we're off to the top or left we need to shif the start address
   1134  1.1  jmcneill 	 * and shrink the gfx layer size
   1135  1.1  jmcneill 	 */
   1136  1.1  jmcneill 	if (xx < 0) {
   1137  1.1  jmcneill 		wi += xx;
   1138  1.1  jmcneill 		addr -= xx * 4;
   1139  1.1  jmcneill 		xx = 0;
   1140  1.1  jmcneill 	}
   1141  1.1  jmcneill 	if (yy < 0) {
   1142  1.1  jmcneill 		he += yy;
   1143  1.1  jmcneill 		addr -= yy * 64 * 4;
   1144  1.1  jmcneill 		yy = 0;
   1145  1.1  jmcneill 	}
   1146  1.1  jmcneill 	if (xx > (sc->sc_width - 64)) {
   1147  1.1  jmcneill 		wi -= (xx + 64 - sc->sc_width);
   1148  1.1  jmcneill 	}
   1149  1.1  jmcneill 	if (yy > (sc->sc_height - 64)) {
   1150  1.1  jmcneill 		he -= (yy + 64 - sc->sc_height);
   1151  1.1  jmcneill 	}
   1152  1.1  jmcneill 	pos = (yy << 16) | xx;
   1153  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_BASE_0,
   1154  1.1  jmcneill 	    addr);
   1155  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_POSITION,
   1156  1.1  jmcneill 	    pos);
   1157  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_SIZE,
   1158  1.1  jmcneill 	    ((he - 1) << 16) | (wi - 1));
   1159  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_GFX_ROW_INC,
   1160  1.1  jmcneill 	    (64 - wi) * 4 + 1);
   1161  1.1  jmcneill 	/*
   1162  1.1  jmcneill 	 * now tell the video controller that we're done mucking around and
   1163  1.1  jmcneill 	 * actually update its settings
   1164  1.1  jmcneill 	 */
   1165  1.1  jmcneill 	reg = bus_space_read_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL);
   1166  1.1  jmcneill 	bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
   1167  1.1  jmcneill 	    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
   1168  1.1  jmcneill }
   1169  1.1  jmcneill 
   1170  1.1  jmcneill static int
   1171  1.1  jmcneill omapfb_do_cursor(struct omapfb_softc * sc,
   1172  1.1  jmcneill                            struct wsdisplay_cursor *cur)
   1173  1.1  jmcneill {
   1174  1.1  jmcneill 	int whack = 0;
   1175  1.1  jmcneill 	int shape = 0;
   1176  1.1  jmcneill 
   1177  1.1  jmcneill 	if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
   1178  1.1  jmcneill 		uint32_t attr = OMAP_DISPC_ATTR_BURST_16x32 |
   1179  1.1  jmcneill 				OMAP_DISPC_ATTR_ARGB32 |
   1180  1.1  jmcneill 				OMAP_DISPC_ATTR_REPLICATION;
   1181  1.1  jmcneill 
   1182  1.1  jmcneill 		if (cur->enable) attr |= OMAP_DISPC_ATTR_ENABLE;
   1183  1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_regh,
   1184  1.1  jmcneill 		    OMAPFB_DISPC_GFX_ATTRIBUTES, attr);
   1185  1.1  jmcneill 		whack = 1;
   1186  1.1  jmcneill 	}
   1187  1.1  jmcneill 	if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
   1188  1.1  jmcneill 
   1189  1.1  jmcneill 		sc->sc_hot_x = cur->hot.x;
   1190  1.1  jmcneill 		sc->sc_hot_y = cur->hot.y;
   1191  1.1  jmcneill 		cur->which |= WSDISPLAY_CURSOR_DOPOS;
   1192  1.1  jmcneill 	}
   1193  1.1  jmcneill 	if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
   1194  1.1  jmcneill 
   1195  1.1  jmcneill 		omapfb_move_cursor(sc, cur->pos.x, cur->pos.y);
   1196  1.1  jmcneill 	}
   1197  1.1  jmcneill 	if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
   1198  1.1  jmcneill 		int i;
   1199  1.1  jmcneill 		uint32_t val;
   1200  1.1  jmcneill 
   1201  1.1  jmcneill 		for (i = 0; i < uimin(cur->cmap.count, 3); i++) {
   1202  1.1  jmcneill 			val = (cur->cmap.red[i] << 16 ) |
   1203  1.1  jmcneill 			      (cur->cmap.green[i] << 8) |
   1204  1.1  jmcneill 			      (cur->cmap.blue[i] ) |
   1205  1.1  jmcneill 			      0xff000000;
   1206  1.1  jmcneill 			sc->sc_cursor_cmap[i + cur->cmap.index + 2] = val;
   1207  1.1  jmcneill 		}
   1208  1.1  jmcneill 		shape = 1;
   1209  1.1  jmcneill 	}
   1210  1.1  jmcneill 	if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
   1211  1.1  jmcneill 
   1212  1.1  jmcneill 		copyin(cur->mask, sc->sc_cursor_mask, 64 * 8);
   1213  1.1  jmcneill 		copyin(cur->image, sc->sc_cursor_bitmap, 64 * 8);
   1214  1.1  jmcneill 		shape = 1;
   1215  1.1  jmcneill 	}
   1216  1.1  jmcneill 	if (shape) {
   1217  1.1  jmcneill 		int i, j, idx;
   1218  1.1  jmcneill 		uint8_t mask;
   1219  1.1  jmcneill 
   1220  1.1  jmcneill 		for (i = 0; i < 64 * 8; i++) {
   1221  1.1  jmcneill 			mask = 0x01;
   1222  1.1  jmcneill 			for (j = 0; j < 8; j++) {
   1223  1.1  jmcneill 				idx = ((sc->sc_cursor_mask[i] & mask) ? 2 : 0) |
   1224  1.1  jmcneill 				    ((sc->sc_cursor_bitmap[i] & mask) ? 1 : 0);
   1225  1.1  jmcneill 				sc->sc_cursor_img[i * 8 + j] =
   1226  1.1  jmcneill 				    sc->sc_cursor_cmap[idx];
   1227  1.1  jmcneill 				mask = mask << 1;
   1228  1.1  jmcneill 			}
   1229  1.1  jmcneill 		}
   1230  1.1  jmcneill 	}
   1231  1.1  jmcneill 	if (whack) {
   1232  1.1  jmcneill 		uint32_t reg;
   1233  1.1  jmcneill 
   1234  1.1  jmcneill 		reg = bus_space_read_4(sc->sc_iot, sc->sc_regh,
   1235  1.1  jmcneill 		    OMAPFB_DISPC_CONTROL);
   1236  1.1  jmcneill 		bus_space_write_4(sc->sc_iot, sc->sc_regh, OMAPFB_DISPC_CONTROL,
   1237  1.1  jmcneill 		    reg | OMAP_DISPC_CTRL_GO_LCD | OMAP_DISPC_CTRL_GO_DIGITAL);
   1238  1.1  jmcneill 	}
   1239  1.1  jmcneill 	return 0;
   1240  1.1  jmcneill 
   1241  1.1  jmcneill }
   1242  1.1  jmcneill 
   1243  1.1  jmcneill static int
   1244  1.1  jmcneill omapfb_console_match(int phandle)
   1245  1.1  jmcneill {
   1246  1.1  jmcneill 	return of_match_compatible(phandle, compatible);
   1247  1.1  jmcneill }
   1248  1.1  jmcneill 
   1249  1.1  jmcneill static void
   1250  1.1  jmcneill omapfb_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
   1251  1.1  jmcneill {
   1252  1.1  jmcneill 	omapfb_console_phandle = faa->faa_phandle;
   1253  1.1  jmcneill }
   1254  1.1  jmcneill 
   1255  1.1  jmcneill static const struct fdt_console omapfb_fdt_console = {
   1256  1.1  jmcneill 	.match = omapfb_console_match,
   1257  1.1  jmcneill 	.consinit = omapfb_console_consinit,
   1258  1.1  jmcneill };
   1259  1.1  jmcneill 
   1260  1.1  jmcneill FDT_CONSOLE(omapfb, &omapfb_fdt_console);
   1261