Home | History | Annotate | Line # | Download | only in sunxi
sunxi_mixer.c revision 1.17
      1 /* $NetBSD: sunxi_mixer.c,v 1.17 2021/12/19 11:00:46 riastradh Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2019 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: sunxi_mixer.c,v 1.17 2021/12/19 11:00:46 riastradh Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/intr.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 #include <sys/conf.h>
     39 #include <sys/sysctl.h>
     40 
     41 #include <drm/drm_drv.h>
     42 #include <drm/drm_crtc.h>
     43 #include <drm/drm_crtc_helper.h>
     44 #include <drm/drm_fourcc.h>
     45 #include <drm/drm_plane_helper.h>
     46 #include <drm/drm_vblank.h>
     47 
     48 #include <dev/fdt/fdtvar.h>
     49 #include <dev/fdt/fdt_port.h>
     50 
     51 #include <arm/sunxi/sunxi_drm.h>
     52 
     53 #define	MIXER_CURSOR_MAXWIDTH	256
     54 #define	MIXER_CURSOR_MAXHEIGHT	256
     55 
     56 #define	SUNXI_MIXER_FREQ	432000000
     57 
     58 #define	GLB_BASE		0x00000
     59 #define	BLD_BASE		0x01000
     60 #define	OVL_BASE(n)		(0x02000 + (n) * 0x1000)
     61 #define	VSU_BASE		0x20000
     62 #define	CSC_BASE(n)		((n) == 0 ? 0xaa050 : 0xa0000)
     63 
     64 /* GLB registers */
     65 #define	GLB_CTL			0x000
     66 #define	 GLB_CTL_EN				__BIT(0)
     67 #define	GLB_STS			0x004
     68 #define	GLB_DBUFFER		0x008
     69 #define	 GLB_DBUFFER_DOUBLE_BUFFER_RDY		__BIT(0)
     70 #define	GLB_SIZE		0x00c
     71 
     72 /* BLD registers */
     73 #define	BLD_FILL_COLOR_CTL	0x000
     74 #define	 BLD_FILL_COLOR_CTL_P3_EN		__BIT(11)
     75 #define	 BLD_FILL_COLOR_CTL_P2_EN		__BIT(10)
     76 #define	 BLD_FILL_COLOR_CTL_P1_EN		__BIT(9)
     77 #define	 BLD_FILL_COLOR_CTL_P0_EN		__BIT(8)
     78 #define	 BLD_FILL_COLOR_CTL_P3_FCEN		__BIT(3)
     79 #define	 BLD_FILL_COLOR_CTL_P2_FCEN		__BIT(2)
     80 #define	 BLD_FILL_COLOR_CTL_P1_FCEN		__BIT(1)
     81 #define	 BLD_FILL_COLOR_CTL_P0_FCEN		__BIT(0)
     82 #define	BLD_FILL_COLOR(n)	(0x004 + (n) * 0x10)
     83 #define	BLD_CH_ISIZE(n)		(0x008 + (n) * 0x10)
     84 #define	BLD_CH_OFFSET(n)	(0x00c + (n) * 0x10)
     85 #define	BLD_CH_RTCTL		0x080
     86 #define	 BLD_CH_RTCTL_P3			__BITS(15,12)
     87 #define	 BLD_CH_RTCTL_P2			__BITS(11,8)
     88 #define	 BLD_CH_RTCTL_P1			__BITS(7,4)
     89 #define	 BLD_CH_RTCTL_P0			__BITS(3,0)
     90 #define	BLD_SIZE		0x08c
     91 #define	BLD_CTL(n)		(0x090 + (n) * 0x04)
     92 
     93 /* OVL_V registers */
     94 #define	OVL_V_ATTCTL(n)		(0x000 + (n) * 0x30)
     95 #define	 OVL_V_ATTCTL_VIDEO_UI_SEL		__BIT(15)
     96 #define	 OVL_V_ATTCTL_LAY_FBFMT			__BITS(12,8)
     97 #define	  OVL_V_ATTCTL_LAY_FBFMT_VYUY		0x00
     98 #define	  OVL_V_ATTCTL_LAY_FBFMT_YVYU		0x01
     99 #define	  OVL_V_ATTCTL_LAY_FBFMT_UYVY		0x02
    100 #define	  OVL_V_ATTCTL_LAY_FBFMT_YUYV		0x03
    101 #define	  OVL_V_ATTCTL_LAY_FBFMT_YUV422		0x06
    102 #define	  OVL_V_ATTCTL_LAY_FBFMT_YUV420		0x0a
    103 #define	  OVL_V_ATTCTL_LAY_FBFMT_YUV411		0x0e
    104 #if BYTE_ORDER == BIG_ENDIAN
    105 #define	  OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888	0x03
    106 #define	  OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888	0x07
    107 #else
    108 #define	  OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888	0x00
    109 #define	  OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888	0x04
    110 #endif
    111 #define	 OVL_V_ATTCTL_LAY0_EN			__BIT(0)
    112 #define	OVL_V_MBSIZE(n)		(0x004 + (n) * 0x30)
    113 #define	OVL_V_COOR(n)		(0x008 + (n) * 0x30)
    114 #define	OVL_V_PITCH0(n)		(0x00c + (n) * 0x30)
    115 #define	OVL_V_PITCH1(n)		(0x010 + (n) * 0x30)
    116 #define	OVL_V_PITCH2(n)		(0x014 + (n) * 0x30)
    117 #define	OVL_V_TOP_LADD0(n)	(0x018 + (n) * 0x30)
    118 #define	OVL_V_TOP_LADD1(n)	(0x01c + (n) * 0x30)
    119 #define	OVL_V_TOP_LADD2(n)	(0x020 + (n) * 0x30)
    120 #define	OVL_V_FILL_COLOR(n)	(0x0c0 + (n) * 0x4)
    121 #define	OVL_V_TOP_HADD0		0x0d0
    122 #define	OVL_V_TOP_HADD1		0x0d4
    123 #define	OVL_V_TOP_HADD2		0x0d8
    124 #define	 OVL_V_TOP_HADD_LAYER0	__BITS(7,0)
    125 #define	OVL_V_SIZE		0x0e8
    126 #define	OVL_V_HDS_CTL0		0x0f0
    127 #define	OVL_V_HDS_CTL1		0x0f4
    128 #define	OVL_V_VDS_CTL0		0x0f8
    129 #define	OVL_V_VDS_CTL1		0x0fc
    130 
    131 /* OVL_UI registers */
    132 #define	OVL_UI_ATTR_CTL(n)	(0x000 + (n) * 0x20)
    133 #define	 OVL_UI_ATTR_CTL_LAY_FBFMT		__BITS(12,8)
    134 #if BYTE_ORDER == BIG_ENDIAN
    135 #define	  OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888	0x03
    136 #define	  OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888	0x07
    137 #else
    138 #define	  OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888	0x00
    139 #define	  OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888	0x04
    140 #endif
    141 #define	 OVL_UI_ATTR_CTL_LAY_EN			__BIT(0)
    142 #define	OVL_UI_MBSIZE(n)	(0x004 + (n) * 0x20)
    143 #define	OVL_UI_COOR(n)		(0x008 + (n) * 0x20)
    144 #define	OVL_UI_PITCH(n)		(0x00c + (n) * 0x20)
    145 #define	OVL_UI_TOP_LADD(n)	(0x010 + (n) * 0x20)
    146 #define	OVL_UI_FILL_COLOR(n)	(0x018 + (n) * 0x20)
    147 #define	OVL_UI_TOP_HADD		0x080
    148 #define	 OVL_UI_TOP_HADD_LAYER1	__BITS(15,8)
    149 #define	 OVL_UI_TOP_HADD_LAYER0	__BITS(7,0)
    150 #define	OVL_UI_SIZE		0x088
    151 
    152 /* VSU registers */
    153 #define	VS_CTRL_REG		0x000
    154 #define	 VS_CTRL_COEF_SWITCH_EN			__BIT(4)
    155 #define	 VS_CTRL_EN				__BIT(0)
    156 #define	VS_STATUS_REG		0x008
    157 #define	VS_FIELD_CTRL_REG	0x00c
    158 #define	VS_OUT_SIZE_REG		0x040
    159 #define	VS_Y_SIZE_REG		0x080
    160 #define	VS_Y_HSTEP_REG		0x088
    161 #define	VS_Y_VSTEP_REG		0x08c
    162 #define	VS_Y_HPHASE_REG		0x090
    163 #define	VS_Y_VPHASE0_REG	0x098
    164 #define	VS_Y_VPHASE1_REG	0x09c
    165 #define	VS_C_SIZE_REG		0x0c0
    166 #define	VS_C_HSTEP_REG		0x0c8
    167 #define	VS_C_VSTEP_REG		0x0cc
    168 #define	VS_C_HPHASE_REG		0x0d0
    169 #define	VS_C_VPHASE0_REG	0x0d8
    170 #define	VS_C_VPHASE1_REG	0x0dc
    171 #define	VS_Y_HCOEF0_REG(n)	(0x200 + (n) * 0x4)
    172 #define	VS_Y_HCOEF1_REG(n)	(0x300 + (n) * 0x4)
    173 #define	VS_Y_VCOEF_REG(n)	(0x400 + (n) * 0x4)
    174 #define	VS_C_HCOEF0_REG(n)	(0x600 + (n) * 0x4)
    175 #define	VS_C_HCOEF1_REG(n)	(0x700 + (n) * 0x4)
    176 #define	VS_C_VCOEF_REG(n)	(0x800 + (n) * 0x4)
    177 
    178 /* CSC registers */
    179 #define	CSC_BYPASS_REG		0x000
    180 #define	 CSC_BYPASS_DISABLE			__BIT(0)
    181 #define	CSC_COEFF0_REG(n)	(0x10 + 0x10 * (n))
    182 #define	GLB_ALPHA_REG		0x040
    183 
    184 enum {
    185 	MIXER_PORT_OUTPUT = 1,
    186 };
    187 
    188 struct sunxi_mixer_compat_data {
    189 	uint8_t ovl_ui_count;
    190 	uint8_t mixer_index;
    191 };
    192 
    193 struct sunxi_mixer_compat_data mixer0_data = {
    194 	.ovl_ui_count = 3,
    195 	.mixer_index = 0,
    196 };
    197 
    198 struct sunxi_mixer_compat_data mixer1_data = {
    199 	.ovl_ui_count = 1,
    200 	.mixer_index = 1,
    201 };
    202 
    203 static const struct device_compatible_entry compat_data[] = {
    204 	{ .compat = "allwinner,sun8i-h3-de2-mixer-0",
    205 	  .data = &mixer0_data },
    206 	{ .compat = "allwinner,sun50i-a64-de2-mixer-0",
    207 	  .data = &mixer0_data },
    208 	{ .compat = "allwinner,sun50i-a64-de2-mixer-1",
    209 	  .data = &mixer1_data },
    210 
    211 	DEVICE_COMPAT_EOL
    212 };
    213 
    214 struct sunxi_mixer_softc;
    215 
    216 struct sunxi_mixer_crtc {
    217 	struct drm_crtc		base;
    218 	struct sunxi_mixer_softc *sc;
    219 };
    220 
    221 struct sunxi_mixer_plane {
    222 	struct drm_plane	base;
    223 	struct sunxi_mixer_softc *sc;
    224 };
    225 
    226 struct sunxi_mixer_softc {
    227 	device_t		sc_dev;
    228 	bus_space_tag_t		sc_bst;
    229 	bus_space_handle_t	sc_bsh;
    230 	int			sc_phandle;
    231 
    232 	u_int			sc_ovl_ui_count;
    233 
    234 	struct sunxi_mixer_crtc	sc_crtc;
    235 	struct sunxi_mixer_plane sc_overlay;
    236 
    237 	struct fdt_device_ports	sc_ports;
    238 };
    239 
    240 #define	GLB_READ(sc, reg)				\
    241 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, GLB_BASE + (reg))
    242 #define	GLB_WRITE(sc, reg, val)				\
    243 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, GLB_BASE + (reg), (val))
    244 
    245 #define	BLD_READ(sc, reg)				\
    246 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, BLD_BASE + (reg))
    247 #define	BLD_WRITE(sc, reg, val)				\
    248 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, BLD_BASE + (reg), (val))
    249 
    250 #define	OVL_V_READ(sc, reg)				\
    251 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg))
    252 #define	OVL_V_WRITE(sc, reg, val)			\
    253 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE(0) + (reg), (val))
    254 
    255 #define	OVL_UI_READ(sc, n, reg)				\
    256 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg))
    257 #define	OVL_UI_WRITE(sc, n, reg, val)			\
    258 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, OVL_BASE((n) + 1) + (reg), (val))
    259 
    260 #define	VSU_READ(sc, reg)				\
    261 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, VSU_BASE + (reg))
    262 #define	VSU_WRITE(sc, reg, val)			\
    263 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, VSU_BASE + (reg), (val))
    264 
    265 #define	CSC_READ(sc, n, reg)				\
    266 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, CSC_BASE(n) + (reg))
    267 #define	CSC_WRITE(sc, n, reg, val)			\
    268 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, CSC_BASE(n) + (reg), (val))
    269 
    270 #define	to_sunxi_mixer_crtc(x)		container_of(x, struct sunxi_mixer_crtc, base)
    271 #define	to_sunxi_mixer_plane(x)	container_of(x, struct sunxi_mixer_plane, base)
    272 
    273 static int
    274 sunxi_mixer_mode_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb,
    275     int x, int y, int atomic)
    276 {
    277 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    278 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    279 	struct sunxi_drm_framebuffer *sfb = atomic?
    280 	    to_sunxi_drm_framebuffer(fb) :
    281 	    to_sunxi_drm_framebuffer(crtc->primary->fb);
    282 	uint32_t val;
    283 
    284 	uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr;
    285 
    286 	paddr += y * sfb->base.pitches[0];
    287 	paddr += x * sfb->base.format->cpp[0];
    288 
    289 	uint32_t haddr = (paddr >> 32) & OVL_UI_TOP_HADD_LAYER0;
    290 	uint32_t laddr = paddr & 0xffffffff;
    291 
    292 	/* Set UI overlay line size */
    293 	OVL_UI_WRITE(sc, 0, OVL_UI_PITCH(0), sfb->base.pitches[0]);
    294 
    295 	/* Framebuffer start address */
    296 	val = OVL_UI_READ(sc, 0, OVL_UI_TOP_HADD);
    297 	val &= ~OVL_UI_TOP_HADD_LAYER0;
    298 	val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0);
    299 	OVL_UI_WRITE(sc, 0, OVL_UI_TOP_HADD, val);
    300 	OVL_UI_WRITE(sc, 0, OVL_UI_TOP_LADD(0), laddr);
    301 
    302 	return 0;
    303 }
    304 
    305 static void
    306 sunxi_mixer_destroy(struct drm_crtc *crtc)
    307 {
    308 	drm_crtc_cleanup(crtc);
    309 }
    310 
    311 static int
    312 sunxi_mixer_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
    313     struct drm_pending_vblank_event *event, uint32_t flags,
    314     struct drm_modeset_acquire_ctx *ctx)
    315 {
    316 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    317 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    318 	unsigned long irqflags;
    319 
    320 	drm_crtc_wait_one_vblank(crtc);
    321 
    322 	sunxi_mixer_mode_do_set_base(crtc, fb, 0, 0, true);
    323 
    324 	/* Commit settings */
    325 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    326 
    327 	if (event) {
    328 		spin_lock_irqsave(&crtc->dev->event_lock, irqflags);
    329 		drm_crtc_send_vblank_event(crtc, event);
    330 		spin_unlock_irqrestore(&crtc->dev->event_lock, irqflags);
    331 	}
    332 
    333 	return 0;
    334 }
    335 
    336 static int
    337 sunxi_mixer_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
    338     uint32_t handle, uint32_t width, uint32_t height)
    339 {
    340 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    341 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    342 	struct drm_gem_object *gem_obj = NULL;
    343 	struct drm_gem_cma_object *obj;
    344 	uint32_t val;
    345 	int error;
    346 
    347 	/* Only mixers with more than one UI layer can support hardware cursors */
    348 	if (sc->sc_ovl_ui_count <= 1)
    349 		return -EINVAL;
    350 
    351 	if (handle == 0) {
    352 		val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
    353 		val &= ~BLD_FILL_COLOR_CTL_P2_EN;
    354 		val |= BLD_FILL_COLOR_CTL_P2_FCEN;
    355 		BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
    356 
    357 		error = 0;
    358 		goto done;
    359 	}
    360 
    361 	/* Arbitrary limits, the hardware layer can do 8192x8192 */
    362 	if (width > MIXER_CURSOR_MAXWIDTH || height > MIXER_CURSOR_MAXHEIGHT) {
    363 		DRM_ERROR("Cursor dimension %ux%u not supported\n", width, height);
    364 		error = -EINVAL;
    365 		goto done;
    366 	}
    367 
    368 	gem_obj = drm_gem_object_lookup(file_priv, handle);
    369 	if (gem_obj == NULL) {
    370 		DRM_ERROR("Cannot find cursor object %#x for crtc %d\n",
    371 		    handle, drm_crtc_index(crtc));
    372 		error = -ENOENT;
    373 		goto done;
    374 	}
    375 	obj = to_drm_gem_cma_obj(gem_obj);
    376 
    377 	if (obj->base.size < width * height * 4) {
    378 		DRM_ERROR("Cursor buffer is too small\n");
    379 		error = -ENOMEM;
    380 		goto done;
    381 	}
    382 
    383 	uint64_t paddr = (uint64_t)obj->dmamap->dm_segs[0].ds_addr;
    384 	uint32_t haddr = (paddr >> 32) & OVL_UI_TOP_HADD_LAYER0;
    385 	uint32_t laddr = paddr & 0xffffffff;
    386 
    387 	/* Framebuffer start address */
    388 	val = OVL_UI_READ(sc, 1, OVL_UI_TOP_HADD);
    389 	val &= ~OVL_UI_TOP_HADD_LAYER0;
    390 	val |= __SHIFTIN(haddr, OVL_UI_TOP_HADD_LAYER0);
    391 	OVL_UI_WRITE(sc, 1, OVL_UI_TOP_HADD, val);
    392 	OVL_UI_WRITE(sc, 1, OVL_UI_TOP_LADD(0), laddr);
    393 
    394 	const uint32_t size = ((height - 1) << 16) | (width - 1);
    395 	const uint32_t offset = (crtc->cursor_y << 16) | crtc->cursor_x;
    396 	const uint32_t crtc_size = ((crtc->primary->fb->height - 1) << 16) |
    397 	    (crtc->primary->fb->width - 1);
    398 
    399 	/* Enable cursor in ARGB8888 mode */
    400 	val = OVL_UI_ATTR_CTL_LAY_EN |
    401 	      __SHIFTIN(OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888, OVL_UI_ATTR_CTL_LAY_FBFMT);
    402 	OVL_UI_WRITE(sc, 1, OVL_UI_ATTR_CTL(0), val);
    403 	/* Set UI overlay layer size */
    404 	OVL_UI_WRITE(sc, 1, OVL_UI_MBSIZE(0), size);
    405 	/* Set UI overlay offset */
    406 	OVL_UI_WRITE(sc, 1, OVL_UI_COOR(0), offset);
    407 	/* Set UI overlay line size */
    408 	OVL_UI_WRITE(sc, 1, OVL_UI_PITCH(0), width * 4);
    409 	/* Set UI overlay window size */
    410 	OVL_UI_WRITE(sc, 1, OVL_UI_SIZE, crtc_size);
    411 
    412 	/* Set blender 2 input size */
    413 	BLD_WRITE(sc, BLD_CH_ISIZE(2), crtc_size);
    414 	/* Set blender 2 offset */
    415 	BLD_WRITE(sc, BLD_CH_OFFSET(2), 0);
    416 	/* Route channel 2 to pipe 2 */
    417 	val = BLD_READ(sc, BLD_CH_RTCTL);
    418 	val &= ~BLD_CH_RTCTL_P2;
    419 	val |= __SHIFTIN(2, BLD_CH_RTCTL_P2);
    420 	BLD_WRITE(sc, BLD_CH_RTCTL, val);
    421 
    422 	/* Enable pipe 2 */
    423 	val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
    424 	val |= BLD_FILL_COLOR_CTL_P2_EN;
    425 	val &= ~BLD_FILL_COLOR_CTL_P2_FCEN;
    426 	BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
    427 
    428 	error = 0;
    429 
    430 done:
    431 	if (error == 0) {
    432 		/* Commit settings */
    433 		GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    434 	}
    435 
    436 	if (gem_obj != NULL)
    437 		drm_gem_object_put_unlocked(gem_obj);
    438 
    439 	return error;
    440 }
    441 
    442 static int
    443 sunxi_mixer_cursor_move(struct drm_crtc *crtc, int x, int y)
    444 {
    445 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    446 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    447 
    448 	crtc->cursor_x = x & 0xffff;
    449 	crtc->cursor_y = y & 0xffff;
    450 
    451 	const uint32_t offset = (crtc->cursor_y << 16) | crtc->cursor_x;
    452 
    453 	OVL_UI_WRITE(sc, 1, OVL_UI_COOR(0), offset);
    454 
    455 	/* Commit settings */
    456 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    457 
    458 	return 0;
    459 }
    460 
    461 static const struct drm_crtc_funcs sunxi_mixer0_crtc_funcs = {
    462 	.set_config = drm_crtc_helper_set_config,
    463 	.destroy = sunxi_mixer_destroy,
    464 	.page_flip = sunxi_mixer_page_flip,
    465 	.cursor_set = sunxi_mixer_cursor_set,
    466 	.cursor_move = sunxi_mixer_cursor_move,
    467 };
    468 
    469 static const struct drm_crtc_funcs sunxi_mixer1_crtc_funcs = {
    470 	.set_config = drm_crtc_helper_set_config,
    471 	.destroy = sunxi_mixer_destroy,
    472 	.page_flip = sunxi_mixer_page_flip,
    473 };
    474 
    475 static void
    476 sunxi_mixer_dpms(struct drm_crtc *crtc, int mode)
    477 {
    478 }
    479 
    480 static bool
    481 sunxi_mixer_mode_fixup(struct drm_crtc *crtc,
    482     const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
    483 {
    484 	return true;
    485 }
    486 
    487 static int
    488 sunxi_mixer_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
    489     struct drm_display_mode *adjusted_mode, int x, int y,
    490     struct drm_framebuffer *old_fb)
    491 {
    492 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    493 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    494 	uint32_t val;
    495 	u_int fbfmt;
    496 
    497 	const uint32_t size = ((adjusted_mode->vdisplay - 1) << 16) |
    498 			      (adjusted_mode->hdisplay - 1);
    499 
    500 	/* Set global size */
    501 	GLB_WRITE(sc, GLB_SIZE, size);
    502 
    503 	/* Enable pipe 0 */
    504 	val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
    505 	val |= BLD_FILL_COLOR_CTL_P0_EN;
    506 	BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
    507 
    508 	/* Set blender 0 input size */
    509 	BLD_WRITE(sc, BLD_CH_ISIZE(0), size);
    510 	/* Set blender 0 offset */
    511 	BLD_WRITE(sc, BLD_CH_OFFSET(0), 0);
    512 	/* Route channel 1 to pipe 0 */
    513 	val = BLD_READ(sc, BLD_CH_RTCTL);
    514 	val &= ~BLD_CH_RTCTL_P0;
    515 	val |= __SHIFTIN(1, BLD_CH_RTCTL_P0);
    516 	BLD_WRITE(sc, BLD_CH_RTCTL, val);
    517 	/* Set blender output size */
    518 	BLD_WRITE(sc, BLD_SIZE, size);
    519 
    520 	/* Enable UI overlay */
    521 	if (crtc->primary->fb->format->format == DRM_FORMAT_XRGB8888)
    522 		fbfmt = OVL_UI_ATTR_CTL_LAY_FBFMT_XRGB_8888;
    523 	else
    524 		fbfmt = OVL_UI_ATTR_CTL_LAY_FBFMT_ARGB_8888;
    525 	val = OVL_UI_ATTR_CTL_LAY_EN | __SHIFTIN(fbfmt, OVL_UI_ATTR_CTL_LAY_FBFMT);
    526 	OVL_UI_WRITE(sc, 0, OVL_UI_ATTR_CTL(0), val);
    527 	/* Set UI overlay layer size */
    528 	OVL_UI_WRITE(sc, 0, OVL_UI_MBSIZE(0), size);
    529 	/* Set UI overlay offset */
    530 	OVL_UI_WRITE(sc, 0, OVL_UI_COOR(0), 0);
    531 	/* Set UI overlay window size */
    532 	OVL_UI_WRITE(sc, 0, OVL_UI_SIZE, size);
    533 
    534 	sunxi_mixer_mode_do_set_base(crtc, old_fb, x, y, 0);
    535 
    536 	return 0;
    537 }
    538 
    539 static int
    540 sunxi_mixer_mode_set_base(struct drm_crtc *crtc, int x, int y,
    541     struct drm_framebuffer *old_fb)
    542 {
    543 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    544 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    545 
    546 	sunxi_mixer_mode_do_set_base(crtc, old_fb, x, y, 0);
    547 
    548 	/* Commit settings */
    549 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    550 
    551 	return 0;
    552 }
    553 
    554 static int
    555 sunxi_mixer_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
    556     int x, int y, enum mode_set_atomic state)
    557 {
    558 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    559 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    560 
    561 	sunxi_mixer_mode_do_set_base(crtc, fb, x, y, 1);
    562 
    563 	/* Commit settings */
    564 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    565 
    566 	return 0;
    567 }
    568 
    569 static void
    570 sunxi_mixer_disable(struct drm_crtc *crtc)
    571 {
    572 }
    573 
    574 static void
    575 sunxi_mixer_prepare(struct drm_crtc *crtc)
    576 {
    577 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    578 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    579 
    580 	/* RT enable */
    581 	GLB_WRITE(sc, GLB_CTL, GLB_CTL_EN);
    582 }
    583 
    584 static void
    585 sunxi_mixer_commit(struct drm_crtc *crtc)
    586 {
    587 	struct sunxi_mixer_crtc *mixer_crtc = to_sunxi_mixer_crtc(crtc);
    588 	struct sunxi_mixer_softc * const sc = mixer_crtc->sc;
    589 
    590 	/* Commit settings */
    591 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
    592 }
    593 
    594 static const struct drm_crtc_helper_funcs sunxi_mixer_crtc_helper_funcs = {
    595 	.dpms = sunxi_mixer_dpms,
    596 	.mode_fixup = sunxi_mixer_mode_fixup,
    597 	.mode_set = sunxi_mixer_mode_set,
    598 	.mode_set_base = sunxi_mixer_mode_set_base,
    599 	.mode_set_base_atomic = sunxi_mixer_mode_set_base_atomic,
    600 	.disable = sunxi_mixer_disable,
    601 	.prepare = sunxi_mixer_prepare,
    602 	.commit = sunxi_mixer_commit,
    603 };
    604 
    605 static void
    606 sunxi_mixer_overlay_destroy(struct drm_plane *plane)
    607 {
    608 }
    609 
    610 static bool
    611 sunxi_mixer_overlay_rgb(uint32_t drm_format)
    612 {
    613 	switch (drm_format) {
    614 	case DRM_FORMAT_ARGB8888:
    615 	case DRM_FORMAT_XRGB8888:
    616 		return true;
    617 	default:
    618 		return false;
    619 	}
    620 }
    621 
    622 static u_int
    623 sunxi_mixer_overlay_format(uint32_t drm_format)
    624 {
    625 	switch (drm_format) {
    626 	case DRM_FORMAT_ARGB8888:	return OVL_V_ATTCTL_LAY_FBFMT_ARGB_8888;
    627 	case DRM_FORMAT_XRGB8888:	return OVL_V_ATTCTL_LAY_FBFMT_XRGB_8888;
    628 	case DRM_FORMAT_VYUY:		return OVL_V_ATTCTL_LAY_FBFMT_VYUY;
    629 	case DRM_FORMAT_YVYU:		return OVL_V_ATTCTL_LAY_FBFMT_YVYU;
    630 	case DRM_FORMAT_UYVY:		return OVL_V_ATTCTL_LAY_FBFMT_UYVY;
    631 	case DRM_FORMAT_YUYV:		return OVL_V_ATTCTL_LAY_FBFMT_YUYV;
    632 	case DRM_FORMAT_YUV422:		return OVL_V_ATTCTL_LAY_FBFMT_YUV422;
    633 	case DRM_FORMAT_YUV420:		return OVL_V_ATTCTL_LAY_FBFMT_YUV420;
    634 	case DRM_FORMAT_YUV411:		return OVL_V_ATTCTL_LAY_FBFMT_YUV411;
    635 	default:			return 0;	/* shouldn't happen */
    636 	}
    637 }
    638 
    639 static const uint32_t lan3coefftab32_left[512] = {
    640 	0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100,
    641 	0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200,
    642 	0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200,
    643 	0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200,
    644 	0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100,
    645 	0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100,
    646 	0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000,
    647 	0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000,
    648 
    649 	0x40000000, 0x40fe0000, 0x3ffd0100, 0x3efc0100,
    650 	0x3efb0100, 0x3dfa0200, 0x3cf90200, 0x3bf80200,
    651 	0x39f70200, 0x37f70200, 0x35f70200, 0x33f70200,
    652 	0x31f70200, 0x2ef70200, 0x2cf70200, 0x2af70200,
    653 	0x27f70200, 0x24f80100, 0x22f80100, 0x1ef90100,
    654 	0x1cf90100, 0x19fa0100, 0x17fa0100, 0x14fb0100,
    655 	0x11fc0000, 0x0ffc0000, 0x0cfd0000, 0x0afd0000,
    656 	0x08fe0000, 0x05ff0000, 0x03ff0000, 0x02000000,
    657 
    658 	0x3806fc02, 0x3805fc02, 0x3803fd01, 0x3801fe01,
    659 	0x3700fe01, 0x35ffff01, 0x35fdff01, 0x34fc0001,
    660 	0x34fb0000, 0x33fa0000, 0x31fa0100, 0x2ff90100,
    661 	0x2df80200, 0x2bf80200, 0x2af70200, 0x28f70200,
    662 	0x27f70200, 0x24f70300, 0x22f70300, 0x1ff70300,
    663 	0x1ef70300, 0x1cf70300, 0x1af70300, 0x18f70300,
    664 	0x16f80300, 0x13f80300, 0x11f90300, 0x0ef90300,
    665 	0x0efa0200, 0x0cfa0200, 0x0afb0200, 0x08fb0200,
    666 
    667 	0x320bfa02, 0x3309fa02, 0x3208fb02, 0x3206fb02,
    668 	0x3205fb02, 0x3104fc02, 0x3102fc01, 0x3001fd01,
    669 	0x3000fd01, 0x2ffffd01, 0x2efefe01, 0x2dfdfe01,
    670 	0x2bfcff01, 0x29fcff01, 0x28fbff01, 0x27fa0001,
    671 	0x26fa0000, 0x24f90000, 0x22f90100, 0x20f90100,
    672 	0x1ff80100, 0x1ef80100, 0x1cf80100, 0x1af80200,
    673 	0x18f80200, 0x17f80200, 0x15f80200, 0x12f80200,
    674 	0x11f90200, 0x0ff90200, 0x0df90200, 0x0cfa0200,
    675 
    676 	0x2e0efa01, 0x2f0dfa01, 0x2f0bfa01, 0x2e0afa01,
    677 	0x2e09fa01, 0x2e07fb01, 0x2d06fb01, 0x2d05fb01,
    678 	0x2c04fb01, 0x2b03fc01, 0x2a02fc01, 0x2a01fc01,
    679 	0x2800fd01, 0x28fffd01, 0x26fefd01, 0x25fefe01,
    680 	0x24fdfe01, 0x23fcfe01, 0x21fcff01, 0x20fbff01,
    681 	0x1efbff01, 0x1efbff00, 0x1cfa0000, 0x1bfa0000,
    682 	0x19fa0000, 0x18fa0000, 0x17f90000, 0x15f90100,
    683 	0x14f90100, 0x12f90100, 0x11f90100, 0x0ff90100,
    684 
    685 	0x2b10fa00, 0x2b0ffa00, 0x2b0efa00, 0x2b0cfa00,
    686 	0x2b0bfa00, 0x2a0afb01, 0x2a09fb01, 0x2908fb01,
    687 	0x2807fb01, 0x2806fb01, 0x2805fb01, 0x2604fc01,
    688 	0x2503fc01, 0x2502fc01, 0x2401fc01, 0x2301fc01,
    689 	0x2100fd01, 0x21fffd01, 0x21fffd01, 0x20fefd01,
    690 	0x1dfefe01, 0x1cfdfe01, 0x1cfdfe00, 0x1bfcfe00,
    691 	0x19fcff00, 0x19fbff00, 0x17fbff00, 0x16fbff00,
    692 	0x15fbff00, 0x14fb0000, 0x13fa0000, 0x11fa0000,
    693 
    694 	0x2811fcff, 0x2810fcff, 0x280ffbff, 0x280efbff,
    695 	0x270dfb00, 0x270cfb00, 0x270bfb00, 0x260afb00,
    696 	0x2609fb00, 0x2508fb00, 0x2507fb00, 0x2407fb00,
    697 	0x2406fc00, 0x2305fc00, 0x2204fc00, 0x2203fc00,
    698 	0x2103fc00, 0x2002fc00, 0x1f01fd00, 0x1e01fd00,
    699 	0x1d00fd00, 0x1dfffd00, 0x1cfffd00, 0x1bfefd00,
    700 	0x1afefe00, 0x19fefe00, 0x18fdfe00, 0x17fdfe00,
    701 	0x16fdfe00, 0x15fcff00, 0x13fcff00, 0x12fcff00,
    702 
    703 	0x2512fdfe, 0x2511fdff, 0x2410fdff, 0x240ffdff,
    704 	0x240efcff, 0x240dfcff, 0x240dfcff, 0x240cfcff,
    705 	0x230bfcff, 0x230afc00, 0x2209fc00, 0x2108fc00,
    706 	0x2108fc00, 0x2007fc00, 0x2006fc00, 0x2005fc00,
    707 	0x1f05fc00, 0x1e04fc00, 0x1e03fc00, 0x1c03fd00,
    708 	0x1c02fd00, 0x1b02fd00, 0x1b01fd00, 0x1a00fd00,
    709 	0x1900fd00, 0x1800fd00, 0x17fffe00, 0x16fffe00,
    710 	0x16fefe00, 0x14fefe00, 0x13fefe00, 0x13fdfe00,
    711 
    712 	0x2212fffe, 0x2211fefe, 0x2211fefe, 0x2110fefe,
    713 	0x210ffeff, 0x220efdff, 0x210dfdff, 0x210dfdff,
    714 	0x210cfdff, 0x210bfdff, 0x200afdff, 0x200afdff,
    715 	0x1f09fdff, 0x1f08fdff, 0x1d08fd00, 0x1c07fd00,
    716 	0x1d06fd00, 0x1b06fd00, 0x1b05fd00, 0x1c04fd00,
    717 	0x1b04fd00, 0x1a03fd00, 0x1a03fd00, 0x1902fd00,
    718 	0x1802fd00, 0x1801fd00, 0x1701fd00, 0x1600fd00,
    719 	0x1400fe00, 0x1400fe00, 0x14fffe00, 0x13fffe00,
    720 
    721 	0x201200fe, 0x201100fe, 0x1f11fffe, 0x2010fffe,
    722 	0x1f0ffffe, 0x1e0ffffe, 0x1f0efeff, 0x1f0dfeff,
    723 	0x1f0dfeff, 0x1e0cfeff, 0x1e0bfeff, 0x1d0bfeff,
    724 	0x1d0afeff, 0x1d09fdff, 0x1d09fdff, 0x1c08fdff,
    725 	0x1c07fdff, 0x1b07fd00, 0x1b06fd00, 0x1a06fd00,
    726 	0x1a05fd00, 0x1805fd00, 0x1904fd00, 0x1804fd00,
    727 	0x1703fd00, 0x1703fd00, 0x1602fe00, 0x1502fe00,
    728 	0x1501fe00, 0x1401fe00, 0x1301fe00, 0x1300fe00,
    729 
    730 	0x1c1202fe, 0x1c1102fe, 0x1b1102fe, 0x1c1001fe,
    731 	0x1b1001fe, 0x1b0f01ff, 0x1b0e00ff, 0x1b0e00ff,
    732 	0x1b0d00ff, 0x1a0d00ff, 0x1a0c00ff, 0x1a0cffff,
    733 	0x1a0bffff, 0x1a0bffff, 0x1a0affff, 0x180affff,
    734 	0x1909ffff, 0x1809ffff, 0x1808ffff, 0x1808feff,
    735 	0x1807feff, 0x1707fe00, 0x1606fe00, 0x1506fe00,
    736 	0x1605fe00, 0x1505fe00, 0x1504fe00, 0x1304fe00,
    737 	0x1304fe00, 0x1303fe00, 0x1203fe00, 0x1203fe00,
    738 
    739 	0x181104ff, 0x191103ff, 0x191003ff, 0x181003ff,
    740 	0x180f03ff, 0x190f02ff, 0x190e02ff, 0x180e02ff,
    741 	0x180d02ff, 0x180d01ff, 0x180d01ff, 0x180c01ff,
    742 	0x180c01ff, 0x180b00ff, 0x170b00ff, 0x170a00ff,
    743 	0x170a00ff, 0x170900ff, 0x160900ff, 0x160900ff,
    744 	0x1608ffff, 0x1508ffff, 0x1507ff00, 0x1507ff00,
    745 	0x1407ff00, 0x1306ff00, 0x1306ff00, 0x1305ff00,
    746 	0x1205ff00, 0x1105ff00, 0x1204ff00, 0x1104ff00,
    747 
    748 	0x171005ff, 0x171005ff, 0x171004ff, 0x170f04ff,
    749 	0x160f04ff, 0x170f03ff, 0x170e03ff, 0x160e03ff,
    750 	0x160d03ff, 0x160d02ff, 0x160d02ff, 0x160c02ff,
    751 	0x160c02ff, 0x160c02ff, 0x160b01ff, 0x150b01ff,
    752 	0x150a01ff, 0x150a01ff, 0x150a01ff, 0x140901ff,
    753 	0x14090000, 0x14090000, 0x14080000, 0x13080000,
    754 	0x13070000, 0x12070000, 0x12070000, 0x12060000,
    755 	0x11060000, 0x11060000, 0x11050000, 0x1105ff00,
    756 
    757 	0x14100600, 0x15100500, 0x150f0500, 0x150f0500,
    758 	0x140f0500, 0x150e0400, 0x140e0400, 0x130e0400,
    759 	0x140d0400, 0x150d0300, 0x130d0300, 0x140c0300,
    760 	0x140c0300, 0x140c0200, 0x140b0200, 0x130b0200,
    761 	0x120b0200, 0x130a0200, 0x130a0200, 0x130a0100,
    762 	0x13090100, 0x12090100, 0x11090100, 0x12080100,
    763 	0x11080100, 0x10080100, 0x11070100, 0x11070000,
    764 	0x10070000, 0x11060000, 0x10060000, 0x10060000,
    765 
    766 	0x140f0600, 0x140f0600, 0x130f0600, 0x140f0500,
    767 	0x140e0500, 0x130e0500, 0x130e0500, 0x140d0400,
    768 	0x140d0400, 0x130d0400, 0x120d0400, 0x130c0400,
    769 	0x130c0300, 0x130c0300, 0x130b0300, 0x130b0300,
    770 	0x110b0300, 0x130a0200, 0x120a0200, 0x120a0200,
    771 	0x120a0200, 0x12090200, 0x10090200, 0x11090100,
    772 	0x11080100, 0x11080100, 0x10080100, 0x10080100,
    773 	0x10070100, 0x10070100, 0x0f070100, 0x10060100,
    774 
    775 	0x120f0701, 0x130f0601, 0x130e0601, 0x130e0601,
    776 	0x120e0601, 0x130e0501, 0x130e0500, 0x130d0500,
    777 	0x120d0500, 0x120d0500, 0x130c0400, 0x130c0400,
    778 	0x120c0400, 0x110c0400, 0x120b0400, 0x120b0300,
    779 	0x120b0300, 0x120b0300, 0x120a0300, 0x110a0300,
    780 	0x110a0200, 0x11090200, 0x11090200, 0x10090200,
    781 	0x10090200, 0x10080200, 0x10080200, 0x10080100,
    782 	0x0f080100, 0x10070100, 0x0f070100, 0x0f070100
    783 };
    784 
    785 static const uint32_t lan3coefftab32_right[512] = {
    786 	0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06,
    787 	0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f,
    788 	0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19,
    789 	0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824,
    790 	0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f,
    791 	0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737,
    792 	0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d,
    793 	0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40,
    794 
    795 	0x00000000, 0x00000002, 0x0000ff04, 0x0000ff06,
    796 	0x0000fe08, 0x0000fd0a, 0x0000fd0c, 0x0000fc0f,
    797 	0x0000fc12, 0x0001fb14, 0x0001fa17, 0x0001fa19,
    798 	0x0001f91c, 0x0001f91f, 0x0001f822, 0x0001f824,
    799 	0x0002f727, 0x0002f72a, 0x0002f72c, 0x0002f72f,
    800 	0x0002f731, 0x0002f733, 0x0002f735, 0x0002f737,
    801 	0x0002f73a, 0x0002f83b, 0x0002f93c, 0x0002fa3d,
    802 	0x0001fb3e, 0x0001fc3f, 0x0001fd40, 0x0000fe40,
    803 
    804 	0x0002fc06, 0x0002fb08, 0x0002fb0a, 0x0002fa0c,
    805 	0x0002fa0e, 0x0003f910, 0x0003f912, 0x0003f814,
    806 	0x0003f816, 0x0003f719, 0x0003f71a, 0x0003f71d,
    807 	0x0003f71f, 0x0003f721, 0x0003f723, 0x0003f725,
    808 	0x0002f727, 0x0002f729, 0x0002f72b, 0x0002f82d,
    809 	0x0002f82e, 0x0001f930, 0x0001fa31, 0x0000fa34,
    810 	0x0000fb34, 0x0100fc35, 0x01fffd36, 0x01ffff37,
    811 	0x01fe0037, 0x01fe0138, 0x01fd0338, 0x02fc0538,
    812 
    813 	0x0002fa0b, 0x0002fa0c, 0x0002f90e, 0x0002f910,
    814 	0x0002f911, 0x0002f813, 0x0002f816, 0x0002f817,
    815 	0x0002f818, 0x0002f81a, 0x0001f81c, 0x0001f81e,
    816 	0x0001f820, 0x0001f921, 0x0001f923, 0x0000f925,
    817 	0x0000fa26, 0x0100fa28, 0x01fffb29, 0x01fffc2a,
    818 	0x01fffc2c, 0x01fefd2d, 0x01fefe2e, 0x01fdff2f,
    819 	0x01fd0030, 0x01fd0130, 0x01fc0232, 0x02fc0432,
    820 	0x02fb0532, 0x02fb0633, 0x02fb0833, 0x02fa0933,
    821 
    822 	0x0001fa0e, 0x0001f90f, 0x0001f911, 0x0001f913,
    823 	0x0001f914, 0x0001f915, 0x0000f918, 0x0000fa18,
    824 	0x0000fa1a, 0x0000fa1b, 0x0000fa1d, 0x00fffb1e,
    825 	0x01fffb1f, 0x01fffb20, 0x01fffc22, 0x01fefc23,
    826 	0x01fefd24, 0x01fefe25, 0x01fdfe27, 0x01fdff28,
    827 	0x01fd0029, 0x01fc012a, 0x01fc022b, 0x01fc032b,
    828 	0x01fb042d, 0x01fb052d, 0x01fb062e, 0x01fb072e,
    829 	0x01fa092e, 0x01fa0a2f, 0x01fa0b2f, 0x01fa0d2f,
    830 
    831 	0x0000fa11, 0x0000fa12, 0x0000fa13, 0x0000fb14,
    832 	0x00fffb16, 0x00fffb16, 0x00fffb17, 0x00fffb19,
    833 	0x00fffc1a, 0x00fefc1c, 0x00fefd1c, 0x01fefd1d,
    834 	0x01fefe1e, 0x01fdfe20, 0x01fdff21, 0x01fdff22,
    835 	0x01fd0023, 0x01fc0124, 0x01fc0124, 0x01fc0225,
    836 	0x01fc0326, 0x01fc0427, 0x01fb0528, 0x01fb0629,
    837 	0x01fb0729, 0x01fb0829, 0x01fb092a, 0x01fb0a2a,
    838 	0x00fa0b2c, 0x00fa0c2b, 0x00fa0e2b, 0x00fa0f2c,
    839 
    840 	0x00fffc11, 0x00fffc12, 0x00fffc14, 0x00fffc15,
    841 	0x00fefd16, 0x00fefd17, 0x00fefd18, 0x00fefe19,
    842 	0x00fefe1a, 0x00fdfe1d, 0x00fdff1d, 0x00fdff1e,
    843 	0x00fd001d, 0x00fd011e, 0x00fd0120, 0x00fc0221,
    844 	0x00fc0321, 0x00fc0323, 0x00fc0423, 0x00fc0523,
    845 	0x00fc0624, 0x00fb0725, 0x00fb0726, 0x00fb0827,
    846 	0x00fb0926, 0x00fb0a26, 0x00fb0b27, 0x00fb0c27,
    847 	0x00fb0d27, 0xfffb0e28, 0xfffb0f29, 0xfffc1028,
    848 
    849 	0x00fefd13, 0x00fefd13, 0x00fefe14, 0x00fefe15,
    850 	0x00fefe17, 0x00feff17, 0x00feff17, 0x00fd0018,
    851 	0x00fd001a, 0x00fd001a, 0x00fd011b, 0x00fd021c,
    852 	0x00fd021c, 0x00fd031d, 0x00fc031f, 0x00fc041f,
    853 	0x00fc051f, 0x00fc0521, 0x00fc0621, 0x00fc0721,
    854 	0x00fc0821, 0x00fc0822, 0x00fc0922, 0x00fc0a23,
    855 	0xfffc0b24, 0xfffc0c24, 0xfffc0d24, 0xfffc0d25,
    856 	0xfffc0e25, 0xfffd0f25, 0xfffd1025, 0xfffd1125,
    857 
    858 	0x00feff12, 0x00feff14, 0x00feff14, 0x00fe0015,
    859 	0x00fe0015, 0x00fd0017, 0x00fd0118, 0x00fd0118,
    860 	0x00fd0218, 0x00fd0219, 0x00fd031a, 0x00fd031a,
    861 	0x00fd041b, 0x00fd041c, 0x00fd051c, 0x00fd061d,
    862 	0x00fd061d, 0x00fd071e, 0x00fd081e, 0xfffd081f,
    863 	0xfffd091f, 0xfffd0a20, 0xfffd0a20, 0xfffd0b21,
    864 	0xfffd0c21, 0xfffd0d21, 0xfffd0d22, 0xfffd0e23,
    865 	0xfffe0f22, 0xfefe1022, 0xfefe1122, 0xfefe1123,
    866 
    867 	0x00fe0012, 0x00fe0013, 0x00fe0114, 0x00fe0114,
    868 	0x00fe0116, 0x00fe0216, 0x00fe0216, 0x00fd0317,
    869 	0x00fd0317, 0x00fd0418, 0x00fd0419, 0x00fd0519,
    870 	0x00fd051a, 0x00fd061b, 0x00fd061b, 0x00fd071c,
    871 	0xfffd071e, 0xfffd081d, 0xfffd091d, 0xfffd091e,
    872 	0xfffe0a1d, 0xfffe0b1e, 0xfffe0b1e, 0xfffe0c1e,
    873 	0xfffe0d1f, 0xfffe0d1f, 0xfffe0e1f, 0xfeff0f1f,
    874 	0xfeff0f20, 0xfeff1020, 0xfeff1120, 0xfe001120,
    875 
    876 	0x00fe0212, 0x00fe0312, 0x00fe0313, 0x00fe0314,
    877 	0x00fe0414, 0x00fe0414, 0x00fe0416, 0x00fe0515,
    878 	0x00fe0516, 0x00fe0616, 0x00fe0617, 0x00fe0717,
    879 	0xfffe0719, 0xfffe0818, 0xffff0818, 0xffff0919,
    880 	0xffff0919, 0xffff0a19, 0xffff0a1a, 0xffff0b1a,
    881 	0xffff0b1b, 0xffff0c1a, 0xff000c1b, 0xff000d1b,
    882 	0xff000d1b, 0xff000e1b, 0xff000e1c, 0xff010f1c,
    883 	0xfe01101c, 0xfe01101d, 0xfe02111c, 0xfe02111c,
    884 
    885 	0x00ff0411, 0x00ff0411, 0x00ff0412, 0x00ff0512,
    886 	0x00ff0513, 0x00ff0513, 0x00ff0613, 0x00ff0614,
    887 	0x00ff0714, 0x00ff0715, 0x00ff0715, 0xffff0816,
    888 	0xffff0816, 0xff000916, 0xff000917, 0xff000918,
    889 	0xff000a17, 0xff000a18, 0xff000b18, 0xff000b18,
    890 	0xff010c18, 0xff010c19, 0xff010d18, 0xff010d18,
    891 	0xff020d18, 0xff020e19, 0xff020e19, 0xff020f19,
    892 	0xff030f19, 0xff031019, 0xff031019, 0xff031119,
    893 
    894 	0x00ff0511, 0x00ff0511, 0x00000511, 0x00000611,
    895 	0x00000612, 0x00000612, 0x00000712, 0x00000713,
    896 	0x00000714, 0x00000814, 0x00000814, 0x00000914,
    897 	0x00000914, 0xff010914, 0xff010a15, 0xff010a16,
    898 	0xff010a17, 0xff010b16, 0xff010b16, 0xff020c16,
    899 	0xff020c16, 0xff020c16, 0xff020d16, 0xff020d17,
    900 	0xff030d17, 0xff030e17, 0xff030e17, 0xff030f17,
    901 	0xff040f17, 0xff040f17, 0xff041017, 0xff051017,
    902 
    903 	0x00000610, 0x00000610, 0x00000611, 0x00000611,
    904 	0x00000711, 0x00000712, 0x00010712, 0x00010812,
    905 	0x00010812, 0x00010812, 0x00010913, 0x00010913,
    906 	0x00010913, 0x00010a13, 0x00020a13, 0x00020a14,
    907 	0x00020b14, 0x00020b14, 0x00020b14, 0x00020c14,
    908 	0x00030c14, 0x00030c15, 0x00030d15, 0x00030d15,
    909 	0x00040d15, 0x00040e15, 0x00040e15, 0x00040e16,
    910 	0x00050f15, 0x00050f15, 0x00050f16, 0x00051015,
    911 
    912 	0x00000611, 0x00010610, 0x00010710, 0x00010710,
    913 	0x00010711, 0x00010811, 0x00010811, 0x00010812,
    914 	0x00010812, 0x00010912, 0x00020912, 0x00020912,
    915 	0x00020a12, 0x00020a12, 0x00020a13, 0x00020a13,
    916 	0x00030b13, 0x00030b13, 0x00030b14, 0x00030c13,
    917 	0x00030c13, 0x00040c13, 0x00040d14, 0x00040d14,
    918 	0x00040d15, 0x00040d15, 0x00050e14, 0x00050e14,
    919 	0x00050e15, 0x00050f14, 0x00060f14, 0x00060f14,
    920 
    921 	0x0001070f, 0x0001070f, 0x00010710, 0x00010710,
    922 	0x00010810, 0x00010810, 0x00020810, 0x00020811,
    923 	0x00020911, 0x00020911, 0x00020912, 0x00020912,
    924 	0x00020a12, 0x00030a12, 0x00030a12, 0x00030b12,
    925 	0x00030b12, 0x00030b12, 0x00040b12, 0x00040c12,
    926 	0x00040c13, 0x00040c14, 0x00040c14, 0x00050d13,
    927 	0x00050d13, 0x00050d14, 0x00050e13, 0x01050e13,
    928 	0x01060e13, 0x01060e13, 0x01060e14, 0x01060f13
    929 };
    930 
    931 static const uint32_t lan2coefftab32[512] = {
    932 	0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
    933 	0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
    934 	0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
    935 	0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
    936 
    937 	0x00004000, 0x000140ff, 0x00033ffe, 0x00043ffd, 0x00063efc, 0xff083dfc, 0x000a3bfb, 0xff0d39fb,
    938 	0xff0f37fb, 0xff1136fa, 0xfe1433fb, 0xfe1631fb, 0xfd192ffb, 0xfd1c2cfb, 0xfd1f29fb, 0xfc2127fc,
    939 	0xfc2424fc, 0xfc2721fc, 0xfb291ffd, 0xfb2c1cfd, 0xfb2f19fd, 0xfb3116fe, 0xfb3314fe, 0xfa3611ff,
    940 	0xfb370fff, 0xfb390dff, 0xfb3b0a00, 0xfc3d08ff, 0xfc3e0600, 0xfd3f0400, 0xfe3f0300, 0xff400100,
    941 
    942 	0xff053804, 0xff063803, 0xff083801, 0xff093701, 0xff0a3700, 0xff0c3500, 0xff0e34ff, 0xff1033fe,
    943 	0xff1232fd, 0xfe1431fd, 0xfe162ffd, 0xfe182dfd, 0xfd1b2cfc, 0xfd1d2afc, 0xfd1f28fc, 0xfd2126fc,
    944 	0xfd2323fd, 0xfc2621fd, 0xfc281ffd, 0xfc2a1dfd, 0xfc2c1bfd, 0xfd2d18fe, 0xfd2f16fe, 0xfd3114fe,
    945 	0xfd3212ff, 0xfe3310ff, 0xff340eff, 0x00350cff, 0x00360a00, 0x01360900, 0x02370700, 0x03370600,
    946 
    947 	0xff083207, 0xff093206, 0xff0a3205, 0xff0c3203, 0xff0d3103, 0xff0e3102, 0xfe113001, 0xfe132f00,
    948 	0xfe142e00, 0xfe162dff, 0xfe182bff, 0xfe192aff, 0xfe1b29fe, 0xfe1d27fe, 0xfe1f25fe, 0xfd2124fe,
    949 	0xfe2222fe, 0xfe2421fd, 0xfe251ffe, 0xfe271dfe, 0xfe291bfe, 0xff2a19fe, 0xff2b18fe, 0xff2d16fe,
    950 	0x002e14fe, 0x002f12ff, 0x013010ff, 0x02300fff, 0x03310dff, 0x04310cff, 0x05310a00, 0x06310900,
    951 
    952 	0xff0a2e09, 0xff0b2e08, 0xff0c2e07, 0xff0e2d06, 0xff0f2d05, 0xff102d04, 0xff122c03, 0xfe142c02,
    953 	0xfe152b02, 0xfe172a01, 0xfe182901, 0xfe1a2800, 0xfe1b2700, 0xfe1d2500, 0xff1e24ff, 0xfe2023ff,
    954 	0xff2121ff, 0xff2320fe, 0xff241eff, 0x00251dfe, 0x00261bff, 0x00281afe, 0x012818ff, 0x012a16ff,
    955 	0x022a15ff, 0x032b13ff, 0x032c12ff, 0x052c10ff, 0x052d0fff, 0x062d0d00, 0x072d0c00, 0x082d0b00,
    956 
    957 	0xff0c2a0b, 0xff0d2a0a, 0xff0e2a09, 0xff0f2a08, 0xff102a07, 0xff112a06, 0xff132905, 0xff142904,
    958 	0xff162803, 0xff172703, 0xff182702, 0xff1a2601, 0xff1b2501, 0xff1c2401, 0xff1e2300, 0xff1f2200,
    959 	0x00202000, 0x00211f00, 0x01221d00, 0x01231c00, 0x01251bff, 0x02251aff, 0x032618ff, 0x032717ff,
    960 	0x042815ff, 0x052814ff, 0x052913ff, 0x06291100, 0x072a10ff, 0x082a0e00, 0x092a0d00, 0x0a2a0c00,
    961 
    962 	0xff0d280c, 0xff0e280b, 0xff0f280a, 0xff102809, 0xff112808, 0xff122708, 0xff142706, 0xff152705,
    963 	0xff162605, 0xff172604, 0xff192503, 0xff1a2403, 0x001b2302, 0x001c2202, 0x001d2201, 0x001e2101,
    964 	0x011f1f01, 0x01211e00, 0x01221d00, 0x02221c00, 0x02231b00, 0x03241900, 0x04241800, 0x04251700,
    965 	0x052616ff, 0x06261400, 0x072713ff, 0x08271100, 0x08271100, 0x09271000, 0x0a280e00, 0x0b280d00,
    966 
    967 	0xff0e260d, 0xff0f260c, 0xff10260b, 0xff11260a, 0xff122609, 0xff132608, 0xff142508, 0xff152507,
    968 	0x00152506, 0x00172405, 0x00182305, 0x00192304, 0x001b2203, 0x001c2103, 0x011d2002, 0x011d2002,
    969 	0x011f1f01, 0x021f1e01, 0x02201d01, 0x03211c00, 0x03221b00, 0x04221a00, 0x04231801, 0x05241700,
    970 	0x06241600, 0x07241500, 0x08251300, 0x09251200, 0x09261100, 0x0a261000, 0x0b260f00, 0x0c260e00,
    971 
    972 	0xff0e250e, 0xff0f250d, 0xff10250c, 0xff11250b, 0x0011250a, 0x00132409, 0x00142408, 0x00152407,
    973 	0x00162307, 0x00172306, 0x00182206, 0x00192205, 0x011a2104, 0x011b2004, 0x011c2003, 0x021c1f03,
    974 	0x021e1e02, 0x031e1d02, 0x03201c01, 0x04201b01, 0x04211a01, 0x05221900, 0x05221801, 0x06231700,
    975 	0x07231600, 0x07241500, 0x08241400, 0x09241300, 0x0a241200, 0x0b241100, 0x0c241000, 0x0d240f00,
    976 
    977 	0x000e240e, 0x000f240d, 0x0010240c, 0x0011240b, 0x0013230a, 0x0013230a, 0x00142309, 0x00152308,
    978 	0x00162208, 0x00172207, 0x01182106, 0x01192105, 0x011a2005, 0x021b1f04, 0x021b1f04, 0x021d1e03,
    979 	0x031d1d03, 0x031e1d02, 0x041e1c02, 0x041f1b02, 0x05201a01, 0x05211901, 0x06211801, 0x07221700,
    980 	0x07221601, 0x08231500, 0x09231400, 0x0a231300, 0x0a231300, 0x0b231200, 0x0c231100, 0x0d231000,
    981 
    982 	0x000f220f, 0x0010220e, 0x0011220d, 0x0012220c, 0x0013220b, 0x0013220b, 0x0015210a, 0x0015210a,
    983 	0x01162108, 0x01172008, 0x01182007, 0x02191f06, 0x02191f06, 0x021a1e06, 0x031a1e05, 0x031c1d04,
    984 	0x041c1c04, 0x041d1c03, 0x051d1b03, 0x051e1a03, 0x061f1902, 0x061f1902, 0x07201801, 0x08201701,
    985 	0x08211601, 0x09211501, 0x0a211500, 0x0b211400, 0x0b221300, 0x0c221200, 0x0d221100, 0x0e221000,
    986 
    987 	0x0010210f, 0x0011210e, 0x0011210e, 0x0012210d, 0x0013210c, 0x0014200c, 0x0114200b, 0x0115200a,
    988 	0x01161f0a, 0x01171f09, 0x02171f08, 0x02181e08, 0x03181e07, 0x031a1d06, 0x031a1d06, 0x041b1c05,
    989 	0x041c1c04, 0x051c1b04, 0x051d1a04, 0x061d1a03, 0x071d1903, 0x071e1803, 0x081e1802, 0x081f1702,
    990 	0x091f1602, 0x0a201501, 0x0b1f1501, 0x0b201401, 0x0c211300, 0x0d211200, 0x0e201200, 0x0e211100,
    991 
    992 	0x00102010, 0x0011200f, 0x0012200e, 0x0013200d, 0x0013200d, 0x01141f0c, 0x01151f0b, 0x01151f0b,
    993 	0x01161f0a, 0x02171e09, 0x02171e09, 0x03181d08, 0x03191d07, 0x03191d07, 0x041a1c06, 0x041b1c05,
    994 	0x051b1b05, 0x051c1b04, 0x061c1a04, 0x071d1903, 0x071d1903, 0x081d1803, 0x081e1703, 0x091e1702,
    995 	0x0a1f1601, 0x0a1f1502, 0x0b1f1501, 0x0c1f1401, 0x0d201300, 0x0d201300, 0x0e201200, 0x0f201100,
    996 
    997 	0x00102010, 0x0011200f, 0x00121f0f, 0x00131f0e, 0x00141f0d, 0x01141f0c, 0x01141f0c, 0x01151e0c,
    998 	0x02161e0a, 0x02171e09, 0x03171d09, 0x03181d08, 0x03181d08, 0x04191c07, 0x041a1c06, 0x051a1b06,
    999 	0x051b1b05, 0x061b1a05, 0x061c1a04, 0x071c1904, 0x081c1903, 0x081d1803, 0x091d1703, 0x091e1702,
   1000 	0x0a1e1602, 0x0b1e1502, 0x0c1e1501, 0x0c1f1401, 0x0d1f1400, 0x0e1f1300, 0x0e1f1201, 0x0f1f1200,
   1001 
   1002 	0x00111e11, 0x00121e10, 0x00131e0f, 0x00131e0f, 0x01131e0e, 0x01141d0e, 0x02151d0c, 0x02151d0c,
   1003 	0x02161d0b, 0x03161c0b, 0x03171c0a, 0x04171c09, 0x04181b09, 0x05181b08, 0x05191b07, 0x06191a07,
   1004 	0x061a1a06, 0x071a1906, 0x071b1905, 0x081b1805, 0x091b1804, 0x091c1704, 0x0a1c1703, 0x0a1c1604,
   1005 	0x0b1d1602, 0x0c1d1502, 0x0c1d1502, 0x0d1d1402, 0x0e1d1401, 0x0e1e1301, 0x0f1e1300, 0x101e1200,
   1006 
   1007 	0x00111e11, 0x00121e10, 0x00131d10, 0x01131d0f, 0x01141d0e, 0x01141d0e, 0x02151c0d, 0x02151c0d,
   1008 	0x03161c0b, 0x03161c0b, 0x04171b0a, 0x04171b0a, 0x05171b09, 0x05181a09, 0x06181a08, 0x06191a07,
   1009 	0x07191907, 0x071a1906, 0x081a1806, 0x081a1806, 0x091a1805, 0x0a1b1704, 0x0a1b1704, 0x0b1c1603,
   1010 	0x0b1c1603, 0x0c1c1503, 0x0d1c1502, 0x0d1d1402, 0x0e1d1401, 0x0f1d1301, 0x0f1d1301, 0x101e1200,
   1011 };
   1012 
   1013 static void
   1014 sunxi_mixer_vsu_init(struct sunxi_mixer_softc *sc, u_int src_w, u_int src_h,
   1015     u_int crtc_w, u_int crtc_h, const struct drm_format_info *format)
   1016 {
   1017 	const u_int hstep = (src_w << 16) / crtc_w;
   1018 	const u_int vstep = (src_h << 16) / crtc_h;
   1019 
   1020 	const int hsub = format->hsub;
   1021 	const int vsub = format->vsub;
   1022 
   1023 	const u_int src_cw = src_w / hsub;
   1024 	const u_int src_ch = src_h / vsub;
   1025 
   1026 	VSU_WRITE(sc, VS_OUT_SIZE_REG, ((crtc_h - 1) << 16) | (crtc_w - 1));
   1027 	VSU_WRITE(sc, VS_Y_SIZE_REG, ((src_h - 1) << 16) | (src_w - 1));
   1028 	VSU_WRITE(sc, VS_Y_HSTEP_REG, hstep << 4);
   1029 	VSU_WRITE(sc, VS_Y_VSTEP_REG, vstep << 4);
   1030 	VSU_WRITE(sc, VS_Y_HPHASE_REG, 0);
   1031 	VSU_WRITE(sc, VS_Y_VPHASE0_REG, 0);
   1032 	VSU_WRITE(sc, VS_Y_VPHASE1_REG, 0);
   1033 	VSU_WRITE(sc, VS_C_SIZE_REG, ((src_ch - 1) << 16) | (src_cw - 1));
   1034 	VSU_WRITE(sc, VS_C_HSTEP_REG, (hstep / hsub) << 4);
   1035 	VSU_WRITE(sc, VS_C_VSTEP_REG, (vstep / vsub) << 4);
   1036 	VSU_WRITE(sc, VS_C_HPHASE_REG, 0);
   1037 	VSU_WRITE(sc, VS_C_VPHASE0_REG, 0);
   1038 	VSU_WRITE(sc, VS_C_VPHASE1_REG, 0);
   1039 
   1040 	/* XXX */
   1041 	const u_int coef_base = 0;
   1042 
   1043 	for (int i = 0; i < 32; i++) {
   1044 		VSU_WRITE(sc, VS_Y_HCOEF0_REG(i), lan3coefftab32_left[coef_base + i]);
   1045 		VSU_WRITE(sc, VS_Y_HCOEF1_REG(i), lan3coefftab32_right[coef_base + i]);
   1046 		VSU_WRITE(sc, VS_Y_VCOEF_REG(i), lan2coefftab32[coef_base + i]);
   1047 		VSU_WRITE(sc, VS_C_HCOEF0_REG(i), lan3coefftab32_left[coef_base + i]);
   1048 		VSU_WRITE(sc, VS_C_HCOEF1_REG(i), lan3coefftab32_right[coef_base + i]);
   1049 		VSU_WRITE(sc, VS_C_VCOEF_REG(i), lan2coefftab32[coef_base + i]);
   1050 	}
   1051 
   1052 	/* Commit settings and enable scaler */
   1053 	VSU_WRITE(sc, VS_CTRL_REG, VS_CTRL_COEF_SWITCH_EN | VS_CTRL_EN);
   1054 }
   1055 
   1056 static const u32 yuv2rgb[] = {
   1057 	0x000004A8, 0x00000000, 0x00000662, 0xFFFC865A,
   1058 	0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021FF4,
   1059 	0x000004A8, 0x00000813, 0x00000000, 0xFFFBAE4A,
   1060 };
   1061 
   1062 static void
   1063 sunxi_mixer_csc_init(struct sunxi_mixer_softc *sc, uint32_t pixel_format)
   1064 {
   1065 	const u_int crtc_index = drm_crtc_index(&sc->sc_crtc.base);
   1066 
   1067 	for (int i = 0; i < __arraycount(yuv2rgb); i++)
   1068 		CSC_WRITE(sc, crtc_index, CSC_COEFF0_REG(0) + i * 4, yuv2rgb[i]);
   1069 
   1070 	CSC_WRITE(sc, crtc_index, CSC_BYPASS_REG, CSC_BYPASS_DISABLE);
   1071 }
   1072 
   1073 static void
   1074 sunxi_mixer_csc_disable(struct sunxi_mixer_softc *sc)
   1075 {
   1076 	const u_int crtc_index = drm_crtc_index(&sc->sc_crtc.base);
   1077 
   1078 	CSC_WRITE(sc, crtc_index, CSC_BYPASS_REG, 0);
   1079 }
   1080 
   1081 static int
   1082 sunxi_mixer_overlay_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
   1083     struct drm_framebuffer *fb, int crtc_x, int crtc_y, u_int crtc_w, u_int crtc_h,
   1084     uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
   1085     struct drm_modeset_acquire_ctx *ctx)
   1086 {
   1087 	struct sunxi_mixer_plane *overlay = to_sunxi_mixer_plane(plane);
   1088 	struct sunxi_mixer_softc * const sc = overlay->sc;
   1089 	struct sunxi_drm_framebuffer *sfb = to_sunxi_drm_framebuffer(fb);
   1090 	uint32_t val;
   1091 
   1092 	const u_int fbfmt = sunxi_mixer_overlay_format(fb->format->format);
   1093 	const uint64_t paddr = (uint64_t)sfb->obj->dmamap->dm_segs[0].ds_addr;
   1094 
   1095 	const uint32_t input_size = (((src_h >> 16) - 1) << 16) | ((src_w >> 16) - 1);
   1096 	const uint32_t input_pos = ((src_y >> 16) << 16) | (src_x >> 16);
   1097 
   1098 	OVL_V_WRITE(sc, OVL_V_MBSIZE(0), input_size);
   1099 	OVL_V_WRITE(sc, OVL_V_COOR(0), input_pos);
   1100 
   1101 	/* Note: DRM and hardware's ideas of pitch 1 and 2 are swapped */
   1102 
   1103 	OVL_V_WRITE(sc, OVL_V_PITCH0(0), fb->pitches[0]);
   1104 	OVL_V_WRITE(sc, OVL_V_PITCH1(0), fb->pitches[2]);
   1105 	OVL_V_WRITE(sc, OVL_V_PITCH2(0), fb->pitches[1]);
   1106 
   1107 	const uint64_t paddr0 = paddr + fb->offsets[0] +
   1108 	    (src_x >> 16) * fb->format->cpp[0] +
   1109 	    (src_y >> 16) * fb->pitches[0];
   1110 	const uint64_t paddr1 = paddr + fb->offsets[2] +
   1111 	    (src_x >> 16) * fb->format->cpp[2] +
   1112 	    (src_y >> 16) * fb->pitches[2];
   1113 	const uint64_t paddr2 = paddr + fb->offsets[1] +
   1114 	    (src_x >> 16) * fb->format->cpp[1] +
   1115 	    (src_y >> 16) * fb->pitches[1];
   1116 
   1117 	OVL_V_WRITE(sc, OVL_V_TOP_HADD0, (paddr0 >> 32) & OVL_V_TOP_HADD_LAYER0);
   1118 	OVL_V_WRITE(sc, OVL_V_TOP_HADD1, (paddr1 >> 32) & OVL_V_TOP_HADD_LAYER0);
   1119 	OVL_V_WRITE(sc, OVL_V_TOP_HADD2, (paddr2 >> 32) & OVL_V_TOP_HADD_LAYER0);
   1120 
   1121 	OVL_V_WRITE(sc, OVL_V_TOP_LADD0(0), paddr0 & 0xffffffff);
   1122 	OVL_V_WRITE(sc, OVL_V_TOP_LADD1(0), paddr1 & 0xffffffff);
   1123 	OVL_V_WRITE(sc, OVL_V_TOP_LADD2(0), paddr2 & 0xffffffff);
   1124 
   1125 	OVL_V_WRITE(sc, OVL_V_SIZE, input_size);
   1126 
   1127 	val = OVL_V_ATTCTL_LAY0_EN;
   1128 	val |= __SHIFTIN(fbfmt, OVL_V_ATTCTL_LAY_FBFMT);
   1129 	if (sunxi_mixer_overlay_rgb(fb->format->format) == true)
   1130 		val |= OVL_V_ATTCTL_VIDEO_UI_SEL;
   1131 	OVL_V_WRITE(sc, OVL_V_ATTCTL(0), val);
   1132 
   1133 	/* Enable video scaler */
   1134 	sunxi_mixer_vsu_init(sc, src_w >> 16, src_h >> 16, crtc_w, crtc_h, fb->format);
   1135 
   1136 	/* Enable colour space conversion for non-RGB formats */
   1137 	if (sunxi_mixer_overlay_rgb(fb->format->format) == false)
   1138 		sunxi_mixer_csc_init(sc, fb->format->format);
   1139 	else
   1140 		sunxi_mixer_csc_disable(sc);
   1141 
   1142 	/* Set blender 1 input size */
   1143 	BLD_WRITE(sc, BLD_CH_ISIZE(1), ((crtc_h - 1) << 16) | (crtc_w - 1));
   1144 	/* Set blender 1 offset */
   1145 	BLD_WRITE(sc, BLD_CH_OFFSET(1), (crtc_y << 16) | crtc_x);
   1146 	/* Route channel 0 to pipe 1 */
   1147 	val = BLD_READ(sc, BLD_CH_RTCTL);
   1148 	val &= ~BLD_CH_RTCTL_P1;
   1149 	val |= __SHIFTIN(0, BLD_CH_RTCTL_P1);
   1150 	BLD_WRITE(sc, BLD_CH_RTCTL, val);
   1151 
   1152         /* Enable pipe 1 */
   1153 	val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
   1154 	val |= BLD_FILL_COLOR_CTL_P1_EN;
   1155 	BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
   1156 
   1157 	/* Commit settings */
   1158 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
   1159 
   1160 	return 0;
   1161 }
   1162 
   1163 static int
   1164 sunxi_mixer_overlay_disable_plane(struct drm_plane *plane,
   1165     struct drm_modeset_acquire_ctx *ctx)
   1166 {
   1167 	struct sunxi_mixer_plane *overlay = to_sunxi_mixer_plane(plane);
   1168 	struct sunxi_mixer_softc * const sc = overlay->sc;
   1169 	uint32_t val;
   1170 
   1171 	sunxi_mixer_csc_disable(sc);
   1172 
   1173 	val = BLD_READ(sc, BLD_FILL_COLOR_CTL);
   1174 	val &= ~BLD_FILL_COLOR_CTL_P1_EN;
   1175 	BLD_WRITE(sc, BLD_FILL_COLOR_CTL, val);
   1176 
   1177 	/* Commit settings */
   1178 	GLB_WRITE(sc, GLB_DBUFFER, GLB_DBUFFER_DOUBLE_BUFFER_RDY);
   1179 
   1180 	return 0;
   1181 }
   1182 
   1183 static const struct drm_plane_funcs sunxi_mixer_overlay_funcs = {
   1184 	.update_plane = sunxi_mixer_overlay_update_plane,
   1185 	.disable_plane = sunxi_mixer_overlay_disable_plane,
   1186 	.destroy = sunxi_mixer_overlay_destroy,
   1187 };
   1188 
   1189 static uint32_t sunxi_mixer_overlay_formats[] = {
   1190 	DRM_FORMAT_ARGB8888,
   1191 	DRM_FORMAT_XRGB8888,
   1192 #if notyet
   1193 	DRM_FORMAT_VYUY,
   1194 	DRM_FORMAT_YVYU,
   1195 	DRM_FORMAT_UYVY,
   1196 	DRM_FORMAT_YUYV,
   1197 #endif
   1198 	DRM_FORMAT_YUV422,
   1199 	DRM_FORMAT_YUV420,
   1200 	DRM_FORMAT_YUV411,
   1201 };
   1202 
   1203 static int
   1204 sunxi_mixer_ep_activate(device_t dev, struct fdt_endpoint *ep, bool activate)
   1205 {
   1206 	struct sunxi_mixer_softc * const sc = device_private(dev);
   1207 	struct drm_device *ddev;
   1208 	bus_size_t reg;
   1209 
   1210 	if (!activate)
   1211 		return EINVAL;
   1212 
   1213 	ddev = sunxi_drm_endpoint_device(ep);
   1214 	if (ddev == NULL) {
   1215 		DRM_ERROR("couldn't find DRM device\n");
   1216 		return ENXIO;
   1217 	}
   1218 
   1219 	sc->sc_crtc.sc = sc;
   1220 	sc->sc_overlay.sc = sc;
   1221 
   1222 	/* Initialize registers */
   1223 	for (reg = 0; reg < 0xc000; reg += 4)
   1224 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, 0);
   1225 	BLD_WRITE(sc, BLD_CTL(0), 0x03010301);
   1226 	BLD_WRITE(sc, BLD_CTL(1), 0x03010301);
   1227 	BLD_WRITE(sc, BLD_CTL(2), 0x03010301);
   1228 	BLD_WRITE(sc, BLD_CTL(3), 0x03010301);
   1229 
   1230 	if (sc->sc_ovl_ui_count > 1)
   1231 		drm_crtc_init(ddev, &sc->sc_crtc.base, &sunxi_mixer0_crtc_funcs);
   1232 	else
   1233 		drm_crtc_init(ddev, &sc->sc_crtc.base, &sunxi_mixer1_crtc_funcs);
   1234 	drm_crtc_helper_add(&sc->sc_crtc.base, &sunxi_mixer_crtc_helper_funcs);
   1235 
   1236 	drm_universal_plane_init(ddev, &sc->sc_overlay.base,
   1237 	    1 << drm_crtc_index(&sc->sc_crtc.base), &sunxi_mixer_overlay_funcs,
   1238 	    sunxi_mixer_overlay_formats, __arraycount(sunxi_mixer_overlay_formats),
   1239 	    NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
   1240 
   1241 	return fdt_endpoint_activate(ep, activate);
   1242 }
   1243 
   1244 static void *
   1245 sunxi_mixer_ep_get_data(device_t dev, struct fdt_endpoint *ep)
   1246 {
   1247 	struct sunxi_mixer_softc * const sc = device_private(dev);
   1248 
   1249 	return &sc->sc_crtc;
   1250 }
   1251 
   1252 static int
   1253 sunxi_mixer_match(device_t parent, cfdata_t cf, void *aux)
   1254 {
   1255 	struct fdt_attach_args * const faa = aux;
   1256 
   1257 	return of_compatible_match(faa->faa_phandle, compat_data);
   1258 }
   1259 
   1260 static void
   1261 sunxi_mixer_attach(device_t parent, device_t self, void *aux)
   1262 {
   1263 	struct sunxi_mixer_softc * const sc = device_private(self);
   1264 	struct fdt_attach_args * const faa = aux;
   1265 	struct fdt_endpoint *out_ep;
   1266 	const int phandle = faa->faa_phandle;
   1267 	const struct sunxi_mixer_compat_data * const cd =
   1268 	    of_compatible_lookup(phandle, compat_data)->data;
   1269 	struct clk *clk_bus, *clk_mod;
   1270 	struct fdtbus_reset *rst;
   1271 	bus_addr_t addr;
   1272 	bus_size_t size;
   1273 
   1274 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
   1275 		aprint_error(": couldn't get registers\n");
   1276 		return;
   1277 	}
   1278 
   1279 	rst = fdtbus_reset_get_index(phandle, 0);
   1280 	if (rst == NULL || fdtbus_reset_deassert(rst) != 0) {
   1281 		aprint_error(": couldn't de-assert reset\n");
   1282 		return;
   1283 	}
   1284 
   1285 	clk_bus = fdtbus_clock_get(phandle, "bus");
   1286 	if (clk_bus == NULL || clk_enable(clk_bus) != 0) {
   1287 		aprint_error(": couldn't enable bus clock\n");
   1288 		return;
   1289 	}
   1290 
   1291 	clk_mod = fdtbus_clock_get(phandle, "mod");
   1292 	if (clk_mod == NULL ||
   1293 	    clk_set_rate(clk_mod, SUNXI_MIXER_FREQ) != 0 ||
   1294 	    clk_enable(clk_mod) != 0) {
   1295 		aprint_error(": couldn't enable mod clock\n");
   1296 		return;
   1297 	}
   1298 
   1299 	sc->sc_dev = self;
   1300 	sc->sc_bst = faa->faa_bst;
   1301 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
   1302 		aprint_error(": couldn't map registers\n");
   1303 		return;
   1304 	}
   1305 	sc->sc_phandle = faa->faa_phandle;
   1306 	sc->sc_ovl_ui_count = cd->ovl_ui_count;
   1307 
   1308 	aprint_naive("\n");
   1309 	aprint_normal(": Display Engine Mixer\n");
   1310 
   1311 	sc->sc_ports.dp_ep_activate = sunxi_mixer_ep_activate;
   1312 	sc->sc_ports.dp_ep_get_data = sunxi_mixer_ep_get_data;
   1313 	fdt_ports_register(&sc->sc_ports, self, phandle, EP_DRM_CRTC);
   1314 
   1315 	out_ep = fdt_endpoint_get_from_index(&sc->sc_ports,
   1316 	    MIXER_PORT_OUTPUT, cd->mixer_index);
   1317 	if (out_ep == NULL) {
   1318 		/* Couldn't find new-style DE2 endpoint, try old style. */
   1319 		out_ep = fdt_endpoint_get_from_index(&sc->sc_ports,
   1320 		    MIXER_PORT_OUTPUT, 0);
   1321 	}
   1322 
   1323 	if (out_ep != NULL)
   1324 		sunxi_drm_register_endpoint(phandle, out_ep);
   1325 }
   1326 
   1327 CFATTACH_DECL_NEW(sunxi_mixer, sizeof(struct sunxi_mixer_softc),
   1328 	sunxi_mixer_match, sunxi_mixer_attach, NULL, NULL);
   1329