Module Name:    src
Committed By:   jmcneill
Date:           Sat Jan 19 21:43:43 UTC 2019

Modified Files:
        src/sys/arch/arm/amlogic: files.meson
Added Files:
        src/sys/arch/arm/amlogic: meson_canvasreg.h meson_genfb.c
            meson_hdmireg.h meson_vpureg.h

Log Message:
Add Meson (FDT) framebuffer support.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/amlogic/files.meson
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/amlogic/meson_canvasreg.h \
    src/sys/arch/arm/amlogic/meson_genfb.c \
    src/sys/arch/arm/amlogic/meson_hdmireg.h \
    src/sys/arch/arm/amlogic/meson_vpureg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/amlogic/files.meson
diff -u src/sys/arch/arm/amlogic/files.meson:1.1 src/sys/arch/arm/amlogic/files.meson:1.2
--- src/sys/arch/arm/amlogic/files.meson:1.1	Sat Jan 19 20:56:03 2019
+++ src/sys/arch/arm/amlogic/files.meson	Sat Jan 19 21:43:43 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.meson,v 1.1 2019/01/19 20:56:03 jmcneill Exp $
+#	$NetBSD: files.meson,v 1.2 2019/01/19 21:43:43 jmcneill Exp $
 #
 # Configuration info for Amlogic Meson family SoCs
 #
@@ -32,6 +32,10 @@ device	mesonuart
 attach	mesonuart at fdt with meson_uart
 file	arch/arm/amlogic/meson_uart.c		meson_uart
 
+# Framebuffer console
+attach	genfb at fdt with meson_genfb
+file	arch/arm/amlogic/meson_genfb.c		meson_genfb & soc_meson
+
 # GPIO
 device	mesonpinctrl: gpiobus
 attach	mesonpinctrl at fdt with meson_pinctrl

Added files:

