Home | History | Annotate | Line # | Download | only in ti
      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