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 */