Index: src/sys/arch/arm/amlogic/meson_canvasreg.h
diff -u /dev/null src/sys/arch/arm/amlogic/meson_canvasreg.h:1.1
--- /dev/null	Sat Jan 19 21:43:43 2019
+++ src/sys/arch/arm/amlogic/meson_canvasreg.h	Sat Jan 19 21:43:43 2019
@@ -0,0 +1,54 @@
+/* $NetBSD: meson_canvasreg.h,v 1.1 2019/01/19 21:43:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MESON_CANVASREG_H
+#define _MESON_CANVASREG_H
+
+#define CANVAS_REG(n)	((n) << 2)
+
+#define DC_CAV_LUT_DATAL_REG	CANVAS_REG(0x12)
+#define DC_CAV_LUT_DATAH_REG	CANVAS_REG(0x13)
+#define DC_CAV_LUT_ADDR_REG	CANVAS_REG(0x14)
+
+#define DC_CAV_LUT_DATAL_FBADDR		__BITS(28,0)
+#define DC_CAV_LUT_DATAL_WIDTH_L	__BITS(31,29)
+
+#define DC_CAV_LUT_DATAH_BLKMODE	__BITS(25,24)
+#define DC_CAV_LUT_DATAH_BLKMODE_LINEAR	0
+#define DC_CAV_LUT_DATAH_BLKMODE_32X32	1
+#define DC_CAV_LUT_DATAH_BLKMODE_64X64	2
+#define DC_CAV_LUT_DATAH_YWRAP		__BIT(23)
+#define DC_CAV_LUT_DATAH_XWRAP		__BIT(22)
+#define DC_CAV_LUT_DATAH_HEIGHT		__BITS(21,9)
+#define DC_CAV_LUT_DATAH_WIDTH_H	__BITS(8,0)
+
+#define DC_CAV_LUT_ADDR_WR_EN		__BIT(9)
+#define DC_CAV_LUT_ADDR_RD_EN		__BIT(8)
+#define DC_CAV_LUT_ADDR_INDEX		__BITS(2,0)
+
+#endif /* _MESON_CANVASREG_H */
Index: src/sys/arch/arm/amlogic/meson_genfb.c
diff -u /dev/null src/sys/arch/arm/amlogic/meson_genfb.c:1.1
--- /dev/null	Sat Jan 19 21:43:43 2019
+++ src/sys/arch/arm/amlogic/meson_genfb.c	Sat Jan 19 21:43:43 2019
@@ -0,0 +1,728 @@
+/* $NetBSD: meson_genfb.c,v 1.1 2019/01/19 21:43:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015-2019 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic framebuffer console driver
+ */
+
+#include "opt_wsdisplay_compat.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: meson_genfb.c,v 1.1 2019/01/19 21:43:43 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kmem.h>
+#include <sys/sysctl.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/amlogic/meson_canvasreg.h>
+#include <arm/amlogic/meson_vpureg.h>
+#include <arm/amlogic/meson_hdmireg.h>
+
+#include <dev/wsfb/genfbvar.h>
+
+static const char * const compatible[] = {
+	"amlogic,meson8b-fb",
+	NULL
+};
+
+#define AMLOGIC_GENFB_DEFAULT_DEPTH	16
+
+/* Map CEA-861-D video code (VIC) to framebuffer dimensions */
+static const struct meson_genfb_vic2mode {
+	u_int vic;
+	u_int width;
+	u_int height;
+	u_int flags;
+#define INTERLACE __BIT(0)
+#define DBLSCAN __BIT(1)
+} meson_genfb_modes[] = {
+	{ 1, 640, 480 },
+	{ 2, 720, 480 },
+	{ 3, 720, 480 },
+	{ 4, 1280, 720 },
+	{ 5, 1920, 1080, INTERLACE },
+	{ 6, 720, 480, DBLSCAN | INTERLACE },
+	{ 7, 720, 480, DBLSCAN | INTERLACE },
+	{ 8, 720, 240, DBLSCAN },
+	{ 9, 720, 240, DBLSCAN },
+	{ 16, 1920, 1080 },
+	{ 17, 720, 576 },
+	{ 18, 720, 576 },
+	{ 19, 1280, 720 },
+	{ 20, 1920, 1080, INTERLACE },
+	{ 31, 1920, 1080 },
+	{ 32, 1920, 1080 },
+	{ 33, 1920, 1080 },
+	{ 34, 1920, 1080 },
+	{ 39, 1920, 1080, INTERLACE },
+};
+
+struct meson_genfb_softc {
+	struct genfb_softc	sc_gen;
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_cav_bsh;
+	bus_space_handle_t	sc_hdmi_bsh;
+	bus_space_handle_t	sc_vpu_bsh;
+	bus_dma_tag_t		sc_dmat;
+
+	kmutex_t		sc_lock;
+
+	u_int			sc_scale;
+
+	bus_dma_segment_t	sc_dmasegs[1];
+	bus_size_t		sc_dmasize;
+	bus_dmamap_t		sc_dmamap;
+	void			*sc_dmap;
+
+	uint32_t		sc_wstype;
+
+	struct sysctllog	*sc_sysctllog;
+	int			sc_node_scale;
+};
+
+static int	meson_genfb_match(device_t, cfdata_t, void *);
+static void	meson_genfb_attach(device_t, device_t, void *);
+
+static int	meson_genfb_ioctl(void *, void *, u_long, void *, int, lwp_t *);
+static paddr_t	meson_genfb_mmap(void *, void *, off_t, int);
+static bool	meson_genfb_shutdown(device_t, int);
+
+static void	meson_genfb_canvas_config(struct meson_genfb_softc *);
+static void	meson_genfb_osd_config(struct meson_genfb_softc *);
+static void	meson_genfb_scaler_config(struct meson_genfb_softc *);
+
+static void	meson_genfb_init(struct meson_genfb_softc *);
+static int	meson_genfb_alloc_videomem(struct meson_genfb_softc *);
+
+static int	meson_genfb_scale_helper(SYSCTLFN_PROTO);
+
+void		meson_genfb_set_console_dev(device_t);
+void		meson_genfb_ddb_trap_callback(int);
+
+static int meson_genfb_console_phandle = -1;
+static device_t meson_genfb_console_dev = NULL;
+
+CFATTACH_DECL_NEW(meson_genfb, sizeof(struct meson_genfb_softc),
+    meson_genfb_match, meson_genfb_attach, NULL, NULL);
+
+static inline uint32_t
+meson_genfb_hdmi_read_4(struct meson_genfb_softc *sc, uint32_t addr)
+{
+	bus_space_write_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_ADDR_REG, addr);
+	bus_space_write_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_ADDR_REG, addr);
+	return bus_space_read_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_DATA_REG);
+}
+
+static __unused inline void
+meson_genfb_hdmi_write_4(struct meson_genfb_softc *sc, uint32_t addr,
+    uint32_t data)
+{
+	bus_space_write_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_ADDR_REG, addr);
+	bus_space_write_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_ADDR_REG, addr);
+	bus_space_write_4(sc->sc_bst, sc->sc_hdmi_bsh, HDMI_DATA_REG, data);
+}
+
+#define HDMI_READ	meson_genfb_hdmi_read_4
+#define HDMI_WRITE	meson_genfb_hdmi_write_4
+
+#define VPU_READ(sc, reg) \
+    bus_space_read_4((sc)->sc_bst, (sc)->sc_vpu_bsh, (reg))
+#define VPU_WRITE(sc, reg, val) \
+    bus_space_write_4((sc)->sc_bst, (sc)->sc_vpu_bsh, (reg), (val))
+
+#define CAV_READ(sc, reg) \
+    bus_space_read_4((sc)->sc_bst, (sc)->sc_cav_bsh, (reg))
+#define CAV_WRITE(sc, reg, val) \
+    bus_space_write_4((sc)->sc_bst, (sc)->sc_cav_bsh, (reg), (val))
+
+static int
+meson_genfb_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct fdt_attach_args * const faa = aux;
+
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+meson_genfb_attach(device_t parent, device_t self, void *aux)
+{
+	struct meson_genfb_softc *sc = device_private(self);
+	struct fdt_attach_args * const faa = aux;
+	const int phandle = faa->faa_phandle;
+	prop_dictionary_t dict = device_properties(self);
+	static const struct genfb_ops zero_ops;
+	struct genfb_ops ops = zero_ops;
+	bus_addr_t addr[3];
+	bus_size_t size[3];
+
+	for (int i = 0; i < 3; i++) {
+		if (fdtbus_get_reg(phandle, i, &addr[i], &size[i]) != 0) {
+			aprint_error(": couldn't get register #%d\n", i);
+			return;
+		}
+	}
+
+	sc->sc_gen.sc_dev = self;
+	sc->sc_bst = faa->faa_bst;
+	sc->sc_dmat = faa->faa_dmat;
+	if (bus_space_map(sc->sc_bst, addr[0], size[0], 0, &sc->sc_cav_bsh) != 0 ||
+	    bus_space_map(sc->sc_bst, addr[1], size[1], 0, &sc->sc_hdmi_bsh) != 0 ||
+	    bus_space_map(sc->sc_bst, addr[2], size[2], 0, &sc->sc_vpu_bsh) != 0) {
+		aprint_error(": couldn't map registers\n");
+		return;
+	}
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+
+	meson_genfb_init(sc);
+
+	sc->sc_wstype = WSDISPLAY_TYPE_MESON;
+
+	aprint_naive("\n");
+	aprint_normal("\n");
+
+	genfb_init(&sc->sc_gen);
+
+	if (sc->sc_gen.sc_width == 0 ||
+	    sc->sc_gen.sc_fbsize == 0) {
+		aprint_normal_dev(self, "disabled\n");
+		return;
+	}
+
+	pmf_device_register1(self, NULL, NULL, meson_genfb_shutdown);
+
+#ifdef WSDISPLAY_MULTICONS
+	const bool is_console = true;
+#else
+	const bool is_console = phandle == meson_genfb_console_phandle;
+	if (is_console)
+		aprint_normal_dev(self, "switching to framebuffer console\n");
+#endif
+	prop_dictionary_set_bool(dict, "is_console", is_console);
+
+	memset(&ops, 0, sizeof(ops));
+	ops.genfb_ioctl = meson_genfb_ioctl;
+	ops.genfb_mmap = meson_genfb_mmap;
+
+	genfb_attach(&sc->sc_gen, &ops);
+}
+
+static int
+meson_genfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
+{
+	struct meson_genfb_softc *sc = v;
+	struct wsdisplayio_bus_id *busid;
+
+	switch (cmd) {
+	case WSDISPLAYIO_GTYPE:
+		*(u_int *)data = sc->sc_wstype;
+		return 0;
+	case WSDISPLAYIO_GET_BUSID:
+		busid = data;
+		busid->bus_type = WSDISPLAYIO_BUS_SOC;
+		return 0;
+	case WSDISPLAYIO_GET_FBINFO:
+		{
+			struct wsdisplayio_fbinfo *fbi = data;
+			struct rasops_info *ri = &sc->sc_gen.vd.active->scr_ri;
+			int ret;
+
+			ret = wsdisplayio_get_fbinfo(ri, fbi);
+			fbi->fbi_flags |= WSFB_VRAM_IS_RAM;
+			return ret;
+		}
+	default:
+		return EPASSTHROUGH;
+	}
+}
+
+static paddr_t
+meson_genfb_mmap(void *v, void *vs, off_t offset, int prot)
+{
+	struct meson_genfb_softc *sc = v;
+
+	if (offset < 0 || offset >= sc->sc_dmasegs[0].ds_len)
+		return -1;
+
+	return bus_dmamem_mmap(sc->sc_dmat, sc->sc_dmasegs, 1,
+	    offset, prot, BUS_DMA_PREFETCHABLE);
+}
+
+static bool
+meson_genfb_shutdown(device_t self, int flags)
+{
+	genfb_enable_polling(self);
+	return true;
+}
+
+static void
+meson_genfb_canvas_config(struct meson_genfb_softc *sc)
+{
+	prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+	const paddr_t pa = sc->sc_dmamap->dm_segs[0].ds_addr;
+	uint32_t datal, datah, addr;
+	u_int width, height, depth;
+
+	prop_dictionary_get_uint32(cfg, "width", &width);
+	prop_dictionary_get_uint32(cfg, "height", &height);
+	prop_dictionary_get_uint32(cfg, "depth", &depth);
+
+	const uint32_t w = (width * (depth/8)) >> 3;
+	const uint32_t h = height;
+
+	datal = CAV_READ(sc, DC_CAV_LUT_DATAL_REG);
+	datah = CAV_READ(sc, DC_CAV_LUT_DATAH_REG);
+	addr = CAV_READ(sc, DC_CAV_LUT_ADDR_REG);
+
+	datal &= ~DC_CAV_LUT_DATAL_WIDTH_L;
+	datal |= __SHIFTIN(w & 7, DC_CAV_LUT_DATAL_WIDTH_L);
+	datal &= ~DC_CAV_LUT_DATAL_FBADDR;
+	datal |= __SHIFTIN(pa >> 3, DC_CAV_LUT_DATAL_FBADDR);
+	CAV_WRITE(sc, DC_CAV_LUT_DATAL_REG, datal);
+
+	datah &= ~DC_CAV_LUT_DATAH_BLKMODE;
+	datah |= __SHIFTIN(DC_CAV_LUT_DATAH_BLKMODE_LINEAR,
+			   DC_CAV_LUT_DATAH_BLKMODE);
+	datah &= ~DC_CAV_LUT_DATAH_WIDTH_H;
+	datah |= __SHIFTIN(w >> 3, DC_CAV_LUT_DATAH_WIDTH_H);
+	datah &= ~DC_CAV_LUT_DATAH_HEIGHT;
+	datah |= __SHIFTIN(h, DC_CAV_LUT_DATAH_HEIGHT);
+	CAV_WRITE(sc, DC_CAV_LUT_DATAH_REG, datah);
+
+	addr |= DC_CAV_LUT_ADDR_WR_EN;
+	CAV_WRITE(sc, DC_CAV_LUT_ADDR_REG, addr);
+}
+
+static void
+meson_genfb_osd_config(struct meson_genfb_softc *sc)
+{
+	prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+	uint32_t cs, tc, w0, w1, w2, w3, w4;
+	u_int width, height, depth;
+	bool interlace_p;
+
+	prop_dictionary_get_uint32(cfg, "width", &width);
+	prop_dictionary_get_uint32(cfg, "height", &height);
+	prop_dictionary_get_uint32(cfg, "depth", &depth);
+	prop_dictionary_get_bool(cfg, "interlace", &interlace_p);
+
+	cs = VPU_READ(sc, VIU_OSD2_CTRL_STAT_REG);
+	cs |= VIU_OSD_CTRL_STAT_ENABLE;
+	cs &= ~VIU_OSD_CTRL_STAT_GLOBAL_ALPHA;
+	cs |= __SHIFTIN(0xff, VIU_OSD_CTRL_STAT_GLOBAL_ALPHA);
+	cs |= VIU_OSD_CTRL_STAT_BLK0_ENABLE;
+	cs &= ~VIU_OSD_CTRL_STAT_BLK1_ENABLE;
+	cs &= ~VIU_OSD_CTRL_STAT_BLK2_ENABLE;
+	cs &= ~VIU_OSD_CTRL_STAT_BLK3_ENABLE;
+	VPU_WRITE(sc, VIU_OSD2_CTRL_STAT_REG, cs);
+
+	tc = __SHIFTIN(0, VIU_OSD_TCOLOR_R) |
+	     __SHIFTIN(0, VIU_OSD_TCOLOR_G) |
+	     __SHIFTIN(0, VIU_OSD_TCOLOR_B) |
+	     __SHIFTIN(255, VIU_OSD_TCOLOR_A);
+	VPU_WRITE(sc, VIU_OSD2_TCOLOR_AG0_REG, tc);
+
+	w0 = VPU_READ(sc, VIU_OSD2_BLK0_CFG_W0_REG);
+	w0 |= VIU_OSD_BLK_CFG_W0_RGB_EN;
+	w0 &= ~VIU_OSD_BLK_CFG_W0_TC_ALPHA_EN;
+	w0 &= ~VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE;
+	w0 &= ~VIU_OSD_BLK_CFG_W0_COLOR_MATRIX;
+	switch (depth) {
+	case 32:
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_32BPP,
+				VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE);
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_ARGB,
+				VIU_OSD_BLK_CFG_W0_COLOR_MATRIX);
+		break;
+	case 24:
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_24BPP,
+				VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE);
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_RGB,
+				VIU_OSD_BLK_CFG_W0_COLOR_MATRIX);
+		break;
+	case 16:
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_16BPP,
+				VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE);
+		w0 |= __SHIFTIN(VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_RGB565,
+				VIU_OSD_BLK_CFG_W0_COLOR_MATRIX);
+		break;
+	}
+	w0 |= VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN;
+	w0 &= ~VIU_OSD_BLK_CFG_W0_RPT_Y;
+	w0 &= ~VIU_OSD_BLK_CFG_W0_INTERP_CTRL;
+	if (interlace_p) {
+		w0 |= VIU_OSD_BLK_CFG_W0_INTERLACE_EN;
+	} else {
+		w0 &= ~VIU_OSD_BLK_CFG_W0_INTERLACE_EN;
+	}
+	VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W0_REG, w0);
+
+	w1 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W1_X_END) |
+	     __SHIFTIN(0, VIU_OSD_BLK_CFG_W1_X_START);
+	w2 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W2_Y_END) |
+	     __SHIFTIN(0, VIU_OSD_BLK_CFG_W2_Y_START);
+	w3 = __SHIFTIN(width - 1, VIU_OSD_BLK_CFG_W3_H_END) |
+	     __SHIFTIN(0, VIU_OSD_BLK_CFG_W3_H_START);
+	w4 = __SHIFTIN(height - 1, VIU_OSD_BLK_CFG_W4_V_END) |
+	     __SHIFTIN(0, VIU_OSD_BLK_CFG_W4_V_START);
+
+	VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W1_REG, w1);
+	VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W2_REG, w2);
+	VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W3_REG, w3);
+	VPU_WRITE(sc, VIU_OSD2_BLK0_CFG_W4_REG, w4);
+}
+
+static void
+meson_genfb_scaler_config(struct meson_genfb_softc *sc)
+{
+	prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+	uint32_t scctl, sci_wh, sco_h, sco_v, hsc, vsc, hps, vps, hip, vip;
+	u_int width, height;
+	bool interlace_p;
+
+	prop_dictionary_get_uint32(cfg, "width", &width);
+	prop_dictionary_get_uint32(cfg, "height", &height);
+	prop_dictionary_get_bool(cfg, "interlace", &interlace_p);
+
+	const u_int scale = sc->sc_scale;
+	const u_int dst_w = (width * scale) / 100;
+	const u_int dst_h = (height * scale) / 100;
+	const u_int margin_w = (width - dst_w) / 2;
+	const u_int margin_h = (height - dst_h) / 2;
+	const bool scale_p = scale != 100;
+
+	VPU_WRITE(sc, VPP_OSD_SC_DUMMY_DATA_REG, 0x00808000);
+
+	scctl = VPU_READ(sc, VPP_OSD_SC_CTRL0_REG);
+	scctl |= VPP_OSD_SC_CTRL0_OSD_SC_PATH_EN;
+	scctl &= ~VPP_OSD_SC_CTRL0_OSD_SC_SEL;
+	scctl |= __SHIFTIN(1, VPP_OSD_SC_CTRL0_OSD_SC_SEL); /* OSD2 */
+	scctl &= ~VPP_OSD_SC_CTRL0_DEFAULT_ALPHA;
+	scctl |= __SHIFTIN(0, VPP_OSD_SC_CTRL0_DEFAULT_ALPHA);
+	VPU_WRITE(sc, VPP_OSD_SC_CTRL0_REG, scctl);
+
+	sci_wh = __SHIFTIN(width - 1, VPP_OSD_SCI_WH_M1_WIDTH) |
+		 __SHIFTIN((height >> interlace_p) - 1, VPP_OSD_SCI_WH_M1_HEIGHT);
+	sco_h = __SHIFTIN(margin_w, VPP_OSD_SCO_H_START) |
+		__SHIFTIN(width - margin_w - 1, VPP_OSD_SCO_H_END);
+	sco_v = __SHIFTIN(margin_h >> interlace_p, VPP_OSD_SCO_V_START) |
+		__SHIFTIN(((height - margin_h) >> interlace_p) - 1,
+			  VPP_OSD_SCO_V_END);
+
+	VPU_WRITE(sc, VPP_OSD_SCI_WH_M1_REG, sci_wh);
+	VPU_WRITE(sc, VPP_OSD_SCO_H_REG, sco_h);
+	VPU_WRITE(sc, VPP_OSD_SCO_V_REG, sco_v);
+
+	/* horizontal scaling */
+	hsc = VPU_READ(sc, VPP_OSD_HSC_CTRL0_REG);
+	if (scale_p) {
+		hsc &= ~VPP_OSD_HSC_CTRL0_BANK_LENGTH;
+		hsc |= __SHIFTIN(4, VPP_OSD_HSC_CTRL0_BANK_LENGTH);
+		hsc &= ~VPP_OSD_HSC_CTRL0_INI_RCV_NUM0;
+		hsc |= __SHIFTIN(4, VPP_OSD_HSC_CTRL0_INI_RCV_NUM0);
+		hsc &= ~VPP_OSD_HSC_CTRL0_RPT_P0_NUM0;
+		hsc |= __SHIFTIN(1, VPP_OSD_HSC_CTRL0_RPT_P0_NUM0);
+		hsc |= VPP_OSD_HSC_CTRL0_HSCALE_EN;
+	} else {
+		hsc &= ~VPP_OSD_HSC_CTRL0_HSCALE_EN;
+	}
+	VPU_WRITE(sc, VPP_OSD_HSC_CTRL0_REG, hsc);
+
+	/* vertical scaling */
+	vsc = VPU_READ(sc, VPP_OSD_VSC_CTRL0_REG);
+	if (scale_p) {
+		vsc &= ~VPP_OSD_VSC_CTRL0_BANK_LENGTH;
+		vsc |= __SHIFTIN(4, VPP_OSD_VSC_CTRL0_BANK_LENGTH);
+		vsc &= ~VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0;
+		vsc |= __SHIFTIN(4, VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0);
+		vsc &= ~VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0;
+		vsc |= __SHIFTIN(1, VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0);
+		vsc &= ~VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0;
+		vsc &= ~VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0;
+		vsc &= ~VPP_OSC_VSC_CTRL0_INTERLACE;
+		if (interlace_p) {
+			/* interlace */
+			vsc |= VPP_OSC_VSC_CTRL0_INTERLACE;
+			vsc |= __SHIFTIN(6, VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0);
+			vsc |= __SHIFTIN(2, VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0);
+		}
+		vsc |= VPP_OSD_VSC_CTRL0_VSCALE_EN;
+	} else {
+		vsc &= ~VPP_OSD_VSC_CTRL0_VSCALE_EN;
+	}
+	VPU_WRITE(sc, VPP_OSD_VSC_CTRL0_REG, vsc);
+
+	/* free scale enable */
+	if (scale_p) {
+		const u_int hf_phase_step = ((width << 18) / dst_w) << 6;
+		const u_int vf_phase_step = ((height << 20) / dst_h) << 4;
+		const u_int bot_ini_phase =
+		    interlace_p ? ((vf_phase_step / 2) >> 8) : 0;
+
+		hps = VPU_READ(sc, VPP_OSD_HSC_PHASE_STEP_REG);
+		hps &= ~VPP_OSD_HSC_PHASE_STEP_FORMAT;
+		hps |= __SHIFTIN(hf_phase_step, VPP_OSD_HSC_PHASE_STEP_FORMAT);
+		VPU_WRITE(sc, VPP_OSD_HSC_PHASE_STEP_REG, hps);
+
+		hip = VPU_READ(sc, VPP_OSD_HSC_INI_PHASE_REG);
+		hip &= ~VPP_OSD_HSC_INI_PHASE_1;
+		VPU_WRITE(sc, VPP_OSD_HSC_INI_PHASE_REG, hip);
+
+		vps = VPU_READ(sc, VPP_OSD_VSC_PHASE_STEP_REG);
+		vps &= ~VPP_OSD_VSC_PHASE_STEP_FORMAT;
+		vps |= __SHIFTIN(hf_phase_step, VPP_OSD_VSC_PHASE_STEP_FORMAT);
+		VPU_WRITE(sc, VPP_OSD_VSC_PHASE_STEP_REG, vps);
+
+		vip = VPU_READ(sc, VPP_OSD_VSC_INI_PHASE_REG);
+		vip &= ~VPP_OSD_VSC_INI_PHASE_1;
+		vip |= __SHIFTIN(0, VPP_OSD_VSC_INI_PHASE_1);
+		vip &= ~VPP_OSD_VSC_INI_PHASE_0;
+		vip |= __SHIFTIN(bot_ini_phase, VPP_OSD_VSC_INI_PHASE_0);
+		VPU_WRITE(sc, VPP_OSD_VSC_INI_PHASE_REG, vip);
+	}
+}
+
+static void
+meson_genfb_init(struct meson_genfb_softc *sc)
+{
+	prop_dictionary_t cfg = device_properties(sc->sc_gen.sc_dev);
+	const struct sysctlnode *node, *devnode;
+	u_int width = 0, height = 0, depth, flags, i, scale = 100;
+	int error;
+
+	/*
+	 * Firmware has (maybe) setup HDMI TX for us. Read the VIC from
+	 * the HDMI AVI InfoFrame (bits 6:0 in PB4) and map that to a
+	 * framebuffer geometry.
+	 */
+	const uint32_t vic = HDMI_READ(sc, HDMITX_AVI_INFO_ADDR + 4) & 0x7f;
+	for (i = 0; i < __arraycount(meson_genfb_modes); i++) {
+		if (meson_genfb_modes[i].vic == vic) {
+			aprint_debug(" [HDMI VIC %d]", vic);
+			width = meson_genfb_modes[i].width;
+			height = meson_genfb_modes[i].height;
+			flags = meson_genfb_modes[i].flags;
+			break;
+		}
+	}
+	if (width == 0 || height == 0) {
+		aprint_error(" [UNSUPPORTED HDMI VIC %d]", vic);
+		return;
+	}
+
+	depth = AMLOGIC_GENFB_DEFAULT_DEPTH;
+	prop_dictionary_get_uint32(cfg, "depth", &depth);
+	switch (depth) {
+	case 16:
+	case 24:
+		break;
+	default:
+		aprint_error_dev(sc->sc_gen.sc_dev,
+		    "unsupported depth %d, using %d\n", depth,
+		    AMLOGIC_GENFB_DEFAULT_DEPTH);
+		depth = AMLOGIC_GENFB_DEFAULT_DEPTH;
+		break;
+	}
+	prop_dictionary_set_uint8(cfg, "depth", depth);
+
+	const uint32_t fbsize = width * height * (depth / 8);
+	sc->sc_dmasize = (fbsize + 3) & ~3;
+
+	error = meson_genfb_alloc_videomem(sc);
+	if (error) {
+		aprint_error_dev(sc->sc_gen.sc_dev,
+		    "failed to allocate %u bytes of video memory: %d\n",
+		    (u_int)sc->sc_dmasize, error);
+		return;
+	}
+
+	prop_dictionary_get_uint32(cfg, "scale", &scale);
+	if (scale > 100) {
+		scale = 100;
+	} else if (scale < 10) {
+		scale = 10;
+	}
+	sc->sc_scale = scale;
+
+	prop_dictionary_set_uint32(cfg, "width", width);
+	prop_dictionary_set_uint32(cfg, "height", height);
+	prop_dictionary_set_bool(cfg, "dblscan", !!(flags & DBLSCAN));
+	prop_dictionary_set_bool(cfg, "interlace", !!(flags & INTERLACE));
+	prop_dictionary_set_uint16(cfg, "linebytes", width * (depth / 8));
+	prop_dictionary_set_uint32(cfg, "address", 0);
+	prop_dictionary_set_uint32(cfg, "virtual_address",
+	    (uintptr_t)sc->sc_dmap);
+
+	meson_genfb_canvas_config(sc);
+	meson_genfb_osd_config(sc);
+	meson_genfb_scaler_config(sc);
+
+	/* sysctl setup */
+	error = sysctl_createv(&sc->sc_sysctllog, 0, NULL, &node,
+	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
+	    NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
+	if (error)
+		goto sysctl_failed;
+	error = sysctl_createv(&sc->sc_sysctllog, 0, &node, &devnode,
+	    0, CTLTYPE_NODE, device_xname(sc->sc_gen.sc_dev), NULL,
+	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
+	if (error)
+		goto sysctl_failed;
+	error = sysctl_createv(&sc->sc_sysctllog, 0, &devnode, &node,
+	    CTLFLAG_READWRITE, CTLTYPE_INT, "scale", NULL,
+	    meson_genfb_scale_helper, 0, (void *)sc, 0,
+	    CTL_CREATE, CTL_EOL);
+	if (error)
+		goto sysctl_failed;
+	sc->sc_node_scale = node->sysctl_num;
+
+	return;
+
+sysctl_failed:
+	aprint_error_dev(sc->sc_gen.sc_dev,
+	    "couldn't create sysctl nodes (%d)\n", error);
+	sysctl_teardown(&sc->sc_sysctllog);
+}
+
+static int
+meson_genfb_scale_helper(SYSCTLFN_ARGS)
+{
+	struct meson_genfb_softc *sc;
+	struct sysctlnode node;
+	int scale, oldscale, error;
+
+	node = *rnode;
+	sc = node.sysctl_data;
+	scale = oldscale = sc->sc_scale;
+	node.sysctl_data = &scale;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (scale > 100) {
+		scale = 100;
+	} else if (scale < 10) {
+		scale = 10;
+	}
+
+	if (scale == oldscale) {
+		return 0;
+	}
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_scale = scale;
+	meson_genfb_scaler_config(sc);
+	mutex_exit(&sc->sc_lock);
+
+	return 0;
+}
+
+static int
+meson_genfb_alloc_videomem(struct meson_genfb_softc *sc)
+{
+	int error, nsegs;
+
+	error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmasize, 0x1000, 0,
+	    sc->sc_dmasegs, 1, &nsegs, BUS_DMA_WAITOK);
+	if (error)
+		return error;
+	error = bus_dmamem_map(sc->sc_dmat, sc->sc_dmasegs, nsegs,
+	    sc->sc_dmasize, &sc->sc_dmap, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
+	if (error)
+		goto free;
+	error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmasize, 1,
+	    sc->sc_dmasize, 0, BUS_DMA_WAITOK, &sc->sc_dmamap);
+	if (error)
+		goto unmap;
+	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_dmap,
+	    sc->sc_dmasize, NULL, BUS_DMA_WAITOK);
+	if (error)
+		goto destroy;
+
+	memset(sc->sc_dmap, 0, sc->sc_dmasize);
+
+	return 0;
+
+destroy:
+	bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
+unmap:
+	bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmap, sc->sc_dmasize);
+free:
+	bus_dmamem_free(sc->sc_dmat, sc->sc_dmasegs, nsegs);
+
+	sc->sc_dmasize = 0;
+	sc->sc_dmap = NULL;
+
+	return error;
+}
+
+void
+meson_genfb_set_console_dev(device_t dev)
+{
+	KASSERT(meson_genfb_console_dev == NULL);
+	meson_genfb_console_dev = dev;
+}
+
+void
+meson_genfb_ddb_trap_callback(int where)
+{
+	if (meson_genfb_console_dev == NULL)
+		return;
+
+	if (where) {
+		genfb_enable_polling(meson_genfb_console_dev);
+	} else {
+		genfb_disable_polling(meson_genfb_console_dev);
+	}
+}
+
+static int
+meson_genfb_console_match(int phandle)
+{
+	return of_match_compatible(phandle, compatible);
+}
+
+static void
+meson_genfb_console_consinit(struct fdt_attach_args *faa, u_int uart_freq)
+{
+	meson_genfb_console_phandle = faa->faa_phandle;
+	genfb_cnattach();
+}
+
+static const struct fdt_console meson_genfb_fdt_console = {
+	.match = meson_genfb_console_match,
+	.consinit = meson_genfb_console_consinit,
+};
+
+FDT_CONSOLE(meson_genfb, &meson_genfb_fdt_console);
Index: src/sys/arch/arm/amlogic/meson_hdmireg.h
diff -u /dev/null src/sys/arch/arm/amlogic/meson_hdmireg.h:1.1
--- /dev/null	Sat Jan 19 21:43:43 2019
+++ src/sys/arch/arm/amlogic/meson_hdmireg.h	Sat Jan 19 21:43:43 2019
@@ -0,0 +1,38 @@
+/* $NetBSD: meson_hdmireg.h,v 1.1 2019/01/19 21:43:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MESON_HDMIREG_H
+#define _MESON_HDMIREG_H
+
+#define HDMI_ADDR_REG		0x2000
+#define HDMI_DATA_REG		0x2004
+#define HDMI_CTRL_REG		0x2008
+
+#define HDMITX_AVI_INFO_ADDR	0x260
+
+#endif /* _MESON_HDMIREG_H */
Index: src/sys/arch/arm/amlogic/meson_vpureg.h
diff -u /dev/null src/sys/arch/arm/amlogic/meson_vpureg.h:1.1
--- /dev/null	Sat Jan 19 21:43:43 2019
+++ src/sys/arch/arm/amlogic/meson_vpureg.h	Sat Jan 19 21:43:43 2019
@@ -0,0 +1,151 @@
+/* $NetBSD: meson_vpureg.h,v 1.1 2019/01/19 21:43:43 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2015 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MESON_VPUREG_H
+#define _MESON_VPUREG_H
+
+#define VPU_REG(n)	((n) << 2)
+
+#define VIU_OSD2_CTRL_STAT_REG		VPU_REG(0x1a30)
+#define VIU_OSD2_TCOLOR_AG0_REG		VPU_REG(0x1a37)
+#define VIU_OSD2_TCOLOR_AG1_REG		VPU_REG(0x1a38)
+#define VIU_OSD2_TCOLOR_AG2_REG		VPU_REG(0x1a39)
+#define VIU_OSD2_TCOLOR_AG3_REG		VPU_REG(0x1a3a)
+#define VIU_OSD2_BLK0_CFG_W0_REG	VPU_REG(0x1a3b)
+#define VIU_OSD2_BLK0_CFG_W1_REG	VPU_REG(0x1a3c)
+#define VIU_OSD2_BLK0_CFG_W2_REG	VPU_REG(0x1a3d)
+#define VIU_OSD2_BLK0_CFG_W3_REG	VPU_REG(0x1a3e)
+#define VIU_OSD2_BLK0_CFG_W4_REG	VPU_REG(0x1a64)
+#define VPP_MISC_REG			VPU_REG(0x1d26)
+#define VPP_OSD_VSC_PHASE_STEP_REG	VPU_REG(0x1dc0)
+#define VPP_OSD_VSC_INI_PHASE_REG	VPU_REG(0x1dc1)
+#define VPP_OSD_VSC_CTRL0_REG		VPU_REG(0x1dc2)
+#define VPP_OSD_HSC_PHASE_STEP_REG	VPU_REG(0x1dc3)
+#define VPP_OSD_HSC_INI_PHASE_REG	VPU_REG(0x1dc4)
+#define VPP_OSD_HSC_CTRL0_REG		VPU_REG(0x1dc5)
+#define VPP_OSD_SC_DUMMY_DATA_REG	VPU_REG(0x1dc7)
+#define VPP_OSD_SC_CTRL0_REG		VPU_REG(0x1dc8)
+#define VPP_OSD_SCI_WH_M1_REG		VPU_REG(0x1dc9)
+#define VPP_OSD_SCO_H_REG		VPU_REG(0x1dca)
+#define VPP_OSD_SCO_V_REG		VPU_REG(0x1dcb)
+
+#define VIU_OSD_CTRL_STAT_ENABLE	__BIT(21)
+#define VIU_OSD_CTRL_STAT_GLOBAL_ALPHA	__BITS(20,12)
+#define VIU_OSD_CTRL_STAT_BLK3_ENABLE	__BIT(3)
+#define VIU_OSD_CTRL_STAT_BLK2_ENABLE	__BIT(2)
+#define VIU_OSD_CTRL_STAT_BLK1_ENABLE	__BIT(1)
+#define VIU_OSD_CTRL_STAT_BLK0_ENABLE	__BIT(0)
+
+#define VIU_OSD_TCOLOR_R		__BITS(31,24)
+#define VIU_OSD_TCOLOR_G		__BITS(23,16)
+#define VIU_OSD_TCOLOR_B		__BITS(15,8)
+#define VIU_OSD_TCOLOR_A		__BITS(7,0)
+
+#define VIU_OSD_BLK_CFG_W0_TBL_ADDR	__BITS(23,16)
+#define VIU_OSD_BLK_CFG_W0_LITTLE_ENDIAN __BIT(15)
+#define VIU_OSD_BLK_CFG_W0_RPT_Y	__BIT(14)
+#define VIU_OSD_BLK_CFG_W0_INTERP_CTRL	__BITS(13,12)
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE	__BITS(11,8)
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_PAL4	0
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_PAL16	1
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_PAL256	2
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_YUV	3
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_16BPP	4
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_32BPP	5
+#define VIU_OSD_BLK_CFG_W0_OSD_BLK_MODE_24BPP	7
+#define VIU_OSD_BLK_CFG_W0_RGB_EN	__BIT(7)
+#define VIU_OSD_BLK_CFG_W0_TC_ALPHA_EN	__BIT(6)
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX	__BITS(5,2)
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_RGB	0
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_RGBA	0
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_ARGB	1
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_ABGR	2
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_BGRA	3
+#define VIU_OSD_BLK_CFG_W0_COLOR_MATRIX_RGB565	4
+#define VIU_OSD_BLK_CFG_W0_INTERLACE_EN	__BIT(1)
+#define VIU_OSD_BLK_CFG_W0_INTERLACE_SEL_ODD __BIT(0)
+
+#define VIU_OSD_BLK_CFG_W1_X_END	__BITS(28,16)
+#define VIU_OSD_BLK_CFG_W1_X_START	__BITS(12,0)
+
+#define VIU_OSD_BLK_CFG_W2_Y_END	__BITS(28,16)
+#define VIU_OSD_BLK_CFG_W2_Y_START	__BITS(12,0)
+
+#define VIU_OSD_BLK_CFG_W3_H_END	__BITS(27,16)
+#define VIU_OSD_BLK_CFG_W3_H_START	__BITS(11,0)
+
+#define VIU_OSD_BLK_CFG_W4_V_END	__BITS(27,16)
+#define VIU_OSD_BLK_CFG_W4_V_START	__BITS(11,0)
+
+#define VPP_MISC_OSD2_PREBLEND		__BIT(17)
+#define VPP_MISC_OSD1_PREBLEND		__BIT(16)
+#define VPP_MISC_OSD2_POSTBLEND		__BIT(13)
+#define VPP_MISC_OSD1_POSTBLEND		__BIT(12)
+#define VPP_MISC_POSTBLEND		__BIT(7)
+#define VPP_MISC_PREBLEND		__BIT(6)
+
+#define VPP_OSD_VSC_PHASE_STEP_FORMAT	__BITS(27,0)
+
+#define VPP_OSD_VSC_INI_PHASE_0		__BITS(31,16)
+#define VPP_OSD_VSC_INI_PHASE_1		__BITS(15,0)
+
+#define VPP_OSD_VSC_CTRL0_VSCALE_EN	__BIT(24)
+#define VPP_OSC_VSC_CTRL0_INTERLACE	__BIT(23)
+#define VPP_OSD_VSC_CTRL0_BOT_RPT_P0_NUM0	__BITS(17,16)
+#define VPP_OSD_VSC_CTRL0_BOT_INI_RCV_NUM0	__BITS(14,11)
+#define VPP_OSD_VSC_CTRL0_TOP_RPT_P0_NUM0	__BITS(9,8)
+#define VPP_OSD_VSC_CTRL0_TOP_INI_RCV_NUM0	__BITS(6,3)
+#define VPP_OSD_VSC_CTRL0_BANK_LENGTH	__BITS(2,0)
+
+#define VPP_OSD_HSC_PHASE_STEP_FORMAT	__BITS(27,0)
+
+#define VPP_OSD_HSC_INI_PHASE_0		__BITS(31,16)
+#define VPP_OSD_HSC_INI_PHASE_1		__BITS(15,0)
+
+#define VPP_OSD_HSC_CTRL0_HSCALE_EN	__BIT(22)
+#define VPP_OSD_HSC_CTRL0_RPT_P0_NUM0	__BITS(9,8)
+#define VPP_OSD_HSC_CTRL0_INI_RCV_NUM0	__BITS(6,3)
+#define VPP_OSD_HSC_CTRL0_BANK_LENGTH	__BITS(2,0)
+
+#define VPP_OSD_SC_CTRL0_OSC_SC_DIN_OSD1_ALPHA_MODE	__BIT(14)
+#define VPP_OSD_SC_CTRL0_OSC_SC_DIN_OSD2_ALPHA_MODE	__BIT(13)
+#define VPP_OSD_SC_CTRL0_OSC_SC_ALPHA_MODE		__BIT(12)
+#define VPP_OSD_SC_CTRL0_DEFAULT_ALPHA	__BITS(11,4)
+#define VPP_OSD_SC_CTRL0_OSD_SC_PATH_EN	__BIT(3)
+#define VPP_OSD_SC_CTRL0_OSD_SC_SEL	__BITS(1,0)
+
+#define VPP_OSD_SCI_WH_M1_WIDTH		__BITS(28,16)
+#define VPP_OSD_SCI_WH_M1_HEIGHT	__BITS(12,0)
+
+#define VPP_OSD_SCO_H_START		__BITS(28,16)
+#define VPP_OSD_SCO_H_END		__BITS(12,0)
+
+#define VPP_OSD_SCO_V_START		__BITS(28,16)
+#define VPP_OSD_SCO_V_END		__BITS(12,0)
+
+#endif /* _MESON_VPUREG_H */

Reply via email to