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